From 15aca9aefbe4559e02f173354f7df80b8da03b8c Mon Sep 17 00:00:00 2001 From: Misaki Date: Thu, 6 Nov 2025 04:13:20 +0000 Subject: [PATCH] Update RenderingContext and D3D12Renderer to use new API. --- Ghost.Core/Graphics/ShaderDescriptor.cs | 6 +- Ghost.Graphics/Contracts/IRenderPass.cs | 7 +- Ghost.Graphics/Core/Material.cs | 2 +- Ghost.Graphics/Core/RenderingContext.cs | 148 +++++++----------- Ghost.Graphics/D3D12/D3D12CommandBuffer.cs | 4 +- Ghost.Graphics/D3D12/D3D12GraphicsEngine.cs | 16 +- Ghost.Graphics/D3D12/D3D12Renderer.cs | 23 ++- Ghost.Graphics/D3D12/D3D12ResourceDatabase.cs | 6 - Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs | 14 +- Ghost.Graphics/RHI/ICommandBuffer.cs | 4 +- Ghost.Graphics/RHI/IGraphicsEngine.cs | 23 +-- Ghost.Graphics/RenderPasses/MeshRenderPass.cs | 8 +- Ghost.Graphics/test.gshader | 10 +- Ghost.Shader/BuiltIn/Common.hlsl | 26 ++- .../Compiler/Parser/PropertiesBlock.cs | 46 +++--- Ghost.Shader/Compiler/SDLCompiler.cs | 22 +-- Ghost.Shader/Compiler/Token.cs | 14 +- 17 files changed, 184 insertions(+), 195 deletions(-) diff --git a/Ghost.Core/Graphics/ShaderDescriptor.cs b/Ghost.Core/Graphics/ShaderDescriptor.cs index c9d7747..d9e9284 100644 --- a/Ghost.Core/Graphics/ShaderDescriptor.cs +++ b/Ghost.Core/Graphics/ShaderDescriptor.cs @@ -13,8 +13,8 @@ public enum ShaderPropertyType Int, Int2, Int3, Int4, UInt, UInt2, UInt3, UInt4, Bool, Bool2, Bool3, Bool4, - Texture2D, Texture3D, TextureCube, - Texture2DArray, TextureCubeArray, + Texture2DBindless, Texture3DBindless, TextureCubeBindless, + Texture2DArrayBindless, TextureCubeArrayBindless, } public struct ShaderEntryPoint @@ -101,4 +101,4 @@ public class ShaderDescriptor public string name = string.Empty; public List globalProperties = new(); public List passes = new(); -} \ No newline at end of file +} diff --git a/Ghost.Graphics/Contracts/IRenderPass.cs b/Ghost.Graphics/Contracts/IRenderPass.cs index f050fdb..d705a48 100644 --- a/Ghost.Graphics/Contracts/IRenderPass.cs +++ b/Ghost.Graphics/Contracts/IRenderPass.cs @@ -1,10 +1,11 @@ +using Ghost.Graphics.Core; using Ghost.Graphics.RHI; namespace Ghost.Graphics.Contracts; public interface IRenderPass { - public void Initialize(ICommandBuffer cmd); - public void Execute(ICommandBuffer cmd); + public void Initialize(ref readonly RenderingContext ctx); + public void Execute(ref readonly RenderingContext ctx); public void Cleanup(IResourceDatabase resourceDatabase); -} \ No newline at end of file +} diff --git a/Ghost.Graphics/Core/Material.cs b/Ghost.Graphics/Core/Material.cs index 4894c4d..9fdfbd1 100644 --- a/Ghost.Graphics/Core/Material.cs +++ b/Ghost.Graphics/Core/Material.cs @@ -211,7 +211,7 @@ public ref struct MaterialAccessor for (var i = 0; i < _shader.PassCount; i++) { ref var cache = ref _materialData.GetPassCache(i); - cmb.Upload(cache.GpuResource, cache.CpuData.AsSpan()); + cmb.UploadBuffer(cache.GpuResource, cache.CpuData.AsSpan()); } } } diff --git a/Ghost.Graphics/Core/RenderingContext.cs b/Ghost.Graphics/Core/RenderingContext.cs index aa1ef93..572114c 100644 --- a/Ghost.Graphics/Core/RenderingContext.cs +++ b/Ghost.Graphics/Core/RenderingContext.cs @@ -9,35 +9,54 @@ namespace Ghost.Graphics.Core; public unsafe readonly ref struct RenderingContext { - private readonly IRenderDevice _device; + private readonly IGraphicsEngine _engine; private readonly ICommandBuffer _directCmb; private readonly ICommandBuffer _copyCmb; private readonly ICommandBuffer _computeCmb; - private readonly IResourceAllocator _resourceAllocator; - private readonly IResourceDatabase _resourceDatabase; - private readonly IPipelineLibrary _stateController; + + public ICommandBuffer DirectCommandBuffer => _directCmb; + public ICommandBuffer CopyCommandBuffer => _copyCmb; + public ICommandBuffer ComputeCommandBuffer => _computeCmb; + + public IResourceAllocator ResourceAllocator => _engine.ResourceAllocator; + public IResourceDatabase ResourceDatabase => _engine.ResourceDatabase; + public IPipelineLibrary PipelineLibrary => _engine.PipelineLibrary; internal RenderingContext( - IRenderDevice device, + IGraphicsEngine engine, ICommandBuffer directCmd, ICommandBuffer copyCmd, - ICommandBuffer computeCmd, - IResourceAllocator resourceAllocator, - IResourceDatabase resourceDatabase, - IPipelineLibrary stateController) + ICommandBuffer computeCmd) { - _device = device; + _engine = engine; _directCmb = directCmd; _copyCmb = copyCmd; _computeCmb = computeCmd; - _resourceAllocator = resourceAllocator; - _resourceDatabase = resourceDatabase; - _stateController = stateController; + } + + public ICommandBuffer CrearteCommandBuffer(CommandBufferType type) + { + return _engine.CreateCommandBuffer(type); + } + + // TODO: ExecuteCommandBufferAsync with fencene.Device.GraphicsQueue.Submit(commandBuffer); + public void ExecuteCommandBuffer(ICommandBuffer commandBuffer) + { + var queue = commandBuffer.Type switch + { + CommandBufferType.Graphics => _engine.Device.GraphicsQueue, + CommandBufferType.Compute => _engine.Device.ComputeQueue, + CommandBufferType.Copy => _engine.Device.CopyQueue, + _ => throw new ArgumentOutOfRangeException(), + }; + + queue.Submit(commandBuffer); + queue.WaitIdle(); } public Handle CreateMesh(UnsafeList vertices, UnsafeList indices) { - var mesh = _resourceAllocator.CreateMesh(vertices, indices); + var mesh = ResourceAllocator.CreateMesh(vertices, indices); return mesh; } @@ -61,36 +80,36 @@ public unsafe readonly ref struct RenderingContext /// Whether to mark the mesh as static. If it's true, the cpu buffer of the mesh will not be avaliable any more public void UploadMesh(Handle mesh, bool markMeshStatic) { - ref var meshData = ref _resourceDatabase.GetMeshReference(mesh); - var vertexState = _resourceDatabase.GetResourceState(meshData.vertexBuffer.AsResource()); - var indexState = _resourceDatabase.GetResourceState(meshData.indexBuffer.AsResource()); + ref var meshData = ref ResourceDatabase.GetMeshReference(mesh); + var vertexState = ResourceDatabase.GetResourceState(meshData.vertexBuffer.AsResource()); + var indexState = ResourceDatabase.GetResourceState(meshData.indexBuffer.AsResource()); var needVertexTransition = vertexState != ResourceState.CopyDest; var needIndexTransition = indexState != ResourceState.CopyDest; if (needVertexTransition) { _copyCmb.ResourceBarrier(meshData.vertexBuffer.AsResource(), vertexState, ResourceState.CopyDest); - _resourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest); + ResourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest); } if (needIndexTransition) { _copyCmb.ResourceBarrier(meshData.indexBuffer.AsResource(), indexState, ResourceState.CopyDest); - _resourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), ResourceState.CopyDest); + ResourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), ResourceState.CopyDest); } - _copyCmb.Upload(meshData.vertexBuffer, meshData.vertices.AsSpan()); - _copyCmb.Upload(meshData.indexBuffer, meshData.indices.AsSpan()); + _copyCmb.UploadBuffer(meshData.vertexBuffer, meshData.vertices.AsSpan()); + _copyCmb.UploadBuffer(meshData.indexBuffer, meshData.indices.AsSpan()); if (needVertexTransition) { _copyCmb.ResourceBarrier(meshData.vertexBuffer.AsResource(), ResourceState.CopyDest, vertexState); - _resourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), vertexState); + ResourceDatabase.SetResourceState(meshData.vertexBuffer.AsResource(), vertexState); } if (needIndexTransition) { - _resourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), indexState); + ResourceDatabase.SetResourceState(meshData.indexBuffer.AsResource(), indexState); _copyCmb.ResourceBarrier(meshData.indexBuffer.AsResource(), ResourceState.CopyDest, indexState); } @@ -102,12 +121,12 @@ public unsafe readonly ref struct RenderingContext public Handle CreateTexture(ref readonly TextureDesc desc, bool tempResource = false) { - return _resourceAllocator.CreateTexture(in desc, tempResource); + return ResourceAllocator.CreateTexture(in desc, tempResource); } public void UploadTexture(Handle texture, ReadOnlySpan data) { - var desc = _resourceDatabase.GetResourceDescription(texture.AsResource()); + var desc = ResourceDatabase.GetResourceDescription(texture.AsResource()); desc.textureDescription.Format.GetSurfaceInfo((int)desc.textureDescription.Width, (int)desc.textureDescription.Height, out var rowPitch, out var slicePitch, out _); var subresourceData = new SubResourceData @@ -117,78 +136,31 @@ public unsafe readonly ref struct RenderingContext slicePitch = slicePitch }; - var sateBefore = _resourceDatabase.GetResourceState(texture.AsResource()); + var sateBefore = ResourceDatabase.GetResourceState(texture.AsResource()); var needTransition = sateBefore != ResourceState.CopyDest; if (needTransition) { _copyCmb.ResourceBarrier(texture.AsResource(), sateBefore, ResourceState.CopyDest); - _resourceDatabase.SetResourceState(texture.AsResource(), ResourceState.CopyDest); + ResourceDatabase.SetResourceState(texture.AsResource(), ResourceState.CopyDest); } - _copyCmb.Upload(texture, subresourceData); + _copyCmb.UploadTexture(texture, subresourceData); if (needTransition) { _copyCmb.ResourceBarrier(texture.AsResource(), ResourceState.CopyDest, sateBefore); - _resourceDatabase.SetResourceState(texture.AsResource(), sateBefore); + ResourceDatabase.SetResourceState(texture.AsResource(), sateBefore); } } -#if false - // TODO: Ideally we should queue the draw call to our rendering system, and render it in the full rendering pipeline. - // This is just a place holder for now for testing purpose. - // TODO: Since we are using mesh shader, we should use dispatch mesh instead of draw calls. - public void RenderMesh(Handle mesh, Handle material, string passName) - { - ref var meshRef = ref _resourceDatabase.GetMeshReference(mesh); - ref var materialRef = ref _resourceDatabase.GetMaterialReference(material); - var shader = _resourceDatabase.GetShaderReference(materialRef.Shader); - - shader.TryGetPassKey(passName, out var passIndex, out var passKey); - var hash = new GraphicsPipelineHash - { - id = passKey, - rtvCount = 1, - dsvFormat = TextureFormat.Unknown, - }; - - hash.rtvFormats[0] = TextureFormat.B8G8R8A8_UNorm; - var pipelineKey = hash.GetKey(); - _directCmb.SetPipelineState(pipelineKey); - - // FIX: Get valid root signature. In D3D12, we use fixed root signature layout for bindless rendering. - // However, our code should not assume that blindly. Each pipeline should have contained root signature info even if there are fixed. - // This ensures that future changes to root signature layout can be accommodated. - - // for (int i = 0; i < 4; i++) - { - ref var cache = ref materialRef.GetPassCache(passIndex); - _directCmb.SetConstantBufferView(RootSignatureLayout.PER_MATERIAL_BUFFER_SLOT, cache.GpuResource); - } - - // NOTE: Since we are using true bindless resources, we only need to set the descriptor heaps, not individual tables. - // TODO: Matbe handle the transitional bindless model? -#if false - var samplerGpuHandle = _descriptorAllocator.GetSamplerHeap()->GetGPUDescriptorHandleForHeapStart(); - _commandList.Get()->SetGraphicsRootDescriptorTable(rootParamIndex, samplerGpuHandle); -#endif - _directCmb.SetPrimitiveTopology(PrimitiveTopology.Triangle); - - // Draw without vertex/index buffers - use instanced drawing - // Each instance represents a triangle (3 vertices) - var triangleCount = (uint)meshRef.indices.Count / 3; - _directCmb.Draw(3, triangleCount, 0, 0); - } -#endif // TODO: Ideally we should queue the draw call to our rendering system, and render it in the full rendering pipeline. // This is just a place holder for now for testing purpose. - // TODO: Since we are using mesh shader, we should use dispatch mesh instead of draw calls. public void DispatchMesh(Handle mesh, Handle material, string passName, uint numThreadsX) { - ref var meshRef = ref _resourceDatabase.GetMeshReference(mesh); - ref var materialRef = ref _resourceDatabase.GetMaterialReference(material); - var shader = _resourceDatabase.GetShaderReference(materialRef.Shader); + ref var meshRef = ref ResourceDatabase.GetMeshReference(mesh); + ref var materialRef = ref ResourceDatabase.GetMaterialReference(material); + var shader = ResourceDatabase.GetShaderReference(materialRef.Shader); shader.TryGetPassKey(passName, out var passIndex, out var passKey); var hash = new GraphicsPipelineHash @@ -202,15 +174,9 @@ public unsafe readonly ref struct RenderingContext var pipelineKey = hash.GetKey(); _directCmb.SetPipelineState(pipelineKey); - // FIX: Get valid root signature. In D3D12, we use fixed root signature layout for bindless rendering. - // However, our code should not assume that blindly. Each pipeline should have contained root signature info even if there are fixed. - // This ensures that future changes to root signature layout can be accommodated. - - // for (int i = 0; i < 4; i++) - { - ref var cache = ref materialRef.GetPassCache(passIndex); - _directCmb.SetConstantBufferView(RootSignatureLayout.PER_MATERIAL_BUFFER_SLOT, cache.GpuResource); - } + // NOTE: We use fixed root signature layout for bindless rendering. + ref var cache = ref materialRef.GetPassCache(passIndex); + _directCmb.SetConstantBufferView(RootSignatureLayout.PER_MATERIAL_BUFFER_SLOT, cache.GpuResource); // NOTE: Since we are using true bindless resources, we only need to set the descriptor heaps, not individual tables. // TODO: Matbe handle the transitional bindless model? @@ -222,10 +188,4 @@ public unsafe readonly ref struct RenderingContext var threadGroupCountX = ((uint)meshRef.indices.Count + numThreadsX - 1) / numThreadsX; _directCmb.DispatchMesh(threadGroupCountX, 1, 1); } - - public void ExecuteCopyCommands() - { - _device.CopyQueue.Submit(_copyCmb); - _device.CopyQueue.WaitIdle(); - } } diff --git a/Ghost.Graphics/D3D12/D3D12CommandBuffer.cs b/Ghost.Graphics/D3D12/D3D12CommandBuffer.cs index 5f77a76..e605254 100644 --- a/Ghost.Graphics/D3D12/D3D12CommandBuffer.cs +++ b/Ghost.Graphics/D3D12/D3D12CommandBuffer.cs @@ -397,7 +397,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer // _commandList.Get()->DispatchRays(); } - public void Upload(Handle buffer, ReadOnlySpan data) + public void UploadBuffer(Handle buffer, ReadOnlySpan data) where T : unmanaged { ThrowIfDisposed(); @@ -422,7 +422,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer _commandList.Get()->CopyBufferRegion(pResource, 0, pUploadResource, 0, sizeInBytes); } - public void Upload(Handle texture, params ReadOnlySpan subresources) + public void UploadTexture(Handle texture, params ReadOnlySpan subresources) { ThrowIfDisposed(); ThrowIfNotRecording(); diff --git a/Ghost.Graphics/D3D12/D3D12GraphicsEngine.cs b/Ghost.Graphics/D3D12/D3D12GraphicsEngine.cs index e0109fd..5fd24d6 100644 --- a/Ghost.Graphics/D3D12/D3D12GraphicsEngine.cs +++ b/Ghost.Graphics/D3D12/D3D12GraphicsEngine.cs @@ -9,7 +9,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine #endif private readonly D3D12RenderDevice _device; - private readonly D3D12PipelineLibrary _stateController; + private readonly D3D12PipelineLibrary _pipelineLibrary; private readonly D3D12DescriptorAllocator _descriptorAllocator; private readonly D3D12ResourceDatabase _resourceDatabase; @@ -17,13 +17,11 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine private readonly D3D12CommandBuffer _copyCommandBuffer; - public IRenderDevice Device => _device; + public IPipelineLibrary PipelineLibrary => _pipelineLibrary; public IResourceDatabase ResourceDatabase => _resourceDatabase; public IResourceAllocator ResourceAllocator => _resourceAllocator; - public IPipelineLibrary PipelineStateController => _stateController; - public D3D12GraphicsEngine(RenderSystem renderSystem) { #if DEBUG @@ -35,10 +33,10 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine _resourceDatabase = new(_descriptorAllocator); _resourceAllocator = new(renderSystem, _device, _descriptorAllocator, _resourceDatabase); - _stateController = new(_device, _resourceDatabase, null); + _pipelineLibrary = new(_device, _resourceDatabase); _copyCommandBuffer = new( _device, - _stateController, + _pipelineLibrary, _resourceDatabase, _resourceAllocator, _descriptorAllocator, @@ -59,7 +57,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine { return new D3D12CommandBuffer( _device, - _stateController, + _pipelineLibrary, _resourceDatabase, _resourceAllocator, _descriptorAllocator, @@ -84,7 +82,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine public void Dispose() { _copyCommandBuffer.Dispose(); - _stateController.Dispose(); + _pipelineLibrary.Dispose(); _resourceAllocator.Dispose(); _resourceDatabase.Dispose(); @@ -97,4 +95,4 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine GC.SuppressFinalize(this); } -} \ No newline at end of file +} diff --git a/Ghost.Graphics/D3D12/D3D12Renderer.cs b/Ghost.Graphics/D3D12/D3D12Renderer.cs index 6ddbee8..5059719 100644 --- a/Ghost.Graphics/D3D12/D3D12Renderer.cs +++ b/Ghost.Graphics/D3D12/D3D12Renderer.cs @@ -184,7 +184,21 @@ internal unsafe class D3D12Renderer : IRenderer { var clearColor = new Color128 { r = 1.0f, g = 0.0f, b = 1.0f, a = 1.0f }; - cmd.BeginRenderPass(target, Handle.Invalid, clearColor); + Span rtDesc = stackalloc PassRenderTargetDesc[1]; + rtDesc[0] = new PassRenderTargetDesc + { + texture = target, + clearColor = clearColor, + }; + + var depthDesc = new PassDepthStencilDesc + { + texture = Handle.Invalid, + clearDepth = 1.0f, + clearStencil = 0, + }; + + cmd.BeginRenderPass(rtDesc, depthDesc, false); var viewport = new ViewportDesc { width = _currentSize.x, height = _currentSize.y, minDepth = 0, maxDepth = 1 }; var scissor = new RectDesc { right = _currentSize.x, bottom = _currentSize.y }; @@ -213,17 +227,12 @@ internal unsafe class D3D12Renderer : IRenderer // For now, we'll do a simple copy operation // In a real implementation, you would use a blit shader for post-processing - // TODO: Implement proper blit operation with shader + // FIX: Implement proper blit operation with shader // This is a placeholder - in D3D12, you would typically: // 1. Set render target to the destination // 2. Use a full-screen quad/triangle with a shader that samples from the source // 3. Apply post-processing effects (tone mapping, gamma correction, etc.) - // For now, just clear the destination (this should be replaced with actual blit) - var clearColor = new Color128 { r = 0.0f, g = 0.0f, b = 0.0f, a = 1.0f }; - cmd.BeginRenderPass(destination, Handle.Invalid, clearColor); - cmd.EndRenderPass(); - // Handle swap chain back buffer transitions if needed if (_swapChain != null) { diff --git a/Ghost.Graphics/D3D12/D3D12ResourceDatabase.cs b/Ghost.Graphics/D3D12/D3D12ResourceDatabase.cs index c180b09..afc346c 100644 --- a/Ghost.Graphics/D3D12/D3D12ResourceDatabase.cs +++ b/Ghost.Graphics/D3D12/D3D12ResourceDatabase.cs @@ -90,12 +90,6 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable } } - private struct Slot - { - public T value; - public bool occupied; - } - private readonly D3D12DescriptorAllocator _descriptorAllocator; private UnsafeSlotMap _resources; diff --git a/Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs b/Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs index 861f821..9fb5fe3 100644 --- a/Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs +++ b/Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs @@ -1,11 +1,9 @@ using Ghost.Core; using Ghost.Core.Utilities; -using Ghost.Graphics.D3D12.Utilities; using Ghost.Graphics.RHI; using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections; using Misaki.HighPerformance.LowLevel.Utilities; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using TerraFX.Interop.DirectX; using TerraFX.Interop.Windows; @@ -204,11 +202,11 @@ internal static unsafe class D3D12ShaderCompiler using ComPtr includeHandler = default; // Create DXC compiler and utils - var pDxcCompiler = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcCompiler); - var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils); + var dxccID = CLSID.CLSID_DxcCompiler; + var dxcuID = CLSID.CLSID_DxcUtils; - ThrowIfFailed(DxcCreateInstance(pDxcCompiler, compiler.IID(), compiler.PPV())); - ThrowIfFailed(DxcCreateInstance(pDxcUtils, utils.IID(), utils.PPV())); + ThrowIfFailed(DxcCreateInstance(&dxccID, compiler.IID(), compiler.PPV())); + ThrowIfFailed(DxcCreateInstance(&dxcuID, utils.IID(), utils.PPV())); //includeHandler.Get()->LoadSource(); utils.Get()->CreateDefaultIncludeHandler(includeHandler.GetAddressOf()); @@ -299,9 +297,9 @@ internal static unsafe class D3D12ShaderCompiler } // Create DXC utils to parse reflection data - var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils); + var dxcuID = CLSID.CLSID_DxcUtils; using ComPtr utils = default; - ThrowIfFailed(DxcCreateInstance(pDxcUtils, utils.IID(), utils.PPV())); + ThrowIfFailed(DxcCreateInstance(&dxcuID, utils.IID(), utils.PPV())); // Create reflection interface from blob var reflectionBuffer = new DxcBuffer diff --git a/Ghost.Graphics/RHI/ICommandBuffer.cs b/Ghost.Graphics/RHI/ICommandBuffer.cs index dfa3598..2e93b30 100644 --- a/Ghost.Graphics/RHI/ICommandBuffer.cs +++ b/Ghost.Graphics/RHI/ICommandBuffer.cs @@ -171,7 +171,7 @@ public interface ICommandBuffer : IDisposable /// A handle to the buffer that will receive the uploaded data. /// A read-only span containing the data to upload to the buffer. The span must contain elements of type /// . - void Upload(Handle buffer, ReadOnlySpan data) + void UploadBuffer(Handle buffer, ReadOnlySpan data) where T : unmanaged; /// @@ -182,7 +182,7 @@ public interface ICommandBuffer : IDisposable /// A reference to the structure containing the subresource data to upload. The data must match the format and layout expected by the texture. /// The number of subresources to upload, starting from . /// Must be greater than zero and not exceed the remaining subresources in the texture. - void Upload(Handle texture, params ReadOnlySpan subresources); + void UploadTexture(Handle texture, params ReadOnlySpan subresources); /// /// Copies a specified number of bytes from the source graphics buffer to the destination graphics buffer. diff --git a/Ghost.Graphics/RHI/IGraphicsEngine.cs b/Ghost.Graphics/RHI/IGraphicsEngine.cs index 40a157f..a11a05f 100644 --- a/Ghost.Graphics/RHI/IGraphicsEngine.cs +++ b/Ghost.Graphics/RHI/IGraphicsEngine.cs @@ -2,44 +2,49 @@ namespace Ghost.Graphics.RHI; public interface IGraphicsEngine : IDisposable { - public IRenderDevice Device + IRenderDevice Device { get; } - public IResourceDatabase ResourceDatabase + IPipelineLibrary PipelineLibrary { get; } - public IResourceAllocator ResourceAllocator + IResourceDatabase ResourceDatabase { get; } - public IRenderer CreateRenderer(); + IResourceAllocator ResourceAllocator + { + get; + } + + IRenderer CreateRenderer(); /// /// Creates a command buffer for recording rendering commands /// /// Type of command buffer to create /// A new command buffer instance - public ICommandBuffer CreateCommandBuffer(CommandBufferType type = CommandBufferType.Graphics); + ICommandBuffer CreateCommandBuffer(CommandBufferType type = CommandBufferType.Graphics); /// /// Creates a swap chain for presentation /// /// Swap chain description /// A new swap chain instance - public ISwapChain CreateSwapChain(SwapChainDesc desc); + ISwapChain CreateSwapChain(SwapChainDesc desc); /// /// Begins a new rendering frame, preparing the graphics context for drawing operations. /// - public void BeginFrame(); + void BeginFrame(); /// /// Completes the current rendering frame and performs any necessary finalization steps. /// - public void EndFrame(); -} \ No newline at end of file + void EndFrame(); +} diff --git a/Ghost.Graphics/RenderPasses/MeshRenderPass.cs b/Ghost.Graphics/RenderPasses/MeshRenderPass.cs index 781f04d..fbe27c9 100644 --- a/Ghost.Graphics/RenderPasses/MeshRenderPass.cs +++ b/Ghost.Graphics/RenderPasses/MeshRenderPass.cs @@ -26,19 +26,19 @@ internal unsafe class MeshRenderPass : IRenderPass "C:/Users/Misaki/Downloads/Im/yande.re 1134666 blue_archive nakamasa_ichika sugarhigh.jpg" ]; - public void Initialize(ref readonly RenderingContext ctx, IResourceAllocator resourceAllocator, IPipelineLibrary pipelineLibrary) + public void Initialize(ref readonly RenderingContext ctx) { var shaderDescriptor = SDLCompiler.CompileShader("F:\\csharp\\GhostEngine\\Ghost.Graphics\\RenderPasses\\ShaderCode.hlsl").GetValueOrThrow(); - var key = pipelineLibrary.CompilePassPSO(shaderDescriptor.passes[0], [TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown); + var key = ctx.PipelineLibrary.CompilePassPSO(shaderDescriptor.passes[0], [TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown); MeshBuilder.CreateCube(0.75f, default, out var vertices, out var indices); _mesh = ctx.CreateMesh(vertices, indices); ctx.UploadMesh(_mesh, true); - _shader = resourceAllocator.CreateShader(shaderDescriptor); - _material = resourceAllocator.CreateMaterial(_shader); + _shader = ctx.ResourceAllocator.CreateShader(shaderDescriptor); + _material = ctx.ResourceAllocator.CreateMaterial(_shader); var imageResults = new ImageResult[_textureFiles.Length]; diff --git a/Ghost.Graphics/test.gshader b/Ghost.Graphics/test.gshader index 3ca5415..cba2589 100644 --- a/Ghost.Graphics/test.gshader +++ b/Ghost.Graphics/test.gshader @@ -3,10 +3,10 @@ shader "MyShader/Standard" properties { float4 color = float4(1, 1, 1, 1); - texture2d texture1 = texture2d(black); - texture2d texture2 = texture2d(white); - texture2d texture3 = texture2d(grey); - texture2d texture4 = texture2d(normal); + tex2d_b texture1 = tex2d_b(black); + tex2d_b texture2 = tex2d_b(white); + tex2d_b texture3 = tex2d_b(grey); + tex2d_b texture4 = tex2d_b(normal); } pipeline @@ -28,4 +28,4 @@ shader "MyShader/Standard" "F:/csharp/GhostEngine/Ghost.Shader/BuiltIn/Common.hlsl"; } } -} \ No newline at end of file +} diff --git a/Ghost.Shader/BuiltIn/Common.hlsl b/Ghost.Shader/BuiltIn/Common.hlsl index 2373f5b..6c73a40 100644 --- a/Ghost.Shader/BuiltIn/Common.hlsl +++ b/Ghost.Shader/BuiltIn/Common.hlsl @@ -3,6 +3,9 @@ #undef USE_TRADITIONAL_BINDLESS // Just for testing, this should be handled by engine feature level. + +// Resource descriptor heap definitions + #if defined(USE_TRADITIONAL_BINDLESS) #define GLOBAL_TEXTURE2D_HEAP_SIZE 32768 #define GLOBAL_TEXTURE3D_HEAP_SIZE 32 @@ -27,6 +30,8 @@ #endif +// Bindless resource type definitions + #define TEXTURE2D_BINDLESS uint #define TEXTURE3D_BINDLESS uint #define TEXTURECUBE_BINDLESS uint @@ -38,6 +43,19 @@ #define STRUCT_BUFFER_BINDLESS uint #define BYTE_ADDRESS_BUFFER_BINDLESS uint +#define TEXTURE2D Texture2D +#define TEXTURE3D Texture3D +#define TEXTURECUBE TextureCube +#define TEXTURE2D_ARRAY Texture2DArray +#define TEXTURECUBE_ARRAY TextureCubeArray + +#define SAMPLER SamplerState + +#define STRUCT_BUFFER(type) StructuredBuffer +#define BYTE_ADDRESS_BUFFER ByteAddressBuffer + + +// Texture and sampler access macros #define GET_TEXTURE2D_BINDLESS(id) GLOBAL_TEXTURE2D_HEAP[id] #define GET_TEXTURE2D_ARRAY_BINDLESS(id) GLOBAL_TEXTURE2D_ARRAY_HEAP[id] @@ -47,6 +65,8 @@ #define GET_SAMPLER_BINDLESS(id) GLOBAL_SAMPLER_HEAP[id] +// Texture sampling macros + #define SAMPLE_TEXTURE2D(tex, samp, uv) tex.Sample(samp, uv) #define SAMPLE_TEXTURE2D_LEVEL(tex, samp, uv, level) tex.SampleLevel(samp, uv, level) #define SAMPLE_TEXTURE2D_BINDLESS(texId, sampId, uv) GET_TEXTURE2D_BINDLESS(texId).Sample(GET_BINDLESS_SAMPLER(sampId), uv) @@ -55,4 +75,8 @@ #define SAMPLE_TEXTURE2D_ARRAY(tex, samp, uv, index) tex.Sample(samp, uv, index) #define SAMPLE_TEXTURE2D_ARRAY_BINDLESS(texId, sampId, uv, index) GET_TEXTURE2D_ARRAY_BINDLESS(texId).Sample(GET_BINDLESS_SAMPLER(sampId), uv, index) -#endif // COMMON_HLSL \ No newline at end of file + + +#define MESH_SHADER_THREADS(x) [NumThreads(x, 1, 1)] + +#endif // COMMON_HLSL diff --git a/Ghost.Shader/Compiler/Parser/PropertiesBlock.cs b/Ghost.Shader/Compiler/Parser/PropertiesBlock.cs index a089fa4..1b11e24 100644 --- a/Ghost.Shader/Compiler/Parser/PropertiesBlock.cs +++ b/Ghost.Shader/Compiler/Parser/PropertiesBlock.cs @@ -73,9 +73,9 @@ internal class PropertiesBlock : IBlockParser ParseTextureDefault(syntax[0], errors)), - [ShaderPropertyType.Texture3D] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)), - [ShaderPropertyType.TextureCube] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)), + [ShaderPropertyType.Texture2DBindless] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)), + [ShaderPropertyType.Texture3DBindless] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)), + [ShaderPropertyType.TextureCubeBindless] = new(1, TokenType.Identifier, (syntax, errors) => ParseTextureDefault(syntax[0], errors)), }; private static float ParseFloatValue(Token token, List errors) @@ -162,25 +162,25 @@ internal class PropertiesBlock : IBlockParser ShaderPropertyType.Float, - "float2" => ShaderPropertyType.Float2, - "float3" => ShaderPropertyType.Float3, - "float4" => ShaderPropertyType.Float4, - "int" => ShaderPropertyType.Int, - "int2" => ShaderPropertyType.Int2, - "int3" => ShaderPropertyType.Int3, - "int4" => ShaderPropertyType.Int4, - "uint" => ShaderPropertyType.UInt, - "uint2" => ShaderPropertyType.UInt2, - "uint3" => ShaderPropertyType.UInt3, - "uint4" => ShaderPropertyType.UInt4, - "bool" => ShaderPropertyType.Bool, - "bool2" => ShaderPropertyType.Bool2, - "bool3" => ShaderPropertyType.Bool3, - "bool4" => ShaderPropertyType.Bool4, - "texture2d" => ShaderPropertyType.Texture2D, - "texture3d" => ShaderPropertyType.Texture3D, - "texturecube" => ShaderPropertyType.TextureCube, + TokenLexicon.KnownTypes.FLOAT => ShaderPropertyType.Float, + TokenLexicon.KnownTypes.FLOAT2 => ShaderPropertyType.Float2, + TokenLexicon.KnownTypes.FLOAT3 => ShaderPropertyType.Float3, + TokenLexicon.KnownTypes.FLOAT4 => ShaderPropertyType.Float4, + TokenLexicon.KnownTypes.INT => ShaderPropertyType.Int, + TokenLexicon.KnownTypes.INT2 => ShaderPropertyType.Int2, + TokenLexicon.KnownTypes.INT3 => ShaderPropertyType.Int3, + TokenLexicon.KnownTypes.INT4 => ShaderPropertyType.Int4, + TokenLexicon.KnownTypes.UINT => ShaderPropertyType.UInt, + TokenLexicon.KnownTypes.UINT2 => ShaderPropertyType.UInt2, + TokenLexicon.KnownTypes.UINT3 => ShaderPropertyType.UInt3, + TokenLexicon.KnownTypes.UINT4 => ShaderPropertyType.UInt4, + TokenLexicon.KnownTypes.BOOL => ShaderPropertyType.Bool, + TokenLexicon.KnownTypes.BOOL2 => ShaderPropertyType.Bool2, + TokenLexicon.KnownTypes.BOOL3 => ShaderPropertyType.Bool3, + TokenLexicon.KnownTypes.BOOL4 => ShaderPropertyType.Bool4, + TokenLexicon.KnownTypes.TEXTURE2D_BINDLESS => ShaderPropertyType.Texture2DBindless, + TokenLexicon.KnownTypes.TEXTURE3D_BINDLESS => ShaderPropertyType.Texture3DBindless, + TokenLexicon.KnownTypes.TEXTURECUBE_BINDLESS => ShaderPropertyType.TextureCubeBindless, _ => ShaderPropertyType.None, }; } @@ -464,4 +464,4 @@ internal class PropertiesBlock : IBlockParser? children; - } + // private struct ShaderInheritance + // { + // public SDLSemantics? parent; + // public List? children; + // } public static List ParseShaders(TokenStream stream) { @@ -289,11 +289,11 @@ internal static class SDLCompiler ShaderPropertyType.Bool3 => "bool3", ShaderPropertyType.Bool4 => "bool4", // NOTE: Textures here are bindless, represented as uint (descriptor index). - ShaderPropertyType.Texture2D => "TEXTURE2D_BINDLESS", - ShaderPropertyType.Texture3D => "TEXTURE3D_BINDLESS", - ShaderPropertyType.TextureCube => "TEXTURECUBE_BINDLESS", - ShaderPropertyType.Texture2DArray => "TEXTURE2D_ARRAY_BINDLESS", - ShaderPropertyType.TextureCubeArray => "TEXTURECUBE_ARRAY_BINDLESS", + ShaderPropertyType.Texture2DBindless => "TEXTURE2D_BINDLESS", + ShaderPropertyType.Texture3DBindless => "TEXTURE3D_BINDLESS", + ShaderPropertyType.TextureCubeBindless => "TEXTURECUBE_BINDLESS", + ShaderPropertyType.Texture2DArrayBindless => "TEXTURE2D_ARRAY_BINDLESS", + ShaderPropertyType.TextureCubeArrayBindless => "TEXTURECUBE_ARRAY_BINDLESS", _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unsupported shader property type: {type}") }; } @@ -396,4 +396,4 @@ struct GlobalData GeneratePass(pass, targetDirectory); } } -} \ No newline at end of file +} diff --git a/Ghost.Shader/Compiler/Token.cs b/Ghost.Shader/Compiler/Token.cs index 1b83035..1b943af 100644 --- a/Ghost.Shader/Compiler/Token.cs +++ b/Ghost.Shader/Compiler/Token.cs @@ -170,11 +170,11 @@ internal static class TokenLexicon public const string BOOL4 = "bool4"; // Texture types - public const string TEXTURE2D = "texture2d"; - public const string TEXTURE2D_ARRAY = "texture2d_array"; - public const string TEXTURE3D = "texture3d"; - public const string TEXTURECUBE = "texturecube"; - public const string TEXTURECUBE_ARRAY = "texturecube_array"; + public const string TEXTURE2D_BINDLESS = "tex2d_b"; + public const string TEXTURE2D_ARRAY_BINDLESS = "tex2d_arr_b"; + public const string TEXTURE3D_BINDLESS = "tex3d_b"; + public const string TEXTURECUBE_BINDLESS = "texcube_b"; + public const string TEXTURECUBE_ARRAY_BINDLESS = "texcube_arr_b"; } public static class KnownTextureValue @@ -215,8 +215,8 @@ internal static class TokenLexicon KnownTypes.INT, KnownTypes.INT2, KnownTypes.INT3, KnownTypes.INT4, KnownTypes.UINT, KnownTypes.UINT2, KnownTypes.UINT3, KnownTypes.UINT4, KnownTypes.BOOL, KnownTypes.BOOL2, KnownTypes.BOOL3, KnownTypes.BOOL4, - KnownTypes.TEXTURE2D, KnownTypes.TEXTURE2D_ARRAY, KnownTypes.TEXTURE3D, - KnownTypes.TEXTURECUBE, KnownTypes.TEXTURECUBE_ARRAY, + KnownTypes.TEXTURE2D_BINDLESS, KnownTypes.TEXTURE2D_ARRAY_BINDLESS, KnownTypes.TEXTURE3D_BINDLESS, + KnownTypes.TEXTURECUBE_BINDLESS, KnownTypes.TEXTURECUBE_ARRAY_BINDLESS, }; private static readonly HashSet s_textureDefaultValues = new()