using Ghost.Core; using System.Runtime.InteropServices; namespace Ghost.RenderGraph.Concept; /// /// GPU resource states for barrier tracking. /// Based on D3D12 resource states. /// [Flags] public enum ResourceState { Common = 0, RenderTarget = 1 << 0, DepthWrite = 1 << 1, DepthRead = 1 << 2, ShaderResource = 1 << 3, UnorderedAccess = 1 << 4, CopySource = 1 << 5, CopyDest = 1 << 6, Present = 1 << 7, } /// /// Types of barriers that can be inserted. /// public enum BarrierType { Transition, // State transition (e.g., RenderTarget -> ShaderResource) Aliasing, // Aliasing barrier (new resource reusing memory) } /// /// Represents a resource barrier that needs to be inserted. /// For D3D12 aliasing barriers: ResourceBefore is the old resource, ResourceAfter is the new resource. /// internal struct ResourceBarrier { [StructLayout(LayoutKind.Explicit)] private struct barrier_union { internal struct barrier_union_transition { public Identifier resource; public ResourceState stateBefore; public ResourceState stateAfter; } internal struct barrier_union_aliasing { public Identifier resourceBefore; public Identifier resourceAfter; } // TODO: union can not have non-blittable types [FieldOffset(0)] public barrier_union_transition transition; [FieldOffset(0)] public barrier_union_aliasing aliasing; } private barrier_union _union; public BarrierType Type { get; init; } public int PassIndex { get; init; } // For Transition and UAV barriers public readonly Identifier 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 ResourceBefore => _union.aliasing.resourceBefore; public readonly Identifier ResourceAfter => _union.aliasing.resourceAfter; // Constructor for Aliasing barriers public static ResourceBarrier CreateAliasingBarrier( Identifier resourceBefore, Identifier resourceAfter, int passIndex) { return new ResourceBarrier { Type = BarrierType.Aliasing, PassIndex = passIndex, _union = new barrier_union { aliasing = new barrier_union.barrier_union_aliasing { resourceBefore = resourceBefore, resourceAfter = resourceAfter } } }; } public static ResourceBarrier CreateTransitionBarrier( Identifier resource, ResourceState before, ResourceState after, int passIndex) { return new ResourceBarrier { Type = BarrierType.Transition, PassIndex = passIndex, _union = new barrier_union { transition = new barrier_union.barrier_union_transition { resource = resource, stateBefore = before, stateAfter = after } } }; } } /// /// Tracks the current state of a resource across passes. /// internal sealed class ResourceStateTracker { public int ResourceIndex; public ResourceState CurrentState = ResourceState.Common; public int LastAccessPass = -1; public void Reset() { ResourceIndex = -1; CurrentState = ResourceState.Common; LastAccessPass = -1; } }