@@ -118,10 +118,11 @@ Dx12AccelerationStructureBuilder::Dx12AccelerationStructureBuilder(graphics::dx1
118118
119119// TODO: Consider batching multiple accel struct builds where possible.
120120void Dx12AccelerationStructureBuilder::Build (
121- const graphics::Dx12GpuVaMap& gpu_va_map,
122- const format::InitDx12AccelerationStructureCommandHeader& command_header,
123- const std::vector<format::InitDx12AccelerationStructureGeometryDesc>& init_geometry_descs,
124- const uint8_t * build_inputs_data)
121+ const graphics::Dx12GpuVaMap& gpu_va_map,
122+ const format::InitDx12AccelerationStructureCommandHeader& command_header,
123+ const std::vector<format::InitDx12AccelerationStructureGeometryDesc>& init_geometry_descs,
124+ StructPointerDecoder<Decoded_D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS>* build_inputs,
125+ const uint8_t * build_inputs_data)
125126{
126127 D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC build_desc;
127128
@@ -142,8 +143,16 @@ void Dx12AccelerationStructureBuilder::Build(
142143
143144 if (build)
144145 {
145- SetupBuild (
146- gpu_va_map, command_header, init_geometry_descs, build_inputs_data, build_desc, use_temp_dest_buffer);
146+ if ((build_inputs != nullptr ) && (build_inputs->GetPointer () != nullptr ))
147+ {
148+ SetupBuild2 (gpu_va_map, command_header, build_inputs, build_inputs_data, build_desc, use_temp_dest_buffer);
149+ }
150+ else
151+ {
152+ SetupBuild (
153+ gpu_va_map, command_header, init_geometry_descs, build_inputs_data, build_desc, use_temp_dest_buffer);
154+ }
155+
147156 ExecuteBuild (gpu_va_map, build_desc);
148157 }
149158
@@ -315,6 +324,189 @@ void Dx12AccelerationStructureBuilder::SetupBuild(
315324 }
316325}
317326
327+ void Dx12AccelerationStructureBuilder::SetupBuild2 (
328+ const graphics::Dx12GpuVaMap& gpu_va_map,
329+ const format::InitDx12AccelerationStructureCommandHeader& command_header,
330+ StructPointerDecoder<Decoded_D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS>* build_inputs,
331+ const uint8_t * build_inputs_data,
332+ D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC& build_desc,
333+ bool use_temp_dest_buffer)
334+ {
335+ if ((build_inputs == nullptr ) || (build_inputs->GetPointer () == nullptr ) || (build_inputs_data == nullptr ))
336+ {
337+ GFXRECON_LOG_ERROR (" Invalid build inputs for acceleration structure build. Build may fail." );
338+ return ;
339+ }
340+
341+ // Build D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC from decoded data.
342+ build_desc.DestAccelerationStructureData = gpu_va_map.Map (command_header.dest_acceleration_structure_data );
343+ auto & inputs_desc = build_desc.Inputs ;
344+ build_desc.SourceAccelerationStructureData = 0 ;
345+ build_desc.ScratchAccelerationStructureData = 0 ;
346+
347+ inputs_desc = *(build_inputs->GetPointer ());
348+ inputs_desc.Type = static_cast <D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE>(command_header.inputs_type );
349+ inputs_desc.Flags = static_cast <D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS>(command_header.inputs_flags );
350+
351+ const uint8_t * final_data = build_inputs_data;
352+
353+ // In order for GetAccelerationStructureInputsBufferEntries2 to correctly process inputs buffer entries, a
354+ // non-zero GPU VA must be set for values that will be used.
355+ const D3D12_GPU_VIRTUAL_ADDRESS kDefaultGpuVa = 1 ;
356+
357+ // Reconstruct acceleration structure build descs.
358+ if (inputs_desc.Type == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL)
359+ {
360+ for (UINT i = 0 ; i < inputs_desc.NumDescs ; ++i)
361+ {
362+ D3D12_RAYTRACING_GEOMETRY_DESC* geom_desc = nullptr ;
363+ if (inputs_desc.DescsLayout == D3D12_ELEMENTS_LAYOUT_ARRAY)
364+ {
365+ GFXRECON_ASSERT (inputs_desc.pGeometryDescs != nullptr );
366+ geom_desc = const_cast <D3D12_RAYTRACING_GEOMETRY_DESC*>(&inputs_desc.pGeometryDescs [i]);
367+ }
368+ else if (inputs_desc.DescsLayout == D3D12_ELEMENTS_LAYOUT_ARRAY_OF_POINTERS)
369+ {
370+ GFXRECON_ASSERT (inputs_desc.ppGeometryDescs != nullptr );
371+ geom_desc = const_cast <D3D12_RAYTRACING_GEOMETRY_DESC*>(inputs_desc.ppGeometryDescs [i]);
372+ }
373+ else
374+ {
375+ GFXRECON_LOG_ERROR (
376+ " Unrecognized raytracing acceleration structure geometry desc layout (DescsLayout=%d)." ,
377+ inputs_desc.DescsLayout );
378+ continue ;
379+ }
380+
381+ GFXRECON_ASSERT (geom_desc);
382+ if (geom_desc->Type == D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES)
383+ {
384+ auto & tris_desc = geom_desc->Triangles ;
385+ tris_desc.Transform3x4 = (tris_desc.Transform3x4 > 0 ) ? kDefaultGpuVa : 0 ;
386+ tris_desc.IndexBuffer = (tris_desc.IndexBuffer > 0 ) ? kDefaultGpuVa : 0 ;
387+ tris_desc.VertexBuffer .StartAddress = kDefaultGpuVa ;
388+ }
389+ else if (geom_desc->Type == D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS)
390+ {
391+ geom_desc->AABBs .AABBs .StartAddress = kDefaultGpuVa ;
392+ }
393+ else if (geom_desc->Type == D3D12_RAYTRACING_GEOMETRY_TYPE_OMM_TRIANGLES)
394+ {
395+ if (geom_desc->OmmTriangles .pTriangles != nullptr )
396+ {
397+ auto triangles_desc =
398+ const_cast <D3D12_RAYTRACING_GEOMETRY_TRIANGLES_DESC*>(geom_desc->OmmTriangles .pTriangles );
399+
400+ triangles_desc->Transform3x4 = (triangles_desc->Transform3x4 > 0 ) ? kDefaultGpuVa : 0 ;
401+ triangles_desc->IndexBuffer = (triangles_desc->IndexBuffer > 0 ) ? kDefaultGpuVa : 0 ;
402+ triangles_desc->VertexBuffer .StartAddress = kDefaultGpuVa ;
403+ }
404+
405+ if (geom_desc->OmmTriangles .pOmmLinkage != nullptr )
406+ {
407+ auto linkage_desc =
408+ const_cast <D3D12_RAYTRACING_GEOMETRY_OMM_LINKAGE_DESC*>(geom_desc->OmmTriangles .pOmmLinkage );
409+ linkage_desc->OpacityMicromapIndexBuffer .StartAddress =
410+ (linkage_desc->OpacityMicromapIndexBuffer .StartAddress > 0 ) ? kDefaultGpuVa : 0 ;
411+ linkage_desc->OpacityMicromapArray = gpu_va_map.Map (linkage_desc->OpacityMicromapArray );
412+ }
413+ }
414+ else
415+ {
416+ GFXRECON_ASSERT (false && " Invalid D3D12_RAYTRACING_GEOMETRY_TYPE." );
417+ }
418+ }
419+ }
420+ else if (inputs_desc.Type == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_OPACITY_MICROMAP_ARRAY)
421+ {
422+ for (UINT i = 0 ; i < inputs_desc.NumDescs ; ++i)
423+ {
424+ auto & omm_desc =
425+ const_cast <D3D12_RAYTRACING_OPACITY_MICROMAP_ARRAY_DESC&>(inputs_desc.pOpacityMicromapArrayDesc [i]);
426+ omm_desc.InputBuffer = (omm_desc.InputBuffer > 0 ) ? kDefaultGpuVa : 0 ;
427+ omm_desc.PerOmmDescs .StartAddress = (omm_desc.PerOmmDescs .StartAddress > 0 ) ? kDefaultGpuVa : 0 ;
428+ }
429+ }
430+ else if (inputs_desc.Type == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL)
431+ {
432+ inputs_desc.InstanceDescs = (inputs_desc.NumDescs > 0 ) ? kDefaultGpuVa : 0 ;
433+
434+ // Map GPU VAs in instance desc input data.
435+ temp_instance_desc_input_data_.clear ();
436+ temp_instance_desc_input_data_.insert (temp_instance_desc_input_data_.end (),
437+ build_inputs_data,
438+ build_inputs_data + command_header.inputs_data_size );
439+ constexpr auto address_stride = sizeof (D3D12_RAYTRACING_INSTANCE_DESC);
440+ constexpr auto address_offset = offsetof (D3D12_RAYTRACING_INSTANCE_DESC, AccelerationStructure);
441+ for (UINT i = 0 ; i < inputs_desc.NumDescs ; ++i)
442+ {
443+ D3D12_GPU_VIRTUAL_ADDRESS* address = reinterpret_cast <D3D12_GPU_VIRTUAL_ADDRESS*>(
444+ temp_instance_desc_input_data_.data () + i * address_stride + address_offset);
445+ *address = gpu_va_map.Map (*address);
446+ }
447+ final_data = temp_instance_desc_input_data_.data ();
448+ }
449+ else
450+ {
451+ GFXRECON_ASSERT (false && " Invalid D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE." );
452+ }
453+
454+ // Compute the required inputs buffer size and entry information.
455+ uint64_t inputs_buffer_size = 0 ;
456+ std::vector<graphics::dx12::InputsBufferEntry> inputs_buffer_entries;
457+ graphics::dx12::GetAccelerationStructureInputsBufferEntries2 (
458+ inputs_desc, inputs_buffer_size, inputs_buffer_entries);
459+
460+ GFXRECON_ASSERT (inputs_buffer_size == command_header.inputs_data_size );
461+
462+ // Get required sizes and update buffers.
463+ D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO prebuild_info;
464+ device5_->GetRaytracingAccelerationStructurePrebuildInfo (&inputs_desc, &prebuild_info);
465+ UpdateBufferSize (device5_,
466+ scratch_buffer_,
467+ scratch_buffer_size_,
468+ prebuild_info.ScratchDataSizeInBytes ,
469+ D3D12_HEAP_TYPE_DEFAULT,
470+ D3D12_RESOURCE_STATE_COMMON,
471+ D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
472+ UpdateBufferSize (device5_,
473+ inputs_buffer_,
474+ inputs_buffer_size_,
475+ command_header.inputs_data_size ,
476+ D3D12_HEAP_TYPE_UPLOAD,
477+ D3D12_RESOURCE_STATE_GENERIC_READ,
478+ D3D12_RESOURCE_FLAG_NONE);
479+
480+ if (use_temp_dest_buffer)
481+ {
482+ UpdateBufferSize (device5_,
483+ temp_dest_buffer_,
484+ temp_dest_buffer_size_,
485+ prebuild_info.ResultDataMaxSizeInBytes ,
486+ D3D12_HEAP_TYPE_DEFAULT,
487+ D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE,
488+ D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
489+ }
490+
491+ // Write inputs data to resources.
492+ GFXRECON_CHECK_CONVERSION_DATA_LOSS (size_t , command_header.inputs_data_size );
493+ HRESULT hr =
494+ MapSubresourceAndWriteData (inputs_buffer_, 0 , static_cast <size_t >(command_header.inputs_data_size ), final_data);
495+ GFXRECON_ASSERT (SUCCEEDED (hr));
496+
497+ // Fix GPU VAs that point into buffers.
498+ if (use_temp_dest_buffer)
499+ {
500+ build_desc.DestAccelerationStructureData = temp_dest_buffer_->GetGPUVirtualAddress ();
501+ }
502+ build_desc.ScratchAccelerationStructureData = scratch_buffer_->GetGPUVirtualAddress ();
503+ D3D12_GPU_VIRTUAL_ADDRESS inputs_buffer_base = inputs_buffer_->GetGPUVirtualAddress ();
504+ for (auto & inputs_buffer_entry : inputs_buffer_entries)
505+ {
506+ *inputs_buffer_entry.desc_gpu_va = inputs_buffer_base + inputs_buffer_entry.offset ;
507+ }
508+ }
509+
318510void Dx12AccelerationStructureBuilder::ExecuteBuild (const graphics::Dx12GpuVaMap& gpu_va_map,
319511 D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC& build_desc)
320512{
0 commit comments