Enhanced barrier

This commit is contained in:
2026-01-22 12:33:23 +09:00
parent 92b966fe0d
commit 139312d73b
35 changed files with 653 additions and 9544 deletions

View File

@@ -193,7 +193,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
_commandList.Get()->RSSetScissorRects(1, &d3d12Rect);
}
public void ResourceBarrier(ReadOnlySpan<BarrierDesc> barrierDescs)
public void ResourceBarrier(params ReadOnlySpan<BarrierDesc> barrierDescs)
{
ThrowIfDisposed();
ThrowIfNotRecording();
@@ -210,170 +210,120 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
return;
}
var count = 0u;
var pBarriers = stackalloc D3D12_RESOURCE_BARRIER[barrierDescs.Length];
var globalCount = 0;
var bufferCount = 0;
var textureCount = 0;
for (var i = 0; i < barrierDescs.Length; i++)
{
switch (barrierDescs[i].Type)
{
case BarrierType.Global: globalCount++; break;
case BarrierType.Buffer: bufferCount++; break;
case BarrierType.Texture: textureCount++; break;
}
}
var pGlobalBarriers = stackalloc D3D12_GLOBAL_BARRIER[globalCount];
var pBufferBarriers = stackalloc D3D12_BUFFER_BARRIER[bufferCount];
var pTextureBarriers = stackalloc D3D12_TEXTURE_BARRIER[textureCount];
var globalIndex = 0;
var bufferIndex = 0;
var textureIndex = 0;
for (var i = 0; i < barrierDescs.Length; i++)
{
var desc = barrierDescs[i];
D3D12_RESOURCE_BARRIER barrier = default;
switch (desc.type)
switch (desc.Type)
{
case BarrierType.Transition:
if (desc.transition.stateBefore == desc.transition.stateAfter)
case BarrierType.Global:
pGlobalBarriers[globalIndex++] = new D3D12_GLOBAL_BARRIER
{
continue;
}
var recordResult = _resourceDatabase.GetResourceRecord(desc.transition.resource);
if (recordResult.Error != ErrorStatus.None)
{
RecordError(nameof(TransitionBarrier), recordResult.Error);
continue;
}
ref var record = ref recordResult.Value;
var stateBefore = desc.transition.stateBefore == ResourceState.Auto ? record.state : desc.transition.stateBefore;
barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
stateBefore.ToD3D12States(), desc.transition.stateAfter.ToD3D12States());
record.state = desc.transition.stateAfter;
SyncBefore = (D3D12_BARRIER_SYNC)desc.SyncBefore,
SyncAfter = (D3D12_BARRIER_SYNC)desc.SyncAfter,
AccessBefore = (D3D12_BARRIER_ACCESS)desc.AccessBefore,
AccessAfter = (D3D12_BARRIER_ACCESS)desc.AccessAfter
};
break;
case BarrierType.Aliasing:
var recordBeforeResult = _resourceDatabase.GetResourceRecord(desc.aliasing.resourceBefore);
if (recordBeforeResult.Error != ErrorStatus.None)
case BarrierType.Buffer:
{
var resource = _resourceDatabase.GetResource(desc.Resource);
pBufferBarriers[bufferIndex++] = new D3D12_BUFFER_BARRIER
{
RecordError(nameof(TransitionBarrier), recordBeforeResult.Error);
continue;
}
var recordAfterResult = _resourceDatabase.GetResourceRecord(desc.aliasing.resourceAfter);
if (recordAfterResult.Error != ErrorStatus.None)
SyncBefore = (D3D12_BARRIER_SYNC)desc.SyncBefore,
SyncAfter = (D3D12_BARRIER_SYNC)desc.SyncAfter,
AccessBefore = (D3D12_BARRIER_ACCESS)desc.AccessBefore,
AccessAfter = (D3D12_BARRIER_ACCESS)desc.AccessAfter,
pResource = resource,
Offset = 0,
Size = ulong.MaxValue
};
}
break;
case BarrierType.Texture:
{
var resource = _resourceDatabase.GetResource(desc.Resource);
pTextureBarriers[textureIndex++] = new D3D12_TEXTURE_BARRIER
{
RecordError(nameof(TransitionBarrier), recordAfterResult.Error);
continue;
}
barrier = D3D12_RESOURCE_BARRIER.InitAliasing(
recordBeforeResult.Value.ResourcePtr,
recordAfterResult.Value.ResourcePtr);
break;
case BarrierType.UAV:
var recordUavResult = _resourceDatabase.GetResourceRecord(desc.uav.resource);
if (recordUavResult.Error != ErrorStatus.None)
{
RecordError(nameof(TransitionBarrier), recordUavResult.Error);
continue;
}
barrier = D3D12_RESOURCE_BARRIER.InitUAV(recordUavResult.Value.ResourcePtr);
break;
SyncBefore = (D3D12_BARRIER_SYNC)desc.SyncBefore,
SyncAfter = (D3D12_BARRIER_SYNC)desc.SyncAfter,
AccessBefore = (D3D12_BARRIER_ACCESS)desc.AccessBefore,
AccessAfter = (D3D12_BARRIER_ACCESS)desc.AccessAfter,
LayoutBefore = (D3D12_BARRIER_LAYOUT)desc.LayoutBefore,
LayoutAfter = (D3D12_BARRIER_LAYOUT)desc.LayoutAfter,
pResource = resource,
Subresources = new D3D12_BARRIER_SUBRESOURCE_RANGE
{
IndexOrFirstMipLevel = desc.Subresources.IndexOrFirstMipLevel,
NumMipLevels = desc.Subresources.NumMipLevels,
FirstArraySlice = desc.Subresources.FirstArraySlice,
NumArraySlices = desc.Subresources.NumArraySlices
},
Flags = desc.Discard ? D3D12_TEXTURE_BARRIER_FLAGS.D3D12_TEXTURE_BARRIER_FLAG_DISCARD : D3D12_TEXTURE_BARRIER_FLAGS.D3D12_TEXTURE_BARRIER_FLAG_NONE
};
}
break;
}
pBarriers[count] = barrier;
count++;
}
_commandList.Get()->ResourceBarrier(count, pBarriers);
}
public void TransitionBarrier(Handle<GPUResource> resource, ResourceState stateBefore, ResourceState stateAfter)
{
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
var groups = stackalloc D3D12_BARRIER_GROUP[3];
var groupCount = 0u;
if (globalCount > 0)
{
return;
groups[groupCount] = new D3D12_BARRIER_GROUP
{
Type = D3D12_BARRIER_TYPE.D3D12_BARRIER_TYPE_GLOBAL,
NumBarriers = (uint)globalCount,
};
groups[groupCount].Anonymous.pGlobalBarriers = pGlobalBarriers;
groupCount++;
}
#endif
IncrementCommandCount();
if (stateBefore == stateAfter)
if (bufferCount > 0)
{
return;
groups[groupCount] = new D3D12_BARRIER_GROUP
{
Type = D3D12_BARRIER_TYPE.D3D12_BARRIER_TYPE_BUFFER,
NumBarriers = (uint)bufferCount,
};
groups[groupCount].Anonymous.pBufferBarriers = pBufferBarriers;
groupCount++;
}
var recordResult = _resourceDatabase.GetResourceRecord(resource);
if (recordResult.Error != ErrorStatus.None)
if (textureCount > 0)
{
RecordError(nameof(TransitionBarrier), recordResult.Error);
return;
groups[groupCount] = new D3D12_BARRIER_GROUP
{
Type = D3D12_BARRIER_TYPE.D3D12_BARRIER_TYPE_TEXTURE,
NumBarriers = (uint)textureCount,
};
groups[groupCount].Anonymous.pTextureBarriers = pTextureBarriers;
groupCount++;
}
ref var record = ref recordResult.Value;
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
stateBefore.ToD3D12States(), stateAfter.ToD3D12States());
_commandList.Get()->ResourceBarrier(1, &barrier);
record.state = stateAfter;
}
public void TransitionBarrier(Handle<GPUResource> resource, ResourceState stateAfter)
{
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
{
return;
}
#endif
IncrementCommandCount();
var recordResult = _resourceDatabase.GetResourceRecord(resource);
if (recordResult.Error != ErrorStatus.None)
{
RecordError(nameof(TransitionBarrier), recordResult.Error);
return;
}
ref var record = ref recordResult.Value;
if (record.state == stateAfter)
{
return;
}
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
record.state.ToD3D12States(), stateAfter.ToD3D12States());
_commandList.Get()->ResourceBarrier(1, &barrier);
record.state = stateAfter;
}
public void AliasBarrier(Handle<GPUResource> resourceBefore, Handle<GPUResource> resourceAfter)
{
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
{
return;
}
#endif
IncrementCommandCount();
var recordBeforeResult = _resourceDatabase.GetResourceRecord(resourceBefore);
if (recordBeforeResult.Error != ErrorStatus.None)
{
RecordError(nameof(AliasBarrier), recordBeforeResult.Error);
return;
}
var recordAfterResult = _resourceDatabase.GetResourceRecord(resourceAfter);
if (recordAfterResult.Error != ErrorStatus.None)
{
RecordError(nameof(AliasBarrier), recordAfterResult.Error);
return;
}
var barrier = D3D12_RESOURCE_BARRIER.InitAliasing(
recordBeforeResult.Value.ResourcePtr,
recordAfterResult.Value.ResourcePtr);
_commandList.Get()->ResourceBarrier(1, &barrier);
_commandList.Get()->Barrier(groupCount, groups);
}
public void SetRenderTargets(ReadOnlySpan<Handle<Texture>> renderTargets, Handle<Texture> depthTarget)
@@ -440,7 +390,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
}
#endif
IncrementCommandCount();
var recordResult = _resourceDatabase.GetResourceRecord(renderTarget.AsResource());
if (recordResult.Error != ErrorStatus.None)
{
@@ -914,7 +864,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
}
public void UploadBuffer<T>(Handle<GraphicsBuffer> buffer, ReadOnlySpan<T> data)
public void UploadBuffer<T>(Handle<GraphicsBuffer> buffer, params ReadOnlySpan<T> data)
where T : unmanaged
{
ThrowIfDisposed();
@@ -944,7 +894,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
_commandList.Get()->CopyBufferRegion(pResource, 0, uploadResource, offset, sizeInBytes);
}
public void UploadTexture(Handle<Texture> texture, ReadOnlySpan<SubResourceData> subresources)
public void UploadTexture(Handle<Texture> texture, params ReadOnlySpan<SubResourceData> subresources)
{
ThrowIfDisposed();
ThrowIfNotRecording();

View File

@@ -179,24 +179,11 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary
return Result.Success(cbufferInfo);
}
private static D3D12_COMPARISON_FUNC ToD3DCompare(ZTest z) => z switch
{
ZTest.Disabled => D3D12_COMPARISON_FUNC_NEVER,
ZTest.Less => D3D12_COMPARISON_FUNC_LESS,
ZTest.LessEqual => D3D12_COMPARISON_FUNC_LESS_EQUAL,
ZTest.Equal => D3D12_COMPARISON_FUNC_EQUAL,
ZTest.GreaterEqual => D3D12_COMPARISON_FUNC_GREATER_EQUAL,
ZTest.Greater => D3D12_COMPARISON_FUNC_GREATER,
ZTest.NotEqual => D3D12_COMPARISON_FUNC_NOT_EQUAL,
ZTest.Always => D3D12_COMPARISON_FUNC_ALWAYS,
_ => D3D12_COMPARISON_FUNC_LESS_EQUAL
};
private static D3D12_DEPTH_STENCIL_DESC BuildDepthStencil(ZTest ztest, ZWrite zwrite)
{
var depthEnabled = ztest != ZTest.Disabled;
var writeEnabled = zwrite == ZWrite.On;
var cmp = ToD3DCompare(ztest);
var cmp = ztest.ToD3DCompare();
return D3D12Utility.D3D12_DEPTH_STENCIL_DESC_CREATE(depthEnabled, writeEnabled, cmp);
}

View File

@@ -10,7 +10,6 @@ using Misaki.HighPerformance.LowLevel.Collections;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Xml.Linq;
using TerraFX.Interop.DirectX;
using TerraFX.Interop.Windows;
@@ -480,84 +479,6 @@ internal sealed unsafe partial class D3D12ResourceAllocator
_ => throw new ArgumentException($"Unsupported memory type: {memoryType}")
};
}
private static D3D12_RESOURCE_STATES DetermineInitialTextureState(TextureUsage usage)
{
if (usage.HasFlag(TextureUsage.RenderTarget))
{
return D3D12_RESOURCE_STATE_RENDER_TARGET;
}
if (usage.HasFlag(TextureUsage.DepthStencil))
{
return D3D12_RESOURCE_STATE_DEPTH_WRITE;
}
if (usage.HasFlag(TextureUsage.UnorderedAccess))
{
return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
return D3D12_RESOURCE_STATE_COMMON;
}
private static D3D12_RESOURCE_STATES DetermineInitialBufferState(BufferUsage usage, ResourceMemoryType memoryType)
{
if (memoryType == ResourceMemoryType.Upload)
{
return D3D12_RESOURCE_STATE_GENERIC_READ;
}
if (memoryType == ResourceMemoryType.Readback)
{
return D3D12_RESOURCE_STATE_COPY_DEST;
}
var state = D3D12_RESOURCE_STATE_COMMON;
#if true
// D3D12 does not support state other than COMMON for buffers at creation.
return state;
#else
if (usage.HasFlag(BufferUsage.Vertex) || usage.HasFlag(BufferUsage.Constant))
{
// Vertex and Constant buffers can share this state
state |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
}
if (usage.HasFlag(BufferUsage.Index))
{
state |= D3D12_RESOURCE_STATE_INDEX_BUFFER;
}
if (usage.HasFlag(BufferUsage.UnorderedAccess))
{
state |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
if (usage.HasFlag(BufferUsage.IndirectArgument))
{
state |= D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
}
// If only one state is set (e.g., just IndexBuffer), return it directly
// This is a common optimization to avoid an initial barrier
if (math.ispow2((int)state))
{
return state;
}
// If multiple roles (e.g., Vertex and Index), start in COMMON
// or return the combined state if they are compatible
// For simplicity, we'll just check for the common "Vertex/Constant" combo
if (state == D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER)
{
return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
}
// If it's a mix, start in common and let the user barrier
return D3D12_RESOURCE_STATE_COMMON;
#endif
}
}
internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
@@ -624,9 +545,9 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Handle<GPUResource> TrackAllocation(D3D12MA_Allocation* allocation, D3D12_RESOURCE_STATES state, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string name, bool isTemp)
private Handle<GPUResource> TrackAllocation(D3D12MA_Allocation* allocation, ResourceBarrierData barrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string name, bool isTemp)
{
var handle = _resourceDatabase.AddAllocation(allocation, _fenceSynchronizer.CPUFenceValue, state.ToResourceState(), resourceDescriptor, desc, name);
var handle = _resourceDatabase.AddAllocation(allocation, _fenceSynchronizer.CPUFenceValue, barrierData, resourceDescriptor, desc, name);
if (isTemp)
{
@@ -653,8 +574,8 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
}
else
{
var nuliid = IID.IID_NULL;
hr = _d3d12MA.Get()->CreateResource(pAllocationDesc, pResourceDesc, initialState, null, (D3D12MA_Allocation**)ppv, &nuliid, null);
var iid_null = IID.IID_NULL;
hr = _d3d12MA.Get()->CreateResource(pAllocationDesc, pResourceDesc, initialState, null, (D3D12MA_Allocation**)ppv, &iid_null, null);
}
return hr;
@@ -696,7 +617,14 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
return Handle<GPUResource>.Invalid;
}
return TrackAllocation(alloc, D3D12_RESOURCE_STATE_COMMON, ResourceViewGroup.Invalid, default, name, false);
var barrierData = new ResourceBarrierData
{
Access = BarrierAccess.NoAccess,
Layout = BarrierLayout.Common,
Sync = BarrierSync.None
};
return TrackAllocation(alloc, barrierData, ResourceViewGroup.Invalid, default, name, false);
}
public Handle<Texture> CreateTexture(ref readonly TextureDesc desc, string name, CreationOptions options = default)
@@ -756,7 +684,6 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
Flags = D3D12MA_ALLOCATION_FLAG_NONE
};
var initialState = DetermineInitialTextureState(desc.Usage);
var isSubAllocation = options.AllocationType == ResourceAllocationType.Suballocation;
D3D12MA_Allocation* pAllocation = default;
ID3D12Resource* pResource = default;
@@ -764,18 +691,18 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
if (isSubAllocation)
{
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, __uuidof(pResource), (void**)&pResource);
hr = CreateResource(&allocationDesc, &resourceDesc, D3D12_RESOURCE_STATE_COMMON, options, __uuidof(pResource), (void**)&pResource);
}
else
{
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, null, (void**)&pAllocation);
hr = CreateResource(&allocationDesc, &resourceDesc, D3D12_RESOURCE_STATE_COMMON, options, null, (void**)&pAllocation);
pResource = pAllocation->GetResource();
}
if (hr.FAILED)
{
#if DEBUG
Marshal.ThrowExceptionForHR(hr);
ThrowIfFailed(hr);
#endif
return Handle<Texture>.Invalid;
}
@@ -822,14 +749,21 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.uav);
}
var barrierData = new ResourceBarrierData
{
Access = BarrierAccess.NoAccess,
Layout = BarrierLayout.Common,
Sync = BarrierSync.None
};
Handle<GPUResource> resource;
if (isSubAllocation)
{
resource = _resourceDatabase.ImportExternalResource(pResource, initialState.ToResourceState(), resourceDescriptor, name);
resource = _resourceDatabase.ImportExternalResource(pResource, barrierData, resourceDescriptor, name);
}
else
{
resource = TrackAllocation(pAllocation, initialState, resourceDescriptor, ResourceDesc.Texture(desc), name, isTemp);
resource = TrackAllocation(pAllocation, barrierData, resourceDescriptor, ResourceDesc.Texture(desc), name, isTemp);
}
return resource.AsTexture();
@@ -864,24 +798,34 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
Flags = D3D12MA_ALLOCATION_FLAG_NONE,
};
var initialState = DetermineInitialBufferState(desc.Usage, desc.MemoryType);
var isSubAllocation = options.Heap.IsValid;
D3D12MA_Allocation* pAllocation = default;
ID3D12Resource* pResource = default;
HRESULT hr;
var initialState = desc.MemoryType switch
{
ResourceMemoryType.Default => D3D12_RESOURCE_STATE_COMMON,
ResourceMemoryType.Upload => D3D12_RESOURCE_STATE_GENERIC_READ,
ResourceMemoryType.Readback => D3D12_RESOURCE_STATE_COPY_DEST,
_ => D3D12_RESOURCE_STATE_COMMON
};
if (isSubAllocation)
{
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, __uuidof(pResource), (void**)&pResource);
}
else
{
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, null, (void**)&pAllocation);
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, null, (void**)&pAllocation);
pResource = pAllocation->GetResource();
}
if (hr.FAILED)
{
#if DEBUG
ThrowIfFailed(hr);
#endif
return Handle<GraphicsBuffer>.Invalid;
}
@@ -922,14 +866,21 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.uav);
}
var barrierData = new ResourceBarrierData
{
Access = BarrierAccess.NoAccess,
Layout = BarrierLayout.Undefined,
Sync = BarrierSync.None
};
Handle<GPUResource> resource;
if (isSubAllocation)
{
resource = _resourceDatabase.ImportExternalResource(pResource, initialState.ToResourceState(), resourceDescriptor, name);
resource = _resourceDatabase.ImportExternalResource(pResource, barrierData, resourceDescriptor, name);
}
else
{
resource = TrackAllocation(pAllocation, initialState, resourceDescriptor, ResourceDesc.Buffer(desc), name, isTemp);
resource = TrackAllocation(pAllocation, barrierData, resourceDescriptor, ResourceDesc.Buffer(desc), name, isTemp);
}
return resource.AsGraphicsBuffer();

View File

@@ -37,32 +37,37 @@ internal class D3D12ResourceDatabase : IResourceDatabase
public ResourceDesc desc;
public ResourceViewGroup viewGroup;
public ResourceUnion resource;
public ResourceState state;
//public BarrierLayout layout;
//public BarrierAccess access;
//public BarrierSync sync;
public ResourceBarrierData barrierData;
public uint cpuFenceValue;
public readonly bool isExternal;
public readonly bool Allocated => isExternal ? resource.resource.Get() != null : resource.allocation.Get() != null;
public readonly SharedPtr<ID3D12Resource> ResourcePtr => isExternal ? resource.resource.Get() : resource.allocation.Get()->GetResource();
public ResourceRecord(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceState state, ResourceViewGroup resourceDescriptor, ResourceDesc desc)
public ResourceRecord(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceBarrierData barrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc)
{
this.resource = new ResourceUnion(allocation);
this.isExternal = false;
this.viewGroup = resourceDescriptor;
this.cpuFenceValue = cpuFenceValue;
this.state = state;
this.barrierData = barrierData;
this.desc = desc;
}
public ResourceRecord(ID3D12Resource* resource, ResourceState state, ResourceViewGroup viewGroup)
public ResourceRecord(ID3D12Resource* resource, ResourceBarrierData barrierData, ResourceViewGroup viewGroup)
{
this.resource = new ResourceUnion(resource);
this.isExternal = true;
this.viewGroup = viewGroup;
this.cpuFenceValue = ~0u;
this.state = state;
this.barrierData = barrierData;
this.desc = resource->GetDesc().ToResourceDesc();
}
@@ -130,7 +135,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
resource = default!;
}
public unsafe Handle<GPUResource> ImportExternalResource(ID3D12Resource* pResource, ResourceState initialState, ResourceViewGroup viewGroup, string? name = null)
public unsafe Handle<GPUResource> ImportExternalResource(ID3D12Resource* pResource, ResourceBarrierData initialBarrierData, ResourceViewGroup viewGroup, string? name = null)
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (pResource == null)
@@ -141,7 +146,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return Handle<GPUResource>.Invalid;
}
var id = _resources.Add(new ResourceRecord(pResource, initialState, viewGroup), out var generation);
var id = _resources.Add(new ResourceRecord(pResource, initialBarrierData, viewGroup), out var generation);
var handle = new Handle<GPUResource>(id, generation);
#if DEBUG || GHOST_EDITOR
@@ -155,7 +160,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return handle;
}
public unsafe Handle<GPUResource> AddAllocation(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceState initialState, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string? name = null)
public unsafe Handle<GPUResource> AddAllocation(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceBarrierData initialBarrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string? name = null)
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (allocation == null)
@@ -166,7 +171,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return Handle<GPUResource>.Invalid;
}
var id = _resources.Add(new ResourceRecord(allocation, cpuFenceValue, initialState, resourceDescriptor, desc), out var generation);
var id = _resources.Add(new ResourceRecord(allocation, cpuFenceValue, initialBarrierData, resourceDescriptor, desc), out var generation);
var handle = new Handle<GPUResource>(id, generation);
#if DEBUG || GHOST_EDITOR
@@ -215,7 +220,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return r.Value.ResourcePtr;
}
public Result<ResourceState, ErrorStatus> GetResourceState(Handle<GPUResource> handle)
public Result<ResourceBarrierData, ErrorStatus> GetResourceBarrierData(Handle<GPUResource> handle)
{
var r = GetResourceRecord(handle);
if (r.IsFailure)
@@ -223,10 +228,10 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return r.Error;
}
return r.Value.state;
return r.Value.barrierData;
}
public ErrorStatus SetResourceState(Handle<GPUResource> handle, ResourceState state)
public ErrorStatus SetResourceBarrierData(Handle<GPUResource> handle, ResourceBarrierData data)
{
var r = GetResourceRecord(handle);
if (r.IsFailure)
@@ -234,7 +239,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return r.Error;
}
r.Value.state = state;
r.Value.barrierData = data;
return ErrorStatus.None;
}

View File

@@ -156,7 +156,14 @@ internal unsafe class D3D12SwapChain : ISwapChain
rtv = rtv
};
var handle = _resourceDatabase.ImportExternalResource(pBackBuffer, ResourceState.Present, view);
var barrierData = new ResourceBarrierData
{
Access = BarrierAccess.NoAccess,
Layout = BarrierLayout.Present,
Sync = BarrierSync.None,
};
var handle = _resourceDatabase.ImportExternalResource(pBackBuffer, barrierData, view);
_backBuffers[i] = handle.AsTexture();
}
}

View File

@@ -1,3 +1,4 @@
using Ghost.Core.Graphics;
using Ghost.Graphics.RHI;
using TerraFX.Interop.DirectX;
@@ -79,62 +80,62 @@ internal unsafe static class D3D12Utility
{
var d3dStates = D3D12_RESOURCE_STATES.D3D12_RESOURCE_STATE_COMMON;
if ((state & ResourceState.VertexAndConstantBuffer) == ResourceState.VertexAndConstantBuffer)
if (state.HasFlag(ResourceState.VertexAndConstantBuffer))
{
d3dStates |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
}
if ((state & ResourceState.IndexBuffer) == ResourceState.IndexBuffer)
if (state.HasFlag(ResourceState.IndexBuffer))
{
d3dStates |= D3D12_RESOURCE_STATE_INDEX_BUFFER;
}
if ((state & ResourceState.RenderTarget) == ResourceState.RenderTarget)
if (state.HasFlag(ResourceState.RenderTarget))
{
d3dStates |= D3D12_RESOURCE_STATE_RENDER_TARGET;
}
if ((state & ResourceState.UnorderedAccess) == ResourceState.UnorderedAccess)
if (state.HasFlag(ResourceState.UnorderedAccess))
{
d3dStates |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
if ((state & ResourceState.DepthWrite) == ResourceState.DepthWrite)
if (state.HasFlag(ResourceState.DepthWrite))
{
d3dStates |= D3D12_RESOURCE_STATE_DEPTH_WRITE;
}
if ((state & ResourceState.DepthRead) == ResourceState.DepthRead)
if (state.HasFlag(ResourceState.DepthRead))
{
d3dStates |= D3D12_RESOURCE_STATE_DEPTH_READ;
}
if ((state & ResourceState.PixelShaderResource) == ResourceState.PixelShaderResource)
if (state.HasFlag(ResourceState.PixelShaderResource))
{
d3dStates |= D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
}
if ((state & ResourceState.CopyDest) == ResourceState.CopyDest)
if (state.HasFlag(ResourceState.CopyDest))
{
d3dStates |= D3D12_RESOURCE_STATE_COPY_DEST;
}
if ((state & ResourceState.CopySource) == ResourceState.CopySource)
if (state.HasFlag(ResourceState.CopySource))
{
d3dStates |= D3D12_RESOURCE_STATE_COPY_SOURCE;
}
if ((state & ResourceState.GenericRead) == ResourceState.GenericRead)
if (state.HasFlag(ResourceState.GenericRead))
{
d3dStates |= D3D12_RESOURCE_STATE_GENERIC_READ;
}
if ((state & ResourceState.IndirectArgument) == ResourceState.IndirectArgument)
if (state.HasFlag(ResourceState.IndirectArgument))
{
d3dStates |= D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
}
if ((state & ResourceState.NonPixelShaderResource) == ResourceState.NonPixelShaderResource)
if (state.HasFlag(ResourceState.NonPixelShaderResource))
{
d3dStates |= D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
}
@@ -250,6 +251,22 @@ internal unsafe static class D3D12Utility
};
}
public static D3D12_COMPARISON_FUNC ToD3DCompare(this ZTest z)
{
return z switch
{
ZTest.Disabled => D3D12_COMPARISON_FUNC_NEVER,
ZTest.Less => D3D12_COMPARISON_FUNC_LESS,
ZTest.LessEqual => D3D12_COMPARISON_FUNC_LESS_EQUAL,
ZTest.Equal => D3D12_COMPARISON_FUNC_EQUAL,
ZTest.GreaterEqual => D3D12_COMPARISON_FUNC_GREATER_EQUAL,
ZTest.Greater => D3D12_COMPARISON_FUNC_GREATER,
ZTest.NotEqual => D3D12_COMPARISON_FUNC_NOT_EQUAL,
ZTest.Always => D3D12_COMPARISON_FUNC_ALWAYS,
_ => D3D12_COMPARISON_FUNC_LESS_EQUAL
};
}
public static D3D12_COMMAND_LIST_TYPE ToCommandListType(CommandBufferType type)
{
return type switch