From 642cef78b1a1c2f3de050ff1b6475571c571008c Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Thu, 29 Jan 2026 19:46:53 +0100 Subject: [PATCH] buffered TLAS --- examples/VulkanTriangle/main.cpp | 8 ++-- ...fter.Graphics-RenderingElement3DVulkan.cpp | 18 +++---- .../Crafter.Graphics-Window_vulkan.cpp | 48 ------------------- ...ter.Graphics-RenderingElement3DVulkan.cppm | 13 +++-- 4 files changed, 23 insertions(+), 64 deletions(-) diff --git a/examples/VulkanTriangle/main.cpp b/examples/VulkanTriangle/main.cpp index 293b4ff..692154f 100644 --- a/examples/VulkanTriangle/main.cpp +++ b/examples/VulkanTriangle/main.cpp @@ -3,6 +3,7 @@ import Crafter.Graphics; using namespace Crafter; import std; +import Crafter.Event; typedef VulkanShader<"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR, 2, {{{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0}, {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1}}}> Raygenspv; typedef VulkanShader<"closesthit.spv", "main", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, 0, {{}}> Closesthitspv; @@ -39,7 +40,8 @@ int main() { std::array index {{2,1,0}}; triangleMesh.Build(verts, index, cmd); RenderingElement3DVulkan::elements.emplace_back(triangleMesh); - RenderingElement3DVulkan::BuildTLAS(cmd); + RenderingElement3DVulkan::tlases.resize(1); + RenderingElement3DVulkan::BuildTLAS(cmd, 0); VkDescriptorImageInfo imageInfo = { .imageView = window.imageViews[0], @@ -49,7 +51,7 @@ int main() { VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, .accelerationStructureCount = 1, - .pAccelerationStructures = &RenderingElement3DVulkan::accelerationStructure + .pAccelerationStructures = &RenderingElement3DVulkan::tlases[0].accelerationStructure }; VkWriteDescriptorSet write[2] = { @@ -84,7 +86,7 @@ int main() { window.SetPipelineRT(); window.descriptorsRt = pool.sets; + window.Render(); - window.StartSync(); } diff --git a/implementations/Crafter.Graphics-RenderingElement3DVulkan.cpp b/implementations/Crafter.Graphics-RenderingElement3DVulkan.cpp index b14167a..a92abe5 100644 --- a/implementations/Crafter.Graphics-RenderingElement3DVulkan.cpp +++ b/implementations/Crafter.Graphics-RenderingElement3DVulkan.cpp @@ -52,19 +52,19 @@ RenderingElement3DVulkan::RenderingElement3DVulkan(Mesh& mesh) { }; } -void RenderingElement3DVulkan::BuildTLAS(VkCommandBuffer cmd) { - instanceBuffer.Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, elements.size()); +void RenderingElement3DVulkan::BuildTLAS(VkCommandBuffer cmd, std::uint32_t index) { + tlases[index].instanceBuffer.Resize(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, elements.size()); for(std::uint32_t i = 0; i < elements.size(); i++) { - instanceBuffer.value[i] = elements[i].instance; + tlases[index].instanceBuffer.value[i] = elements[i].instance; } - instanceBuffer.FlushDevice(cmd, VK_ACCESS_MEMORY_READ_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); + tlases[index].instanceBuffer.FlushDevice(cmd, VK_ACCESS_MEMORY_READ_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); VkAccelerationStructureGeometryInstancesDataKHR instancesData = VkAccelerationStructureGeometryInstancesDataKHR { .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR, .arrayOfPointers = VK_FALSE, - .data = {instanceBuffer.address} + .data = {tlases[index].instanceBuffer.address} }; VkAccelerationStructureGeometryDataKHR geometryData; @@ -101,19 +101,19 @@ void RenderingElement3DVulkan::BuildTLAS(VkCommandBuffer cmd) { scratchBuffer.Resize(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, tlasBuildSizes.buildScratchSize); tlasBuildGeometryInfo.scratchData.deviceAddress = scratchBuffer.address; - tlasBuffer.Resize(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, tlasBuildSizes.accelerationStructureSize); + tlases[index].buffer.Resize(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, tlasBuildSizes.accelerationStructureSize); // Create and store the TLAS handle VkAccelerationStructureCreateInfoKHR tlasCreateInfo { .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, - .buffer = tlasBuffer.buffer, + .buffer = tlases[index].buffer.buffer, .offset = 0, .size = tlasBuildSizes.accelerationStructureSize, .type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR, }; - VulkanDevice::CheckVkResult(VulkanDevice::vkCreateAccelerationStructureKHR(VulkanDevice::device, &tlasCreateInfo, nullptr, &accelerationStructure)); - tlasBuildGeometryInfo.dstAccelerationStructure = accelerationStructure; + VulkanDevice::CheckVkResult(VulkanDevice::vkCreateAccelerationStructureKHR(VulkanDevice::device, &tlasCreateInfo, nullptr, &tlases[index].accelerationStructure)); + tlasBuildGeometryInfo.dstAccelerationStructure = tlases[index].accelerationStructure; // Prepare the build range for the TLAS VkAccelerationStructureBuildRangeInfoKHR tlasRangeInfo { diff --git a/implementations/Crafter.Graphics-Window_vulkan.cpp b/implementations/Crafter.Graphics-Window_vulkan.cpp index 14997ae..5dea6f7 100644 --- a/implementations/Crafter.Graphics-Window_vulkan.cpp +++ b/implementations/Crafter.Graphics-Window_vulkan.cpp @@ -297,54 +297,6 @@ WindowVulkan::WindowVulkan(std::uint32_t width, std::uint32_t height) : Window(w subpassDescription.pPreserveAttachments = nullptr; subpassDescription.pResolveAttachments = nullptr; - // // Subpass dependencies for layout transitions - // std::array dependencies{}; - - // dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; - // dependencies[0].dstSubpass = 0; - // dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - // dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - // dependencies[0].srcAccessMask = 0; - // dependencies[0].dstAccessMask = 0; - // dependencies[0].dependencyFlags = 0; - - // dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL; - // dependencies[1].dstSubpass = 0; - // dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - // dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - // dependencies[1].srcAccessMask = 0; - // dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - // dependencies[1].dependencyFlags = 0; - - // VkRenderPassCreateInfo renderPassInfo = {}; - // renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - // renderPassInfo.attachmentCount = static_cast(attachments.size()); - // renderPassInfo.pAttachments = attachments.data(); - // renderPassInfo.subpassCount = 1; - // renderPassInfo.pSubpasses = &subpassDescription; - // renderPassInfo.dependencyCount = static_cast(dependencies.size()); - // renderPassInfo.pDependencies = dependencies.data(); - - // VulkanDevice::CheckVkResult(vkCreateRenderPass(VulkanDevice::device, &renderPassInfo, nullptr, &renderPass)); - - // Create frame buffers for every swap chain image - // frameBuffers.resize(images.size()); - // for (uint32_t i = 0; i < frameBuffers.size(); i++) - // { - // const VkImageView attachments[1] = { - // imageViews[i] - // }; - // VkFramebufferCreateInfo frameBufferCreateInfo{}; - // frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - // frameBufferCreateInfo.renderPass = VK_NULL_HANDLE; - // frameBufferCreateInfo.attachmentCount = 1; - // frameBufferCreateInfo.pAttachments = attachments; - // frameBufferCreateInfo.width = width; - // frameBufferCreateInfo.height = height; - // frameBufferCreateInfo.layers = 1; - // VulkanDevice::CheckVkResult(vkCreateFramebuffer(VulkanDevice::device, &frameBufferCreateInfo, nullptr, &frameBuffers[i])); - // } - drawCmdBuffers.resize(images.size()); VkCommandBufferAllocateInfo cmdBufAllocateInfo {}; diff --git a/interfaces/Crafter.Graphics-RenderingElement3DVulkan.cppm b/interfaces/Crafter.Graphics-RenderingElement3DVulkan.cppm index 2f897e1..8da0279 100644 --- a/interfaces/Crafter.Graphics-RenderingElement3DVulkan.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement3DVulkan.cppm @@ -28,17 +28,22 @@ import :Mesh; import :VulkanBuffer; export namespace Crafter { + + struct TlasWithBuffer { + VulkanBuffer buffer; + VkAccelerationStructureKHR accelerationStructure; + VulkanBuffer instanceBuffer; + }; + class RenderingElement3DVulkan { public: Mesh* mesh; VkAccelerationStructureInstanceKHR instance; static std::vector elements; - inline static VulkanBuffer instanceBuffer; inline static VulkanBuffer scratchBuffer; - inline static VulkanBuffer tlasBuffer; - inline static VkAccelerationStructureKHR accelerationStructure; + inline static std::vector tlases; RenderingElement3DVulkan(Mesh& mesh); - static void BuildTLAS(VkCommandBuffer cmd); + static void BuildTLAS(VkCommandBuffer cmd, std::uint32_t index); }; } #endif \ No newline at end of file