feat(rhi)!: refactor resource handles to GPUTexture/GPUBuffer

Refactored all graphics resource handles to use Handle<GPUTexture> and Handle<GPUBuffer> instead of Handle<Texture> and Handle<GraphicsBuffer>. Updated all APIs, interfaces, and implementations to use the new types, including ICommandBuffer, IResourceAllocator, ISwapChain, IRenderOutput, IRenderGraphBuilder, and related classes. Introduced TempJobAllocator for frame-latency-aware allocations. Updated ResourceHandleExtensions for new conversions. Performed minor code cleanups and removed the empty ClusterLod.cs file.

BREAKING CHANGE: All usages of Handle<Texture> and Handle<GraphicsBuffer> are replaced with Handle<GPUTexture> and Handle<GPUBuffer>. This affects all APIs and resource management code. Callers must update their code to use the new handle types.
This commit is contained in:
2026-03-30 21:27:16 +09:00
parent b28b32f502
commit 89e6c68f2a
32 changed files with 447 additions and 270 deletions

View File

@@ -11,16 +11,16 @@ namespace Ghost.Graphics.Core;
internal struct CBufferCache : IResourceReleasable
{
private UnsafeArray<byte> _cpuData;
private Handle<GraphicsBuffer> _gpuResource;
private Handle<RHI.GPUBuffer> _gpuResource;
private uint _size;
public readonly UnsafeArray<byte> CpuData => _cpuData;
public readonly Handle<GraphicsBuffer> GpuResource => _gpuResource;
public readonly Handle<RHI.GPUBuffer> GpuResource => _gpuResource;
public readonly uint Size => _size;
public readonly bool IsCreated => _size != 0 && _gpuResource.IsValid && _cpuData.IsCreated;
public CBufferCache(Handle<GraphicsBuffer> buffer, uint bufferSize)
public CBufferCache(Handle<RHI.GPUBuffer> buffer, uint bufferSize)
{
_size = bufferSize;
_cpuData = new UnsafeArray<byte>((int)bufferSize, Allocator.Persistent);
@@ -37,7 +37,7 @@ internal struct CBufferCache : IResourceReleasable
_cpuData.Dispose();
database.ReleaseResource(_gpuResource.AsResource());
_gpuResource = Handle<GraphicsBuffer>.Invalid;
_gpuResource = Handle<RHI.GPUBuffer>.Invalid;
_size = 0;
}
}

View File

@@ -138,7 +138,7 @@ public struct Mesh : IResourceReleasable
/// <summary>
/// Gets the handle to the vertex buffer on the GPU.
/// </summary>
public Handle<GraphicsBuffer> VertexBuffer
public Handle<RHI.GPUBuffer> VertexBuffer
{
get; internal set;
}
@@ -146,7 +146,7 @@ public struct Mesh : IResourceReleasable
/// <summary>
/// Gets the handle to the index buffer on the GPU.
/// </summary>
public Handle<GraphicsBuffer> IndexBuffer
public Handle<RHI.GPUBuffer> IndexBuffer
{
get; internal set;
}
@@ -154,7 +154,7 @@ public struct Mesh : IResourceReleasable
/// <summary>
/// Gets the handle to the meshlet buffer on the GPU.
/// </summary>
public Handle<GraphicsBuffer> MeshLetBuffer
public Handle<RHI.GPUBuffer> MeshLetBuffer
{
get; internal set;
}
@@ -162,7 +162,7 @@ public struct Mesh : IResourceReleasable
/// <summary>
/// Gets the handle to the meshlet vertices buffer on the GPU.
/// </summary>
public Handle<GraphicsBuffer> MeshletVerticesBuffer
public Handle<RHI.GPUBuffer> MeshletVerticesBuffer
{
get; internal set;
}
@@ -170,7 +170,7 @@ public struct Mesh : IResourceReleasable
/// <summary>
/// Gets the handle to the meshlet triangles buffer on the GPU.
/// </summary>
public Handle<GraphicsBuffer> MeshletTrianglesBuffer
public Handle<RHI.GPUBuffer> MeshletTrianglesBuffer
{
get; internal set;
}
@@ -178,12 +178,12 @@ public struct Mesh : IResourceReleasable
/// <summary>
/// Gets the handle to the mesh data buffer on the GPU.
/// </summary>
public Handle<GraphicsBuffer> ObjectDataBuffer
public Handle<RHI.GPUBuffer> ObjectDataBuffer
{
get; internal set;
}
internal Mesh(ReadOnlySpan<Vertex> vertices, ReadOnlySpan<uint> indices, Handle<GraphicsBuffer> vertexBuffer, Handle<GraphicsBuffer> indexBuffer)
internal Mesh(ReadOnlySpan<Vertex> vertices, ReadOnlySpan<uint> indices, Handle<RHI.GPUBuffer> vertexBuffer, Handle<RHI.GPUBuffer> indexBuffer)
{
Vertices = new UnsafeList<Vertex>(vertices.Length, Allocator.Persistent);
Indices = new UnsafeList<uint>(indices.Length, Allocator.Persistent);

View File

@@ -25,7 +25,7 @@ internal class SwapChainRenderOutput : IRenderOutput
Scissor = new ScissorRectDesc { Right = swapChain.Width, Bottom = swapChain.Height };
}
public Handle<Texture> GetRenderTarget()
public Handle<GPUTexture> GetRenderTarget()
{
return _swapChain.GetCurrentBackBuffer();
}
@@ -58,7 +58,7 @@ internal class SwapChainRenderOutput : IRenderOutput
internal class TextureRenderOutput : IRenderOutput
{
private readonly Handle<Texture> _texture;
private readonly Handle<GPUTexture> _texture;
public ViewportDesc Viewport
{
@@ -70,12 +70,12 @@ internal class TextureRenderOutput : IRenderOutput
get; set;
}
public TextureRenderOutput(Handle<Texture> texture)
public TextureRenderOutput(Handle<GPUTexture> texture)
{
_texture = texture;
}
public Handle<Texture> GetRenderTarget()
public Handle<GPUTexture> GetRenderTarget()
{
return _texture;
}

View File

@@ -183,8 +183,8 @@ public unsafe struct RenderRequest: IDisposable
public RenderView view;
public int swapChainIndex;
public Handle<Texture> colorTarget;
public Handle<Texture> depthTarget;
public Handle<GPUTexture> colorTarget;
public Handle<GPUTexture> depthTarget;
public RenderList opaqueRenderList;
public RenderList transparentRenderList;

View File

@@ -242,7 +242,7 @@ public readonly unsafe ref struct RenderingContext
TransitionBarrier(bufferHandle, false, BarrierLayout.Undefined, BarrierAccess.ShaderResource, BarrierSync.PixelShading | BarrierSync.NonPixelShading);
}
public Handle<Texture> CreateTexture<T>(ref readonly TextureDesc desc, ReadOnlySpan<T> data, string name)
public Handle<GPUTexture> CreateTexture<T>(ref readonly TextureDesc desc, ReadOnlySpan<T> data, string name)
where T : unmanaged
{
var handle = ResourceAllocator.CreateTexture(in desc, name);
@@ -251,7 +251,7 @@ public readonly unsafe ref struct RenderingContext
return handle;
}
public void UploadTexture<T>(Handle<Texture> texture, ReadOnlySpan<T> data)
public void UploadTexture<T>(Handle<GPUTexture> texture, ReadOnlySpan<T> data)
where T : unmanaged
{
var desc = ResourceDatabase.GetResourceDescription(texture.AsResource()).GetValueOrThrow();

View File

@@ -105,7 +105,7 @@ public sealed class RenderGraph : IDisposable
/// </summary>
/// <param name="texture">The external texture handle.</param>
/// <returns>The identifier of the imported render graph texture. Invalid if import fails.</returns>
public Identifier<RGTexture> ImportTexture(Handle<Texture> texture, string name,
public Identifier<RGTexture> ImportTexture(Handle<GPUTexture> texture, string name,
Color128 clearColor = default, float clearDepth = 1.0f, byte clearStencil = 0,
bool clearAtFirstUse = true, bool discardAtLastUse = true)
{
@@ -125,7 +125,7 @@ public sealed class RenderGraph : IDisposable
/// </summary>
/// <param name="buffer">The external buffer handle.</param>
/// <returns>The identifier of the imported render graph buffer. Invalid if import fails.</returns>
public Identifier<RGBuffer> ImportBuffer(Handle<GraphicsBuffer> buffer, string name)
public Identifier<RGBuffer> ImportBuffer(Handle<RHI.GPUBuffer> buffer, string name)
{
var r = _resourceDatabase.GetResourceDescription(buffer.AsResource());
if (r.IsFailure)

View File

@@ -79,6 +79,20 @@ public interface IRenderGraphBuilder : IDisposable
/// <param name="hint">Optional hint about how the buffer will be used.</param>
/// <returns>An identifier for the buffer.</returns>
Identifier<RGBuffer> UseBuffer(Identifier<RGBuffer> buffer, AccessFlags accessMode);
/// <summary>
/// Extracts the actual texture resource associated with the given identifier for use in outside of the render graph execution context.
/// </summary>
/// <param name="texture">The identifier of the texture to be extracted.</param>
/// <returns>A handle to the actual texture resource that can be used outside of the render graph execution context.</returns>
Handle<GPUTexture> ExtractTexture(Identifier<RGTexture> texture);
/// <summary>
/// Extracts the actual buffer resource associated with the given identifier for use in outside of the render graph execution context.
/// </summary>
/// <param name="buffer">The identifier of the buffer to be extracted.</param>
/// <returns>A handle to the actual buffer resource that can be used outside of the render graph execution context.</returns>
Handle<GPUBuffer> ExtractBuffer(Identifier<RGBuffer> buffer);
}
public interface IRasterRenderGraphBuilder : IRenderGraphBuilder
@@ -254,6 +268,17 @@ internal class RenderGraphBuilder : IRasterRenderGraphBuilder, IComputeRenderGra
return UseResource(buffer.AsResource(), flags, RenderGraphResourceType.Buffer).AsBuffer();
}
// TODO: Implement ExtractTexture and ExtractBuffer to allow users to get the actual GPU resources for use outside of the render graph execution context.
public Handle<GPUTexture> ExtractTexture(Identifier<RGTexture> texture)
{
throw new NotImplementedException();
}
public Handle<GPUBuffer> ExtractBuffer(Identifier<RGBuffer> buffer)
{
throw new NotImplementedException();
}
public Identifier<RGTexture> UseRandomAccessTexture(Identifier<RGTexture> texture)
{
ThrowIfDisposed();

View File

@@ -11,11 +11,11 @@ public interface IRenderGraphContext
IResourceDatabase ResourceDatabase { get; }
Handle<GPUResource> GetActualResource(Identifier<RGResource> resource);
Handle<Texture> GetActualTexture(Identifier<RGTexture> texture);
Handle<GraphicsBuffer> GetActualBuffer(Identifier<RGBuffer> buffer);
Handle<GPUTexture> GetActualTexture(Identifier<RGTexture> texture);
Handle<RHI.GPUBuffer> GetActualBuffer(Identifier<RGBuffer> buffer);
Handle<Texture> GetHistoryTexture(ReadOnlySpan<Identifier<RGTexture>> texture, int historyOffset);
Handle<GraphicsBuffer> GetHistoryBuffer(ReadOnlySpan<Identifier<RGBuffer>> buffer, int historyOffset);
Handle<GPUTexture> GetHistoryTexture(ReadOnlySpan<Identifier<RGTexture>> texture, int historyOffset);
Handle<RHI.GPUBuffer> GetHistoryBuffer(ReadOnlySpan<Identifier<RGBuffer>> buffer, int historyOffset);
ICommandBuffer GetCommandBufferUnsafe();
}
@@ -60,8 +60,8 @@ internal sealed class RenderGraphContext : IUnsafeRenderContext
private TextureFormat _dsvFormat;
private int _rtvCount;
private Handle<GraphicsBuffer> _activePerMaterialData;
private Handle<GraphicsBuffer> _activePerMeshData;
private Handle<RHI.GPUBuffer> _activePerMaterialData;
private Handle<RHI.GPUBuffer> _activePerMeshData;
private int _activeMeshIndexCount;
private uint _activeFrameBuffer;
@@ -115,21 +115,21 @@ internal sealed class RenderGraphContext : IUnsafeRenderContext
return _resources.GetResource(resource).backingResource;
}
public Handle<Texture> GetActualTexture(Identifier<RGTexture> texture)
public Handle<GPUTexture> GetActualTexture(Identifier<RGTexture> texture)
{
return _resources.GetResource(texture.AsResource()).backingResource.AsTexture();
}
public Handle<GraphicsBuffer> GetActualBuffer(Identifier<RGBuffer> buffer)
public Handle<RHI.GPUBuffer> GetActualBuffer(Identifier<RGBuffer> buffer)
{
return _resources.GetResource(buffer.AsResource()).backingResource.AsGraphicsBuffer();
}
public Handle<Texture> GetHistoryTexture(ReadOnlySpan<Identifier<RGTexture>> textures, int historyOffset)
public Handle<GPUTexture> GetHistoryTexture(ReadOnlySpan<Identifier<RGTexture>> textures, int historyOffset)
{
if (historyOffset < 0 || historyOffset >= textures.Length)
{
return Handle<Texture>.Invalid;
return Handle<GPUTexture>.Invalid;
}
var index = (int)(_frameIndex % textures.Length) - historyOffset;
@@ -141,11 +141,11 @@ internal sealed class RenderGraphContext : IUnsafeRenderContext
return GetActualTexture(textures[index]);
}
public Handle<GraphicsBuffer> GetHistoryBuffer(ReadOnlySpan<Identifier<RGBuffer>> buffers, int historyOffset)
public Handle<RHI.GPUBuffer> GetHistoryBuffer(ReadOnlySpan<Identifier<RGBuffer>> buffers, int historyOffset)
{
if (historyOffset < 0 || historyOffset >= buffers.Length)
{
return Handle<GraphicsBuffer>.Invalid;
return Handle<RHI.GPUBuffer>.Invalid;
}
var index = (int)(_frameIndex % buffers.Length) - historyOffset;
@@ -172,7 +172,7 @@ internal sealed class RenderGraphContext : IUnsafeRenderContext
var r = _resourceManager.GetMaterialReference(material);
if (r.IsFailure)
{
_activePerMaterialData = Handle<GraphicsBuffer>.Invalid;
_activePerMaterialData = Handle<RHI.GPUBuffer>.Invalid;
return;
}
@@ -185,7 +185,7 @@ internal sealed class RenderGraphContext : IUnsafeRenderContext
var shaderResult = _resourceManager.GetShaderReference(material.Shader);
if (shaderResult.IsFailure)
{
_activePerMaterialData = Handle<GraphicsBuffer>.Invalid;
_activePerMaterialData = Handle<RHI.GPUBuffer>.Invalid;
return;
}
@@ -230,7 +230,7 @@ internal sealed class RenderGraphContext : IUnsafeRenderContext
var r = _resourceManager.GetMeshReference(mesh);
if (r.IsFailure)
{
_activePerMeshData = Handle<GraphicsBuffer>.Invalid;
_activePerMeshData = Handle<RHI.GPUBuffer>.Invalid;
_activeMeshIndexCount = 0;
return;
}

View File

@@ -134,7 +134,7 @@ internal sealed class RenderGraphExecutor
{
Texture = nativePass.hasDepthAttachment
? _resources.GetResource(nativePass.depthAttachment.texture).backingResource.AsTexture()
: Handle<Texture>.Invalid,
: Handle<GPUTexture>.Invalid,
ClearDepth = nativePass.depthAttachment.clearDepth,
ClearStencil = nativePass.depthAttachment.clearStencil,
DepthLoadOp = nativePass.hasDepthAttachment

View File

@@ -163,7 +163,7 @@ internal sealed class RenderGraphResourceRegistry
_resources.Clear();
}
public Identifier<RGTexture> ImportTexture(ref readonly TextureDesc desc, Handle<Texture> texture, string name,
public Identifier<RGTexture> ImportTexture(ref readonly TextureDesc desc, Handle<GPUTexture> texture, string name,
Color128 clearColor, float clearDepth, byte clearStencil,
bool clearAtFirstUse, bool discardAtLastUse)
{
@@ -211,7 +211,7 @@ internal sealed class RenderGraphResourceRegistry
return new Identifier<RGTexture>(resource.index);
}
public Identifier<RGBuffer> ImportBuffer(ref readonly BufferDesc desc, Handle<GraphicsBuffer> buffer, string name)
public Identifier<RGBuffer> ImportBuffer(ref readonly BufferDesc desc, Handle<RHI.GPUBuffer> buffer, string name)
{
var resource = _pool.Rent<RenderGraphResource>();
resource.name = name;

View File

@@ -1,7 +1,6 @@
using Ghost.MeshOptimizer;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.LowLevel.Utilities;
using Misaki.HighPerformance.Mathematics;
using System.Diagnostics;
@@ -19,9 +18,9 @@ internal struct Cluster : IDisposable
public void Dispose()
{
if (indices.IsCreated) indices.Dispose();
if (uniqueVertices.IsCreated) uniqueVertices.Dispose();
if (localIndices.IsCreated) localIndices.Dispose();
indices.Dispose();
uniqueVertices.Dispose();
localIndices.Dispose();
}
}
@@ -267,7 +266,7 @@ public static unsafe class MeshletUtility
for (nuint j = 0; j < meshlet.triangle_count * 3; j++)
{
byte localIdx = pMeshletTriangles[meshlet.triangle_offset + j];
var localIdx = pMeshletTriangles[meshlet.triangle_offset + j];
cluster.localIndices.Add(localIdx);
cluster.indices.Add(pMeshletVertices[meshlet.vertex_offset + localIdx]);
}

View File

@@ -109,14 +109,12 @@ shader "MyShader/Standard"
// float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
// return perMaterialData.color * blendedColor + input.color;
// TODO: Randome color on meshlet.
// return 1.0;
uint hash = PCGHash(input.meshletID);
float r = float((hash & 0xFF0000u) >> 16) / 255.0;
float g = float((hash & 0x00FF00u) >> 8) / 255.0;
float b = float((hash & 0x0000FFu)) / 255.0;
return float4(r, g, b, 1.0);
}
}