ray_tracing_indirect_scissor/hello_vulkan.cpp
void HelloVulkan::createRtShaderBindingTable()
{
  uint32_t missCount{3};
  uint32_t hitCount{4};
  auto     handleCount = 1 + missCount + hitCount;
  uint32_t handleSize  = m_rtProperties.shaderGroupHandleSize;

  // 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);
  
  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);

  // Get the shader group handles
  uint32_t             dataSize = handleCount * handleSize;
  std::vector<uint8_t> handles(dataSize);
  auto result = vkGetRayTracingShaderGroupHandlesKHR(m_device, m_rtPipeline, 0, handleCount, dataSize, handles.data());
  assert(result == VK_SUCCESS);

  // 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.

  // 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;

  // Helper to retrieve the handle data
  auto getHandle = [&](int i) { return handles.data() + i * handleSize; };

  // Map the SBT buffer and write in the handles.
  auto*    pSBTBuffer = reinterpret_cast<uint8_t*>(m_alloc.map(m_rtSBTBuffer));
  uint8_t* pData{nullptr};
  uint32_t handleIdx{0};
  // Raygen
  pData = pSBTBuffer;
  memcpy(pData, getHandle(handleIdx++), handleSize);
  // Miss
  pData = pSBTBuffer + m_rgenRegion.size;
  for(uint32_t c = 0; c < missCount; c++)
  {
    memcpy(pData, getHandle(handleIdx++), handleSize);
    pData += m_missRegion.stride;
  }
  // 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;
  }


  m_alloc.unmap(m_rtSBTBuffer);
  m_alloc.finalizeAndReleaseStaging();
}
//--------------------------------------------------------------------------------------------------
// The Shader Binding Table (SBT)
// - getting all shader handles and write them in a SBT buffer
// - Besides exception, this could be always done like this
//
The Shader Binding Table (SBT)
getting all shader handles and write them in a SBT buffer
Besides exception, this could be always done like this
The Shader Binding Table ( SBT ) getting all shader handles and write them in a SBT buffer Besides exception this could be always done like this
void HelloVulkan::createRtShaderBindingTable()
{
  uint32_t missCount{3};
  uint32_t hitCount{4};
  auto     handleCount = 1 + missCount + hitCount;
  uint32_t handleSize  = m_rtProperties.shaderGroupHandleSize;
  uint32_t handleSizeAligned = nvh::align_up(handleSize, m_rtProperties.shaderGroupHandleAlignment);
  m_rgenRegion.stride = nvh::align_up(handleSizeAligned, m_rtProperties.shaderGroupBaseAlignment);
  m_rgenRegion.size   = m_rgenRegion.stride;  
  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);
  uint32_t             dataSize = handleCount * handleSize;
  std::vector<uint8_t> handles(dataSize);
  auto result = vkGetRayTracingShaderGroupHandlesKHR(m_device, m_rtPipeline, 0, handleCount, dataSize, handles.data());
  assert(result == VK_SUCCESS);
  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"));  
  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;
  auto getHandle = [&](int i) { return handles.data() + i * handleSize; };
  auto*    pSBTBuffer = reinterpret_cast<uint8_t*>(m_alloc.map(m_rtSBTBuffer));
  uint8_t* pData{nullptr};
  uint32_t handleIdx{0};
  pData = pSBTBuffer;
  memcpy(pData, getHandle(handleIdx++), handleSize);
  pData = pSBTBuffer + m_rgenRegion.size;
  for(uint32_t c = 0; c < missCount; c++)
  {
    memcpy(pData, getHandle(handleIdx++), handleSize);
    pData += m_missRegion.stride;
  }
  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;
  }
  m_alloc.unmap(m_rtSBTBuffer);
  m_alloc.finalizeAndReleaseStaging();
}
void HelloVulkan :: createRtShaderBindingTable ( ) { uint32_t missCount { 3 } ; uint32_t hitCount { 4 } ; auto handleCount = 1 + missCount + hitCount ; uint32_t handleSize = m_rtProperties . shaderGroupHandleSize ; uint32_t handleSizeAligned = nvh :: align_up ( handleSize , m_rtProperties . shaderGroupHandleAlignment ) ; m_rgenRegion . stride = nvh :: align_up ( handleSizeAligned , m_rtProperties . shaderGroupBaseAlignment ) ; m_rgenRegion . size = m_rgenRegion . stride ; 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 ) ; uint32_t dataSize = handleCount * handleSize ; std :: vector < uint8_t > handles ( dataSize ) ; auto result = vkGetRayTracingShaderGroupHandlesKHR ( m_device , m_rtPipeline , 0 , handleCount , dataSize , handles . data ( ) ) ; assert ( result == VK_SUCCESS ) ; 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 ( " " ) ) ; 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 ; auto getHandle = [ & ] ( int i ) { return handles . data ( ) + i * handleSize ; } ; auto * pSBTBuffer = reinterpret_cast < uint8_t * > ( m_alloc . map ( m_rtSBTBuffer ) ) ; uint8_t * pData { nullptr } ; uint32_t handleIdx { 0 } ; pData = pSBTBuffer ; memcpy ( pData , getHandle ( handleIdx ++ ) , handleSize ) ; pData = pSBTBuffer + m_rgenRegion . size ; for ( uint32_t c = 0 ; c < missCount ; c ++ ) { memcpy ( pData , getHandle ( handleIdx ++ ) , handleSize ) ; pData += m_missRegion . stride ; } 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 ; } m_alloc . unmap ( m_rtSBTBuffer ) ; m_alloc . finalizeAndReleaseStaging ( ) ; }
The Shader Binding Table (SBT)
 getting all shader handles and write them in a SBT buffer
 Besides exception, this could be always done like this
The Shader Binding Table ( SBT ) getting all shader handles and write them in a SBT buffer Besides exception this could be always done like this
// The SBT (buffer) need to have starting groups to be aligned and handles in the group to be aligned. // The size member of pRayGenShaderBindingTable must be equal to its stride member // Get the shader group handles // Allocate a buffer for storing the SBT. // Give it a debug name for NSight. // Find the SBT addresses of each group // Helper to retrieve the handle data // Map the SBT buffer and write in the handles. // Raygen // Miss // Hit