D3D12: Batch Usage Transitions For Render Pass
Instead of looping through usages and calling ResourceBarrier for each transition, we should load all transitions into a single call. This allows the driver to make better optimization decisions. Bug: dawn:163 Change-Id: I4859aa2c71b60a40249df00ad67ab13eb0389cd9 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/7680 Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Brandon Jones <brandon1.jones@intel.com>
This commit is contained in:
parent
2b82eb2902
commit
de1ac9fd7b
|
@ -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<ID3D12GraphicsCommandList> 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;
|
||||
}
|
||||
|
|
|
@ -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<ID3D12Resource> GetD3D12Resource();
|
||||
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
|
||||
void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite);
|
||||
|
||||
void SetUsage(dawn::BufferUsageBit newUsage);
|
||||
void TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList,
|
||||
dawn::BufferUsageBit usage);
|
||||
|
||||
|
|
|
@ -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<ID3D12GraphicsCommandList> commandList,
|
||||
const PassResourceUsage& usages) {
|
||||
std::vector<D3D12_RESOURCE_BARRIER> 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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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<ID3D12GraphicsCommandList> commandList,
|
||||
dawn::TextureUsageBit usage) {
|
||||
TransitionUsageNow(commandList, D3D12TextureUsage(usage, GetFormat()));
|
||||
|
@ -202,21 +230,10 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
void Texture::TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> 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;
|
||||
}
|
||||
|
|
|
@ -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<ID3D12GraphicsCommandList> commandList,
|
||||
dawn::TextureUsageBit usage);
|
||||
void TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList,
|
||||
|
|
Loading…
Reference in New Issue