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>
This commit is contained in:
jchen10 2023-05-02 08:36:10 +00:00 committed by Dawn LUCI CQ
parent 642a4f1d8c
commit 1b01b665d7
2 changed files with 42 additions and 20 deletions

View File

@ -445,23 +445,51 @@ MaybeError Buffer::WriteInternal(CommandRecordingContext* commandContext,
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);
}

View File

@ -994,9 +994,6 @@ TEST_P(BindGroupTests, DrawThenChangePipelineTwiceAndBindGroup) {
// 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 @@ TEST_P(BindGroupTests, DynamicAndNonDynamicBindingsDoNotConflictAfterRemapping)
// // 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;