Skip to content

Commit

Permalink
[DX12] Move root signature construction to RootSignatureBuilderDX12
Browse files Browse the repository at this point in the history
[DX12] Removed PipelineStateBuilderDX12.BuildRootSignature()
[DX12] Added RootSignatureBuilderDX12
  • Loading branch information
Syncaidius committed May 7, 2024
1 parent ce733c2 commit a76fd30
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 74 deletions.
77 changes: 3 additions & 74 deletions Molten.Graphics.DX12/Pipeline/State/PipelineStateBuilderDX12.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,12 @@ public bool Equals(CacheKey other)
}
}

static readonly char[] _errorDelimiters = ['\r', '\n'];

KeyedObjectCache<CacheKey, PipelineStateDX12> _cache = new();
static readonly Dictionary<D3DRootSignatureVersion, RootSignaturePopulatorDX12> _rootPopulators = new()
{
[D3DRootSignatureVersion.Version10] = new RootSigPopulator1_0(),
[D3DRootSignatureVersion.Version11] = new RootSigPopulator1_1(),
};

D3DRootSignatureVersion _rootSignatureVersion;
RootSignaturePopulatorDX12 _rootParser;
RootSignatureBuilderDX12 _rootBuilder;

internal PipelineStateBuilderDX12(DeviceDX12 device)
{
_rootSignatureVersion = device.CapabilitiesDX12.RootSignatureVersion;

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

internal unsafe PipelineStateDX12 Build(
Expand Down Expand Up @@ -169,7 +152,7 @@ internal unsafe PipelineStateDX12 Build(
desc.SampleDesc = default; // TODO Implement multisampling
}

RootSignatureDX12 rootSig = BuildRootSignature(pass, layout, ref desc);
RootSignatureDX12 rootSig = _rootBuilder.Build(pass, layout, ref desc);
desc.PRootSignature = rootSig;

Guid guid = ID3D12PipelineState.Guid;
Expand All @@ -192,58 +175,4 @@ internal unsafe PipelineStateDX12 Build(

return result;
}

private unsafe RootSignatureDX12 BuildRootSignature(ShaderPassDX12 pass, PipelineInputLayoutDX12 layout, ref readonly GraphicsPipelineStateDesc psoDesc)
{
DeviceDX12 device = pass.Device as DeviceDX12;

// TODO Check root signature cache for existing root signature.

VersionedRootSignatureDesc sigDesc = new(_rootSignatureVersion);
RootSigMetaDX12 rootMeta = _rootParser.Populate(ref sigDesc, in psoDesc, pass, layout);

// Serialize the root signature.
ID3D10Blob* signature = null;
ID3D10Blob* errors = null;

HResult hr = device.Renderer.Api.SerializeVersionedRootSignature(&sigDesc, &signature, &errors);
if (!device.Log.CheckResult(hr, () => "Failed to serialize root signature"))
{
ParseErrors(pass, hr, errors);
hr.Throw();
}

// TODO Implement root signature caching - Store the serialized signature blob in cache file.

// Create the root signature.
Guid guid = ID3D12RootSignature.Guid;
void* ptr = null;
hr = device.Handle->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), &guid, &ptr);
if (!device.Log.CheckResult(hr, () => "Failed to create root signature"))
hr.Throw();

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

private unsafe void ParseErrors(ShaderPassDX12 pass, HResult hr, ID3D10Blob* errors)
{
if (errors == null)
return;

void* ptrErrors = errors->GetBufferPointer();
nuint numBytes = errors->GetBufferSize();
string strErrors = SilkMarshal.PtrToString((nint)ptrErrors, NativeStringEncoding.UTF8);
string[] errorList = strErrors.Split(_errorDelimiters, StringSplitOptions.RemoveEmptyEntries);

if (hr.IsSuccess)
{
for (int i = 0; i < errorList.Length; i++)
pass.Device.Log.Warning($"[{nameof(PipelineStateBuilderDX12)}] {errorList[i]}");
}
else
{
for (int i = 0; i < errorList.Length; i++)
pass.Device.Log.Error($"[{nameof(PipelineStateBuilderDX12)}] {errorList[i]}");
}
}
}
84 changes: 84 additions & 0 deletions Molten.Graphics.DX12/Pipeline/State/RootSignatureBuilderDX12.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using Silk.NET.Core.Native;
using Silk.NET.Direct3D12;

namespace Molten.Graphics.DX12;
internal unsafe class RootSignatureBuilderDX12
{
static readonly char[] _errorDelimiters = ['\r', '\n'];

static readonly Dictionary<D3DRootSignatureVersion, RootSignaturePopulatorDX12> _rootPopulators = new()
{
[D3DRootSignatureVersion.Version10] = new RootSigPopulator1_0(),
[D3DRootSignatureVersion.Version11] = new RootSigPopulator1_1(),
};

D3DRootSignatureVersion _rootSignatureVersion;
RootSignaturePopulatorDX12 _rootParser;

internal RootSignatureBuilderDX12(DeviceDX12 device)
{
_rootSignatureVersion = device.CapabilitiesDX12.RootSignatureVersion;

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

internal RootSignatureDX12 Build(ShaderPassDX12 pass, PipelineInputLayoutDX12 layout, ref readonly GraphicsPipelineStateDesc psoDesc)
{
DeviceDX12 device = pass.Device as DeviceDX12;

// TODO Check root signature cache for existing root signature.

VersionedRootSignatureDesc sigDesc = new(_rootSignatureVersion);
RootSigMetaDX12 rootMeta = _rootParser.Populate(ref sigDesc, in psoDesc, pass, layout);

// Serialize the root signature.
ID3D10Blob* signature = null;
ID3D10Blob* errors = null;

HResult hr = device.Renderer.Api.SerializeVersionedRootSignature(&sigDesc, &signature, &errors);
if (!device.Log.CheckResult(hr, () => "Failed to serialize root signature"))
{
ParseErrors(pass, hr, errors);
hr.Throw();
}

// TODO Implement root signature caching - Store the serialized signature blob in cache file.

// Create the root signature.
Guid guid = ID3D12RootSignature.Guid;
void* ptr = null;
hr = device.Handle->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), &guid, &ptr);
if (!device.Log.CheckResult(hr, () => "Failed to create root signature"))
hr.Throw();

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

private unsafe void ParseErrors(ShaderPassDX12 pass, HResult hr, ID3D10Blob* errors)
{
if (errors == null)
return;

void* ptrErrors = errors->GetBufferPointer();
nuint numBytes = errors->GetBufferSize();
string strErrors = SilkMarshal.PtrToString((nint)ptrErrors, NativeStringEncoding.UTF8);
string[] errorList = strErrors.Split(_errorDelimiters, StringSplitOptions.RemoveEmptyEntries);

if (hr.IsSuccess)
{
for (int i = 0; i < errorList.Length; i++)
pass.Device.Log.Warning($"[{nameof(PipelineStateBuilderDX12)}] {errorList[i]}");
}
else
{
for (int i = 0; i < errorList.Length; i++)
pass.Device.Log.Error($"[{nameof(PipelineStateBuilderDX12)}] {errorList[i]}");
}
}
}

0 comments on commit a76fd30

Please sign in to comment.