Code cleanup
This commit is contained in:
parent
50a3f5f820
commit
c7eed13c7c
1 changed files with 32 additions and 51 deletions
|
|
@ -339,11 +339,11 @@ public:
|
||||||
vkFreeMemory(device, stagingBuffers.indexBuffer.memory, nullptr);
|
vkFreeMemory(device, stagingBuffers.indexBuffer.memory, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Descriptors are allocated from a pool, that tells the implementation how many and what types of descriptors we are going to use (at maximum)
|
// Decriptors are used to pass data to shaders, for our sample we use a descriptor to pass parameters like matrices to the shader
|
||||||
void createDescriptorPool()
|
void createDescriptors()
|
||||||
{
|
{
|
||||||
// We need to tell the API the number of max. requested descriptors per type
|
// Descriptors are allocated from a pool, that tells the implementation how many and what types of descriptors we are going to use (at maximum)
|
||||||
VkDescriptorPoolSize descriptorTypeCounts[1];
|
VkDescriptorPoolSize descriptorTypeCounts[1]{};
|
||||||
// This example only one descriptor type (uniform buffer)
|
// This example only one descriptor type (uniform buffer)
|
||||||
descriptorTypeCounts[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
descriptorTypeCounts[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
// We have one buffer (and as such descriptor) per frame
|
// We have one buffer (and as such descriptor) per frame
|
||||||
|
|
@ -362,13 +362,10 @@ public:
|
||||||
// Our sample will create one set per uniform buffer per frame
|
// Our sample will create one set per uniform buffer per frame
|
||||||
descriptorPoolCI.maxSets = MAX_CONCURRENT_FRAMES;
|
descriptorPoolCI.maxSets = MAX_CONCURRENT_FRAMES;
|
||||||
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool));
|
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolCI, nullptr, &descriptorPool));
|
||||||
}
|
|
||||||
|
|
||||||
// Descriptor set layouts define the interface between our application and the shader
|
// Descriptor set layouts define the interface between our application and the shader
|
||||||
// Basically connects the different shader stages to descriptors for binding uniform buffers, image samplers, etc.
|
// Basically connects the different shader stages to descriptors for binding uniform buffers, image samplers, etc.
|
||||||
// So every shader binding should map to one descriptor set layout binding
|
// So every shader binding should map to one descriptor set layout binding
|
||||||
void createDescriptorSetLayout()
|
|
||||||
{
|
|
||||||
// Binding 0: Uniform buffer (Vertex shader)
|
// Binding 0: Uniform buffer (Vertex shader)
|
||||||
VkDescriptorSetLayoutBinding layoutBinding{};
|
VkDescriptorSetLayoutBinding layoutBinding{};
|
||||||
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
|
@ -380,19 +377,8 @@ public:
|
||||||
descriptorLayoutCI.pBindings = &layoutBinding;
|
descriptorLayoutCI.pBindings = &layoutBinding;
|
||||||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout));
|
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayout));
|
||||||
|
|
||||||
// Create the pipeline layout that is used to generate the rendering pipelines that are based on this descriptor set layout
|
// Where the descriptor set layout is the interface, the descriptor set points to actual data
|
||||||
// In a more complex scenario you would have different pipeline layouts for different descriptor set layouts that could be reused
|
// Descriptors that are changed per frame need to be multiplied, so we can update descriptor n+1 while n is still used by the GPU, so we create one per max frame in flight
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutCI{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
|
||||||
pipelineLayoutCI.setLayoutCount = 1;
|
|
||||||
pipelineLayoutCI.pSetLayouts = &descriptorSetLayout;
|
|
||||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shaders access data using descriptor sets that "point" at our uniform buffers
|
|
||||||
// The descriptor sets make use of the descriptor set layouts created above
|
|
||||||
void createDescriptorSets()
|
|
||||||
{
|
|
||||||
// Allocate one descriptor set per frame from the global descriptor pool
|
|
||||||
for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) {
|
for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) {
|
||||||
VkDescriptorSetAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
VkDescriptorSetAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
|
||||||
allocInfo.descriptorPool = descriptorPool;
|
allocInfo.descriptorPool = descriptorPool;
|
||||||
|
|
@ -404,7 +390,7 @@ public:
|
||||||
// For every binding point used in a shader there needs to be one
|
// For every binding point used in a shader there needs to be one
|
||||||
// descriptor set matching that binding point
|
// descriptor set matching that binding point
|
||||||
VkWriteDescriptorSet writeDescriptorSet{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
|
VkWriteDescriptorSet writeDescriptorSet{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
|
||||||
|
|
||||||
// The buffer's information is passed using a descriptor info structure
|
// The buffer's information is passed using a descriptor info structure
|
||||||
VkDescriptorBufferInfo bufferInfo{};
|
VkDescriptorBufferInfo bufferInfo{};
|
||||||
bufferInfo.buffer = uniformBuffers[i].handle;
|
bufferInfo.buffer = uniformBuffers[i].handle;
|
||||||
|
|
@ -516,12 +502,17 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createPipelines()
|
void createPipeline()
|
||||||
{
|
{
|
||||||
|
// The pipeline layout is the interface telling the pipeline what type of descriptors will later be bound
|
||||||
|
VkPipelineLayoutCreateInfo pipelineLayoutCI{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||||
|
pipelineLayoutCI.setLayoutCount = 1;
|
||||||
|
pipelineLayoutCI.pSetLayouts = &descriptorSetLayout;
|
||||||
|
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipelineLayout));
|
||||||
|
|
||||||
// Create the graphics pipeline used in this example
|
// Create the graphics pipeline used in this example
|
||||||
// Vulkan uses the concept of rendering pipelines to encapsulate fixed states, replacing OpenGL's complex state machine
|
// Vulkan uses the concept of rendering pipelines to encapsulate fixed states, replacing OpenGL's complex state machine
|
||||||
// A pipeline is then stored and hashed on the GPU making pipeline changes very fast
|
// A pipeline is then stored and hashed on the GPU making pipeline changes very fast
|
||||||
// Note: There are still a few dynamic states that are not directly part of the pipeline (but the info that they are used is)
|
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipelineCI{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
|
VkGraphicsPipelineCreateInfo pipelineCI{ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
|
||||||
// The layout used for this pipeline (can be shared among multiple pipelines using the same layout)
|
// The layout used for this pipeline (can be shared among multiple pipelines using the same layout)
|
||||||
|
|
@ -560,12 +551,9 @@ public:
|
||||||
viewportStateCI.scissorCount = 1;
|
viewportStateCI.scissorCount = 1;
|
||||||
|
|
||||||
// Enable dynamic states
|
// Enable dynamic states
|
||||||
// Most states are baked into the pipeline, but there are still a few dynamic states that can be changed within a command buffer
|
// Most states are baked into the pipeline, but there is somee state that can be dynamically changed within the command buffer to mak e things easuer
|
||||||
// To be able to change these we need do specify which dynamic states will be changed using this pipeline. Their actual states are set later on in the command buffer.
|
// To be able to change these we need do specify which dynamic states will be changed using this pipeline. Their actual states are set later on in the command buffer
|
||||||
// For this example we will set the viewport and scissor using dynamic states
|
std::vector<VkDynamicState> dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
||||||
std::vector<VkDynamicState> dynamicStateEnables;
|
|
||||||
dynamicStateEnables.push_back(VK_DYNAMIC_STATE_VIEWPORT);
|
|
||||||
dynamicStateEnables.push_back(VK_DYNAMIC_STATE_SCISSOR);
|
|
||||||
VkPipelineDynamicStateCreateInfo dynamicStateCI{ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
VkPipelineDynamicStateCreateInfo dynamicStateCI{ VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
||||||
dynamicStateCI.pDynamicStates = dynamicStateEnables.data();
|
dynamicStateCI.pDynamicStates = dynamicStateEnables.data();
|
||||||
dynamicStateCI.dynamicStateCount = static_cast<uint32_t>(dynamicStateEnables.size());
|
dynamicStateCI.dynamicStateCount = static_cast<uint32_t>(dynamicStateEnables.size());
|
||||||
|
|
@ -583,11 +571,9 @@ public:
|
||||||
depthStencilStateCI.stencilTestEnable = VK_FALSE;
|
depthStencilStateCI.stencilTestEnable = VK_FALSE;
|
||||||
depthStencilStateCI.front = depthStencilStateCI.back;
|
depthStencilStateCI.front = depthStencilStateCI.back;
|
||||||
|
|
||||||
// Multi sampling state
|
|
||||||
// This example does not make use of multi sampling (for anti-aliasing), the state must still be set and passed to the pipeline
|
// This example does not make use of multi sampling (for anti-aliasing), the state must still be set and passed to the pipeline
|
||||||
VkPipelineMultisampleStateCreateInfo multisampleStateCI{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
VkPipelineMultisampleStateCreateInfo multisampleStateCI{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
||||||
multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
multisampleStateCI.pSampleMask = nullptr;
|
|
||||||
|
|
||||||
// Vertex input descriptions
|
// Vertex input descriptions
|
||||||
// Specifies the vertex input parameters for a pipeline
|
// Specifies the vertex input parameters for a pipeline
|
||||||
|
|
@ -645,12 +631,12 @@ public:
|
||||||
pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
|
pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
|
||||||
pipelineCI.pStages = shaderStages.data();
|
pipelineCI.pStages = shaderStages.data();
|
||||||
|
|
||||||
// New create info to define color, depth and stencil attachments at pipeline create time
|
// Attachment information for dynamic rendering
|
||||||
VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo{ VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR };
|
VkPipelineRenderingCreateInfoKHR pipelineRenderingCI{ VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR };
|
||||||
pipelineRenderingCreateInfo.colorAttachmentCount = 1;
|
pipelineRenderingCI.colorAttachmentCount = 1;
|
||||||
pipelineRenderingCreateInfo.pColorAttachmentFormats = &swapChain.colorFormat;
|
pipelineRenderingCI.pColorAttachmentFormats = &swapChain.colorFormat;
|
||||||
pipelineRenderingCreateInfo.depthAttachmentFormat = depthFormat;
|
pipelineRenderingCI.depthAttachmentFormat = depthFormat;
|
||||||
pipelineRenderingCreateInfo.stencilAttachmentFormat = depthFormat;
|
pipelineRenderingCI.stencilAttachmentFormat = depthFormat;
|
||||||
|
|
||||||
// Assign the pipeline states to the pipeline creation info structure
|
// Assign the pipeline states to the pipeline creation info structure
|
||||||
pipelineCI.pVertexInputState = &vertexInputStateCI;
|
pipelineCI.pVertexInputState = &vertexInputStateCI;
|
||||||
|
|
@ -661,12 +647,12 @@ public:
|
||||||
pipelineCI.pViewportState = &viewportStateCI;
|
pipelineCI.pViewportState = &viewportStateCI;
|
||||||
pipelineCI.pDepthStencilState = &depthStencilStateCI;
|
pipelineCI.pDepthStencilState = &depthStencilStateCI;
|
||||||
pipelineCI.pDynamicState = &dynamicStateCI;
|
pipelineCI.pDynamicState = &dynamicStateCI;
|
||||||
pipelineCI.pNext = &pipelineRenderingCreateInfo;
|
pipelineCI.pNext = &pipelineRenderingCI;
|
||||||
|
|
||||||
// Create rendering pipeline using the specified states
|
// Create rendering pipeline using the specified states
|
||||||
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline));
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline));
|
||||||
|
|
||||||
// Shader modules are no longer needed once the graphics pipeline has been created
|
// Shader modules can safely be destroyed when the pipeline has been created
|
||||||
vkDestroyShaderModule(device, shaderStages[0].module, nullptr);
|
vkDestroyShaderModule(device, shaderStages[0].module, nullptr);
|
||||||
vkDestroyShaderModule(device, shaderStages[1].module, nullptr);
|
vkDestroyShaderModule(device, shaderStages[1].module, nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -675,7 +661,6 @@ public:
|
||||||
{
|
{
|
||||||
// Prepare and initialize the per-frame uniform buffer blocks containing shader uniforms
|
// Prepare and initialize the per-frame uniform buffer blocks containing shader uniforms
|
||||||
// Single uniforms like in OpenGL are no longer present in Vulkan. All Shader uniforms are passed via uniform buffer blocks
|
// Single uniforms like in OpenGL are no longer present in Vulkan. All Shader uniforms are passed via uniform buffer blocks
|
||||||
VkMemoryRequirements memReqs;
|
|
||||||
|
|
||||||
// Vertex shader uniform buffer block
|
// Vertex shader uniform buffer block
|
||||||
VkBufferCreateInfo bufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
VkBufferCreateInfo bufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
|
||||||
|
|
@ -691,6 +676,7 @@ public:
|
||||||
for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) {
|
for (uint32_t i = 0; i < MAX_CONCURRENT_FRAMES; i++) {
|
||||||
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferInfo, nullptr, &uniformBuffers[i].handle));
|
VK_CHECK_RESULT(vkCreateBuffer(device, &bufferInfo, nullptr, &uniformBuffers[i].handle));
|
||||||
// Get memory requirements including size, alignment and memory type
|
// Get memory requirements including size, alignment and memory type
|
||||||
|
VkMemoryRequirements memReqs;
|
||||||
vkGetBufferMemoryRequirements(device, uniformBuffers[i].handle, &memReqs);
|
vkGetBufferMemoryRequirements(device, uniformBuffers[i].handle, &memReqs);
|
||||||
allocInfo.allocationSize = memReqs.size;
|
allocInfo.allocationSize = memReqs.size;
|
||||||
// Get the memory type index that supports host visible memory access
|
// Get the memory type index that supports host visible memory access
|
||||||
|
|
@ -714,18 +700,13 @@ public:
|
||||||
createCommandBuffers();
|
createCommandBuffers();
|
||||||
createVertexBuffer();
|
createVertexBuffer();
|
||||||
createUniformBuffers();
|
createUniformBuffers();
|
||||||
createDescriptorSetLayout();
|
createDescriptors();
|
||||||
createDescriptorPool();
|
createPipeline();
|
||||||
createDescriptorSets();
|
|
||||||
createPipelines();
|
|
||||||
prepared = true;
|
prepared = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void render()
|
virtual void render() override
|
||||||
{
|
{
|
||||||
if (!prepared)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Use a fence to wait until the command buffer has finished execution before using it again
|
// Use a fence to wait until the command buffer has finished execution before using it again
|
||||||
vkWaitForFences(device, 1, &waitFences[currentFrame], VK_TRUE, UINT64_MAX);
|
vkWaitForFences(device, 1, &waitFences[currentFrame], VK_TRUE, UINT64_MAX);
|
||||||
VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentFrame]));
|
VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentFrame]));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue