feat(resource): refactor heap management & suballocation
Major overhaul of GPU resource/heap management: - Replace resource pooling and upload buffer logic with transient heap/page-based suballocation in ResourceManager. - Add support for suballocation and heap flags/types, with D3D12 helpers. - Remove ICommandBuffer.UploadBuffer/UploadTexture; add UpdateSubResources and CopyBuffer, move upload logic to RenderingContext. - Refactor D3D12ResourceAllocator/Database for suballocation, heap flags, and mapping. - Standardize on Handle<GPUBuffer> usage. - Update meshlet/mesh utilities for new allocation handles and memory pools. - Refactor RenderGraph and docs to use "heap" terminology. - Use cpuFrame/gpuFrame consistently for frame sync. - Add s2h.hlsl, s2h_3d.hlsl, s2h_scatter.hlsl shader debug libs. - Miscellaneous fixes, cleanup, and dependency updates. BREAKING CHANGE: Resource pooling and upload APIs replaced with new heap/page-based suballocation system. Update all buffer/texture creation and upload code to use new ResourceManager and ICommandBuffer methods.
This commit is contained in:
@@ -152,6 +152,19 @@ public record struct Vertex
|
||||
public float2 uv;
|
||||
}
|
||||
|
||||
public struct ResourceRange
|
||||
{
|
||||
public nuint Start
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public nuint End
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct ShaderVariant;
|
||||
public readonly struct GraphicsPipeline;
|
||||
|
||||
|
||||
@@ -185,24 +185,6 @@ public interface ICommandBuffer : IDisposable
|
||||
// TODO: This method is not supported yet.
|
||||
void DispatchRay();
|
||||
|
||||
/// <summary>
|
||||
/// Uploads the specified data to the buffer represented by the given handle.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The unmanaged Value space of the elements to upload to the buffer.</typeparam>
|
||||
/// <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 space
|
||||
/// <typeparamref name="T"/>.</param>
|
||||
void UploadBuffer<T>(Handle<GPUBuffer> buffer, params ReadOnlySpan<T> data)
|
||||
where T : unmanaged;
|
||||
|
||||
/// <summary>
|
||||
/// Uploads texture data to the specified texture resource starting at the given subresource index.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture resource to which the subresource data will be uploaded. Must be a valid, initialized texture handle.</param>
|
||||
/// <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>
|
||||
/// Must be greater than zero and not exceed the remaining subresources in the texture.</param>
|
||||
void UploadTexture(Handle<GPUTexture> texture, params ReadOnlySpan<SubResourceData> subresources);
|
||||
|
||||
/// <summary>
|
||||
/// Copies a specified number of bytes from the source graphics buffer to the destination graphics buffer.
|
||||
/// </summary>
|
||||
@@ -221,4 +203,6 @@ public interface ICommandBuffer : IDisposable
|
||||
/// <param name="src">The handle to the source texture from which data will be read.</param>
|
||||
/// <param name="srcRegion">The region of the source texture to copy from. If null, the entire texture will be used.</param>
|
||||
void CopyTexture(Handle<GPUTexture> dst, TextureRegion? dstRegion, Handle<GPUTexture> src, TextureRegion? srcRegion);
|
||||
|
||||
void UpdateSubResources(Handle<GPUResource> resource, Handle<GPUResource> intermediate, params ReadOnlySpan<SubResourceData> subResources);
|
||||
}
|
||||
|
||||
@@ -74,14 +74,14 @@ public interface IGraphicsEngine : IDisposable
|
||||
/// <summary>
|
||||
/// Begin the current frame.
|
||||
/// </summary>
|
||||
/// <param name="currentFrame">CPU fence value for synchronization</param>
|
||||
/// <param name="cpuFrame">CPU fence value for synchronization</param>
|
||||
/// <returns>Result of the begin frame operation</returns>
|
||||
Result BeginFrame(ulong currentFrame);
|
||||
Result BeginFrame(ulong cpuFrame);
|
||||
|
||||
/// <summary>
|
||||
/// End the current frame.
|
||||
/// </summary>
|
||||
/// <param name="completedFrame">GPU fence value for synchronization</param>
|
||||
/// <param name="gpuFrame">GPU fence value for synchronization</param>
|
||||
/// <returns>Result of the end frame operation</returns>
|
||||
Result EndFrame(ulong completedFrame);
|
||||
Result EndFrame(ulong gpuFrame);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using Ghost.Core;
|
||||
|
||||
namespace Ghost.Graphics.RHI;
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace Ghost.Graphics.RHI;
|
||||
public enum ResourceAllocationType
|
||||
{
|
||||
Default,
|
||||
Temporary,
|
||||
Suballocation,
|
||||
}
|
||||
|
||||
@@ -36,11 +35,12 @@ public enum HeapType
|
||||
|
||||
public enum HeapFlags
|
||||
{
|
||||
None = 0,
|
||||
AllowBuffers,
|
||||
AllowTextures,
|
||||
AllowRTAndDS,
|
||||
AlowBufferAndTexture,
|
||||
None,
|
||||
Shared,
|
||||
AllowOnlyBuffers,
|
||||
AllowOnlyTextures,
|
||||
AllowOnlyRTAndDS,
|
||||
AllowAllBufferAndTexture,
|
||||
}
|
||||
|
||||
public struct AllocationDesc
|
||||
@@ -89,7 +89,7 @@ public interface IResourceAllocator : IDisposable
|
||||
/// <param name="desc">Allocation description</param>
|
||||
/// <param name="name">Debug name of the allocation</param>
|
||||
/// <returns>An <see cref="Handle{GPUResource}"/> point to the allocated memory</returns>
|
||||
Handle<GPUResource> Allocate(ref readonly AllocationDesc desc, string name);
|
||||
Handle<GPUResource> Allocate(ref readonly AllocationDesc desc, string? name = null);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a texture resource
|
||||
@@ -98,7 +98,7 @@ public interface IResourceAllocator : IDisposable
|
||||
/// <param name="name">Debug name of the resource</param>
|
||||
/// <param name="options">Additional options of the resource allocation</param>
|
||||
/// <returns>An <see cref="Handle{Texture}"/> point to the resource</returns>
|
||||
Handle<GPUTexture> CreateTexture(ref readonly TextureDesc desc, string name, CreationOptions options = default);
|
||||
Handle<GPUTexture> CreateTexture(ref readonly TextureDesc desc, string? name = null, CreationOptions options = default);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a render Target for off-screen rendering
|
||||
@@ -107,7 +107,7 @@ public interface IResourceAllocator : IDisposable
|
||||
/// <param name="name">Debug name of the resource</param>
|
||||
/// <param name="options">Additional options of the resource allocation</param>
|
||||
/// <returns>An <see cref="Handle{Texture}"/> point to the resource</returns>
|
||||
Handle<GPUTexture> CreateRenderTarget(ref readonly RenderTargetDesc desc, string name, CreationOptions options = default);
|
||||
Handle<GPUTexture> CreateRenderTarget(ref readonly RenderTargetDesc desc, string? name = null, CreationOptions options = default);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a buffer resource
|
||||
@@ -116,18 +116,7 @@ public interface IResourceAllocator : IDisposable
|
||||
/// <param name="name">Debug name of the resource</param>
|
||||
/// <param name="options">Additional options of the resource allocation</param>
|
||||
/// <returns>An <see cref="Handle{GraphicsBuffer}"/> point to the resource</returns>
|
||||
Handle<GPUBuffer> CreateBuffer(ref readonly BufferDesc desc, string name, CreationOptions options = default);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a temporary upload buffer of the specified size in bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method has been optimized for frequent calls during frame updates. It efficiently manages memory to minimize fragmentation and overhead.
|
||||
/// </remarks>
|
||||
/// <param name="sizeInBytes">The size of the upload buffer to create, in bytes.</param>
|
||||
/// <param name="offset">The offset within the upload buffer where the allocation begins.</param>
|
||||
/// <returns>An <see cref="Handle{GraphicsBuffer}"/> pointing to the created upload buffer.</returns>
|
||||
Handle<GPUBuffer> CreateTempUploadBuffer(ulong sizeInBytes, out ulong offset);
|
||||
Handle<GPUBuffer> CreateBuffer(ref readonly BufferDesc desc, string? name = null, CreationOptions options = default);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new sampler object using the specified sampler description.
|
||||
|
||||
@@ -31,22 +31,8 @@ public enum BindlessAccess
|
||||
UnorderedAccess,
|
||||
}
|
||||
|
||||
// TODO: Consider adding methods for resource enumeration, statistics, and bulk operations.
|
||||
// TODO: Consider adding async resource loading and streaming support.
|
||||
public interface IResourceDatabase : IDisposable
|
||||
public unsafe interface IResourceDatabase : IDisposable
|
||||
{
|
||||
/*
|
||||
/// <summary>
|
||||
/// Imports an external unmanaged resource and returns a handle for use within the resource management system.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The space 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>
|
||||
unsafe Handle<GPUResource> ImportExternalResource<T>(T resourcePtr, ResourceState initialState, string? name = null)
|
||||
where T : unmanaged;
|
||||
*/
|
||||
|
||||
void EnterParallelRead();
|
||||
|
||||
void ExitParallelRead();
|
||||
@@ -139,4 +125,8 @@ public interface IResourceDatabase : IDisposable
|
||||
/// <param name="handleB">The second handle whose associated resource is to be swapped.</param>
|
||||
/// <returns>An Error indicating the success or failure of the swap operation.</returns>
|
||||
Error Swap(Handle<GPUResource> handleA, Handle<GPUResource> handleB);
|
||||
|
||||
Error Map(Handle<GPUResource> handle, uint subResource, ResourceRange? readRange, ResourceRange? writeRange, void* pData, nuint size);
|
||||
|
||||
ulong GetIntermediateResourceSize(Handle<GPUResource> resource, uint firstSubResource, uint numSubResources);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public interface ISwapChain : IDisposable
|
||||
/// <summary>
|
||||
/// Gets all back buffer textures
|
||||
/// </summary>
|
||||
/// <returns>AlowBufferAndTexture back buffer textures</returns>
|
||||
/// <returns>AllowAllBufferAndTexture back buffer textures</returns>
|
||||
ReadOnlySpan<Handle<GPUTexture>> GetBackBuffers();
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -25,7 +25,7 @@ public static class ResourceHandleExtensions
|
||||
return new Handle<GPUTexture>(resource.ID, resource.Generation);
|
||||
}
|
||||
|
||||
public static Handle<GPUBuffer> AsGraphicsBuffer(this Handle<GPUResource> resource)
|
||||
public static Handle<GPUBuffer> AsBuffer(this Handle<GPUResource> resource)
|
||||
{
|
||||
return new Handle<GPUBuffer>(resource.ID, resource.Generation);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user