diff --git a/docs/vkrt_tuto_manyhits.md.htm b/docs/vkrt_tuto_manyhits.md.htm index 791cd70..966e1d9 100644 --- a/docs/vkrt_tuto_manyhits.md.htm +++ b/docs/vkrt_tuto_manyhits.md.htm @@ -218,9 +218,10 @@ The size of each group can be described as follows: ~~~~ C++ // Sizes - uint32_t rayGenSize = groupHandleSize; - uint32_t missSize = groupHandleSize; - uint32_t hitSize = groupHandleSize + sizeof(HitRecordBuffer); + uint32_t rayGenSize = baseAlignment; + uint32_t missSize = baseAlignment; + uint32_t hitSize = + ROUND_UP(groupHandleSize + static_cast(sizeof(HitRecordBuffer)), baseAlignment); uint32_t newSbtSize = rayGenSize + 2 * missSize + 2 * hitSize; ~~~~ @@ -238,14 +239,16 @@ Then write the new SBT like this, where only Hit 1 has extra data. memcpy(pBuffer, handles[2], groupHandleSize); // Miss 1 pBuffer += missSize; - memcpy(pBuffer, handles[3], groupHandleSize); // Hit 0 - pBuffer += groupHandleSize; - pBuffer += sizeof(HitRecordBuffer); // No data + uint8_t* pHitBuffer = pBuffer; + memcpy(pHitBuffer, handles[3], groupHandleSize); // Hit 0 + // No data + pBuffer += hitSize; - memcpy(pBuffer, handles[4], groupHandleSize); // Hit 1 - pBuffer += groupHandleSize; - memcpy(pBuffer, &m_hitShaderRecord[0], sizeof(HitRecordBuffer)); // Hit 1 data - pBuffer += sizeof(HitRecordBuffer); + pHitBuffer = pBuffer; + memcpy(pHitBuffer, handles[4], groupHandleSize); // Hit 1 + pHitBuffer += groupHandleSize; + memcpy(pHitBuffer, &m_hitShaderRecord[0], sizeof(HitRecordBuffer)); // Hit 1 data + pBuffer += hitSize; } ~~~~ @@ -255,12 +258,21 @@ Then change the call to `m_alloc.createBuffer` to create the SBT buffer from `sb m_rtSBTBuffer = m_alloc.createBuffer(cmdBuf, sbtBuffer, vk::BufferUsageFlagBits::eRayTracingKHR); ~~~~ +Note: we are using this `define` for rounding up to the correct alignment +~~~~ C++ +#ifndef ROUND_UP +#define ROUND_UP(v, powerOf2Alignment) (((v) + (powerOf2Alignment)-1) & ~((powerOf2Alignment)-1)) +#endif +~~~~ + + ## `raytrace` Finally, since the size of the hit group is now larger than just the handle, we need to set the new value of the hit group stride in `HelloVulkan::raytrace`. ~~~~ C++ -vk::DeviceSize hitGroupStride = progSize + sizeof(HitRecordBuffer); +vk::DeviceSize hitGroupStride = +ROUND_UP(m_rtProperties.shaderGroupHandleSize + sizeof(HitRecordBuffer), progOffset); ~~~~ !!! Note: @@ -316,10 +328,11 @@ The size of the SBT will now account for its 3 hit groups: Finally, we need to add the new entry as well at the end of the buffer, reusing the handle of the second Hit Group and setting a different color. ~~~~ C++ - memcpy(pBuffer, handles[4], groupHandleSize); // Hit 2 - pBuffer += groupHandleSize; - memcpy(pBuffer, &m_hitShaderRecord[1], sizeof(HitRecordBuffer)); // Hit 2 data - pBuffer += sizeof(HitRecordBuffer); + pHitBuffer = pBuffer; + memcpy(pHitBuffer, handles[4], groupHandleSize); // Hit 2 + pHitBuffer += groupHandleSize; + memcpy(pHitBuffer, &m_hitShaderRecord[1], sizeof(HitRecordBuffer)); // Hit 2 data + pBuffer += hitSize; ~~~~ !!! Warning diff --git a/docs/vkrt_tutorial.md.htm b/docs/vkrt_tutorial.md.htm index 718a8c7..ad874f0 100644 --- a/docs/vkrt_tutorial.md.htm +++ b/docs/vkrt_tutorial.md.htm @@ -1238,9 +1238,9 @@ group for that instance. The SBT is an array containing the handles to the shader groups used in the ray tracing pipeline. In our example, we will create a buffer for the three groups: raygen, miss and closest hit. The size of the handle is given by the -`shaderGroupHandleSize` member of the ray tracing properties. We will then allocate a buffer of size `3 * -shaderGroupHandleSize` and will consecutively write the handle of each shader group. To retrieve all the handles, we -will call `vkGetRayTracingShaderGroupHandlesKHR`. +`shaderGroupHandleSize` member of the ray tracing properties, but the offset need to be aligned on `shaderGroupBaseAlignment`. + We will then allocate a buffer of size `3 * shaderGroupBaseAlignment` and will consecutively write the handle of each shader group. + To retrieve all the handles, we will call `vkGetRayTracingShaderGroupHandlesKHR`. The buffer will have the following information, which will later be used when calling `vkCmdTraceRaysKHR`: @@ -1279,9 +1279,10 @@ void HelloVulkan::createRtShaderBindingTable() auto groupCount = static_cast(m_rtShaderGroups.size()); // 3 shaders: raygen, miss, chit uint32_t groupHandleSize = m_rtProperties.shaderGroupHandleSize; // Size of a program identifier + uint32_t baseAlignment = m_rtProperties.shaderGroupBaseAlignment; // Size of shader alignment // Fetch all the shader handles used in the pipeline, so that they can be written in the SBT - uint32_t sbtSize = groupCount * groupHandleSize; + uint32_t sbtSize = groupCount * baseAlignment; ```` We then fetch the handles to the shader groups of the pipeline, and let the allocator allocate the device memory and @@ -1291,16 +1292,21 @@ copy the handles into the SBT: std::vector shaderHandleStorage(sbtSize); m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, shaderHandleStorage.data()); + // Write the handles in the SBT + m_rtSBTBuffer = m_alloc.createBuffer(sbtSize, vk::BufferUsageFlagBits::eTransferSrc, + vk::MemoryPropertyFlagBits::eHostVisible + | vk::MemoryPropertyFlagBits::eHostCoherent); + m_debug.setObjectName(m_rtSBTBuffer.buffer, std::string("SBT").c_str()); + // Write the handles in the SBT - nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex); - vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); - - m_rtSBTBuffer = - m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); - m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); - - - genCmdBuf.submitAndWait(cmdBuf); + 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); // raygen + pData += baseAlignment; + } + m_alloc.unmap(m_rtSBTBuffer); m_alloc.finalizeAndReleaseStaging(); } @@ -1360,7 +1366,7 @@ each shader. In our case the stride is simply the size of a shader group handle, shader-group-specific data within the SBT, resulting in a larger stride. ```` C - vk::DeviceSize progSize = m_rtProperties.shaderGroupHandleSize; // Size of a program identifier + vk::DeviceSize progSize = m_rtProperties.shaderGroupBaseAlignment; // Size of a program identifier vk::DeviceSize rayGenOffset = 0u * progSize; // Start at the beginning of m_sbtBuffer vk::DeviceSize missOffset = 1u * progSize; // Jump over raygen vk::DeviceSize missStride = progSize;