Skip to content

Commit

Permalink
[DX12] Ensure root signature version can fallback to supported versio…
Browse files Browse the repository at this point in the history
…n on newer devices

[DX12] Add debug helper method RootSignatureDX12.LayoutToLog()
[DX12] RootSignatureDX12 now stores description for binding validation purposes
  • Loading branch information
Syncaidius committed May 6, 2024
1 parent b20a1b7 commit 3eaa659
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Molten.Graphics.DX12/Pipeline/CommandListDX12.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ protected override GpuBindResult DoRenderPass(ShaderPass hlslPass, QueueValidati
_handle->SetPipelineState(state.Handle);
_handle->SetGraphicsRootSignature(state.RootSignature.Handle);

Device.Heap.PrepareGpuHeap(pass, this);
Device.Heap.PrepareGpuHeap(pass, state, this);

CpuDescriptorHandle* dsvHandle = _dsv->Ptr != 0 ? _dsv : null;
_handle->OMSetRenderTargets(_numRTVs, _rtvs, false, dsvHandle);
Expand Down
2 changes: 1 addition & 1 deletion Molten.Graphics.DX12/Pipeline/CommandQueueDX12.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ internal void Execute(GpuCommandList cmd)

_handle->ExecuteCommandLists(1, lists);
_prevCmdList = dxCmd;
dxCmd.ApplyBarrierStates();
_lockerExecute.Unlock();

dxCmd.ApplyBarrierStates();
}

protected override void OnGpuRelease()
Expand Down
22 changes: 16 additions & 6 deletions Molten.Graphics.DX12/Pipeline/Heap/DescriptorHeapManagerDX12.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,16 @@ internal HeapHandleDX12 GetSamplerHandle(uint numDescriptors)
/// <summary>
/// Consolidates all of the CPU-side descriptors into a single GPU descriptor heap ready for use.
/// </summary>
internal unsafe void PrepareGpuHeap(ShaderPassDX12 pass, CommandListDX12 cmd)
internal unsafe void PrepareGpuHeap(ShaderPassDX12 pass, PipelineStateDX12 state, CommandListDX12 cmd)
{
DeviceDX12 device = pass.Device as DeviceDX12;
DescriptorHeapDX12 resHeap = _gpuResourceHeap.Prepare();
CpuDescriptorHandle gpuResHandle = resHeap.CpuStartHandle;
uint resBindCount = 0;

DescriptorHeapDX12 samplerHeap = _gpuSamplerHeap.Prepare();
CpuDescriptorHandle gpuSamplerHandle = samplerHeap.CpuStartHandle;
uint samplerBindCount = 0;

// TODO Replace this once DX11 is removed and resources can be created during instantiation instead of during Apply().
// Apply resources.
Expand All @@ -103,27 +105,32 @@ internal unsafe void PrepareGpuHeap(ShaderPassDX12 pass, CommandListDX12 cmd)
case ShaderBindType.ConstantBuffer:
CBHandleDX12 cbHandle = resHandle as CBHandleDX12;
cpuHandle = cbHandle.CBV.CpuHandle;
cmd.Transition(resHandle, ResourceStates.VertexAndConstantBuffer);
break;

case ShaderBindType.Resource:
cpuHandle = resHandle.SRV.CpuHandle;
cmd.Transition(resHandle, ResourceStates.AllShaderResource);
break;

case ShaderBindType.UnorderedAccess:
cpuHandle = resHandle.UAV.CpuHandle;
// TODO Handle UAV barriers?
break;
}

// TODO transition resources to PIXEL_SHADER_RESOURCE
// TODO transition CBs to VERTEX_AND_CONSTANT_BUFFER
// TODO Move cmd.Transition into ResourceHandleDX12.Transition(cmd, ResourceState) - Track per-resource barrier state.

if (cpuHandle.Ptr != 0)
{
device.Handle->CopyDescriptorsSimple(1, gpuResHandle, cpuHandle, DescriptorHeapType.CbvSrvUav);

// Increment GPU heap handle
resBindCount++;
}
else
{

}

// Increment GPU heap handle
gpuResHandle.Ptr += resHeap.IncrementSize;
}
}
Expand All @@ -137,9 +144,12 @@ internal unsafe void PrepareGpuHeap(ShaderPassDX12 pass, CommandListDX12 cmd)
ShaderSampler heapSampler = bind.Object.Sampler;
// TODO _handleBuffer[index] = heapSampler.View.CpuHandle;
gpuSamplerHandle.Ptr += samplerHeap.IncrementSize;
samplerBindCount++;
}
}

state.RootSignature.LayoutToLog();

// Populate SRV, UAV, and CBV descriptors first.
// TODO Pull descriptor info from our pass, render targets, samplers, depth-stencil, etc.

Expand Down
17 changes: 10 additions & 7 deletions Molten.Graphics.DX12/Pipeline/State/PipelineStateBuilderDX12.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,14 @@ public bool Equals(CacheKey other)
internal PipelineStateBuilderDX12(DeviceDX12 device)
{
_rootSignatureVersion = device.CapabilitiesDX12.RootSignatureVersion;
if (!_rootPopulators.TryGetValue(_rootSignatureVersion, out _rootSigPopulator))
throw new NotSupportedException($"Unsupported root signature version: {_rootSignatureVersion}.");

// Decrease root signature version until we find one the engine supports.
while (!_rootPopulators.TryGetValue(_rootSignatureVersion, out _rootSigPopulator))
{
_rootSignatureVersion--;
if(_rootSignatureVersion <= 0)
throw new NotSupportedException("The current device does not support any known root signature versions.");
}
}

internal unsafe PipelineStateDX12 Build(
Expand Down Expand Up @@ -168,7 +174,7 @@ internal unsafe PipelineStateDX12 Build(

Guid guid = ID3D12PipelineState.Guid;
void* ptr = null;
HResult hr = device.Handle->CreateGraphicsPipelineState(desc, &guid, &ptr);
HResult hr = device.Handle->CreateGraphicsPipelineState(ref desc, &guid, &ptr);
if (!device.Log.CheckResult(hr, () => "Failed to create pipeline state object (PSO)"))
return null;

Expand Down Expand Up @@ -216,10 +222,7 @@ private unsafe RootSignatureDX12 BuildRootSignature(ShaderPassDX12 pass, Pipelin
if (!device.Log.CheckResult(hr, () => "Failed to create root signature"))
hr.Throw();

RootSignatureDX12 result = new RootSignatureDX12(device, (ID3D12RootSignature*)ptr);
_rootSigPopulator.Free(ref sigDesc);

return result;
return new RootSignatureDX12(device, (ID3D12RootSignature*)ptr, sigDesc);
}

private unsafe void ParseErrors(ShaderPassDX12 pass, HResult hr, ID3D10Blob* errors)
Expand Down
11 changes: 0 additions & 11 deletions Molten.Graphics.DX12/Pipeline/State/RootSigPopulator1_0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,6 @@ internal override unsafe void Populate(ref VersionedRootSignatureDesc versionedD
rangeSpan.CopyTo(tableRanges);
}

internal unsafe override void Free(ref VersionedRootSignatureDesc versionedDesc)
{
ref RootSignatureDesc desc = ref versionedDesc.Desc10;

for (int i = 0; i < desc.NumParameters; i++)
EngineUtil.Free(ref desc.PParameters[i].DescriptorTable.PDescriptorRanges);

EngineUtil.Free(ref desc.PParameters);
EngineUtil.Free(ref desc.PStaticSamplers);
}

private void PopulateRanges<V>(DescriptorRangeType type, List<DescriptorRange> ranges, ShaderBind<V>[] variables, ref uint numDescriptors)
where V : ShaderVariable
{
Expand Down
11 changes: 0 additions & 11 deletions Molten.Graphics.DX12/Pipeline/State/RootSigPopulator1_1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,6 @@ internal override unsafe void Populate(ref VersionedRootSignatureDesc versionedD
rangeSpan.CopyTo(tableRanges);
}

internal override unsafe void Free(ref VersionedRootSignatureDesc versionedDesc)
{
ref RootSignatureDesc1 desc = ref versionedDesc.Desc11;

for (int i = 0; i < desc.NumParameters; i++)
EngineUtil.Free(ref desc.PParameters[i].DescriptorTable.PDescriptorRanges);

EngineUtil.Free(ref desc.PParameters);
EngineUtil.Free(ref desc.PStaticSamplers);
}

private void PopulateRanges<V>(DescriptorRangeType type, List<DescriptorRange1> ranges, ShaderBind<V>[] variables, ref uint numDescriptors)
where V: ShaderVariable
{
Expand Down
73 changes: 71 additions & 2 deletions Molten.Graphics.DX12/Pipeline/State/RootSignatureDX12.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,88 @@ namespace Molten.Graphics.DX12;
internal unsafe class RootSignatureDX12 : GpuObject<DeviceDX12>
{
ID3D12RootSignature* _handle;
VersionedRootSignatureDesc _desc;

internal RootSignatureDX12(DeviceDX12 device, ID3D12RootSignature* handle) :
internal RootSignatureDX12(DeviceDX12 device, ID3D12RootSignature* handle, VersionedRootSignatureDesc desc) :
base(device)
{
_handle = handle;
_desc = desc;
}

public static implicit operator ID3D12RootSignature*(RootSignatureDX12 sig) => sig._handle;
/// <summary>
/// Outputs the layout of the current <see cref="RootSignatureDX12"/> to it's parent <see cref="DeviceDX12"/> log.
/// </summary>
internal unsafe void LayoutToLog()
{
// Validate GPU heap
if (_desc.Version == D3DRootSignatureVersion.Version10)
LogLayout1_0();
else if (_desc.Version == D3DRootSignatureVersion.Version11)
LogLayout1_1();
}

private void LogLayout1_0()
{
throw new NotImplementedException($"{nameof(LayoutToLog)}: Logging of V1.0 root signatures is not yet supported.");
}

private void LogLayout1_1()
{
ref RootSignatureDesc1 desc = ref _desc.Desc11;
Device.Log.Debug($"Bound Root-Sigature (V1.1) with {desc.NumParameters} parameter(s):");

for (uint i = 0; i < desc.NumParameters; i++)
{
ref RootParameter1 rootParam = ref desc.PParameters[i];
Device.Log.Debug($"\tRoot parameter {i} - Type: {rootParam.ParameterType}");

if (rootParam.ParameterType == RootParameterType.TypeDescriptorTable)
{
ref RootDescriptorTable1 table = ref rootParam.DescriptorTable;
for (uint j = 0; j < table.NumDescriptorRanges; j++)
{
ref DescriptorRange1 range = ref table.PDescriptorRanges[j];
Device.Log.Debug($"\t\tRange {j} - Type: {range.RangeType}, Descriptor(s): {range.NumDescriptors}");
for (uint k = 0; k < range.NumDescriptors; k++)
{
uint offsetFromStart = range.OffsetInDescriptorsFromTableStart + k;
Device.Log.Debug($"\t\t\tDescriptor {k} - Offset: {offsetFromStart}");
}
}
}
}
}

protected override void OnGpuRelease()
{
NativeUtil.ReleasePtr(ref _handle);

if (_desc.Version == D3DRootSignatureVersion.Version11)
{
ref RootSignatureDesc1 desc = ref _desc.Desc11;

for (int i = 0; i < desc.NumParameters; i++)
EngineUtil.Free(ref desc.PParameters[i].DescriptorTable.PDescriptorRanges);

EngineUtil.Free(ref desc.PParameters);
EngineUtil.Free(ref desc.PStaticSamplers);
}
else if (_desc.Version == D3DRootSignatureVersion.Version10)
{
ref RootSignatureDesc desc = ref _desc.Desc10;

for (int i = 0; i < desc.NumParameters; i++)
EngineUtil.Free(ref desc.PParameters[i].DescriptorTable.PDescriptorRanges);

EngineUtil.Free(ref desc.PParameters);
EngineUtil.Free(ref desc.PStaticSamplers);
}
}

public static implicit operator ID3D12RootSignature*(RootSignatureDX12 sig) => sig._handle;

public ref readonly ID3D12RootSignature* Handle => ref _handle;

public ref readonly VersionedRootSignatureDesc Desc => ref _desc;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ internal abstract void Populate(ref VersionedRootSignatureDesc versionedDesc,
ShaderPassDX12 pass,
PipelineInputLayoutDX12 layout);

internal abstract void Free(ref VersionedRootSignatureDesc versionedDesc);

protected unsafe void PopulateStaticSamplers(ref StaticSamplerDesc* samplers, ref uint numSamplers, ShaderPassDX12 pass)
{
// Finalize sampler visibility. Iterate over all samplers used in the pass.
Expand Down

0 comments on commit 3eaa659

Please sign in to comment.