From 06439511e4fe407768e26716552b9aff337aba6d Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Sun, 7 Jan 2024 20:22:48 +0100 Subject: [PATCH] Code cleanup, fix query results --- .../pipelinestatistics/pipelinestatistics.cpp | 181 ++++++++---------- 1 file changed, 77 insertions(+), 104 deletions(-) diff --git a/examples/pipelinestatistics/pipelinestatistics.cpp b/examples/pipelinestatistics/pipelinestatistics.cpp index 753cb405..0a7832e1 100644 --- a/examples/pipelinestatistics/pipelinestatistics.cpp +++ b/examples/pipelinestatistics/pipelinestatistics.cpp @@ -9,46 +9,41 @@ #include "vulkanexamplebase.h" #include "VulkanglTFModel.h" -#define OBJ_DIM 0.05f - class VulkanExample : public VulkanExampleBase { public: + // This sample lets you select between different models to display struct Models { std::vector objects; - int32_t objectIndex = 3; + int32_t objectIndex{ 3 }; std::vector names; } models; + // Size for the two-dimensional grid of objects (e.g. 3 = draws 3x3 objects) + int32_t gridSize{ 3 }; - struct UniformBuffers { - vks::Buffer VS; - } uniformBuffers; - - struct UBOVS { + struct UniformData { glm::mat4 projection; glm::mat4 modelview; - glm::vec4 lightPos = glm::vec4(-10.0f, -10.0f, 10.0f, 1.0f); - } uboVS; + glm::vec4 lightPos{ -10.0f, -10.0f, 10.0f, 1.0f }; + } uniformData; + vks::Buffer uniformBuffer; - VkPipeline pipeline = VK_NULL_HANDLE; + int32_t cullMode{ VK_CULL_MODE_BACK_BIT }; + bool blending{ false }; + bool discard{ false }; + bool wireframe{ false }; + bool tessellation{ false }; - int32_t cullMode = VK_CULL_MODE_BACK_BIT; - bool blending = false; - bool discard = false; - bool wireframe = false; - bool tessellation = false; + VkPipeline pipeline{ VK_NULL_HANDLE }; + VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; + VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; + VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; - VkPipelineLayout pipelineLayout; - VkDescriptorSet descriptorSet; - VkDescriptorSetLayout descriptorSetLayout; - - VkQueryPool queryPool; + VkQueryPool queryPool{ VK_NULL_HANDLE }; // Vector for storing pipeline statistics results - std::vector pipelineStats; - std::vector pipelineStatNames; - - int32_t gridSize = 3; + std::vector pipelineStats{}; + std::vector pipelineStatNames{}; VulkanExample() : VulkanExampleBase() { @@ -63,11 +58,13 @@ public: ~VulkanExample() { - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vkDestroyQueryPool(device, queryPool, nullptr); - uniformBuffers.VS.destroy(); + if (device) { + vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + vkDestroyQueryPool(device, queryPool, nullptr); + uniformBuffer.destroy(); + } } virtual void getEnabledFeatures() @@ -141,7 +138,7 @@ public: dataSize, pipelineStats.data(), stride, - VK_QUERY_RESULT_64_BIT); + VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT); } void buildCommandBuffers() @@ -206,20 +203,6 @@ public: } } - void draw() - { - VulkanExampleBase::prepareFrame(); - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; - VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); - - // Read query results for displaying in next frame - getQueryResults(); - - VulkanExampleBase::submitFrame(); - } - void loadAssets() { // Objects @@ -231,47 +214,45 @@ public: } } - void setupDescriptorPool() + void setupDescriptors() { + // Pool std::vector poolSizes = { vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3) }; - VkDescriptorPoolCreateInfo descriptorPoolInfo = - vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); + VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); - } - void setupDescriptorSetLayout() - { + // Layout std::vector setLayoutBindings = { vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) }; - VkDescriptorSetLayoutCreateInfo descriptorLayout = - vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); + VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = - vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); - VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec3), 0); - pipelineLayoutCreateInfo.pushConstantRangeCount = 1; - pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; - VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); - } - - void setupDescriptorSets() - { - 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 = { - vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.VS.descriptor) + vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor) }; vkUpdateDescriptorSets(device, static_cast(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); } void preparePipelines() { + // Layout + if (pipelineLayout == VK_NULL_HANDLE) { + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); + VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::vec3), 0); + pipelineLayoutCreateInfo.pushConstantRangeCount = 1; + pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; + VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + } + + // Pipeline if (pipeline != VK_NULL_HANDLE) { + // Destroy old pipeline if we're going to recreate it vkDestroyPipeline(device, pipeline, nullptr); } @@ -336,23 +317,15 @@ public: // Prepare and initialize uniform buffer containing shader uniforms void prepareUniformBuffers() { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBuffers.VS, - sizeof(uboVS))); - - // Map persistent - VK_CHECK_RESULT(uniformBuffers.VS.map()); - - updateUniformBuffers(); + 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))); + VK_CHECK_RESULT(uniformBuffer.map()); } void updateUniformBuffers() { - uboVS.projection = camera.matrices.perspective; - uboVS.modelview = camera.matrices.view; - memcpy(uniformBuffers.VS.mapped, &uboVS, sizeof(uboVS)); + uniformData.projection = camera.matrices.perspective; + uniformData.modelview = camera.matrices.view; + memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); } void prepare() @@ -361,24 +334,32 @@ public: loadAssets(); setupQueryPool(); prepareUniformBuffers(); - setupDescriptorSetLayout(); + setupDescriptors(); preparePipelines(); - setupDescriptorPool(); - setupDescriptorSets(); 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(); + + // Read query results for displaying in next frame + getQueryResults(); + } + virtual void render() { if (!prepared) return; - draw(); - } - - virtual void viewChanged() - { updateUniformBuffers(); + draw(); } virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) @@ -391,28 +372,20 @@ public: if (overlay->sliderInt("Grid size", &gridSize, 1, 10)) { buildCommandBuffers(); } + // To avoid having to create pipelines for all the settings up front, we recreate a single pipelin with different settings instead + bool recreatePipeline{ false }; std::vector cullModeNames = { "None", "Front", "Back", "Back and front" }; - if (overlay->comboBox("Cull mode", &cullMode, cullModeNames)) { - preparePipelines(); - buildCommandBuffers(); - } - if (overlay->checkBox("Blending", &blending)) { - preparePipelines(); - buildCommandBuffers(); - } + recreatePipeline |= overlay->comboBox("Cull mode", &cullMode, cullModeNames); + recreatePipeline |= overlay->checkBox("Blending", &blending); + recreatePipeline |= overlay->checkBox("Discard", &discard); + // These features may not be supported by all implementations if (deviceFeatures.fillModeNonSolid) { - if (overlay->checkBox("Wireframe", &wireframe)) { - preparePipelines(); - buildCommandBuffers(); - } + recreatePipeline |= overlay->checkBox("Wireframe", &wireframe); } if (deviceFeatures.tessellationShader) { - if (overlay->checkBox("Tessellation", &tessellation)) { - preparePipelines(); - buildCommandBuffers(); - } + recreatePipeline |= overlay->checkBox("Tessellation", &tessellation); } - if (overlay->checkBox("Discard", &discard)) { + if (recreatePipeline) { preparePipelines(); buildCommandBuffers(); }