forked from Misaki/GhostEngine
Enhanced barrier
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user