Refactoring Rendering backend
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -14,7 +14,7 @@ public interface IShaderPipeline
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPipelineStateController
|
||||
public interface IPipelineLibrary
|
||||
{
|
||||
public void CompileShader(Identifier<Shader> id, string shaderPath);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user