Hey,
I have a problem with initializing BLAS with DX12. What is failing is function - BuildRaytracingAccelrationStructure.
Here is an error:
D3D12 ERROR: ID3D12CommandList::BuildRaytracingAccelerationStructure: D3D12_RAYTRACING_GEOMETRY_DESC[0].Triangles.IndexBuffer + SizeInBytes - 1 (0x000000000714b08f) exceeds end of the virtual address range of Resource (0x0000026741E0AB50:'Unnamed ID3D12Resource Object', GPU VA Range: 0x000000000714b000 - 0x000000000714b01f). [ RESOURCE_MANIPULATION ERROR #1158: BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INVALID]
D3D12: **BREAK** enabled for the previous message, which was: [ ERROR RESOURCE_MANIPULATION #1158: BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INVALID ]
Here is full function. Exception is thrown at the very end of it:
void Renderer::CreateBLAS(std::shared_ptr<ModelClass> model)
{
// Describe the geometry that goes in the bottom acceleration structure(s)
D3D12_RAYTRACING_GEOMETRY_DESC geometryDesc{};
geometryDesc.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
geometryDesc.Triangles.VertexBuffer.StartAddress = model->GetVertexBuffer()->GetGPUVirtualAddress();
geometryDesc.Triangles.VertexBuffer.StrideInBytes = model->GetVertexBufferView().StrideInBytes;
geometryDesc.Triangles.VertexCount = static_cast<UINT>(model->GetMesh(0).vertices.size());
geometryDesc.Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
geometryDesc.Triangles.IndexBuffer = model->GetIndexBuffer()->GetGPUVirtualAddress();
geometryDesc.Triangles.IndexFormat = model->GetIndexBufferView().Format;
geometryDesc.Triangles.IndexCount = static_cast<UINT>(model->GetIndicesCount());
geometryDesc.Triangles.Transform3x4 = 0;
geometryDesc.Flags = D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE;
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS buildFlags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
// Get the size requirements for the BLAS buffers
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS ASInputs = {};
ASInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;
ASInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
ASInputs.pGeometryDescs = &geometryDesc;
ASInputs.NumDescs = 1;
ASInputs.Flags = buildFlags;
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO ASPreBuildInfo = {};
m_device->GetRaytracingAccelerationStructurePrebuildInfo(&ASInputs, &ASPreBuildInfo);
ASPreBuildInfo.ScratchDataSizeInBytes = ALIGN(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, ASPreBuildInfo.ScratchDataSizeInBytes);
ASPreBuildInfo.ResultDataMaxSizeInBytes = ALIGN(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, ASPreBuildInfo.ResultDataMaxSizeInBytes);
// Create the BLAS scratch buffer
auto bufferInfo = CD3DX12_RESOURCE_DESC::Buffer(ASPreBuildInfo.ScratchDataSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
bufferInfo.Alignment = std::max(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT);
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&bufferInfo,
D3D12_RESOURCE_STATE_COMMON,
nullptr,
IID_PPV_ARGS(&m_blasScratch)
));
// Create the BLAS buffer
bufferInfo = CD3DX12_RESOURCE_DESC::Buffer(ASPreBuildInfo.ResultDataMaxSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE);
bufferInfo.Alignment = std::max(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BYTE_ALIGNMENT, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT);
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&bufferInfo,
D3D12_RESOURCE_STATE_COMMON,
nullptr,
IID_PPV_ARGS(&m_blasResult)
));
// Describe and build the bottom level acceleration structure
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC buildDesc = {};
buildDesc.Inputs = ASInputs;
buildDesc.ScratchAccelerationStructureData = m_blasScratch->GetGPUVirtualAddress();
buildDesc.DestAccelerationStructureData = m_blasResult->GetGPUVirtualAddress();
m_commandList->BuildRaytracingAccelerationStructure(&buildDesc, 0, nullptr);
// Wait for the BLAS build to complete
D3D12_RESOURCE_BARRIER uavBarrier;
uavBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
uavBarrier.UAV.pResource = m_blasResult.Get();
uavBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
m_commandList->ResourceBarrier(1, &uavBarrier);
}
And here is ModelClass class, which I'm passing to function creating BLAS. PrepareBuffers is used to provide vertex/index buffers and buffer views stored in ModelClass:
bool ModelClass::PrepareBuffers(ComPtr<ID3D12Device2> device)
{
Mesh mesh = GetMesh(0);
const UINT vertexBufferSize = static_cast<UINT>(sizeof(ModelClass::VertexBufferStruct)) * static_cast<UINT>(mesh.vertices.size());
ThrowIfFailed(device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_vertexBuffer)));
// Copy the triangle data to the vertex buffer.
UINT8* pVertexDataBegin;
CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.
ThrowIfFailed(m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
memcpy(pVertexDataBegin, &mesh.vertices[0], vertexBufferSize);
m_vertexBuffer->Unmap(0, nullptr);
// Initialize the vertex buffer view.
m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
m_vertexBufferView.StrideInBytes = sizeof(ModelClass::VertexBufferStruct);
m_vertexBufferView.SizeInBytes = vertexBufferSize;
// Create index buffer
const UINT indexBufferSize = sizeof(mesh.indices);
m_indicesCount = static_cast<UINT>(mesh.indices.size());
ThrowIfFailed(device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_indexBuffer)));
// Copy the triangle data to the vertex buffer.
UINT8* pIndexDataBegin;
ThrowIfFailed(m_indexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pIndexDataBegin)));
memcpy(pIndexDataBegin, &mesh.indices[0], sizeof(mesh.indices));
m_indexBuffer->Unmap(0, nullptr);
// Initialize the vertex buffer view.
m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress();
m_indexBufferView.Format = DXGI_FORMAT_R32_UINT;
m_indexBufferView.SizeInBytes = indexBufferSize;
return true;
}
Thank you in advance. I am using code from this repository - https://github.com/microsoft/DirectX-Graphics-Samples/blob/master/Samples/Desktop/D3D12Raytracing/src/D3D12RaytracingHelloWorld/D3D12RaytracingHelloWorld.cpp which is part of RayTracing Gems books - http://www.realtimerendering.com/raytracinggems/unofficial_RayTracingGems_v1.7.pdf