forked from Misaki/GhostEngine
Fixed bugs in rendering.
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Core.Graphics;
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Versioning;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
using static TerraFX.Aliases.D3D_Alias;
|
||||
@@ -15,7 +13,6 @@ using static TerraFX.Aliases.DXGI_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
{
|
||||
private ComPtr<ID3D12CommandAllocator> _allocator;
|
||||
|
||||
@@ -49,6 +49,8 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
CommandBufferType.Copy);
|
||||
|
||||
_renderers = ImmutableArray<IRenderer>.Empty;
|
||||
|
||||
_pipelineLibrary.InitializeLibrary(null);
|
||||
}
|
||||
|
||||
~D3D12GraphicsEngine()
|
||||
@@ -59,10 +61,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(D3D12GraphicsEngine));
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
}
|
||||
|
||||
public IRenderer CreateRenderer()
|
||||
|
||||
@@ -9,7 +9,6 @@ using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using Misaki.HighPerformance.Utilities;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
@@ -32,7 +31,6 @@ internal struct D3D12GraphicsCompiledResult : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal struct D3D12PipelineState : IDisposable
|
||||
{
|
||||
// NOTE: This is just a temporary cache for compiled shader code. We will implement a proper disk cache later.
|
||||
@@ -47,10 +45,9 @@ internal struct D3D12PipelineState : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
{
|
||||
private const int _ROOT_PARAM_COUNT =
|
||||
private const int rootParamCount =
|
||||
#if USE_TRADITIONAL_BINDLESS
|
||||
6
|
||||
#else
|
||||
@@ -83,7 +80,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
_defaultRootSignature = default;
|
||||
|
||||
// NOTE: Since we are targeting SM 6.6, we can use ResourceDescriptorHeap and SamplerDescriptorHeap directly without needing to set up viewGroup tables.
|
||||
var rootParameters = stackalloc D3D12_ROOT_PARAMETER1[_ROOT_PARAM_COUNT];
|
||||
var rootParameters = stackalloc D3D12_ROOT_PARAMETER1[rootParamCount];
|
||||
rootParameters[0] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
@@ -146,7 +143,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
|
||||
var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC1
|
||||
{
|
||||
NumParameters = _ROOT_PARAM_COUNT,
|
||||
NumParameters = rootParamCount,
|
||||
pParameters = rootParameters,
|
||||
NumStaticSamplers = 0,
|
||||
pStaticSamplers = null,
|
||||
@@ -180,7 +177,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
_defaultRootSignature.Attach(pRootSignature);
|
||||
}
|
||||
|
||||
public void LoadLibraryFromDisk(string? filePath)
|
||||
public void InitializeLibrary(string? filePath)
|
||||
{
|
||||
ID3D12PipelineLibrary1* pLibrary = default;
|
||||
|
||||
@@ -219,9 +216,9 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
|
||||
private static void ValidateReflectionData(ShaderReflectionData reflectionData)
|
||||
{
|
||||
if (reflectionData.ConstantBuffers.Count != _ROOT_PARAM_COUNT)
|
||||
if (reflectionData.ConstantBuffers.Count != rootParamCount)
|
||||
{
|
||||
throw new InvalidOperationException($"Shader reflection data has {reflectionData.ConstantBuffers.Count} constant buffers, expected {_ROOT_PARAM_COUNT}");
|
||||
throw new InvalidOperationException($"Shader reflection data has {reflectionData.ConstantBuffers.Count} constant buffers, expected {rootParamCount}");
|
||||
}
|
||||
|
||||
if (reflectionData.OtherResources.Count != 0)
|
||||
@@ -240,13 +237,16 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: This does not include generated code. This will cause a root signature mismatch.
|
||||
var result = D3D12ShaderCompiler.Compile(ref config, Allocator.Persistent, &reflectionBlob).GetValueOrThrow();
|
||||
|
||||
#if false
|
||||
if (reflectionBlob != null)
|
||||
{
|
||||
var reflection = D3D12ShaderCompiler.PerformDXCReflection(reflectionBlob).GetValueOrThrow();
|
||||
ValidateReflectionData(reflection);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -415,15 +415,16 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
existing.compileResult = compiled;
|
||||
existing.psoDesc = desc;
|
||||
|
||||
var meshStream = new CD3DX12_PIPELINE_MESH_STATE_STREAM(in desc);
|
||||
var streamDesc = new D3D12_PIPELINE_STATE_STREAM_DESC
|
||||
{
|
||||
pPipelineStateSubobjectStream = &desc,
|
||||
SizeInBytes = (nuint)sizeof(D3DX12_MESH_SHADER_PIPELINE_STATE_DESC)
|
||||
pPipelineStateSubobjectStream = &meshStream,
|
||||
SizeInBytes = (nuint)sizeof(CD3DX12_PIPELINE_MESH_STATE_STREAM)
|
||||
};
|
||||
|
||||
ID3D12PipelineState* pPipelineState = default;
|
||||
|
||||
char* pKeyStr = stackalloc char[GraphicsPipelineKey.KEY_STRING_LENGTH];
|
||||
var pKeyStr = stackalloc char[GraphicsPipelineKey.KEY_STRING_LENGTH];
|
||||
var keySpan = new Span<char>(pKeyStr, GraphicsPipelineKey.KEY_STRING_LENGTH);
|
||||
key.GetString(keySpan).ThrowIfFailed();
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace Ghost.Graphics.D3D12;
|
||||
/// <summary>
|
||||
/// D3D12 implementation of the render device interface
|
||||
/// </summary>
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal unsafe class D3D12RenderDevice : IRenderDevice
|
||||
{
|
||||
private ComPtr<IDXGIFactory7> _dxgiFactory;
|
||||
|
||||
@@ -6,7 +6,6 @@ using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using Misaki.HighPerformance.Mathematics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Versioning;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
@@ -16,8 +15,7 @@ using static TerraFX.Interop.DirectX.D3D12MemAlloc;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal unsafe sealed partial class D3D12ResourceAllocator
|
||||
internal sealed unsafe partial class D3D12ResourceAllocator
|
||||
{
|
||||
// NOTE: _MAX_BYTES may not be accurate, we need to verify it with feature level checks.
|
||||
private const uint _MAX_BYTES = D3D12_REQ_RESOURCE_SIZE_IN_MEGABYTES_EXPRESSION_A_TERM * 1024u * 1024u;
|
||||
@@ -593,7 +591,7 @@ internal unsafe sealed partial class D3D12ResourceAllocator
|
||||
// TODO: Thread safety for resource allocator
|
||||
// A common solution is to use ticket. Each allocation request create a ticket and put it into a thread-safe queue. A dedicated thread process the queue and fulfill the requests.
|
||||
|
||||
internal unsafe sealed partial class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
{
|
||||
private readonly IFenceSynchronizer _fenceSynchronizer;
|
||||
private readonly D3D12RenderDevice _device;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.Collections;
|
||||
@@ -7,13 +6,11 @@ using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
{
|
||||
internal unsafe struct ResourceRecord
|
||||
@@ -100,8 +97,8 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
private readonly Dictionary<Handle<GPUResource>, string> _resourceName;
|
||||
#endif
|
||||
|
||||
private readonly UnsafeSlotMap<Mesh> _meshes;
|
||||
private readonly UnsafeSlotMap<Material> _materials;
|
||||
private UnsafeSlotMap<Mesh> _meshes;
|
||||
private UnsafeSlotMap<Material> _materials;
|
||||
private readonly DynamicArray<Shader?> _shaders; // NOTE: We use a simple list since shader is not frequently added/removed. This can save 4 bytes for each ecs component.
|
||||
private readonly Dictionary<ShaderPassKey, ShaderPass> _shaderPasses; // NOTE: The reason we use Dictionary here is that ShaderPassKey is a presistence identifier across multiple application sessions.
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using TerraFX.Interop.DirectX;
|
||||
@@ -11,7 +10,7 @@ using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
internal unsafe struct CompileResult : IDisposable
|
||||
internal struct CompileResult : IDisposable
|
||||
{
|
||||
public UnsafeArray<byte> bytecode;
|
||||
|
||||
@@ -120,7 +119,6 @@ internal readonly struct ShaderReflectionData
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal static unsafe class D3D12ShaderCompiler
|
||||
{
|
||||
private static string GetProfileString(ShaderStage stage, CompilerTier version)
|
||||
@@ -209,8 +207,8 @@ internal static unsafe class D3D12ShaderCompiler
|
||||
var dxccID = CLSID.CLSID_DxcCompiler;
|
||||
var dxcuID = CLSID.CLSID_DxcUtils;
|
||||
|
||||
ThrowIfFailed(DxcCreateInstance(&dxccID, pCompiler->IID(), (void**)&pCompiler));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxcuID, pUtils->IID(), (void**)&pUtils));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxccID, __uuidof(pCompiler), (void**)&pCompiler));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxcuID, __uuidof(pUtils), (void**)&pUtils));
|
||||
|
||||
//pIncludeHandler.Get()->LoadSource();
|
||||
pUtils->CreateDefaultIncludeHandler(&pIncludeHandler);
|
||||
@@ -218,7 +216,7 @@ internal static unsafe class D3D12ShaderCompiler
|
||||
// Create source blob
|
||||
using ComPtr<IDxcBlobEncoding> sourceBlob = default;
|
||||
fixed (char* pPath = config.shaderPath)
|
||||
{
|
||||
{
|
||||
if (pUtils->LoadFile(pPath, null, sourceBlob.GetAddressOf()).FAILED)
|
||||
{
|
||||
return Result.Fail($"Failed to load shader file: {config.shaderPath}");
|
||||
@@ -244,7 +242,7 @@ internal static unsafe class D3D12ShaderCompiler
|
||||
Encoding = DXC.DXC_CP_UTF8
|
||||
};
|
||||
|
||||
ThrowIfFailed(pCompiler->Compile(&buffer, argPtrs, (uint)argsArray.Count, pIncludeHandler, pResult->IID(), (void**)&pResult));
|
||||
ThrowIfFailed(pCompiler->Compile(&buffer, argPtrs, (uint)argsArray.Count, pIncludeHandler, __uuidof(pResult), (void**)&pResult));
|
||||
|
||||
// Check compilation pResult
|
||||
HRESULT hrStatus;
|
||||
@@ -257,7 +255,7 @@ internal static unsafe class D3D12ShaderCompiler
|
||||
|
||||
if (errorBlob.Get() != null)
|
||||
{
|
||||
var errorMessage = Marshal.PtrToStringUni((IntPtr)errorBlob.Get()->GetBufferPointer());
|
||||
var errorMessage = Marshal.PtrToStringUTF8((IntPtr)errorBlob.Get()->GetBufferPointer());
|
||||
return Result.Fail($"DXC shader compilation failed:\n{errorMessage}");
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,6 +2,7 @@ using Ghost.Graphics.RHI;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12.Utilities;
|
||||
|
||||
@@ -31,12 +32,13 @@ internal unsafe static class D3D12Utility
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
TextureFormat.R8G8B8A8_UNorm => DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
TextureFormat.B8G8R8A8_UNorm => DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
TextureFormat.R16G16B16A16_Float => DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
TextureFormat.R32G32B32A32_Float => DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
TextureFormat.D32_Float => DXGI_FORMAT.DXGI_FORMAT_D32_FLOAT,
|
||||
TextureFormat.Unknown => DXGI_FORMAT_UNKNOWN,
|
||||
TextureFormat.R8G8B8A8_UNorm => DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
TextureFormat.B8G8R8A8_UNorm => DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
TextureFormat.R16G16B16A16_Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
TextureFormat.R32G32B32A32_Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
TextureFormat.D32_Float => DXGI_FORMAT_D32_FLOAT,
|
||||
_ => throw new NotSupportedException($"Texture format {format} is not supported."),
|
||||
};
|
||||
}
|
||||
@@ -45,12 +47,12 @@ internal unsafe static class D3D12Utility
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM => TextureFormat.R8G8B8A8_UNorm,
|
||||
DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM => TextureFormat.B8G8R8A8_UNorm,
|
||||
DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT => TextureFormat.R16G16B16A16_Float,
|
||||
DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT => TextureFormat.R32G32B32A32_Float,
|
||||
DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt,
|
||||
DXGI_FORMAT.DXGI_FORMAT_D32_FLOAT => TextureFormat.D32_Float,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM => TextureFormat.R8G8B8A8_UNorm,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM => TextureFormat.B8G8R8A8_UNorm,
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT => TextureFormat.R16G16B16A16_Float,
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT => TextureFormat.R32G32B32A32_Float,
|
||||
DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt,
|
||||
DXGI_FORMAT_D32_FLOAT => TextureFormat.D32_Float,
|
||||
_ => TextureFormat.Unknown,
|
||||
};
|
||||
}
|
||||
@@ -59,16 +61,16 @@ internal unsafe static class D3D12Utility
|
||||
{
|
||||
return state switch
|
||||
{
|
||||
ResourceState.Common or ResourceState.Present => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON,
|
||||
ResourceState.VertexAndConstantBuffer => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
|
||||
ResourceState.IndexBuffer => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_INDEX_BUFFER,
|
||||
ResourceState.RenderTarget => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
ResourceState.UnorderedAccess => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
||||
ResourceState.DepthWrite => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_WRITE,
|
||||
ResourceState.DepthRead => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_READ,
|
||||
ResourceState.PixelShaderResource => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
ResourceState.CopyDest => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
ResourceState.CopySource => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_SOURCE,
|
||||
ResourceState.Common or ResourceState.Present => D3D12_RESOURCE_STATE_COMMON,
|
||||
ResourceState.VertexAndConstantBuffer => D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
|
||||
ResourceState.IndexBuffer => D3D12_RESOURCE_STATE_INDEX_BUFFER,
|
||||
ResourceState.RenderTarget => D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
ResourceState.UnorderedAccess => D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
|
||||
ResourceState.DepthWrite => D3D12_RESOURCE_STATE_DEPTH_WRITE,
|
||||
ResourceState.DepthRead => D3D12_RESOURCE_STATE_DEPTH_READ,
|
||||
ResourceState.PixelShaderResource => D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
ResourceState.CopyDest => D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
ResourceState.CopySource => D3D12_RESOURCE_STATE_COPY_SOURCE,
|
||||
_ => throw new ArgumentException($"Unknown resource state: {state}")
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user