diff --git a/android/computeshader/example.json b/android/computeshader/example.json index 360a4dc6..66a29fe2 100644 --- a/android/computeshader/example.json +++ b/android/computeshader/example.json @@ -5,7 +5,7 @@ }, "assets": { "textures": [ - "het_kanonschot_rgba8.ktx" + "vulkan_11_rgba.ktx" ] } } \ No newline at end of file diff --git a/data/textures/het_kanonschot_rgba8.ktx b/data/textures/het_kanonschot_rgba8.ktx deleted file mode 100644 index f4f7545a..00000000 Binary files a/data/textures/het_kanonschot_rgba8.ktx and /dev/null differ diff --git a/examples/computeshader/computeshader.cpp b/examples/computeshader/computeshader.cpp index b1e8b2fe..ec950dbf 100644 --- a/examples/computeshader/computeshader.cpp +++ b/examples/computeshader/computeshader.cpp @@ -175,7 +175,7 @@ public: sampler.maxAnisotropy = 1.0f; sampler.compareOp = VK_COMPARE_OP_NEVER; sampler.minLod = 0.0f; - sampler.maxLod = 0.0f; + sampler.maxLod = tex->mipLevels; sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &tex->sampler)); @@ -198,13 +198,7 @@ public: void loadAssets() { - textureColorMap.loadFromFile( - getAssetPath() + "textures/het_kanonschot_rgba8.ktx", - VK_FORMAT_R8G8B8A8_UNORM, - vulkanDevice, - queue, - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, - VK_IMAGE_LAYOUT_GENERAL); + textureColorMap.loadFromFile(getAssetPath() + "textures/vulkan_11_rgba.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL); } void buildCommandBuffers() @@ -343,30 +337,18 @@ public: void setupVertexDescriptions() { // Binding description - vertices.bindingDescriptions.resize(1); - vertices.bindingDescriptions[0] = - vks::initializers::vertexInputBindingDescription( - VERTEX_BUFFER_BIND_ID, - sizeof(Vertex), - VK_VERTEX_INPUT_RATE_VERTEX); + vertices.bindingDescriptions = { + vks::initializers::vertexInputBindingDescription(VERTEX_BUFFER_BIND_ID, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX) + }; // Attribute descriptions // Describes memory layout and shader positions - vertices.attributeDescriptions.resize(2); - // Location 0 : Position - vertices.attributeDescriptions[0] = - vks::initializers::vertexInputAttributeDescription( - VERTEX_BUFFER_BIND_ID, - 0, - VK_FORMAT_R32G32B32_SFLOAT, - offsetof(Vertex, pos)); - // Location 1 : Texture coordinates - vertices.attributeDescriptions[1] = - vks::initializers::vertexInputAttributeDescription( - VERTEX_BUFFER_BIND_ID, - 1, - VK_FORMAT_R32G32_SFLOAT, - offsetof(Vertex, uv)); + vertices.attributeDescriptions = { + // Location 0: Position + vks::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)), + // Location 1: Texture coordinates + vks::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 1, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)), + }; // Assign to vertex buffer vertices.inputState = vks::initializers::pipelineVertexInputStateCreateInfo(); @@ -378,111 +360,55 @@ public: void setupDescriptorPool() { - std::vector poolSizes = - { + std::vector poolSizes = { + // Graphics pipelines uniform buffers vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2), - // Graphics pipeline uses image samplers for display + // Graphics pipelines image samplers for displaying compute output image vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2), - // Compute pipeline uses a sampled image for reading - vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1), // Compute pipelines uses a storage image for image reads and writes vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2), }; - - VkDescriptorPoolCreateInfo descriptorPoolInfo = - vks::initializers::descriptorPoolCreateInfo( - poolSizes.size(), - poolSizes.data(), - 3); - + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); } void setupDescriptorSetLayout() { - std::vector setLayoutBindings = - { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - VK_SHADER_STAGE_VERTEX_BIT, - 0), - // Binding 1 : Fragment shader image sampler - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - VK_SHADER_STAGE_FRAGMENT_BIT, - 1) + std::vector setLayoutBindings = { + // Binding 0: Vertex shader uniform buffer + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), + // Binding 1: Fragment shader input image + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1) }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = - vks::initializers::descriptorSetLayoutCreateInfo( - setLayoutBindings.data(), - setLayoutBindings.size()); - + VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &graphics.descriptorSetLayout)); - VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = - vks::initializers::pipelineLayoutCreateInfo( - &graphics.descriptorSetLayout, - 1); - + VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&graphics.descriptorSetLayout, 1); VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &graphics.pipelineLayout)); } void setupDescriptorSet() { VkDescriptorSetAllocateInfo allocInfo = - vks::initializers::descriptorSetAllocateInfo( - descriptorPool, - &graphics.descriptorSetLayout, - 1); - - VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSetPostCompute)); - - std::vector writeDescriptorSets = - { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet( - graphics.descriptorSetPostCompute, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 0, - &uniformBufferVS.descriptor), - // Binding 1 : Fragment shader texture sampler - vks::initializers::writeDescriptorSet( - graphics.descriptorSetPostCompute, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 1, - &textureComputeTarget.descriptor) - }; - - vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); - - // Base image (before compute post process) - allocInfo = - vks::initializers::descriptorSetAllocateInfo( - descriptorPool, - &graphics.descriptorSetLayout, - 1); + vks::initializers::descriptorSetAllocateInfo(descriptorPool, &graphics.descriptorSetLayout, 1); + // Input image (before compute post processing) VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSetPreCompute)); - - std::vector baseImageWriteDescriptorSets = - { - // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet( - graphics.descriptorSetPreCompute, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 0, - &uniformBufferVS.descriptor), - // Binding 1 : Fragment shader texture sampler - vks::initializers::writeDescriptorSet( - graphics.descriptorSetPreCompute, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 1, - &textureColorMap.descriptor) + std::vector baseImageWriteDescriptorSets = { + vks::initializers::writeDescriptorSet(graphics.descriptorSetPreCompute, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor), + vks::initializers::writeDescriptorSet(graphics.descriptorSetPreCompute, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureColorMap.descriptor) }; + vkUpdateDescriptorSets(device, baseImageWriteDescriptorSets.size(), baseImageWriteDescriptorSets.data(), 0, nullptr); + + // Final image (after compute shader processing) + VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &graphics.descriptorSetPostCompute)); + std::vector writeDescriptorSets = { + vks::initializers::writeDescriptorSet(graphics.descriptorSetPostCompute, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor), + vks::initializers::writeDescriptorSet(graphics.descriptorSetPostCompute, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &textureComputeTarget.descriptor) + }; + vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, nullptr); - vkUpdateDescriptorSets(device, baseImageWriteDescriptorSets.size(), baseImageWriteDescriptorSets.data(), 0, NULL); } void preparePipelines() @@ -612,73 +538,41 @@ public: // Compute pipelines are created separate from graphics pipelines even if they use the same queue std::vector setLayoutBindings = { - // Binding 0 : Sampled image (read) - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - VK_SHADER_STAGE_COMPUTE_BIT, - 0), - // Binding 1 : Sampled image (write) - vks::initializers::descriptorSetLayoutBinding( - VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - VK_SHADER_STAGE_COMPUTE_BIT, - 1), + // Binding 0: Input image (read-only) + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 0), + // Binding 1: Output image (write) + vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT, 1), }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = - vks::initializers::descriptorSetLayoutCreateInfo( - setLayoutBindings.data(), - setLayoutBindings.size()); - + VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout)); VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = - vks::initializers::pipelineLayoutCreateInfo( - &compute.descriptorSetLayout, - 1); + vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1); VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout)); VkDescriptorSetAllocateInfo allocInfo = - vks::initializers::descriptorSetAllocateInfo( - descriptorPool, - &compute.descriptorSetLayout, - 1); + vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSet)); - - std::vector computeWriteDescriptorSets = - { - // Binding 0 : Sampled image (read) - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - 0, - &textureColorMap.descriptor), - // Binding 1 : Sampled image (write) - vks::initializers::writeDescriptorSet( - compute.descriptorSet, - VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - 1, - &textureComputeTarget.descriptor) + std::vector computeWriteDescriptorSets = { + vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 0, &textureColorMap.descriptor), + vks::initializers::writeDescriptorSet(compute.descriptorSet, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &textureComputeTarget.descriptor) }; - vkUpdateDescriptorSets(device, computeWriteDescriptorSets.size(), computeWriteDescriptorSets.data(), 0, NULL); - // Create compute shader pipelines VkComputePipelineCreateInfo computePipelineCreateInfo = - vks::initializers::computePipelineCreateInfo( - compute.pipelineLayout, - 0); + vks::initializers::computePipelineCreateInfo(compute.pipelineLayout, 0); // One pipeline for each effect - shaderNames = { "sharpen", "edgedetect", "emboss" }; + shaderNames = { "emboss", "edgedetect", "sharpen" }; for (auto& shaderName : shaderNames) { std::string fileName = getAssetPath() + "shaders/computeshader/" + shaderName + ".comp.spv"; computePipelineCreateInfo.stage = loadShader(fileName.c_str(), VK_SHADER_STAGE_COMPUTE_BIT); VkPipeline pipeline; VK_CHECK_RESULT(vkCreateComputePipelines(device, pipelineCache, 1, &computePipelineCreateInfo, nullptr, &pipeline)); - compute.pipelines.push_back(pipeline); }