Refactor namespaces and improve resource handling
- Updated namespaces from `Ghost.UnitTest` to `Ghost.Graphics.Test` across multiple files. - Refactored `GraphicsTestWindow` to use a new `RenderSystem` configuration. - Removed deprecated `Logger` and `SerializationTest` classes. - Improved memory management in D3D12 components, including resource allocation and cleanup. - Added `[SupportedOSPlatform]` attributes to specify Windows version compatibility. - Updated `.editorconfig` settings and project references for consistency. - Enabled `nativeDebugging` in `launchSettings.json`.
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
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.D3D12_Alias;
|
||||
using static TerraFX.Aliases.D3D_Alias;
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
using Ghost.Core.Graphics;
|
||||
using Ghost.Graphics.Core;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
{
|
||||
private ComPtr<ID3D12CommandAllocator> _allocator;
|
||||
@@ -71,8 +73,6 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
_resourceAllocator = resourceAllocator;
|
||||
_descriptorAllocator = descriptorAllocator;
|
||||
|
||||
// Command lists are created in recording state, so close it
|
||||
_commandList.Get()->Close();
|
||||
_isRecording = false;
|
||||
_disposed = false;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
public ISwapChain CreateSwapChain(SwapChainDesc desc)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return new D3D12SwapChain(_resourceDatabase, _device.DXGIFactory, ((D3D12CommandQueue)_device.ComputeQueue).NativeQueue, desc);
|
||||
return new D3D12SwapChain(_resourceDatabase, _device.DXGIFactory, ((D3D12CommandQueue)_device.GraphicsQueue).NativeQueue, desc);
|
||||
}
|
||||
|
||||
public void BeginFrame()
|
||||
|
||||
@@ -9,6 +9,7 @@ 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;
|
||||
|
||||
@@ -31,6 +32,7 @@ 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.
|
||||
@@ -45,6 +47,7 @@ internal struct D3D12PipelineState : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
{
|
||||
private const int _ROOT_PARAM_COUNT =
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using System.Runtime.Versioning;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
using static TerraFX.Aliases.D3D_Alias;
|
||||
@@ -11,6 +11,7 @@ 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;
|
||||
@@ -57,31 +58,34 @@ internal unsafe class D3D12RenderDevice : IRenderDevice
|
||||
_dxgiFactory.Attach(pFactory);
|
||||
|
||||
ID3D12Device14* pDevice = default;
|
||||
ComPtr<IDXGIAdapter1> adapter = default;
|
||||
IDXGIAdapter1* pAdapter = default;
|
||||
|
||||
for (uint adapterIndex = 0;
|
||||
_dxgiFactory.Get()->EnumAdapterByGpuPreference(adapterIndex, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, adapter.IID(), adapter.ReleaseAndGetVoidAddressOf()).SUCCEEDED;
|
||||
_dxgiFactory.Get()->EnumAdapterByGpuPreference(adapterIndex, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, __uuidof<IDXGIAdapter1>(), (void**)&pAdapter).SUCCEEDED;
|
||||
adapterIndex++)
|
||||
{
|
||||
DXGI_ADAPTER_DESC1 desc = default;
|
||||
adapter.Get()->GetDesc1(&desc);
|
||||
pAdapter->GetDesc1(&desc);
|
||||
|
||||
// Don't select the Basic Render Driver adapter.
|
||||
if (desc.Flags.HasFlag(DXGI_ADAPTER_FLAG_SOFTWARE))
|
||||
{
|
||||
continue;
|
||||
goto NEXT_ITERATION;
|
||||
}
|
||||
|
||||
if (D3D12CreateDevice((IUnknown*)adapter.Get(), D3D_FEATURE_LEVEL_12_0, __uuidof(pDevice), (void**)&pDevice).SUCCEEDED)
|
||||
if (D3D12CreateDevice((IUnknown*)pAdapter, D3D_FEATURE_LEVEL_12_0, __uuidof(pDevice), (void**)&pDevice).SUCCEEDED)
|
||||
{
|
||||
_adapter = adapter.Move();
|
||||
_adapter.Attach(pAdapter);
|
||||
break;
|
||||
}
|
||||
|
||||
NEXT_ITERATION:
|
||||
pAdapter->Release();
|
||||
}
|
||||
|
||||
if (pDevice == null)
|
||||
{
|
||||
adapter.Dispose(); // Dispose the last adapter we tried. If the operation succeeded, we would have moved it.
|
||||
pAdapter->Release(); // Dispose the last adapter we tried. If the operation succeeded, we would have moved it.
|
||||
throw new PlatformNotSupportedException("Cannot create ID3D12Device with feature level 12.0");
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ using Ghost.Core.Graphics;
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.Mathematics;
|
||||
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;
|
||||
using static TerraFX.Aliases.D3D12MA_Alias;
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
@@ -16,6 +16,7 @@ using static TerraFX.Interop.DirectX.D3D12MemAlloc;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal unsafe sealed partial class D3D12ResourceAllocator
|
||||
{
|
||||
// NOTE: _MAX_BYTES may not be accurate, we need to verify it with feature level checks.
|
||||
@@ -591,6 +592,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
|
||||
{
|
||||
private readonly IFenceSynchronizer _fenceSynchronizer;
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.Collections;
|
||||
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;
|
||||
using Ghost.Graphics.Core;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
{
|
||||
internal unsafe struct ResourceRecord
|
||||
@@ -106,13 +109,13 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
|
||||
public D3D12ResourceDatabase(D3D12DescriptorAllocator descriptorAllocator)
|
||||
{
|
||||
_resources = new(64, Allocator.Persistent);
|
||||
_resources = new(64, Allocator.Persistent, AllocationOption.Clear);
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
_resourceName = new(64);
|
||||
#endif
|
||||
|
||||
_meshes = new(64, Allocator.Persistent);
|
||||
_materials = new(16, Allocator.Persistent);
|
||||
_meshes = new(64, Allocator.Persistent, AllocationOption.Clear);
|
||||
_materials = new(16, Allocator.Persistent, AllocationOption.Clear);
|
||||
_shaders = new(16);
|
||||
_shaderPasses = new(16);
|
||||
|
||||
@@ -168,7 +171,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
public bool HasResource(Handle<GPUResource> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _resources.Contain(handle.id, handle.generation);
|
||||
return _resources.Contains(handle.id, handle.generation);
|
||||
}
|
||||
|
||||
public ref ResourceRecord GetResourceInfo(Handle<GPUResource> handle)
|
||||
@@ -292,7 +295,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
public bool HasMesh(Handle<Mesh> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _meshes.Contain(handle.id, handle.generation);
|
||||
return _meshes.Contains(handle.id, handle.generation);
|
||||
}
|
||||
|
||||
public ref Mesh GetMeshReference(Handle<Mesh> handle)
|
||||
@@ -333,7 +336,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
public bool HasMaterial(Handle<Material> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _materials.Contain(handle.id, handle.generation);
|
||||
return _materials.Contains(handle.id, handle.generation);
|
||||
}
|
||||
|
||||
public ref Material GetMaterialReference(Handle<Material> handle)
|
||||
|
||||
@@ -5,6 +5,7 @@ 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;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
@@ -119,6 +120,7 @@ internal readonly struct ShaderReflectionData
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
|
||||
internal static unsafe class D3D12ShaderCompiler
|
||||
{
|
||||
private static string GetProfileString(ShaderStage stage, CompilerTier version)
|
||||
@@ -196,94 +198,109 @@ internal static unsafe class D3D12ShaderCompiler
|
||||
|
||||
public static Result<CompileResult> Compile(ref readonly CompilerConfig config, Allocator allocator, IDxcBlob** ppReflectionBlob)
|
||||
{
|
||||
// NOTE: Should we cache the compiler and utils instances for better performance?
|
||||
using ComPtr<IDxcCompiler3> compiler = default;
|
||||
using ComPtr<IDxcUtils> utils = default;
|
||||
using ComPtr<IDxcIncludeHandler> includeHandler = default;
|
||||
|
||||
// Create DXC compiler and utils
|
||||
var dxccID = CLSID.CLSID_DxcCompiler;
|
||||
var dxcuID = CLSID.CLSID_DxcUtils;
|
||||
|
||||
ThrowIfFailed(DxcCreateInstance(&dxccID, compiler.IID(), compiler.PPV()));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxcuID, utils.IID(), utils.PPV()));
|
||||
|
||||
//includeHandler.Get()->LoadSource();
|
||||
utils.Get()->CreateDefaultIncludeHandler(includeHandler.GetAddressOf());
|
||||
|
||||
// Create source blob
|
||||
using ComPtr<IDxcBlobEncoding> sourceBlob = default;
|
||||
if (utils.Get()->LoadFile(config.shaderPath.AsSpan().GetUnsafePtr(), null, sourceBlob.GetAddressOf()).FAILED)
|
||||
{
|
||||
return Result.Fail($"Failed to load shader file: {config.shaderPath}");
|
||||
}
|
||||
|
||||
var argsArray = GetCompilerArguments(in config);
|
||||
var argPtrs = stackalloc char*[argsArray.Count];
|
||||
for (var i = 0; i < argsArray.Count; i++)
|
||||
{
|
||||
argPtrs[i] = (char*)Marshal.StringToHGlobalUni(argsArray[i]);
|
||||
}
|
||||
// NOTE: Should we cache the pCompiler and pUtils instances for better performance?
|
||||
IDxcCompiler3* pCompiler = default;
|
||||
IDxcUtils* pUtils = default;
|
||||
IDxcIncludeHandler* pIncludeHandler = default;
|
||||
|
||||
try
|
||||
{
|
||||
// Compile shader
|
||||
using ComPtr<IDxcResult> result = default;
|
||||
var buffer = new DxcBuffer
|
||||
{
|
||||
Ptr = sourceBlob.Get()->GetBufferPointer(),
|
||||
Size = sourceBlob.Get()->GetBufferSize(),
|
||||
Encoding = DXC.DXC_CP_UTF8
|
||||
};
|
||||
// Create DXC pCompiler and pUtils
|
||||
var dxccID = CLSID.CLSID_DxcCompiler;
|
||||
var dxcuID = CLSID.CLSID_DxcUtils;
|
||||
|
||||
ThrowIfFailed(compiler.Get()->Compile(&buffer, argPtrs, (uint)argsArray.Count, includeHandler.Get(), result.IID(), result.PPV()));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxccID, pCompiler->IID(), (void**)&pCompiler));
|
||||
ThrowIfFailed(DxcCreateInstance(&dxcuID, pUtils->IID(), (void**)&pUtils));
|
||||
|
||||
// Check compilation result
|
||||
HRESULT hrStatus;
|
||||
result.Get()->GetStatus(&hrStatus);
|
||||
if (hrStatus.FAILED)
|
||||
{
|
||||
// Get error messages
|
||||
using ComPtr<IDxcBlobEncoding> errorBlob = default;
|
||||
result.Get()->GetErrorBuffer(errorBlob.GetAddressOf());
|
||||
//pIncludeHandler.Get()->LoadSource();
|
||||
pUtils->CreateDefaultIncludeHandler(&pIncludeHandler);
|
||||
|
||||
if (errorBlob.Get() != null)
|
||||
// Create source blob
|
||||
using ComPtr<IDxcBlobEncoding> sourceBlob = default;
|
||||
fixed (char* pPath = config.shaderPath)
|
||||
{
|
||||
if (pUtils->LoadFile(pPath, null, sourceBlob.GetAddressOf()).FAILED)
|
||||
{
|
||||
var errorMessage = Marshal.PtrToStringUni((IntPtr)errorBlob.Get()->GetBufferPointer());
|
||||
return Result.Fail($"DXC shader compilation failed:\n{errorMessage}");
|
||||
}
|
||||
else
|
||||
{
|
||||
return Result.Fail("DXC shader compilation failed with unknown error.");
|
||||
return Result.Fail($"Failed to load shader file: {config.shaderPath}");
|
||||
}
|
||||
}
|
||||
|
||||
// Get compiled bytecode
|
||||
using ComPtr<IDxcBlob> bytecodeBlob = default;
|
||||
ThrowIfFailed(result.Get()->GetResult(bytecodeBlob.GetAddressOf()));
|
||||
|
||||
// Get reflection data using DXC API
|
||||
if (ppReflectionBlob != null)
|
||||
var argsArray = GetCompilerArguments(in config);
|
||||
var argPtrs = stackalloc char*[argsArray.Count];
|
||||
for (var i = 0; i < argsArray.Count; i++)
|
||||
{
|
||||
ThrowIfFailed(result.Get()->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof<IDxcBlob>(), (void**)ppReflectionBlob, null));
|
||||
argPtrs[i] = (char*)Marshal.StringToHGlobalUni(argsArray[i]);
|
||||
}
|
||||
|
||||
var bytecodeSize = bytecodeBlob.Get()->GetBufferSize();
|
||||
var bytecode = new UnsafeArray<byte>((int)bytecodeSize, allocator);
|
||||
IDxcResult* pResult = default;
|
||||
|
||||
NativeMemory.Copy(bytecodeBlob.Get()->GetBufferPointer(), bytecode.GetUnsafePtr(), bytecodeSize);
|
||||
|
||||
return new CompileResult
|
||||
try
|
||||
{
|
||||
bytecode = bytecode,
|
||||
};
|
||||
// Compile shader
|
||||
var buffer = new DxcBuffer
|
||||
{
|
||||
Ptr = sourceBlob.Get()->GetBufferPointer(),
|
||||
Size = sourceBlob.Get()->GetBufferSize(),
|
||||
Encoding = DXC.DXC_CP_UTF8
|
||||
};
|
||||
|
||||
ThrowIfFailed(pCompiler->Compile(&buffer, argPtrs, (uint)argsArray.Count, pIncludeHandler, pResult->IID(), (void**)&pResult));
|
||||
|
||||
// Check compilation pResult
|
||||
HRESULT hrStatus;
|
||||
pResult->GetStatus(&hrStatus);
|
||||
if (hrStatus.FAILED)
|
||||
{
|
||||
// Get error messages
|
||||
using ComPtr<IDxcBlobEncoding> errorBlob = default;
|
||||
pResult->GetErrorBuffer(errorBlob.GetAddressOf());
|
||||
|
||||
if (errorBlob.Get() != null)
|
||||
{
|
||||
var errorMessage = Marshal.PtrToStringUni((IntPtr)errorBlob.Get()->GetBufferPointer());
|
||||
return Result.Fail($"DXC shader compilation failed:\n{errorMessage}");
|
||||
}
|
||||
else
|
||||
{
|
||||
return Result.Fail("DXC shader compilation failed with unknown error.");
|
||||
}
|
||||
}
|
||||
|
||||
// Get compiled bytecode
|
||||
using ComPtr<IDxcBlob> bytecodeBlob = default;
|
||||
ThrowIfFailed(pResult->GetResult(bytecodeBlob.GetAddressOf()));
|
||||
|
||||
// Get reflection data using DXC API
|
||||
if (ppReflectionBlob != null)
|
||||
{
|
||||
ThrowIfFailed(pResult->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof<IDxcBlob>(), (void**)ppReflectionBlob, null));
|
||||
}
|
||||
|
||||
var bytecodeSize = bytecodeBlob.Get()->GetBufferSize();
|
||||
var bytecode = new UnsafeArray<byte>((int)bytecodeSize, allocator);
|
||||
|
||||
NativeMemory.Copy(bytecodeBlob.Get()->GetBufferPointer(), bytecode.GetUnsafePtr(), bytecodeSize);
|
||||
|
||||
return new CompileResult
|
||||
{
|
||||
bytecode = bytecode,
|
||||
};
|
||||
}
|
||||
finally
|
||||
{
|
||||
for (var i = 0; i < argsArray.Count; i++)
|
||||
{
|
||||
Marshal.FreeHGlobal((nint)argPtrs[i]);
|
||||
}
|
||||
|
||||
pResult->Release();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
for (var i = 0; i < argsArray.Count; i++)
|
||||
{
|
||||
Marshal.FreeHGlobal((nint)argPtrs[i]);
|
||||
}
|
||||
pCompiler->Release();
|
||||
pUtils->Release();
|
||||
pIncludeHandler->Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,98 +313,108 @@ internal static unsafe class D3D12ShaderCompiler
|
||||
return Result<ShaderReflectionData>.Fail("Reflection blob is null.");
|
||||
}
|
||||
|
||||
// Create DXC utils to parse reflection data
|
||||
var dxcuID = CLSID.CLSID_DxcUtils;
|
||||
using ComPtr<IDxcUtils> utils = default;
|
||||
ThrowIfFailed(DxcCreateInstance(&dxcuID, utils.IID(), utils.PPV()));
|
||||
ComPtr<IDxcUtils> utils = default;
|
||||
ComPtr<ID3D12ShaderReflection> reflection = default;
|
||||
|
||||
// Create reflection interface from blob
|
||||
var reflectionBuffer = new DxcBuffer
|
||||
try
|
||||
{
|
||||
Ptr = reflectionBlob->GetBufferPointer(),
|
||||
Size = reflectionBlob->GetBufferSize(),
|
||||
Encoding = DXC.DXC_CP_ACP
|
||||
};
|
||||
// Create DXC pUtils to parse reflection data
|
||||
var dxcuID = CLSID.CLSID_DxcUtils;
|
||||
ThrowIfFailed(DxcCreateInstance(&dxcuID, utils.IID(), utils.PPV()));
|
||||
|
||||
using ComPtr<ID3D12ShaderReflection> reflection = default;
|
||||
ThrowIfFailed(utils.Get()->CreateReflection(&reflectionBuffer, reflection.IID(), reflection.PPV()));
|
||||
|
||||
D3D12_SHADER_DESC shaderDesc;
|
||||
ThrowIfFailed(reflection.Get()->GetDesc(&shaderDesc));
|
||||
|
||||
var reflectionData = new ShaderReflectionData();
|
||||
|
||||
for (uint i = 0; i < shaderDesc.BoundResources; i++)
|
||||
{
|
||||
D3D12_SHADER_INPUT_BIND_DESC bindDesc;
|
||||
ThrowIfFailed(reflection.Get()->GetResourceBindingDesc(i, &bindDesc));
|
||||
|
||||
var resourceName = Marshal.PtrToStringUTF8((IntPtr)bindDesc.Name);
|
||||
if (resourceName == null)
|
||||
// Create reflection interface from blob
|
||||
var reflectionBuffer = new DxcBuffer
|
||||
{
|
||||
return Result.Fail("Failed to get resource name from reflection data.");
|
||||
}
|
||||
Ptr = reflectionBlob->GetBufferPointer(),
|
||||
Size = reflectionBlob->GetBufferSize(),
|
||||
Encoding = DXC.DXC_CP_ACP
|
||||
};
|
||||
|
||||
switch (bindDesc.Type)
|
||||
ThrowIfFailed(utils.Get()->CreateReflection(&reflectionBuffer, reflection.IID(), reflection.PPV()));
|
||||
|
||||
D3D12_SHADER_DESC shaderDesc;
|
||||
ThrowIfFailed(reflection.Get()->GetDesc(&shaderDesc));
|
||||
|
||||
var reflectionData = new ShaderReflectionData();
|
||||
|
||||
for (uint i = 0; i < shaderDesc.BoundResources; i++)
|
||||
{
|
||||
case D3D_SHADER_INPUT_TYPE.D3D_SIT_CBUFFER:
|
||||
D3D12_SHADER_INPUT_BIND_DESC bindDesc;
|
||||
ThrowIfFailed(reflection.Get()->GetResourceBindingDesc(i, &bindDesc));
|
||||
|
||||
var resourceName = Marshal.PtrToStringUTF8((IntPtr)bindDesc.Name);
|
||||
if (resourceName == null)
|
||||
{
|
||||
var cbuffer = reflection.Get()->GetConstantBufferByName(bindDesc.Name);
|
||||
D3D12_SHADER_BUFFER_DESC cbufferDesc;
|
||||
ThrowIfFailed(cbuffer->GetDesc(&cbufferDesc));
|
||||
return Result.Fail("Failed to get resource name from reflection data.");
|
||||
}
|
||||
|
||||
var variables = new List<CBufferVariableInfo>((int)cbufferDesc.Variables);
|
||||
|
||||
// Now we iterate all variables for *every* cbuffer, not just b3
|
||||
for (uint j = 0; j < cbufferDesc.Variables; j++)
|
||||
switch (bindDesc.Type)
|
||||
{
|
||||
case D3D_SHADER_INPUT_TYPE.D3D_SIT_CBUFFER:
|
||||
{
|
||||
var variable = cbuffer->GetVariableByIndex(j);
|
||||
D3D12_SHADER_VARIABLE_DESC varDesc;
|
||||
variable->GetDesc(&varDesc);
|
||||
var cbuffer = reflection.Get()->GetConstantBufferByName(bindDesc.Name);
|
||||
D3D12_SHADER_BUFFER_DESC cbufferDesc;
|
||||
ThrowIfFailed(cbuffer->GetDesc(&cbufferDesc));
|
||||
|
||||
var variableName = Marshal.PtrToStringUTF8((IntPtr)varDesc.Name);
|
||||
if (variableName == null)
|
||||
var variables = new List<CBufferVariableInfo>((int)cbufferDesc.Variables);
|
||||
|
||||
// Now we iterate all variables for *every* cbuffer, not just b3
|
||||
for (uint j = 0; j < cbufferDesc.Variables; j++)
|
||||
{
|
||||
continue;
|
||||
var variable = cbuffer->GetVariableByIndex(j);
|
||||
D3D12_SHADER_VARIABLE_DESC varDesc;
|
||||
variable->GetDesc(&varDesc);
|
||||
|
||||
var variableName = Marshal.PtrToStringUTF8((IntPtr)varDesc.Name);
|
||||
if (variableName == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
variables.Add(new CBufferVariableInfo
|
||||
{
|
||||
Name = variableName,
|
||||
StartOffset = varDesc.StartOffset,
|
||||
Size = varDesc.Size
|
||||
});
|
||||
}
|
||||
|
||||
variables.Add(new CBufferVariableInfo
|
||||
reflectionData.ConstantBuffers.Add(new CBufferInfo
|
||||
{
|
||||
Name = variableName,
|
||||
StartOffset = varDesc.StartOffset,
|
||||
Size = varDesc.Size
|
||||
Name = resourceName,
|
||||
RegisterSlot = bindDesc.BindPoint,
|
||||
RegisterSpace = bindDesc.Space,
|
||||
SizeInBytes = cbufferDesc.Size,
|
||||
Variables = variables
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
reflectionData.ConstantBuffers.Add(new CBufferInfo
|
||||
// NOTE: Currently we do not support resource bindings yet, everything access through bindless heaps.
|
||||
default:
|
||||
{
|
||||
Name = resourceName,
|
||||
RegisterSlot = bindDesc.BindPoint,
|
||||
RegisterSpace = bindDesc.Space,
|
||||
SizeInBytes = cbufferDesc.Size,
|
||||
Variables = variables
|
||||
});
|
||||
reflectionData.OtherResources.Add(new ResourceBindingInfo
|
||||
{
|
||||
Name = resourceName,
|
||||
Type = bindDesc.Type,
|
||||
BindPoint = bindDesc.BindPoint,
|
||||
BindCount = bindDesc.BindCount,
|
||||
Space = bindDesc.Space
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: Currently we do not support resource bindings yet, everything access through bindless heaps.
|
||||
default:
|
||||
{
|
||||
reflectionData.OtherResources.Add(new ResourceBindingInfo
|
||||
{
|
||||
Name = resourceName,
|
||||
Type = bindDesc.Type,
|
||||
BindPoint = bindDesc.BindPoint,
|
||||
BindCount = bindDesc.BindCount,
|
||||
Space = bindDesc.Space
|
||||
});
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reflectionData;
|
||||
return reflectionData;
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
utils.Dispose();
|
||||
reflection.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,18 +71,18 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
Stereo = false,
|
||||
};
|
||||
|
||||
using ComPtr<IDXGISwapChain1> tempSwapChain = default;
|
||||
IDXGISwapChain1* pTempSwapChain = default;
|
||||
|
||||
switch (desc.target.type)
|
||||
{
|
||||
case SwapChainTargetType.Composition:
|
||||
pFactory->CreateSwapChainForComposition((IUnknown*)commandQueue, &swapChainDesc, null, tempSwapChain.GetAddressOf());
|
||||
ThrowIfFailed(pFactory->CreateSwapChainForComposition((IUnknown*)commandQueue, &swapChainDesc, null, &pTempSwapChain));
|
||||
|
||||
// Set the composition surface
|
||||
if (desc.target.compositionSurface != null)
|
||||
{
|
||||
using var swapChainPanelNative = ISwapChainPanelNative.FromSwapChainPanel(desc.target.compositionSurface);
|
||||
swapChainPanelNative.SetSwapChain((IntPtr)tempSwapChain.Get());
|
||||
swapChainPanelNative.SetSwapChain((IntPtr)pTempSwapChain);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -98,7 +98,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
&swapChainDesc,
|
||||
&swapChainFullscreenDesc,
|
||||
null,
|
||||
tempSwapChain.GetAddressOf());
|
||||
&pTempSwapChain);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -106,7 +106,8 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
}
|
||||
|
||||
IDXGISwapChain4* pSwapChain = default;
|
||||
tempSwapChain.Get()->QueryInterface(__uuidof(pSwapChain), (void**)&pSwapChain);
|
||||
pTempSwapChain->QueryInterface(__uuidof(pSwapChain), (void**)&pSwapChain);
|
||||
pTempSwapChain->Release();
|
||||
|
||||
_swapChain.Attach(pSwapChain);
|
||||
}
|
||||
|
||||
@@ -288,7 +288,15 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
_heap.Attach(pHeap);
|
||||
|
||||
_startCpuHandle = _heap.Get()->GetCPUDescriptorHandleForHeapStart();
|
||||
_allocatedDescriptors.Resize(numDescriptors);
|
||||
|
||||
if (!_allocatedDescriptors.IsCreated)
|
||||
{
|
||||
_allocatedDescriptors = new UnsafeArray<bool>(numDescriptors, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||
}
|
||||
else
|
||||
{
|
||||
_allocatedDescriptors.Resize(numDescriptors);
|
||||
}
|
||||
|
||||
if (ShaderVisible)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user