Fix the initialization of the buffers with MapRead and MapAtCreation

This patch fixes the issues on the initialization of buffers with
MapRead usage and mappedAtCreation == true.
1. The buffers with MapRead usage and mappedAtCreation == true can be
   read from the CPU side just after the creation of the buffer,
   however at that time the internal pending command buffers may not
   be executed, thus causing the buffer is not cleared as is expected.
2. On D3D12 the buffer with MapRead and mappedAtCreation == true is
   created on the READBACK heap, so all the data written in the CPU
   side cannot be uploaded to the GPU memory. When the buffer is mapped
   again all the original data written through the CPU pointer will be
   overwritten by the data in the GPU memory (which means it is also
   cleared to 0).

This patch fixes this issue by:
1. clearing the buffers with mappedAtCreation == true on the CPU side.
2. on D3D12 making the buffer with MapRead and mappedAtCreation == true
   use the staging buffer instead of mapping itself.

Note that this change is only related to the code path with Toggle
"nonzero_clear_resources_on_creation_for_testing" enabled, currently
we don't plan to do the similar change when we enable Dawn wire.

BUG=dawn:414
TEST=dawn_end2end_tests

Change-Id: I2b3d0840333e8d99759800ab9fc141d0a7cf2f8d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/27220
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
Jiawei Shao
2020-09-01 08:08:57 +00:00
committed by Commit Bot service account
parent 0b89b27263
commit 1c4a7f780f
16 changed files with 255 additions and 69 deletions

View File

@@ -27,7 +27,7 @@ namespace dawn_native { namespace opengl {
bool shouldLazyClear) {
Ref<Buffer> buffer = AcquireRef(new Buffer(device, descriptor, shouldLazyClear));
if (descriptor->mappedAtCreation) {
DAWN_TRY(buffer->MapAtCreation());
DAWN_TRY(buffer->MapAtCreationInternal());
}
return std::move(buffer);
@@ -42,7 +42,10 @@ namespace dawn_native { namespace opengl {
device->gl.GenBuffers(1, &mBuffer);
device->gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
// The buffers with mappedAtCreation == true will be initialized in
// BufferBase::MapAtCreation().
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting) &&
!descriptor->mappedAtCreation) {
std::vector<uint8_t> clearValues(size, 1u);
device->gl.BufferData(GL_ARRAY_BUFFER, size, clearValues.data(), GL_STATIC_DRAW);
} else {
@@ -127,15 +130,13 @@ namespace dawn_native { namespace opengl {
SetIsDataInitialized();
}
bool Buffer::IsMappableAtCreation() const {
bool Buffer::IsCPUWritableAtCreation() const {
// TODO(enga): All buffers in GL can be mapped. Investigate if mapping them will cause the
// driver to migrate it to shared memory.
return true;
}
MaybeError Buffer::MapAtCreationImpl() {
EnsureDataInitialized();
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
gl.BindBuffer(GL_ARRAY_BUFFER, mBuffer);
mMappedData = gl.MapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

View File

@@ -43,7 +43,7 @@ namespace dawn_native { namespace opengl {
MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
void UnmapImpl() override;
void DestroyImpl() override;
bool IsMappableAtCreation() const override;
bool IsCPUWritableAtCreation() const override;
MaybeError MapAtCreationImpl() override;
void* GetMappedPointerImpl() override;