Fixes buffer unmapping issue in D3D12

- Ensures that the D3D12 buffer destruction implementation no longer handles unmapping as that is now handled in the frontend.
- Moves around when the frontend buffer state is set to MappedAtCreation so that it only happens when the staging buffer (when necessary) is created successfully. Note that if the staging buffer was not created successfully, we will never return that buffer and would instead return an error buffer anyways. We need the state to be Unmapped though since it needs to be properly destroyed.

Bug: chromium:1265923, dawn:628
Change-Id: I62f98f0f1379a9cf0af565adfb8256ffe592b1ad
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/68880
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Loko Kung 2021-11-10 20:28:02 +00:00 committed by Dawn LUCI CQ
parent df77ecde39
commit 75c978f9b9
2 changed files with 23 additions and 27 deletions

View File

@ -261,30 +261,32 @@ namespace dawn_native {
MaybeError BufferBase::MapAtCreationInternal() {
ASSERT(!IsError());
mState = BufferState::MappedAtCreation;
mMapOffset = 0;
mMapSize = mSize;
// 0-sized buffers are not supposed to be written to, Return back any non-null pointer.
// Handle 0-sized buffers first so we don't try to map them in the backend.
if (mSize == 0) {
return {};
}
// Mappable buffers don't use a staging buffer and are just as if mapped through MapAsync.
// 0-sized buffers are not supposed to be written to. Return back any non-null pointer.
// Skip handling 0-sized buffers so we don't try to map them in the backend.
if (mSize != 0) {
// Mappable buffers don't use a staging buffer and are just as if mapped through
// MapAsync.
if (IsCPUWritableAtCreation()) {
DAWN_TRY(MapAtCreationImpl());
} else {
// If any of these fail, the buffer will be deleted and replaced with an
// error buffer.
// The staging buffer is used to return mappable data to inititalize the buffer
// contents. Allocate one as large as the real buffer size so that every byte is
// initialized.
// TODO(crbug.com/dawn/828): Suballocate and reuse memory from a larger staging buffer
// so we don't create many small buffers.
DAWN_TRY_ASSIGN(mStagingBuffer, GetDevice()->CreateStagingBuffer(GetAllocatedSize()));
// If any of these fail, the buffer will be deleted and replaced with an error
// buffer. The staging buffer is used to return mappable data to inititalize the
// buffer contents. Allocate one as large as the real buffer size so that every byte
// is initialized.
// TODO(crbug.com/dawn/828): Suballocate and reuse memory from a larger staging
// buffer so we don't create many small buffers.
DAWN_TRY_ASSIGN(mStagingBuffer,
GetDevice()->CreateStagingBuffer(GetAllocatedSize()));
}
}
// Only set the state to mapped at creation if we did no fail any point in this helper.
// Otherwise, if we override the default unmapped state before succeeding to create a
// staging buffer, we will have issues when we try to destroy the buffer.
mState = BufferState::MappedAtCreation;
return {};
}

View File

@ -379,14 +379,8 @@ namespace dawn_native { namespace d3d12 {
}
void Buffer::DestroyApiObjectImpl() {
if (mMappedData != nullptr) {
// If the buffer is currently mapped, unmap without flushing the writes to the GPU
// since the buffer cannot be used anymore. UnmapImpl checks mWrittenRange to know
// which parts to flush, so we set it to an empty range to prevent flushes.
mWrittenMappedRange = {0, 0};
UnmapImpl();
}
// TODO(crbug.com/dawn/1189) Reintroduce optimization to skip flushing the writes to the GPU
// memory when we unmap in destruction case since the buffer will be destroyed anyways.
ToBackend(GetDevice())->DeallocateMemory(mResourceAllocation);
}