Fixing SBT alignment
This commit is contained in:
parent
ccdc90f35c
commit
41d6bbeea4
2 changed files with 48 additions and 29 deletions
|
|
@ -218,9 +218,10 @@ The size of each group can be described as follows:
|
||||||
|
|
||||||
~~~~ C++
|
~~~~ C++
|
||||||
// Sizes
|
// Sizes
|
||||||
uint32_t rayGenSize = groupHandleSize;
|
uint32_t rayGenSize = baseAlignment;
|
||||||
uint32_t missSize = groupHandleSize;
|
uint32_t missSize = baseAlignment;
|
||||||
uint32_t hitSize = groupHandleSize + sizeof(HitRecordBuffer);
|
uint32_t hitSize =
|
||||||
|
ROUND_UP(groupHandleSize + static_cast<int>(sizeof(HitRecordBuffer)), baseAlignment);
|
||||||
uint32_t newSbtSize = rayGenSize + 2 * missSize + 2 * hitSize;
|
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
|
memcpy(pBuffer, handles[2], groupHandleSize); // Miss 1
|
||||||
pBuffer += missSize;
|
pBuffer += missSize;
|
||||||
|
|
||||||
memcpy(pBuffer, handles[3], groupHandleSize); // Hit 0
|
uint8_t* pHitBuffer = pBuffer;
|
||||||
pBuffer += groupHandleSize;
|
memcpy(pHitBuffer, handles[3], groupHandleSize); // Hit 0
|
||||||
pBuffer += sizeof(HitRecordBuffer); // No data
|
// No data
|
||||||
|
pBuffer += hitSize;
|
||||||
|
|
||||||
memcpy(pBuffer, handles[4], groupHandleSize); // Hit 1
|
pHitBuffer = pBuffer;
|
||||||
pBuffer += groupHandleSize;
|
memcpy(pHitBuffer, handles[4], groupHandleSize); // Hit 1
|
||||||
memcpy(pBuffer, &m_hitShaderRecord[0], sizeof(HitRecordBuffer)); // Hit 1 data
|
pHitBuffer += groupHandleSize;
|
||||||
pBuffer += sizeof(HitRecordBuffer);
|
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);
|
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`
|
## `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`.
|
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++
|
~~~~ C++
|
||||||
vk::DeviceSize hitGroupStride = progSize + sizeof(HitRecordBuffer);
|
vk::DeviceSize hitGroupStride =
|
||||||
|
ROUND_UP(m_rtProperties.shaderGroupHandleSize + sizeof(HitRecordBuffer), progOffset);
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
!!! Note:
|
!!! 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.
|
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++
|
~~~~ C++
|
||||||
memcpy(pBuffer, handles[4], groupHandleSize); // Hit 2
|
pHitBuffer = pBuffer;
|
||||||
pBuffer += groupHandleSize;
|
memcpy(pHitBuffer, handles[4], groupHandleSize); // Hit 2
|
||||||
memcpy(pBuffer, &m_hitShaderRecord[1], sizeof(HitRecordBuffer)); // Hit 2 data
|
pHitBuffer += groupHandleSize;
|
||||||
pBuffer += sizeof(HitRecordBuffer);
|
memcpy(pHitBuffer, &m_hitShaderRecord[1], sizeof(HitRecordBuffer)); // Hit 2 data
|
||||||
|
pBuffer += hitSize;
|
||||||
~~~~
|
~~~~
|
||||||
|
|
||||||
!!! Warning
|
!!! Warning
|
||||||
|
|
|
||||||
|
|
@ -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
|
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
|
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` member of the ray tracing properties, but the offset need to be aligned on `shaderGroupBaseAlignment`.
|
||||||
shaderGroupHandleSize` and will consecutively write the handle of each shader group. To retrieve all the handles, we
|
We will then allocate a buffer of size `3 * shaderGroupBaseAlignment` and will consecutively write the handle of each shader group.
|
||||||
will call `vkGetRayTracingShaderGroupHandlesKHR`.
|
To retrieve all the handles, we will call `vkGetRayTracingShaderGroupHandlesKHR`.
|
||||||
|
|
||||||
The buffer will have the following information, which will later be used when calling `vkCmdTraceRaysKHR`:
|
The buffer will have the following information, which will later be used when calling `vkCmdTraceRaysKHR`:
|
||||||
|
|
||||||
|
|
@ -1279,9 +1279,10 @@ void HelloVulkan::createRtShaderBindingTable()
|
||||||
auto groupCount =
|
auto groupCount =
|
||||||
static_cast<uint32_t>(m_rtShaderGroups.size()); // 3 shaders: raygen, miss, chit
|
static_cast<uint32_t>(m_rtShaderGroups.size()); // 3 shaders: raygen, miss, chit
|
||||||
uint32_t groupHandleSize = m_rtProperties.shaderGroupHandleSize; // Size of a program identifier
|
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
|
// 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
|
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<uint8_t> shaderHandleStorage(sbtSize);
|
std::vector<uint8_t> shaderHandleStorage(sbtSize);
|
||||||
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
|
||||||
shaderHandleStorage.data());
|
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
|
// Write the handles in the SBT
|
||||||
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
|
void* mapped = m_alloc.map(m_rtSBTBuffer);
|
||||||
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
|
auto* pData = reinterpret_cast<uint8_t*>(mapped);
|
||||||
|
for(uint32_t g = 0; g < groupCount; g++)
|
||||||
m_rtSBTBuffer =
|
{
|
||||||
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
|
memcpy(pData, shaderHandleStorage.data() + g * groupHandleSize, groupHandleSize); // raygen
|
||||||
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
|
pData += baseAlignment;
|
||||||
|
}
|
||||||
|
m_alloc.unmap(m_rtSBTBuffer);
|
||||||
genCmdBuf.submitAndWait(cmdBuf);
|
|
||||||
|
|
||||||
m_alloc.finalizeAndReleaseStaging();
|
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.
|
shader-group-specific data within the SBT, resulting in a larger stride.
|
||||||
|
|
||||||
```` C
|
```` 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 rayGenOffset = 0u * progSize; // Start at the beginning of m_sbtBuffer
|
||||||
vk::DeviceSize missOffset = 1u * progSize; // Jump over raygen
|
vk::DeviceSize missOffset = 1u * progSize; // Jump over raygen
|
||||||
vk::DeviceSize missStride = progSize;
|
vk::DeviceSize missStride = progSize;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue