Residency 3: Track Resource Heap Usages

Track what heaps are required to be resident upon command list
submission.

Bug: dawn:193
Change-Id: Icefe5aed047140f401d51018937c5364b3ed7c4f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16382
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Brandon Jones 2020-03-12 13:23:22 +00:00 committed by Commit Bot service account
parent 421684f943
commit 0338b7ae19
13 changed files with 168 additions and 72 deletions

View File

@ -20,6 +20,7 @@
#include "dawn_native/d3d12/CommandRecordingContext.h" #include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/HeapD3D12.h"
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
@ -127,6 +128,29 @@ namespace dawn_native { namespace d3d12 {
return mResourceAllocation.GetD3D12Resource(); return mResourceAllocation.GetD3D12Resource();
} }
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors.
bool Buffer::TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
wgpu::BufferUsage newUsage) {
// Track the underlying heap to ensure residency.
Heap* heap = ToBackend(mResourceAllocation.GetResourceHeap());
commandContext->TrackHeapUsage(heap, GetDevice()->GetPendingCommandSerial());
// Return the resource barrier.
return TransitionUsageAndGetResourceBarrier(commandContext, barrier, newUsage);
}
void Buffer::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::BufferUsage newUsage) {
D3D12_RESOURCE_BARRIER barrier;
if (TrackUsageAndGetResourceBarrier(commandContext, &barrier, newUsage)) {
commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
}
}
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a // When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can // ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors. // cause subsequent errors.
@ -202,15 +226,6 @@ namespace dawn_native { namespace d3d12 {
return true; return true;
} }
void Buffer::TransitionUsageNow(CommandRecordingContext* commandContext,
wgpu::BufferUsage usage) {
D3D12_RESOURCE_BARRIER barrier;
if (TransitionUsageAndGetResourceBarrier(commandContext, &barrier, usage)) {
commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
}
}
D3D12_GPU_VIRTUAL_ADDRESS Buffer::GetVA() const { D3D12_GPU_VIRTUAL_ADDRESS Buffer::GetVA() const {
return mResourceAllocation.GetGPUPointer(); return mResourceAllocation.GetGPUPointer();
} }

View File

@ -36,10 +36,12 @@ namespace dawn_native { namespace d3d12 {
ComPtr<ID3D12Resource> GetD3D12Resource() const; ComPtr<ID3D12Resource> GetD3D12Resource() const;
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const; D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite); void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite);
bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
bool TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier, D3D12_RESOURCE_BARRIER* barrier,
wgpu::BufferUsage newUsage); wgpu::BufferUsage newUsage);
void TransitionUsageNow(CommandRecordingContext* commandContext, wgpu::BufferUsage usage); void TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::BufferUsage newUsage);
private: private:
// Dawn API // Dawn API
@ -51,6 +53,10 @@ namespace dawn_native { namespace d3d12 {
bool IsMapWritable() const override; bool IsMapWritable() const override;
virtual MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override; virtual MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override;
bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
wgpu::BufferUsage newUsage);
ResourceHeapAllocation mResourceAllocation; ResourceHeapAllocation mResourceAllocation;
bool mFixedResourceState = false; bool mFixedResourceState = false;
wgpu::BufferUsage mLastUsage = wgpu::BufferUsage::None; wgpu::BufferUsage mLastUsage = wgpu::BufferUsage::None;

View File

@ -131,7 +131,7 @@ namespace dawn_native { namespace d3d12 {
switch (bindingType) { switch (bindingType) {
case wgpu::BindingType::StorageBuffer: case wgpu::BindingType::StorageBuffer:
ToBackend(mBuffers[index][binding]) ToBackend(mBuffers[index][binding])
->TransitionUsageNow(commandContext, ->TrackUsageAndTransitionNow(commandContext,
wgpu::BufferUsage::Storage); wgpu::BufferUsage::Storage);
break; break;
@ -431,9 +431,9 @@ namespace dawn_native { namespace d3d12 {
Texture* resolveTexture = ToBackend(resolveTarget->GetTexture()); Texture* resolveTexture = ToBackend(resolveTarget->GetTexture());
// Transition the usages of the color attachment and resolve target. // Transition the usages of the color attachment and resolve target.
colorTexture->TransitionUsageNow(commandContext, colorTexture->TrackUsageAndTransitionNow(commandContext,
D3D12_RESOURCE_STATE_RESOLVE_SOURCE); D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
resolveTexture->TransitionUsageNow(commandContext, resolveTexture->TrackUsageAndTransitionNow(commandContext,
D3D12_RESOURCE_STATE_RESOLVE_DEST); D3D12_RESOURCE_STATE_RESOLVE_DEST);
// Do MSAA resolve with ResolveSubResource(). // Do MSAA resolve with ResolveSubResource().
@ -469,7 +469,7 @@ namespace dawn_native { namespace d3d12 {
bindingTracker.SetID3D12DescriptorHeaps(commandList); bindingTracker.SetID3D12DescriptorHeaps(commandList);
// Records the necessary barriers for the resource usage pre-computed by the frontend // Records the necessary barriers for the resource usage pre-computed by the frontend
auto TransitionForPass = [](CommandRecordingContext* commandContext, auto PrepareResourcesForSubmission = [](CommandRecordingContext* commandContext,
const PassResourceUsage& usages) -> bool { const PassResourceUsage& usages) -> bool {
std::vector<D3D12_RESOURCE_BARRIER> barriers; std::vector<D3D12_RESOURCE_BARRIER> barriers;
@ -480,7 +480,7 @@ namespace dawn_native { namespace d3d12 {
for (size_t i = 0; i < usages.buffers.size(); ++i) { for (size_t i = 0; i < usages.buffers.size(); ++i) {
D3D12_RESOURCE_BARRIER barrier; D3D12_RESOURCE_BARRIER barrier;
if (ToBackend(usages.buffers[i]) if (ToBackend(usages.buffers[i])
->TransitionUsageAndGetResourceBarrier(commandContext, &barrier, ->TrackUsageAndGetResourceBarrier(commandContext, &barrier,
usages.bufferUsages[i])) { usages.bufferUsages[i])) {
barriers.push_back(barrier); barriers.push_back(barrier);
} }
@ -504,7 +504,7 @@ namespace dawn_native { namespace d3d12 {
for (size_t i = 0; i < usages.textures.size(); ++i) { for (size_t i = 0; i < usages.textures.size(); ++i) {
D3D12_RESOURCE_BARRIER barrier; D3D12_RESOURCE_BARRIER barrier;
if (ToBackend(usages.textures[i]) if (ToBackend(usages.textures[i])
->TransitionUsageAndGetResourceBarrier(commandContext, &barrier, ->TrackUsageAndGetResourceBarrier(commandContext, &barrier,
usages.textureUsages[i])) { usages.textureUsages[i])) {
barriers.push_back(barrier); barriers.push_back(barrier);
} }
@ -528,7 +528,8 @@ namespace dawn_native { namespace d3d12 {
case Command::BeginComputePass: { case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>(); mCommands.NextCommand<BeginComputePassCmd>();
TransitionForPass(commandContext, passResourceUsages[nextPassNumber]); PrepareResourcesForSubmission(commandContext,
passResourceUsages[nextPassNumber]);
bindingTracker.SetInComputePass(true); bindingTracker.SetInComputePass(true);
DAWN_TRY(RecordComputePass(commandContext, &bindingTracker)); DAWN_TRY(RecordComputePass(commandContext, &bindingTracker));
@ -539,8 +540,8 @@ namespace dawn_native { namespace d3d12 {
BeginRenderPassCmd* beginRenderPassCmd = BeginRenderPassCmd* beginRenderPassCmd =
mCommands.NextCommand<BeginRenderPassCmd>(); mCommands.NextCommand<BeginRenderPassCmd>();
const bool passHasUAV = const bool passHasUAV = PrepareResourcesForSubmission(
TransitionForPass(commandContext, passResourceUsages[nextPassNumber]); commandContext, passResourceUsages[nextPassNumber]);
bindingTracker.SetInComputePass(false); bindingTracker.SetInComputePass(false);
LazyClearRenderPassAttachments(beginRenderPassCmd); LazyClearRenderPassAttachments(beginRenderPassCmd);
@ -555,8 +556,10 @@ namespace dawn_native { namespace d3d12 {
Buffer* srcBuffer = ToBackend(copy->source.Get()); Buffer* srcBuffer = ToBackend(copy->source.Get());
Buffer* dstBuffer = ToBackend(copy->destination.Get()); Buffer* dstBuffer = ToBackend(copy->destination.Get());
srcBuffer->TransitionUsageNow(commandContext, wgpu::BufferUsage::CopySrc); srcBuffer->TrackUsageAndTransitionNow(commandContext,
dstBuffer->TransitionUsageNow(commandContext, wgpu::BufferUsage::CopyDst); wgpu::BufferUsage::CopySrc);
dstBuffer->TrackUsageAndTransitionNow(commandContext,
wgpu::BufferUsage::CopyDst);
commandList->CopyBufferRegion( commandList->CopyBufferRegion(
dstBuffer->GetD3D12Resource().Get(), copy->destinationOffset, dstBuffer->GetD3D12Resource().Get(), copy->destinationOffset,
@ -578,8 +581,9 @@ namespace dawn_native { namespace d3d12 {
copy->destination.arrayLayer, 1); copy->destination.arrayLayer, 1);
} }
buffer->TransitionUsageNow(commandContext, wgpu::BufferUsage::CopySrc); buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopySrc);
texture->TransitionUsageNow(commandContext, wgpu::TextureUsage::CopyDst); texture->TrackUsageAndTransitionNow(commandContext,
wgpu::TextureUsage::CopyDst);
auto copySplit = ComputeTextureCopySplit( auto copySplit = ComputeTextureCopySplit(
copy->destination.origin, copy->copySize, texture->GetFormat(), copy->destination.origin, copy->copySize, texture->GetFormat(),
@ -613,8 +617,9 @@ namespace dawn_native { namespace d3d12 {
texture->EnsureSubresourceContentInitialized( texture->EnsureSubresourceContentInitialized(
commandContext, copy->source.mipLevel, 1, copy->source.arrayLayer, 1); commandContext, copy->source.mipLevel, 1, copy->source.arrayLayer, 1);
texture->TransitionUsageNow(commandContext, wgpu::TextureUsage::CopySrc); texture->TrackUsageAndTransitionNow(commandContext,
buffer->TransitionUsageNow(commandContext, wgpu::BufferUsage::CopyDst); wgpu::TextureUsage::CopySrc);
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
TextureCopySplit copySplit = ComputeTextureCopySplit( TextureCopySplit copySplit = ComputeTextureCopySplit(
copy->source.origin, copy->copySize, texture->GetFormat(), copy->source.origin, copy->copySize, texture->GetFormat(),
@ -660,8 +665,9 @@ namespace dawn_native { namespace d3d12 {
commandContext, copy->destination.mipLevel, 1, commandContext, copy->destination.mipLevel, 1,
copy->destination.arrayLayer, 1); copy->destination.arrayLayer, 1);
} }
source->TransitionUsageNow(commandContext, wgpu::TextureUsage::CopySrc); source->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopySrc);
destination->TransitionUsageNow(commandContext, wgpu::TextureUsage::CopyDst); destination->TrackUsageAndTransitionNow(commandContext,
wgpu::TextureUsage::CopyDst);
if (CanUseCopyResource(source->GetNumMipLevels(), source->GetSize(), if (CanUseCopyResource(source->GetNumMipLevels(), source->GetSize(),
destination->GetSize(), copy->copySize)) { destination->GetSize(), copy->copySize)) {
@ -811,8 +817,8 @@ namespace dawn_native { namespace d3d12 {
Texture* resolveDestinationTexture = Texture* resolveDestinationTexture =
ToBackend(resolveDestinationView->GetTexture()); ToBackend(resolveDestinationView->GetTexture());
resolveDestinationTexture->TransitionUsageNow(commandContext, resolveDestinationTexture->TrackUsageAndTransitionNow(
D3D12_RESOURCE_STATE_RESOLVE_DEST); commandContext, D3D12_RESOURCE_STATE_RESOLVE_DEST);
renderPassBuilder->SetRenderTargetEndingAccessResolve(i, attachmentInfo.storeOp, renderPassBuilder->SetRenderTargetEndingAccessResolve(i, attachmentInfo.storeOp,
view, resolveDestinationView); view, resolveDestinationView);

View File

@ -14,6 +14,7 @@
#include "dawn_native/d3d12/CommandRecordingContext.h" #include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/CommandAllocatorManager.h" #include "dawn_native/d3d12/CommandAllocatorManager.h"
#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/HeapD3D12.h"
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
@ -58,7 +59,7 @@ namespace dawn_native { namespace d3d12 {
// common state right before command list submission. TransitionUsageNow itself ensures // common state right before command list submission. TransitionUsageNow itself ensures
// no unnecessary transitions happen if the resources is already in the common state. // no unnecessary transitions happen if the resources is already in the common state.
for (Texture* texture : mSharedTextures) { for (Texture* texture : mSharedTextures) {
texture->TransitionUsageNow(this, D3D12_RESOURCE_STATE_COMMON); texture->TrackUsageAndTransitionNow(this, D3D12_RESOURCE_STATE_COMMON);
} }
MaybeError error = MaybeError error =
@ -73,10 +74,20 @@ namespace dawn_native { namespace d3d12 {
mIsOpen = false; mIsOpen = false;
mSharedTextures.clear(); mSharedTextures.clear();
mHeapsPendingUsage.clear();
} }
return {}; return {};
} }
void CommandRecordingContext::TrackHeapUsage(Heap* heap, Serial serial) {
// Before tracking the heap, check the last serial it was recorded on to ensure we aren't
// tracking it more than once.
if (heap->GetLastUsage() < serial) {
heap->SetLastUsage(serial);
mHeapsPendingUsage.push_back(heap);
}
}
ID3D12GraphicsCommandList* CommandRecordingContext::GetCommandList() const { ID3D12GraphicsCommandList* CommandRecordingContext::GetCommandList() const {
ASSERT(mD3d12CommandList != nullptr); ASSERT(mD3d12CommandList != nullptr);
ASSERT(IsOpen()); ASSERT(IsOpen());
@ -96,6 +107,7 @@ namespace dawn_native { namespace d3d12 {
mD3d12CommandList4.Reset(); mD3d12CommandList4.Reset();
mIsOpen = false; mIsOpen = false;
mSharedTextures.clear(); mSharedTextures.clear();
mHeapsPendingUsage.clear();
} }
bool CommandRecordingContext::IsOpen() const { bool CommandRecordingContext::IsOpen() const {

View File

@ -37,11 +37,14 @@ namespace dawn_native { namespace d3d12 {
MaybeError ExecuteCommandList(ID3D12CommandQueue* d3d12CommandQueue); MaybeError ExecuteCommandList(ID3D12CommandQueue* d3d12CommandQueue);
void TrackHeapUsage(Heap* heap, Serial serial);
private: private:
ComPtr<ID3D12GraphicsCommandList> mD3d12CommandList; ComPtr<ID3D12GraphicsCommandList> mD3d12CommandList;
ComPtr<ID3D12GraphicsCommandList4> mD3d12CommandList4; ComPtr<ID3D12GraphicsCommandList4> mD3d12CommandList4;
bool mIsOpen = false; bool mIsOpen = false;
std::set<Texture*> mSharedTextures; std::set<Texture*> mSharedTextures;
std::vector<Heap*> mHeapsPendingUsage;
}; };
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -290,12 +290,14 @@ namespace dawn_native { namespace d3d12 {
CommandRecordingContext* commandRecordingContext; CommandRecordingContext* commandRecordingContext;
DAWN_TRY_ASSIGN(commandRecordingContext, GetPendingCommandContext()); DAWN_TRY_ASSIGN(commandRecordingContext, GetPendingCommandContext());
ToBackend(destination) Buffer* dstBuffer = ToBackend(destination);
->TransitionUsageNow(commandRecordingContext, wgpu::BufferUsage::CopyDst); StagingBuffer* srcBuffer = ToBackend(source);
dstBuffer->TrackUsageAndTransitionNow(commandRecordingContext, wgpu::BufferUsage::CopyDst);
srcBuffer->TrackUsage(commandRecordingContext);
commandRecordingContext->GetCommandList()->CopyBufferRegion( commandRecordingContext->GetCommandList()->CopyBufferRegion(
ToBackend(destination)->GetD3D12Resource().Get(), destinationOffset, dstBuffer->GetD3D12Resource().Get(), destinationOffset, srcBuffer->GetResource(),
ToBackend(source)->GetResource(), sourceOffset, size); sourceOffset, size);
return {}; return {};
} }

View File

@ -33,6 +33,14 @@ namespace dawn_native { namespace d3d12 {
return mD3d12Pageable; return mD3d12Pageable;
} }
Serial Heap::GetLastUsage() const {
return mLastUsage;
}
void Heap::SetLastUsage(Serial serial) {
mLastUsage = serial;
}
uint64_t Heap::GetSize() const { uint64_t Heap::GetSize() const {
return mSize; return mSize;
} }

View File

@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_D3D12_HEAPD3D12_H_ #ifndef DAWNNATIVE_D3D12_HEAPD3D12_H_
#define DAWNNATIVE_D3D12_HEAPD3D12_H_ #define DAWNNATIVE_D3D12_HEAPD3D12_H_
#include "common/Serial.h"
#include "dawn_native/ResourceHeap.h" #include "dawn_native/ResourceHeap.h"
#include "dawn_native/d3d12/d3d12_platform.h" #include "dawn_native/d3d12/d3d12_platform.h"
@ -28,10 +29,17 @@ namespace dawn_native { namespace d3d12 {
ComPtr<ID3D12Heap> GetD3D12Heap() const; ComPtr<ID3D12Heap> GetD3D12Heap() const;
ComPtr<ID3D12Pageable> GetD3D12Pageable() const; ComPtr<ID3D12Pageable> GetD3D12Pageable() const;
// We set mLastRecordingSerial to denote the serial this heap was last recorded to be used.
// We must check this serial against the current serial when recording heap usages to ensure
// we do not process residency for this heap multiple times.
Serial GetLastUsage() const;
void SetLastUsage(Serial serial);
uint64_t GetSize() const; uint64_t GetSize() const;
private: private:
ComPtr<ID3D12Pageable> mD3d12Pageable; ComPtr<ID3D12Pageable> mD3d12Pageable;
Serial mLastUsage = 0;
uint64_t mSize = 0; uint64_t mSize = 0;
}; };
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -15,6 +15,7 @@
#include "dawn_native/d3d12/StagingBufferD3D12.h" #include "dawn_native/d3d12/StagingBufferD3D12.h"
#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/HeapD3D12.h"
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
@ -60,4 +61,9 @@ namespace dawn_native { namespace d3d12 {
return mUploadHeap.GetD3D12Resource().Get(); return mUploadHeap.GetD3D12Resource().Get();
} }
void StagingBuffer::TrackUsage(CommandRecordingContext* commandContext) {
// Track the underlying heap to ensure residency.
Heap* heap = ToBackend(mUploadHeap.GetResourceHeap());
commandContext->TrackHeapUsage(heap, mDevice->GetPendingCommandSerial());
}
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -21,6 +21,7 @@
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
class CommandRecordingContext;
class Device; class Device;
class StagingBuffer : public StagingBufferBase { class StagingBuffer : public StagingBufferBase {
@ -32,6 +33,8 @@ namespace dawn_native { namespace d3d12 {
MaybeError Initialize() override; MaybeError Initialize() override;
void TrackUsage(CommandRecordingContext* commandContext);
private: private:
Device* mDevice; Device* mDevice;
ResourceHeapAllocation mUploadHeap; ResourceHeapAllocation mUploadHeap;

View File

@ -55,7 +55,7 @@ namespace dawn_native { namespace d3d12 {
DAWN_TRY_ASSIGN(commandContext, device->GetPendingCommandContext()); DAWN_TRY_ASSIGN(commandContext, device->GetPendingCommandContext());
// Perform the necessary transition for the texture to be presented. // Perform the necessary transition for the texture to be presented.
ToBackend(texture)->TransitionUsageNow(commandContext, mTextureUsage); ToBackend(texture)->TrackUsageAndTransitionNow(commandContext, mTextureUsage);
DAWN_TRY(device->ExecutePendingCommandContext()); DAWN_TRY(device->ExecutePendingCommandContext());

View File

@ -19,9 +19,11 @@
#include "dawn_native/DynamicUploader.h" #include "dawn_native/DynamicUploader.h"
#include "dawn_native/Error.h" #include "dawn_native/Error.h"
#include "dawn_native/d3d12/BufferD3D12.h" #include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DescriptorHeapAllocator.h" #include "dawn_native/d3d12/DescriptorHeapAllocator.h"
#include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/HeapD3D12.h"
#include "dawn_native/d3d12/ResourceAllocatorManagerD3D12.h" #include "dawn_native/d3d12/ResourceAllocatorManagerD3D12.h"
#include "dawn_native/d3d12/StagingBufferD3D12.h" #include "dawn_native/d3d12/StagingBufferD3D12.h"
#include "dawn_native/d3d12/TextureCopySplitter.h" #include "dawn_native/d3d12/TextureCopySplitter.h"
@ -417,13 +419,47 @@ namespace dawn_native { namespace d3d12 {
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a // When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can // ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors. // cause subsequent errors.
bool Texture::TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext, bool Texture::TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier, D3D12_RESOURCE_BARRIER* barrier,
wgpu::TextureUsage newUsage) { wgpu::TextureUsage newUsage) {
return TransitionUsageAndGetResourceBarrier(commandContext, barrier, return TrackUsageAndGetResourceBarrier(commandContext, barrier,
D3D12TextureUsage(newUsage, GetFormat())); D3D12TextureUsage(newUsage, GetFormat()));
} }
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors.
bool Texture::TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState) {
if (mResourceAllocation.GetInfo().mMethod != AllocationMethod::kExternal) {
// Track the underlying heap to ensure residency.
Heap* heap = ToBackend(mResourceAllocation.GetResourceHeap());
commandContext->TrackHeapUsage(heap, GetDevice()->GetPendingCommandSerial());
}
// Return the resource barrier.
return TransitionUsageAndGetResourceBarrier(commandContext, barrier, newState);
}
void Texture::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage) {
D3D12_RESOURCE_BARRIER barrier;
if (TrackUsageAndGetResourceBarrier(commandContext, &barrier, usage)) {
commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
}
}
void Texture::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState) {
D3D12_RESOURCE_BARRIER barrier;
if (TrackUsageAndGetResourceBarrier(commandContext, &barrier, newState)) {
commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
}
}
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a // When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can // ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors. // cause subsequent errors.
@ -502,20 +538,6 @@ namespace dawn_native { namespace d3d12 {
return true; return true;
} }
void Texture::TransitionUsageNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage) {
TransitionUsageNow(commandContext, D3D12TextureUsage(usage, GetFormat()));
}
void Texture::TransitionUsageNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState) {
D3D12_RESOURCE_BARRIER barrier;
if (TransitionUsageAndGetResourceBarrier(commandContext, &barrier, newState)) {
commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
}
}
D3D12_RENDER_TARGET_VIEW_DESC Texture::GetRTVDescriptor(uint32_t baseMipLevel, D3D12_RENDER_TARGET_VIEW_DESC Texture::GetRTVDescriptor(uint32_t baseMipLevel,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
uint32_t layerCount) const { uint32_t layerCount) const {
@ -583,7 +605,7 @@ namespace dawn_native { namespace d3d12 {
if (GetFormat().isRenderable) { if (GetFormat().isRenderable) {
if (GetFormat().HasDepthOrStencil()) { if (GetFormat().HasDepthOrStencil()) {
TransitionUsageNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE); TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE);
DescriptorHeapHandle dsvHeap; DescriptorHeapHandle dsvHeap;
DAWN_TRY_ASSIGN(dsvHeap, descriptorHeapAllocator->AllocateCPUHeap( DAWN_TRY_ASSIGN(dsvHeap, descriptorHeapAllocator->AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1)); D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1));
@ -603,7 +625,7 @@ namespace dawn_native { namespace d3d12 {
commandList->ClearDepthStencilView(dsvHandle, clearFlags, fClearColor, clearColor, commandList->ClearDepthStencilView(dsvHandle, clearFlags, fClearColor, clearColor,
0, nullptr); 0, nullptr);
} else { } else {
TransitionUsageNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET); TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET);
DescriptorHeapHandle rtvHeap; DescriptorHeapHandle rtvHeap;
DAWN_TRY_ASSIGN(rtvHeap, descriptorHeapAllocator->AllocateCPUHeap( DAWN_TRY_ASSIGN(rtvHeap, descriptorHeapAllocator->AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1)); D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1));
@ -637,7 +659,7 @@ namespace dawn_native { namespace d3d12 {
uploader->Allocate(bufferSize, device->GetPendingCommandSerial())); uploader->Allocate(bufferSize, device->GetPendingCommandSerial()));
memset(uploadHandle.mappedBuffer, clearColor, bufferSize); memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
TransitionUsageNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST); TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST);
// compute d3d12 texture copy locations for texture and buffer // compute d3d12 texture copy locations for texture and buffer
Extent3D copySize = {GetSize().width, GetSize().height, 1}; Extent3D copySize = {GetSize().width, GetSize().height, 1};

View File

@ -48,12 +48,6 @@ namespace dawn_native { namespace d3d12 {
DXGI_FORMAT GetD3D12Format() const; DXGI_FORMAT GetD3D12Format() const;
ID3D12Resource* GetD3D12Resource() const; ID3D12Resource* GetD3D12Resource() const;
bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
wgpu::TextureUsage newUsage);
void TransitionUsageNow(CommandRecordingContext* commandContext, wgpu::TextureUsage usage);
void TransitionUsageNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState);
D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor(uint32_t baseMipLevel, D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor(uint32_t baseMipLevel,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
@ -65,6 +59,14 @@ namespace dawn_native { namespace d3d12 {
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
uint32_t layerCount); uint32_t layerCount);
bool TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
wgpu::TextureUsage newUsage);
void TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage);
void TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState);
private: private:
using TextureBase::TextureBase; using TextureBase::TextureBase;
@ -84,6 +86,9 @@ namespace dawn_native { namespace d3d12 {
UINT16 GetDepthOrArraySize(); UINT16 GetDepthOrArraySize();
bool TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState);
bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext, bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier, D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState); D3D12_RESOURCE_STATES newState);