public unsafe AccelerationStructureBuffers CreateTopLevelAS(ID3D12Device5 pDevice, ID3D12GraphicsCommandList4 pCmdList, AccelerationStructureBuffers[] pBottomLevelAS, ref long tlasSize) { int instances = 2; // First, get the size of the TLAS buffers and create them BuildRaytracingAccelerationStructureInputs inputs = new BuildRaytracingAccelerationStructureInputs(); inputs.Layout = ElementsLayout.Array; inputs.Flags = RaytracingAccelerationStructureBuildFlags.None; inputs.DescriptorsCount = instances; inputs.Type = RaytracingAccelerationStructureType.TopLevel; RaytracingAccelerationStructurePrebuildInfo info; info = pDevice.GetRaytracingAccelerationStructurePrebuildInfo(inputs); // Create the buffers AccelerationStructureBuffers buffers = new AccelerationStructureBuffers(); buffers.pScratch = this.CreateBuffer(pDevice, (uint)info.ScratchDataSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.UnorderedAccess, kDefaultHeapProps); buffers.pResult = this.CreateBuffer(pDevice, (uint)info.ResultDataMaxSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.RaytracingAccelerationStructure, kDefaultHeapProps); tlasSize = info.ResultDataMaxSizeInBytes; // The instance desc should be inside a buffer, create and map the buffer buffers.pInstanceDesc = this.CreateBuffer(pDevice, (uint)(Unsafe.SizeOf <FixedRaytracingInstanceDescription>() * instances), ResourceFlags.None, ResourceStates.GenericRead, kUploadHeapProps); FixedRaytracingInstanceDescription[] pInstanceDesc = new FixedRaytracingInstanceDescription[instances]; // The transformation matrices for the instances Matrix4x4[] transformation = new Matrix4x4[instances]; transformation[0] = Matrix4x4.CreateTranslation(new Vector3(0, -1.0f, 0)); transformation[1] = Matrix4x4.CreateScale(2.0f); pInstanceDesc[0].InstanceID = 0; // This value will be exposed to the shader via InstanceID() pInstanceDesc[0].InstanceContributionToHitGroupIndex = 0; // This is the offset inside the shader-table. We only have a single geometry, so the offset 0 pInstanceDesc[0].Flags = (byte)RaytracingInstanceFlags.None; pInstanceDesc[0].Transform = Matrix4x4.Transpose(transformation[0]).ToMatrix3x4(); // GLM is column major, the INSTANCE_DESC is row major pInstanceDesc[0].AccelerationStructure = pBottomLevelAS[0].pResult.GPUVirtualAddress; pInstanceDesc[0].InstanceMask = 0xff; for (int i = 1; i < instances; i++) { pInstanceDesc[i].InstanceID = i; // This value will be exposed to the shader via InstanceID() pInstanceDesc[i].InstanceContributionToHitGroupIndex = 0; // This is the offset inside the shader-table. We only have a single geometry, so the offset 0 pInstanceDesc[i].Flags = (byte)RaytracingInstanceFlags.None; pInstanceDesc[i].Transform = Matrix4x4.Transpose(transformation[i]).ToMatrix3x4(); // GLM is column major, the INSTANCE_DESC is row major pInstanceDesc[i].AccelerationStructure = pBottomLevelAS[1].pResult.GPUVirtualAddress; pInstanceDesc[i].InstanceMask = 0xff; } IntPtr data; data = buffers.pInstanceDesc.Map(0, null); Helpers.MemCpy(data, pInstanceDesc, (uint)(Unsafe.SizeOf <FixedRaytracingInstanceDescription>() * instances)); buffers.pInstanceDesc.Unmap(0, null); // Create the TLAS BuildRaytracingAccelerationStructureDescription asDesc = new BuildRaytracingAccelerationStructureDescription(); asDesc.Inputs = inputs; asDesc.Inputs.InstanceDescriptions = buffers.pInstanceDesc.GPUVirtualAddress; asDesc.DestinationAccelerationStructureData = buffers.pResult.GPUVirtualAddress; asDesc.ScratchAccelerationStructureData = buffers.pScratch.GPUVirtualAddress; pCmdList.BuildRaytracingAccelerationStructure(asDesc); // We need to insert a UAV barrier before using the acceleration structures in a raytracing operation ResourceBarrier uavBarrier = new ResourceBarrier(new ResourceUnorderedAccessViewBarrier(buffers.pResult)); pCmdList.ResourceBarrier(uavBarrier); return(buffers); }
public unsafe AccelerationStructureBuffers BuildTopLevelAS(ID3D12Device5 pDevice, ID3D12GraphicsCommandList4 pCmdList, ID3D12Resource[] pBottomLevelAS, ref long tlasSize, float rotation, bool update, ref AccelerationStructureBuffers buffers) { // First, get the size of the TLAS buffers and create them BuildRaytracingAccelerationStructureInputs inputs = new BuildRaytracingAccelerationStructureInputs(); inputs.Layout = ElementsLayout.Array; inputs.Flags = RaytracingAccelerationStructureBuildFlags.AllowUpdate; inputs.DescriptorsCount = 3; // NumDescs inputs.Type = RaytracingAccelerationStructureType.TopLevel; RaytracingAccelerationStructurePrebuildInfo info; info = pDevice.GetRaytracingAccelerationStructurePrebuildInfo(inputs); if (update) { // If this a request for an update, then the TLAS was already used in a DispatchRay() call. We need a UAV barrier to make sure the read operation ends before updating the buffer ResourceBarrier uavBarrier1 = new ResourceBarrier(new ResourceUnorderedAccessViewBarrier(buffers.pResult)); pCmdList.ResourceBarrier(uavBarrier1); } else { buffers.pScratch = this.CreateBuffer(pDevice, (uint)info.ScratchDataSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.UnorderedAccess, kDefaultHeapProps); buffers.pResult = this.CreateBuffer(pDevice, (uint)info.ResultDataMaxSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.RaytracingAccelerationStructure, kDefaultHeapProps); buffers.pInstanceDesc = this.CreateBuffer(pDevice, (uint)Unsafe.SizeOf <FixedRaytracingInstanceDescription>() * 3, ResourceFlags.None, ResourceStates.GenericRead, kUploadHeapProps); tlasSize = info.ResultDataMaxSizeInBytes; } FixedRaytracingInstanceDescription[] instanceDescs = new FixedRaytracingInstanceDescription[3]; // The transformation matrices for the instances Matrix4x4[] transformation = new Matrix4x4[3]; Matrix4x4 rotationMat = Matrix4x4.CreateRotationY(rotation); transformation[0] = Matrix4x4.Identity; transformation[1] = rotationMat * Matrix4x4.CreateTranslation(new Vector3(-2, 0, 0)); transformation[2] = rotationMat * Matrix4x4.CreateTranslation(new Vector3(2, 0, 0)); // The InstanceContributionToHitGroupIndex is set based on the shader-table layout specified in createShaderTable() // Create the desc for the triangle/plane instance instanceDescs[0].InstanceID = 0; instanceDescs[0].InstanceContributionToHitGroupIndex = 0; instanceDescs[0].Flags = (byte)RaytracingInstanceFlags.None; instanceDescs[0].Transform = Matrix4x4.Transpose(transformation[0]).ToMatrix3x4(); // GLM is column major, the INSTANCE_DESC is row major instanceDescs[0].AccelerationStructure = pBottomLevelAS[0].GPUVirtualAddress; instanceDescs[0].InstanceMask = 0xFF; for (int i = 1; i < 3; i++) { instanceDescs[i].InstanceID = i; // This value will be exposed to the shader via InstanceID() instanceDescs[i].InstanceContributionToHitGroupIndex = (i * 2) + 2; // The plane takes an additional entry in the shader-table, hence the +1 instanceDescs[i].Flags = (byte)RaytracingInstanceFlags.None; instanceDescs[i].Transform = Matrix4x4.Transpose(transformation[i]).ToMatrix3x4(); // GLM is column major, the INSTANCE_DESC is row major instanceDescs[i].AccelerationStructure = pBottomLevelAS[1].GPUVirtualAddress; instanceDescs[i].InstanceMask = 0xFF; } // Map the instance desc buffer IntPtr data; data = buffers.pInstanceDesc.Map(0, null); Helpers.MemCpy(data, instanceDescs, (uint)Unsafe.SizeOf <FixedRaytracingInstanceDescription>() * 3); buffers.pInstanceDesc.Unmap(0, null); // Create the TLAS BuildRaytracingAccelerationStructureDescription asDesc = new BuildRaytracingAccelerationStructureDescription(); asDesc.Inputs = inputs; asDesc.Inputs.InstanceDescriptions = buffers.pInstanceDesc.GPUVirtualAddress; asDesc.DestinationAccelerationStructureData = buffers.pResult.GPUVirtualAddress; asDesc.ScratchAccelerationStructureData = buffers.pScratch.GPUVirtualAddress; // If this is an update operation, set the source buffer and the perform_update flag if (update) { asDesc.Inputs.Flags |= RaytracingAccelerationStructureBuildFlags.PerformUpdate; asDesc.SourceAccelerationStructureData = buffers.pResult.GPUVirtualAddress; } pCmdList.BuildRaytracingAccelerationStructure(asDesc); // We need to insert a UAV barrier before using the acceleration structures in a raytracing operation ResourceBarrier uavBarrier = new ResourceBarrier(new ResourceUnorderedAccessViewBarrier(buffers.pResult)); pCmdList.ResourceBarrier(uavBarrier); return(buffers); }