Code cleanup, comments

This commit is contained in:
Sascha Willems 2024-01-20 19:41:53 +01:00
parent 93a873c678
commit d641086a29

View file

@ -9,17 +9,6 @@
#include "vulkanexamplebase.h" #include "vulkanexamplebase.h"
#include "VulkanglTFModel.h" #include "VulkanglTFModel.h"
// 16 bits of depth is enough for such a small scene
#define DEPTH_FORMAT VK_FORMAT_D16_UNORM
// Shadowmap properties
#if defined(__ANDROID__)
#define SHADOWMAP_DIM 1024
#else
#define SHADOWMAP_DIM 2048
#endif
#define DEFAULT_SHADOWMAP_FILTER VK_FILTER_LINEAR
class VulkanExample : public VulkanExampleBase class VulkanExample : public VulkanExampleBase
{ {
public: public:
@ -44,12 +33,7 @@ public:
std::vector<std::string> sceneNames; std::vector<std::string> sceneNames;
int32_t sceneIndex = 0; int32_t sceneIndex = 0;
struct { struct UniformDataScene {
vks::Buffer scene;
vks::Buffer offscreen;
} uniformBuffers;
struct {
glm::mat4 projection; glm::mat4 projection;
glm::mat4 view; glm::mat4 view;
glm::mat4 model; glm::mat4 model;
@ -58,27 +42,32 @@ public:
// Used for depth map visualization // Used for depth map visualization
float zNear; float zNear;
float zFar; float zFar;
} uboVSscene; } uniformDataScene;
struct { struct UniformDataOffscreen {
glm::mat4 depthMVP; glm::mat4 depthMVP;
} uboOffscreenVS; } uniformDataOffscreen;
struct { struct {
VkPipeline offscreen; vks::Buffer scene;
VkPipeline sceneShadow; vks::Buffer offscreen;
VkPipeline sceneShadowPCF; } uniformBuffers;
VkPipeline debug;
struct {
VkPipeline offscreen{ VK_NULL_HANDLE };
VkPipeline sceneShadow{ VK_NULL_HANDLE };
// Pipeline with percentage close filtering (PCF) of the shadow map
VkPipeline sceneShadowPCF{ VK_NULL_HANDLE };
VkPipeline debug{ VK_NULL_HANDLE };
} pipelines; } pipelines;
VkPipelineLayout pipelineLayout; VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
struct { struct {
VkDescriptorSet offscreen; VkDescriptorSet offscreen{ VK_NULL_HANDLE };
VkDescriptorSet scene; VkDescriptorSet scene{ VK_NULL_HANDLE };
VkDescriptorSet debug; VkDescriptorSet debug{ VK_NULL_HANDLE };
} descriptorSets; } descriptorSets;
VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE };
VkDescriptorSetLayout descriptorSetLayout;
// Framebuffer for offscreen rendering // Framebuffer for offscreen rendering
struct FrameBufferAttachment { struct FrameBufferAttachment {
@ -93,47 +82,56 @@ public:
VkRenderPass renderPass; VkRenderPass renderPass;
VkSampler depthSampler; VkSampler depthSampler;
VkDescriptorImageInfo descriptor; VkDescriptorImageInfo descriptor;
} offscreenPass; } offscreenPass{};
// 16 bits of depth is enough for such a small scene
const VkFormat offscreenDepthFormat{ VK_FORMAT_D16_UNORM };
// Shadow map dimension
#if defined(__ANDROID__)
// Use a smaller size on Android for performance reasons
const uint32_t shadowMapize{ 1024 };
#else
const uint32_t shadowMapize{ 2048 };
#endif
VulkanExample() : VulkanExampleBase() VulkanExample() : VulkanExampleBase()
{ {
title = "Projected shadow mapping"; title = "Projected shadow mapping";
camera.type = Camera::CameraType::lookat; camera.type = Camera::CameraType::lookat;
camera.setPosition(glm::vec3(0.0f, -0.0f, -20.0f)); camera.setPosition(glm::vec3(0.0f, 0.0f, -12.5f));
camera.setRotation(glm::vec3(-15.0f, -390.0f, 0.0f)); camera.setRotation(glm::vec3(-25.0f, -390.0f, 0.0f));
camera.setPerspective(60.0f, (float)width / (float)height, 1.0f, 256.0f); camera.setPerspective(60.0f, (float)width / (float)height, 1.0f, 256.0f);
timerSpeed *= 0.5f; timerSpeed *= 0.5f;
} }
~VulkanExample() ~VulkanExample()
{ {
// Clean up used Vulkan resources if (device) {
// Note : Inherited destructor cleans up resources stored in base class // Frame buffer
vkDestroySampler(device, offscreenPass.depthSampler, nullptr);
// Frame buffer // Depth attachment
vkDestroySampler(device, offscreenPass.depthSampler, nullptr); vkDestroyImageView(device, offscreenPass.depth.view, nullptr);
vkDestroyImage(device, offscreenPass.depth.image, nullptr);
vkFreeMemory(device, offscreenPass.depth.mem, nullptr);
// Depth attachment vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr);
vkDestroyImageView(device, offscreenPass.depth.view, nullptr);
vkDestroyImage(device, offscreenPass.depth.image, nullptr);
vkFreeMemory(device, offscreenPass.depth.mem, nullptr);
vkDestroyFramebuffer(device, offscreenPass.frameBuffer, nullptr); vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr);
vkDestroyRenderPass(device, offscreenPass.renderPass, nullptr); vkDestroyPipeline(device, pipelines.debug, nullptr);
vkDestroyPipeline(device, pipelines.offscreen, nullptr);
vkDestroyPipeline(device, pipelines.sceneShadow, nullptr);
vkDestroyPipeline(device, pipelines.sceneShadowPCF, nullptr);
vkDestroyPipeline(device, pipelines.debug, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyPipeline(device, pipelines.offscreen, nullptr);
vkDestroyPipeline(device, pipelines.sceneShadow, nullptr);
vkDestroyPipeline(device, pipelines.sceneShadowPCF, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); // Uniform buffers
uniformBuffers.offscreen.destroy();
// Uniform buffers uniformBuffers.scene.destroy();
uniformBuffers.offscreen.destroy(); }
uniformBuffers.scene.destroy();
} }
// Set up a separate render pass for the offscreen frame buffer // Set up a separate render pass for the offscreen frame buffer
@ -141,7 +139,7 @@ public:
void prepareOffscreenRenderpass() void prepareOffscreenRenderpass()
{ {
VkAttachmentDescription attachmentDescription{}; VkAttachmentDescription attachmentDescription{};
attachmentDescription.format = DEPTH_FORMAT; attachmentDescription.format = offscreenDepthFormat;
attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at beginning of the render pass attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at beginning of the render pass
attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // We will read from depth, so it's important to store the depth attachment results attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // We will read from depth, so it's important to store the depth attachment results
@ -193,8 +191,8 @@ public:
// The depth attachment of this framebuffer will then be used to sample from in the fragment shader of the shadowing pass // The depth attachment of this framebuffer will then be used to sample from in the fragment shader of the shadowing pass
void prepareOffscreenFramebuffer() void prepareOffscreenFramebuffer()
{ {
offscreenPass.width = SHADOWMAP_DIM; offscreenPass.width = shadowMapize;
offscreenPass.height = SHADOWMAP_DIM; offscreenPass.height = shadowMapize;
// For shadow mapping we only need a depth attachment // For shadow mapping we only need a depth attachment
VkImageCreateInfo image = vks::initializers::imageCreateInfo(); VkImageCreateInfo image = vks::initializers::imageCreateInfo();
@ -206,7 +204,7 @@ public:
image.arrayLayers = 1; image.arrayLayers = 1;
image.samples = VK_SAMPLE_COUNT_1_BIT; image.samples = VK_SAMPLE_COUNT_1_BIT;
image.tiling = VK_IMAGE_TILING_OPTIMAL; image.tiling = VK_IMAGE_TILING_OPTIMAL;
image.format = DEPTH_FORMAT; // Depth stencil attachment image.format = offscreenDepthFormat; // Depth stencil attachment
image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; // We will sample directly from the depth attachment for the shadow mapping image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; // We will sample directly from the depth attachment for the shadow mapping
VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image)); VK_CHECK_RESULT(vkCreateImage(device, &image, nullptr, &offscreenPass.depth.image));
@ -220,7 +218,7 @@ public:
VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo(); VkImageViewCreateInfo depthStencilView = vks::initializers::imageViewCreateInfo();
depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
depthStencilView.format = DEPTH_FORMAT; depthStencilView.format = offscreenDepthFormat;
depthStencilView.subresourceRange = {}; depthStencilView.subresourceRange = {};
depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.baseMipLevel = 0;
@ -232,9 +230,7 @@ public:
// Create sampler to sample from to depth attachment // Create sampler to sample from to depth attachment
// Used to sample in the fragment shader for shadowed rendering // Used to sample in the fragment shader for shadowed rendering
VkFilter shadowmap_filter = vks::tools::formatIsFilterable(physicalDevice, DEPTH_FORMAT, VK_IMAGE_TILING_OPTIMAL) ? VkFilter shadowmap_filter = vks::tools::formatIsFilterable(physicalDevice, offscreenDepthFormat, VK_IMAGE_TILING_OPTIMAL) ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
DEFAULT_SHADOWMAP_FILTER :
VK_FILTER_NEAREST;
VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo(); VkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo();
sampler.magFilter = shadowmap_filter; sampler.magFilter = shadowmap_filter;
sampler.minFilter = shadowmap_filter; sampler.minFilter = shadowmap_filter;
@ -370,19 +366,17 @@ public:
sceneNames = {"Vulkan scene", "Teapots and pillars" }; sceneNames = {"Vulkan scene", "Teapots and pillars" };
} }
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),
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3) vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3)
}; };
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3); VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 3);
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
}
void setupDescriptorSetLayout() // Layout
{
// Shared pipeline layout for all pipelines used in this sample
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = { std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
// Binding 0 : Vertex shader uniform buffer // Binding 0 : Vertex shader uniform buffer
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0), vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0),
@ -391,20 +385,16 @@ public:
}; };
VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout));
}
void setupDescriptorSets() // Sets
{
std::vector<VkWriteDescriptorSet> writeDescriptorSets; std::vector<VkWriteDescriptorSet> writeDescriptorSets;
// Image descriptor for the shadow map attachment // Image descriptor for the shadow map attachment
VkDescriptorImageInfo shadowMapDescriptor = VkDescriptorImageInfo shadowMapDescriptor =
vks::initializers::descriptorImageInfo( vks::initializers::descriptorImageInfo(
offscreenPass.depthSampler, offscreenPass.depthSampler,
offscreenPass.depth.view, offscreenPass.depth.view,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
// Debug display // Debug display
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
@ -413,7 +403,7 @@ public:
// Binding 0 : Parameters uniform buffer // Binding 0 : Parameters uniform buffer
vks::initializers::writeDescriptorSet(descriptorSets.debug, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), vks::initializers::writeDescriptorSet(descriptorSets.debug, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor),
// Binding 1 : Fragment shader texture sampler // Binding 1 : Fragment shader texture sampler
vks::initializers::writeDescriptorSet(descriptorSets.debug, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &shadowMapDescriptor) vks::initializers::writeDescriptorSet(descriptorSets.debug, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &shadowMapDescriptor)
}; };
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
@ -431,13 +421,18 @@ public:
// Binding 0 : Vertex shader uniform buffer // Binding 0 : Vertex shader uniform buffer
vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor), vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.scene.descriptor),
// Binding 1 : Fragment shader shadow sampler // Binding 1 : Fragment shader shadow sampler
vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &shadowMapDescriptor) vks::initializers::writeDescriptorSet(descriptorSets.scene, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &shadowMapDescriptor)
}; };
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
} }
void preparePipelines() void preparePipelines()
{ {
// Layout
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
// Pipelines
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE);
VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); VkPipelineRasterizationStateCreateInfo rasterizationStateCI = 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); VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE);
@ -507,19 +502,9 @@ public:
void prepareUniformBuffers() void prepareUniformBuffers()
{ {
// Offscreen vertex shader uniform buffer block // Offscreen vertex shader uniform buffer block
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, &uniformBuffers.offscreen, sizeof(UniformDataOffscreen)));
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&uniformBuffers.offscreen,
sizeof(uboOffscreenVS)));
// Scene vertex shader uniform buffer block // Scene vertex shader uniform buffer block
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, &uniformBuffers.scene, sizeof(UniformDataScene)));
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&uniformBuffers.scene,
sizeof(uboVSscene)));
// Map persistent // Map persistent
VK_CHECK_RESULT(uniformBuffers.offscreen.map()); VK_CHECK_RESULT(uniformBuffers.offscreen.map());
VK_CHECK_RESULT(uniformBuffers.scene.map()); VK_CHECK_RESULT(uniformBuffers.scene.map());
@ -539,14 +524,14 @@ public:
void updateUniformBuffers() void updateUniformBuffers()
{ {
uboVSscene.projection = camera.matrices.perspective; uniformDataScene.projection = camera.matrices.perspective;
uboVSscene.view = camera.matrices.view; uniformDataScene.view = camera.matrices.view;
uboVSscene.model = glm::mat4(1.0f); uniformDataScene.model = glm::mat4(1.0f);
uboVSscene.lightPos = glm::vec4(lightPos, 1.0f); uniformDataScene.lightPos = glm::vec4(lightPos, 1.0f);
uboVSscene.depthBiasMVP = uboOffscreenVS.depthMVP; uniformDataScene.depthBiasMVP = uniformDataOffscreen.depthMVP;
uboVSscene.zNear = zNear; uniformDataScene.zNear = zNear;
uboVSscene.zFar = zFar; uniformDataScene.zFar = zFar;
memcpy(uniformBuffers.scene.mapped, &uboVSscene, sizeof(uboVSscene)); memcpy(uniformBuffers.scene.mapped, &uniformDataScene, sizeof(uniformDataScene));
} }
void updateUniformBufferOffscreen() void updateUniformBufferOffscreen()
@ -556,23 +541,9 @@ public:
glm::mat4 depthViewMatrix = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0, 1, 0)); glm::mat4 depthViewMatrix = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0, 1, 0));
glm::mat4 depthModelMatrix = glm::mat4(1.0f); glm::mat4 depthModelMatrix = glm::mat4(1.0f);
uboOffscreenVS.depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix; uniformDataOffscreen.depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix;
memcpy(uniformBuffers.offscreen.mapped, &uboOffscreenVS, sizeof(uboOffscreenVS)); memcpy(uniformBuffers.offscreen.mapped, &uniformDataOffscreen, sizeof(uniformDataOffscreen));
}
void draw()
{
VulkanExampleBase::prepareFrame();
// Command buffer to be submitted to the queue
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
// Submit to queue
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame();
} }
void prepare() void prepare()
@ -581,25 +552,31 @@ public:
loadAssets(); loadAssets();
prepareOffscreenFramebuffer(); prepareOffscreenFramebuffer();
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();
}
virtual void render() virtual void render()
{ {
if (!prepared) if (!prepared)
return; return;
draw(); if (!paused || camera.updated) {
if (!paused || camera.updated)
{
updateLight(); updateLight();
updateUniformBufferOffscreen(); updateUniformBufferOffscreen();
updateUniformBuffers(); updateUniformBuffers();
} }
draw();
} }
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)