Use UpdateSubresource1() to write data to ID3D11Buffer
Since Windows 8, UpdateSubresource1() supports partial updating constant
buffers, so use it to avoid an extra copy.
Bug: none
Change-Id: I6b162e485b91df08364d6a1af128bd90b4e80f1d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/171641
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
diff --git a/src/dawn/native/d3d11/BufferD3D11.cpp b/src/dawn/native/d3d11/BufferD3D11.cpp
index 80947d3..5f6c915 100644
--- a/src/dawn/native/d3d11/BufferD3D11.cpp
+++ b/src/dawn/native/d3d11/BufferD3D11.cpp
@@ -28,6 +28,7 @@
#include "dawn/native/d3d11/BufferD3D11.h"
#include <algorithm>
+#include <memory>
#include <utility>
#include <vector>
@@ -541,16 +542,17 @@
if (mD3d11NonConstantBuffer) {
D3D11_BOX box;
- box.left = offset;
- box.right = offset + size;
+ box.left = static_cast<UINT>(offset);
box.top = 0;
- box.bottom = 1;
box.front = 0;
+ box.right = static_cast<UINT>(offset + size);
+ box.bottom = 1;
box.back = 1;
- commandContext->UpdateSubresource(mD3d11NonConstantBuffer.Get(), /*DstSubresource=*/0, &box,
- data,
- /*SrcRowPitch=*/0,
- /*SrcDepthPitch*/ 0);
+ commandContext->UpdateSubresource1(mD3d11NonConstantBuffer.Get(), /*DstSubresource=*/0,
+ /*pDstBox=*/&box, data,
+ /*SrcRowPitch=*/0,
+ /*SrcDepthPitch=*/0,
+ /*CopyFlags=*/0);
if (!mD3d11ConstantBuffer) {
return {};
}
@@ -565,33 +567,47 @@
commandContext->CopySubresourceRegion(
mD3d11ConstantBuffer.Get(), /*DstSubresource=*/0, /*DstX=*/offset,
/*DstY=*/0,
- /*DstZ=*/0, mD3d11NonConstantBuffer.Get(), /*SrcSubresource=*/0, &box);
+ /*DstZ=*/0, mD3d11NonConstantBuffer.Get(), /*SrcSubresource=*/0, /*pSrcBux=*/&box);
return {};
}
DAWN_ASSERT(mD3d11ConstantBuffer);
- // For a full size write, UpdateSubresource() can be used to update mD3d11ConstantBuffer.
+ // For a full size write, UpdateSubresource1(D3D11_COPY_DISCARD) can be used to update
+ // mD3d11ConstantBuffer.
if (size == GetSize() && offset == 0) {
- if (size == mAllocatedSize) {
- commandContext->UpdateSubresource(mD3d11ConstantBuffer.Get(), /*DstSubresource=*/0,
- nullptr, data,
- /*SrcRowPitch=*/size,
- /*SrcDepthPitch*/ 0);
- } else {
- std::vector<uint8_t> allocatedData(mAllocatedSize, 0);
- std::memcpy(allocatedData.data(), data, size);
- commandContext->UpdateSubresource(mD3d11ConstantBuffer.Get(), /*DstSubresource=*/0,
- nullptr, allocatedData.data(),
- /*SrcRowPitch=*/mAllocatedSize,
- /*SrcDepthPitch*/ 0);
+ // Offset and size must be aligned with 16 for using UpdateSubresource1() on constant
+ // buffer.
+ constexpr size_t kConstantBufferUpdateAlignment = 16;
+ size_t alignedSize = Align(size, kConstantBufferUpdateAlignment);
+ DAWN_ASSERT(alignedSize <= GetAllocatedSize());
+ std::unique_ptr<uint8_t[]> alignedBuffer;
+ if (size != alignedSize) {
+ alignedBuffer.reset(new uint8_t[alignedSize]);
+ std::memcpy(alignedBuffer.get(), data, size);
+ data = alignedBuffer.get();
}
+
+ D3D11_BOX dstBox;
+ dstBox.left = 0;
+ dstBox.top = 0;
+ dstBox.front = 0;
+ dstBox.right = static_cast<UINT>(alignedSize);
+ dstBox.bottom = 1;
+ dstBox.back = 1;
+ // For full buffer write, D3D11_COPY_DISCARD is used to avoid GPU CPU synchronization.
+ commandContext->UpdateSubresource1(mD3d11ConstantBuffer.Get(), /*DstSubresource=*/0,
+ &dstBox, data,
+ /*SrcRowPitch=*/0,
+ /*SrcDepthPitch=*/0,
+ /*CopyFlags=*/D3D11_COPY_DISCARD);
return {};
}
- // If the mD3d11NonConstantBuffer is null, we have to create a staging buffer for transfer the
- // data to mD3d11ConstantBuffer.
+ // If the mD3d11NonConstantBuffer is null and copy offset and size are not 16 bytes
+ // aligned, we have to create a staging buffer for transfer the data to
+ // mD3d11ConstantBuffer.
Ref<BufferBase> stagingBuffer;
DAWN_TRY_ASSIGN(stagingBuffer, ToBackend(GetDevice())->GetStagingBuffer(commandContext, size));
@@ -624,11 +640,11 @@
Buffer* destination,
uint64_t destinationOffset) {
D3D11_BOX srcBox;
- srcBox.left = sourceOffset;
- srcBox.right = sourceOffset + size;
+ srcBox.left = static_cast<UINT>(sourceOffset);
srcBox.top = 0;
- srcBox.bottom = 1;
srcBox.front = 0;
+ srcBox.right = static_cast<UINT>(sourceOffset + size);
+ srcBox.bottom = 1;
srcBox.back = 1;
ID3D11Buffer* d3d11SourceBuffer = source->mD3d11NonConstantBuffer
? source->mD3d11NonConstantBuffer.Get()
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
index b226973..7d79769 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
@@ -50,14 +50,15 @@
return Get()->mDevice.Get();
}
-void ScopedCommandRecordingContext::UpdateSubresource(ID3D11Resource* pDstResource,
- UINT DstSubresource,
- const D3D11_BOX* pDstBox,
- const void* pSrcData,
- UINT SrcRowPitch,
- UINT SrcDepthPitch) const {
- Get()->mD3D11DeviceContext4->UpdateSubresource(pDstResource, DstSubresource, pDstBox, pSrcData,
- SrcRowPitch, SrcDepthPitch);
+void ScopedCommandRecordingContext::UpdateSubresource1(ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch,
+ UINT CopyFlags) const {
+ Get()->mD3D11DeviceContext4->UpdateSubresource1(pDstResource, DstSubresource, pDstBox, pSrcData,
+ SrcRowPitch, SrcDepthPitch, CopyFlags);
}
void ScopedCommandRecordingContext::CopyResource(ID3D11Resource* pDstResource,
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
index 05f7197..63e9ea4 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
@@ -111,12 +111,13 @@
Device* GetDevice() const;
// Wrapper method which don't depend on context state.
- void UpdateSubresource(ID3D11Resource* pDstResource,
- UINT DstSubresource,
- const D3D11_BOX* pDstBox,
- const void* pSrcData,
- UINT SrcRowPitch,
- UINT SrcDepthPitch) const;
+ void UpdateSubresource1(ID3D11Resource* pDstResource,
+ UINT DstSubresource,
+ const D3D11_BOX* pDstBox,
+ const void* pSrcData,
+ UINT SrcRowPitch,
+ UINT SrcDepthPitch,
+ UINT CopyFlags) const;
void CopyResource(ID3D11Resource* pDstResource, ID3D11Resource* pSrcResource) const;
void CopySubresourceRegion(ID3D11Resource* pDstResource,
UINT DstSubresource,
diff --git a/src/dawn/native/d3d11/TextureD3D11.cpp b/src/dawn/native/d3d11/TextureD3D11.cpp
index 4edaeb1..613080a 100644
--- a/src/dawn/native/d3d11/TextureD3D11.cpp
+++ b/src/dawn/native/d3d11/TextureD3D11.cpp
@@ -770,8 +770,9 @@
dstBox.back = origin.z + size.depthOrArrayLayers;
uint32_t subresource =
GetSubresourceIndex(subresources.baseMipLevel, 0, D3D11Aspect(subresources.aspects));
- commandContext->UpdateSubresource(GetD3D11Resource(), subresource, &dstBox, data,
- bytesPerRow, bytesPerRow * rowsPerImage);
+ commandContext->UpdateSubresource1(GetD3D11Resource(), subresource, &dstBox, data,
+ bytesPerRow, bytesPerRow * rowsPerImage,
+ /*CopyFlags=*/0);
} else {
dstBox.front = 0;
dstBox.back = 1;
@@ -780,8 +781,8 @@
GetSubresourceIndex(subresources.baseMipLevel, subresources.baseArrayLayer + layer,
D3D11Aspect(subresources.aspects));
D3D11_BOX* pDstBox = GetFormat().HasDepthOrStencil() ? nullptr : &dstBox;
- commandContext->UpdateSubresource(GetD3D11Resource(), subresource, pDstBox, data,
- bytesPerRow, 0);
+ commandContext->UpdateSubresource1(GetD3D11Resource(), subresource, pDstBox, data,
+ bytesPerRow, 0, /*CopyFlags=*/0);
data += rowsPerImage * bytesPerRow;
}
}