Continue working on RHI

This commit is contained in:
2025-09-12 21:44:32 +09:00
parent 1b0ef03728
commit 1dfed83e38
49 changed files with 1780 additions and 2195 deletions

View File

@@ -10,36 +10,36 @@ public interface ICommandBuffer : IDisposable
/// <summary>
/// Begins recording commands into this command buffer
/// </summary>
void Begin();
public void Begin();
/// <summary>
/// Ends recording commands and prepares for submission
/// </summary>
void End();
public void End();
/// <summary>
/// Begins a render pass with the specified render target
/// </summary>
/// <param name="renderTarget">Render target to render into</param>
/// <param name="clearColor">Color to clear the render target with</param>
void BeginRenderPass(IRenderTarget renderTarget, Color128 clearColor);
public void BeginRenderPass(IRenderTarget renderTarget, Color128 clearColor);
/// <summary>
/// Ends the current render pass
/// </summary>
void EndRenderPass();
public void EndRenderPass();
/// <summary>
/// Sets the viewport for rendering
/// </summary>
/// <param name="viewport">Viewport to set</param>
void SetViewport(ViewportDesc viewport);
public void SetViewport(ViewportDesc viewport);
/// <summary>
/// Sets the scissor rectangle
/// </summary>
/// <param name="rect">Scissor rectangle to set</param>
void SetScissorRect(RectDesc rect);
public void SetScissorRect(RectDesc rect);
/// <summary>
/// Inserts a resource barrier for state transitions
@@ -47,35 +47,26 @@ public interface ICommandBuffer : IDisposable
/// <param name="resource">Resource to transition</param>
/// <param name="before">Current resource state</param>
/// <param name="after">Target resource state</param>
void ResourceBarrier(IResource resource, ResourceState before, ResourceState after);
public void ResourceBarrier(IResource resource, ResourceState before, ResourceState after);
/// <summary>
/// Sets the graphics root signature
/// </summary>
/// <param name="rootSignature">Root signature to set</param>
void SetGraphicsRootSignature(IRootSignature rootSignature);
public void SetGraphicsRootSignature(IRootSignature rootSignature);
/// <summary>
/// Sets the pipeline state object
/// </summary>
/// <param name="pipelineState">Pipeline state to set</param>
void SetPipelineState(IPipelineState pipelineState);
public void SetPipelineState(IPipelineStateController pipelineState);
/// <summary>
/// Sets descriptor heaps for bindless rendering
/// Renders the specified mesh using the provided material.
/// </summary>
/// <param name="heaps">Descriptor heaps to set</param>
void SetDescriptorHeaps(IDescriptorHeap[] heaps);
/// <summary>
/// Draws indexed geometry
/// </summary>
/// <param name="indexCount">Number of indices to draw</param>
/// <param name="instanceCount">Number of instances to draw</param>
/// <param name="startIndex">Starting index location</param>
/// <param name="baseVertex">Base vertex location</param>
/// <param name="startInstance">Starting instance location</param>
void DrawIndexedInstanced(uint indexCount, uint instanceCount = 1, uint startIndex = 0, int baseVertex = 0, uint startInstance = 0);
/// <param name="mesh">The mesh to be drawn. Must not be null.</param>
/// <param name="material">The material to use for rendering the mesh. Must not be null.</param>
public void DrawMesh(Mesh mesh, Material material);
/// <summary>
/// Dispatches compute threads
@@ -83,7 +74,7 @@ public interface ICommandBuffer : IDisposable
/// <param name="threadGroupCountX">Thread groups in X dimension</param>
/// <param name="threadGroupCountY">Thread groups in Y dimension</param>
/// <param name="threadGroupCountZ">Thread groups in Z dimension</param>
void Dispatch(uint threadGroupCountX, uint threadGroupCountY = 1, uint threadGroupCountZ = 1);
public void Dispatch(uint threadGroupCountX, uint threadGroupCountY = 1, uint threadGroupCountZ = 1);
}
/// <summary>
@@ -129,7 +120,7 @@ public struct RectDesc
}
/// <summary>
/// D3D12-style resource states
/// Resource states
/// </summary>
public enum ResourceState
{
@@ -143,5 +134,5 @@ public enum ResourceState
PixelShaderResource = 0x80,
CopyDest = 0x400,
CopySource = 0x800,
Present = 0
Present = 0,
}

View File

@@ -8,7 +8,10 @@ public interface ICommandQueue : IDisposable
/// <summary>
/// Type of commands this queue can execute
/// </summary>
CommandQueueType Type { get; }
CommandQueueType Type
{
get;
}
/// <summary>
/// Submits a single command buffer for execution
@@ -20,7 +23,7 @@ public interface ICommandQueue : IDisposable
/// Submits multiple command buffers for execution
/// </summary>
/// <param name="commandBuffers">Command buffers to submit</param>
void Submit(ICommandBuffer[] commandBuffers);
void Submit(params ReadOnlySpan<ICommandBuffer> commandBuffers);
/// <summary>
/// Signals a fence with the specified value

View File

@@ -1,144 +0,0 @@
namespace Ghost.Graphics.RHI;
/// <summary>
/// D3D12-style descriptor allocator interface
/// </summary>
public interface IDescriptorAllocator : IDisposable
{
/// <summary>
/// Allocates a render target view descriptor
/// </summary>
/// <returns>RTV descriptor handle</returns>
DescriptorHandle AllocateRTV();
/// <summary>
/// Allocates multiple render target view descriptors
/// </summary>
/// <param name="count">Number of descriptors to allocate</param>
/// <returns>Array of RTV descriptor handles</returns>
DescriptorHandle[] AllocateRTVs(uint count);
/// <summary>
/// Allocates a depth stencil view descriptor
/// </summary>
/// <returns>DSV descriptor handle</returns>
DescriptorHandle AllocateDSV();
/// <summary>
/// Allocates a shader resource view descriptor
/// </summary>
/// <returns>SRV descriptor handle</returns>
DescriptorHandle AllocateSRV();
/// <summary>
/// Allocates a sampler descriptor
/// </summary>
/// <returns>Sampler descriptor handle</returns>
DescriptorHandle AllocateSampler();
/// <summary>
/// Allocates a bindless descriptor for SM 6.6 rendering
/// </summary>
/// <returns>Bindless descriptor handle</returns>
DescriptorHandle AllocateBindless();
/// <summary>
/// Releases a render target view descriptor
/// </summary>
/// <param name="handle">RTV descriptor to release</param>
void ReleaseRTV(DescriptorHandle handle);
/// <summary>
/// Releases a depth stencil view descriptor
/// </summary>
/// <param name="handle">DSV descriptor to release</param>
void ReleaseDSV(DescriptorHandle handle);
/// <summary>
/// Releases a shader resource view descriptor
/// </summary>
/// <param name="handle">SRV descriptor to release</param>
void ReleaseSRV(DescriptorHandle handle);
/// <summary>
/// Releases a sampler descriptor
/// </summary>
/// <param name="handle">Sampler descriptor to release</param>
void ReleaseSampler(DescriptorHandle handle);
/// <summary>
/// Releases a bindless descriptor
/// </summary>
/// <param name="handle">Bindless descriptor to release</param>
void ReleaseBindless(DescriptorHandle handle);
}
/// <summary>
/// D3D12-style descriptor heap interface
/// </summary>
public interface IDescriptorHeap : IDisposable
{
/// <summary>
/// Type of descriptors this heap contains
/// </summary>
DescriptorHeapType Type { get; }
/// <summary>
/// Maximum number of descriptors in this heap
/// </summary>
uint MaxDescriptors { get; }
/// <summary>
/// Whether this heap is shader visible
/// </summary>
bool IsShaderVisible { get; }
/// <summary>
/// Gets a CPU descriptor handle at the specified index
/// </summary>
/// <param name="index">Index of the descriptor</param>
/// <returns>CPU descriptor handle</returns>
DescriptorHandle GetCPUHandle(uint index);
/// <summary>
/// Gets a GPU descriptor handle at the specified index
/// </summary>
/// <param name="index">Index of the descriptor</param>
/// <returns>GPU descriptor handle</returns>
DescriptorHandle GetGPUHandle(uint index);
}
/// <summary>
/// Descriptor handle for D3D12-style descriptor management
/// </summary>
public struct DescriptorHandle : IEquatable<DescriptorHandle>
{
public uint Index;
public bool IsValid;
public DescriptorHandle(uint index)
{
Index = index;
IsValid = true;
}
public static DescriptorHandle Invalid => new() { Index = uint.MaxValue, IsValid = false };
public bool Equals(DescriptorHandle other) => Index == other.Index && IsValid == other.IsValid;
public override bool Equals(object? obj) => obj is DescriptorHandle other && Equals(other);
public override int GetHashCode() => HashCode.Combine(Index, IsValid);
public static bool operator ==(DescriptorHandle left, DescriptorHandle right) => left.Equals(right);
public static bool operator !=(DescriptorHandle left, DescriptorHandle right) => !left.Equals(right);
}
/// <summary>
/// D3D12 descriptor heap types
/// </summary>
public enum DescriptorHeapType
{
CBV_SRV_UAV,
Sampler,
RTV,
DSV
}

View File

@@ -0,0 +1,30 @@
namespace Ghost.Graphics.RHI;
public interface IGraphicsEngine : IDisposable
{
public IRenderDevice Device
{
get;
}
public IResourceAllocator ResourceAllocator
{
get;
}
public IRenderer CreateRenderer();
/// <summary>
/// Creates a command buffer for recording rendering commands
/// </summary>
/// <param name="type">Type of command buffer to create</param>
/// <returns>A new command buffer instance</returns>
public ICommandBuffer CreateCommandBuffer(CommandBufferType type = CommandBufferType.Graphics);
/// <summary>
/// Creates a swap chain for presentation
/// </summary>
/// <param name="desc">Swap chain description</param>
/// <returns>A new swap chain instance</returns>
public ISwapChain CreateSwapChain(SwapChainDesc desc);
}

View File

@@ -0,0 +1,25 @@
using Ghost.Graphics.Data;
namespace Ghost.Graphics.RHI;
public interface IShaderPipeline
{
/// <summary>
/// Pipeline type
/// </summary>
PipelineType Type
{
get;
}
}
public interface IPipelineStateController
{
public void ColectionShader(ReadOnlySpan<Shader> shaders);
public void CompileCollected();
public void PreCookPipelineState();
public IShaderPipeline GetShaderPipeline(Shader shader);
}

View File

@@ -8,7 +8,7 @@ public interface IRenderDevice : IDisposable
/// <summary>
/// Graphics command queue for rendering operations
/// </summary>
ICommandQueue GraphicsQueue
public ICommandQueue GraphicsQueue
{
get;
}
@@ -16,7 +16,7 @@ public interface IRenderDevice : IDisposable
/// <summary>
/// Compute command queue for compute shader operations
/// </summary>
ICommandQueue ComputeQueue
public ICommandQueue ComputeQueue
{
get;
}
@@ -24,32 +24,10 @@ public interface IRenderDevice : IDisposable
/// <summary>
/// Copy command queue for data transfer operations
/// </summary>
ICommandQueue CopyQueue
public ICommandQueue CopyQueue
{
get;
}
/// <summary>
/// Gets the descriptor allocator for managing descriptors
/// </summary>
IDescriptorAllocator DescriptorAllocator
{
get;
}
/// <summary>
/// Creates a command buffer for recording rendering commands
/// </summary>
/// <param name="type">Type of command buffer to create</param>
/// <returns>A new command buffer instance</returns>
ICommandBuffer CreateCommandBuffer(CommandBufferType type = CommandBufferType.Graphics);
/// <summary>
/// Creates a swap chain for presentation
/// </summary>
/// <param name="desc">Swap chain description</param>
/// <returns>A new swap chain instance</returns>
ISwapChain CreateSwapChain(SwapChainDesc desc);
}
/// <summary>

View File

@@ -1,27 +1,7 @@
using System.Runtime.CompilerServices;
namespace Ghost.Graphics.RHI;
/// <summary>
/// Pipeline state object interface
/// </summary>
public interface IPipelineState : IDisposable
{
/// <summary>
/// Pipeline type (graphics or compute)
/// </summary>
PipelineType Type
{
get;
}
/// <summary>
/// Pipeline name for debugging
/// </summary>
string Name
{
get; set;
}
}
/// <summary>
/// Root signature interface
/// </summary>
@@ -54,48 +34,89 @@ public struct RenderTargetDesc
/// <summary>
/// Width of the render target
/// </summary>
public uint Width;
public uint Width
{
get;
set;
}
/// <summary>
/// Height of the render target
/// </summary>
public uint Height;
public uint Height
{
get;
set;
}
/// <summary>
/// Type of render target (color or depth)
/// Slice of the render target
/// </summary>
public RenderTargetType Type;
public uint Slice
{
get;
set;
}
/// <summary>
/// Type of render target
/// </summary>
public RenderTargetType Type
{
get;
set;
}
/// <summary>
/// Target texture format
/// </summary>
public TextureFormat Format;
public TextureFormat Format
{
get;
set;
}
/// <summary>
/// Texture dimension
/// </summary>
public TextureDimension Dimension;
public TextureDimension Dimension
{
get;
set;
}
/// <summary>
/// Creation flags for the render target
/// </summary>
public RenderTargetCreationFlags CreationFlags;
public RenderTargetCreationFlags CreationFlags
{
get;
set;
}
/// <summary>
/// Number of mip levels. 0 to generate full mip chain
/// </summary>
public uint MipLevels;
public uint MipLevels
{
get;
set;
}
/// <summary>
/// Number of samples for MSAA
/// </summary>
public uint SampleCount;
public uint SampleCount
{
get;
set;
}
/// <summary>
/// Creates a color render target
/// </summary>
public static RenderTargetDesc Color(uint width, uint height,
TextureFormat format, TextureDimension dimension = TextureDimension.Texture2D,
public static RenderTargetDesc Color(uint width, uint height, uint slice = 1,
TextureFormat format = TextureFormat.R8G8B8A8_UNorm, TextureDimension dimension = TextureDimension.Texture2D,
RenderTargetCreationFlags creationFlags = RenderTargetCreationFlags.AllowUAV | RenderTargetCreationFlags.DynamicallyScalable | RenderTargetCreationFlags.GenerateMips,
uint mipLevels = 0u, uint sampleCount = 1)
{
@@ -103,6 +124,7 @@ public struct RenderTargetDesc
{
Width = width,
Height = height,
Slice = slice,
Type = RenderTargetType.Color,
Format = format,
Dimension = dimension,
@@ -115,7 +137,7 @@ public struct RenderTargetDesc
/// <summary>
/// Creates a depth render target
/// </summary>
public static RenderTargetDesc Depth(uint width, uint height,
public static RenderTargetDesc Depth(uint width, uint height, uint slice = 1,
TextureFormat format = TextureFormat.D24_UNorm_S8_UInt, TextureDimension dimension = TextureDimension.Texture2D,
RenderTargetCreationFlags creationFlags = RenderTargetCreationFlags.AllowUAV | RenderTargetCreationFlags.DynamicallyScalable,
uint mipLevels = 0u, uint sampleCount = 1)
@@ -124,6 +146,7 @@ public struct RenderTargetDesc
{
Width = width,
Height = height,
Slice = slice,
Type = RenderTargetType.Depth,
Format = format,
Dimension = dimension,
@@ -132,6 +155,18 @@ public struct RenderTargetDesc
SampleCount = sampleCount
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TextureDesc ToTextureDescriptor(RenderTargetDesc desc)
{
var usage = desc.Type == RenderTargetType.Color ? TextureUsage.RenderTarget : TextureUsage.DepthStencil;
if (desc.CreationFlags.HasFlag(RenderTargetCreationFlags.AllowUAV))
{
usage |= TextureUsage.UnorderedAccess;
}
return new TextureDesc(desc.Width, desc.Height, desc.Slice, desc.Format, desc.Dimension, desc.MipLevels, usage);
}
}
/// <summary>
@@ -142,37 +177,73 @@ public struct TextureDesc
/// <summary>
/// Width of the texture
/// </summary>
public uint Width;
public uint Width
{
get;
set;
}
/// <summary>
/// Height of the texture
/// </summary>
public uint Height;
public uint Height
{
get;
set;
}
/// <summary>
/// Slice of the texture
/// </summary>
public uint Slice
{
get;
set;
}
/// <summary>
/// Texture format
/// </summary>
public TextureFormat Format;
public TextureFormat Format
{
get;
set;
}
/// <summary>
/// Texture dimension
/// </summary>
public TextureDimension Dimension;
public TextureDimension Dimension
{
get;
set;
}
/// <summary>
/// Number of mip levels. 0 to generate full mip chain
/// </summary>
public uint MipLevels;
public uint MipLevels
{
get;
set;
}
/// <summary>
/// Texture usage flags
/// </summary>
public TextureUsage Usage;
public TextureUsage Usage
{
get;
set;
}
public TextureDesc(uint width, uint height, TextureFormat format, TextureDimension dimension = TextureDimension.Texture2D, uint mipLevels = 0u, TextureUsage usage = TextureUsage.ShaderResource)
public TextureDesc(uint width, uint height, uint slice = 1,
TextureFormat format = TextureFormat.R8G8B8A8_UNorm, TextureDimension dimension = TextureDimension.Texture2D,
uint mipLevels = 0u, TextureUsage usage = TextureUsage.ShaderResource)
{
Width = width;
Height = height;
Slice = slice;
Format = format;
Dimension = dimension;
MipLevels = mipLevels;
@@ -188,17 +259,29 @@ public struct BufferDesc
/// <summary>
/// Size of the buffer in bytes
/// </summary>
public ulong Size;
public ulong Size
{
get;
set;
}
/// <summary>
/// Buffer usage flags
/// </summary>
public BufferUsage Usage;
public BufferUsage Usage
{
get;
set;
}
/// <summary>
/// Memory type for the buffer
/// </summary>
public MemoryType MemoryType;
public MemoryType MemoryType
{
get;
set;
}
public BufferDesc(ulong size, BufferUsage usage, MemoryType memoryType = MemoryType.Default)
{

View File

@@ -73,27 +73,12 @@ public interface IBuffer : IResource
/// Render target interface for rendering operations
/// Supports either color OR depth rendering, not both
/// </summary>
public interface IRenderTarget : IDisposable
public interface IRenderTarget : ITexture
{
/// <summary>
/// Width of the render target
/// </summary>
uint Width { get; }
/// <summary>
/// Height of the render target
/// </summary>
uint Height { get; }
/// <summary>
/// Type of render target (color or depth)
/// </summary>
RenderTargetType Type { get; }
/// <summary>
/// Gets the target texture (either color or depth based on Type)
/// </summary>
ITexture Target { get; }
}
/// <summary>

View File

@@ -2,40 +2,58 @@
namespace Ghost.Graphics.RHI;
public interface IResourceFactory
public interface IResourceAllocator
{
/// <summary>
/// Creates a render target for off-screen rendering
/// </summary>
/// <param name="desc">Render target description</param>
/// <returns>A new render target instance</returns>
public IRenderTarget CreateRenderTarget(ref readonly RenderTargetDesc desc);
public IRenderTarget CreateRenderTarget(ref readonly RenderTargetDesc desc, bool tempResource = false);
/// <summary>
/// Creates a texture resource
/// </summary>
/// <param name="desc">Texture description</param>
/// <returns>A new texture handle point to the resource</returns>
public TextureHandle CreateTextureHandle(ref readonly TextureDesc desc);
public TextureHandle CreateTextureHandle(ref readonly TextureDesc desc, bool tempResource = false);
/// <summary>
/// Creates a texture resource
/// </summary>
/// <param name="desc">Texture description</param>
/// <returns>A new texture instance</returns>
public ITexture CreateTexture(ref readonly TextureDesc desc);
public ITexture CreateTexture(ref readonly TextureDesc desc, bool tempResource = false);
/// <summary>
/// Creates a buffer resource
/// </summary>
/// <param name="desc">Buffer description</param>
/// <returns>A new buffer handle point to the resource</returns>
public BufferHandle CreateBufferHandle(ref readonly BufferDesc desc);
public BufferHandle CreateBufferHandle(ref readonly BufferDesc desc, bool tempResource = false);
/// <summary>
/// Creates a buffer resource
/// </summary>
/// <param name="desc">Buffer description</param>
/// <returns>A new buffer instance</returns>
public IBuffer CreateBuffer(ref readonly BufferDesc desc);
public IBuffer CreateBuffer(ref readonly BufferDesc desc, bool tempResource = false);
/// <summary>
/// Release a resource given its handle
/// </summary>
/// <param name="handle">Resource handle</param>
public void ReleaseResource(ResourceHandle handle);
}
internal interface IResourceAllocator<T> : IResourceAllocator
where T : unmanaged
{
/// <summary>
/// Get the raw gpu resource pointer from a resource handle
/// </summary>
/// <typeparam name="T">The type of the resource.</typeparam>
/// <param name="handle">Resource handle</param>
/// <returns>Pointer to the resource</returns>
public unsafe T* GetResource(ResourceHandle handle);
}

View File

@@ -26,13 +26,7 @@ public interface ISwapChain : IDisposable
/// Gets the current back buffer texture
/// </summary>
/// <returns>Current back buffer texture</returns>
ITexture GetCurrentBackBuffer();
/// <summary>
/// Gets the current back buffer as a render target
/// </summary>
/// <returns>Current back buffer render target</returns>
IRenderTarget GetCurrentBackBufferRenderTarget();
IRenderTarget GetCurrentBackBuffer();
/// <summary>
/// Presents the rendered frame
@@ -56,35 +50,29 @@ public struct SwapChainDesc
/// <summary>
/// Width of the swap chain
/// </summary>
public uint Width;
public uint width;
/// <summary>
/// Height of the swap chain
/// </summary>
public uint Height;
public uint height;
/// <summary>
/// Back buffer format
/// </summary>
public TextureFormat Format;
/// <summary>
/// Number of back buffers
/// </summary>
public uint BufferCount;
public TextureFormat format;
/// <summary>
/// Target for presentation (window handle or composition target)
/// </summary>
public SwapChainTarget Target;
public SwapChainTarget target;
public SwapChainDesc(uint width, uint height, SwapChainTarget target, TextureFormat format = TextureFormat.B8G8R8A8_UNorm, uint bufferCount = 2)
{
Width = width;
Height = height;
Format = format;
BufferCount = bufferCount;
Target = target;
this.width = width;
this.height = height;
this.format = format;
this.target = target;
}
}