Skip to content

Commit 68d2aca

Browse files
committed
Support dx12 raytracing opacity micromap trimming
DX12 AS trim metadata payloads now include serialized D3D12 build-input structs to preserve OMM and OMM-array behavior: - Add a new meta id kInitDx12AccelerationStructureCommand2. - Encode and write full AS build inputs from state tracking and writer paths. - Decode and route structured build inputs through DX12 consumers. - Update DX12 utility and builder logic for OMM triangles and OMM-array input buffer entry handling.
1 parent 54d7a6b commit 68d2aca

30 files changed

Lines changed: 723 additions & 203 deletions

framework/decode/api_decoder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ class ApiDecoder
192192
virtual void DispatchInitDx12AccelerationStructureCommand(
193193
const format::InitDx12AccelerationStructureCommandHeader& command_header,
194194
const std::vector<format::InitDx12AccelerationStructureGeometryDesc>& geometry_descs,
195+
const std::vector<uint8_t>& build_inputs,
195196
const uint8_t* build_inputs_data) = 0;
196197

197198
virtual void DispatchGetDxgiAdapterInfo(const format::DxgiAdapterInfoCommandHeader& adapter_info_header){};

framework/decode/api_payload.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,14 @@ struct InitDx12AccelerationStructureArgs
416416

417417
format::InitDx12AccelerationStructureCommandHeader command_header;
418418
std::vector<format::InitDx12AccelerationStructureGeometryDesc> geometry_descs;
419+
std::vector<uint8_t> inputs;
419420
const uint8_t* data;
420421

421-
auto GetTuple() const { return std::tie(command_header, geometry_descs, data); }
422+
auto GetTuple() const { return std::tie(command_header, geometry_descs, inputs, data); }
422423
};
424+
template <>
425+
struct DispatchHasAllocGuard<InitDx12AccelerationStructureArgs> : std::true_type
426+
{};
423427
struct GetDxgiAdapterArgs
424428
{
425429
format::MetaDataId meta_data_id; // Needed by DispatchVisitor, but not ApiDecoder

framework/decode/block_parser.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,7 @@ ParsedBlock& BlockParser::ParseMetaData(BlockBuffer& block_buffer)
12921292

12931293
// Parse geometry descs.
12941294
std::vector<format::InitDx12AccelerationStructureGeometryDesc> geom_descs;
1295+
std::vector<uint8_t> build_inputs_data;
12951296
if (success)
12961297
{
12971298
for (uint32_t i = 0; i < header.inputs_num_geometry_descs; ++i)
@@ -1323,6 +1324,7 @@ ParsedBlock& BlockParser::ParseMetaData(BlockBuffer& block_buffer)
13231324
read_result.uncompressed_size,
13241325
header,
13251326
geom_descs,
1327+
build_inputs_data,
13261328
reinterpret_cast<const uint8_t*>(read_result.buffer.data()));
13271329
return MakeCompressibleParsedBlock(block_buffer, read_result, payload);
13281330
}
@@ -1333,6 +1335,53 @@ ParsedBlock& BlockParser::ParseMetaData(BlockBuffer& block_buffer)
13331335
"Failed to read init DX12 acceleration structure meta-data block header");
13341336
}
13351337
}
1338+
else if (meta_data_type == format::MetaDataType::kInitDx12AccelerationStructureCommand2)
1339+
{
1340+
// Parse command header.
1341+
format::InitDx12AccelerationStructureCommandHeader header;
1342+
success = block_buffer.Read(header.thread_id);
1343+
success = success && block_buffer.Read(header.dest_acceleration_structure_data);
1344+
success = success && block_buffer.Read(header.copy_source_gpu_va);
1345+
success = success && block_buffer.Read(header.copy_mode);
1346+
success = success && block_buffer.Read(header.inputs_type);
1347+
success = success && block_buffer.Read(header.inputs_flags);
1348+
success = success && block_buffer.Read(header.inputs_num_instance_descs);
1349+
success = success && block_buffer.Read(header.inputs_num_geometry_descs);
1350+
success = success && block_buffer.Read(header.inputs_data_size);
1351+
1352+
// Parse build inputs.
1353+
std::vector<format::InitDx12AccelerationStructureGeometryDesc> geom_descs;
1354+
std::vector<uint8_t> build_inputs_data;
1355+
size_t inputs_size = static_cast<size_t>(header.inputs_num_geometry_descs);
1356+
if (success && (inputs_size > 0))
1357+
{
1358+
build_inputs_data.resize(inputs_size);
1359+
success = success && block_buffer.ReadBytes(build_inputs_data.data(), inputs_size);
1360+
}
1361+
1362+
BlockBuffer::BlockSpan parameter_data;
1363+
if (success)
1364+
{
1365+
const char* label = "init DX12 acceleration structure meta-data V2 block";
1366+
ParameterReadResult read_result = ReadParameterBuffer(label, block_buffer, header.inputs_data_size);
1367+
if (read_result.success)
1368+
{
1369+
auto* payload = Emplace<InitDx12AccelerationStructureArgs>(
1370+
meta_data_id,
1371+
read_result.uncompressed_size,
1372+
header,
1373+
geom_descs,
1374+
build_inputs_data,
1375+
reinterpret_cast<const uint8_t*>(read_result.buffer.data()));
1376+
return MakeCompressibleParsedBlock(block_buffer, read_result, payload);
1377+
}
1378+
}
1379+
else
1380+
{
1381+
HandleBlockReadError(kErrorReadingBlockHeader,
1382+
"Failed to read init DX12 acceleration structure meta-data V2 block header");
1383+
}
1384+
}
13361385
else if (meta_data_type == format::MetaDataType::kDxgiAdapterInfoCommand)
13371386
{
13381387
format::DxgiAdapterInfoCommandHeader adapter_info_header;

framework/decode/custom_ags_decoder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ class AgsDecoder : public ApiDecoder
184184
virtual void DispatchInitDx12AccelerationStructureCommand(
185185
const format::InitDx12AccelerationStructureCommandHeader& command_header,
186186
const std::vector<format::InitDx12AccelerationStructureGeometryDesc>& geometry_descs,
187+
const std::vector<uint8_t>& build_inputs,
187188
const uint8_t* build_inputs_data) override
188189
{}
189190

framework/decode/dx12_acceleration_structure_builder.cpp

Lines changed: 198 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,11 @@ Dx12AccelerationStructureBuilder::Dx12AccelerationStructureBuilder(graphics::dx1
118118

119119
// TODO: Consider batching multiple accel struct builds where possible.
120120
void 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+
318510
void Dx12AccelerationStructureBuilder::ExecuteBuild(const graphics::Dx12GpuVaMap& gpu_va_map,
319511
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC& build_desc)
320512
{

framework/decode/dx12_acceleration_structure_builder.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#ifndef GFXRECON_DECODE_DX12_ACCELERATION_STRUCTURE_BUILDER_H
2424
#define GFXRECON_DECODE_DX12_ACCELERATION_STRUCTURE_BUILDER_H
2525

26+
#include "decode/custom_dx12_struct_decoders.h"
2627
#include "graphics/dx12_gpu_va_map.h"
2728
#include "graphics/dx12_util.h"
2829
#include "format/format.h"
@@ -41,10 +42,11 @@ class Dx12AccelerationStructureBuilder
4142

4243
virtual ~Dx12AccelerationStructureBuilder() {}
4344

44-
void Build(const graphics::Dx12GpuVaMap& gpu_va_map,
45-
const format::InitDx12AccelerationStructureCommandHeader& command_header,
46-
const std::vector<format::InitDx12AccelerationStructureGeometryDesc>& init_geometry_descs,
47-
const uint8_t* build_inputs_data);
45+
void Build(const graphics::Dx12GpuVaMap& gpu_va_map,
46+
const format::InitDx12AccelerationStructureCommandHeader& command_header,
47+
const std::vector<format::InitDx12AccelerationStructureGeometryDesc>& init_geometry_descs,
48+
StructPointerDecoder<Decoded_D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS>* build_inputs,
49+
const uint8_t* build_inputs_data);
4850

4951
private:
5052
void SetupBuild(const graphics::Dx12GpuVaMap& gpu_va_map,
@@ -54,6 +56,13 @@ class Dx12AccelerationStructureBuilder
5456
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC& build_desc,
5557
bool use_temp_dest_buffer);
5658

59+
void SetupBuild2(const graphics::Dx12GpuVaMap& gpu_va_map,
60+
const format::InitDx12AccelerationStructureCommandHeader& command_header,
61+
StructPointerDecoder<Decoded_D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS>* build_inputs,
62+
const uint8_t* build_inputs_data,
63+
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC& build_desc,
64+
bool use_temp_dest_buffer);
65+
5766
void ExecuteBuild(const graphics::Dx12GpuVaMap& gpu_va_map,
5867
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC& build_desc);
5968

0 commit comments

Comments
 (0)