Workaround for UpdateSubresource1 16-byte alignment
In case of misalignment, we write to a temp staging buffer first,
and then copy to the dest buffer using CopySubresourceRegion.
Bug: dawn:1776
Bug: dawn:1705
Change-Id: Iba44dd79d9ee4b02f8cc83263bcfc911e1cce136
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/130140
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
diff --git a/src/dawn/native/d3d11/BufferD3D11.cpp b/src/dawn/native/d3d11/BufferD3D11.cpp
index b7e894c..b399870 100644
--- a/src/dawn/native/d3d11/BufferD3D11.cpp
+++ b/src/dawn/native/d3d11/BufferD3D11.cpp
@@ -445,23 +445,51 @@
return {};
}
- D3D11_BOX dstBox;
- dstBox.left = offset;
- dstBox.right = offset + size;
- dstBox.top = 0;
- dstBox.bottom = 1;
- dstBox.front = 0;
- dstBox.back = 1;
+ D3D11_BOX box;
+ box.left = offset;
+ box.right = offset + size;
+ box.top = 0;
+ box.bottom = 1;
+ box.front = 0;
+ box.back = 1;
- // TODO(dawn:1739): check whether driver supports partial update of uniform buffer.
if ((GetUsage() & wgpu::BufferUsage::Uniform)) {
- d3d11DeviceContext1->UpdateSubresource1(GetD3D11Buffer(), /*DstSubresource=*/0, &dstBox,
- data,
- /*SrcRowPitch=*/0,
- /*SrcDepthPitch*/ 0, D3D11_COPY_NO_OVERWRITE);
+ if (!IsAligned(box.left, 16) || !IsAligned(box.right, 16)) {
+ // Create a temp staging buffer to workaround the alignment issue.
+ BufferDescriptor descriptor;
+ descriptor.size = box.right - box.left;
+ DAWN_ASSERT(IsAligned(descriptor.size, 4));
+ descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
+ descriptor.mappedAtCreation = false;
+ descriptor.label = "temp staging buffer";
+ Ref<BufferBase> stagingBufferBase;
+ DAWN_TRY_ASSIGN(stagingBufferBase, GetDevice()->CreateBuffer(&descriptor));
+ Ref<Buffer> stagingBuffer;
+ stagingBuffer = ToBackend(std::move(stagingBufferBase));
+ {
+ ScopedMap scopedMap;
+ DAWN_TRY_ASSIGN(scopedMap, ScopedMap::Create(stagingBuffer.Get()));
+ uint8_t* mappedData = scopedMap.GetMappedData();
+ DAWN_ASSERT(mappedData);
+ memcpy(mappedData, data, size);
+ }
+ box.left = 0;
+ box.right = descriptor.size;
+ commandContext->GetD3D11DeviceContext()->CopySubresourceRegion(
+ GetD3D11Buffer(), /*DstSubresource=*/0, /*DstX=*/offset,
+ /*DstY=*/0,
+ /*DstZ=*/0, stagingBuffer->GetD3D11Buffer(), /*SrcSubresource=*/0, &box);
+ stagingBuffer = nullptr;
+
+ } else {
+ // TODO(dawn:1739): check whether driver supports partial update of uniform buffer.
+ d3d11DeviceContext1->UpdateSubresource1(GetD3D11Buffer(), /*DstSubresource=*/0, &box,
+ data,
+ /*SrcRowPitch=*/0,
+ /*SrcDepthPitch*/ 0, D3D11_COPY_NO_OVERWRITE);
+ }
} else {
- d3d11DeviceContext1->UpdateSubresource(GetD3D11Buffer(), /*DstSubresource=*/0, &dstBox,
- data,
+ d3d11DeviceContext1->UpdateSubresource(GetD3D11Buffer(), /*DstSubresource=*/0, &box, data,
/*SrcRowPitch=*/0,
/*SrcDepthPitch*/ 0);
}
diff --git a/src/dawn/tests/end2end/BindGroupTests.cpp b/src/dawn/tests/end2end/BindGroupTests.cpp
index 999023a..f4551e7 100644
--- a/src/dawn/tests/end2end/BindGroupTests.cpp
+++ b/src/dawn/tests/end2end/BindGroupTests.cpp
@@ -994,9 +994,6 @@
// Regression test for crbug.com/dawn/408 where dynamic offsets were applied in the wrong order.
// Dynamic offsets should be applied in increasing order of binding number.
TEST_P(BindGroupTests, DynamicOffsetOrder) {
- // TODO(dawn:1776): Fix the UpdateSubresource1 16-byte alignment.
- DAWN_SUPPRESS_TEST_IF(IsD3D11());
-
// We will put the following values and the respective offsets into a buffer.
// The test will ensure that the correct dynamic offset is applied to each buffer by reading the
// value from an offset binding.
@@ -1082,9 +1079,6 @@
// // TODO(crbug.com/dawn/1106): Test output is wrong on D3D12 using WARP.
DAWN_SUPPRESS_TEST_IF(IsWARP());
- // TODO(dawn:1776): Fix the UpdateSubresource1 16-byte alignment.
- DAWN_SUPPRESS_TEST_IF(IsD3D11());
-
auto RunTestWith = [&](bool dynamicBufferFirst) {
uint32_t dynamicBufferBindingNumber = dynamicBufferFirst ? 0 : 1;
uint32_t bufferBindingNumber = dynamicBufferFirst ? 1 : 0;