Refactoring Rendering backend

This commit is contained in:
2025-10-05 16:26:37 +09:00
parent a39f377533
commit 01a850ff94
99 changed files with 5056 additions and 5136 deletions

View File

@@ -1,7 +1,6 @@
using Ghost.Graphics.D3D12;
using Ghost.Core;
using Ghost.Graphics.Data;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Drawing;
using Win32.Graphics.Direct3D12;
namespace Ghost.Graphics.RHI;
@@ -15,6 +14,11 @@ public interface ICommandBuffer : IDisposable
get;
}
public bool IsEmpty
{
get;
}
/// <summary>
/// Begins recording commands into this command buffer
/// </summary>
@@ -25,12 +29,25 @@ public interface ICommandBuffer : IDisposable
/// </summary>
public void End();
/// <summary>
/// Sets the optional render targets and optional depth target for subsequent rendering operations.
/// </summary>
/// <remarks>
/// To specify no render targets, provide an empty span for <paramref name="renderTargets"/>.
/// Use <see cref="Handle{Texture}.Invalid"/> for <paramref name="depthTarget"/> if no depth target is required.
/// </remarks>
/// <param name="renderTargets">A read-only span of handles to textures that will be used as render targets.
/// The order of handles determines the order in which render targets are bound.</param>
/// <param name="depthTarget">A handle to the texture to be used as the depth target. Specify a invalid handle if no depth target is required.</param>
public void SetRenderTargets(ReadOnlySpan<Handle<Texture>> renderTargets, Handle<Texture> depthTarget);
/// <summary>
/// Begins a render pass with the specified render target
/// </summary>
/// <param name="renderTarget">Render target to render into</param>
/// <param name="renderTarget">Render target to render into (can be invalid)</param>
/// <param name="depthTarget">Depth target to use (can be invalid)</param>
/// <param name="clearColor">Color to clear the render target with</param>
public void BeginRenderPass(IRenderTarget renderTarget, Color128 clearColor);
public void BeginRenderPass(Handle<Texture> renderTarget, Handle<Texture> depthTarget, Color128 clearColor);
/// <summary>
/// Ends the current render pass
@@ -55,26 +72,25 @@ 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>
public void ResourceBarrier(IResource resource, ResourceState before, ResourceState after);
public void ResourceBarrier(Handle<GPUResource> resource, ResourceState before, ResourceState after);
/// <summary>
/// Sets the graphics root signature
/// </summary>
/// <param name="rootSignature">Root signature to set</param>
public void SetGraphicsRootSignature(IRootSignature rootSignature);
public void SetRootSignature(IRootSignature rootSignature);
/// <summary>
/// Sets the pipeline state object
/// </summary>
/// <param name="pipelineState">Pipeline state to set</param>
public void SetPipelineState(IPipelineStateController pipelineState);
public void SetPipelineState(IShaderPipeline pipelineState);
/// <summary>
/// Renders the specified mesh using the provided material.
/// </summary>
/// <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(MeshClass mesh, MaterialClass material);
public void SetVertexBuffer(uint slot, Handle<GraphicsBuffer> buffer, ulong offset = 0);
public void SetIndexBuffer(Handle<GraphicsBuffer> buffer, IndexType type, ulong offset = 0);
public void Draw(uint vertexCount, uint instanceCount = 1, uint startVertex = 0, uint startInstance = 0);
public void DrawIndexed(uint indexCount, uint instanceCount = 1, uint startIndex = 0, int baseVertex = 0, uint startInstance = 0);
/// <summary>
/// Dispatches compute threads
@@ -91,7 +107,7 @@ public interface ICommandBuffer : IDisposable
/// <param name="buffer">A handle to the buffer that will receive the uploaded data.</param>
/// <param name="data">A read-only span containing the data to upload to the buffer. The span must contain elements of type
/// <typeparamref name="T"/>.</param>
public void Upload<T>(BufferHandle buffer, ReadOnlySpan<T> data)
public void Upload<T>(Handle<GraphicsBuffer> buffer, ReadOnlySpan<T> data)
where T : unmanaged;
/// <summary>
@@ -102,7 +118,17 @@ public interface ICommandBuffer : IDisposable
/// <param name="subresources">A reference to the structure containing the subresource data to upload. The data must match the format and layout expected by the texture.</param>
/// <param name="numSubresources">The number of subresources to upload, starting from <paramref name="firstSubresource"/>.
/// Must be greater than zero and not exceed the remaining subresources in the texture.</param>
public void Upload(TextureHandle texture, uint firstSubresource, ref SubResourceData subresources, uint numSubresources);
public void Upload(Handle<Texture> texture, params ReadOnlySpan<SubResourceData> subresources);
/// <summary>
/// Copies a specified number of bytes from the source graphics buffer to the destination graphics buffer.
/// </summary>
/// <param name="dest">The handle to the destination graphics buffer where data will be written. Cannot be null.</param>
/// <param name="src">The handle to the source graphics buffer from which data will be read. Cannot be null.</param>
/// <param name="destOffset">The byte offset in the destination buffer at which to begin writing. Must be zero or greater.</param>
/// <param name="srcOffset">The byte offset in the source buffer at which to begin reading. Must be zero or greater.</param>
/// <param name="numBytes">The number of bytes to copy. If zero, copies the remaining bytes from the source buffer starting at <paramref name="srcOffset"/>.</param>
public void CopyBuffer(Handle<GraphicsBuffer> dest, Handle<GraphicsBuffer> src, ulong destOffset = 0, ulong srcOffset = 0, ulong numBytes = 0);
}
/// <summary>
@@ -116,16 +142,6 @@ public struct ViewportDesc
public float height;
public float minDepth;
public float maxDepth;
public ViewportDesc(float width, float height)
{
x = 0;
y = 0;
this.width = width;
this.height = height;
minDepth = 0.0f;
maxDepth = 1.0f;
}
}
/// <summary>
@@ -133,18 +149,10 @@ public struct ViewportDesc
/// </summary>
public struct RectDesc
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RectDesc(int left, int top, int right, int bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
public uint left;
public uint top;
public uint right;
public uint bottom;
}
/// <summary>
@@ -168,6 +176,27 @@ public enum ResourceState
Present = 0,
}
internal static class ResourceStateExtensions
{
public static ResourceStates ToD3D12States(this ResourceState state)
{
return state switch
{
ResourceState.Common or ResourceState.Present => ResourceStates.Common,
ResourceState.VertexAndConstantBuffer => ResourceStates.VertexAndConstantBuffer,
ResourceState.IndexBuffer => ResourceStates.IndexBuffer,
ResourceState.RenderTarget => ResourceStates.RenderTarget,
ResourceState.UnorderedAccess => ResourceStates.UnorderedAccess,
ResourceState.DepthWrite => ResourceStates.DepthWrite,
ResourceState.DepthRead => ResourceStates.DepthRead,
ResourceState.PixelShaderResource => ResourceStates.PixelShaderResource,
ResourceState.CopyDest => ResourceStates.CopyDest,
ResourceState.CopySource => ResourceStates.CopySource,
_ => throw new ArgumentException($"Unknown resource state: {state}")
};
}
}
public struct SubResourceData
{

View File

@@ -8,7 +8,7 @@ public interface ICommandQueue : IDisposable
/// <summary>
/// Type of commands this queue can execute
/// </summary>
CommandQueueType Type
public CommandQueueType Type
{
get;
}
@@ -17,32 +17,37 @@ public interface ICommandQueue : IDisposable
/// Submits a single command buffer for execution
/// </summary>
/// <param name="commandBuffer">Command buffer to submit</param>
void Submit(ICommandBuffer commandBuffer);
public void Submit(ICommandBuffer commandBuffer);
/// <summary>
/// Submits multiple command buffers for execution
/// </summary>
/// <param name="commandBuffers">Command buffers to submit</param>
void Submit(params ReadOnlySpan<ICommandBuffer> commandBuffers);
public void Submit(params ReadOnlySpan<ICommandBuffer> commandBuffers);
/// <summary>
/// Signals a fence with the specified value
/// </summary>
/// <param name="value">Value to signal</param>
/// <returns>The fence value that was signaled</returns>
ulong Signal(ulong value);
public ulong Signal(ulong value);
/// <summary>
/// Waits for the fence to reach the specified value
/// </summary>
/// <param name="value">Value to wait for</param>
void WaitForValue(ulong value);
public void WaitForValue(ulong value);
/// <summary>
/// Gets the last completed fence value
/// </summary>
/// <returns>Last completed fence value</returns>
ulong GetCompletedValue();
public ulong GetCompletedValue();
/// <summary>
/// Waits until all submitted commands have finished executing
/// </summary>
public void WaitIdle();
}
/// <summary>

View File

@@ -1,64 +0,0 @@
using Ghost.Graphics.Data;
using System.Runtime.CompilerServices;
using Win32.Graphics.Direct3D12;
namespace Ghost.Graphics.RHI;
public interface IDescriptorAllocator
{
public RenderTargetDescriptor AllocateRTV();
public RenderTargetDescriptor[] AllocateRTVs(uint count);
public DepthStencilDescriptor AllocateDSV();
public DepthStencilDescriptor[] AllocateDSVs(uint count);
public ShaderResourceDescriptor AllocateSRV();
public ShaderResourceDescriptor[] AllocateSRVs(uint count);
public SamplerDescriptor AllocateSampler();
public SamplerDescriptor[] AllocateSamplers(uint count);
public BindlessDescriptor AllocateBindless();
public BindlessDescriptor[] AllocateBindless(uint count);
public CpuDescriptorHandle GetCpuHandle(RenderTargetDescriptor descriptor);
public CpuDescriptorHandle GetCpuHandle(DepthStencilDescriptor descriptor);
public CpuDescriptorHandle GetCpuHandle(ShaderResourceDescriptor descriptor);
public GpuDescriptorHandle GetGpuHandle(ShaderResourceDescriptor descriptor);
public CpuDescriptorHandle GetCpuHandle(SamplerDescriptor descriptor);
public GpuDescriptorHandle GetGpuHandle(SamplerDescriptor descriptor);
public CpuDescriptorHandle GetCpuHandle(BindlessDescriptor descriptor);
public GpuDescriptorHandle GetGpuHandle(BindlessDescriptor descriptor);
public void Release(RenderTargetDescriptor descriptor);
public void Release(ReadOnlySpan<RenderTargetDescriptor> descriptors);
public void Release(DepthStencilDescriptor descriptor);
public void Release(ReadOnlySpan<DepthStencilDescriptor> descriptors);
public void Release(ShaderResourceDescriptor descriptor);
public void Release(ReadOnlySpan<ShaderResourceDescriptor> descriptors);
public void Release(SamplerDescriptor descriptor);
public void Release(ReadOnlySpan<SamplerDescriptor> descriptors);
public void Release(BindlessDescriptor descriptor);
public void Release(ReadOnlySpan<BindlessDescriptor> descriptors);
}

View File

@@ -14,7 +14,7 @@ public interface IShaderPipeline
}
}
public interface IPipelineStateController
public interface IPipelineLibrary
{
public void CompileShader(Identifier<Shader> id, string shaderPath);

View File

@@ -1,4 +1,6 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Win32.Graphics.Direct3D12;
namespace Ghost.Graphics.RHI;
@@ -25,6 +27,61 @@ public enum PipelineType
Compute
}
[StructLayout(LayoutKind.Explicit)]
public struct ResourceDesc
{
[FieldOffset(0)]
public TextureDesc textureDescription;
[FieldOffset(0)]
public BufferDesc bufferDescription;
public static ResourceDesc Buffer(BufferDesc desc)
{
return new ResourceDesc
{
bufferDescription = desc
};
}
public static ResourceDesc Texture(TextureDesc desc)
{
return new ResourceDesc
{
textureDescription = desc
};
}
internal static ResourceDesc FromD3D12(ResourceDescription desc)
{
if (desc.Dimension == ResourceDimension.Buffer)
{
return Buffer(new BufferDesc
{
Size = desc.Width,
Stride = 0,
Usage = BufferUsage.None,
CreationFlags = BufferCreationFlags.None,
MemoryType = MemoryType.Default
});
}
else
{
return Texture(new TextureDesc
{
Width = (uint)desc.Width,
Height = desc.Height,
Slice = desc.DepthOrArraySize,
Format = desc.Format.ToTextureFormat(),
Dimension = desc.Dimension.ToTextureDimension(),
MipLevels = desc.MipLevels,
Usage = TextureUsage.None,
CreationFlags = TextureCreationFlags.None
});
}
}
}
/// <summary>
/// Render target description
/// Supports either color OR depth rendering, not both
@@ -157,7 +214,7 @@ public struct RenderTargetDesc
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TextureDesc ToTextureDescriptor(RenderTargetDesc desc)
public static TextureDesc ToTextureDescripton(RenderTargetDesc desc)
{
var usage = desc.Type == RenderTargetType.Color ? TextureUsage.RenderTarget : TextureUsage.DepthStencil;
if (desc.CreationFlags.HasFlag(RenderTargetCreationFlags.AllowUAV))
@@ -329,6 +386,20 @@ public enum TextureDimension
TextureCubeArray = 5
}
public static class TextureDimensionExtension
{
public static TextureDimension ToTextureDimension(this ResourceDimension dimension)
{
return dimension switch
{
ResourceDimension.Texture1D => TextureDimension.Texture2D,
ResourceDimension.Texture2D => TextureDimension.Texture2D,
ResourceDimension.Texture3D => TextureDimension.Texture3D,
_ => TextureDimension.Unknown,
};
}
}
/// <summary>
/// Render target creation flags
/// </summary>

View File

@@ -1,4 +1,6 @@
using Ghost.Graphics.RHI;
using Ghost.Core;
using Ghost.Graphics.Data;
using Misaki.HighPerformance.Mathematics;
namespace Ghost.Graphics.RHI;
@@ -7,37 +9,42 @@ namespace Ghost.Graphics.RHI;
/// </summary>
public interface IRenderer : IDisposable
{
public uint2 Size
{
get;
}
/// <summary>
/// Sets the render target for this renderer
/// </summary>
/// <param name="renderTarget">Render target to render into</param>
void SetRenderTarget(IRenderTarget? renderTarget);
public void SetRenderTarget(Handle<Texture> renderTarget);
/// <summary>
/// Sets the swap chain for this renderer
/// </summary>
/// <param name="swapChain">Swap chain for presentation</param>
void SetSwapChain(ISwapChain? swapChain);
public void SetSwapChain(ISwapChain? swapChain);
/// <summary>
/// Executes any pending resize operations
/// </summary>
void ExecutePendingResize();
public void ExecutePendingResize();
/// <summary>
/// Renders a frame
/// </summary>
void Render();
public void Render();
/// <summary>
/// Requests a resize operation
/// </summary>
/// <param name="width">New width</param>
/// <param name="height">New height</param>
void RequestResize(uint width, uint height);
public void RequestResize(uint width, uint height);
/// <summary>
/// Waits for the GPU to complete all work
/// </summary>
void WaitIdle();
public void WaitIdle();
}

View File

@@ -1,120 +1,7 @@
using Ghost.Graphics.Data;
using Win32.Graphics.Dxgi.Common;
namespace Ghost.Graphics.RHI;
/// <summary>
/// Base interface for all graphics resources
/// </summary>
public interface IResource : IDisposable
{
/// <summary>
/// Current resource state
/// </summary>
ResourceState CurrentState
{
get;
}
/// <summary>
/// Resource name for debugging
/// </summary>
string Name
{
get; set;
}
/// <summary>
/// Size of the resource in bytes
/// </summary>
ulong Size
{
get;
}
}
/// <summary>
/// Texture resource interface
/// </summary>
public interface ITexture : IResource
{
/// <summary>
/// Width of the texture in pixels
/// </summary>
uint Width
{
get;
}
/// <summary>
/// Height of the texture in pixels
/// </summary>
uint Height
{
get;
}
/// <summary>
/// Texture format
/// </summary>
TextureFormat Format
{
get;
}
/// <summary>
/// Number of mip levels
/// </summary>
uint MipLevels
{
get;
}
}
/// <summary>
/// Buffer resource interface
/// </summary>
public interface IBuffer : IResource
{
/// <summary>
/// Buffer usage type
/// </summary>
public BufferUsage Usage
{
get;
}
public BufferHandle Handle
{
get;
}
/// <summary>
/// Maps the buffer for CPU access
/// </summary>
/// <returns>Pointer to mapped memory</returns>
public unsafe void* Map();
/// <summary>
/// Unmaps the buffer from CPU access
/// </summary>
public void Unmap();
}
/// <summary>
/// Render target interface for rendering operations
/// Supports either color OR depth rendering, not both
/// </summary>
public interface IRenderTarget : ITexture
{
/// <summary>
/// Type of render target (color or depth)
/// </summary>
RenderTargetType Type
{
get;
}
}
/// <summary>
/// Type of render target
/// </summary>
@@ -127,6 +14,8 @@ public enum RenderTargetType
/// <summary>
/// Texture format enumeration
/// </summary>
// TODO: Support compressed formats (BCn, ASTC, ETC2, etc)
public enum TextureFormat
{
Unknown,
@@ -162,4 +51,160 @@ public enum BufferCreationFlags
{
None = 0,
Bindless = 1 << 0
}
public enum IndexType
{
UInt16,
UInt32
}
internal static class TextureFormatExtensions
{
public static Format ToD3D12Format(this TextureFormat format)
{
return format switch
{
TextureFormat.R8G8B8A8_UNorm => Format.R8G8B8A8Unorm,
TextureFormat.B8G8R8A8_UNorm => Format.B8G8R8A8Unorm,
TextureFormat.R16G16B16A16_Float => Format.R16G16B16A16Float,
TextureFormat.R32G32B32A32_Float => Format.R32G32B32A32Float,
TextureFormat.D24_UNorm_S8_UInt => Format.D24UnormS8Uint,
TextureFormat.D32_Float => Format.D32Float,
_ => throw new NotSupportedException($"Texture format {format} is not supported."),
};
}
public static TextureFormat ToTextureFormat(this Format format)
{
return format switch
{
Format.R8G8B8A8Unorm => TextureFormat.R8G8B8A8_UNorm,
Format.B8G8R8A8Unorm => TextureFormat.B8G8R8A8_UNorm,
Format.R16G16B16A16Float => TextureFormat.R16G16B16A16_Float,
Format.R32G32B32A32Float => TextureFormat.R32G32B32A32_Float,
Format.D24UnormS8Uint => TextureFormat.D24_UNorm_S8_UInt,
Format.D32Float => TextureFormat.D32_Float,
_ => TextureFormat.Unknown,
};
}
public static int GetBytesPerPixel(this TextureFormat format)
{
return format switch
{
TextureFormat.R8G8B8A8_UNorm => 4,
TextureFormat.B8G8R8A8_UNorm => 4,
TextureFormat.R16G16B16A16_Float => 8,
TextureFormat.R32G32B32A32_Float => 16,
TextureFormat.D24_UNorm_S8_UInt => 4,
TextureFormat.D32_Float => 4,
_ => throw new NotSupportedException($"Texture format {format} is not supported."),
};
}
public static void GetSurfaceInfo(this TextureFormat format, int width, int height, out int rowPitch, out int slicePitch, out int rowCount)
{
var bc = false;
var packed = false;
var planar = false;
var bpe = 0;
//switch (format)
//{
// case Format.BC1Typeless:
// case Format.BC1Unorm:
// case Format.BC1UnormSrgb:
// case Format.BC4Typeless:
// case Format.BC4Unorm:
// case Format.BC4Snorm:
// bc = true;
// bpe = 8;
// break;
// case Format.BC2Typeless:
// case Format.BC2Unorm:
// case Format.BC2UnormSrgb:
// case Format.BC3Typeless:
// case Format.BC3Unorm:
// case Format.BC3UnormSrgb:
// case Format.BC5Typeless:
// case Format.BC5Unorm:
// case Format.BC5Snorm:
// case Format.BC6HTypeless:
// case Format.BC6HUF16:
// case Format.BC6HSF16:
// case Format.BC7Typeless:
// case Format.BC7Unorm:
// case Format.BC7UnormSrgb:
// bc = true;
// bpe = 16;
// break;
// case Format.R8G8_B8G8Unorm:
// case Format.G8R8_G8B8Unorm:
// case Format.YUY2:
// packed = true;
// bpe = 4;
// break;
// case Format.Y210:
// case Format.Y216:
// packed = true;
// bpe = 8;
// break;
// case Format.NV12:
// case Format.Opaque420:
// case Format.P208:
// planar = true;
// bpe = 2;
// break;
// case Format.P010:
// case Format.P016:
// planar = true;
// bpe = 4;
// break;
// default:
// break;
//}
if (bc)
{
var numBlocksWide = 0;
if (width > 0)
{
numBlocksWide = Math.Max(1, (width + 3) / 4);
}
var numBlocksHigh = 0;
if (height > 0)
{
numBlocksHigh = Math.Max(1, (height + 3) / 4);
}
rowPitch = numBlocksWide * bpe;
rowCount = numBlocksHigh;
slicePitch = rowPitch * numBlocksHigh;
}
else if (packed)
{
rowPitch = ((width + 1) >> 1) * bpe;
rowCount = height;
slicePitch = rowPitch * height;
}
else if (planar)
{
rowPitch = ((width + 1) >> 1) * bpe;
slicePitch = (rowPitch * height) + ((rowPitch * height + 1) >> 1);
rowCount = (int)(height + ((height + 1u) >> 1));
}
else
{
var bpp = GetBytesPerPixel(format) * 8;
rowPitch = (width * bpp + 7) / 8; // round up to nearest byte
rowCount = height;
slicePitch = rowPitch * height;
}
}
}

View File

@@ -1,4 +1,6 @@
using Ghost.Graphics.Data;
using Ghost.Core;
using Ghost.Graphics.Data;
using Misaki.HighPerformance.LowLevel.Collections;
namespace Ghost.Graphics.RHI;
@@ -9,25 +11,46 @@ public interface IResourceAllocator
/// </summary>
/// <param name="desc">Texture description</param>
/// <returns>A new texture handle point to the resource</returns>
public TextureHandle CreateTexture(ref readonly TextureDesc desc, bool tempResource = false);
public Handle<Texture> CreateTexture(ref readonly TextureDesc desc, bool tempResource = false);
/// <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 TextureHandle CreateRenderTarget(ref readonly RenderTargetDesc desc, bool tempResource = false);
/// <returns>A new texture handle point to the resource</returns>
public Handle<Texture> CreateRenderTarget(ref readonly RenderTargetDesc 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 CreateBuffer(ref readonly BufferDesc desc, bool tempResource = false);
public Handle<GraphicsBuffer> CreateBuffer(ref readonly BufferDesc desc, bool tempResource = false);
/// <summary>
/// Creates a new mesh from the specified vertex and index data.
/// </summary>
/// <param name="vertices">A UnsafeList containing the vertices that define the geometry of the mesh. Must contain at least one vertex.</param>
/// <param name="indices">A UnsafeList containing the indices that specify how vertices are connected to form primitives. Must contain at least one index.</param>
/// <returns>An <see cref="Identifier{Mesh}"/> representing the newly created mesh.</returns>
public Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices);
/// <summary>
/// Creates a new material instance using the specified shader.
/// </summary>
/// <param name="shader">The identifier of the shader to associate with the new material. Cannot be null.</param>
/// <returns>An <see cref="Identifier{Material}"/> representing the newly created material.</returns>
public Handle<Material> CreateMaterial(Identifier<Shader> shader);
/// <summary>
/// Creates a new shader and returns its unique identifier.
/// </summary>
/// <returns>An <see cref="Identifier{Shader}"/> representing the newly created shader.</returns>
public Identifier<Shader> CreateShader();
/// <summary>
/// Release a resource given its handle
/// </summary>
/// <param name="handle">Resource handle</param>
public void ReleaseResource(ResourceHandle handle);
public void ReleaseResource(Handle<GPUResource> handle);
}

View File

@@ -6,51 +6,127 @@ namespace Ghost.Graphics.RHI;
public interface IResourceDatabase
{
/// <summary>
/// Get the raw gpu resource pointer from a resource handle
/// Imports an external unmanaged resource and returns a handle for use within the resource management system.
/// </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<T>(ResourceHandle handle)
where T: unmanaged;
/// <typeparam name="T">The type of the unmanaged resource pointer to import.</typeparam>
/// <param name="resourcePtr">A pointer to the external unmanaged resource to be imported. Must remain valid for the duration of the resource's usage.</param>
/// <param name="initialState">The initial state to assign to the imported resource.</param>
/// <returns>A handle representing the imported resource, which can be used for subsequent operations.</returns>
public unsafe Handle<GPUResource> ImportExternalResource<T>(T resourcePtr, ResourceState initialState)
where T : unmanaged;
/// <summary>
/// Retrieves the current state of the specified resource.
/// </summary>
/// <param name="handle">The handle that uniquely identifies the resource whose state is to be retrieved. Must not be null.</param>
/// <returns>A ResourceState value representing the current state of the resource associated with the specified handle.</returns>
public ResourceState GetResourceState(ResourceHandle handle);
public ResourceState GetResourceState(Handle<GPUResource> handle);
/// <summary>
/// Sets the state of the specified resource handle to the given value.
/// </summary>
/// <param name="handle">The handle that identifies the resource whose state will be updated. Cannot be null.</param>
/// <param name="state">The new state to assign to the resource represented by <paramref name="handle"/>.</param>
public void SetResourceState(ResourceHandle handle, ResourceState state);
public void SetResourceState(Handle<GPUResource> handle, ResourceState state);
/// <summary>
/// Retrieves the description of a GPU resource associated with the specified handle.
/// </summary>
/// <param name="handle">A handle that identifies the GPU resource for which to obtain the description. Must reference a valid resource.</param>
/// <returns>A ResourceDesc structure containing details about the specified GPU resource.</returns>
public ResourceDesc GetResourceDescription(Handle<GPUResource> handle);
/// <summary>
/// Retrieves the bindless index associated with the specified GPU resource handle.
/// </summary>
/// <param name="handle">A handle to the GPU resource for which to obtain the bindless index. Must reference a valid, currently registered resource.</param>
/// <returns>The bindless index corresponding to the specified GPU resource handle. -1 if the resource does not support bindless access or is not found.</returns>
public int GetBindlessIndex(Handle<GPUResource> handle);
/// <summary>
/// Removes a resource from the database using its handle.
/// </summary>
/// <param name="handle">The handle of the resource to be removed.</param>
public void RemoveResource(ResourceHandle handle);
public void ReleaseResource(Handle<GPUResource> handle);
public Identifier<Mesh> AddMesh(ref readonly Mesh mesh);
/// <summary>
/// Adds a mesh to the resource database and returns its handle.
/// </summary>
/// <param name="mesh">The mesh data to be added to the database.</param>
/// <returns>The <see cref="Handle{Mesh}"/> representing the newly added mesh.</returns>"/>
public Handle<Mesh> AddMesh(ref readonly Mesh mesh);
public bool HasMesh(Identifier<Mesh> id);
/// <summary>
/// Determines whether a mesh with the specified Handle exists.
/// </summary>
/// <param name="handle">The handle of the mesh to check for existence. Cannot be null.</param>
/// <returns>true if a mesh with the specified Handle exists; otherwise, false.</returns>
public bool HasMesh(Handle<Mesh> handle);
public Mesh GetMesh(Identifier<Mesh> id);
/// <summary>
/// Returns a reference to the mesh associated with the specified handle.
/// </summary>
/// <param name="handle">The handle of the mesh to retrieve. Must refer to a valid mesh; otherwise, the behavior is undefined.</param>
/// <returns>A reference to the mesh corresponding to the specified handle.</returns>
public ref Mesh GetMeshReference(Handle<Mesh> handle);
public ref Mesh GetMeshReference(Identifier<Mesh> id);
/// <summary>
/// Releases the mesh resource associated with the specified handle, freeing any resources held by it. Includes both CPU and GPU resources.
/// </summary>
/// <param name="handle">The handle of the mesh to release. Must refer to a mesh that was previously created and not already released.</param>
public void ReleaseMesh(Handle<Mesh> handle);
public void RemoveMesh(Identifier<Mesh> id);
/// <summary>
/// Adds a new material to the collection and returns its unique handle.
/// </summary>
/// <param name="material">The material to add. The material must be fully initialized before calling this method.</param>
/// <returns>The <see cref="Handle{Material}"/> representing the newly added material.</returns>
public Handle<Material> AddMaterial(ref readonly Material material);
/// <summary>
/// Determines whether a material with the specified handle exists in the collection.
/// </summary>
/// <param name="handle">The handle of the material to check for existence.</param>
/// <returns>true if a material with the specified handle exists; otherwise, false.</returns>
public bool HasMaterial(Handle<Material> handle);
/// <summary>
/// Gets a reference to the material associated with the specified handle.
/// </summary>
/// <param name="handle">The handle of the material to retrieve. Must refer to a valid material.</param>
/// <returns>A reference to the material corresponding to the specified handle.</returns>
public ref Material GetMaterialReference(Handle<Material> handle);
/// <summary>
/// Releases the material associated with the specified handle, making it available for reuse or disposal.
/// </summary>
/// <param name="handle">The handle of the material to release. Must refer to a material that has been previously acquired.</param>
public void ReleaseMaterial(Handle<Material> handle);
/// <summary>
/// Adds the specified shader to the collection and returns its unique identifier.
/// </summary>
/// <param name="shader">The shader to add. The shader is passed by read-only reference and will not be modified.</param>
/// <returns>The <see cref="Identifier{Shader}"/> representing the newly added shader.</returns>
public Identifier<Shader> AddShader(ref readonly Shader shader);
/// <summary>
/// Determines whether a shader with the specified identifier exists in the collection.
/// </summary>
/// <param name="id">The identifier of the shader to check for existence.</param>
/// <returns>true if a shader with the specified identifier exists; otherwise, false.</returns>
public bool HasShader(Identifier<Shader> id);
public Shader GetShader(Identifier<Shader> id);
/// <summary>
/// Returns a reference to the shader associated with the specified identifier.
/// </summary>
/// <param name="id">The identifier of the shader to retrieve. Must refer to a valid shader.</param>
/// <returns>A reference to the shader corresponding to the specified identifier.</returns>
public ref Shader GetShaderReference(Identifier<Shader> id);
public void RemoveShader(Identifier<Shader> id);
/// <summary>
/// Releases the shader associated with the specified identifier, freeing any resources allocated to it.
/// </summary>
/// <param name="id">The identifier of the shader to release. Must refer to a valid, previously created shader.</param>
public void ReleaseShader(Identifier<Shader> id);
}

View File

@@ -1,4 +1,5 @@
using Ghost.Graphics.Contracts;
using Ghost.Core;
using Ghost.Graphics.Data;
namespace Ghost.Graphics.RHI;
@@ -10,36 +11,45 @@ public interface ISwapChain : IDisposable
/// <summary>
/// Width of the swap chain back buffers
/// </summary>
uint Width { get; }
public uint Width
{
get;
}
/// <summary>
/// Height of the swap chain back buffers
/// </summary>
uint Height { get; }
public uint Height
{
get;
}
/// <summary>
/// Number of back buffers
/// </summary>
uint BufferCount { get; }
public uint BufferCount
{
get;
}
/// <summary>
/// Gets the current back buffer texture
/// </summary>
/// <returns>Current back buffer texture</returns>
IRenderTarget GetCurrentBackBuffer();
public Handle<Texture> GetCurrentBackBuffer();
/// <summary>
/// Presents the rendered frame
/// </summary>
/// <param name="vsync">Enable vertical synchronization</param>
void Present(bool vsync = true);
public void Present(bool vsync = true);
/// <summary>
/// Resizes the swap chain back buffers
/// </summary>
/// <param name="width">New width</param>
/// <param name="height">New height</param>
void Resize(uint width, uint height);
public void Resize(uint width, uint height);
}
/// <summary>
@@ -84,25 +94,25 @@ public struct SwapChainTarget
/// <summary>
/// Target type
/// </summary>
public SwapChainTargetType Type;
public SwapChainTargetType type;
/// <summary>
/// Window handle for HWND targets
/// </summary>
public nint WindowHandle;
public nint windowHandle;
/// <summary>
/// Composition surface for UWP/WinUI targets
/// </summary>
public object? CompositionSurface;
public object? compositionSurface;
public static SwapChainTarget FromWindowHandle(nint hwnd)
{
return new SwapChainTarget
{
Type = SwapChainTargetType.WindowHandle,
WindowHandle = hwnd,
CompositionSurface = null
type = SwapChainTargetType.WindowHandle,
windowHandle = hwnd,
compositionSurface = null
};
}
@@ -110,9 +120,9 @@ public struct SwapChainTarget
{
return new SwapChainTarget
{
Type = SwapChainTargetType.Composition,
WindowHandle = nint.Zero,
CompositionSurface = surface
type = SwapChainTargetType.Composition,
windowHandle = nint.Zero,
compositionSurface = surface
};
}
}