forked from Misaki/GhostEngine
Refactor and enhance codebase for maintainability
Refactored and reorganized the codebase to improve readability, performance, and maintainability. Introduced new interfaces and structs for better resource management, updated project configuration files, and refactored shader and graphics pipeline management. Improved error handling, code formatting, and removed unused code and namespaces. Updated DLL references and method signatures for consistency and maintainability.
This commit is contained in:
603
Ghost.Graphics/RHI/Common.cs
Normal file
603
Ghost.Graphics/RHI/Common.cs
Normal file
@@ -0,0 +1,603 @@
|
||||
using Misaki.HighPerformance.Utilities;
|
||||
using System.IO.Hashing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
||||
namespace Ghost.Graphics.RHI;
|
||||
|
||||
public readonly struct ShaderPassKey
|
||||
{
|
||||
public readonly ulong value;
|
||||
|
||||
public ShaderPassKey(ulong value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ShaderPassKey(string passId)
|
||||
{
|
||||
var passIdSpan = passId.AsSpan();
|
||||
value = XxHash3.HashToUInt64(MemoryMarshal.AsBytes(passIdSpan));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return value.ToString("X16");
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct GraphicsPipelineKey
|
||||
{
|
||||
public readonly ulong value;
|
||||
|
||||
public GraphicsPipelineKey(ulong value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return value.ToString("X16");
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
internal struct GraphicsPipelineHash
|
||||
{
|
||||
[InlineArray(8)]
|
||||
public struct rtv_array
|
||||
{
|
||||
public TextureFormat rtvFormats;
|
||||
}
|
||||
|
||||
public rtv_array rtvFormats;
|
||||
public ShaderPassKey id;
|
||||
public uint rtvCount;
|
||||
public TextureFormat dsvFormat;
|
||||
// Do we need to store blend state?
|
||||
// TODO: Variants
|
||||
|
||||
public readonly GraphicsPipelineKey GetKey()
|
||||
{
|
||||
Span<ulong> data = stackalloc ulong[3 + 8];
|
||||
data[0] = id.value;
|
||||
data[1] = rtvCount;
|
||||
data[2] = (ulong)dsvFormat;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
data[3 + i] = (ulong)rtvFormats[i];
|
||||
}
|
||||
|
||||
var bytes = MemoryMarshal.AsBytes(data);
|
||||
return new GraphicsPipelineKey(XxHash3.HashToUInt64(bytes));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public struct ViewportDesc
|
||||
{
|
||||
public float x;
|
||||
public float y;
|
||||
public float width;
|
||||
public float height;
|
||||
public float minDepth;
|
||||
public float maxDepth;
|
||||
}
|
||||
|
||||
public struct RectDesc
|
||||
{
|
||||
public uint left;
|
||||
public uint top;
|
||||
public uint right;
|
||||
public uint bottom;
|
||||
}
|
||||
|
||||
public struct SubResourceData
|
||||
{
|
||||
public unsafe void* pData;
|
||||
public nint rowPitch;
|
||||
public nint slicePitch;
|
||||
}
|
||||
|
||||
[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(D3D12_RESOURCE_DESC desc)
|
||||
{
|
||||
if (desc.Dimension == D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
return Buffer(new BufferDesc
|
||||
{
|
||||
Size = (uint)desc.Width,
|
||||
Stride = 0,
|
||||
Usage = BufferUsage.None,
|
||||
MemoryType = ResourceMemoryType.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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Render target description
|
||||
/// Supports either color OR depth rendering, not both
|
||||
/// </summary>
|
||||
public struct RenderTargetDesc
|
||||
{
|
||||
/// <summary>
|
||||
/// Width of the render target
|
||||
/// </summary>
|
||||
public uint Width
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Height of the render target
|
||||
/// </summary>
|
||||
public uint Height
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Slice of the render target
|
||||
/// </summary>
|
||||
public uint Slice
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of render target
|
||||
/// </summary>
|
||||
public RenderTargetType Type
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Target texture format
|
||||
/// </summary>
|
||||
public TextureFormat Format
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture dimension
|
||||
/// </summary>
|
||||
public TextureDimension Dimension
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creation flags for the render target
|
||||
/// </summary>
|
||||
public RenderTargetCreationFlags CreationFlags
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of mip levels. 0 to generate full mip chain
|
||||
/// </summary>
|
||||
public uint MipLevels
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of samples for MSAA
|
||||
/// </summary>
|
||||
public uint SampleCount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a color render target
|
||||
/// </summary>
|
||||
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.DynamicallyResolution | RenderTargetCreationFlags.GenerateMips,
|
||||
uint mipLevels = 0u, uint sampleCount = 1)
|
||||
{
|
||||
return new RenderTargetDesc
|
||||
{
|
||||
Width = width,
|
||||
Height = height,
|
||||
Slice = slice,
|
||||
Type = RenderTargetType.Color,
|
||||
Format = format,
|
||||
Dimension = dimension,
|
||||
CreationFlags = creationFlags,
|
||||
MipLevels = mipLevels,
|
||||
SampleCount = sampleCount
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a depth render target
|
||||
/// </summary>
|
||||
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.DynamicallyResolution,
|
||||
uint mipLevels = 0u, uint sampleCount = 1)
|
||||
{
|
||||
return new RenderTargetDesc
|
||||
{
|
||||
Width = width,
|
||||
Height = height,
|
||||
Slice = slice,
|
||||
Type = RenderTargetType.Depth,
|
||||
Format = format,
|
||||
Dimension = dimension,
|
||||
CreationFlags = creationFlags,
|
||||
MipLevels = mipLevels,
|
||||
SampleCount = sampleCount
|
||||
};
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TextureDesc ToTextureDescripton(RenderTargetDesc desc)
|
||||
{
|
||||
var usage = desc.Type == RenderTargetType.Color ? TextureUsage.RenderTarget : TextureUsage.DepthStencil;
|
||||
if (desc.CreationFlags.HasFlag(RenderTargetCreationFlags.AllowUAV))
|
||||
{
|
||||
usage |= TextureUsage.UnorderedAccess;
|
||||
}
|
||||
|
||||
return new TextureDesc
|
||||
{
|
||||
Width = desc.Width,
|
||||
Height = desc.Height,
|
||||
Slice = desc.Slice,
|
||||
Format = desc.Format,
|
||||
Dimension = desc.Dimension,
|
||||
MipLevels = desc.MipLevels,
|
||||
Usage = usage,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture description
|
||||
/// </summary>
|
||||
public struct TextureDesc
|
||||
{
|
||||
/// <summary>
|
||||
/// Width of the texture
|
||||
/// </summary>
|
||||
public uint Width
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Height of the texture
|
||||
/// </summary>
|
||||
public uint Height
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Slice of the texture
|
||||
/// </summary>
|
||||
public uint Slice
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture format
|
||||
/// </summary>
|
||||
public TextureFormat Format
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture dimension
|
||||
/// </summary>
|
||||
public TextureDimension Dimension
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of mip levels. 0 to generate full mip chain
|
||||
/// </summary>
|
||||
public uint MipLevels
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture usage flags
|
||||
/// </summary>
|
||||
public TextureUsage Usage
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Buffer description
|
||||
/// </summary>
|
||||
public struct BufferDesc
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of the buffer in bytes
|
||||
/// </summary>
|
||||
public ulong Size
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public uint Stride
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Buffer usage flags
|
||||
/// </summary>
|
||||
public BufferUsage Usage
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Memory type for the buffer
|
||||
/// </summary>
|
||||
public ResourceMemoryType MemoryType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TextureDimensionExtension
|
||||
{
|
||||
public static TextureDimension ToTextureDimension(this D3D12_RESOURCE_DIMENSION dimension)
|
||||
{
|
||||
return dimension switch
|
||||
{
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE1D => TextureDimension.Texture2D,
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE2D => TextureDimension.Texture2D,
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE3D => TextureDimension.Texture3D,
|
||||
_ => TextureDimension.Unknown,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Flags]
|
||||
public enum ResourceState
|
||||
{
|
||||
Common = 0,
|
||||
VertexAndConstantBuffer = 1 << 0,
|
||||
IndexBuffer = 1 << 1,
|
||||
RenderTarget = 1 << 2,
|
||||
UnorderedAccess = 1 << 3,
|
||||
DepthWrite = 1 << 4,
|
||||
DepthRead = 1 << 5,
|
||||
PixelShaderResource = 1 << 6,
|
||||
CopyDest = 1 << 7,
|
||||
CopySource = 1 << 8,
|
||||
GenericRead = 1 << 9,
|
||||
IndirectArgument = 1 << 10,
|
||||
Present = 0,
|
||||
}
|
||||
|
||||
public enum CommandQueueType
|
||||
{
|
||||
Graphics,
|
||||
Compute,
|
||||
Copy
|
||||
}
|
||||
|
||||
public enum CommandBufferType
|
||||
{
|
||||
Graphics,
|
||||
Compute,
|
||||
Copy
|
||||
}
|
||||
|
||||
public enum PipelineType
|
||||
{
|
||||
Graphics,
|
||||
Compute
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum RenderTargetCreationFlags
|
||||
{
|
||||
None = 0,
|
||||
AllowUAV = 1 << 0,
|
||||
AllowMSAA = 1 << 1,
|
||||
DynamicallyResolution = 1 << 2,
|
||||
GenerateMips = 1 << 3
|
||||
}
|
||||
|
||||
public enum ResourceMemoryType
|
||||
{
|
||||
Default, // GPU memory
|
||||
Upload, // CPU-to-GPU memory
|
||||
Readback // GPU-to-CPU memory
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum TextureUsage
|
||||
{
|
||||
None = 0,
|
||||
ShaderResource = 1 << 0,
|
||||
RenderTarget = 1 << 1,
|
||||
DepthStencil = 1 << 2,
|
||||
UnorderedAccess = 1 << 3
|
||||
}
|
||||
|
||||
public enum TextureDimension
|
||||
{
|
||||
Unknown = -1,
|
||||
None = 0,
|
||||
Texture2D = 1,
|
||||
Texture3D = 2,
|
||||
TextureCube = 3,
|
||||
Texture2DArray = 4,
|
||||
TextureCubeArray = 5
|
||||
}
|
||||
|
||||
public enum RenderTargetType
|
||||
{
|
||||
Color,
|
||||
Depth
|
||||
}
|
||||
|
||||
// TODO: Support compressed formats (BCn, ASTC, ETC2, etc)
|
||||
public enum TextureFormat
|
||||
{
|
||||
Unknown,
|
||||
R8G8B8A8_UNorm,
|
||||
B8G8R8A8_UNorm,
|
||||
R16G16B16A16_Float,
|
||||
R32G32B32A32_Float,
|
||||
D24_UNorm_S8_UInt,
|
||||
D32_Float
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum BufferUsage
|
||||
{
|
||||
None = 0,
|
||||
Vertex = 1 << 0,
|
||||
Index = 1 << 1,
|
||||
Constant = 1 << 2,
|
||||
Structured = 1 << 3,
|
||||
Raw = 1 << 4,
|
||||
Upload = 1 << 5,
|
||||
Readback = 1 << 6,
|
||||
IndirectArgument = 1 << 7,
|
||||
|
||||
ShaderResource = Vertex | Index | Constant
|
||||
}
|
||||
|
||||
public enum IndexType
|
||||
{
|
||||
UInt16,
|
||||
UInt32
|
||||
}
|
||||
|
||||
// Shader compiler
|
||||
|
||||
internal ref struct CompilerConfig
|
||||
{
|
||||
public ReadOnlySpan<string> includes;
|
||||
public ReadOnlySpan<string> defines;
|
||||
public string shaderPath;
|
||||
public string entryPoint;
|
||||
public ShaderStage stage;
|
||||
public CompilerTier tier;
|
||||
public CompilerOptimizeLevel optimizeLevel;
|
||||
public CompilerOption options;
|
||||
}
|
||||
|
||||
internal enum CompilerTier
|
||||
{
|
||||
Tier0,
|
||||
Tier1,
|
||||
Tier2
|
||||
}
|
||||
|
||||
internal enum CompilerOptimizeLevel
|
||||
{
|
||||
O0,
|
||||
O1,
|
||||
O2,
|
||||
O3
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum CompilerOption
|
||||
{
|
||||
None = 0,
|
||||
KeepDebugInfo = 1 << 0,
|
||||
KeepReflections = 1 << 1,
|
||||
WarnAsError = 1 << 2
|
||||
}
|
||||
|
||||
internal enum ShaderStage
|
||||
{
|
||||
TaskShader,
|
||||
MeshShader,
|
||||
PixelShader,
|
||||
ComputeShader
|
||||
}
|
||||
@@ -131,51 +131,6 @@ public interface ICommandBuffer : IDisposable
|
||||
public void CopyBuffer(Handle<GraphicsBuffer> dest, Handle<GraphicsBuffer> src, ulong destOffset = 0, ulong srcOffset = 0, ulong numBytes = 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Viewport description
|
||||
/// </summary>
|
||||
public struct ViewportDesc
|
||||
{
|
||||
public float x;
|
||||
public float y;
|
||||
public float width;
|
||||
public float height;
|
||||
public float minDepth;
|
||||
public float maxDepth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rectangle description
|
||||
/// </summary>
|
||||
public struct RectDesc
|
||||
{
|
||||
public uint left;
|
||||
public uint top;
|
||||
public uint right;
|
||||
public uint bottom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resource states
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ResourceState
|
||||
{
|
||||
Common = 0,
|
||||
VertexAndConstantBuffer = 1 << 0,
|
||||
IndexBuffer = 1 << 1,
|
||||
RenderTarget = 1 << 2,
|
||||
UnorderedAccess = 1 << 3,
|
||||
DepthWrite = 1 << 4,
|
||||
DepthRead = 1 << 5,
|
||||
PixelShaderResource = 1 << 6,
|
||||
CopyDest = 1 << 7,
|
||||
CopySource = 1 << 8,
|
||||
GenericRead = 1 << 9,
|
||||
IndirectArgument = 1 << 10,
|
||||
Present = 0,
|
||||
}
|
||||
|
||||
internal static class ResourceStateExtensions
|
||||
{
|
||||
public static D3D12_RESOURCE_STATES ToD3D12States(this ResourceState state)
|
||||
@@ -196,11 +151,3 @@ internal static class ResourceStateExtensions
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public struct SubResourceData
|
||||
{
|
||||
public unsafe void* pData;
|
||||
public nint rowPitch;
|
||||
public nint slicePitch;
|
||||
}
|
||||
@@ -48,14 +48,4 @@ public interface ICommandQueue : IDisposable
|
||||
/// Waits until all submitted commands have finished executing
|
||||
/// </summary>
|
||||
public void WaitIdle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command queue types
|
||||
/// </summary>
|
||||
public enum CommandQueueType
|
||||
{
|
||||
Graphics,
|
||||
Compute,
|
||||
Copy
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.Data;
|
||||
using Ghost.Core.Graphics;
|
||||
|
||||
namespace Ghost.Graphics.RHI;
|
||||
|
||||
@@ -16,9 +15,8 @@ public interface IShaderPipeline
|
||||
|
||||
public interface IPipelineLibrary
|
||||
{
|
||||
public void CompileShader(Identifier<Shader> id, string shaderPath);
|
||||
|
||||
public void PreCookPipelineState();
|
||||
|
||||
public IShaderPipeline GetShaderPipeline(Identifier<Shader> id);
|
||||
void CompilePass(IPassDescriptor descriptor);
|
||||
void CompileShader(ShaderDescriptor descriptor);
|
||||
void PreCookPipelineState();
|
||||
void SaveLibraryToDisk(string filePath);
|
||||
}
|
||||
@@ -28,14 +28,4 @@ public interface IRenderDevice : IDisposable
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command buffer types
|
||||
/// </summary>
|
||||
public enum CommandBufferType
|
||||
{
|
||||
Graphics,
|
||||
Compute,
|
||||
Copy
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
||||
namespace Ghost.Graphics.RHI;
|
||||
|
||||
/// <summary>
|
||||
@@ -16,391 +12,4 @@ public interface IRootSignature : IDisposable
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pipeline types
|
||||
/// </summary>
|
||||
public enum PipelineType
|
||||
{
|
||||
Graphics,
|
||||
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(D3D12_RESOURCE_DESC desc)
|
||||
{
|
||||
if (desc.Dimension == D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
return Buffer(new BufferDesc
|
||||
{
|
||||
Size = (uint)desc.Width,
|
||||
Stride = 0,
|
||||
Usage = BufferUsage.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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Render target description
|
||||
/// Supports either color OR depth rendering, not both
|
||||
/// </summary>
|
||||
public struct RenderTargetDesc
|
||||
{
|
||||
/// <summary>
|
||||
/// Width of the render target
|
||||
/// </summary>
|
||||
public uint Width
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Height of the render target
|
||||
/// </summary>
|
||||
public uint Height
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Slice of the render target
|
||||
/// </summary>
|
||||
public uint Slice
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of render target
|
||||
/// </summary>
|
||||
public RenderTargetType Type
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Target texture format
|
||||
/// </summary>
|
||||
public TextureFormat Format
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture dimension
|
||||
/// </summary>
|
||||
public TextureDimension Dimension
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creation flags for the render target
|
||||
/// </summary>
|
||||
public RenderTargetCreationFlags CreationFlags
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of mip levels. 0 to generate full mip chain
|
||||
/// </summary>
|
||||
public uint MipLevels
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of samples for MSAA
|
||||
/// </summary>
|
||||
public uint SampleCount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a color render target
|
||||
/// </summary>
|
||||
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.DynamicallyResolution | RenderTargetCreationFlags.GenerateMips,
|
||||
uint mipLevels = 0u, uint sampleCount = 1)
|
||||
{
|
||||
return new RenderTargetDesc
|
||||
{
|
||||
Width = width,
|
||||
Height = height,
|
||||
Slice = slice,
|
||||
Type = RenderTargetType.Color,
|
||||
Format = format,
|
||||
Dimension = dimension,
|
||||
CreationFlags = creationFlags,
|
||||
MipLevels = mipLevels,
|
||||
SampleCount = sampleCount
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a depth render target
|
||||
/// </summary>
|
||||
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.DynamicallyResolution,
|
||||
uint mipLevels = 0u, uint sampleCount = 1)
|
||||
{
|
||||
return new RenderTargetDesc
|
||||
{
|
||||
Width = width,
|
||||
Height = height,
|
||||
Slice = slice,
|
||||
Type = RenderTargetType.Depth,
|
||||
Format = format,
|
||||
Dimension = dimension,
|
||||
CreationFlags = creationFlags,
|
||||
MipLevels = mipLevels,
|
||||
SampleCount = sampleCount
|
||||
};
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TextureDesc ToTextureDescripton(RenderTargetDesc desc)
|
||||
{
|
||||
var usage = desc.Type == RenderTargetType.Color ? TextureUsage.RenderTarget : TextureUsage.DepthStencil;
|
||||
if (desc.CreationFlags.HasFlag(RenderTargetCreationFlags.AllowUAV))
|
||||
{
|
||||
usage |= TextureUsage.UnorderedAccess;
|
||||
}
|
||||
|
||||
return new TextureDesc
|
||||
{
|
||||
Width = desc.Width,
|
||||
Height = desc.Height,
|
||||
Slice = desc.Slice,
|
||||
Format = desc.Format,
|
||||
Dimension = desc.Dimension,
|
||||
MipLevels = desc.MipLevels,
|
||||
Usage = usage,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture description
|
||||
/// </summary>
|
||||
public struct TextureDesc
|
||||
{
|
||||
/// <summary>
|
||||
/// Width of the texture
|
||||
/// </summary>
|
||||
public uint Width
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Height of the texture
|
||||
/// </summary>
|
||||
public uint Height
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Slice of the texture
|
||||
/// </summary>
|
||||
public uint Slice
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture format
|
||||
/// </summary>
|
||||
public TextureFormat Format
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture dimension
|
||||
/// </summary>
|
||||
public TextureDimension Dimension
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of mip levels. 0 to generate full mip chain
|
||||
/// </summary>
|
||||
public uint MipLevels
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture usage flags
|
||||
/// </summary>
|
||||
public TextureUsage Usage
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Buffer description
|
||||
/// </summary>
|
||||
public struct BufferDesc
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of the buffer in bytes
|
||||
/// </summary>
|
||||
public uint Size
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public uint Stride
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Buffer usage flags
|
||||
/// </summary>
|
||||
public BufferUsage Usage
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Memory type for the buffer
|
||||
/// </summary>
|
||||
public MemoryType MemoryType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture usage flags
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum TextureUsage
|
||||
{
|
||||
None = 0,
|
||||
ShaderResource = 1 << 0,
|
||||
RenderTarget = 1 << 1,
|
||||
DepthStencil = 1 << 2,
|
||||
UnorderedAccess = 1 << 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dimensions of the texture
|
||||
/// </summary>
|
||||
public enum TextureDimension
|
||||
{
|
||||
Unknown = -1,
|
||||
None = 0,
|
||||
Texture2D = 1,
|
||||
Texture3D = 2,
|
||||
TextureCube = 3,
|
||||
Texture2DArray = 4,
|
||||
TextureCubeArray = 5
|
||||
}
|
||||
|
||||
public static class TextureDimensionExtension
|
||||
{
|
||||
public static TextureDimension ToTextureDimension(this D3D12_RESOURCE_DIMENSION dimension)
|
||||
{
|
||||
return dimension switch
|
||||
{
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE1D => TextureDimension.Texture2D,
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE2D => TextureDimension.Texture2D,
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE3D => TextureDimension.Texture3D,
|
||||
_ => TextureDimension.Unknown,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Render target creation flags
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum RenderTargetCreationFlags
|
||||
{
|
||||
None = 0,
|
||||
AllowUAV = 1 << 0,
|
||||
AllowMSAA = 1 << 1,
|
||||
DynamicallyResolution = 1 << 2,
|
||||
GenerateMips = 1 << 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Memory types for resources
|
||||
/// </summary>
|
||||
public enum MemoryType
|
||||
{
|
||||
Default, // GPU memory
|
||||
Upload, // CPU-to-GPU memory
|
||||
Readback // GPU-to-CPU memory
|
||||
}
|
||||
@@ -2,56 +2,6 @@ using TerraFX.Interop.DirectX;
|
||||
|
||||
namespace Ghost.Graphics.RHI;
|
||||
|
||||
/// <summary>
|
||||
/// Type of render target
|
||||
/// </summary>
|
||||
public enum RenderTargetType
|
||||
{
|
||||
Color,
|
||||
Depth
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Texture format enumeration
|
||||
/// </summary>
|
||||
|
||||
// TODO: Support compressed formats (BCn, ASTC, ETC2, etc)
|
||||
public enum TextureFormat
|
||||
{
|
||||
Unknown,
|
||||
R8G8B8A8_UNorm,
|
||||
B8G8R8A8_UNorm,
|
||||
R16G16B16A16_Float,
|
||||
R32G32B32A32_Float,
|
||||
D24_UNorm_S8_UInt,
|
||||
D32_Float
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Buffer usage flags
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum BufferUsage
|
||||
{
|
||||
None = 0,
|
||||
Vertex = 1 << 0,
|
||||
Index = 1 << 1,
|
||||
Constant = 1 << 2,
|
||||
Structured = 1 << 3,
|
||||
Raw = 1 << 4,
|
||||
Upload = 1 << 5,
|
||||
Readback = 1 << 6,
|
||||
IndirectArgument = 1 << 7,
|
||||
|
||||
ShaderResource = Vertex | Index | Constant
|
||||
}
|
||||
|
||||
public enum IndexType
|
||||
{
|
||||
UInt16,
|
||||
UInt32
|
||||
}
|
||||
|
||||
internal static class TextureFormatExtensions
|
||||
{
|
||||
public static DXGI_FORMAT ToD3D12Format(this TextureFormat format)
|
||||
|
||||
@@ -3,6 +3,14 @@ using Ghost.Graphics.Data;
|
||||
|
||||
namespace Ghost.Graphics.RHI;
|
||||
|
||||
public interface IResourceReleasable
|
||||
{
|
||||
/// <summary>
|
||||
/// A method to release GPU resources.
|
||||
/// </summary>
|
||||
void ReleaseResource(IResourceDatabase database);
|
||||
}
|
||||
|
||||
public interface IResourceDatabase
|
||||
{
|
||||
/// <summary>
|
||||
@@ -12,7 +20,7 @@ public interface IResourceDatabase
|
||||
/// <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)
|
||||
unsafe Handle<GPUResource> ImportExternalResource<T>(T resourcePtr, ResourceState initialState)
|
||||
where T : unmanaged;
|
||||
|
||||
/// <summary>
|
||||
@@ -20,113 +28,129 @@ public interface IResourceDatabase
|
||||
/// </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(Handle<GPUResource> handle);
|
||||
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(Handle<GPUResource> handle, ResourceState state);
|
||||
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);
|
||||
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);
|
||||
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 ReleaseResource(Handle<GPUResource> handle);
|
||||
void ReleaseResource(Handle<GPUResource> handle);
|
||||
|
||||
/// <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);
|
||||
Handle<Mesh> AddMesh(ref readonly Mesh mesh);
|
||||
|
||||
/// <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);
|
||||
bool HasMesh(Handle<Mesh> handle);
|
||||
|
||||
/// <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);
|
||||
ref Mesh GetMeshReference(Handle<Mesh> handle);
|
||||
|
||||
/// <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);
|
||||
void ReleaseMesh(Handle<Mesh> handle);
|
||||
|
||||
/// <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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
bool HasShader(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);
|
||||
ref Shader GetShaderReference(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);
|
||||
void ReleaseShader(Identifier<Shader> id);
|
||||
|
||||
// TODO: Use xxhash3 to generate passKey from string id.
|
||||
|
||||
/// <summary>
|
||||
/// Adds a shader pass to the collection using the specified identifier.
|
||||
/// </summary>
|
||||
/// <param name="passKey">The unique identifier for the shader pass.</param>
|
||||
/// <param name="pass">The shader pass to add. Cannot be null.</param>
|
||||
void AddShaderPass(ShaderPassKey passKey, ShaderPass pass);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the shader pass associated with the specified pass identifier.
|
||||
/// </summary>
|
||||
/// <param name="passKey">The unique identifier of the shader pass to retrieve.</param>
|
||||
/// <returns>The <see cref="ShaderPass"/> corresponding to the specified identifier, or null if no matching shader pass is found.</returns>
|
||||
ShaderPass GetShaderPass(ShaderPassKey passKey);
|
||||
}
|
||||
Reference in New Issue
Block a user