2
3
4
5
12#include "Core/Library/MemoryLibrary.h"
26 return m_tlas.accel->Get();
33 const std::vector<BlasInput>& input ,
34 VkBuildAccelerationStructureFlagsKHR flags
39 const auto nbBlas =
static_cast<uint32_t>(input.size());
40 VkDeviceSize asTotalSize = 0;
41 uint32_t nbCompactions = 0;
42 VkDeviceSize maxScratchSize = 0;
45
46
47 std::vector<BuildAccelerationStructure> buildAs(nbBlas);
48 for (uint32_t idx = 0; idx < nbBlas; idx++)
51
52
53
54 buildAs[idx].buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
55 buildAs[idx].buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
56 buildAs[idx].buildInfo.flags = input[idx].flags | flags;
57 buildAs[idx].buildInfo.geometryCount =
static_cast<uint32_t>(input[idx].asGeometry.size());
58 buildAs[idx].buildInfo.pGeometries = input[idx].asGeometry.data();
59 buildAs[idx].rangeInfo = input[idx].asBuildOffsetInfo.data();
60 buildAs[idx].as = input[idx].accel;
63
64
65 std::vector<uint32_t> maxPrimCount(input[idx].asBuildOffsetInfo.size());
66 for (
auto tt = 0; tt < input[idx].asBuildOffsetInfo.size(); tt++)
68 maxPrimCount[tt] = input[idx].asBuildOffsetInfo[tt].primitiveCount;
72
73
74 m_VulkanState.m_VkFunc.vkGetAccelerationStructureBuildSizesKHR(
75 m_VulkanState.m_Device,
76 VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
77 &buildAs[idx].buildInfo,
79 &buildAs[idx].sizeInfo
83
84
85 asTotalSize += buildAs[idx].sizeInfo.accelerationStructureSize;
86 maxScratchSize = std::max(maxScratchSize, buildAs[idx].sizeInfo.buildScratchSize);
87 nbCompactions += hasFlag(buildAs[idx].buildInfo.flags, VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR);
91
92
97 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
98 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ,
99 VMA_MEMORY_PROPERTY_DEDICATED_MEMORY_BIT
102 const VkDeviceAddress scratchAddress = scratchBuffer.GetAddress();
105
106
108 if (nbCompactions > 0)
110 assert(nbCompactions == nbBlas);
113
114
115 queryPool = std::make_shared<VulkanQueryPool>(m_VulkanState, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, nbBlas);
119
120
121 std::vector<uint32_t> indices;
122 VkDeviceSize batchSize = 0;
123 constexpr VkDeviceSize batchLimit = 256'000'000;
125 for (uint32_t idx = 0; idx < nbBlas; idx++)
127 indices.push_back(idx);
128 batchSize += buildAs[idx].sizeInfo.accelerationStructureSize;
131
132
133 if (batchSize >= batchLimit || idx == nbBlas - 1)
135 VulkanCommandBuffer::CustomGraphicCmd(m_VulkanState, [&](
const VkCommandBuffer& commandBuffer) {
136 CmdCreateBLAS(commandBuffer, indices, buildAs, scratchAddress, queryPool);
141 VulkanCommandBuffer::CustomGraphicCmd(m_VulkanState, [&](
const VkCommandBuffer& commandBuffer) {
142 CmdCompactBLAS(commandBuffer, indices, buildAs, queryPool);
147
148
160 VkAccelerationStructureBuildGeometryInfoKHR buildInfos{};
161 buildInfos.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
162 buildInfos.flags = flags;
163 buildInfos.geometryCount =
static_cast<uint32_t>(blas.asGeometry.size());
164 buildInfos.pGeometries = blas.asGeometry.data();
165 buildInfos.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR;
166 buildInfos.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
171 std::vector<uint32_t> maxPrimCount(blas.asBuildOffsetInfo.size());
173 for (
auto tt = 0; tt < blas.asBuildOffsetInfo.size(); tt++)
175 maxPrimCount[tt] = blas.asBuildOffsetInfo[tt].primitiveCount;
178 VkAccelerationStructureBuildSizesInfoKHR sizeInfo{};
179 sizeInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
181 m_VulkanState.m_VkFunc.vkGetAccelerationStructureBuildSizesKHR(
182 m_VulkanState.m_Device,
183 VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
193 sizeInfo.buildScratchSize,
194 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
195 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
199 VkBufferDeviceAddressInfo bufferInfo{};
200 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
201 bufferInfo.buffer = scratchBuffer.Get();
202 buildInfos.scratchData.deviceAddress = vkGetBufferDeviceAddress(m_VulkanState.m_Device, &bufferInfo);
204 std::vector<
const VkAccelerationStructureBuildRangeInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
205 for (size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++)
207 pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
214 m_VulkanState.m_VkFunc.vkCmdBuildAccelerationStructuresKHR(commandBuffer, 1, &buildInfos, pBuildOffset.data());
219 const std::vector<VkAccelerationStructureInstanceKHR>& instances ,
220 VkBuildAccelerationStructureFlagsKHR flags ,
226 BuildTLAS(instances, flags, update,
false);
230 VkCommandBuffer cmdBuf ,
231 uint32_t countInstance ,
232 VkDeviceAddress instBufferAddr ,
233 std::unique_ptr<VulkanBuffer>& scratchBuffer ,
234 VkBuildAccelerationStructureFlagsKHR flags ,
242
243
244 VkAccelerationStructureGeometryInstancesDataKHR instancesVk{};
245 instancesVk.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
246 instancesVk.data.deviceAddress = instBufferAddr;
249
250
251 VkAccelerationStructureGeometryKHR topASGeometry{};
252 topASGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
253 topASGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
254 topASGeometry.geometry.instances = instancesVk;
257
258
259 VkAccelerationStructureBuildGeometryInfoKHR buildInfo{};
260 buildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
261 buildInfo.flags = flags;
262 buildInfo.geometryCount = 1;
263 buildInfo.pGeometries = &topASGeometry;
264 buildInfo.mode = update ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
265 buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
266 buildInfo.srcAccelerationStructure = VK_NULL_HANDLE;
268 VkAccelerationStructureBuildSizesInfoKHR sizeInfo{};
269 sizeInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
271 m_VulkanState.m_VkFunc.vkGetAccelerationStructureBuildSizesKHR(
272 m_VulkanState.m_Device,
273 VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
279#ifdef VK_NV_ray_tracing_motion_blur
281 VkAccelerationStructureMotionInfoNV motionInfo{};
282 motionInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV;
283 motionInfo.maxInstances = countInstance;
288
289
292 VkAccelerationStructureCreateInfoKHR createInfo{};
293 createInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
294 createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
295 createInfo.size = sizeInfo.accelerationStructureSize;
297#ifdef VK_NV_ray_tracing_motion_blur
301 createInfo.createFlags = VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV;
302 createInfo.pNext = &motionInfo;
307 m_tlas = CreateAcceleration(createInfo);
311
312
313 scratchBuffer = std::make_unique<VulkanBuffer>(
316 sizeInfo.buildScratchSize,
317 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
318 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
319 VMA_MEMORY_PROPERTY_DEDICATED_MEMORY_BIT
322 VkDeviceAddress scratchAddress = scratchBuffer->GetAddress();
325
326
327 buildInfo.srcAccelerationStructure = update ? m_tlas.accel->Get() : VK_NULL_HANDLE;
328 buildInfo.dstAccelerationStructure = m_tlas.accel->Get();
329 buildInfo.scratchData.deviceAddress = scratchAddress;
332
333
334 VkAccelerationStructureBuildRangeInfoKHR buildOffsetInfo{};
335 buildOffsetInfo.primitiveCount = countInstance;
336 buildOffsetInfo.primitiveOffset = 0;
337 buildOffsetInfo.firstVertex = 0;
338 buildOffsetInfo.transformOffset = 0;
340 const VkAccelerationStructureBuildRangeInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
343
344
345 m_VulkanState.m_VkFunc.vkCmdBuildAccelerationStructuresKHR(cmdBuf, 1, &buildInfo, &pBuildOffsetInfo);
354 m_HitGroups = std::make_shared<std::unordered_map<std::string, uint32_t>>();
364 const uint32_t hitCount =
static_cast<uint32_t>(m_HitGroups->size());
366 const auto handleCount = rgenCount + missCount + hitCount;
367 const uint32_t handleSize = VulkanDevice::GetRTPipelineProperties().shaderGroupHandleSize;
370
371
372 const uint32_t handleSizeAligned = MemoryLibrary::align_up(handleSize, VulkanDevice::GetRTPipelineProperties().shaderGroupHandleAlignment);
374 m_RgenRegion.stride = MemoryLibrary::align_up(handleSizeAligned, VulkanDevice::GetRTPipelineProperties().shaderGroupBaseAlignment);
375 m_RgenRegion.size = m_RgenRegion.stride;
377 m_MissRegion.stride = handleSizeAligned;
378 m_MissRegion.size = MemoryLibrary::align_up(missCount * handleSizeAligned, VulkanDevice::GetRTPipelineProperties().shaderGroupBaseAlignment);
380 m_HitRegion.stride = handleSizeAligned;
381 m_HitRegion.size = MemoryLibrary::align_up(hitCount * handleSizeAligned, VulkanDevice::GetRTPipelineProperties().shaderGroupBaseAlignment);
384
385
386 const uint32_t dataSize = handleCount * handleSize;
387 std::vector<uint8_t> handles(dataSize);
390 .vkGetRayTracingShaderGroupHandlesKHR(
391 m_VulkanState.m_Device ,
400
401
402 VkDeviceSize sbtSize = m_RgenRegion.size + m_MissRegion.size + m_HitRegion.size + m_CallRegion.size;
404 m_RTSBTBuffer = std::make_unique<VulkanBuffer>(
408 VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
409 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT |
410 VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR ,
411 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
412 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
415 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_BUFFER, (uint64_t)m_RTSBTBuffer->Get(), m_VulkanState.m_Device,
"SBT Buffer")
417 m_RgenRegion.deviceAddress = m_RTSBTBuffer->GetAddress();
418 m_MissRegion.deviceAddress = m_RTSBTBuffer->GetAddress() + m_RgenRegion.size;
419 m_HitRegion.deviceAddress = m_RTSBTBuffer->GetAddress() + m_RgenRegion.size + m_MissRegion.size;
422
423
424 auto getHandle = [&](
int i) {
return handles.data() + i * handleSize; };
427
428
430 uint32_t handleIdx = 0 ;
433
434
435 for (uint32_t c = 0; c < rgenCount; c++)
437 m_RTSBTBuffer->WriteToBuffer(getHandle(handleIdx++), handleSize, offset);
442
443
444 offset = m_RgenRegion.size;
445 for (uint32_t c = 0; c < missCount; c++)
447 m_RTSBTBuffer->WriteToBuffer(getHandle(handleIdx++), handleSize, offset);
448 offset += m_MissRegion.stride;
452
453
454 offset = m_RgenRegion.size + m_MissRegion.size;
455 for (uint32_t c = 0; c < hitCount; c++)
457 m_RTSBTBuffer->WriteToBuffer(getHandle(handleIdx++), handleSize, offset);
458 offset += m_HitRegion.stride;
470 VkCommandBuffer cmdBuf ,
471 const std::vector<uint32_t>& indices ,
472 std::vector<BuildAccelerationStructure>& buildAs ,
473 VkDeviceAddress scratchAddress ,
480
481
484 queryPool->Reset(cmdBuf);
487 uint32_t queryCnt{ 0 };
490
491
492 for (
const auto& idx : indices)
495
496
497 VkAccelerationStructureCreateInfoKHR createInfo{};
498 createInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
499 createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
500 createInfo.size = buildAs[idx].sizeInfo.accelerationStructureSize;
502 *buildAs[idx].as = CreateAcceleration(createInfo);
505
506
507 buildAs[idx].buildInfo.dstAccelerationStructure = buildAs[idx].as->accel->Get();
508 buildAs[idx].buildInfo.scratchData.deviceAddress = scratchAddress;
511
512
513 m_VulkanState.m_VkFunc.vkCmdBuildAccelerationStructuresKHR(cmdBuf, 1, &buildAs[idx].buildInfo, &buildAs[idx].rangeInfo);
516
517
518
519 VkMemoryBarrier barrier{};
520 barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
521 barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
522 barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
524 vkCmdPipelineBarrier(
526 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
527 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
538
539
543
544
545 m_VulkanState.m_VkFunc.vkCmdWriteAccelerationStructuresPropertiesKHR(
548 &buildAs[idx].buildInfo.dstAccelerationStructure,
549 VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
558 VkCommandBuffer cmdBuf ,
559 const std::vector<uint32_t>& indices ,
560 std::vector<BuildAccelerationStructure>& buildAs ,
567 uint32_t queryCtn = 0;
570
571
572 std::vector<VkDeviceSize> compactSizes(
static_cast<uint32_t>(indices.size()));
575
576
577 queryPool->QueryResults(compactSizes.data());
579 for (
const auto idx : indices)
581 buildAs[idx].cleanupAS = *buildAs[idx].as;
582 buildAs[idx].sizeInfo.accelerationStructureSize = compactSizes[queryCtn++];
585
586
587 VkAccelerationStructureCreateInfoKHR asCreateInfo{};
588 asCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
589 asCreateInfo.size = buildAs[idx].sizeInfo.accelerationStructureSize;
590 asCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
591 *buildAs[idx].as = CreateAcceleration(asCreateInfo);
594
595
596 VkCopyAccelerationStructureInfoKHR copyInfo{};
597 copyInfo.sType = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR;
598 copyInfo.src = buildAs[idx].buildInfo.dstAccelerationStructure;
599 copyInfo.dst = buildAs[idx].as->accel->Get();
600 copyInfo.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR;
602 m_VulkanState.m_VkFunc.vkCmdCopyAccelerationStructureKHR(cmdBuf, ©Info);
613
614
615 resultAccel.buffer = std::make_shared<VulkanBuffer>(
619 VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR |
620 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
625
626
627 accel.buffer = resultAccel.buffer->Get();
630
631
632 resultAccel.accel = std::make_shared<VulkanAccelerationStructure>(m_VulkanState, accel);
#define SPICES_PROFILE_ZONE
#define VK_CHECK(expr)
Vulkan Check macro. Verify Vulkan API Effectiveness.
This Class is a Wrapper of VulkanBuffer.
VulkanCommandBuffer Class. This class defines the VulkanCommandBuffer behaves. This class is just a w...
VulkanState & m_VulkanState
The global VulkanState Referenced from VulkanRenderBackend.
VulkanObject(VulkanState &vulkanState)
Constructor Function. Init member variables.
VulkanObject Class. This class defines the basic behaves of VulkanObject. When we create an new Vulka...
This Class is a Wrapper of VulkanQueryPool.
void BuildBLAS(const std::vector< BlasInput > &input, VkBuildAccelerationStructureFlagsKHR flags=VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR)
Create all the BLAS from the vector of BlasInput. There will be one BLAS per input-vector entry....
VulkanRayTracing(VulkanState &vulkanState)
Constructor Function.
void CmdCreateTLAS(VkCommandBuffer cmdBuf, uint32_t countInstance, VkDeviceAddress instBufferAddr, std::unique_ptr< VulkanBuffer > &scratchBuffer, VkBuildAccelerationStructureFlagsKHR flags, bool update, bool motion)
Low level of Tlas creation. Creating the TLAS, called by buildTlas.
void CmdCreateBLAS(VkCommandBuffer cmdBuf, const std::vector< uint32_t > &indices, std::vector< BuildAccelerationStructure > &buildAs, VkDeviceAddress scratchAddress, std::shared_ptr< VulkanQueryPool > queryPool) const
Creating the bottom level acceleration structure for all indices of buildAs vector....
const VkAccelerationStructureKHR GetAccelerationStructure() const
Get AccelerationStructure.
Attribute< uint64_t > & GetMeshDesc()
Get Mesh Description.
void BuildTLAS(const std::vector< VkAccelerationStructureInstanceKHR > &instances, VkBuildAccelerationStructureFlagsKHR flags=VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, bool update=false)
Creating the top-level acceleration structure from the vector of Instance. The resulting TLAS will be...
void CmdCompactBLAS(VkCommandBuffer cmdBuf, const std::vector< uint32_t > &indices, std::vector< BuildAccelerationStructure > &buildAs, std::shared_ptr< VulkanQueryPool > queryPool) const
Create and replace a new acceleration structure and buffer based on the size retrieved by the Query....
AccelKHR CreateAcceleration(VkAccelerationStructureCreateInfoKHR &accel) const
Create Acceleration.
std::shared_ptr< std::unordered_map< std::string, uint32_t > > GetHitGroups()
Get Scene hit groups.
void UpdateBlas(uint32_t blasIdx, const BlasInput &blas, VkBuildAccelerationStructureFlagsKHR flags) const
Update part of BLAS.
void CreateRTShaderBindingTable(uint32_t rgenCount, uint32_t missCount, VkPipeline pipeline)
Create Shader Binding Table.
Wrapper of Scene RayTracing (KHR/VK) Features and Data.
MeshResource's item template.
This struct contains all Vulkan object in used global.