Fixed bugs in rendering.

This commit is contained in:
2025-11-12 20:31:37 +09:00
parent 6cf2e35a9b
commit 708b8cd065
18 changed files with 102 additions and 90 deletions

View File

@@ -6,12 +6,7 @@ using TerraFX.Interop.Windows;
namespace Ghost.Core.Utilities; namespace Ghost.Core.Utilities;
internal static partial class Win32Utility [SupportedOSPlatform("windows10.0.19041.0")]
{
public const string OS_SUPPORTED_VERSION = "windows10.0.19041.0";
}
[SupportedOSPlatform(OS_SUPPORTED_VERSION)]
internal static unsafe partial class Win32Utility internal static unsafe partial class Win32Utility
{ {
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]

View File

@@ -6,7 +6,7 @@ namespace Ghost.Entities.Query;
public struct QueryFilter : IDisposable public struct QueryFilter : IDisposable
{ {
private readonly Stack.Scope _scope; //private readonly Stack.Scope _scope;
internal UnsafeList<TypeHandle> _all; internal UnsafeList<TypeHandle> _all;
internal UnsafeList<TypeHandle> _any; internal UnsafeList<TypeHandle> _any;
@@ -15,7 +15,7 @@ public struct QueryFilter : IDisposable
public QueryFilter() public QueryFilter()
{ {
_scope = AllocationManager.CreateStackScope(); //_scope = AllocationManager.CreateStackScope();
_all = new UnsafeList<TypeHandle>(4, Allocator.Stack); _all = new UnsafeList<TypeHandle>(4, Allocator.Stack);
_any = new UnsafeList<TypeHandle>(4, Allocator.Stack); _any = new UnsafeList<TypeHandle>(4, Allocator.Stack);
@@ -92,6 +92,6 @@ public struct QueryFilter : IDisposable
public readonly void Dispose() public readonly void Dispose()
{ {
_scope.Dispose(); //_scope.Dispose();
} }
} }

View File

@@ -2,6 +2,7 @@ using Ghost.Graphics.Test.Windows;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer; using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
using System.Runtime.InteropServices;
// To learn more about WinUI, the WinUI project structure, // To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info. // and more about our project templates, see: http://aka.ms/winui-project-info.
@@ -23,12 +24,31 @@ public partial class UnitTestApp : Application
InitializeComponent(); InitializeComponent();
} }
private static void LoadDll()
{
var currentDir = AppContext.BaseDirectory;
var platform = OperatingSystem.IsWindows() ? "win" :
OperatingSystem.IsLinux() ? "linux" :
OperatingSystem.IsMacOS() ? "osx" : "unknown";
var arch = Environment.Is64BitProcess ? "x64" : "x86";
var nativeDllDir = Path.Combine(currentDir, "runtime", platform + "-" + arch, "native");
if (Directory.Exists(nativeDllDir))
{
foreach (var dll in Directory.EnumerateFiles(nativeDllDir, "*.dll"))
{
NativeLibrary.Load(dll);
}
}
}
/// <summary> /// <summary>
/// Invoked when the application is launched. /// Invoked when the application is launched.
/// </summary> /// </summary>
/// <param name="args">Details about the launch request and process.</param> /// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs args) protected override void OnLaunched(LaunchActivatedEventArgs args)
{ {
LoadDll();
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI(); Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
_window = new GraphicsTestWindow(); _window = new GraphicsTestWindow();

View File

@@ -4,11 +4,15 @@ global using static TerraFX.Interop.DirectX.DXGI;
global using static TerraFX.Interop.Windows.Windows; global using static TerraFX.Interop.Windows.Windows;
using Ghost.Core.Attributes; using Ghost.Core.Attributes;
using Ghost.Core.Utilities;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
[assembly: InternalsVisibleTo("Ghost.Engine")] [assembly: InternalsVisibleTo("Ghost.Engine")]
[assembly: InternalsVisibleTo("Ghost.Editor")] [assembly: InternalsVisibleTo("Ghost.Editor")]
[assembly: InternalsVisibleTo("Ghost.Editor.Core")] [assembly: InternalsVisibleTo("Ghost.Editor.Core")]
[assembly: InternalsVisibleTo("Ghost.Graphics.Test")] [assembly: InternalsVisibleTo("Ghost.Graphics.Test")]
[assembly: SupportedOSPlatform("windows10.0.19041.0")]
[assembly: EngineAssembly] [assembly: EngineAssembly]

View File

@@ -1,12 +1,10 @@
using Ghost.Core; using Ghost.Core;
using Ghost.Core.Graphics; using Ghost.Core.Graphics;
using Ghost.Core.Utilities;
using Ghost.Graphics.Core; using Ghost.Graphics.Core;
using Ghost.Graphics.D3D12.Utilities; using Ghost.Graphics.D3D12.Utilities;
using Ghost.Graphics.RHI; using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Utilities; using Misaki.HighPerformance.LowLevel.Utilities;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX; using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows; using TerraFX.Interop.Windows;
using static TerraFX.Aliases.D3D_Alias; using static TerraFX.Aliases.D3D_Alias;
@@ -15,7 +13,6 @@ using static TerraFX.Aliases.DXGI_Alias;
namespace Ghost.Graphics.D3D12; namespace Ghost.Graphics.D3D12;
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal unsafe class D3D12CommandBuffer : ICommandBuffer internal unsafe class D3D12CommandBuffer : ICommandBuffer
{ {
private ComPtr<ID3D12CommandAllocator> _allocator; private ComPtr<ID3D12CommandAllocator> _allocator;

View File

@@ -49,6 +49,8 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
CommandBufferType.Copy); CommandBufferType.Copy);
_renderers = ImmutableArray<IRenderer>.Empty; _renderers = ImmutableArray<IRenderer>.Empty;
_pipelineLibrary.InitializeLibrary(null);
} }
~D3D12GraphicsEngine() ~D3D12GraphicsEngine()
@@ -59,10 +61,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ThrowIfDisposed() private void ThrowIfDisposed()
{ {
if (_disposed) ObjectDisposedException.ThrowIf(_disposed, this);
{
throw new ObjectDisposedException(nameof(D3D12GraphicsEngine));
}
} }
public IRenderer CreateRenderer() public IRenderer CreateRenderer()

View File

@@ -9,7 +9,6 @@ using Misaki.HighPerformance.LowLevel.Utilities;
using Misaki.HighPerformance.Utilities; using Misaki.HighPerformance.Utilities;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX; using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows; using TerraFX.Interop.Windows;
@@ -32,7 +31,6 @@ internal struct D3D12GraphicsCompiledResult : IDisposable
} }
} }
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal struct D3D12PipelineState : IDisposable internal struct D3D12PipelineState : IDisposable
{ {
// NOTE: This is just a temporary cache for compiled shader code. We will implement a proper disk cache later. // 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 internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
{ {
private const int _ROOT_PARAM_COUNT = private const int rootParamCount =
#if USE_TRADITIONAL_BINDLESS #if USE_TRADITIONAL_BINDLESS
6 6
#else #else
@@ -83,7 +80,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
_defaultRootSignature = default; _defaultRootSignature = default;
// NOTE: Since we are targeting SM 6.6, we can use ResourceDescriptorHeap and SamplerDescriptorHeap directly without needing to set up viewGroup tables. // 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 rootParameters[0] = new D3D12_ROOT_PARAMETER1
{ {
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV, ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
@@ -146,7 +143,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC1 var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC1
{ {
NumParameters = _ROOT_PARAM_COUNT, NumParameters = rootParamCount,
pParameters = rootParameters, pParameters = rootParameters,
NumStaticSamplers = 0, NumStaticSamplers = 0,
pStaticSamplers = null, pStaticSamplers = null,
@@ -180,7 +177,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
_defaultRootSignature.Attach(pRootSignature); _defaultRootSignature.Attach(pRootSignature);
} }
public void LoadLibraryFromDisk(string? filePath) public void InitializeLibrary(string? filePath)
{ {
ID3D12PipelineLibrary1* pLibrary = default; ID3D12PipelineLibrary1* pLibrary = default;
@@ -219,9 +216,9 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
private static void ValidateReflectionData(ShaderReflectionData reflectionData) 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) if (reflectionData.OtherResources.Count != 0)
@@ -240,13 +237,16 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
try 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(); var result = D3D12ShaderCompiler.Compile(ref config, Allocator.Persistent, &reflectionBlob).GetValueOrThrow();
#if false
if (reflectionBlob != null) if (reflectionBlob != null)
{ {
var reflection = D3D12ShaderCompiler.PerformDXCReflection(reflectionBlob).GetValueOrThrow(); var reflection = D3D12ShaderCompiler.PerformDXCReflection(reflectionBlob).GetValueOrThrow();
ValidateReflectionData(reflection); ValidateReflectionData(reflection);
} }
#endif
return result; return result;
} }
@@ -415,15 +415,16 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
existing.compileResult = compiled; existing.compileResult = compiled;
existing.psoDesc = desc; existing.psoDesc = desc;
var meshStream = new CD3DX12_PIPELINE_MESH_STATE_STREAM(in desc);
var streamDesc = new D3D12_PIPELINE_STATE_STREAM_DESC var streamDesc = new D3D12_PIPELINE_STATE_STREAM_DESC
{ {
pPipelineStateSubobjectStream = &desc, pPipelineStateSubobjectStream = &meshStream,
SizeInBytes = (nuint)sizeof(D3DX12_MESH_SHADER_PIPELINE_STATE_DESC) SizeInBytes = (nuint)sizeof(CD3DX12_PIPELINE_MESH_STATE_STREAM)
}; };
ID3D12PipelineState* pPipelineState = default; 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); var keySpan = new Span<char>(pKeyStr, GraphicsPipelineKey.KEY_STRING_LENGTH);
key.GetString(keySpan).ThrowIfFailed(); key.GetString(keySpan).ThrowIfFailed();

View File

@@ -11,7 +11,6 @@ namespace Ghost.Graphics.D3D12;
/// <summary> /// <summary>
/// D3D12 implementation of the render device interface /// D3D12 implementation of the render device interface
/// </summary> /// </summary>
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal unsafe class D3D12RenderDevice : IRenderDevice internal unsafe class D3D12RenderDevice : IRenderDevice
{ {
private ComPtr<IDXGIFactory7> _dxgiFactory; private ComPtr<IDXGIFactory7> _dxgiFactory;

View File

@@ -6,7 +6,6 @@ using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Collections; using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.Mathematics; using Misaki.HighPerformance.Mathematics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX; using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows; using TerraFX.Interop.Windows;
using static TerraFX.Aliases.D3D12_Alias; using static TerraFX.Aliases.D3D12_Alias;
@@ -16,8 +15,7 @@ using static TerraFX.Interop.DirectX.D3D12MemAlloc;
namespace Ghost.Graphics.D3D12; namespace Ghost.Graphics.D3D12;
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)] internal sealed unsafe partial class D3D12ResourceAllocator
internal unsafe sealed partial class D3D12ResourceAllocator
{ {
// NOTE: _MAX_BYTES may not be accurate, we need to verify it with feature level checks. // 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; 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 // 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. // 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 IFenceSynchronizer _fenceSynchronizer;
private readonly D3D12RenderDevice _device; private readonly D3D12RenderDevice _device;

View File

@@ -1,5 +1,4 @@
using Ghost.Core; using Ghost.Core;
using Ghost.Core.Utilities;
using Ghost.Graphics.Core; using Ghost.Graphics.Core;
using Ghost.Graphics.RHI; using Ghost.Graphics.RHI;
using Misaki.HighPerformance.Collections; using Misaki.HighPerformance.Collections;
@@ -7,13 +6,11 @@ using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections; using Misaki.HighPerformance.LowLevel.Collections;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using TerraFX.Interop.DirectX; using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows; using TerraFX.Interop.Windows;
namespace Ghost.Graphics.D3D12; namespace Ghost.Graphics.D3D12;
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
{ {
internal unsafe struct ResourceRecord internal unsafe struct ResourceRecord
@@ -100,8 +97,8 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
private readonly Dictionary<Handle<GPUResource>, string> _resourceName; private readonly Dictionary<Handle<GPUResource>, string> _resourceName;
#endif #endif
private readonly UnsafeSlotMap<Mesh> _meshes; private UnsafeSlotMap<Mesh> _meshes;
private readonly UnsafeSlotMap<Material> _materials; 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 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. private readonly Dictionary<ShaderPassKey, ShaderPass> _shaderPasses; // NOTE: The reason we use Dictionary here is that ShaderPassKey is a presistence identifier across multiple application sessions.

View File

@@ -3,7 +3,6 @@ using Ghost.Core.Utilities;
using Ghost.Graphics.RHI; using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections; using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using TerraFX.Interop.DirectX; using TerraFX.Interop.DirectX;
@@ -11,7 +10,7 @@ using TerraFX.Interop.Windows;
namespace Ghost.Graphics.D3D12; namespace Ghost.Graphics.D3D12;
internal unsafe struct CompileResult : IDisposable internal struct CompileResult : IDisposable
{ {
public UnsafeArray<byte> bytecode; public UnsafeArray<byte> bytecode;
@@ -120,7 +119,6 @@ internal readonly struct ShaderReflectionData
} }
} }
[SupportedOSPlatform(Win32Utility.OS_SUPPORTED_VERSION)]
internal static unsafe class D3D12ShaderCompiler internal static unsafe class D3D12ShaderCompiler
{ {
private static string GetProfileString(ShaderStage stage, CompilerTier version) private static string GetProfileString(ShaderStage stage, CompilerTier version)
@@ -209,8 +207,8 @@ internal static unsafe class D3D12ShaderCompiler
var dxccID = CLSID.CLSID_DxcCompiler; var dxccID = CLSID.CLSID_DxcCompiler;
var dxcuID = CLSID.CLSID_DxcUtils; var dxcuID = CLSID.CLSID_DxcUtils;
ThrowIfFailed(DxcCreateInstance(&dxccID, pCompiler->IID(), (void**)&pCompiler)); ThrowIfFailed(DxcCreateInstance(&dxccID, __uuidof(pCompiler), (void**)&pCompiler));
ThrowIfFailed(DxcCreateInstance(&dxcuID, pUtils->IID(), (void**)&pUtils)); ThrowIfFailed(DxcCreateInstance(&dxcuID, __uuidof(pUtils), (void**)&pUtils));
//pIncludeHandler.Get()->LoadSource(); //pIncludeHandler.Get()->LoadSource();
pUtils->CreateDefaultIncludeHandler(&pIncludeHandler); pUtils->CreateDefaultIncludeHandler(&pIncludeHandler);
@@ -218,7 +216,7 @@ internal static unsafe class D3D12ShaderCompiler
// Create source blob // Create source blob
using ComPtr<IDxcBlobEncoding> sourceBlob = default; using ComPtr<IDxcBlobEncoding> sourceBlob = default;
fixed (char* pPath = config.shaderPath) fixed (char* pPath = config.shaderPath)
{ {
if (pUtils->LoadFile(pPath, null, sourceBlob.GetAddressOf()).FAILED) if (pUtils->LoadFile(pPath, null, sourceBlob.GetAddressOf()).FAILED)
{ {
return Result.Fail($"Failed to load shader file: {config.shaderPath}"); return Result.Fail($"Failed to load shader file: {config.shaderPath}");
@@ -244,7 +242,7 @@ internal static unsafe class D3D12ShaderCompiler
Encoding = DXC.DXC_CP_UTF8 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 // Check compilation pResult
HRESULT hrStatus; HRESULT hrStatus;
@@ -257,7 +255,7 @@ internal static unsafe class D3D12ShaderCompiler
if (errorBlob.Get() != null) 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}"); return Result.Fail($"DXC shader compilation failed:\n{errorMessage}");
} }
else else

View File

@@ -2,6 +2,7 @@ using Ghost.Graphics.RHI;
using TerraFX.Interop.DirectX; using TerraFX.Interop.DirectX;
using static TerraFX.Aliases.D3D12_Alias; using static TerraFX.Aliases.D3D12_Alias;
using static TerraFX.Aliases.DXGI_Alias;
namespace Ghost.Graphics.D3D12.Utilities; namespace Ghost.Graphics.D3D12.Utilities;
@@ -31,12 +32,13 @@ internal unsafe static class D3D12Utility
{ {
return format switch return format switch
{ {
TextureFormat.R8G8B8A8_UNorm => DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM, TextureFormat.Unknown => DXGI_FORMAT_UNKNOWN,
TextureFormat.B8G8R8A8_UNorm => DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM, TextureFormat.R8G8B8A8_UNorm => DXGI_FORMAT_R8G8B8A8_UNORM,
TextureFormat.R16G16B16A16_Float => DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT, TextureFormat.B8G8R8A8_UNorm => DXGI_FORMAT_B8G8R8A8_UNORM,
TextureFormat.R32G32B32A32_Float => DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT, TextureFormat.R16G16B16A16_Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT, TextureFormat.R32G32B32A32_Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
TextureFormat.D32_Float => DXGI_FORMAT.DXGI_FORMAT_D32_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."), _ => throw new NotSupportedException($"Texture format {format} is not supported."),
}; };
} }
@@ -45,12 +47,12 @@ internal unsafe static class D3D12Utility
{ {
return format switch return format switch
{ {
DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM => TextureFormat.R8G8B8A8_UNorm, DXGI_FORMAT_R8G8B8A8_UNORM => TextureFormat.R8G8B8A8_UNorm,
DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM => TextureFormat.B8G8R8A8_UNorm, DXGI_FORMAT_B8G8R8A8_UNORM => TextureFormat.B8G8R8A8_UNorm,
DXGI_FORMAT.DXGI_FORMAT_R16G16B16A16_FLOAT => TextureFormat.R16G16B16A16_Float, DXGI_FORMAT_R16G16B16A16_FLOAT => TextureFormat.R16G16B16A16_Float,
DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT => TextureFormat.R32G32B32A32_Float, DXGI_FORMAT_R32G32B32A32_FLOAT => TextureFormat.R32G32B32A32_Float,
DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt, DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt,
DXGI_FORMAT.DXGI_FORMAT_D32_FLOAT => TextureFormat.D32_Float, DXGI_FORMAT_D32_FLOAT => TextureFormat.D32_Float,
_ => TextureFormat.Unknown, _ => TextureFormat.Unknown,
}; };
} }
@@ -59,16 +61,16 @@ internal unsafe static class D3D12Utility
{ {
return state switch return state switch
{ {
ResourceState.Common or ResourceState.Present => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON, ResourceState.Common or ResourceState.Present => D3D12_RESOURCE_STATE_COMMON,
ResourceState.VertexAndConstantBuffer => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, ResourceState.VertexAndConstantBuffer => D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
ResourceState.IndexBuffer => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_INDEX_BUFFER, ResourceState.IndexBuffer => D3D12_RESOURCE_STATE_INDEX_BUFFER,
ResourceState.RenderTarget => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_RENDER_TARGET, ResourceState.RenderTarget => D3D12_RESOURCE_STATE_RENDER_TARGET,
ResourceState.UnorderedAccess => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_UNORDERED_ACCESS, ResourceState.UnorderedAccess => D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
ResourceState.DepthWrite => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_WRITE, ResourceState.DepthWrite => D3D12_RESOURCE_STATE_DEPTH_WRITE,
ResourceState.DepthRead => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_DEPTH_READ, ResourceState.DepthRead => D3D12_RESOURCE_STATE_DEPTH_READ,
ResourceState.PixelShaderResource => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, ResourceState.PixelShaderResource => D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
ResourceState.CopyDest => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_DEST, ResourceState.CopyDest => D3D12_RESOURCE_STATE_COPY_DEST,
ResourceState.CopySource => D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COPY_SOURCE, ResourceState.CopySource => D3D12_RESOURCE_STATE_COPY_SOURCE,
_ => throw new ArgumentException($"Unknown resource state: {state}") _ => throw new ArgumentException($"Unknown resource state: {state}")
}; };
} }

View File

@@ -16,6 +16,20 @@
<IsAotCompatible>True</IsAotCompatible> <IsAotCompatible>True</IsAotCompatible>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Remove="runtime\win-x64\native\dxcompiler.dll" />
<None Remove="runtime\win-x64\native\dxil.dll" />
</ItemGroup>
<ItemGroup>
<Content Include="runtime\win-x64\native\dxcompiler.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="runtime\win-x64\native\dxil.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Misaki.HighPerformance.Image" Version="1.0.0" /> <PackageReference Include="Misaki.HighPerformance.Image" Version="1.0.0" />
<PackageReference Include="TerraFX.Interop.D3D12MemoryAllocator" Version="2.0.1.5" /> <PackageReference Include="TerraFX.Interop.D3D12MemoryAllocator" Version="2.0.1.5" />

View File

@@ -19,7 +19,7 @@ public interface IPipelineLibrary
/// Load pipeline library from disk. /// Load pipeline library from disk.
/// </summary> /// </summary>
/// <param name="filePath">File path. If null, load default library.</param> /// <param name="filePath">File path. If null, load default library.</param>
void LoadLibraryFromDisk(string? filePath); void InitializeLibrary(string? filePath);
void SaveLibraryToDisk(string filePath); void SaveLibraryToDisk(string filePath);
GraphicsPipelineKey CompilePassPSO(IPassDescriptor descriptor, ReadOnlySpan<TextureFormat> rtvs, TextureFormat dsv); GraphicsPipelineKey CompilePassPSO(IPassDescriptor descriptor, ReadOnlySpan<TextureFormat> rtvs, TextureFormat dsv);
} }

View File

@@ -28,7 +28,7 @@ internal unsafe class MeshRenderPass : IRenderPass
public void Initialize(ref readonly RenderingContext ctx) public void Initialize(ref readonly RenderingContext ctx)
{ {
var shaderDescriptor = SDLCompiler.CompileShader("F:\\csharp\\GhostEngine\\Ghost.Graphics\\RenderPasses\\ShaderCode.hlsl").GetValueOrThrow(); var shaderDescriptor = SDLCompiler.CompileShader("F:\\csharp\\GhostEngine\\Ghost.Graphics\\test.gshader").GetValueOrThrow();
var key = ctx.PipelineLibrary.CompilePassPSO(shaderDescriptor.passes[0], [TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown); var key = ctx.PipelineLibrary.CompilePassPSO(shaderDescriptor.passes[0], [TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown);

View File

@@ -1,4 +1,4 @@
cbuffer ConstantBuffer : register(b0) cbuffer ConstantBuffer : register(b0)
{ {
float4 _Color; float4 _Color;
uint _TextureIndex1; uint _TextureIndex1;
@@ -9,9 +9,6 @@
uint _IndexBufferIndex; uint _IndexBufferIndex;
}; };
// SM 6.6 approach - direct access to global descriptor heap
SamplerState _MainSampler : register(s0);
struct Vertex struct Vertex
{ {
float4 position; float4 position;
@@ -54,6 +51,8 @@ void MSMain(
v.color = asfloat(vertexBuffer.Load4(vertexOffset + 48)); v.color = asfloat(vertexBuffer.Load4(vertexOffset + 48));
v.uv = asfloat(vertexBuffer.Load4(vertexOffset + 64)); v.uv = asfloat(vertexBuffer.Load4(vertexOffset + 64));
SetMeshOutputCounts(3, 1);
// Write vertex output // Write vertex output
outVerts[vertexId].position = v.position; outVerts[vertexId].position = v.position;
outVerts[vertexId].color = v.color; outVerts[vertexId].color = v.color;
@@ -62,28 +61,17 @@ void MSMain(
// Thread 0 defines topology // Thread 0 defines topology
if (vertexId == 0) if (vertexId == 0)
{ {
SetMeshOutputCounts(3, 1);
outTris[0] = uint3(0, 1, 2); outTris[0] = uint3(0, 1, 2);
} }
} }
float4 PSMain(PixelInput input) : SV_TARGET float4 PSMain(PixelInput input) : SV_TARGET
{ {
// SM 6.6 Modern Bindless Approach: float4 color1 = SAMPLE_TEXTURE2D_BINDLESS(_TextureIndex1, 0, input.uv.xy);
// ResourceDescriptorHeap[index] directly accesses any texture in the heap float4 color2 = SAMPLE_TEXTURE2D_BINDLESS(_TextureIndex2, 0, input.uv.xy);
Texture2D tex1 = ResourceDescriptorHeap[_TextureIndex1]; float4 color3 = SAMPLE_TEXTURE2D_BINDLESS(_TextureIndex3, 0, input.uv.xy);
Texture2D tex2 = ResourceDescriptorHeap[_TextureIndex2]; float4 color4 = SAMPLE_TEXTURE2D_BINDLESS(_TextureIndex4, 0, input.uv.xy);
Texture2D tex3 = ResourceDescriptorHeap[_TextureIndex3];
Texture2D tex4 = ResourceDescriptorHeap[_TextureIndex4];
// Sample the textures
float4 color1 = tex1.Sample(_MainSampler, input.uv.xy);
float4 color2 = tex2.Sample(_MainSampler, input.uv.xy);
float4 color3 = tex3.Sample(_MainSampler, input.uv.xy);
float4 color4 = tex4.Sample(_MainSampler, input.uv.xy);
// Blend all textures together (simple average)
float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f; float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
return blendedColor * _Color; return blendedColor * _Color;
} }

Binary file not shown.

Binary file not shown.