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)