Skip to content

Commit

Permalink
Adding support for Shader Records with Descriptor Tables and Empty To…
Browse files Browse the repository at this point in the history
…p Level Acceleration Structures (#297)

This adds support for local root signatures/shader records with descriptor table handles as the parameter. This removes the need for the app having to do it's own bindless indexing to associate a ClosestHit shader with a texture.

Also adding tests for verifying the use of descriptor tables. These tests have a pass-through raygen trace against a null acceleration structure and invoke the varying miss shaders that test different varieties of descriptor tables pulled from the shader record.

Finally, modifying the MiniEngine sample to use descriptor tables as local root signature arguments, which cleans up the shader code nicely.
  • Loading branch information
wallisc authored Apr 5, 2018
1 parent 73d496c commit 5ff0bea
Show file tree
Hide file tree
Showing 29 changed files with 593 additions and 276 deletions.
10 changes: 4 additions & 6 deletions Libraries/D3D12RaytracingFallback/developerguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,8 @@ The use of an AnyHit requires that the traversal code must stop it's current tra

## Known Issues & Limitations

* #### Local Root Signature Support limited to Root Constants
Currently local root signature/shader records are limited to root constants.

Descriptor Tables can be emulated for the time-being by binding descriptor tables that are dynamically indexed by a root constant (see ModelViewer's implementation)

Root descriptors are similarly not supported. This is expected to be supported in the future, but it should be noted that these will require the use of `WRAPPED_GPU_POINTER`'s rather then being able to consume a `GPU_VIRTUAL_ADDRESS` directly
* #### No Local Root Signature Support for Root Descriptors
Root descriptors are not currently supported. This is expected to be supported in the future, but it should be noted that these will require the use of `WRAPPED_GPU_POINTER`'s rather then being able to consume a `GPU_VIRTUAL_ADDRESS` directly

* #### No Callable or Intersection shaders
Both Callable and Intersection shaders are not yet supported.
Expand All @@ -204,6 +200,8 @@ The stack size passed by `SetPipelineStackSize` is ignored and uses a hard-coded

* #### Only one AccelerationStructure can be bound per call to DispatchRays()

* #### Use of the Shader Record is thrown off when using an empty ray payload

* #### D3D12_RAYTRACING_GEOMETRY_FLAG_OPAQUE is ignored
As a result, the `RAY_FLAG_CULL_OPAQUE`/`RAY_FLAG_CULL_NON_OPAQUE` flags will have no effect either
## Debugging & Tooling
Expand Down
2 changes: 2 additions & 0 deletions Libraries/D3D12RaytracingFallback/src/BitonicSort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ void BitonicSort::Sort(
bool IsPartiallyPreSorted,
bool SortAscending)
{
if (ElementCount == 0) return;

const uint32_t AlignedNumElements = AlignPowerOfTwo(ElementCount);
const uint32_t MaxIterations = Log2(std::max(2048u, AlignedNumElements)) - 10;

Expand Down
17 changes: 12 additions & 5 deletions Libraries/D3D12RaytracingFallback/src/ConstructAABBPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,30 +49,37 @@ namespace FallbackLayer
D3D12_GPU_DESCRIPTOR_HANDLE globalDescriptorHeap,
UINT numElements)
{
bool isEmptyAccelerationStructure = numElements == 0;
Level level = (sceneType == SceneType::Triangles) ? Level::Bottom : Level::Top;

InputConstants constants = { numElements };

pCommandList->SetComputeRootSignature(m_pRootSignature);
pCommandList->SetComputeRoot32BitConstants(InputRootConstants, SizeOfInUint32(InputConstants), &constants, 0);
pCommandList->SetComputeRootUnorderedAccessView(OutputBVHRootUAVParam, outputVH);
pCommandList->SetComputeRootUnorderedAccessView(ScratchUAVParam, scratchBuffer);
pCommandList->SetComputeRootUnorderedAccessView(ChildNodesProcessedCountBufferParam, childNodesProcessedCountBuffer);
pCommandList->SetComputeRootUnorderedAccessView(MortonCodesBufferParam, mortonCodeBuffer);
pCommandList->SetComputeRootUnorderedAccessView(HierarchyUAVParam, hierarchyBuffer);
if (!isEmptyAccelerationStructure)
{
pCommandList->SetComputeRootUnorderedAccessView(ScratchUAVParam, scratchBuffer);
pCommandList->SetComputeRootUnorderedAccessView(ChildNodesProcessedCountBufferParam, childNodesProcessedCountBuffer);
pCommandList->SetComputeRootUnorderedAccessView(MortonCodesBufferParam, mortonCodeBuffer);
pCommandList->SetComputeRootUnorderedAccessView(HierarchyUAVParam, hierarchyBuffer);
}

if (level == Top)
{
pCommandList->SetComputeRootDescriptorTable(GlobalDescriptorHeap, globalDescriptorHeap);
}

// Only given the GPU VA not the resource itself so need to resort to doing an overarching UAV barrier
const UINT dispatchWidth = DivideAndRoundUp<UINT>(numElements, THREAD_GROUP_1D_WIDTH);
const UINT dispatchWidth = isEmptyAccelerationStructure ? 1 : DivideAndRoundUp<UINT>(numElements, THREAD_GROUP_1D_WIDTH);
auto uavBarrier = CD3DX12_RESOURCE_BARRIER::UAV(nullptr);

pCommandList->SetPipelineState(m_pPrepareForComputeAABBs[level]);
pCommandList->Dispatch(dispatchWidth, 1, 1);
pCommandList->ResourceBarrier(1, &uavBarrier);

if (isEmptyAccelerationStructure) return;

// Build the AABBs from the bottom-up
pCommandList->SetPipelineState(m_pComputeAABBs[level]);
pCommandList->Dispatch(dispatchWidth, 1, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ namespace FallbackLayer
D3D12_GPU_DESCRIPTOR_HANDLE globalDescriptorHeap,
UINT numElements)
{
if (numElements == 0) return;

Level level = (sceneType == SceneType::Triangles) ? Level::Bottom : Level::Top;

InputConstants constants = { numElements };
Expand Down
10 changes: 0 additions & 10 deletions Libraries/D3D12RaytracingFallback/src/DxilShaderPatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,16 +233,6 @@ namespace FallbackLayer

std::vector<LPCWSTR> arguments;
arguments.push_back(dxilPatchShaderRecordString);
if (!pShaderInfo->IsLib)
{
// Because a fully resolved shader has meta-data already generated, a whole bunch of passes need
// to be run to keep all the meta-data up-to-date
arguments.push_back(L"-dxil-dfe"); // Dead function elimination to remove functions like buffer loads that may no longer be needed due to binding re-mapping
arguments.push_back(L"-dce"); // Dead code eliminition to remove old bindings that were remapped to the shader binding table
arguments.push_back(L"-hlsl-dxil-condense"); // Because old bindings get replaced with new bindings, it leaves gaps that need to be condensed
arguments.push_back(L"-hlsl-dxil-update-metadata");
}

HRESULT hr = m_pOptimizer->RunOptimizer(pShaderBlob, arguments.data(), (UINT32)arguments.size(), &pPatchedBlob, &pErrorMessage);

#if SPEW_SHADERS
Expand Down
56 changes: 2 additions & 54 deletions Libraries/D3D12RaytracingFallback/src/FallbackDxil.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
#pragma once

#define FallbackLayerRegisterSpace 214743647
Expand All @@ -20,12 +10,13 @@
#define FallbackLayerCallableShaderRecordByteAddressBufferRegister 3

// SRV & UAV
#define FallbackLayerDescriptorHeapBufferTable 0
#define FallbackLayerDescriptorHeapTable 0

// There's a driver issue on some hardware that has issues
// starting a bindless table on any register but 0, so
// make sure each bindless table has it's own register space
#define FallbackLayerDescriptorHeapStartingSpaceOffset 1
#define FallbackLayerNumDescriptorHeapSpacesPerView 10

// CBVs
#define FallbackLayerDispatchConstantsRegister 0
Expand All @@ -38,7 +29,6 @@ struct ShaderInfo
unsigned int SamplerDescriptorSizeInBytes;
unsigned int SrvCbvUavDescriptorSizeInBytes;
unsigned int ShaderRecordIdentifierSizeInBytes;
bool IsLib;
const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *pRootSignatureDesc;
};

Expand All @@ -63,45 +53,6 @@ enum DescriptorRangeTypes
NumRangeTypes
};

enum RegisterSpaceOffsets
{
SRVBufferOffset = FallbackLayerDescriptorHeapStartingSpaceOffset,
SRVStructuredBufferOffset,
SRVRawBufferOffset,
SRVTexture1DOffset,
SRVTexture1DArrayOffset,
SRVTexture2DOffset,
SRVTexture2DMSOffset,
SRVTexture2DArrayOffset,
SRVTexture2DMSArrayOffset,
SRVTexture3DOffset,
SRVTextureCubeOffset,
SRVTextureCubeArrayOffset,

SRVStartOffset = SRVBufferOffset,
NumSRVSpaces = SRVTextureCubeArrayOffset - SRVStartOffset + 1,

UAVRawBufferOffset = FallbackLayerDescriptorHeapStartingSpaceOffset,
UAVBufferOffset,
UAVStructuredBufferOffset,
UAVTexture1DOffset,
UAVTexture1DArrayOffset,
UAVTexture2DOffset,
UAVTexture2DArrayOffset,
UAVTexture3DOffset,

UAVStartOffset = UAVRawBufferOffset,
NumUAVSpaces = UAVTexture3DOffset - UAVStartOffset + 1,

SamplerOffset = FallbackLayerDescriptorHeapStartingSpaceOffset,
NumSamplerSpaces = 1,

ConstantBufferOffset = FallbackLayerDescriptorHeapStartingSpaceOffset,
NumConstantBufferSpaces = 1,

NumSpaces = NumSRVSpaces + NumUAVSpaces + NumConstantBufferSpaces + NumSamplerSpaces,
};

enum RootSignatureParameterOffset
{
HitGroupRecord = 0,
Expand All @@ -114,9 +65,6 @@ enum RootSignatureParameterOffset
AccelerationStructuresList,
#if ENABLE_UAV_LOG
DebugUAVLog,
#endif
#if ENABLE_ACCELERATION_STRUCTURE_VISUALIZATION
DebugConstants,
#endif
NumParameters
};
Expand Down
58 changes: 31 additions & 27 deletions Libraries/D3D12RaytracingFallback/src/FallbackLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,12 @@ namespace FallbackLayer
{
for (UINT i = 0; i < pRootSignature->NumParameters; i++)
{
if (pRootSignature->pParameters[i].ParameterType != D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS)
if (pRootSignature->pParameters[i].ParameterType != D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS &&
pRootSignature->pParameters[i].ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
{
ThrowFailure(E_INVALIDARG,
L"Only D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS is currently supported for local root signatures."
L"For details, view the Fallback Layer readme.md");
L"Only D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS/D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE are currently "
"supported for local root signatures. For details, view the Fallback Layer readme.md");
}
}
}
Expand All @@ -196,32 +197,24 @@ namespace FallbackLayer
TD3DX12_ROOT_PARAMETER *pOriginalParameters = (TD3DX12_ROOT_PARAMETER*)pRootSignature->pParameters;
std::copy(pOriginalParameters, pOriginalParameters + pRootSignature->NumParameters, patchedRootParameters.begin());

patchedRanges.reserve(RegisterSpaceOffsets::NumSpaces);
for (UINT i = 0; i < NumSRVSpaces; i++)
{
patchedRanges.push_back(
TD3DX12_DESCRIPTOR_RANGE(
D3D12_DESCRIPTOR_RANGE_TYPE_SRV, UINT_MAX, FallbackLayerDescriptorHeapBufferTable, FallbackLayerRegisterSpace + SRVStartOffset + i));
}

for (UINT i = 0; i < NumUAVSpaces; i++)
{
patchedRanges.push_back(
TD3DX12_DESCRIPTOR_RANGE(
D3D12_DESCRIPTOR_RANGE_TYPE_UAV, UINT_MAX, FallbackLayerDescriptorHeapBufferTable, FallbackLayerRegisterSpace + UAVStartOffset + i));
}

patchedRanges.push_back(
TD3DX12_DESCRIPTOR_RANGE(
D3D12_DESCRIPTOR_RANGE_TYPE_CBV, UINT_MAX, FallbackLayerDescriptorHeapBufferTable, FallbackLayerRegisterSpace + ConstantBufferOffset));
UINT CbvSrvUavParamterCount = static_cast<UINT>(patchedRanges.size());
UINT CbvSrvUavParamterCount = 0;
D3D12_DESCRIPTOR_RANGE_TYPE descriptorTypes[] = {
D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
D3D12_DESCRIPTOR_RANGE_TYPE_UAV,

patchedRanges.push_back(
TD3DX12_DESCRIPTOR_RANGE(
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, UINT_MAX, FallbackLayerDescriptorHeapBufferTable, FallbackLayerRegisterSpace + SamplerOffset));
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER };

for (auto &range : patchedRanges)
for (auto descriptorType : descriptorTypes)
{
UINT numSpacesNeeded = 1;
if (descriptorType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV || descriptorType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV)
{
numSpacesNeeded = FallbackLayerNumDescriptorHeapSpacesPerView;
}

auto range = TD3DX12_DESCRIPTOR_RANGE(
descriptorType, UINT_MAX, FallbackLayerDescriptorHeapTable, FallbackLayerRegisterSpace + FallbackLayerDescriptorHeapStartingSpaceOffset);
range.OffsetInDescriptorsFromTableStart = 0;
__if_exists(TD3DX12_DESCRIPTOR_RANGE::Flags)
{
Expand All @@ -230,8 +223,19 @@ namespace FallbackLayer
range.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
}
}
}

for (UINT i = 0; i < numSpacesNeeded; i++)
{
patchedRanges.push_back(range);
range.RegisterSpace++;
}

if (descriptorType != D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER)
{
CbvSrvUavParamterCount += numSpacesNeeded;
}
}

UINT patchedParameterOffset = pRootSignature->NumParameters;
patchedRootParameters[patchedParameterOffset + HitGroupRecord].InitAsShaderResourceView(FallbackLayerHitGroupRecordByteAddressBufferRegister, FallbackLayerRegisterSpace);
patchedRootParameters[patchedParameterOffset + MissShaderRecord].InitAsShaderResourceView(FallbackLayerMissShaderRecordByteAddressBufferRegister, FallbackLayerRegisterSpace);
Expand Down
Loading

0 comments on commit 5ff0bea

Please sign in to comment.