Fixes in examples: support swapchain image count change on resize, fix multiple validation layer errors on resize and quit, multiview now supports resize/fullscreen, computecloth deltaT now based on frame time, multisampling recreates attachments on resize, P key now pauses computeparticles, descriptorsets, and pushdescriptors

This commit is contained in:
Stephen Saunders 2022-06-01 13:02:33 -04:00
parent cb343c329a
commit 121612857c
10 changed files with 148 additions and 65 deletions

View file

@ -101,6 +101,7 @@ public:
~VulkanExample() ~VulkanExample()
{ {
// Graphics // Graphics
graphics.indices.destroy();
graphics.uniformBuffer.destroy(); graphics.uniformBuffer.destroy();
vkDestroyPipeline(device, graphics.pipelines.cloth, nullptr); vkDestroyPipeline(device, graphics.pipelines.cloth, nullptr);
vkDestroyPipeline(device, graphics.pipelines.sphere, nullptr); vkDestroyPipeline(device, graphics.pipelines.sphere, nullptr);
@ -670,13 +671,13 @@ public:
void updateComputeUBO() void updateComputeUBO()
{ {
if (!paused) { if (!paused) {
compute.ubo.deltaT = 0.000005f; //compute.ubo.deltaT = 0.000005f;
// todo: base on frametime // todo: base on frametime
//compute.ubo.deltaT = frameTimer * 0.0075f; compute.ubo.deltaT = frameTimer * 0.0015f;
if (simulateWind) { if (simulateWind) {
std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr)); std::default_random_engine rndEngine(benchmark.active ? 0 : (unsigned)time(nullptr));
std::uniform_real_distribution<float> rd(1.0f, 6.0f); std::uniform_real_distribution<float> rd(1.0f, 30.0f);
compute.ubo.gravity.x = cos(glm::radians(-timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine)); compute.ubo.gravity.x = cos(glm::radians(-timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine));
compute.ubo.gravity.z = sin(glm::radians(timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine)); compute.ubo.gravity.z = sin(glm::radians(timer * 360.0f)) * (rd(rndEngine) - rd(rndEngine));
} }

View file

@ -620,6 +620,13 @@ public:
// Semaphore for compute & graphics sync // Semaphore for compute & graphics sync
VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore)); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore));
// Signal the semaphore
VkSubmitInfo submitInfo = vks::initializers::submitInfo();
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &graphics.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(vkQueueWaitIdle(queue));
} }
void prepareCompute() void prepareCompute()
@ -736,13 +743,6 @@ public:
VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore)); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore));
// Signal the semaphore
VkSubmitInfo submitInfo = vks::initializers::submitInfo();
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &compute.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(vkQueueWaitIdle(queue));
// Build a single command buffer containing the compute dispatch commands // Build a single command buffer containing the compute dispatch commands
buildComputeCommandBuffer(); buildComputeCommandBuffer();
@ -841,6 +841,20 @@ public:
void draw() void draw()
{ {
// Wait for rendering finished
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
// Submit compute commands
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
computeSubmitInfo.commandBufferCount = 1;
computeSubmitInfo.pCommandBuffers = &compute.commandBuffer;
computeSubmitInfo.waitSemaphoreCount = 1;
computeSubmitInfo.pWaitSemaphores = &graphics.semaphore;
computeSubmitInfo.pWaitDstStageMask = &waitStageMask;
computeSubmitInfo.signalSemaphoreCount = 1;
computeSubmitInfo.pSignalSemaphores = &compute.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE));
VulkanExampleBase::prepareFrame(); VulkanExampleBase::prepareFrame();
VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
@ -858,20 +872,6 @@ public:
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame(); VulkanExampleBase::submitFrame();
// Wait for rendering finished
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
// Submit compute commands
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
computeSubmitInfo.commandBufferCount = 1;
computeSubmitInfo.pCommandBuffers = &compute.commandBuffer;
computeSubmitInfo.waitSemaphoreCount = 1;
computeSubmitInfo.pWaitSemaphores = &graphics.semaphore;
computeSubmitInfo.pWaitDstStageMask = &waitStageMask;
computeSubmitInfo.signalSemaphoreCount = 1;
computeSubmitInfo.pSignalSemaphores = &compute.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE));
} }
void prepare() void prepare()
@ -901,4 +901,4 @@ public:
} }
}; };
VULKAN_EXAMPLE_MAIN() VULKAN_EXAMPLE_MAIN()

View file

@ -86,6 +86,7 @@ public:
vkDestroyPipeline(device, graphics.pipeline, nullptr); vkDestroyPipeline(device, graphics.pipeline, nullptr);
vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr); vkDestroyPipelineLayout(device, graphics.pipelineLayout, nullptr);
vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, graphics.descriptorSetLayout, nullptr);
vkDestroySemaphore(device, graphics.semaphore, nullptr);
// Compute // Compute
compute.storageBuffer.destroy(); compute.storageBuffer.destroy();
@ -551,6 +552,13 @@ public:
// Semaphore for compute & graphics sync // Semaphore for compute & graphics sync
VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore)); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &graphics.semaphore));
// Signal the semaphore
VkSubmitInfo submitInfo = vks::initializers::submitInfo();
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &graphics.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(vkQueueWaitIdle(queue));
} }
void prepareCompute() void prepareCompute()
@ -636,13 +644,6 @@ public:
VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo(); VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore)); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore));
// Signal the semaphore
VkSubmitInfo submitInfo = vks::initializers::submitInfo();
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &compute.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(vkQueueWaitIdle(queue));
// Build a single command buffer containing the compute dispatch commands // Build a single command buffer containing the compute dispatch commands
buildComputeCommandBuffer(); buildComputeCommandBuffer();
@ -716,7 +717,7 @@ public:
void updateUniformBuffers() void updateUniformBuffers()
{ {
compute.ubo.deltaT = frameTimer * 2.5f; compute.ubo.deltaT = paused ? 0.0f : frameTimer * 2.5f;
if (!attachToCursor) if (!attachToCursor)
{ {
compute.ubo.destX = sin(glm::radians(timer * 360.0f)) * 0.75f; compute.ubo.destX = sin(glm::radians(timer * 360.0f)) * 0.75f;
@ -735,6 +736,20 @@ public:
void draw() void draw()
{ {
// Wait for rendering finished
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
// Submit compute commands
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
computeSubmitInfo.commandBufferCount = 1;
computeSubmitInfo.pCommandBuffers = &compute.commandBuffer;
computeSubmitInfo.waitSemaphoreCount = 1;
computeSubmitInfo.pWaitSemaphores = &graphics.semaphore;
computeSubmitInfo.pWaitDstStageMask = &waitStageMask;
computeSubmitInfo.signalSemaphoreCount = 1;
computeSubmitInfo.pSignalSemaphores = &compute.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE));
VulkanExampleBase::prepareFrame(); VulkanExampleBase::prepareFrame();
VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
@ -752,21 +767,6 @@ public:
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame(); VulkanExampleBase::submitFrame();
// Wait for rendering finished
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
// Submit compute commands
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
computeSubmitInfo.commandBufferCount = 1;
computeSubmitInfo.pCommandBuffers = &compute.commandBuffer;
computeSubmitInfo.waitSemaphoreCount = 1;
computeSubmitInfo.pWaitSemaphores = &graphics.semaphore;
computeSubmitInfo.pWaitDstStageMask = &waitStageMask;
computeSubmitInfo.signalSemaphoreCount = 1;
computeSubmitInfo.pSignalSemaphores = &compute.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE));
} }
void prepare() void prepare()

View file

@ -362,7 +362,7 @@ public:
if (!prepared) if (!prepared)
return; return;
draw(); draw();
if (animate) { if (animate && !paused) {
cubes[0].rotation.x += 2.5f * frameTimer; cubes[0].rotation.x += 2.5f * frameTimer;
if (cubes[0].rotation.x > 360.0f) if (cubes[0].rotation.x > 360.0f)
cubes[0].rotation.x -= 360.0f; cubes[0].rotation.x -= 360.0f;
@ -370,7 +370,7 @@ public:
if (cubes[1].rotation.x > 360.0f) if (cubes[1].rotation.x > 360.0f)
cubes[1].rotation.x -= 360.0f; cubes[1].rotation.x -= 360.0f;
} }
if ((camera.updated) || (animate)) { if ((camera.updated) || (animate && !paused)) {
updateUniformBuffers(); updateUniformBuffers();
} }
} }
@ -383,4 +383,4 @@ public:
} }
}; };
VULKAN_EXAMPLE_MAIN() VULKAN_EXAMPLE_MAIN()

View file

@ -180,11 +180,23 @@ public:
for (auto i = 0; i < attachments.size(); i++) { for (auto i = 0; i < attachments.size(); i++) {
clearAttachment(&attachments[i].color); clearAttachment(&attachments[i].color);
clearAttachment(&attachments[i].depth); clearAttachment(&attachments[i].depth);
}
// SRS - Recreate attachments and descriptors in case number of swapchain images has changed on resize
attachments.resize(swapChain.imageCount);
for (auto i = 0; i < attachments.size(); i++) {
createAttachment(colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments[i].color); createAttachment(colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &attachments[i].color);
createAttachment(depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &attachments[i].depth); createAttachment(depthFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, &attachments[i].depth);
// Since the framebuffers/attachments are referred in the descriptor sets, these need to be updated too
updateAttachmentReadDescriptors(i);
} }
vkDestroyPipelineLayout(device, pipelineLayouts.attachmentWrite, nullptr);
vkDestroyPipelineLayout(device, pipelineLayouts.attachmentRead, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.attachmentWrite, nullptr);
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.attachmentRead, nullptr);
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
// Since the framebuffers/attachments are referred in the descriptor sets, these need to be updated on resize
setupDescriptors();
} }
VkImageView views[3]; VkImageView views[3];

View file

@ -48,6 +48,7 @@ public:
VkPipelineLayout pipelineLayout; VkPipelineLayout pipelineLayout;
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
VkDescriptorSetLayout descriptorSetLayout; VkDescriptorSetLayout descriptorSetLayout;
VkExtent2D attachmentSize;
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
{ {
@ -199,6 +200,8 @@ public:
void setupRenderPass() void setupRenderPass()
{ {
// Overrides the virtual function of the base class // Overrides the virtual function of the base class
attachmentSize = { width, height };
std::array<VkAttachmentDescription, 3> attachments = {}; std::array<VkAttachmentDescription, 3> attachments = {};
@ -290,6 +293,20 @@ public:
{ {
// Overrides the virtual function of the base class // Overrides the virtual function of the base class
// SRS - If the window is resized, the MSAA attachments need to be released and recreated
if (attachmentSize.width != width || attachmentSize.height != height)
{
attachmentSize = { width, height };
// Destroy MSAA target
vkDestroyImage(device, multisampleTarget.color.image, nullptr);
vkDestroyImageView(device, multisampleTarget.color.view, nullptr);
vkFreeMemory(device, multisampleTarget.color.memory, nullptr);
vkDestroyImage(device, multisampleTarget.depth.image, nullptr);
vkDestroyImageView(device, multisampleTarget.depth.view, nullptr);
vkFreeMemory(device, multisampleTarget.depth.memory, nullptr);
}
std::array<VkImageView, 3> attachments; std::array<VkImageView, 3> attachments;
setupMultisampleTarget(); setupMultisampleTarget();

View file

@ -98,6 +98,7 @@ public:
vkDestroySampler(device, multiviewPass.sampler, nullptr); vkDestroySampler(device, multiviewPass.sampler, nullptr);
vkDestroyFramebuffer(device, multiviewPass.frameBuffer, nullptr); vkDestroyFramebuffer(device, multiviewPass.frameBuffer, nullptr);
vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(multiviewPass.commandBuffers.size()), multiviewPass.commandBuffers.data());
vkDestroySemaphore(device, multiviewPass.semaphore, nullptr); vkDestroySemaphore(device, multiviewPass.semaphore, nullptr);
for (auto& fence : multiviewPass.waitFences) { for (auto& fence : multiviewPass.waitFences) {
vkDestroyFence(device, fence, nullptr); vkDestroyFence(device, fence, nullptr);
@ -337,6 +338,9 @@ public:
void buildCommandBuffers() void buildCommandBuffers()
{ {
if (resized)
return;
/* /*
View display View display
*/ */
@ -392,11 +396,6 @@ public:
Multiview layered attachment scene rendering Multiview layered attachment scene rendering
*/ */
multiviewPass.commandBuffers.resize(drawCmdBuffers.size());
VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(drawCmdBuffers.size()));
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, multiviewPass.commandBuffers.data()));
{ {
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
@ -467,13 +466,18 @@ public:
*/ */
VkDescriptorSetAllocateInfo allocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); VkDescriptorSetAllocateInfo allocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocateInfo, &descriptorSet)); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocateInfo, &descriptorSet));
updateDescriptors();
}
void updateDescriptors()
{
std::vector<VkWriteDescriptorSet> writeDescriptorSets = { std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor),
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &multiviewPass.descriptor), vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &multiviewPass.descriptor),
}; };
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()
{ {
@ -669,6 +673,11 @@ public:
prepareUniformBuffers(); prepareUniformBuffers();
prepareDescriptors(); prepareDescriptors();
preparePipelines(); preparePipelines();
VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(drawCmdBuffers.size()));
multiviewPass.commandBuffers.resize(drawCmdBuffers.size());
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, multiviewPass.commandBuffers.data()));
buildCommandBuffers(); buildCommandBuffers();
VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT);
@ -680,6 +689,45 @@ public:
prepared = true; prepared = true;
} }
// SRS - Recreate and update Multiview resources when window size has changed
virtual void windowResized()
{
vkDestroyImageView(device, multiviewPass.color.view, nullptr);
vkDestroyImage(device, multiviewPass.color.image, nullptr);
vkFreeMemory(device, multiviewPass.color.memory, nullptr);
vkDestroyImageView(device, multiviewPass.depth.view, nullptr);
vkDestroyImage(device, multiviewPass.depth.image, nullptr);
vkFreeMemory(device, multiviewPass.depth.memory, nullptr);
vkDestroyRenderPass(device, multiviewPass.renderPass, nullptr);
vkDestroySampler(device, multiviewPass.sampler, nullptr);
vkDestroyFramebuffer(device, multiviewPass.frameBuffer, nullptr);
prepareMultiview();
updateDescriptors();
// SRS - Recreate Multiview command buffers in case number of swapchain images has changed on resize
vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(multiviewPass.commandBuffers.size()), multiviewPass.commandBuffers.data());
VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(drawCmdBuffers.size()));
multiviewPass.commandBuffers.resize(drawCmdBuffers.size());
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, multiviewPass.commandBuffers.data()));
resized = false;
buildCommandBuffers();
// SRS - Recreate Multiview fences in case number of swapchain images has changed on resize
for (auto& fence : multiviewPass.waitFences) {
vkDestroyFence(device, fence, nullptr);
}
VkFenceCreateInfo fenceCreateInfo = vks::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT);
multiviewPass.waitFences.resize(multiviewPass.commandBuffers.size());
for (auto& fence : multiviewPass.waitFences) {
VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence));
}
}
virtual void render() virtual void render()
{ {
if (!prepared) if (!prepared)
@ -704,4 +752,4 @@ public:
}; };
VULKAN_EXAMPLE_MAIN() VULKAN_EXAMPLE_MAIN()

View file

@ -262,7 +262,7 @@ public:
memcpy(cube.uniformBuffer.mapped, &cube.modelMat, sizeof(glm::mat4)); memcpy(cube.uniformBuffer.mapped, &cube.modelMat, sizeof(glm::mat4));
} }
if (animate) { if (animate && !paused) {
cubes[0].rotation.x += 2.5f * frameTimer; cubes[0].rotation.x += 2.5f * frameTimer;
if (cubes[0].rotation.x > 360.0f) if (cubes[0].rotation.x > 360.0f)
cubes[0].rotation.x -= 360.0f; cubes[0].rotation.x -= 360.0f;
@ -323,7 +323,7 @@ public:
if (!prepared) if (!prepared)
return; return;
draw(); draw();
if (animate) { if (animate && !paused) {
cubes[0].rotation.x += 2.5f * frameTimer; cubes[0].rotation.x += 2.5f * frameTimer;
if (cubes[0].rotation.x > 360.0f) if (cubes[0].rotation.x > 360.0f)
cubes[0].rotation.x -= 360.0f; cubes[0].rotation.x -= 360.0f;
@ -348,4 +348,4 @@ public:
} }
}; };
VULKAN_EXAMPLE_MAIN() VULKAN_EXAMPLE_MAIN()

View file

@ -901,7 +901,9 @@ public:
virtual void windowResized() virtual void windowResized()
{ {
updateTextOverlay(); // SRS - Recreate text overlay resources in case number of swapchain images has changed on resize
delete textOverlay;
prepareTextOverlay();
} }
#if !defined(__ANDROID__) #if !defined(__ANDROID__)
@ -917,4 +919,4 @@ public:
#endif #endif
}; };
VULKAN_EXAMPLE_MAIN() VULKAN_EXAMPLE_MAIN()

View file

@ -126,6 +126,9 @@ public:
~VulkanExample() ~VulkanExample()
{ {
// SRS - Ensure all operations on the device have finished before destroying resources
vkDeviceWaitIdle(device);
// Clean up used Vulkan resources // Clean up used Vulkan resources
// Note: Inherited destructor cleans up resources stored in base class // Note: Inherited destructor cleans up resources stored in base class
vkDestroyPipeline(device, pipeline, nullptr); vkDestroyPipeline(device, pipeline, nullptr);