Skip to content

Commit 9b82e67

Browse files
committed
Update additional samples to use new sync
1 parent 4176ebb commit 9b82e67

3 files changed

Lines changed: 168 additions & 179 deletions

File tree

examples/gltfloading/gltfloading.cpp

Lines changed: 83 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Vulkan Example - glTF scene loading and rendering
33
*
4-
* Copyright (C) 2020-2023 by Sascha Willems - www.saschawillems.de
4+
* Copyright (C) 2020-2025 by Sascha Willems - www.saschawillems.de
55
*
66
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
77
*/
@@ -384,37 +384,37 @@ class VulkanExample : public VulkanExampleBase
384384

385385
VulkanglTFModel glTFModel;
386386

387-
struct ShaderData {
388-
vks::Buffer buffer;
389-
struct Values {
390-
glm::mat4 projection;
391-
glm::mat4 model;
392-
glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, -5.0f, 1.0f);
393-
glm::vec4 viewPos;
394-
} values;
395-
} shaderData;
387+
struct UniformData {
388+
glm::mat4 projection;
389+
glm::mat4 model;
390+
glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, -5.0f, 1.0f);
391+
glm::vec4 viewPos;
392+
} uniformData;
393+
std::vector<vks::Buffer> uniformBuffers;
396394

395+
VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
397396
struct Pipelines {
398397
VkPipeline solid{ VK_NULL_HANDLE };
399398
VkPipeline wireframe{ VK_NULL_HANDLE };
400399
} pipelines;
401400

402-
VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
403-
VkDescriptorSet descriptorSet{ VK_NULL_HANDLE };
404-
405401
struct DescriptorSetLayouts {
406402
VkDescriptorSetLayout matrices{ VK_NULL_HANDLE };
407403
VkDescriptorSetLayout textures{ VK_NULL_HANDLE };
408404
} descriptorSetLayouts;
405+
std::vector<VkDescriptorSet> descriptorSets;
409406

410407
VulkanExample() : VulkanExampleBase()
411408
{
409+
useNewSync = true;
412410
title = "glTF model rendering";
413411
camera.type = Camera::CameraType::lookat;
414412
camera.flipY = true;
415413
camera.setPosition(glm::vec3(0.0f, -0.1f, -1.0f));
416414
camera.setRotation(glm::vec3(0.0f, 45.0f, 0.0f));
417415
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f);
416+
uniformBuffers.resize(maxConcurrentFrames);
417+
descriptorSets.resize(maxConcurrentFrames);
418418
}
419419

420420
~VulkanExample()
@@ -427,7 +427,9 @@ class VulkanExample : public VulkanExampleBase
427427
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
428428
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr);
429429
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr);
430-
shaderData.buffer.destroy();
430+
for (auto& buffer : uniformBuffers) {
431+
buffer.destroy();
432+
}
431433
}
432434
}
433435

@@ -439,43 +441,6 @@ class VulkanExample : public VulkanExampleBase
439441
};
440442
}
441443

442-
void buildCommandBuffers()
443-
{
444-
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
445-
446-
VkClearValue clearValues[2];
447-
clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };;
448-
clearValues[1].depthStencil = { 1.0f, 0 };
449-
450-
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
451-
renderPassBeginInfo.renderPass = renderPass;
452-
renderPassBeginInfo.renderArea.offset.x = 0;
453-
renderPassBeginInfo.renderArea.offset.y = 0;
454-
renderPassBeginInfo.renderArea.extent.width = width;
455-
renderPassBeginInfo.renderArea.extent.height = height;
456-
renderPassBeginInfo.clearValueCount = 2;
457-
renderPassBeginInfo.pClearValues = clearValues;
458-
459-
const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
460-
const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
461-
462-
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
463-
{
464-
renderPassBeginInfo.framebuffer = frameBuffers[i];
465-
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
466-
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
467-
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
468-
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
469-
// Bind scene matrices descriptor to set 0
470-
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
471-
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid);
472-
glTFModel.draw(drawCmdBuffers[i], pipelineLayout);
473-
drawUI(drawCmdBuffers[i]);
474-
vkCmdEndRenderPass(drawCmdBuffers[i]);
475-
VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
476-
}
477-
}
478-
479444
void loadglTFFile(std::string filename)
480445
{
481446
tinygltf::Model glTFInput;
@@ -521,26 +486,21 @@ class VulkanExample : public VulkanExampleBase
521486
size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t);
522487
glTFModel.indices.count = static_cast<uint32_t>(indexBuffer.size());
523488

524-
struct StagingBuffer {
525-
VkBuffer buffer;
526-
VkDeviceMemory memory;
527-
} vertexStaging, indexStaging;
489+
vks::Buffer vertexStaging, indexStaging;
528490

529491
// Create host visible staging buffers (source)
530492
VK_CHECK_RESULT(vulkanDevice->createBuffer(
531493
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
532494
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
495+
&vertexStaging,
533496
vertexBufferSize,
534-
&vertexStaging.buffer,
535-
&vertexStaging.memory,
536497
vertexBuffer.data()));
537498
// Index data
538499
VK_CHECK_RESULT(vulkanDevice->createBuffer(
539500
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
540501
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
502+
&indexStaging,
541503
indexBufferSize,
542-
&indexStaging.buffer,
543-
&indexStaging.memory,
544504
indexBuffer.data()));
545505

546506
// Create device local buffers (target)
@@ -579,11 +539,8 @@ class VulkanExample : public VulkanExampleBase
579539

580540
vulkanDevice->flushCommandBuffer(copyCmd, queue, true);
581541

582-
// Free staging resources
583-
vkDestroyBuffer(device, vertexStaging.buffer, nullptr);
584-
vkFreeMemory(device, vertexStaging.memory, nullptr);
585-
vkDestroyBuffer(device, indexStaging.buffer, nullptr);
586-
vkFreeMemory(device, indexStaging.memory, nullptr);
542+
vertexStaging.destroy();
543+
indexStaging.destroy();
587544
}
588545

589546
void loadAssets()
@@ -598,12 +555,12 @@ class VulkanExample : public VulkanExampleBase
598555
*/
599556

600557
std::vector<VkDescriptorPoolSize> poolSizes = {
601-
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
558+
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, maxConcurrentFrames),
602559
// One combined image sampler per model image/texture
603-
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast<uint32_t>(glTFModel.images.size())),
560+
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, static_cast<uint32_t>(glTFModel.images.size()) * maxConcurrentFrames),
604561
};
605562
// One set for matrices and one per model image/texture
606-
const uint32_t maxSetCount = static_cast<uint32_t>(glTFModel.images.size()) + 1;
563+
const uint32_t maxSetCount = (static_cast<uint32_t>(glTFModel.images.size()) + 1) * maxConcurrentFrames;
607564
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, maxSetCount);
608565
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
609566

@@ -615,12 +572,15 @@ class VulkanExample : public VulkanExampleBase
615572
setLayoutBinding = vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0);
616573
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &descriptorSetLayouts.textures));
617574

618-
// Descriptor set for scene matrices
619-
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1);
620-
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
621-
VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &shaderData.buffer.descriptor);
622-
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
623-
// Descriptor sets for materials
575+
// Descriptor set for scene matrices per frame, just like the buffers themselves
576+
for (auto i = 0; i < uniformBuffers.size(); i++) {
577+
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.matrices, 1);
578+
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSets[i]));
579+
VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(descriptorSets[i], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers[i].descriptor);
580+
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
581+
}
582+
583+
// Descriptor sets for materials, since they only use static images, no need to duplicate them per frame
624584
for (auto& image : glTFModel.images) {
625585
const VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.textures, 1);
626586
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &image.descriptorSet));
@@ -699,18 +659,18 @@ class VulkanExample : public VulkanExampleBase
699659
// Prepare and initialize uniform buffer containing shader uniforms
700660
void prepareUniformBuffers()
701661
{
702-
// Vertex shader uniform buffer block
703-
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &shaderData.buffer, sizeof(shaderData.values)));
704-
// Map persistent
705-
VK_CHECK_RESULT(shaderData.buffer.map());
662+
for (auto& buffer : uniformBuffers) {
663+
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &buffer, sizeof(UniformData), &uniformData));
664+
VK_CHECK_RESULT(buffer.map());
665+
}
706666
}
707667

708668
void updateUniformBuffers()
709669
{
710-
shaderData.values.projection = camera.matrices.perspective;
711-
shaderData.values.model = camera.matrices.view;
712-
shaderData.values.viewPos = camera.viewPos;
713-
memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values));
670+
uniformData.projection = camera.matrices.perspective;
671+
uniformData.model = camera.matrices.view;
672+
uniformData.viewPos = camera.viewPos;
673+
memcpy(uniformBuffers[currentBuffer].mapped, &uniformData, sizeof(UniformData));
714674
}
715675

716676
void prepare()
@@ -720,23 +680,59 @@ class VulkanExample : public VulkanExampleBase
720680
prepareUniformBuffers();
721681
setupDescriptors();
722682
preparePipelines();
723-
buildCommandBuffers();
724683
prepared = true;
725684
}
726685

686+
void buildCommandBuffer()
687+
{
688+
VkCommandBuffer cmdBuffer = drawCmdBuffers[currentBuffer];
689+
vkResetCommandBuffer(cmdBuffer, 0);
690+
691+
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
692+
693+
VkClearValue clearValues[2]{};
694+
clearValues[0].color = { { 0.25f, 0.25f, 0.25f, 1.0f } };;
695+
clearValues[1].depthStencil = { 1.0f, 0 };
696+
697+
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
698+
renderPassBeginInfo.renderPass = renderPass;
699+
renderPassBeginInfo.renderArea.offset.x = 0;
700+
renderPassBeginInfo.renderArea.offset.y = 0;
701+
renderPassBeginInfo.renderArea.extent.width = width;
702+
renderPassBeginInfo.renderArea.extent.height = height;
703+
renderPassBeginInfo.clearValueCount = 2;
704+
renderPassBeginInfo.pClearValues = clearValues;
705+
renderPassBeginInfo.framebuffer = frameBuffers[currentImageIndex];
706+
707+
VK_CHECK_RESULT(vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo));
708+
vkCmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
709+
const VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
710+
vkCmdSetViewport(cmdBuffer, 0, 1, &viewport);
711+
const VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
712+
vkCmdSetScissor(cmdBuffer, 0, 1, &scissor);
713+
// Bind scene matrices descriptor to set 0
714+
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[currentBuffer], 0, nullptr);
715+
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, wireframe ? pipelines.wireframe : pipelines.solid);
716+
glTFModel.draw(cmdBuffer, pipelineLayout);
717+
drawUI(cmdBuffer);
718+
vkCmdEndRenderPass(cmdBuffer);
719+
VK_CHECK_RESULT(vkEndCommandBuffer(cmdBuffer));
720+
}
721+
727722
virtual void render()
728723
{
724+
if (!prepared)
725+
return;
726+
VulkanExampleBase::prepareFrame();
729727
updateUniformBuffers();
730-
renderFrame();
731-
728+
buildCommandBuffer();
729+
VulkanExampleBase::submitFrame();
732730
}
733731

734732
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)
735733
{
736734
if (overlay->header("Settings")) {
737-
if (overlay->checkBox("Wireframe", &wireframe)) {
738-
buildCommandBuffers();
739-
}
735+
overlay->checkBox("Wireframe", &wireframe);
740736
}
741737
}
742738
};

0 commit comments

Comments
 (0)