From 1970dcbb0fa0cdd7edefcd7e6b758ae6086b14f9 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Sun, 7 Jan 2024 20:39:36 +0100 Subject: [PATCH] Code cleanup, comments --- examples/pipelines/pipelines.cpp | 163 ++++++++++++------------------- 1 file changed, 64 insertions(+), 99 deletions(-) diff --git a/examples/pipelines/pipelines.cpp b/examples/pipelines/pipelines.cpp index 1792fe5d..c0195425 100644 --- a/examples/pipelines/pipelines.cpp +++ b/examples/pipelines/pipelines.cpp @@ -1,5 +1,7 @@ /* -* Vulkan Example - Using different pipelines in one single renderpass +* Vulkan Example - Using different pipelines in a single renderpass +* +* This sample shows how to setup multiple graphics pipelines and how to use them for drawing objects with differring visuals * * Copyright (C) 2016-2023 by Sascha Willems - www.saschawillems.de * @@ -14,23 +16,21 @@ class VulkanExample: public VulkanExampleBase public: vkglTF::Model scene; - vks::Buffer uniformBuffer; - - // Same uniform buffer layout as shader - struct UBOVS { + struct UniformData { glm::mat4 projection; glm::mat4 modelView; - glm::vec4 lightPos = glm::vec4(0.0f, 2.0f, 1.0f, 0.0f); - } uboVS; + glm::vec4 lightPos{ 0.0f, 2.0f, 1.0f, 0.0f }; + } uniformData; + vks::Buffer uniformBuffer; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; + VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; + VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; + VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; struct { - VkPipeline phong; - VkPipeline wireframe; - VkPipeline toon; + VkPipeline phong{ VK_NULL_HANDLE }; + VkPipeline wireframe{ VK_NULL_HANDLE }; + VkPipeline toon{ VK_NULL_HANDLE }; } pipelines; VulkanExample() : VulkanExampleBase() @@ -45,19 +45,19 @@ public: ~VulkanExample() { - // Clean up used Vulkan resources - // Note : Inherited destructor cleans up resources stored in base class - vkDestroyPipeline(device, pipelines.phong, nullptr); - if (enabledFeatures.fillModeNonSolid) - { - vkDestroyPipeline(device, pipelines.wireframe, nullptr); + if (device) { + vkDestroyPipeline(device, pipelines.phong, nullptr); + if (enabledFeatures.fillModeNonSolid) + { + vkDestroyPipeline(device, pipelines.wireframe, nullptr); + } + vkDestroyPipeline(device, pipelines.toon, nullptr); + + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + + uniformBuffer.destroy(); } - vkDestroyPipeline(device, pipelines.toon, nullptr); - - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - - uniformBuffer.destroy(); } // Enable physical device features required for this example @@ -93,7 +93,6 @@ public: for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) { - // Set target frame buffer renderPassBeginInfo.framebuffer = frameBuffers[i]; VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); @@ -109,14 +108,14 @@ public: vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); scene.bindBuffers(drawCmdBuffers[i]); - // Left : Solid colored + // Left : Render the scene using the solid colored pipeline with phong shading viewport.width = (float)width / 3.0f; vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.phong); vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f); scene.draw(drawCmdBuffers[i]); - // Center : Toon + // Center : Render the scene using a toon style pipeline viewport.x = (float)width / 3.0f; vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.toon); @@ -126,9 +125,8 @@ public: } scene.draw(drawCmdBuffers[i]); - if (enabledFeatures.fillModeNonSolid) - { - // Right : Wireframe + // Right : Render the scene as wireframe (if that feature is supported by the implementation) + if (enabledFeatures.fillModeNonSolid) { viewport.x = (float)width / 3.0f + (float)width / 3.0f; vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.wireframe); @@ -149,58 +147,43 @@ public: scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, glTFLoadingFlags); } - void setupDescriptorPool() + void setupDescriptors() { - std::vector poolSizes = - { + // Pool + std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1) }; - - VkDescriptorPoolCreateInfo descriptorPoolInfo = - vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); - + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 2); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - } - void setupDescriptorSetLayout() - { - std::vector setLayoutBindings = - { + // Layout + std::vector setLayoutBindings = { // Binding 0 : Vertex shader uniform buffer vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) }; VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - } - - void setupDescriptorSet() - { - VkDescriptorSetAllocateInfo allocInfo = - vks::initializers::descriptorSetAllocateInfo( - descriptorPool, - &descriptorSetLayout, - 1); - + // Set + VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); - std::vector writeDescriptorSets = - { + std::vector writeDescriptorSets = { // Binding 0 : Vertex shader uniform buffer - vks::initializers::writeDescriptorSet( - descriptorSet, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 0, - &uniformBuffer.descriptor) + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) }; - vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); } void preparePipelines() { + // Layout + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + // Pipelines + + // Most state is shared between all pipelines VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); @@ -224,7 +207,7 @@ public: pipelineCI.pStages = shaderStages.data(); pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); - // Create the graphics pipeline state objects + // Create the different pipelines used in this sample // We are using this pipeline as the base for the other pipelines (derivatives) // Pipeline derivatives can be used for pipelines that share most of their state @@ -253,8 +236,7 @@ public: // Pipeline for wire frame rendering // Non solid rendering is not a mandatory Vulkan feature - if (enabledFeatures.fillModeNonSolid) - { + if (enabledFeatures.fillModeNonSolid) { rasterizationState.polygonMode = VK_POLYGON_MODE_LINE; shaderStages[0] = loadShader(getShadersPath() + "pipelines/wireframe.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages[1] = loadShader(getShadersPath() + "pipelines/wireframe.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); @@ -266,34 +248,16 @@ public: void prepareUniformBuffers() { // Create the vertex shader uniform buffer block - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffer, - sizeof(uboVS))); - + VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData))); // Map persistent VK_CHECK_RESULT(uniformBuffer.map()); - - updateUniformBuffers(); } void updateUniformBuffers() { - uboVS.projection = camera.matrices.perspective; - uboVS.modelView = camera.matrices.view; - memcpy(uniformBuffer.mapped, &uboVS, sizeof(uboVS)); - } - - void draw() - { - VulkanExampleBase::prepareFrame(); - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - VulkanExampleBase::submitFrame(); + uniformData.projection = camera.matrices.perspective; + uniformData.modelView = camera.matrices.view; + memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); } void prepare() @@ -301,28 +265,29 @@ public: VulkanExampleBase::prepare(); loadAssets(); prepareUniformBuffers(); - setupDescriptorSetLayout(); + setupDescriptors(); preparePipelines(); - setupDescriptorPool(); - setupDescriptorSet(); buildCommandBuffers(); prepared = true; } + void draw() + { + VulkanExampleBase::prepareFrame(); + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; + VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); + VulkanExampleBase::submitFrame(); + } + virtual void render() { if (!prepared) return; - draw(); - if (camera.updated) { - updateUniformBuffers(); - } - } - - virtual void viewChanged() - { + // Override the base sample camera setup, since we use three viewports camera.setPerspective(60.0f, (float)(width / 3.0f) / (float)height, 0.1f, 256.0f); updateUniformBuffers(); + draw(); } virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)