Game/src/main.cpp
// Create the lights structured buffers.

Create the lights structured buffers.
Create the lights structured buffers .
void CreateLightBuffers()
{
    auto commandQueue = g_RenderDevice->GetCopyQueue();
    auto commandBuffer = commandQueue->GetCopyCommandBuffer();
    CreatePointLightsBuffer( commandBuffer );
    CreateSpotLightsBuffer( commandBuffer );
    CreateDirLightsBuffer( commandBuffer );
    if ( !g_LightsAABB )
    {
        g_LightsAABB = g_RenderDevice->CreateStructuredBuffer( commandBuffer, 512, sizeof( AABB ) );
        g_LightsAABB->SetName( L"Lights AABB" );
    }
    g_PointLightMortonCodes = g_RenderDevice->CreateStructuredBuffer( commandBuffer, g_Config.NumPointLights, sizeof( uint32_t ) );
    g_PointLightMortonCodes->SetName( L"Point Light Morton Codes" );
    g_PointLightIndices = g_RenderDevice->CreateStructuredBuffer( commandBuffer, g_Config.NumPointLights, sizeof( uint32_t ) );
    g_PointLightIndices->SetName( L"Point Light Indices" );
    g_PointLightMortonCodes_OUT = g_RenderDevice->CreateStructuredBuffer( commandBuffer, g_Config.NumPointLights, sizeof( uint32_t ) );
    g_PointLightMortonCodes_OUT->SetName( L"Point Light Morton Codes (OUT)" );
    g_PointLightIndices_OUT = g_RenderDevice->CreateStructuredBuffer( commandBuffer, g_Config.NumPointLights, sizeof( uint32_t ) );
    g_PointLightIndices_OUT->SetName( L"Point Light Indices (OUT)" );
    uint32_t numNodes = GetNumNodes( g_Config.NumPointLights );
    g_PointLightBVH = g_RenderDevice->CreateStructuredBuffer( commandBuffer, numNodes, sizeof( AABB ) );
    g_PointLightBVH->SetName( L"Point Light BVH" );
    numNodes = GetNumNodes( g_Config.NumSpotLights );
    g_SpotLightBVH = g_RenderDevice->CreateStructuredBuffer( commandBuffer, numNodes, sizeof( AABB ) );
    g_SpotLightBVH->SetName( L"Spot Light BVH" );
    g_SpotLightMortonCodes = g_RenderDevice->CreateStructuredBuffer( commandBuffer, g_Config.NumSpotLights, sizeof( uint32_t ) );
    g_SpotLightMortonCodes->SetName( L"Spot Light Morton Codes" );
    g_SpotLightIndices = g_RenderDevice->CreateStructuredBuffer( commandBuffer, g_Config.NumSpotLights, sizeof( uint32_t ) );
    g_SpotLightIndices->SetName( L"Spot Light Indices" );
    g_SpotLightMortonCodes_OUT = g_RenderDevice->CreateStructuredBuffer( commandBuffer, g_Config.NumSpotLights, sizeof( uint32_t ) );
    g_SpotLightMortonCodes_OUT->SetName( L"Spot Light Morton Codes (OUT)" );
    g_SpotLightIndices_OUT = g_RenderDevice->CreateStructuredBuffer( commandBuffer, g_Config.NumSpotLights, sizeof( uint32_t ) );
    g_SpotLightIndices_OUT->SetName( L"Spot Light Indices (OUT)" );
    uint32_t maxElements = glm::max( g_Config.NumPointLights, g_Config.NumSpotLights );
    uint32_t chunkSize = SORT_NUM_THREADS_PER_THREAD_GROUP;
    uint32_t numChunks = static_cast<uint32_t>( glm::ceil( maxElements / (float)chunkSize ) );
    uint32_t maxSortGroups = numChunks / 2;
    uint32_t numMergePathPartitionsPerSortGroup = static_cast<uint32_t>( glm::ceil( ( chunkSize * 2 ) / (float)( SORT_ELEMENTS_PER_THREAD * SORT_NUM_THREADS_PER_THREAD_GROUP ) ) ) + 1u;
    uint32_t maxMergePathPartitions = numMergePathPartitionsPerSortGroup * maxSortGroups;
    g_MergePathPartitions = g_RenderDevice->CreateStructuredBuffer( commandBuffer, maxMergePathPartitions, sizeof( uint32_t ) );
    g_MergePathPartitions->SetName( L"Merge Path Partitions" );
    auto fence = commandQueue->Submit( commandBuffer );
    fence->WaitFor();
}
void CreateLightBuffers ( ) { auto commandQueue = g_RenderDevice -> GetCopyQueue ( ) ; auto commandBuffer = commandQueue -> GetCopyCommandBuffer ( ) ; CreatePointLightsBuffer ( commandBuffer ) ; CreateSpotLightsBuffer ( commandBuffer ) ; CreateDirLightsBuffer ( commandBuffer ) ; if ( ! g_LightsAABB ) { g_LightsAABB = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , 512 , sizeof ( AABB ) ) ; g_LightsAABB -> SetName ( L" " ) ; } g_PointLightMortonCodes = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , g_Config . NumPointLights , sizeof ( uint32_t ) ) ; g_PointLightMortonCodes -> SetName ( L" " ) ; g_PointLightIndices = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , g_Config . NumPointLights , sizeof ( uint32_t ) ) ; g_PointLightIndices -> SetName ( L" " ) ; g_PointLightMortonCodes_OUT = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , g_Config . NumPointLights , sizeof ( uint32_t ) ) ; g_PointLightMortonCodes_OUT -> SetName ( L" " ) ; g_PointLightIndices_OUT = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , g_Config . NumPointLights , sizeof ( uint32_t ) ) ; g_PointLightIndices_OUT -> SetName ( L" " ) ; uint32_t numNodes = GetNumNodes ( g_Config . NumPointLights ) ; g_PointLightBVH = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , numNodes , sizeof ( AABB ) ) ; g_PointLightBVH -> SetName ( L" " ) ; numNodes = GetNumNodes ( g_Config . NumSpotLights ) ; g_SpotLightBVH = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , numNodes , sizeof ( AABB ) ) ; g_SpotLightBVH -> SetName ( L" " ) ; g_SpotLightMortonCodes = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , g_Config . NumSpotLights , sizeof ( uint32_t ) ) ; g_SpotLightMortonCodes -> SetName ( L" " ) ; g_SpotLightIndices = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , g_Config . NumSpotLights , sizeof ( uint32_t ) ) ; g_SpotLightIndices -> SetName ( L" " ) ; g_SpotLightMortonCodes_OUT = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , g_Config . NumSpotLights , sizeof ( uint32_t ) ) ; g_SpotLightMortonCodes_OUT -> SetName ( L" " ) ; g_SpotLightIndices_OUT = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , g_Config . NumSpotLights , sizeof ( uint32_t ) ) ; g_SpotLightIndices_OUT -> SetName ( L" " ) ; uint32_t maxElements = glm :: max ( g_Config . NumPointLights , g_Config . NumSpotLights ) ; uint32_t chunkSize = SORT_NUM_THREADS_PER_THREAD_GROUP ; uint32_t numChunks = static_cast < uint32_t > ( glm :: ceil ( maxElements / ( float ) chunkSize ) ) ; uint32_t maxSortGroups = numChunks / 2 ; uint32_t numMergePathPartitionsPerSortGroup = static_cast < uint32_t > ( glm :: ceil ( ( chunkSize * 2 ) / ( float ) ( SORT_ELEMENTS_PER_THREAD * SORT_NUM_THREADS_PER_THREAD_GROUP ) ) ) + 1u ; uint32_t maxMergePathPartitions = numMergePathPartitionsPerSortGroup * maxSortGroups ; g_MergePathPartitions = g_RenderDevice -> CreateStructuredBuffer ( commandBuffer , maxMergePathPartitions , sizeof ( uint32_t ) ) ; g_MergePathPartitions -> SetName ( L" " ) ; auto fence = commandQueue -> Submit ( commandBuffer ) ; fence -> WaitFor ( ) ; }
Create the lights structured buffers.
Create the lights structured buffers .
// Create structured buffers to store the lights.
 // Create a structured buffer to store the AABB for the lights in the scene.
 // To compute the AABB for all of the lights in the scene, a parallel reduction algorithm is used.
 // The reduction compute shader will be dispatched with 512 thread groups each group with 512 threads.
 // The first pass of the reduction will compute 512 AABBs and the second pass will dispatch a single 
 // thread group that will reduce the 512 AABBs into a single AABB at index 0 of the LightsAABB structured buffer.
 // Create a buffer to store the Morton codes for point lights.
 // Create a buffer to store the sorted indices for the point lights.
 // For sorting, we need to double buffer the output.
 // BVH for point lights.
 // BVH for spot lights.
 // Create a buffer to store the Morton codes for spot lights.
 // Create a buffer to store the sorted indices for the spot lights.
 // For sorting, we need to double buffer the output.
 // The maximum number of elements that need to be sorted.
 // Radix sort will sort Morton codes (keys) into chunks of SORT_NUM_THREADS_PER_THREAD_GROUP size.
 // The number of chunks that need to be merge sorted after Radix sort finishes.
 // The number of sort groups that are needed to sort the first set of chunks.
 // Each sort group will sort 2 chunks. So the maximum number of sort groups is 1/2 of the 
 // number of chunks.
 // The number of merge path partitions per sort group is the total values
 // to be sorted per sort group (2 chunks) divided by the number of elements 
 // that can be sorted per thread group. One is added to account for the 
 // merge path partition at the END of the chunk.
 // The maximum number of merge path partitions is the number of merge path partitions
 // needed by a single sort group multiplied by the maximum number of sort groups.
