D3D12: Fix usage of CopyResource

CopyResource may only be used for resources that have exactly the same
format, dimension, mips, layers. And it can only be used if the entire
texture region is copied.

Bug: dawn:353
Change-Id: Ia8f96cc10c88fe026e23bce2d0532624725b12e0
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16984
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Austin Eng 2020-03-18 01:11:17 +00:00 committed by Commit Bot service account
parent b988e03982
commit 83e138ca96
2 changed files with 52 additions and 13 deletions

View File

@ -53,18 +53,40 @@ namespace dawn_native { namespace d3d12 {
}
}
bool CanUseCopyResource(const uint32_t sourceNumMipLevels,
const Extent3D& srcSize,
const Extent3D& dstSize,
const Extent3D& copySize) {
if (sourceNumMipLevels == 1 && srcSize.width == dstSize.width &&
srcSize.height == dstSize.height && srcSize.depth == dstSize.depth &&
srcSize.width == copySize.width && srcSize.height == copySize.height &&
srcSize.depth == copySize.depth) {
return true;
}
bool CanUseCopyResource(const Texture* src, const Texture* dst, const Extent3D& copySize) {
// Checked by validation
ASSERT(src->GetSampleCount() == dst->GetSampleCount());
ASSERT(src->GetFormat().format == dst->GetFormat().format);
return false;
const Extent3D& srcSize = src->GetSize();
const Extent3D& dstSize = dst->GetSize();
auto GetCopyDepth = [](const Texture* texture) {
switch (texture->GetDimension()) {
case wgpu::TextureDimension::e1D:
return 1u;
case wgpu::TextureDimension::e2D:
return texture->GetArrayLayers();
case wgpu::TextureDimension::e3D:
return texture->GetSize().depth;
}
};
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-copyresource
// In order to use D3D12's copy resource, the textures must be the same dimensions, and
// the copy must be of the entire resource.
// TODO(dawn:129): Support 1D textures.
return src->GetDimension() == dst->GetDimension() && //
dst->GetNumMipLevels() == 1 && //
src->GetNumMipLevels() == 1 && // A copy command is of a single mip, so if a
// resource has more than one, we definitely
// cannot use CopyResource.
copySize.width == dstSize.width && //
copySize.width == srcSize.width && //
copySize.height == dstSize.height && //
copySize.height == srcSize.height && //
copySize.depth == GetCopyDepth(src) && //
copySize.depth == GetCopyDepth(dst);
}
} // anonymous namespace
@ -669,8 +691,7 @@ namespace dawn_native { namespace d3d12 {
destination->TrackUsageAndTransitionNow(commandContext,
wgpu::TextureUsage::CopyDst);
if (CanUseCopyResource(source->GetNumMipLevels(), source->GetSize(),
destination->GetSize(), copy->copySize)) {
if (CanUseCopyResource(source, destination, copy->copySize)) {
commandList->CopyResource(destination->GetD3D12Resource(),
source->GetD3D12Resource());
} else {

View File

@ -729,6 +729,24 @@ TEST_P(CopyTests_T2T, TextureMip) {
}
}
TEST_P(CopyTests_T2T, SingleMipSrcMultipleMipDst) {
constexpr uint32_t kWidth = 256;
constexpr uint32_t kHeight = 128;
for (unsigned int i = 1; i < 4; ++i) {
DoTest({kWidth >> i, kHeight >> i, 0, 0, 0}, {kWidth, kHeight, 0, 0, i},
{kWidth >> i, kHeight >> i});
}
}
TEST_P(CopyTests_T2T, MultipleMipSrcSingleMipDst) {
constexpr uint32_t kWidth = 256;
constexpr uint32_t kHeight = 128;
for (unsigned int i = 1; i < 4; ++i) {
DoTest({kWidth, kHeight, 0, 0, i}, {kWidth >> i, kHeight >> i, 0, 0, 0},
{kWidth >> i, kHeight >> i});
}
}
// TODO(brandon1.jones@intel.com) Add test for ensuring blitCommandEncoder on Metal.
DAWN_INSTANTIATE_TEST(CopyTests_T2T, D3D12Backend(), MetalBackend(), OpenGLBackend(), VulkanBackend());