Skip to content

Commit 6aeec7b

Browse files
committed
Finish sync rework
1 parent b5c0927 commit 6aeec7b

1 file changed

Lines changed: 68 additions & 80 deletions

File tree

examples/computecullandlod/computecullandlod.cpp

Lines changed: 68 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ class VulkanExample : public VulkanExampleBase
7070
VkCommandPool commandPool; // Use a separate command pool (queue family may differ from the one used for graphics)
7171
std::array<VkCommandBuffer, maxConcurrentFrames> commandBuffers; // Command buffer storing the dispatch commands and barriers
7272
std::array<VkFence, maxConcurrentFrames> fences; // Synchronization fence to avoid rewriting compute CB if still in use
73-
std::array<VkSemaphore, maxConcurrentFrames> semaphores; // Used as a wait semaphore for graphics submission
73+
struct ComputeSemaphores {
74+
VkSemaphore ready{ VK_NULL_HANDLE };
75+
VkSemaphore complete{ VK_NULL_HANDLE };
76+
};
77+
std::array<ComputeSemaphores, maxConcurrentFrames> semaphores{}; // Used as a wait semaphore for graphics submission
78+
//std::array<VkSemaphore, maxConcurrentFrames> semaphores; // Used as a wait semaphore for graphics submission
7479
VkDescriptorSetLayout descriptorSetLayout; // Compute shader binding layout
7580
std::array<VkDescriptorSet, maxConcurrentFrames> descriptorSets{}; // Compute shader bindings
7681
VkPipelineLayout pipelineLayout; // Layout of the compute pipeline
@@ -90,7 +95,6 @@ class VulkanExample : public VulkanExampleBase
9095
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 512.0f);
9196
camera.setTranslation(glm::vec3(0.5f, 0.0f, 0.0f));
9297
camera.movementSpeed = 5.0f;
93-
settings.overlay = false;
9498
}
9599

96100
~VulkanExample()
@@ -118,7 +122,8 @@ class VulkanExample : public VulkanExampleBase
118122
vkDestroyFence(device, fence, nullptr);
119123
}
120124
for (auto& semaphore : compute.semaphores) {
121-
vkDestroySemaphore(device, semaphore, nullptr);
125+
vkDestroySemaphore(device, semaphore.complete, nullptr);
126+
vkDestroySemaphore(device, semaphore.ready, nullptr);
122127
}
123128

124129
}
@@ -406,37 +411,17 @@ class VulkanExample : public VulkanExampleBase
406411

407412
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
408413
// Binding 0: Instance input data buffer
409-
vks::initializers::descriptorSetLayoutBinding(
410-
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
411-
VK_SHADER_STAGE_COMPUTE_BIT,
412-
0),
414+
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 0),
413415
// Binding 1: Indirect draw command output buffer (input)
414-
vks::initializers::descriptorSetLayoutBinding(
415-
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
416-
VK_SHADER_STAGE_COMPUTE_BIT,
417-
1),
416+
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 1),
418417
// Binding 2: Uniform buffer with global matrices (input)
419-
vks::initializers::descriptorSetLayoutBinding(
420-
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
421-
VK_SHADER_STAGE_COMPUTE_BIT,
422-
2),
418+
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 2),
423419
// Binding 3: Indirect draw stats (output)
424-
vks::initializers::descriptorSetLayoutBinding(
425-
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
426-
VK_SHADER_STAGE_COMPUTE_BIT,
427-
3),
420+
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT, 3),
428421
// Binding 4: LOD info (input)
429-
vks::initializers::descriptorSetLayoutBinding(
430-
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
431-
VK_SHADER_STAGE_COMPUTE_BIT,
432-
4),
422+
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT,4),
433423
};
434-
435-
VkDescriptorSetLayoutCreateInfo descriptorLayout =
436-
vks::initializers::descriptorSetLayoutCreateInfo(
437-
setLayoutBindings.data(),
438-
static_cast<uint32_t>(setLayoutBindings.size()));
439-
424+
VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
440425
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &compute.descriptorSetLayout));
441426

442427
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&compute.descriptorSetLayout, 1);
@@ -445,8 +430,7 @@ class VulkanExample : public VulkanExampleBase
445430
for (auto i = 0; i < uniformBuffers.size(); i++) {
446431
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &compute.descriptorSetLayout, 1);
447432
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &compute.descriptorSets[i]));
448-
std::vector<VkWriteDescriptorSet> computeWriteDescriptorSets =
449-
{
433+
std::vector<VkWriteDescriptorSet> computeWriteDescriptorSets = {
450434
// Binding 0: Instance input data buffer
451435
vks::initializers::writeDescriptorSet(compute.descriptorSets[i], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, &instanceBuffer.descriptor),
452436
// Binding 1: Indirect draw command output buffer
@@ -504,8 +488,14 @@ class VulkanExample : public VulkanExampleBase
504488
// Semaphores to order compute and graphics submissions
505489
for (auto& semaphore : compute.semaphores) {
506490
VkSemaphoreCreateInfo semaphoreInfo{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
507-
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &semaphore);
491+
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &semaphore.complete));
492+
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &semaphore.ready));
508493
}
494+
// Signal first used ready semaphore
495+
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
496+
computeSubmitInfo.signalSemaphoreCount = 1;
497+
computeSubmitInfo.pSignalSemaphores = &compute.semaphores[-1 % maxConcurrentFrames].ready;
498+
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE));
509499
}
510500

511501
void updateUniformBuffer()
@@ -731,8 +721,6 @@ class VulkanExample : public VulkanExampleBase
731721
0, nullptr);
732722
}
733723

734-
// todo: barrier for indirect stats buffer?
735-
736724
vkEndCommandBuffer(cmdBuffer);
737725
}
738726

@@ -741,55 +729,55 @@ class VulkanExample : public VulkanExampleBase
741729
if (!prepared)
742730
return;
743731

744-
VulkanExampleBase::prepareFrame(false);
745-
746732
// Submit compute commands
747-
748-
VK_CHECK_RESULT(vkWaitForFences(device, 1, &compute.fences[currentBuffer], VK_TRUE, UINT64_MAX));
749-
VK_CHECK_RESULT(vkResetFences(device, 1, &compute.fences[currentBuffer]));
750-
751-
// Get draw count from compute
752-
memcpy(&indirectStats, indirectDrawCountBuffers[currentBuffer].mapped, sizeof(indirectStats));
753-
754-
//updateComputeUniformBuffers();
755-
buildComputeCommandBuffer();
756-
757-
// Wait for rendering finished
758-
VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
759-
760-
VkSubmitInfo computeSubmitInfo = vks::initializers::submitInfo();
761-
computeSubmitInfo.commandBufferCount = 1;
762-
computeSubmitInfo.pCommandBuffers = &compute.commandBuffers[currentBuffer];
763-
computeSubmitInfo.pWaitDstStageMask = &waitStageMask;
764-
computeSubmitInfo.signalSemaphoreCount = 1;
765-
computeSubmitInfo.pSignalSemaphores = &compute.semaphores[currentBuffer];
766-
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, compute.fences[currentBuffer]));
767-
768-
// Submit graphics commands
769-
770-
VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX));
771-
VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentBuffer]));
772-
773-
// @todo: need to split for new sycn
774-
updateUniformBuffer();
775-
buildGraphicsCommandBuffer();
776-
777-
VkPipelineStageFlags graphicsWaitStageMasks[] = { VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
778-
VkSemaphore graphicsWaitSemaphores[] = { compute.semaphores[currentBuffer], presentCompleteSemaphores[currentBuffer] };
733+
{
734+
VK_CHECK_RESULT(vkWaitForFences(device, 1, &compute.fences[currentBuffer], VK_TRUE, UINT64_MAX));
735+
VK_CHECK_RESULT(vkResetFences(device, 1, &compute.fences[currentBuffer]));
736+
737+
// Get draw count from compute
738+
memcpy(&indirectStats, indirectDrawCountBuffers[currentBuffer].mapped, sizeof(indirectStats));
739+
buildComputeCommandBuffer();
740+
741+
// Wait for rendering finished
742+
VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
743+
VkSubmitInfo submitInfo = vks::initializers::submitInfo();
744+
submitInfo.waitSemaphoreCount = 1;
745+
submitInfo.pWaitSemaphores = &compute.semaphores[((int)currentBuffer - 1) % maxConcurrentFrames].ready;
746+
submitInfo.pWaitDstStageMask = &waitDstStageMask;
747+
submitInfo.signalSemaphoreCount = 1;
748+
submitInfo.pSignalSemaphores = &compute.semaphores[currentBuffer].complete;
749+
submitInfo.commandBufferCount = 1;
750+
submitInfo.pCommandBuffers = &compute.commandBuffers[currentBuffer];
751+
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &submitInfo, compute.fences[currentBuffer]));
752+
}
779753

780754
// Submit graphics commands
781-
VkSubmitInfo graphicsSubmitInfo = vks::initializers::submitInfo();
782-
graphicsSubmitInfo.commandBufferCount = 1;
783-
graphicsSubmitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
784-
graphicsSubmitInfo.waitSemaphoreCount = 2;
785-
graphicsSubmitInfo.pWaitSemaphores = graphicsWaitSemaphores;
786-
graphicsSubmitInfo.pWaitDstStageMask = graphicsWaitStageMasks;
787-
graphicsSubmitInfo.signalSemaphoreCount = 1;
788-
graphicsSubmitInfo.pSignalSemaphores = &renderCompleteSemaphores[currentImageIndex];
789-
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &graphicsSubmitInfo, waitFences[currentBuffer]));
790-
791-
VulkanExampleBase::submitFrame(VK_NULL_HANDLE, true);
792-
755+
{
756+
VK_CHECK_RESULT(vkWaitForFences(device, 1, &waitFences[currentBuffer], VK_TRUE, UINT64_MAX));
757+
VK_CHECK_RESULT(vkResetFences(device, 1, &waitFences[currentBuffer]));
758+
759+
VulkanExampleBase::prepareFrame(false);
760+
761+
updateUniformBuffer();
762+
buildGraphicsCommandBuffer();
763+
764+
VkPipelineStageFlags waitDstStageMask[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT };
765+
VkSemaphore waitSemaphores[2] = { presentCompleteSemaphores[currentBuffer], compute.semaphores[currentBuffer].complete };
766+
VkSemaphore signalSemaphores[2] = { renderCompleteSemaphores[currentImageIndex], compute.semaphores[currentBuffer].ready };
767+
768+
// Submit graphics commands
769+
VkSubmitInfo submitInfo = vks::initializers::submitInfo();
770+
submitInfo.waitSemaphoreCount = 2;
771+
submitInfo.pWaitDstStageMask = waitDstStageMask;
772+
submitInfo.pWaitSemaphores = waitSemaphores;
773+
submitInfo.commandBufferCount = 1;
774+
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
775+
submitInfo.signalSemaphoreCount = 2;
776+
submitInfo.pSignalSemaphores = signalSemaphores;
777+
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, waitFences[currentBuffer]));
778+
779+
VulkanExampleBase::submitFrame(VK_NULL_HANDLE, true);
780+
}
793781
}
794782

795783
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)

0 commit comments

Comments
 (0)