diff --git a/include/LLGL/CommandBuffer.h b/include/LLGL/CommandBuffer.h
index ec3deab5fc..693fc05942 100644
--- a/include/LLGL/CommandBuffer.h
+++ b/include/LLGL/CommandBuffer.h
@@ -43,7 +43,7 @@ Before any command can be encoded, the command buffer must be set into encode mo
\remarks In a multi-threaded environment, all blit commands (e.g. CommandBuffer::UpdateBuffer, CommandBuffer::CopyBuffer etc.) must not be called simultaneously
with the same source and/or destination resources even if their ranges do not collide.
-Depending on the backend, those resources might be transitioned into difference states during those commands.
+Depending on the backend, those resources might be transitioned into different states during those commands.
The same applies to CommandBuffer::BeginRenderPass where the specified RenderTarget might be transitioned into rendering state.
Binding resources (CommandBuffer::SetResource, CommandBuffer::SetResourceHeap) as well as vertex (CommandBuffer::SetVertexBuffer) and
index streams (CommandBuffer::SetIndexBuffer) can be performed in a multi-threaded fashion with either the same or separate resources.
diff --git a/sources/Renderer/Direct3D12/Buffer/D3D12Buffer.cpp b/sources/Renderer/Direct3D12/Buffer/D3D12Buffer.cpp
index 47d60f3d63..0e7b1ea01e 100644
--- a/sources/Renderer/Direct3D12/Buffer/D3D12Buffer.cpp
+++ b/sources/Renderer/Direct3D12/Buffer/D3D12Buffer.cpp
@@ -225,8 +225,12 @@ void D3D12Buffer::ClearSubresourceUInt(
CreateIntermediateUAVDescriptorHeap(resource, format, formatStride);
/* Get GPU and CPU descriptor handles for intermediate descriptor heap */
- D3D12_GPU_DESCRIPTOR_HANDLE gpuDescHandle = uavIntermediateDescHeap_->GetGPUDescriptorHandleForHeapStart();
+ D3D12DescriptorHeapSetLayout layout;
+ layout.numHeapResourceViews = 1;
+ commandContext.PrepareStagingDescriptorHeaps(layout, {});
+ //D3D12_GPU_DESCRIPTOR_HANDLE gpuDescHandle = uavIntermediateDescHeap_->GetGPUDescriptorHandleForHeapStart();
D3D12_CPU_DESCRIPTOR_HANDLE cpuDescHandle = uavIntermediateDescHeap_->GetCPUDescriptorHandleForHeapStart();
+ D3D12_GPU_DESCRIPTOR_HANDLE gpuDescHandle = commandContext.CopyDescriptorsForStaging(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, cpuDescHandle, 0, 1);
if (useIntermediateBuffer)
{
@@ -258,7 +262,7 @@ void D3D12Buffer::ClearSubresourceUInt(
else
{
/* Clear destination buffer directly with intermediate UAV */
- commandContext.TransitionResource(GetResource(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true);
+ commandContext.TransitionResource(GetResource(), D3D12_RESOURCE_STATE_COMMON, true);
{
ClearSubresourceWithUAV(
commandList,
@@ -401,6 +405,9 @@ void D3D12Buffer::CreateGpuBuffer(ID3D12Device* device, const BufferDescriptor&
if ((desc.bindFlags & BindFlags::StreamOutputBuffer) != 0)
internalSize_ += g_soBufferFillSizeLen;
+ /* Store buffer primary usage stage */
+ resource_.usageState = GetD3DUsageState(desc.bindFlags);
+
/* Create generic buffer resource */
const CD3DX12_HEAP_PROPERTIES heapProperties{ D3D12_HEAP_TYPE_DEFAULT };
const CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(GetInternalBufferSize(), GetD3DResourceFlags(desc));
@@ -408,7 +415,7 @@ void D3D12Buffer::CreateGpuBuffer(ID3D12Device* device, const BufferDescriptor&
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&bufferDesc,
- resource_.SetInitialAndUsageStates(D3D12_RESOURCE_STATE_COPY_DEST, GetD3DUsageState(desc.bindFlags)),
+ D3D12_RESOURCE_STATE_COMMON, // Buffers are effectively created in D3D12_RESOURCE_STATE_COMMON state
nullptr,
IID_PPV_ARGS(resource_.native.ReleaseAndGetAddressOf())
);
@@ -440,7 +447,7 @@ void D3D12Buffer::CreateCpuAccessBuffer(ID3D12Device* device, long cpuAccessFlag
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&bufferDesc,
- cpuAccessBuffer_.usageState,
+ D3D12_RESOURCE_STATE_COMMON, // Buffers are effectively created in D3D12_RESOURCE_STATE_COMMON state
nullptr,
IID_PPV_ARGS(cpuAccessBuffer_.native.ReleaseAndGetAddressOf())
);
@@ -495,13 +502,11 @@ void D3D12Buffer::CreateIntermediateUAVBuffer()
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&bufferDesc,
- D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+ D3D12_RESOURCE_STATE_COMMON, // Buffers are effectively created in D3D12_RESOURCE_STATE_COMMON state
nullptr,
IID_PPV_ARGS(uavIntermediateBuffer_.native.ReleaseAndGetAddressOf())
);
DXThrowIfCreateFailed(hr, "ID3D12Resource", "for buffer subresource UAV");
-
- uavIntermediateBuffer_.SetInitialState(D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
}
void D3D12Buffer::CreateVertexBufferView(const BufferDescriptor& desc)
diff --git a/sources/Renderer/Direct3D12/Buffer/D3D12BufferArray.cpp b/sources/Renderer/Direct3D12/Buffer/D3D12BufferArray.cpp
index c9b7d5031f..cc3eec0380 100644
--- a/sources/Renderer/Direct3D12/Buffer/D3D12BufferArray.cpp
+++ b/sources/Renderer/Direct3D12/Buffer/D3D12BufferArray.cpp
@@ -21,8 +21,12 @@ D3D12BufferArray::D3D12BufferArray(std::uint32_t numBuffers, Buffer* const * buf
{
/* Store the strides and offests of each D3D12VertexBuffer inside the arrays */
vertexBufferViews_.reserve(numBuffers);
+ resourceRefs_.reserve(numBuffers);
while (D3D12Buffer* next = NextArrayResource(numBuffers, bufferArray))
+ {
vertexBufferViews_.push_back(next->GetVertexBufferView());
+ resourceRefs_.push_back(&(next->GetResource()));
+ }
}
diff --git a/sources/Renderer/Direct3D12/Buffer/D3D12BufferArray.h b/sources/Renderer/Direct3D12/Buffer/D3D12BufferArray.h
index 27e39cf576..5c45a4b37b 100644
--- a/sources/Renderer/Direct3D12/Buffer/D3D12BufferArray.h
+++ b/sources/Renderer/Direct3D12/Buffer/D3D12BufferArray.h
@@ -10,8 +10,8 @@
#include
+#include
#include
-#include
namespace LLGL
@@ -19,6 +19,7 @@ namespace LLGL
class Buffer;
+struct D3D12Resource;
class D3D12BufferArray final : public BufferArray
{
@@ -28,14 +29,21 @@ class D3D12BufferArray final : public BufferArray
D3D12BufferArray(std::uint32_t numBuffers, Buffer* const * bufferArray);
// Returns the array of vertex buffer views.
- inline const std::vector& GetVertexBufferViews() const
+ inline ArrayView GetVertexBufferViews() const
{
return vertexBufferViews_;
}
+ // Returns the array of vertex buffer resource references.
+ inline ArrayView GetResourceRefs() const
+ {
+ return resourceRefs_;
+ }
+
private:
- std::vector vertexBufferViews_;
+ SmallVector vertexBufferViews_;
+ SmallVector resourceRefs_;
};
diff --git a/sources/Renderer/Direct3D12/Buffer/D3D12BufferConstantsPool.cpp b/sources/Renderer/Direct3D12/Buffer/D3D12BufferConstantsPool.cpp
index 39d50306b7..a6ad829fbd 100644
--- a/sources/Renderer/Direct3D12/Buffer/D3D12BufferConstantsPool.cpp
+++ b/sources/Renderer/Direct3D12/Buffer/D3D12BufferConstantsPool.cpp
@@ -95,11 +95,12 @@ void D3D12BufferConstantsPool::CreateImmutableBuffer(
const UINT64 bufferSize = data.size() * sizeof(UINT64);
const CD3DX12_HEAP_PROPERTIES heapProperties{ D3D12_HEAP_TYPE_DEFAULT };
const CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(bufferSize);
+ resource_.usageState = D3D12_RESOURCE_STATE_COPY_SOURCE;
HRESULT hr = device->CreateCommittedResource(
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&bufferDesc,
- resource_.SetInitialAndUsageStates(D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE),
+ D3D12_RESOURCE_STATE_COMMON, // Buffers are effectively created in D3D12_RESOURCE_STATE_COMMON state
nullptr,
IID_PPV_ARGS(resource_.native.ReleaseAndGetAddressOf())
);
diff --git a/sources/Renderer/Direct3D12/Command/D3D12CommandBuffer.cpp b/sources/Renderer/Direct3D12/Command/D3D12CommandBuffer.cpp
index 01e45f9d03..bfb7772b03 100644
--- a/sources/Renderer/Direct3D12/Command/D3D12CommandBuffer.cpp
+++ b/sources/Renderer/Direct3D12/Command/D3D12CommandBuffer.cpp
@@ -152,7 +152,7 @@ void D3D12CommandBuffer::CopyBufferFromTexture(
const UINT64 alignedBufferSize = GetAlignedImageSize(srcExtent, rowStride, alignedRowStride);
ID3D12Resource* alignedBuffer = commandContext_.AllocIntermediateBuffer(alignedBufferSize, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
- commandContext_.TransitionResource(alignedBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ, true);
+ commandContext_.TransitionBarrier(alignedBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ, true);
/* Copy entire region from source texture into intermediate buffer */
const D3D12_TEXTURE_COPY_LOCATION dstLocationD3D = srcTextureD3D.CalcCopyLocation(alignedBuffer, 0, srcExtent, alignedRowStride);
@@ -165,7 +165,7 @@ void D3D12CommandBuffer::CopyBufferFromTexture(
&srcBox // pSrcBox
);
- commandContext_.TransitionResource(alignedBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST, true);
+ commandContext_.TransitionBarrier(alignedBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST, true);
/* Copy each row individually from intermediate buffer into destination buffer due to unalgined row pitch */
UINT64 alignedOffset = 0;
@@ -179,7 +179,7 @@ void D3D12CommandBuffer::CopyBufferFromTexture(
}
}
- commandContext_.TransitionResource(alignedBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_SOURCE, true);
+ commandContext_.TransitionBarrier(alignedBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_SOURCE, true);
}
else
{
@@ -286,7 +286,7 @@ void D3D12CommandBuffer::CopyTextureFromBuffer(
const UINT64 alignedBufferSize = GetAlignedImageSize(dstExtent, rowStride, alignedRowStride);
ID3D12Resource* alignedBuffer = commandContext_.AllocIntermediateBuffer(alignedBufferSize, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
- commandContext_.TransitionResource(alignedBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ, true);
+ commandContext_.TransitionBarrier(alignedBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ, true);
/* Copy each row individually from intermediate buffer into destination texture due to unalgined row pitch */
UINT64 alignedOffset = 0;
@@ -300,7 +300,7 @@ void D3D12CommandBuffer::CopyTextureFromBuffer(
}
}
- commandContext_.TransitionResource(alignedBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST, true);
+ commandContext_.TransitionBarrier(alignedBuffer, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST, true);
/* Copy entire region from intermediate buffer into destination texture */
const D3D12_TEXTURE_COPY_LOCATION srcLocationD3D = dstTextureD3D.CalcCopyLocation(alignedBuffer, 0, dstExtent, alignedRowStride);
@@ -313,7 +313,7 @@ void D3D12CommandBuffer::CopyTextureFromBuffer(
&srcBox // pSrcBox
);
- commandContext_.TransitionResource(alignedBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_SOURCE, true);
+ commandContext_.TransitionBarrier(alignedBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_SOURCE, true);
}
else
{
@@ -510,12 +510,18 @@ void D3D12CommandBuffer::ClearAttachments(std::uint32_t numAttachments, const At
void D3D12CommandBuffer::SetVertexBuffer(Buffer& buffer)
{
auto& bufferD3D = LLGL_CAST(D3D12Buffer&, buffer);
+ commandContext_.TransitionResource(bufferD3D.GetResource(), D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, true);
GetNative()->IASetVertexBuffers(0, 1, &(bufferD3D.GetVertexBufferView()));
}
void D3D12CommandBuffer::SetVertexBufferArray(BufferArray& bufferArray)
{
auto& bufferArrayD3D = LLGL_CAST(D3D12BufferArray&, bufferArray);
+
+ for (D3D12Resource* resource : bufferArrayD3D.GetResourceRefs())
+ commandContext_.TransitionResource(*resource, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
+ commandContext_.FlushResourceBarrieres();
+
GetNative()->IASetVertexBuffers(
0,
static_cast(bufferArrayD3D.GetVertexBufferViews().size()),
@@ -526,6 +532,7 @@ void D3D12CommandBuffer::SetVertexBufferArray(BufferArray& bufferArray)
void D3D12CommandBuffer::SetIndexBuffer(Buffer& buffer)
{
auto& bufferD3D = LLGL_CAST(D3D12Buffer&, buffer);
+ commandContext_.TransitionResource(bufferD3D.GetResource(), D3D12_RESOURCE_STATE_INDEX_BUFFER, true);
commandContext_.SetIndexBuffer(bufferD3D.GetIndexBufferView());
}
@@ -535,6 +542,8 @@ void D3D12CommandBuffer::SetIndexBuffer(Buffer& buffer, const Format format, std
D3D12_INDEX_BUFFER_VIEW indexBufferView = bufferD3D.GetIndexBufferView();
if (indexBufferView.SizeInBytes > offset)
{
+ commandContext_.TransitionResource(bufferD3D.GetResource(), D3D12_RESOURCE_STATE_INDEX_BUFFER, true);
+
/* Update buffer location and size by offset, and override format */
indexBufferView.BufferLocation += offset;
indexBufferView.SizeInBytes -= static_cast(offset);
@@ -576,7 +585,8 @@ void D3D12CommandBuffer::SetResourceHeap(ResourceHeap& resourceHeap, std::uint32
}
/* Insert resource barriers for the specified descriptor set */
- resourceHeapD3D.InsertResourceBarriers(GetNative(), descriptorSet);
+ resourceHeapD3D.TransitionResources(commandContext_, descriptorSet);
+ resourceHeapD3D.InsertUAVBarriers(GetNative(), descriptorSet);
}
/*
@@ -605,6 +615,11 @@ void D3D12CommandBuffer::SetResource(std::uint32_t descriptor, Resource& resourc
const D3D12DescriptorLocation& rootParameterLocation = boundPipelineLayout_->GetRootParameterMap()[descriptor];
if (rootParameterLocation.type != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
{
+ /* Transition resource into target state */
+ //TODO: should this be flushed immediately for root parameters?
+ commandContext_.TransitionGenericResource(resource, rootParameterLocation.state);
+
+ /* Set resource as root parameter */
D3D12_GPU_VIRTUAL_ADDRESS gpuVirtualAddr = GetD3DResourceGPUAddr(resource);
if (gpuVirtualAddr != 0)
{
@@ -617,8 +632,9 @@ void D3D12CommandBuffer::SetResource(std::uint32_t descriptor, Resource& resourc
}
else
{
- /* Bind resource with staging descriptor heap */
+ /* Transition resource into target state and bind resource with staging descriptor heap */
const D3D12DescriptorHeapLocation& descriptorLocation = boundPipelineLayout_->GetDescriptorMap()[descriptor];
+ commandContext_.TransitionGenericResource(resource, descriptorLocation.state);
commandContext_.EmplaceDescriptorForStaging(resource, descriptorLocation.index, descriptorLocation.type);
}
}
diff --git a/sources/Renderer/Direct3D12/Command/D3D12CommandContext.cpp b/sources/Renderer/Direct3D12/Command/D3D12CommandContext.cpp
index 911d4411ce..a97e2fbbc9 100644
--- a/sources/Renderer/Direct3D12/Command/D3D12CommandContext.cpp
+++ b/sources/Renderer/Direct3D12/Command/D3D12CommandContext.cpp
@@ -9,7 +9,10 @@
#include "D3D12CommandQueue.h"
#include "../D3D12Device.h"
#include "../D3D12Resource.h"
+#include "../Buffer/D3D12Buffer.h"
+#include "../Texture/D3D12Texture.h"
#include "../RenderState/D3D12Fence.h"
+#include "../../CheckedCast.h"
#include "../../DXCommon/DXCore.h"
#include "../../../Core/Assertion.h"
#include
@@ -147,7 +150,7 @@ void D3D12CommandContext::FinishAndSync(D3D12CommandQueue& commandQueue)
commandQueue.WaitIdle();
}
-void D3D12CommandContext::TransitionResource(ID3D12Resource* resource, D3D12_RESOURCE_STATES newState, D3D12_RESOURCE_STATES oldState, bool flushImmediate)
+void D3D12CommandContext::TransitionBarrier(ID3D12Resource* resource, D3D12_RESOURCE_STATES newState, D3D12_RESOURCE_STATES oldState, UINT subresource, bool flushImmediate)
{
D3D12_RESOURCE_BARRIER& barrier = NextResourceBarrier();
@@ -155,7 +158,7 @@ void D3D12CommandContext::TransitionResource(ID3D12Resource* resource, D3D12_RES
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = resource;
- barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ barrier.Transition.Subresource = subresource;
barrier.Transition.StateBefore = oldState;
barrier.Transition.StateAfter = newState;
@@ -164,6 +167,11 @@ void D3D12CommandContext::TransitionResource(ID3D12Resource* resource, D3D12_RES
FlushResourceBarrieres();
}
+void D3D12CommandContext::TransitionBarrier(ID3D12Resource* resource, D3D12_RESOURCE_STATES newState, D3D12_RESOURCE_STATES oldState, bool flushImmediate)
+{
+ TransitionBarrier(resource, newState, oldState, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, flushImmediate);
+}
+
void D3D12CommandContext::TransitionResource(D3D12Resource& resource, D3D12_RESOURCE_STATES newState, bool flushImmediate)
{
if (resource.currentState != newState)
@@ -187,13 +195,36 @@ void D3D12CommandContext::TransitionResource(D3D12Resource& resource, D3D12_RESO
FlushResourceBarrieres();
}
-void D3D12CommandContext::InsertUAVBarrier(D3D12Resource& resource, bool flushImmediate)
+void D3D12CommandContext::TransitionGenericResource(Resource& resource, D3D12_RESOURCE_STATES newState, bool flushImmediate)
+{
+ switch (resource.GetResourceType())
+ {
+ case ResourceType::Buffer:
+ {
+ auto& bufferD3D = LLGL_CAST(D3D12Buffer&, resource);
+ TransitionResource(bufferD3D.GetResource(), newState, flushImmediate);
+ }
+ break;
+
+ case ResourceType::Texture:
+ {
+ auto& textureD3D = LLGL_CAST(D3D12Texture&, resource);
+ TransitionResource(textureD3D.GetResource(), newState, flushImmediate);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void D3D12CommandContext::UAVBarrier(ID3D12Resource* resource, bool flushImmediate)
{
D3D12_RESOURCE_BARRIER& barrier = NextResourceBarrier();
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrier.UAV.pResource = resource.native.Get();
+ barrier.UAV.pResource = resource;
if (flushImmediate)
FlushResourceBarrieres();
@@ -481,6 +512,7 @@ void D3D12CommandContext::DrawInstanced(
UINT startVertexLocation,
UINT startInstanceLocation)
{
+ FlushResourceBarrieres();
FlushDeferredPipelineState();
FlushGraphicsStagingDescriptorTables();
commandList_->DrawInstanced(vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation);
@@ -493,6 +525,7 @@ void D3D12CommandContext::DrawIndexedInstanced(
INT baseVertexLocation,
UINT startInstanceLocation)
{
+ FlushResourceBarrieres();
FlushDeferredPipelineState();
FlushGraphicsStagingDescriptorTables();
commandList_->DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);
@@ -506,6 +539,7 @@ void D3D12CommandContext::DrawIndirect(
ID3D12Resource* countBuffer,
UINT64 countBufferOffset)
{
+ FlushResourceBarrieres();
FlushDeferredPipelineState();
FlushGraphicsStagingDescriptorTables();
commandList_->ExecuteIndirect(commandSignature, maxCommandCount, argumentBuffer, argumentBufferOffset, countBuffer, countBufferOffset);
@@ -516,6 +550,7 @@ void D3D12CommandContext::Dispatch(
UINT threadGroupCountY,
UINT threadGroupCountZ)
{
+ FlushResourceBarrieres();
FlushComputeStagingDescriptorTables();
commandList_->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ);
}
@@ -528,6 +563,7 @@ void D3D12CommandContext::DispatchIndirect(
ID3D12Resource* countBuffer,
UINT64 countBufferOffset)
{
+ FlushResourceBarrieres();
FlushComputeStagingDescriptorTables();
commandList_->ExecuteIndirect(commandSignature, maxCommandCount, argumentBuffer, argumentBufferOffset, countBuffer, countBufferOffset);
}
diff --git a/sources/Renderer/Direct3D12/Command/D3D12CommandContext.h b/sources/Renderer/Direct3D12/Command/D3D12CommandContext.h
index b69ce10e19..23ba7ea154 100644
--- a/sources/Renderer/Direct3D12/Command/D3D12CommandContext.h
+++ b/sources/Renderer/Direct3D12/Command/D3D12CommandContext.h
@@ -79,12 +79,16 @@ class D3D12CommandContext
return commandList_.Get();
}
- // Transition all subresources to the specified new state.
- void TransitionResource(ID3D12Resource* resource, D3D12_RESOURCE_STATES newState, D3D12_RESOURCE_STATES oldState, bool flushImmediate = false);
- void TransitionResource(D3D12Resource& resource, D3D12_RESOURCE_STATES newState, bool flushImmediate = false);
-
// Insert a resource barrier for an unordered access view (UAV).
- void InsertUAVBarrier(D3D12Resource& resource, bool flushImmediate = false);
+ void UAVBarrier(ID3D12Resource* resource, bool flushImmediate = false);
+
+ // Insert a transition barrier for a native D3D12 subresource.
+ void TransitionBarrier(ID3D12Resource* resource, D3D12_RESOURCE_STATES newState, D3D12_RESOURCE_STATES oldState, bool flushImmediate = false);
+ void TransitionBarrier(ID3D12Resource* resource, D3D12_RESOURCE_STATES newState, D3D12_RESOURCE_STATES oldState, UINT subresource, bool flushImmediate);
+
+ // Transition and cache a resource state.
+ void TransitionResource(D3D12Resource& resource, D3D12_RESOURCE_STATES newState, bool flushImmediate = false);
+ void TransitionGenericResource(Resource& resource, D3D12_RESOURCE_STATES newState, bool flushImmediate = false);
// Flush all accumulated resource barriers.
void FlushResourceBarrieres();
diff --git a/sources/Renderer/Direct3D12/D3D12Resource.h b/sources/Renderer/Direct3D12/D3D12Resource.h
index d73aad5185..1e67121623 100644
--- a/sources/Renderer/Direct3D12/D3D12Resource.h
+++ b/sources/Renderer/Direct3D12/D3D12Resource.h
@@ -52,7 +52,7 @@ struct D3D12Resource
}
ComPtr native;
- D3D12_RESOURCE_STATES usageState = D3D12_RESOURCE_STATE_COMMON;
+ D3D12_RESOURCE_STATES usageState = D3D12_RESOURCE_STATE_COMMON; //TODO: remove usage state
D3D12_RESOURCE_STATES currentState = D3D12_RESOURCE_STATE_COMMON;
};
diff --git a/sources/Renderer/Direct3D12/D3D12SubresourceContext.cpp b/sources/Renderer/Direct3D12/D3D12SubresourceContext.cpp
index c84692cab7..2ef91aa471 100644
--- a/sources/Renderer/Direct3D12/D3D12SubresourceContext.cpp
+++ b/sources/Renderer/Direct3D12/D3D12SubresourceContext.cpp
@@ -26,7 +26,7 @@ D3D12SubresourceContext::~D3D12SubresourceContext()
commandContext_.FinishAndSync(commandQueue_);
}
-ID3D12Resource* D3D12SubresourceContext::CreateUploadBuffer(UINT64 size, D3D12_RESOURCE_STATES initialState)
+ID3D12Resource* D3D12SubresourceContext::CreateUploadBuffer(UINT64 size)
{
/* Create buffer resource in upload heap */
ComPtr resource;
@@ -36,15 +36,15 @@ ID3D12Resource* D3D12SubresourceContext::CreateUploadBuffer(UINT64 size, D3D12_R
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&bufferDesc,
- initialState,
+ D3D12_RESOURCE_STATE_GENERIC_READ, // Initial state of upload heap resourceds must be D3D12_RESOURCE_STATE_GENERIC_READ
nullptr,
IID_PPV_ARGS(resource.ReleaseAndGetAddressOf())
);
DXThrowIfCreateFailed(hr, "ID3D12Resource", "for subresource upload buffer");
- return TakeAndGetNative(resource);
+ return StoreAndGetNative(std::move(resource));
}
-ID3D12Resource* D3D12SubresourceContext::CreateReadbackBuffer(UINT64 size, D3D12_RESOURCE_STATES initialState)
+ID3D12Resource* D3D12SubresourceContext::CreateReadbackBuffer(UINT64 size)
{
/* Create buffer resource in readback heap */
ComPtr resource;
@@ -54,12 +54,12 @@ ID3D12Resource* D3D12SubresourceContext::CreateReadbackBuffer(UINT64 size, D3D12
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&bufferDesc,
- initialState,
+ D3D12_RESOURCE_STATE_COPY_DEST, // Initial state of readback heap resources must be D3D12_RESOURCE_STATE_COPY_DEST
nullptr,
IID_PPV_ARGS(resource.ReleaseAndGetAddressOf())
);
DXThrowIfCreateFailed(hr, "ID3D12Resource", "for subresource readback buffer");
- return TakeAndGetNative(resource);
+ return StoreAndGetNative(std::move(resource));
}
ID3D12Resource* D3D12SubresourceContext::CreateTexture(const D3D12_RESOURCE_DESC& desc, D3D12_RESOURCE_STATES initialState)
@@ -76,7 +76,7 @@ ID3D12Resource* D3D12SubresourceContext::CreateTexture(const D3D12_RESOURCE_DESC
IID_PPV_ARGS(resource.ReleaseAndGetAddressOf())
);
DXThrowIfCreateFailed(hr, "ID3D12Resource", "for subresource update texture");
- return TakeAndGetNative(resource);
+ return StoreAndGetNative(std::move(resource));
}
ComPtr D3D12SubresourceContext::TakeResource()
@@ -86,7 +86,7 @@ ComPtr D3D12SubresourceContext::TakeResource()
return resource;
}
-ID3D12Resource* D3D12SubresourceContext::TakeAndGetNative(ComPtr& resource)
+ID3D12Resource* D3D12SubresourceContext::StoreAndGetNative(ComPtr&& resource)
{
intermediateResources_.push_back(std::move(resource));
return intermediateResources_.back().Get();
diff --git a/sources/Renderer/Direct3D12/D3D12SubresourceContext.h b/sources/Renderer/Direct3D12/D3D12SubresourceContext.h
index 51f32610b4..7f6886e8f4 100644
--- a/sources/Renderer/Direct3D12/D3D12SubresourceContext.h
+++ b/sources/Renderer/Direct3D12/D3D12SubresourceContext.h
@@ -29,15 +29,15 @@ class D3D12SubresourceContext
~D3D12SubresourceContext();
// Creates a buffer resource in the upload heap (D3D12_HEAP_TYPE_UPLOAD).
- ID3D12Resource* CreateUploadBuffer(UINT64 size, D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_GENERIC_READ);
+ ID3D12Resource* CreateUploadBuffer(UINT64 size);
// Creates a buffer resource in the readback heap (D3D12_HEAP_TYPE_READBACK).
- ID3D12Resource* CreateReadbackBuffer(UINT64 size, D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COPY_DEST);
+ ID3D12Resource* CreateReadbackBuffer(UINT64 size);
// Creates a texture resource in the default heap (D3D12_HEAP_TYPE_DEFAULT).
ID3D12Resource* CreateTexture(const D3D12_RESOURCE_DESC& desc, D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COPY_DEST);
- // Returns ownership of the most recently added resource.
+ // Returns ownership of the most recently stored resource.
ComPtr TakeResource();
inline D3D12CommandContext& GetCommandContext()
@@ -57,7 +57,8 @@ class D3D12SubresourceContext
private:
- ID3D12Resource* TakeAndGetNative(ComPtr& resource);
+ // Stores the specified resource in the container of intermediate resources and returns its native handle.
+ ID3D12Resource* StoreAndGetNative(ComPtr&& resource);
private:
diff --git a/sources/Renderer/Direct3D12/RenderState/D3D12DescriptorCache.cpp b/sources/Renderer/Direct3D12/RenderState/D3D12DescriptorCache.cpp
index d600e463bd..ff84db6fa8 100644
--- a/sources/Renderer/Direct3D12/RenderState/D3D12DescriptorCache.cpp
+++ b/sources/Renderer/Direct3D12/RenderState/D3D12DescriptorCache.cpp
@@ -42,7 +42,7 @@ void D3D12DescriptorCache::Create(
void D3D12DescriptorCache::Reset(UINT numResources, UINT numSamplers)
{
- /* Store new strides and resize descriptor heaps if necessary */
+ /* Store new sizes and resize descriptor heaps if necessary */
currentStrides_[g_dhIndexCbvSrvUav] = numResources;
if (descriptorHeaps_[g_dhIndexCbvSrvUav].GetSize() < numResources)
{
diff --git a/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.cpp b/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.cpp
index 7813a3e11e..bc303bddf1 100644
--- a/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.cpp
+++ b/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.cpp
@@ -280,6 +280,27 @@ static bool IsFilteredBinding(const BindingDescriptor& bindingDesc, const Resour
return (bindingDesc.type == resourceType && (bindFlags == 0 || (bindingDesc.bindFlags & bindFlags) != 0));
}
+static D3D12_RESOURCE_STATES GetD3D12BindingResourceState(const BindingDescriptor& bindingDesc)
+{
+ if (bindingDesc.stageFlags != 0)
+ {
+ if ((bindingDesc.bindFlags & BindFlags::ConstantBuffer) != 0 && bindingDesc.type == ResourceType::Buffer)
+ return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
+ if ((bindingDesc.bindFlags & BindFlags::Storage) != 0)
+ return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
+ if ((bindingDesc.bindFlags & BindFlags::Sampled) != 0)
+ {
+ if (bindingDesc.stageFlags == StageFlags::FragmentStage)
+ return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
+ else if ((bindingDesc.stageFlags & StageFlags::FragmentStage) == 0)
+ return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ else
+ return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
+ }
+ }
+ return D3D12_RESOURCE_STATE_COMMON;
+}
+
void D3D12PipelineLayout::BuildHeapRootParameterTables(
D3D12RootSignature& rootSignature,
D3D12_DESCRIPTOR_RANGE_TYPE descRangeType,
@@ -339,6 +360,9 @@ void D3D12PipelineLayout::BuildHeapRootParameterTableEntry(
rootParamIndexStored = rootParamIndex;
}
+ /* Store target state the binding must be in when it's bound */
+ outLocation.state = GetD3D12BindingResourceState(bindingDesc);
+
/* Cache binding flags in the same order root parameters are build */
descriptorHeapLayout_.GetDescriptorLocation(descRangeType, outLocation);
}
@@ -417,6 +441,9 @@ void D3D12PipelineLayout::BuildRootParameterTableEntry(
rootParamIndexStored = rootParamIndex;
}
+ /* Store target state the binding must be in when it's bound */
+ outLocation.state = GetD3D12BindingResourceState(bindingDesc);
+
/* Cache binding flags in the same order root parameters are build */
descriptorLayout_.GetDescriptorLocation(descRangeType, outLocation);
}
@@ -461,6 +488,7 @@ void D3D12PipelineLayout::BuildRootParameter(
/* Cache binding flags in the same order root parameters are build */
outLocation.type = rootParamType;
outLocation.index = rootParamIndex;
+ outLocation.state = GetD3D12BindingResourceState(bindingDesc);
}
void D3D12PipelineLayout::BuildStaticSamplers(
diff --git a/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.h b/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.h
index 83041882cd..9dea849d15 100644
--- a/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.h
+++ b/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.h
@@ -32,6 +32,7 @@ struct D3D12DescriptorHeapLocation
D3D12_DESCRIPTOR_RANGE_TYPE type;
UINT heap : 1; // Descriptor heap index (0 = SBC/SRV/UAV, 1 = Sampler)
UINT index : 31; // Descriptor index within its descriptor heap
+ D3D12_RESOURCE_STATES state; // Target resource state
};
// Resource descriptor to root parameter/ descriptor table range mapping structure.
@@ -39,6 +40,7 @@ struct D3D12DescriptorLocation
{
D3D12_ROOT_PARAMETER_TYPE type;
UINT index; // Root parameter index
+ D3D12_RESOURCE_STATES state; // Target resource state
};
// Uniform to root constant mapping structure.
diff --git a/sources/Renderer/Direct3D12/RenderState/D3D12ResourceHeap.cpp b/sources/Renderer/Direct3D12/RenderState/D3D12ResourceHeap.cpp
index 4f6fec931d..478e9c414a 100644
--- a/sources/Renderer/Direct3D12/RenderState/D3D12ResourceHeap.cpp
+++ b/sources/Renderer/Direct3D12/RenderState/D3D12ResourceHeap.cpp
@@ -12,6 +12,7 @@
#include "../Buffer/D3D12Buffer.h"
#include "../Texture/D3D12Sampler.h"
#include "../Texture/D3D12Texture.h"
+#include "../Command/D3D12CommandContext.h"
#include "../../DXCommon/DXCore.h"
#include "../../ResourceUtils.h"
#include "../../TextureUtils.h"
@@ -56,6 +57,7 @@ D3D12ResourceHeap::D3D12ResourceHeap(
/* Keep copy of root parameter map */
descriptorMap_ = pipelineLayoutD3D->GetDescriptorHeapMap();
+ resources_.resize(numDescriptorSets_ * numDescriptorsPerSet_[0], nullptr);
/* Create descriptor heaps */
if (numDescriptorsPerSet_[0] > 0)
@@ -84,6 +86,30 @@ D3D12ResourceHeap::D3D12ResourceHeap(
SetDebugName(desc.debugName);
}
+static D3D12Resource* GetD3DResourceRef(Resource& resource)
+{
+ switch (resource.GetResourceType())
+ {
+ case ResourceType::Buffer:
+ {
+ auto& bufferD3D = LLGL_CAST(D3D12Buffer&, resource);
+ return &(bufferD3D.GetResource());
+ }
+ break;
+
+ case ResourceType::Texture:
+ {
+ auto& textureD3D = LLGL_CAST(D3D12Texture&, resource);
+ return &(textureD3D.GetResource());
+ }
+ break;
+
+ default:
+ break;
+ }
+ return nullptr;
+}
+
std::uint32_t D3D12ResourceHeap::CreateResourceViewHandles(
ID3D12Device* device,
std::uint32_t firstDescriptor,
@@ -115,7 +141,7 @@ std::uint32_t D3D12ResourceHeap::CreateResourceViewHandles(
std::uint32_t numWritten = 0;
std::uint32_t uavChangeSetRange[2] = { UINT32_MAX, 0 };
- for (const auto& desc : resourceViews)
+ for (const ResourceViewDescriptor& desc : resourceViews)
{
/* Skip over empty resource descriptors */
if (desc.resource == nullptr)
@@ -129,6 +155,14 @@ std::uint32_t D3D12ResourceHeap::CreateResourceViewHandles(
cpuDescHandle.ptr = cpuDescHandles[descriptorLocation.heap].ptr + handleOffset + setOffset;
+ /* Store reference to resource state */
+ if (descriptorLocation.heap == 0)
+ {
+ const UINT descriptorHeap0Index = descriptorSet * numDescriptorsPerSet_[0] + descriptorLocation.index;
+ LLGL_ASSERT(descriptorHeap0Index < resources_.size());
+ resources_[descriptorHeap0Index] = GetD3DResourceRef(*(desc.resource));
+ }
+
/* Write current resource view to descriptor heap */
switch (descriptorLocation.type)
{
@@ -173,9 +207,21 @@ std::uint32_t D3D12ResourceHeap::CreateResourceViewHandles(
return numWritten;
}
-void D3D12ResourceHeap::InsertResourceBarriers(ID3D12GraphicsCommandList* commandList, std::uint32_t descriptorSet)
+void D3D12ResourceHeap::TransitionResources(D3D12CommandContext& context, std::uint32_t descriptorSet)
+{
+ /* Transition all D3D resources in the specified descriptor set; Only heap 0 for CBV/SRV/UAV */
+ for_range(i, numDescriptorsPerSet_[0])
+ {
+ const UINT descriptorHeap0Index = descriptorSet * numDescriptorsPerSet_[0] + i;
+ LLGL_ASSERT(descriptorHeap0Index < resources_.size());
+ if (D3D12Resource* resource = resources_[descriptorHeap0Index])
+ context.TransitionResource(*resource, descriptorMap_[i].state);
+ }
+}
+
+void D3D12ResourceHeap::InsertUAVBarriers(ID3D12GraphicsCommandList* commandList, std::uint32_t descriptorSet)
{
- if (descriptorSet < numDescriptorSets_ && HasBarriers())
+ if (descriptorSet < numDescriptorSets_ && HasUAVBarriers())
{
const auto barrierHeapStart = &barriers_[descriptorSet * barrierStride_];
const auto numBarriers = *reinterpret_cast(barrierHeapStart);
@@ -364,7 +410,7 @@ void D3D12ResourceHeap::ExchangeUAVResource(
Resource& resource,
std::uint32_t (&setRange)[2])
{
- if (HasBarriers())
+ if (HasUAVBarriers())
{
if (resource.GetResourceType() == ResourceType::Buffer)
{
@@ -411,8 +457,11 @@ void D3D12ResourceHeap::EmplaceD3DUAVResource(
void D3D12ResourceHeap::UpdateBarriers(std::uint32_t descriptorSet)
{
- auto barrierHeapStart = &barriers_[descriptorSet * barrierStride_];
- auto barriers = reinterpret_cast(barrierHeapStart + sizeof(UINT));
+ if (!HasUAVBarriers())
+ return;
+
+ char* barrierHeapStart = &barriers_[descriptorSet * barrierStride_];
+ auto* barriers = reinterpret_cast(barrierHeapStart + sizeof(UINT));
/* Write new barriers for entire descriptor set */
UINT numBarriers = 0;
diff --git a/sources/Renderer/Direct3D12/RenderState/D3D12ResourceHeap.h b/sources/Renderer/Direct3D12/RenderState/D3D12ResourceHeap.h
index de97729505..3e05aec8b6 100644
--- a/sources/Renderer/Direct3D12/RenderState/D3D12ResourceHeap.h
+++ b/sources/Renderer/Direct3D12/RenderState/D3D12ResourceHeap.h
@@ -23,7 +23,9 @@ namespace LLGL
{
+struct D3D12Resource;
struct ResourceHeapDescriptor;
+class D3D12CommandContext;
class D3D12ResourceHeap final : public ResourceHeap
{
@@ -49,8 +51,11 @@ class D3D12ResourceHeap final : public ResourceHeap
const ArrayView& resourceViews
);
+ // Inserts the resource barriers for the specified descritpor set into the command context.
+ void TransitionResources(D3D12CommandContext& context, std::uint32_t descriptorSet);
+
// Inserts the resource barriers for the specified descritpor set into the command list.
- void InsertResourceBarriers(ID3D12GraphicsCommandList* commandList, std::uint32_t descriptorSet);
+ void InsertUAVBarriers(ID3D12GraphicsCommandList* commandList, std::uint32_t descriptorSet);
// Returns the CPU descriptor handle for heap start of the specified descriptor set.
D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandleForHeapStart(D3D12_DESCRIPTOR_HEAP_TYPE heapType, std::uint32_t descriptorSet) const;
@@ -98,7 +103,7 @@ class D3D12ResourceHeap final : public ResourceHeap
void UpdateBarriers(std::uint32_t descriptorSet);
- inline bool HasBarriers() const
+ inline bool HasUAVBarriers() const
{
return (barrierStride_ > 0);
}
@@ -110,9 +115,10 @@ class D3D12ResourceHeap final : public ResourceHeap
UINT descriptorHandleStrides_[2] = {};
UINT descriptorSetStrides_[2] = {};
UINT numDescriptorsPerSet_[2] = {};
- UINT numDescriptorSets_ = 0; // Only used for 'GetNumDescriptorSets'
+ UINT numDescriptorSets_ = 0;
SmallVector descriptorMap_;
+ std::vector resources_;
std::vector uavResourceHeap_; // Heap of UAV resources that require a barrier
UINT uavResourceSetStride_ = 0; // Number of (potential) UAV resources per descriptor set
diff --git a/sources/Renderer/Direct3D12/Texture/D3D12MipGenerator.cpp b/sources/Renderer/Direct3D12/Texture/D3D12MipGenerator.cpp
index ed08af8178..577c83604f 100644
--- a/sources/Renderer/Direct3D12/Texture/D3D12MipGenerator.cpp
+++ b/sources/Renderer/Direct3D12/Texture/D3D12MipGenerator.cpp
@@ -88,18 +88,18 @@ HRESULT D3D12MipGenerator::GenerateMips(
{
case TextureType::Texture1D:
case TextureType::Texture1DArray:
- GenerateMips1D(commandContext, texture.GetResource(), mipDescHeap, texture.GetDXFormat(), subresource);
+ GenerateMips1D(commandContext, texture, mipDescHeap, subresource);
return S_OK;
case TextureType::Texture2D:
case TextureType::TextureCube:
case TextureType::Texture2DArray:
case TextureType::TextureCubeArray:
- GenerateMips2D(commandContext, texture.GetResource(), mipDescHeap, texture.GetDXFormat(), subresource);
+ GenerateMips2D(commandContext, texture, mipDescHeap, subresource);
return S_OK;
case TextureType::Texture3D:
- GenerateMips3D(commandContext, texture.GetResource(), mipDescHeap, texture.GetDXFormat(), subresource);
+ GenerateMips3D(commandContext, texture, mipDescHeap, subresource);
return S_OK;
case TextureType::Texture2DMS:
@@ -225,15 +225,16 @@ void D3D12MipGenerator::CreateResourcesFor3DMips(ID3D12Device* device)
void D3D12MipGenerator::GenerateMips1D(
D3D12CommandContext& commandContext,
- D3D12Resource& resource,
+ D3D12Texture& texture,
ID3D12DescriptorHeap* mipDescHeap,
- DXGI_FORMAT format,
const TextureSubresource& subresource)
{
- const bool isFormatSRGB = DXTypes::IsDXGIFormatSRGB(format);
+ const bool isFormatSRGB = DXTypes::IsDXGIFormatSRGB(texture.GetDXFormat());
ID3D12GraphicsCommandList* commandList = commandContext.GetCommandList();
+ D3D12Resource& resource = texture.GetResource();
+ const D3D12_RESOURCE_STATES oldResourceState = texture.GetResource().currentState;
commandContext.TransitionResource(resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true);
/* Set root signature and descriptor heap */
@@ -248,7 +249,7 @@ void D3D12MipGenerator::GenerateMips1D(
commandList->SetComputeRootDescriptorTable(1, gpuDescHandle);
gpuDescHandle.ptr += descHandleSize_;
- D3D12_RESOURCE_DESC resourceDesc = resource.native->GetDesc();
+ D3D12_RESOURCE_DESC resourceDesc = texture.GetNative()->GetDesc();
const std::uint32_t mipLevelEnd = subresource.baseMipLevel + subresource.numMipLevels - 1;
@@ -285,25 +286,26 @@ void D3D12MipGenerator::GenerateMips1D(
);
/* Insert UAV barrier and move to next four MIP-maps */
- commandContext.InsertUAVBarrier(resource, true);
+ commandContext.UAVBarrier(texture.GetNative(), true);
mipLevel += numMips;
}
- commandContext.TransitionResource(resource, resource.usageState, true);
+ commandContext.TransitionResource(resource, oldResourceState, true);
}
void D3D12MipGenerator::GenerateMips2D(
D3D12CommandContext& commandContext,
- D3D12Resource& resource,
+ D3D12Texture& texture,
ID3D12DescriptorHeap* mipDescHeap,
- DXGI_FORMAT format,
const TextureSubresource& subresource)
{
- const bool isFormatSRGB = DXTypes::IsDXGIFormatSRGB(format);
+ const bool isFormatSRGB = DXTypes::IsDXGIFormatSRGB(texture.GetDXFormat());
ID3D12GraphicsCommandList* commandList = commandContext.GetCommandList();
+ D3D12Resource& resource = texture.GetResource();
+ const D3D12_RESOURCE_STATES oldResourceState = resource.currentState;
commandContext.TransitionResource(resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true);
/* Set root signature and descriptor heap */
@@ -318,7 +320,7 @@ void D3D12MipGenerator::GenerateMips2D(
commandList->SetComputeRootDescriptorTable(1, gpuDescHandle);
gpuDescHandle.ptr += descHandleSize_;
- D3D12_RESOURCE_DESC resourceDesc = resource.native->GetDesc();
+ D3D12_RESOURCE_DESC resourceDesc = texture.GetNative()->GetDesc();
const std::uint32_t mipLevelEnd = subresource.baseMipLevel + subresource.numMipLevels - 1;
@@ -358,25 +360,26 @@ void D3D12MipGenerator::GenerateMips2D(
);
/* Insert UAV barrier and move to next four MIP-maps */
- commandContext.InsertUAVBarrier(resource, true);
+ commandContext.UAVBarrier(texture.GetNative(), true);
mipLevel += numMips;
}
- commandContext.TransitionResource(resource, resource.usageState, true);
+ commandContext.TransitionResource(resource, oldResourceState, true);
}
void D3D12MipGenerator::GenerateMips3D(
D3D12CommandContext& commandContext,
- D3D12Resource& resource,
+ D3D12Texture& texture,
ID3D12DescriptorHeap* mipDescHeap,
- DXGI_FORMAT format,
const TextureSubresource& subresource)
{
- const bool isFormatSRGB = DXTypes::IsDXGIFormatSRGB(format);
+ const bool isFormatSRGB = DXTypes::IsDXGIFormatSRGB(texture.GetDXFormat());
ID3D12GraphicsCommandList* commandList = commandContext.GetCommandList();
+ D3D12Resource& resource = texture.GetResource();
+ const D3D12_RESOURCE_STATES oldResourceState = texture.GetResource().currentState;
commandContext.TransitionResource(resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, true);
/* Set root signature and descriptor heap */
@@ -391,7 +394,7 @@ void D3D12MipGenerator::GenerateMips3D(
commandList->SetComputeRootDescriptorTable(1, gpuDescHandle);
gpuDescHandle.ptr += descHandleSize_;
- D3D12_RESOURCE_DESC resourceDesc = resource.native->GetDesc();
+ D3D12_RESOURCE_DESC resourceDesc = texture.GetNative()->GetDesc();
const std::uint32_t mipLevelEnd = subresource.baseMipLevel + subresource.numMipLevels - 1;
@@ -433,12 +436,12 @@ void D3D12MipGenerator::GenerateMips3D(
);
/* Insert UAV barrier and move to next four MIP-maps */
- commandContext.InsertUAVBarrier(resource, true);
+ commandContext.UAVBarrier(texture.GetNative(), true);
mipLevel += numMips;
}
- commandContext.TransitionResource(resource, resource.usageState, true);
+ commandContext.TransitionResource(resource, oldResourceState, true);
}
diff --git a/sources/Renderer/Direct3D12/Texture/D3D12MipGenerator.h b/sources/Renderer/Direct3D12/Texture/D3D12MipGenerator.h
index 7ebdbe4121..0958c7060b 100644
--- a/sources/Renderer/Direct3D12/Texture/D3D12MipGenerator.h
+++ b/sources/Renderer/Direct3D12/Texture/D3D12MipGenerator.h
@@ -68,25 +68,22 @@ class D3D12MipGenerator
void GenerateMips1D(
D3D12CommandContext& commandContext,
- D3D12Resource& resource,
+ D3D12Texture& texture,
ID3D12DescriptorHeap* mipDescHeap,
- DXGI_FORMAT format,
const TextureSubresource& subresource
);
void GenerateMips2D(
D3D12CommandContext& commandContext,
- D3D12Resource& resource,
+ D3D12Texture& texture,
ID3D12DescriptorHeap* mipDescHeap,
- DXGI_FORMAT format,
const TextureSubresource& subresource
);
void GenerateMips3D(
D3D12CommandContext& commandContext,
- D3D12Resource& resource,
+ D3D12Texture& texture,
ID3D12DescriptorHeap* mipDescHeap,
- DXGI_FORMAT format,
const TextureSubresource& subresource
);
diff --git a/sources/Renderer/Direct3D12/Texture/D3D12Texture.cpp b/sources/Renderer/Direct3D12/Texture/D3D12Texture.cpp
index 2c43c43fc0..f2149b7573 100644
--- a/sources/Renderer/Direct3D12/Texture/D3D12Texture.cpp
+++ b/sources/Renderer/Direct3D12/Texture/D3D12Texture.cpp
@@ -320,7 +320,7 @@ void D3D12Texture::UpdateSubresourceRegion(
const D3D12_BOX srcBox = CalcRegion(Offset3D{}, srcExtent);
/* Transition texture resource for shader access */
- context.GetCommandContext().TransitionResource(intermediateTexture, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST);
+ context.GetCommandContext().TransitionBarrier(intermediateTexture, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_DEST);
context.GetCommandContext().TransitionResource(GetResource(), D3D12_RESOURCE_STATE_COPY_DEST, true);
{
for_range(arrayLayer, subresource.numArrayLayers)
@@ -409,6 +409,7 @@ void D3D12Texture::CreateSubresourceCopyAsReadbackBuffer(
const D3D12_BOX srcBox = CalcRegion(offset, extent);
+ const D3D12_RESOURCE_STATES oldResourceState = resource_.currentState;
context.GetCommandContext().TransitionResource(resource_, D3D12_RESOURCE_STATE_COPY_SOURCE, true);
{
for_range(arrayLayer, region.subresource.numArrayLayers)
@@ -427,7 +428,7 @@ void D3D12Texture::CreateSubresourceCopyAsReadbackBuffer(
dstBufferFootprint.Offset += outLayerStride;
}
}
- context.GetCommandContext().TransitionResource(resource_, resource_.usageState, true);
+ context.GetCommandContext().TransitionResource(resource_, oldResourceState, true);
}
void D3D12Texture::CreateShaderResourceView(ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE cpuDescHandle)
diff --git a/tests/Testbed/UnitTests/TestCommandBufferSubmit.cpp b/tests/Testbed/UnitTests/TestCommandBufferSubmit.cpp
index c324ffb318..612e1eb37e 100644
--- a/tests/Testbed/UnitTests/TestCommandBufferSubmit.cpp
+++ b/tests/Testbed/UnitTests/TestCommandBufferSubmit.cpp
@@ -36,6 +36,7 @@ DEF_TEST( CommandBufferSubmit )
}
TextureDescriptor texDesc;
{
+ texDesc.debugName = "CommandBufferSubmit.Framebuffer";
texDesc.bindFlags = BindFlags::Sampled | BindFlags::CopyDst;
texDesc.format = swapChain->GetColorFormat();
}
diff --git a/tests/Testbed/UnitTests/TestResourceBinding.cpp b/tests/Testbed/UnitTests/TestResourceBinding.cpp
index 2fa22553ca..61a861b326 100644
--- a/tests/Testbed/UnitTests/TestResourceBinding.cpp
+++ b/tests/Testbed/UnitTests/TestResourceBinding.cpp
@@ -592,17 +592,14 @@ DEF_TEST( ResourceBinding )
cmdBuf.End();
};
- // Skip every other frame on fast test
- if (opt.fastTest && (frame % 2 == 0))
- return TestResult::ContinueSkipFrame;
-
// Encode dispatch and render commands to calculate values in buffer/texture
ExpectedResults expectedResults = {};
EncodeCommandBuffer(*cmdBuffer, expectedResults);
- // Evaluate readback result
- constexpr unsigned numFrames = 10;
+ // Run this test many times in full test mode to ensure resource transitioning works, but only use a few iterations in fast mode
+ const unsigned numFrames = (opt.fastTest ? 10 : 1000);
+ // Evaluate readback result
TestResult intermediateResult = TestResult::Passed;
for_range(i, 4)