Code cleanup, fix query results

This commit is contained in:
Sascha Willems 2024-01-07 20:22:48 +01:00
parent dec7d2e9f8
commit 06439511e4

View file

@ -9,46 +9,41 @@
#include "vulkanexamplebase.h" #include "vulkanexamplebase.h"
#include "VulkanglTFModel.h" #include "VulkanglTFModel.h"
#define OBJ_DIM 0.05f
class VulkanExample : public VulkanExampleBase class VulkanExample : public VulkanExampleBase
{ {
public: public:
// This sample lets you select between different models to display
struct Models { struct Models {
std::vector<vkglTF::Model> objects; std::vector<vkglTF::Model> objects;
int32_t objectIndex = 3; int32_t objectIndex{ 3 };
std::vector<std::string> names; std::vector<std::string> names;
} models; } models;
// Size for the two-dimensional grid of objects (e.g. 3 = draws 3x3 objects)
int32_t gridSize{ 3 };
struct UniformBuffers { struct UniformData {
vks::Buffer VS;
} uniformBuffers;
struct UBOVS {
glm::mat4 projection; glm::mat4 projection;
glm::mat4 modelview; glm::mat4 modelview;
glm::vec4 lightPos = glm::vec4(-10.0f, -10.0f, 10.0f, 1.0f); glm::vec4 lightPos{ -10.0f, -10.0f, 10.0f, 1.0f };
} uboVS; } 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; VkPipeline pipeline{ VK_NULL_HANDLE };
bool blending = false; VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
bool discard = false; VkDescriptorSet descriptorSet{ VK_NULL_HANDLE };
bool wireframe = false; VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE };
bool tessellation = false;
VkPipelineLayout pipelineLayout; VkQueryPool queryPool{ VK_NULL_HANDLE };
VkDescriptorSet descriptorSet;
VkDescriptorSetLayout descriptorSetLayout;
VkQueryPool queryPool;
// Vector for storing pipeline statistics results // Vector for storing pipeline statistics results
std::vector<uint64_t> pipelineStats; std::vector<uint64_t> pipelineStats{};
std::vector<std::string> pipelineStatNames; std::vector<std::string> pipelineStatNames{};
int32_t gridSize = 3;
VulkanExample() : VulkanExampleBase() VulkanExample() : VulkanExampleBase()
{ {
@ -63,11 +58,13 @@ public:
~VulkanExample() ~VulkanExample()
{ {
if (device) {
vkDestroyPipeline(device, pipeline, nullptr); vkDestroyPipeline(device, pipeline, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
vkDestroyQueryPool(device, queryPool, nullptr); vkDestroyQueryPool(device, queryPool, nullptr);
uniformBuffers.VS.destroy(); uniformBuffer.destroy();
}
} }
virtual void getEnabledFeatures() virtual void getEnabledFeatures()
@ -141,7 +138,7 @@ public:
dataSize, dataSize,
pipelineStats.data(), pipelineStats.data(),
stride, stride,
VK_QUERY_RESULT_64_BIT); VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
} }
void buildCommandBuffers() 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() void loadAssets()
{ {
// Objects // Objects
@ -231,47 +214,45 @@ public:
} }
} }
void setupDescriptorPool() void setupDescriptors()
{ {
// Pool
std::vector<VkDescriptorPoolSize> poolSizes = { std::vector<VkDescriptorPoolSize> poolSizes = {
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3) vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3)
}; };
VkDescriptorPoolCreateInfo descriptorPoolInfo = VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3);
vks::initializers::descriptorPoolCreateInfo(poolSizes, 3);
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
}
void setupDescriptorSetLayout() // Layout
{
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = { std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0) vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0)
}; };
VkDescriptorSetLayoutCreateInfo descriptorLayout = VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = // Set
vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &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);
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
std::vector<VkWriteDescriptorSet> writeDescriptorSets = { std::vector<VkWriteDescriptorSet> 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<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
} }
void preparePipelines() 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) { if (pipeline != VK_NULL_HANDLE) {
// Destroy old pipeline if we're going to recreate it
vkDestroyPipeline(device, pipeline, nullptr); vkDestroyPipeline(device, pipeline, nullptr);
} }
@ -336,23 +317,15 @@ public:
// Prepare and initialize uniform buffer containing shader uniforms // Prepare and initialize uniform buffer containing shader uniforms
void prepareUniformBuffers() void prepareUniformBuffers()
{ {
VK_CHECK_RESULT(vulkanDevice->createBuffer( 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_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_CHECK_RESULT(uniformBuffer.map());
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();
} }
void updateUniformBuffers() void updateUniformBuffers()
{ {
uboVS.projection = camera.matrices.perspective; uniformData.projection = camera.matrices.perspective;
uboVS.modelview = camera.matrices.view; uniformData.modelview = camera.matrices.view;
memcpy(uniformBuffers.VS.mapped, &uboVS, sizeof(uboVS)); memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData));
} }
void prepare() void prepare()
@ -361,24 +334,32 @@ public:
loadAssets(); loadAssets();
setupQueryPool(); setupQueryPool();
prepareUniformBuffers(); prepareUniformBuffers();
setupDescriptorSetLayout(); setupDescriptors();
preparePipelines(); preparePipelines();
setupDescriptorPool();
setupDescriptorSets();
buildCommandBuffers(); buildCommandBuffers();
prepared = true; 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() virtual void render()
{ {
if (!prepared) if (!prepared)
return; return;
draw();
}
virtual void viewChanged()
{
updateUniformBuffers(); updateUniformBuffers();
draw();
} }
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)
@ -391,28 +372,20 @@ public:
if (overlay->sliderInt("Grid size", &gridSize, 1, 10)) { if (overlay->sliderInt("Grid size", &gridSize, 1, 10)) {
buildCommandBuffers(); 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<std::string> cullModeNames = { "None", "Front", "Back", "Back and front" }; std::vector<std::string> cullModeNames = { "None", "Front", "Back", "Back and front" };
if (overlay->comboBox("Cull mode", &cullMode, cullModeNames)) { recreatePipeline |= overlay->comboBox("Cull mode", &cullMode, cullModeNames);
preparePipelines(); recreatePipeline |= overlay->checkBox("Blending", &blending);
buildCommandBuffers(); recreatePipeline |= overlay->checkBox("Discard", &discard);
} // These features may not be supported by all implementations
if (overlay->checkBox("Blending", &blending)) {
preparePipelines();
buildCommandBuffers();
}
if (deviceFeatures.fillModeNonSolid) { if (deviceFeatures.fillModeNonSolid) {
if (overlay->checkBox("Wireframe", &wireframe)) { recreatePipeline |= overlay->checkBox("Wireframe", &wireframe);
preparePipelines();
buildCommandBuffers();
}
} }
if (deviceFeatures.tessellationShader) { if (deviceFeatures.tessellationShader) {
if (overlay->checkBox("Tessellation", &tessellation)) { recreatePipeline |= overlay->checkBox("Tessellation", &tessellation);
preparePipelines();
buildCommandBuffers();
} }
} if (recreatePipeline) {
if (overlay->checkBox("Discard", &discard)) {
preparePipelines(); preparePipelines();
buildCommandBuffers(); buildCommandBuffers();
} }