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