diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp index dad2fd6570..492a52d628 100644 --- a/src/dawn_native/d3d12/BufferD3D12.cpp +++ b/src/dawn_native/d3d12/BufferD3D12.cpp @@ -111,6 +111,32 @@ namespace dawn_native { namespace d3d12 { DestroyInternal(); } + bool Buffer::CreateD3D12ResourceBarrierIfNeeded(D3D12_RESOURCE_BARRIER* barrier, + dawn::BufferUsageBit newUsage) const { + // Resources in upload and readback heaps must be kept in the COPY_SOURCE/DEST state + if (mFixedResourceState) { + ASSERT(mLastUsage == newUsage); + return false; + } + + // We can skip transitions to already current usages. + // TODO(cwallez@chromium.org): Need some form of UAV barriers at some point. + if ((mLastUsage & newUsage) == newUsage) { + return false; + } + + D3D12_RESOURCE_STATES lastState = D3D12BufferUsage(mLastUsage); + D3D12_RESOURCE_STATES newState = D3D12BufferUsage(newUsage); + barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier->Transition.pResource = mResource.Get(); + barrier->Transition.StateBefore = lastState; + barrier->Transition.StateAfter = newState; + barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + + return true; + } + uint32_t Buffer::GetD3D12Size() const { // TODO(enga@google.com): TODO investigate if this needs to be a constraint at the API level return Align(GetSize(), 256); @@ -120,33 +146,17 @@ namespace dawn_native { namespace d3d12 { return mResource; } + void Buffer::SetUsage(dawn::BufferUsageBit newUsage) { + mLastUsage = newUsage; + } + void Buffer::TransitionUsageNow(ComPtr commandList, dawn::BufferUsageBit usage) { - // Resources in upload and readback heaps must be kept in the COPY_SOURCE/DEST state - if (mFixedResourceState) { - ASSERT(usage == mLastUsage); - return; - } - - // We can skip transitions to already current usages. - // TODO(cwallez@chromium.org): Need some form of UAV barriers at some point. - bool lastIncludesTarget = (mLastUsage & usage) == usage; - if (lastIncludesTarget) { - return; - } - - D3D12_RESOURCE_STATES lastState = D3D12BufferUsage(mLastUsage); - D3D12_RESOURCE_STATES newState = D3D12BufferUsage(usage); - D3D12_RESOURCE_BARRIER barrier; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = mResource.Get(); - barrier.Transition.StateBefore = lastState; - barrier.Transition.StateAfter = newState; - barrier.Transition.Subresource = 0; - commandList->ResourceBarrier(1, &barrier); + if (CreateD3D12ResourceBarrierIfNeeded(&barrier, usage)) { + commandList->ResourceBarrier(1, &barrier); + } mLastUsage = usage; } diff --git a/src/dawn_native/d3d12/BufferD3D12.h b/src/dawn_native/d3d12/BufferD3D12.h index 4926396bfb..86954a748a 100644 --- a/src/dawn_native/d3d12/BufferD3D12.h +++ b/src/dawn_native/d3d12/BufferD3D12.h @@ -29,11 +29,13 @@ namespace dawn_native { namespace d3d12 { Buffer(Device* device, const BufferDescriptor* descriptor); ~Buffer(); + bool CreateD3D12ResourceBarrierIfNeeded(D3D12_RESOURCE_BARRIER* barrier, + dawn::BufferUsageBit newUsage) const; uint32_t GetD3D12Size() const; ComPtr GetD3D12Resource(); D3D12_GPU_VIRTUAL_ADDRESS GetVA() const; void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite); - + void SetUsage(dawn::BufferUsageBit newUsage); void TransitionUsageNow(ComPtr commandList, dawn::BufferUsageBit usage); diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 6b9f8e631c..eed39632a0 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -429,13 +429,28 @@ namespace dawn_native { namespace d3d12 { // Records the necessary barriers for the resource usage pre-computed by the frontend auto TransitionForPass = [](ComPtr commandList, const PassResourceUsage& usages) { + std::vector barriers; + for (size_t i = 0; i < usages.buffers.size(); ++i) { - Buffer* buffer = ToBackend(usages.buffers[i]); - buffer->TransitionUsageNow(commandList, usages.bufferUsages[i]); + D3D12_RESOURCE_BARRIER barrier; + if (ToBackend(usages.buffers[i]) + ->CreateD3D12ResourceBarrierIfNeeded(&barrier, usages.bufferUsages[i])) { + barriers.push_back(barrier); + ToBackend(usages.buffers[i])->SetUsage(usages.bufferUsages[i]); + } } + for (size_t i = 0; i < usages.textures.size(); ++i) { - Texture* texture = ToBackend(usages.textures[i]); - texture->TransitionUsageNow(commandList, usages.textureUsages[i]); + D3D12_RESOURCE_BARRIER barrier; + if (ToBackend(usages.textures[i]) + ->CreateD3D12ResourceBarrierIfNeeded(&barrier, usages.textureUsages[i])) { + barriers.push_back(barrier); + ToBackend(usages.textures[i])->SetUsage(usages.textureUsages[i]); + } + } + + if (barriers.size()) { + commandList->ResourceBarrier(barriers.size(), barriers.data()); } }; diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index 795a71269e..f686ec7b17 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -172,6 +172,30 @@ namespace dawn_native { namespace d3d12 { DestroyInternal(); } + bool Texture::CreateD3D12ResourceBarrierIfNeeded(D3D12_RESOURCE_BARRIER* barrier, + dawn::TextureUsageBit newUsage) const { + return CreateD3D12ResourceBarrierIfNeeded(barrier, + D3D12TextureUsage(newUsage, GetFormat())); + } + + bool Texture::CreateD3D12ResourceBarrierIfNeeded(D3D12_RESOURCE_BARRIER* barrier, + D3D12_RESOURCE_STATES newState) const { + // Avoid transitioning the texture when it isn't needed. + // TODO(cwallez@chromium.org): Need some form of UAV barriers at some point. + if (mLastState == newState) { + return false; + } + + barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier->Transition.pResource = mResourcePtr; + barrier->Transition.StateBefore = mLastState; + barrier->Transition.StateAfter = newState; + barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + + return true; + } + void Texture::DestroyImpl() { // If we own the resource, release it. ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource); @@ -195,6 +219,10 @@ namespace dawn_native { namespace d3d12 { } } + void Texture::SetUsage(dawn::TextureUsageBit newUsage) { + mLastState = D3D12TextureUsage(newUsage, GetFormat()); + } + void Texture::TransitionUsageNow(ComPtr commandList, dawn::TextureUsageBit usage) { TransitionUsageNow(commandList, D3D12TextureUsage(usage, GetFormat())); @@ -202,21 +230,10 @@ namespace dawn_native { namespace d3d12 { void Texture::TransitionUsageNow(ComPtr commandList, D3D12_RESOURCE_STATES newState) { - // Avoid transitioning the texture when it isn't needed. - // TODO(cwallez@chromium.org): Need some form of UAV barriers at some point. - if (mLastState == newState) { - return; - } - D3D12_RESOURCE_BARRIER barrier; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = mResourcePtr; - barrier.Transition.StateBefore = mLastState; - barrier.Transition.StateAfter = newState; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - - commandList->ResourceBarrier(1, &barrier); + if (CreateD3D12ResourceBarrierIfNeeded(&barrier, newState)) { + commandList->ResourceBarrier(1, &barrier); + } mLastState = newState; } diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h index 3aea5ad621..455a42e1e9 100644 --- a/src/dawn_native/d3d12/TextureD3D12.h +++ b/src/dawn_native/d3d12/TextureD3D12.h @@ -31,9 +31,13 @@ namespace dawn_native { namespace d3d12 { Texture(Device* device, const TextureDescriptor* descriptor, ID3D12Resource* nativeTexture); ~Texture(); + bool CreateD3D12ResourceBarrierIfNeeded(D3D12_RESOURCE_BARRIER* barrier, + dawn::TextureUsageBit newUsage) const; + bool CreateD3D12ResourceBarrierIfNeeded(D3D12_RESOURCE_BARRIER* barrier, + D3D12_RESOURCE_STATES newState) const; DXGI_FORMAT GetD3D12Format() const; ID3D12Resource* GetD3D12Resource() const; - + void SetUsage(dawn::TextureUsageBit newUsage); void TransitionUsageNow(ComPtr commandList, dawn::TextureUsageBit usage); void TransitionUsageNow(ComPtr commandList,