From f47651244063da0ae600a57c2c07ef72679afbdd Mon Sep 17 00:00:00 2001 From: mklefrancois Date: Wed, 8 Sep 2021 15:55:19 +0200 Subject: [PATCH] Update SBT documentation --- docs/Images/sbt_0.png | Bin 0 -> 8628 bytes docs/Images/sbt_1.png | Bin 0 -> 9405 bytes docs/vkrt_tutorial.md.html | 279 +++++++++++++++++++------------------ 3 files changed, 145 insertions(+), 134 deletions(-) create mode 100644 docs/Images/sbt_0.png create mode 100644 docs/Images/sbt_1.png diff --git a/docs/Images/sbt_0.png b/docs/Images/sbt_0.png new file mode 100644 index 0000000000000000000000000000000000000000..2c9d4ff87f2a839937dc4bee72143590124059b1 GIT binary patch literal 8628 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 literal 0 HcmV?d00001 diff --git a/docs/Images/sbt_1.png b/docs/Images/sbt_1.png new file mode 100644 index 0000000000000000000000000000000000000000..78847f57e4b0c86f5260cadac4e28cd814a2ef56 GIT binary patch literal 9405 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.size()); // 4 shaders: raygen, 2 miss, chit - uint32_t groupHandleSize = m_rtProperties.shaderGroupHandleSize; // Size of a program identifier - // Compute the actual size needed per SBT entry (round-up to alignment needed). - uint32_t groupSizeAligned = nvh::align_up(groupHandleSize, m_rtProperties.shaderGroupBaseAlignment); - // Bytes needed for the SBT. - uint32_t sbtSize = groupCount * groupSizeAligned; + uint32_t missCount{1}; + uint32_t hitCount{1}; + auto handleCount = 1 + missCount + hitCount; + uint32_t handleSize = m_rtProperties.shaderGroupHandleSize; ~~~~ -We then fetch the handles to the shader groups of the pipeline, and let the allocator -allocate the device memory and copy the handles into the SBT. Note that SBT buffer need the -`VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR` flag and since we will need the address -of SBT buffer, therefore the buffer need also the `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` flag. +The following sets the stride and size for each group. With the exception of RayGen, the stride will be the size of the handle aligned to the `shaderGroupHandleAlignment`. And the size of each group, is the number of elements in the group aligned to the `shaderGroupBaseAlignment`. ~~~~ C - // Fetch all the shader handles used in the pipeline. This is opaque data, - // so we store it in a vector of bytes. - std::vector shaderHandleStorage(sbtSize); - auto result = vkGetRayTracingShaderGroupHandlesKHR(m_device, m_rtPipeline, 0, groupCount, sbtSize, shaderHandleStorage.data()); +// The SBT (buffer) need to have starting groups to be aligned and handles in the group to be aligned. +uint32_t handleSizeAligned = nvh::align_up(handleSize, m_rtProperties.shaderGroupHandleAlignment); - assert(result == VK_SUCCESS); +m_rgenRegion.stride = nvh::align_up(handleSizeAligned, m_rtProperties.shaderGroupBaseAlignment); +m_rgenRegion.size = m_rgenRegion.stride; // The size member of pRayGenShaderBindingTable must be equal to its stride member +m_missRegion.stride = handleSizeAligned; +m_missRegion.size = nvh::align_up(missCount * handleSizeAligned, m_rtProperties.shaderGroupBaseAlignment); +m_hitRegion.stride = handleSizeAligned; +m_hitRegion.size = nvh::align_up(hitCount * handleSizeAligned, m_rtProperties.shaderGroupBaseAlignment); +~~~~ - // Allocate a buffer for storing the SBT. Give it a debug name for NSight. - m_rtSBTBuffer = m_alloc.createBuffer(sbtSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - m_debug.setObjectName(m_rtSBTBuffer.buffer, std::string("SBT").c_str()); +We then fetch the handles to the shader groups of the pipeline. - // Map the SBT buffer and write in the handles. - void* mapped = m_alloc.map(m_rtSBTBuffer); - auto* pData = reinterpret_cast(mapped); - for(uint32_t g = 0; g < groupCount; g++) - { - memcpy(pData, shaderHandleStorage.data() + g * groupHandleSize, groupHandleSize); - pData += groupSizeAligned; - } +~~~~ C +// Get the shader group handles +uint32_t dataSize = handleCount * handleSize; +std::vector handles(dataSize); +auto result = vkGetRayTracingShaderGroupHandlesKHR(m_device, m_rtPipeline, 0, handleCount, dataSize, handles.data()); +assert(result == VK_SUCCESS); +~~~~ + +The following will allocate the buffer that will hold the handle data. Note that the SBT buffer needs the `VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR` flag. In order to trace rays we will also need the address of the SBT, which requires the `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` flag. + +~~~~ C +// Allocate a buffer for storing the SBT. +VkDeviceSize sbtSize = m_rgenRegion.size + m_missRegion.size + m_hitRegion.size + m_callRegion.size; +m_rtSBTBuffer = m_alloc.createBuffer(sbtSize, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); +m_debug.setObjectName(m_rtSBTBuffer.buffer, std::string("SBT")); // Give it a debug name for NSight. +~~~~ + +In the next section, we store the device address of each shader group. Since we do not use callables, we leave it at 0. + +~~~~ C +// Find the SBT addresses of each group +VkBufferDeviceAddressInfo info{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, nullptr, m_rtSBTBuffer.buffer}; +VkDeviceAddress sbtAddress = vkGetBufferDeviceAddress(m_device, &info); +m_rgenRegion.deviceAddress = sbtAddress; +m_missRegion.deviceAddress = sbtAddress + m_rgenRegion.size; +m_hitRegion.deviceAddress = sbtAddress + m_rgenRegion.size + m_missRegion.size; +~~~~ + +This lambda function will return the pointer to the previously retrieved handle. We will use this function to copy the data from the handle into the SBT buffer. + +~~~~ C +// Helper to retrieve the handle data +auto getHandle = [&] (int i) { return handles.data() + i * handleSize; }; +~~~~ + +Since our buffer is visible to the host, we will map its memory in preparation for the data copy. + +~~~~ C +// Map the SBT buffer and write in the handles. +auto* pSBTBuffer = reinterpret_cast(m_alloc.map(m_rtSBTBuffer)); +uint8_t* pData{nullptr}; +uint32_t handleIdx{0}; +~~~~ + +Copy the RayGen handle. Only the handle data is copied, even if the stride and size are larger. + +~~~~ C +// Raygen +pData = pSBTBuffer; +memcpy(pData, getHandle(handleIdx++), handleSize); +~~~~ + +Set the pointer to the beginning of the miss group and copy all the miss handles. +We only have one miss group for now, but this for-loop will work when we add more missed shaders. + +~~~~ C +// Miss +pData = pSBTBuffer + m_rgenRegion.size; +for(uint32_t c = 0; c < missCount; c++) +{ + memcpy(pData, getHandle(handleIdx++), handleSize); + pData += m_missRegion.stride; +} +~~~~ + +In the same way, copy the handles for the hit group. + +~~~~ C +// Hit +pData = pSBTBuffer + m_rgenRegion.size + m_missRegion.size; +for(uint32_t c = 0; c < hitCount; c++) +{ + memcpy(pData, getHandle(handleIdx++), handleSize); + pData += m_hitRegion.stride; +} +~~~~ + +Finalize and Clean up. + +~~~~ C m_alloc.unmap(m_rtSBTBuffer); m_alloc.finalizeAndReleaseStaging(); } @@ -1531,19 +1606,7 @@ As with other resources, we destroy the SBT in `destroyResources`: m_alloc.destroy(m_rtSBTBuffer); ~~~~ -!!! Warning Size and Alignment Gotcha - Pay close attention to the calculation of `groupSizeAligned` (the stride used for array entries). - There is no guarantee that the alignment divides the group size, so rounding up is necessary. - Using `groupHandleSize` as the stride may coincidentally work on your hardware, but not all hardware. - On hardware with a smaller handle size than alignment, you can get some `shaderRecordEXT` data "for free", - but naïve stride calculation fails. For those with long memories, this is similar to the problem created - by OpenGL std140 alignment rules for `vec3`. - - Round up sizes to the next alignment using the formula - - $alignedSize = [size + (alignment - 1)]\ \texttt{&}\ \texttt{~}(alignment - 1)$ - - Learn from our hard experience, don't find out the hard way!!! + !!! Tip Shader order As with the pipeline, there is no requirement that raygen, miss, and hit groups come @@ -1552,11 +1615,11 @@ As with other resources, we destroy the SBT in `destroyResources`: array used to build the pipeline. In general though, the order of the SBT need not match the pipeline shader stage order. -!!! Tip SBTWrapper - To avoid potential issues in the contruction of the SBT, we have a wrapper that uses the information - sent to the creation of the ray tracing pipeline to allocate the SBT. In further tutorials - we might use the [`nnvk::SBTWrapper`](https://github.com/nvpro-samples/nvpro_core/tree/master/nvvk#sbtwrapper_vkhpp) - instead of manually describing all steps. +!!! Tip SBT Wrapper + The number of entries per group can be retrieved from the `VkPhysicalDeviceRayTracingPipelinePropertiesKHR` that we used to create the ray tracing pipeline. The advantage of retrieving information from this structure, is that we don't have to follow a specific order. It goes beyond this tutorial, but we have a wrapper class that does all of the above automatically. You can find its implementation in + [`nnvk::SBTWrapper`](https://github.com/nvpro-samples/nvpro_core/tree/master/nvvk#sbtwrapper_vkhpp). + Some of the extra samples will be using this class. + ## main @@ -1578,10 +1641,6 @@ void raytrace(const VkCommandBuffer& cmdBuf, const nvmath::vec4f& clearCol We first bind the pipeline and its layout, and set the push constants that will be available throughout the pipeline: ~~~~ C -m_alloc.unmap(m_rtSBTBuffer); -m_alloc.finalizeAndReleaseStaging(); -} - //-------------------------------------------------------------------------------------------------- // Ray Tracing the scene // @@ -1603,39 +1662,7 @@ void HelloVulkan::raytrace(const VkCommandBuffer& cmdBuf, const nvmath::vec4f& c 0, sizeof(PushConstantRay), &m_pcRay); ~~~~ -Since the structure of the Shader Binding Table is up to the developer, we need to indicate the ray tracing pipeline how -to interpret it. In particular we compute the offsets in the SBT where the ray generation shader, miss shaders and hit -groups can be found. We stored miss shaders and hit groups contiguously, hence we also compute the stride separating -each shader. In our case the stride is simply the size of a shader group handle (plus padding for alignment as mentioned in the warning), -but more advanced uses may embed shader-group-specific data within the SBT, resulting in a larger stride. - -The location for each array of the SBT is passed as a `VkStridedDeviceAddressRegionKHR` struct, consisting of: - -* The device address where the array starts - -* The stride in bytes between consecutive array entries - -* The size in bytes of the entire array - -~~~~ C -// Size of a program identifier -uint32_t groupSize = nvh::align_up(m_rtProperties.shaderGroupHandleSize, m_rtProperties.shaderGroupBaseAlignment); -uint32_t groupStride = groupSize; - -VkBufferDeviceAddressInfo info{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, nullptr, m_rtSBTBuffer.buffer}; -VkDeviceAddress sbtAddress = vkGetBufferDeviceAddress(m_device, &info); - -using Stride = VkStridedDeviceAddressRegionKHR; -std::array strideAddresses{Stride{sbtAddress + 0u * groupSize, groupStride, groupSize * 1}, // raygen - Stride{sbtAddress + 1u * groupSize, groupStride, groupSize * 1}, // miss - Stride{sbtAddress + 2u * groupSize, groupStride, groupSize * 1}, // hit - Stride{0u, 0u, 0u}}; // callable -~~~~ - -!!! NOTE Separate Arrays - For this simple example, as we are not storing user data in the SBT, each array of the SBT has the same stride. - This allows us to treat the entire SBT as a single array, but in general, different arrays within the SBT may - have different strides. +Fortunately, all information about each `VkStridedDeviceAddressRegionKHR` was created in the `createRtShaderBindingTable()`. We can finally call `traceRaysKHR` that will add the ray tracing launch in the command buffer. Note that the SBT buffer address is mentioned several times. This is due to the possibility of separating the SBT into several buffers, one for each @@ -1644,19 +1671,16 @@ three parameters are equivalent to the grid size of a compute launch, and repres we want to trace one ray per pixel, the grid size has the width and height of the output image, and a depth of 1. ~~~~ C - vkCmdTraceRaysKHR(cmdBuf, &strideAddresses[0], &strideAddresses[1], &strideAddresses[2], &strideAddresses[3], - m_size.width, m_size.height, 1); - + vkCmdTraceRaysKHR(cmdBuf, &m_rgenRegion, &m_missRegion, &m_hitRegion, &m_callRegion, m_size.width, m_size.height, 1); m_debug.endLabel(cmdBuf); } ~~~~ - !!! TIP Raygen shader selection If you built a pipeline with multiple raygen shaders, the raygen shader can be selected by changing the - device address of the first `VkStridedDeviceAddressRegionKHR` structure (change the `0u` in `sbtAddress + 0u * groupSize`). + device address. !!! TIP SBTWrapper - When using the SBTWrapper, the above could be replaced by + When using the SBTWrapper, the above could be replaced by folowing. ``` auto& regions = m_stbWrapper.getRegions(); vkCmdTraceRaysKHR(cmdBuf, ®ions[0], ®ions[1], ®ions[2], ®ions[3], size.width, size.height, 1); @@ -1893,18 +1917,21 @@ fact that `clearColor` is the first member in the struct, and do not even declar ~~~~ C #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require + #include "raycommon.glsl" +#include "wavefront.glsl" layout(location = 0) rayPayloadInEXT hitPayload prd; -layout(push_constant) uniform Constants +layout(push_constant) uniform _PushConstantRay { - vec4 clearColor; + PushConstantRay pcRay; }; void main() { - prd.hitValue = clearColor.xyz * 0.8; + prd.hitValue = pcRay.clearColor.xyz * 0.8; } ~~~~ @@ -2192,32 +2219,16 @@ The pipeline now has to allow shooting rays from the closest hit program, which Recall that `m_rtProperties` was filled in in `HelloVulkan::initRayTracing`. -## `traceRaysKHR` +## `createRtShaderBindingTable` The addition of the new miss shader group has modified our shader binding table, which now looks like: -****************** -*+--------------+* -*| RayGen |* -*| Handle |* -*+--------------+* -*| Miss |* -*| Handle (0) |* -*+··············+* -*| ShadowMiss |* -*| Handle (1) |* -*+--------------+* -*| HitGroup |* -*| Handle |* -*+--------------+* -****************** +![](images/sbt_1.png) -Therefore, we have to change `HelloVulkan::raytrace` to adjust the the closest hit offset before calling `traceRaysKHR`. -This also points out that in real-world applications the SBT should be embedded so that it can handle those offsets -automatically. +Therefore, we have to change `HelloVulkan::createRtShaderBindingTable` to indicate that there are two miss shaders. ~~~~ C -Stride{sbtAddress + 3u * groupSize, groupStride, groupSize * 1}, // hit - Jump over the raygen and 2 miss shaders +uint32_t missCount{2}; ~~~~ ## `createRtDescriptorSet`