public void CreateAccelerationStructures() { acs = new AccelerationStructures(); long mTlasSize = 0; ID3D12Resource[] mpVertexBuffer = new ID3D12Resource[2]; mpVertexBuffer[0] = acs.CreateTriangleVB(mpDevice); mpVertexBuffer[1] = acs.CreatePlaneVB(mpDevice); // The first bottom-level buffer is for the plane and the triangle int[] vertexCount = new int[] { 3, 6 }; // Triangle has 3 vertices, plane has 6 AccelerationStructureBuffers[] bottomLevelBuffers = new AccelerationStructureBuffers[2]; bottomLevelBuffers[0] = acs.CreateBottomLevelAS(mpDevice, mpCmdList, mpVertexBuffer, vertexCount, 2); mpBottomLevelAS = new ID3D12Resource[2]; mpBottomLevelAS[0] = bottomLevelBuffers[0].pResult; // The second bottom-level buffer is for the triangle only bottomLevelBuffers[1] = acs.CreateBottomLevelAS(mpDevice, mpCmdList, mpVertexBuffer, vertexCount, 1); mpBottomLevelAS[1] = bottomLevelBuffers[1].pResult; // Create the TLAS AccelerationStructureBuffers topLevelBuffers = acs.CreateTopLevelAS(mpDevice, mpCmdList, mpBottomLevelAS, ref mTlasSize); // The tutorial doesn't have any resource lifetime management, so we flush and sync here. This is not required by the DXR spec - you can submit the list whenever you like as long as you take care of the resources lifetime. mFenceValue = context.SubmitCommandList(mpCmdList, mpCmdQueue, mpFence, mFenceValue); mpFence.SetEventOnCompletion(mFenceValue, mFenceEvent); mFenceEvent.WaitOne(); int bufferIndex = mpSwapChain.GetCurrentBackBufferIndex(); mpCmdList.Reset(mFrameObjects[0].pCmdAllocator, null); // Store the AS buffers. The rest of the buffers will be released once we exit the function mpTopLevelAS = topLevelBuffers.pResult; }
public unsafe AccelerationStructureBuffers CreateTopLevelAS(ID3D12Device5 pDevice, ID3D12GraphicsCommandList4 pCmdList, ID3D12Resource pBottomLevelAS, ref long tlasSize) { // 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 = 1; 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>(), ResourceFlags.None, ResourceStates.GenericRead, kUploadHeapProps); FixedRaytracingInstanceDescription pInstanceDesc; // Initialize the instance desc. We only have a single instance pInstanceDesc.InstanceID = 0; // This value will be exposed to the shader via InstanceID() pInstanceDesc.InstanceContributionToHitGroupIndex = 0; // This is the offset inside the shader-table. We only have a single geometry, so the offset 0 pInstanceDesc.Flags = (byte)RaytracingInstanceFlags.None; pInstanceDesc.Transform = Matrix4x4.Identity.ToMatrix3x4(); pInstanceDesc.AccelerationStructure = pBottomLevelAS.GPUVirtualAddress; pInstanceDesc.InstanceMask = 0xff; IntPtr data; data = buffers.pInstanceDesc.Map(0, null); Helpers.MemCpy(data, pInstanceDesc, (uint)Unsafe.SizeOf <FixedRaytracingInstanceDescription>()); 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); }
private AccelerationStructureBuffers CreateBottomLevelAS(ID3D12Device5 pDevice, ID3D12GraphicsCommandList4 pCmdList, ID3D12Resource vb, uint vbCount, ID3D12Resource ib, uint ibCount) { int geometryCount = 1; RaytracingGeometryDescription[] geomDesc = new RaytracingGeometryDescription[geometryCount]; // Primitives geomDesc[0].Type = RaytracingGeometryType.Triangles; geomDesc[0].Triangles = new RaytracingGeometryTrianglesDescription(); geomDesc[0].Triangles.VertexBuffer = new GpuVirtualAddressAndStride(); geomDesc[0].Triangles.VertexBuffer.StartAddress = vb.GPUVirtualAddress; geomDesc[0].Triangles.VertexBuffer.StrideInBytes = Unsafe.SizeOf <VertexPositionNormalTangentTexture>(); geomDesc[0].Triangles.VertexFormat = Format.R32G32B32_Float; geomDesc[0].Triangles.VertexCount = (int)vbCount; geomDesc[0].Triangles.IndexBuffer = ib.GPUVirtualAddress; geomDesc[0].Triangles.IndexCount = (int)ibCount; geomDesc[0].Triangles.IndexFormat = Format.R16_UInt; geomDesc[0].Flags = RaytracingGeometryFlags.Opaque; // Get the size requirements for the scratch and AS buffers BuildRaytracingAccelerationStructureInputs inputs = new BuildRaytracingAccelerationStructureInputs(); inputs.Layout = ElementsLayout.Array; inputs.Flags = RaytracingAccelerationStructureBuildFlags.None; inputs.DescriptorsCount = geometryCount; inputs.GeometryDescriptions = geomDesc; inputs.Type = RaytracingAccelerationStructureType.BottomLevel; RaytracingAccelerationStructurePrebuildInfo info; info = pDevice.GetRaytracingAccelerationStructurePrebuildInfo(inputs); // Create the buffers. They need to support UAV, and since we are going to immediately use them, we create them with an unordered-access state 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); // Create the bottom-level AS BuildRaytracingAccelerationStructureDescription asDesc = new BuildRaytracingAccelerationStructureDescription(); asDesc.Inputs = inputs; 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 void CreateAccelerationStructures() { acs = new AccelerationStructures(); AccelerationStructureBuffers bottomLevelBuffers = acs.CreateBottomLevelAS(mpDevice, mpCmdList); AccelerationStructureBuffers topLevelBuffers = acs.CreateTopLevelAS(mpDevice, mpCmdList, bottomLevelBuffers.pResult, ref mTlasSize); // The tutorial doesn't have any resource lifetime management, so we flush and sync here. This is not required by the DXR spec - you can submit the list whenever you like as long as you take care of the resources lifetime. mFenceValue = context.SubmitCommandList(mpCmdList, mpCmdQueue, mpFence, mFenceValue); mpFence.SetEventOnCompletion(mFenceValue, mFenceEvent); mFenceEvent.WaitOne(); int bufferIndex = mpSwapChain.GetCurrentBackBufferIndex(); mpCmdList.Reset(mFrameObjects[0].pCmdAllocator, null); // Store the AS buffers. The rest of the buffers will be released once we exit the function mpTopLevelAS = topLevelBuffers.pResult; mpBottomLevelAS = bottomLevelBuffers.pResult; }
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); }