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);
        }