Refactor Render Graph: unified resources, benchmarking

Major overhaul of Render Graph system:
- Replaced texture handles with generic Identifier<T> for unified, type-safe resource management (textures, buffers, etc.)
- Refactored resource registry and pooling for performance and extensibility
- Added AccessFlags and TextureAccess for precise resource usage tracking
- Split passes into Raster and Compute types; introduced builder interfaces for safer pass construction
- Modernized pass setup API (SetColorAttachment, UseTexture, etc.)
- Updated command buffer and context structs to use new resource system
- Refactored barrier and aliasing logic for improved correctness
- Integrated BenchmarkDotNet for performance/memory benchmarking
- Improved blackboard type safety and removed obsolete code/extensions
- Added BenchmarkDotNet NuGet package

These changes make the Render Graph more extensible, efficient, and ready for future resource types and advanced features.
This commit is contained in:
2026-01-12 23:48:56 +09:00
parent 1fc9df1812
commit 954e3756aa
15 changed files with 940 additions and 776 deletions

View File

@@ -1,3 +1,4 @@
using Ghost.Core;
using System.Runtime.InteropServices;
namespace Ghost.RenderGraph.Concept;
@@ -9,7 +10,7 @@ namespace Ghost.RenderGraph.Concept;
[Flags]
public enum ResourceState
{
Undefined = 0,
Common = 0,
RenderTarget = 1 << 0,
DepthWrite = 1 << 1,
DepthRead = 1 << 2,
@@ -27,7 +28,6 @@ public enum BarrierType
{
Transition, // State transition (e.g., RenderTarget -> ShaderResource)
Aliasing, // Aliasing barrier (new resource reusing memory)
UAV, // UAV barrier (synchronize UAV access)
}
/// <summary>
@@ -41,71 +41,69 @@ internal struct ResourceBarrier
{
internal struct barrier_union_transition
{
public RenderGraphTextureHandle Resource;
public ResourceState StateBefore;
public ResourceState StateAfter;
public Identifier<RGResource> resource;
public ResourceState stateBefore;
public ResourceState stateAfter;
}
internal struct barrier_union_aliasing
{
public RenderGraphTextureHandle ResourceBefore;
public RenderGraphTextureHandle ResourceAfter;
public Identifier<RGResource> resourceBefore;
public Identifier<RGResource> resourceAfter;
}
// TODO: union can not have non-blittable types
[FieldOffset(0)]
public barrier_union_transition Transition;
public barrier_union_transition transition;
[FieldOffset(0)]
public barrier_union_aliasing Aliasing;
public barrier_union_aliasing aliasing;
}
public BarrierType Type;
// For Transition and UAV barriers
public RenderGraphTextureHandle Resource;
public ResourceState StateBefore;
public ResourceState StateAfter;
// For Aliasing barriers (D3D12_RESOURCE_BARRIER::Aliasing)
public RenderGraphTextureHandle ResourceBefore; // pResourceBefore
public RenderGraphTextureHandle ResourceAfter; // pResourceAfter
public int PassIndex;
private barrier_union _union;
// Constructor for Transition and UAV barriers
public ResourceBarrier(BarrierType type, RenderGraphTextureHandle resource,
ResourceState before, ResourceState after, int passIndex)
public BarrierType Type
{
Type = type;
Resource = resource;
StateBefore = before;
StateAfter = after;
ResourceBefore = default;
ResourceAfter = default;
PassIndex = passIndex;
get; init;
}
public int PassIndex
{
get; init;
}
// For Transition and UAV barriers
public readonly Identifier<RGResource> Resource => _union.transition.resource;
public readonly ResourceState StateBefore => _union.transition.stateBefore;
public readonly ResourceState StateAfter => _union.transition.stateAfter;
// For Aliasing barriers (D3D12_RESOURCE_BARRIER::Aliasing)
public readonly Identifier<RGResource> ResourceBefore => _union.aliasing.resourceBefore;
public readonly Identifier<RGResource> ResourceAfter => _union.aliasing.resourceAfter;
// Constructor for Aliasing barriers
public static ResourceBarrier CreateAliasingBarrier(
RenderGraphTextureHandle resourceBefore,
RenderGraphTextureHandle resourceAfter,
Identifier<RGResource> resourceBefore,
Identifier<RGResource> resourceAfter,
int passIndex)
{
return new ResourceBarrier
{
Type = BarrierType.Aliasing,
ResourceBefore = resourceBefore,
ResourceAfter = resourceAfter,
PassIndex = passIndex,
Resource = default,
StateBefore = ResourceState.Undefined,
StateAfter = ResourceState.Undefined
_union = new barrier_union
{
aliasing = new barrier_union.barrier_union_aliasing
{
resourceBefore = resourceBefore,
resourceAfter = resourceAfter
}
}
};
}
public static ResourceBarrier CreateTransitionBarrier(
RenderGraphTextureHandle resource,
Identifier<RGResource> resource,
ResourceState before,
ResourceState after,
int passIndex)
@@ -113,27 +111,18 @@ internal struct ResourceBarrier
return new ResourceBarrier
{
Type = BarrierType.Transition,
Resource = resource,
StateBefore = before,
StateAfter = after,
PassIndex = passIndex,
ResourceBefore = default,
ResourceAfter = default
_union = new barrier_union
{
transition = new barrier_union.barrier_union_transition
{
resource = resource,
stateBefore = before,
stateAfter = after
}
}
};
}
#if DEBUG
public override readonly string ToString()
{
return Type switch
{
BarrierType.Transition => $"[Pass {PassIndex}] TRANSITION: {Resource.Name} ({StateBefore} -> {StateAfter})",
BarrierType.Aliasing => $"[Pass {PassIndex}] ALIASING: {ResourceBefore.Name} -> {ResourceAfter.Name} (reusing physical memory)",
BarrierType.UAV => $"[Pass {PassIndex}] UAV: {Resource.Name}",
_ => $"[Pass {PassIndex}] UNKNOWN BARRIER"
};
}
#endif
}
/// <summary>
@@ -142,13 +131,13 @@ internal struct ResourceBarrier
internal sealed class ResourceStateTracker
{
public int ResourceIndex;
public ResourceState CurrentState = ResourceState.Undefined;
public ResourceState CurrentState = ResourceState.Common;
public int LastAccessPass = -1;
public void Reset()
{
ResourceIndex = -1;
CurrentState = ResourceState.Undefined;
CurrentState = ResourceState.Common;
LastAccessPass = -1;
}
}