Copy from a zeroed-out buffer to clear in D3D12
When setting a buffer to zero now uses copies from a previously allocated, zeroed out buffer to perform the clear rather than making new allocations every time. Bug: dawn:1160 Change-Id: I0c8e7e56b2afcb5961723e352d8bbdf276f4557c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/70760 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Brandon Jones <bajones@chromium.org>
This commit is contained in:
parent
2294cf4480
commit
e7efad0325
|
@ -469,6 +469,8 @@ namespace dawn_native { namespace d3d12 {
|
||||||
"D3D12 map at clear buffer"));
|
"D3D12 map at clear buffer"));
|
||||||
memset(mMappedData, clearValue, size);
|
memset(mMappedData, clearValue, size);
|
||||||
UnmapImpl();
|
UnmapImpl();
|
||||||
|
} else if (clearValue == 0u) {
|
||||||
|
DAWN_TRY(device->ClearBufferToZero(commandContext, this, offset, size));
|
||||||
} else {
|
} else {
|
||||||
// TODO(crbug.com/dawn/852): use ClearUnorderedAccessView*() when the buffer usage
|
// TODO(crbug.com/dawn/852): use ClearUnorderedAccessView*() when the buffer usage
|
||||||
// includes STORAGE.
|
// includes STORAGE.
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "dawn_native/d3d12/DeviceD3D12.h"
|
#include "dawn_native/d3d12/DeviceD3D12.h"
|
||||||
|
|
||||||
#include "common/GPUInfo.h"
|
#include "common/GPUInfo.h"
|
||||||
|
#include "dawn_native/DynamicUploader.h"
|
||||||
#include "dawn_native/Instance.h"
|
#include "dawn_native/Instance.h"
|
||||||
#include "dawn_native/d3d12/AdapterD3D12.h"
|
#include "dawn_native/d3d12/AdapterD3D12.h"
|
||||||
#include "dawn_native/d3d12/BackendD3D12.h"
|
#include "dawn_native/d3d12/BackendD3D12.h"
|
||||||
|
@ -49,6 +50,9 @@ namespace dawn_native { namespace d3d12 {
|
||||||
static constexpr uint16_t kShaderVisibleDescriptorHeapSize = 1024;
|
static constexpr uint16_t kShaderVisibleDescriptorHeapSize = 1024;
|
||||||
static constexpr uint8_t kAttachmentDescriptorHeapSize = 64;
|
static constexpr uint8_t kAttachmentDescriptorHeapSize = 64;
|
||||||
|
|
||||||
|
// Value may change in the future to better accomodate large clears.
|
||||||
|
static constexpr uint64_t kZeroBufferSize = 1024 * 1024 * 4; // 4 Mb
|
||||||
|
|
||||||
static constexpr uint64_t kMaxDebugMessagesToPrint = 5;
|
static constexpr uint64_t kMaxDebugMessagesToPrint = 5;
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -166,6 +170,9 @@ namespace dawn_native { namespace d3d12 {
|
||||||
// The environment can only use DXC when it's available. Override the decision if it is not
|
// The environment can only use DXC when it's available. Override the decision if it is not
|
||||||
// applicable.
|
// applicable.
|
||||||
DAWN_TRY(ApplyUseDxcToggle());
|
DAWN_TRY(ApplyUseDxcToggle());
|
||||||
|
|
||||||
|
DAWN_TRY(CreateZeroBuffer());
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,6 +258,59 @@ namespace dawn_native { namespace d3d12 {
|
||||||
return &mPendingCommands;
|
return &mPendingCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeError Device::CreateZeroBuffer() {
|
||||||
|
BufferDescriptor zeroBufferDescriptor;
|
||||||
|
zeroBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||||
|
zeroBufferDescriptor.size = kZeroBufferSize;
|
||||||
|
zeroBufferDescriptor.label = "ZeroBuffer_Internal";
|
||||||
|
DAWN_TRY_ASSIGN(mZeroBuffer, Buffer::Create(this, &zeroBufferDescriptor));
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
MaybeError Device::ClearBufferToZero(CommandRecordingContext* commandContext,
|
||||||
|
BufferBase* destination,
|
||||||
|
uint64_t offset,
|
||||||
|
uint64_t size) {
|
||||||
|
// TODO(crbug.com/dawn/852): It would be ideal to clear the buffer in CreateZeroBuffer, but
|
||||||
|
// the allocation of the staging buffer causes various end2end tests that monitor heap usage
|
||||||
|
// to fail if it's done during device creation. Perhaps ClearUnorderedAccessView*() can be
|
||||||
|
// used to avoid that.
|
||||||
|
if (!mZeroBuffer->IsDataInitialized()) {
|
||||||
|
DynamicUploader* uploader = GetDynamicUploader();
|
||||||
|
UploadHandle uploadHandle;
|
||||||
|
DAWN_TRY_ASSIGN(uploadHandle,
|
||||||
|
uploader->Allocate(kZeroBufferSize, GetPendingCommandSerial(),
|
||||||
|
kCopyBufferToBufferOffsetAlignment));
|
||||||
|
|
||||||
|
memset(uploadHandle.mappedBuffer, 0u, kZeroBufferSize);
|
||||||
|
|
||||||
|
CopyFromStagingToBufferImpl(commandContext, uploadHandle.stagingBuffer,
|
||||||
|
uploadHandle.startOffset, mZeroBuffer.Get(), 0,
|
||||||
|
kZeroBufferSize);
|
||||||
|
|
||||||
|
mZeroBuffer->SetIsDataInitialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer* dstBuffer = ToBackend(destination);
|
||||||
|
|
||||||
|
// Necessary to ensure residency of the zero buffer.
|
||||||
|
mZeroBuffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopySrc);
|
||||||
|
dstBuffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
|
||||||
|
|
||||||
|
while (size > 0) {
|
||||||
|
uint64_t copySize = std::min(kZeroBufferSize, size);
|
||||||
|
commandContext->GetCommandList()->CopyBufferRegion(
|
||||||
|
dstBuffer->GetD3D12Resource(), offset, mZeroBuffer->GetD3D12Resource(), 0,
|
||||||
|
copySize);
|
||||||
|
|
||||||
|
offset += copySize;
|
||||||
|
size -= copySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
MaybeError Device::TickImpl() {
|
MaybeError Device::TickImpl() {
|
||||||
// Perform cleanup operations to free unused objects
|
// Perform cleanup operations to free unused objects
|
||||||
ExecutionSerial completedSerial = GetCompletedCommandSerial();
|
ExecutionSerial completedSerial = GetCompletedCommandSerial();
|
||||||
|
|
|
@ -72,6 +72,11 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
ResultOrError<CommandRecordingContext*> GetPendingCommandContext();
|
ResultOrError<CommandRecordingContext*> GetPendingCommandContext();
|
||||||
|
|
||||||
|
MaybeError ClearBufferToZero(CommandRecordingContext* commandContext,
|
||||||
|
BufferBase* destination,
|
||||||
|
uint64_t destinationOffset,
|
||||||
|
uint64_t size);
|
||||||
|
|
||||||
const D3D12DeviceInfo& GetDeviceInfo() const;
|
const D3D12DeviceInfo& GetDeviceInfo() const;
|
||||||
|
|
||||||
MaybeError NextSerial();
|
MaybeError NextSerial();
|
||||||
|
@ -191,6 +196,8 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
MaybeError ApplyUseDxcToggle();
|
MaybeError ApplyUseDxcToggle();
|
||||||
|
|
||||||
|
MaybeError CreateZeroBuffer();
|
||||||
|
|
||||||
ComPtr<ID3D12Fence> mFence;
|
ComPtr<ID3D12Fence> mFence;
|
||||||
HANDLE mFenceEvent = nullptr;
|
HANDLE mFenceEvent = nullptr;
|
||||||
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
||||||
|
@ -246,6 +253,10 @@ namespace dawn_native { namespace d3d12 {
|
||||||
// release is called.
|
// release is called.
|
||||||
std::unique_ptr<SamplerHeapCache> mSamplerHeapCache;
|
std::unique_ptr<SamplerHeapCache> mSamplerHeapCache;
|
||||||
|
|
||||||
|
// A buffer filled with zeros that is used to copy into other buffers when they need to be
|
||||||
|
// cleared.
|
||||||
|
Ref<Buffer> mZeroBuffer;
|
||||||
|
|
||||||
// The number of nanoseconds required for a timestamp query to be incremented by 1
|
// The number of nanoseconds required for a timestamp query to be incremented by 1
|
||||||
float mTimestampPeriod = 1.0f;
|
float mTimestampPeriod = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
|
@ -351,7 +351,6 @@ namespace dawn_native { namespace d3d12 {
|
||||||
// Places an artifical cap on Dawn's budget so we can test in a predictable manner. If used,
|
// Places an artifical cap on Dawn's budget so we can test in a predictable manner. If used,
|
||||||
// this function must be called before any resources have been created.
|
// this function must be called before any resources have been created.
|
||||||
void ResidencyManager::RestrictBudgetForTesting(uint64_t artificialBudgetCap) {
|
void ResidencyManager::RestrictBudgetForTesting(uint64_t artificialBudgetCap) {
|
||||||
ASSERT(mVideoMemoryInfo.local.lruCache.empty());
|
|
||||||
ASSERT(mVideoMemoryInfo.nonLocal.lruCache.empty());
|
ASSERT(mVideoMemoryInfo.nonLocal.lruCache.empty());
|
||||||
ASSERT(!mRestrictBudgetForTesting);
|
ASSERT(!mRestrictBudgetForTesting);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue