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); }
private AccelerationStructureBuffers CreateBottomLevelAS(ID3D12Device5 device, ID3D12GraphicsCommandList4 commandList, ID3D12Resource[] vertexBuffers, int[] vertexCounts, int geometryCount) { RaytracingGeometryDescription[] descs = new RaytracingGeometryDescription[geometryCount]; for (int i = 0; i < descs.Length; i++) { descs[i] = new RaytracingGeometryDescription(); descs[i].Type = RaytracingGeometryType.Triangles; descs[i].Triangles = new RaytracingGeometryTrianglesDescription(); descs[i].Triangles.VertexBuffer = new GpuVirtualAddressAndStride(); descs[i].Triangles.VertexBuffer.StartAddress = vertexBuffers[i].GPUVirtualAddress; descs[i].Triangles.VertexBuffer.StrideInBytes = 3 * 4; descs[i].Triangles.VertexFormat = Format.R32G32B32_Float; descs[i].Triangles.VertexCount = vertexCounts[i]; descs[i].Flags = RaytracingGeometryFlags.Opaque; } BuildRaytracingAccelerationStructureInputs inputs = new BuildRaytracingAccelerationStructureInputs(); inputs.Layout = ElementsLayout.Array; inputs.Flags = RaytracingAccelerationStructureBuildFlags.None; inputs.DescriptorsCount = geometryCount; inputs.GeometryDescriptions = descs; inputs.Type = RaytracingAccelerationStructureType.BottomLevel; RaytracingAccelerationStructurePrebuildInfo info = device.GetRaytracingAccelerationStructurePrebuildInfo(inputs); HeapProperties properties = new HeapProperties(HeapType.Default, CpuPageProperty.Unknown, MemoryPool.Unknown, 0, 0); AccelerationStructureBuffers buffers = new AccelerationStructureBuffers(); buffers.Scratch = CreateBuffer(device, info.ScratchDataSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.UnorderedAccess, properties); buffers.Result = CreateBuffer(device, info.ResultDataMaxSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.RaytracingAccelerationStructure, properties); BuildRaytracingAccelerationStructureDescription asDesc = new BuildRaytracingAccelerationStructureDescription(); asDesc.Inputs = inputs; asDesc.DestinationAccelerationStructureData = buffers.Result.GPUVirtualAddress; asDesc.ScratchAccelerationStructureData = buffers.Scratch.GPUVirtualAddress; commandList.BuildRaytracingAccelerationStructure(asDesc); commandList.ResourceBarrier(ResourceBarrier.BarrierUnorderedAccessView(buffers.Result)); return(buffers); }
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); }
private void CreateTopLevelAS(ID3D12Device5 device, ID3D12GraphicsCommandList4 commandList, ID3D12Resource[] bottomLevelAS, ref long tlasSize, bool isUpdate, float rotate) { int instanceCount = 3; BuildRaytracingAccelerationStructureInputs inputs = new BuildRaytracingAccelerationStructureInputs(); inputs.Layout = ElementsLayout.Array; inputs.Flags = RaytracingAccelerationStructureBuildFlags.AllowUpdate; inputs.DescriptorsCount = instanceCount; inputs.Type = RaytracingAccelerationStructureType.TopLevel; var info = device.GetRaytracingAccelerationStructurePrebuildInfo(inputs); if (isUpdate == false) { HeapProperties properties = new HeapProperties(HeapType.Default, CpuPageProperty.Unknown, MemoryPool.Unknown, 0, 0); HeapProperties upload_properties = new HeapProperties(HeapType.Upload, CpuPageProperty.Unknown, MemoryPool.Unknown, 0, 0); long descSize = (long)Unsafe.SizeOf <MyRaytracingInstanceDescription>(); buffers = new AccelerationStructureBuffers(); buffers.Scratch = CreateBuffer(device, info.ScratchDataSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.UnorderedAccess, properties); buffers.Result = CreateBuffer(device, info.ResultDataMaxSizeInBytes, ResourceFlags.AllowUnorderedAccess, ResourceStates.RaytracingAccelerationStructure, properties); buffers.InstanceDesc = CreateBuffer(device, descSize * instanceCount, ResourceFlags.None, ResourceStates.GenericRead, upload_properties); tlasSize = info.ResultDataMaxSizeInBytes; } else { InsertUAVResourceBarrier(buffers.Result); } int instanceContr = 0; MyRaytracingInstanceDescription[] instanceDescs = new MyRaytracingInstanceDescription[instanceCount]; for (int i = 0; i < instanceCount; i++) { instanceDescs[i] = new MyRaytracingInstanceDescription(); float xPos = (i - 1) * 1.5f; float yPos = 0.0f; float zPos = 0.0f; instanceDescs[i].Transform = Matrix4x4.Identity; if (i != 1) { instanceDescs[i].Transform *= Matrix4x4.CreateRotationY(rotate); if (i == 2) { zPos = -0.5f; } } instanceDescs[i].Transform *= Matrix4x4.CreateTranslation(xPos, yPos, zPos); instanceDescs[i].Transform = Matrix4x4.Transpose(instanceDescs[i].Transform); instanceDescs[i].InstanceID = i; instanceDescs[i].InstanceContributionToHitGroupIndex = instanceContr; instanceDescs[i].Flags = (byte)RaytracingInstanceFlags.None; instanceDescs[i].InstanceMask = 0xFF; if (i == 1) { instanceDescs[i].AccelerationStructure = bottomLevelAS[0].GPUVirtualAddress; instanceContr += 4; } else { instanceDescs[i].AccelerationStructure = bottomLevelAS[1].GPUVirtualAddress; instanceContr += 2; } } IntPtr data = buffers.InstanceDesc.Map(0, null); Helpers.CopyMemory <MyRaytracingInstanceDescription>(data, new ReadOnlySpan <MyRaytracingInstanceDescription>( instanceDescs)); buffers.InstanceDesc.Unmap(0, null); BuildRaytracingAccelerationStructureDescription asDesc = new BuildRaytracingAccelerationStructureDescription(); asDesc.Inputs = inputs; asDesc.Inputs.InstanceDescriptions = buffers.InstanceDesc.GPUVirtualAddress; asDesc.DestinationAccelerationStructureData = buffers.Result.GPUVirtualAddress; asDesc.ScratchAccelerationStructureData = buffers.Scratch.GPUVirtualAddress; if (isUpdate) { asDesc.Inputs.Flags |= RaytracingAccelerationStructureBuildFlags.PerformUpdate; asDesc.SourceAccelerationStructureData = buffers.Result.GPUVirtualAddress; } commandList.BuildRaytracingAccelerationStructure(asDesc); InsertUAVResourceBarrier(buffers.Result); }
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); }