Example #1
0
        public unsafe void CreateShaderTable()
        {
            /** The shader-table layout is as follows:
             *  Entry 0 - Ray-gen program
             *  Entry 1 - Miss program
             *  Entry 2 - Hit program
             *  All entries in the shader-table must have the same size, so we will choose it base on the largest required entry.
             *  The ray-gen program requires the largest entry - sizeof(program identifier) + 8 bytes for a descriptor-table.
             *  The entry size must be aligned up to D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT
             */

            // Calculate the size and create the buffer
            mShaderTableEntrySize  = D3D12ShaderIdentifierSizeInBytes;
            mShaderTableEntrySize += 8; // the ray-gen's descriptor table
            mShaderTableEntrySize  = align_to(D3D12RaytracingShaderRecordByteAlignment, mShaderTableEntrySize);
            uint shaderTableSize = mShaderTableEntrySize * 4;

            // For simplicity, we create the shader.table on the upload heap. You can also create it on the default heap
            mpShaderTable = this.acs.CreateBuffer(mpDevice, shaderTableSize, ResourceFlags.None, ResourceStates.GenericRead, AccelerationStructures.kUploadHeapProps);

            // Map the buffer
            IntPtr pData;

            pData = mpShaderTable.Map(0, null);

            ID3D12StateObjectProperties pRtsoProps;

            pRtsoProps = mpPipelineState.QueryInterface <ID3D12StateObjectProperties>();

            // Entry 0 - ray-gen program ID and descriptor data
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kRayGenShader), D3D12ShaderIdentifierSizeInBytes);

            ulong heapStart = (ulong)mpSrvUavHeap.GetGPUDescriptorHandleForHeapStart().Ptr;

            Unsafe.Write <ulong>((pData + (int)D3D12ShaderIdentifierSizeInBytes).ToPointer(), heapStart);

            // This is where we need to set the descriptor data for the ray-gen shader. We'll get to it in the next tutorial

            // Entry 1 - miss program
            pData += (int)mShaderTableEntrySize; // +1 skips ray-gen
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kMissShader), D3D12ShaderIdentifierSizeInBytes);

            // Entry 2 - miss program
            pData += (int)mShaderTableEntrySize; // +1 skips ray-gen
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kShadowMiss), D3D12ShaderIdentifierSizeInBytes);

            // Entry 3 - hit program
            pData += (int)mShaderTableEntrySize; // +1 skips miss entries
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kHitGroup), D3D12ShaderIdentifierSizeInBytes);
            heapStart = (ulong)mpSrvUavHeap.GetGPUDescriptorHandleForHeapStart().Ptr;
            Unsafe.Write <ulong>((pData + (int)D3D12ShaderIdentifierSizeInBytes).ToPointer(), heapStart);

            // Unmap
            mpShaderTable.Unmap(0, null);
        }
        public DescriptorHandle Allocate(int count)
        {
            if (_currentHeap == null ||
                _remainingFreeHandles < count)
            {
                _currentHeap      = Device.RequestNewHeap(Type, DescriptorsPerHeap);
                _currentCpuHandle = _currentHeap.GetCPUDescriptorHandleForHeapStart();
                if (IsShaderVisible)
                {
                    _currentGpuHandle = _currentHeap.GetGPUDescriptorHandleForHeapStart();
                }

                _remainingFreeHandles = DescriptorsPerHeap;

                if (_descriptorSize == 0)
                {
                    _descriptorSize = Device.D3D12Device.GetDescriptorHandleIncrementSize(Type);
                }
            }

            var cpuHandle = _currentCpuHandle;

            _currentCpuHandle.Ptr += count * _descriptorSize;
            _remainingFreeHandles -= count;

            if (IsShaderVisible)
            {
                var gpuHandle = _currentGpuHandle;
                _currentGpuHandle.Ptr += (long)(count * _descriptorSize);
                return(new DescriptorHandle(_currentHeap, _descriptorSize, cpuHandle, gpuHandle));
            }

            return(new DescriptorHandle(_currentHeap, _descriptorSize, cpuHandle));
        }
Example #3
0
        public void GetTempHandle(out CpuDescriptorHandle cpuHandle, out GpuDescriptorHandle gpuHandle)
        {
            CpuDescriptorHandle cpuHandle1 = heap.GetCPUDescriptorHandleForHeapStart();

            cpuHandle1.Ptr += (nuint)(allocatedCount * IncrementSize);
            GpuDescriptorHandle gpuHandle1 = heap.GetGPUDescriptorHandleForHeapStart();

            gpuHandle1.Ptr += (ulong)(allocatedCount * IncrementSize);

            allocatedCount = (allocatedCount + 1) % descriptorCount;
            cpuHandle      = cpuHandle1;
            gpuHandle      = gpuHandle1;
        }
        public unsafe void CreateShaderTable()
        {
            /** The shader-table layout is as follows:
             *  Entry 0 - Ray-gen program
             *  Entry 1 - Miss program for the primary ray
             *  Entry 2 - Miss programm for the shadow ray
             *  Entry 3,4 - Hit program for triangle 0 (primary followed by shadow)
             *  Entry 5,6 - Hit program for the plane (primary followed by shadow)
             *  Entry 7,8 - Hit program for triangle 1 (primary followed by shadow)
             *  Entry 9,10 - Hit program for triangle 2 (primary followed by shadow)
             *  All entries in the shader-table must have the same size, so we will choose it base on the largest required entry.
             *  The ray-gen program requires the largest entry - sizeof(program identifier) + 8 bytes for a descriptor-table.
             *  The entry size must be aligned up to D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT
             */

            // Calculate the size and create the buffer
            mShaderTableEntrySize  = D3D12ShaderIdentifierSizeInBytes;
            mShaderTableEntrySize += 8; // the ray-gen's descriptor table
            mShaderTableEntrySize  = align_to(D3D12RaytracingShaderRecordByteAlignment, mShaderTableEntrySize);
            uint shaderTableSize = mShaderTableEntrySize * 11;

            // For simplicity, we create the shader.table on the upload heap. You can also create it on the default heap
            mpShaderTable = this.acs.CreateBuffer(mpDevice, shaderTableSize, ResourceFlags.None, ResourceStates.GenericRead, AccelerationStructures.kUploadHeapProps);

            // Map the buffer
            IntPtr pData;

            pData = mpShaderTable.Map(0, null);

            ID3D12StateObjectProperties pRtsoProps;

            pRtsoProps = mpPipelineState.QueryInterface <ID3D12StateObjectProperties>();

            // Entry 0 - ray-gen program ID and descriptor data
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kRayGenShader), D3D12ShaderIdentifierSizeInBytes);
            ulong heapStart = (ulong)mpSrvUavHeap.GetGPUDescriptorHandleForHeapStart().Ptr;

            Unsafe.Write <ulong>((pData + (int)D3D12ShaderIdentifierSizeInBytes).ToPointer(), heapStart);

            // Entry 1 - primary ray miss
            pData += (int)mShaderTableEntrySize; // +1 skips ray-gen
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kMissShader), D3D12ShaderIdentifierSizeInBytes);

            // Entry 2 - shadow-ray miss
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kShadowMiss), D3D12ShaderIdentifierSizeInBytes);

            // Entry 3 - Triangle 0, PRIMARY RAY. ProgramID and constant-buffer data
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kTriHitGroup), D3D12ShaderIdentifierSizeInBytes);
            void *pEntry3 = (pData + (int)D3D12ShaderIdentifierSizeInBytes).ToPointer();

            Unsafe.Write <ulong>(pEntry3, (ulong)mpContantBuffer[0].GPUVirtualAddress);

            // Entry 4 - Triangle 0, shadow ray. ProgramID only
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kShadowHitGroup), D3D12ShaderIdentifierSizeInBytes);

            // Entry 5 - Plane, primary ray. ProgramID only and the TLAS SRV
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kPlaneHitGroup), D3D12ShaderIdentifierSizeInBytes);
            void *pEntry5 = (pData + (int)D3D12ShaderIdentifierSizeInBytes).ToPointer();

            Unsafe.Write <ulong>(pEntry5, heapStart + (ulong)mpDevice.GetDescriptorHandleIncrementSize(DescriptorHeapType.ConstantBufferViewShaderResourceViewUnorderedAccessView)); // The SRV comes directly after the program id

            // Entry 6 - Plane shadow ray
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kShadowHitGroup), D3D12ShaderIdentifierSizeInBytes);

            // Entry 7 - Triangle 1 hit. ProgramID and constant-buffer data
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kTriHitGroup), D3D12ShaderIdentifierSizeInBytes);
            void *pEntry7 = (pData + (int)D3D12ShaderIdentifierSizeInBytes).ToPointer();

            Unsafe.Write <ulong>(pEntry7, (ulong)mpContantBuffer[1].GPUVirtualAddress);

            // Entry 8 - Triangle 1, shadow ray. ProgramID only
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kShadowHitGroup), D3D12ShaderIdentifierSizeInBytes);

            // Entry 9 - Triangle 2 hit. ProgramID and constant-buffer data
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kTriHitGroup), D3D12ShaderIdentifierSizeInBytes);
            void *pEntry9 = (pData + (int)D3D12ShaderIdentifierSizeInBytes).ToPointer();

            Unsafe.Write <ulong>(pEntry9, (ulong)mpContantBuffer[2].GPUVirtualAddress);

            // Entry 10 - Triangle 2, shadow ray. ProgramID only
            pData += (int)mShaderTableEntrySize;
            Unsafe.CopyBlock((void *)pData, (void *)pRtsoProps.GetShaderIdentifier(RTPipeline.kShadowHitGroup), D3D12ShaderIdentifierSizeInBytes);

            // Unmap
            mpShaderTable.Unmap(0, null);
        }