Files
GhostEngine/src/Runtime/Ghost.Graphics/Utilities/RenderingUtility.cs
Misaki 817b32b8d9 feat(graphics): refactor pipeline keying and allocators
Major refactor of graphics pipeline keying, shader cache, and resource allocation.
Replaced most Allocator usage with AllocationHandle, modernized logger usage,
and unified pipeline state keys. Updated MeshUtility to use AllocationHandle.FreeList.
Added new shader pipeline architecture docs and improved error handling throughout.

BREAKING CHANGE: Pipeline keying and resource allocation APIs have changed.
2026-04-13 23:07:52 +09:00

94 lines
3.4 KiB
C#

using Ghost.Core;
using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Utilities;
using Ghost.Graphics.Services;
namespace Ghost.Graphics.Utilities;
public static unsafe class RenderingUtility
{
public static void UploadBuffer<T>(ResourceManager resourceManager, IResourceDatabase resourceDatabase, ICommandBuffer cmd, Handle<GPUBuffer> buffer, params ReadOnlySpan<T> data)
where T : unmanaged
{
var r = resourceDatabase.GetResourceDescription(buffer.AsResource());
if (r.IsFailure)
{
return;
}
Logger.DebugAssert(r.Value.Type == ResourceType.Buffer);
var sizeInBytes = (nuint)(data.Length * sizeof(T));
var memoryType = r.Value.BufferDescriptor.HeapType;
if (memoryType == HeapType.Upload)
{
fixed (T* pData = data)
{
var mappedData = resourceDatabase.MapResource(buffer.AsResource(), 0, null);
MemoryUtility.MemCpy(mappedData, pData, sizeInBytes);
resourceDatabase.UnmapResource(buffer.AsResource(), 0, null);
}
}
else
{
var uploadDesc = new BufferDesc
{
Size = sizeInBytes,
Usage = BufferUsage.Upload,
HeapType = HeapType.Upload,
};
var uploadHandle = resourceManager.CreateTransientBuffer(in uploadDesc);
if (uploadHandle.IsInvalid)
{
throw new OutOfMemoryException("Failed to create upload buffer for buffer data.");
}
fixed (T* pData = data)
{
var mappedData = resourceDatabase.MapResource(uploadHandle.AsResource(), 0, null);
MemoryUtility.MemCpy(mappedData, pData, sizeInBytes);
resourceDatabase.UnmapResource(uploadHandle.AsResource(), 0, null);
}
cmd.CopyBuffer(buffer, uploadHandle, 0, 0, sizeInBytes);
}
}
public static void UploadTexture<T>(ResourceManager resourceManager, IResourceDatabase resourceDatabase, ICommandBuffer cmd, Handle<GPUTexture> texture, ReadOnlySpan<T> data)
where T : unmanaged
{
var desc = resourceDatabase.GetResourceDescription(texture.AsResource()).GetValueOrThrow();
desc.TextureDescriptor.Format.GetSurfaceInfo(desc.TextureDescriptor.Width, desc.TextureDescriptor.Height, out var rowPitch, out var slicePitch, out _);
var requiredSize = resourceDatabase.GetIntermediateResourceSize(texture.AsResource(), 0, 1);
var uploadDesc = new BufferDesc
{
Size = requiredSize,
Usage = BufferUsage.Upload,
HeapType = HeapType.Upload,
};
var uploadHandle = resourceManager.CreateTransientBuffer(in uploadDesc);
if (uploadHandle.IsInvalid)
{
throw new OutOfMemoryException("Failed to create upload buffer for texture data.");
}
cmd.Barrier(BarrierDesc.Texture(texture.AsResource(), BarrierSync.Copy, BarrierAccess.CopyDest, BarrierLayout.CopyDest));
fixed (T* pData = data)
{
var subresourceData = new SubResourceData
{
pData = pData,
rowPitch = rowPitch,
slicePitch = slicePitch
};
cmd.UpdateSubResources(texture.AsResource(), uploadHandle.AsResource(), subresourceData);
}
}
}