Fix bugs in the multi-layer copies with BC formats on D3D12 and OpenGL

This patch fixes two bugs in the copy commands with BC formats and
multiple array layers on D3D12 and OpenGL and adds two end2end tests as
the regression tests.

This patch also removes "viewArrayLayer" in the struct CopyConfig used
in CompressedTextureBCFormatTest and sets the base array layer into
CopyConfig.copyOrigin3D.z instead.

BUG=dawn:453
TEST=dawn_end2end_tests

Change-Id: I1c2e6b79fb7c44fc996655ab5a908e27ba8c4729
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24183
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Jiawei Shao 2020-07-02 09:08:09 +00:00 committed by Commit Bot service account
parent 16ca52cc16
commit 4d007f34f3
3 changed files with 95 additions and 36 deletions

View File

@ -592,7 +592,8 @@ namespace dawn_native { namespace d3d12 {
subresources);
const uint64_t bytesPerSlice =
copy->source.bytesPerRow * copy->source.rowsPerImage;
copy->source.bytesPerRow *
(copy->source.rowsPerImage / texture->GetFormat().blockHeight);
const dawn_native::Extent3D copyOneLayerSize = {copy->copySize.width,
copy->copySize.height, 1};
@ -648,7 +649,8 @@ namespace dawn_native { namespace d3d12 {
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
const uint64_t bytesPerSlice =
copy->destination.bytesPerRow * copy->destination.rowsPerImage;
copy->destination.bytesPerRow *
(copy->destination.rowsPerImage / texture->GetFormat().blockHeight);
const dawn_native::Extent3D copyOneLayerSize = {copy->copySize.width,
copy->copySize.height, 1};

View File

@ -542,7 +542,7 @@ namespace dawn_native { namespace opengl {
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
uint64_t copyDataSize = (copySize.width / formatInfo.blockWidth) *
(copySize.height / formatInfo.blockHeight) *
formatInfo.blockByteSize;
formatInfo.blockByteSize * copySize.depth;
Extent3D copyExtent = ComputeTextureCopyExtent(dst, copySize);
if (texture->GetArrayLayers() > 1) {

View File

@ -27,7 +27,6 @@ struct CopyConfig {
wgpu::Extent3D copyExtent3D;
wgpu::Origin3D copyOrigin3D = {0, 0, 0};
uint32_t viewMipmapLevel = 0;
uint32_t viewArrayLayer = 0;
uint32_t bufferOffset = 0;
uint32_t bytesPerRowAlignment = kTextureBytesPerRowAlignment;
uint32_t rowsPerImage = 0;
@ -69,19 +68,24 @@ class CompressedTextureBCFormatTest : public DawnTest {
copyWidthInBlockAtLevel *
utils::GetTexelBlockSizeInBytes(copyConfig.textureDescriptor.format);
}
uint32_t copyBytesPerImage = bufferRowPitchInBytes * copyHeightInBlockAtLevel;
uint32_t uploadBufferSize =
copyConfig.bufferOffset + bufferRowPitchInBytes * copyHeightInBlockAtLevel;
copyConfig.bufferOffset + copyBytesPerImage * copyConfig.copyExtent3D.depth;
// Fill uploadData with the pre-prepared one-block compressed texture data.
std::vector<uint8_t> uploadData(uploadBufferSize, 0);
std::vector<uint8_t> oneBlockCompressedTextureData =
GetOneBlockBCFormatTextureData(copyConfig.textureDescriptor.format);
for (uint32_t h = 0; h < copyHeightInBlockAtLevel; ++h) {
for (uint32_t w = 0; w < copyWidthInBlockAtLevel; ++w) {
uint32_t uploadBufferOffset = copyConfig.bufferOffset + bufferRowPitchInBytes * h +
oneBlockCompressedTextureData.size() * w;
std::memcpy(&uploadData[uploadBufferOffset], oneBlockCompressedTextureData.data(),
oneBlockCompressedTextureData.size() * sizeof(uint8_t));
for (uint32_t layer = 0; layer < copyConfig.copyExtent3D.depth; ++layer) {
for (uint32_t h = 0; h < copyHeightInBlockAtLevel; ++h) {
for (uint32_t w = 0; w < copyWidthInBlockAtLevel; ++w) {
uint32_t uploadBufferOffset =
copyConfig.bufferOffset + copyBytesPerImage * layer +
bufferRowPitchInBytes * h + oneBlockCompressedTextureData.size() * w;
std::memcpy(&uploadData[uploadBufferOffset],
oneBlockCompressedTextureData.data(),
oneBlockCompressedTextureData.size() * sizeof(uint8_t));
}
}
}
@ -92,11 +96,8 @@ class CompressedTextureBCFormatTest : public DawnTest {
utils::CreateBufferCopyView(stagingBuffer, copyConfig.bufferOffset,
copyConfig.bytesPerRowAlignment, copyConfig.rowsPerImage);
ASSERT(copyConfig.copyOrigin3D.z == 0);
wgpu::Origin3D copyOrigin = copyConfig.copyOrigin3D;
copyOrigin.z = copyConfig.viewArrayLayer;
wgpu::TextureCopyView textureCopyView = utils::CreateTextureCopyView(
bcCompressedTexture, copyConfig.viewMipmapLevel, copyOrigin);
bcCompressedTexture, copyConfig.viewMipmapLevel, copyConfig.copyOrigin3D);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copyConfig.copyExtent3D);
@ -204,9 +205,6 @@ class CompressedTextureBCFormatTest : public DawnTest {
wgpu::Texture bcTexture = CreateTextureWithCompressedData(config);
wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest();
wgpu::BindGroup bindGroup = CreateBindGroupForTest(
renderPipeline.GetBindGroupLayout(0), bcTexture, config.textureDescriptor.format,
config.viewArrayLayer, config.viewMipmapLevel);
wgpu::Extent3D virtualSizeAtLevel = GetVirtualSizeAtLevel(config);
@ -220,11 +218,21 @@ class CompressedTextureBCFormatTest : public DawnTest {
if (config.copyOrigin3D.y + config.copyExtent3D.height > virtualSizeAtLevel.height) {
noPaddingExtent3D.height = virtualSizeAtLevel.height - config.copyOrigin3D.y;
}
noPaddingExtent3D.depth = 1u;
std::vector<RGBA8> expectedData =
GetExpectedData(config.textureDescriptor.format, virtualSizeAtLevel);
VerifyCompressedTexturePixelValues(renderPipeline, bindGroup, virtualSizeAtLevel,
config.copyOrigin3D, noPaddingExtent3D, expectedData);
wgpu::Origin3D firstLayerCopyOrigin = {config.copyOrigin3D.x, config.copyOrigin3D.y, 0};
for (uint32_t layer = config.copyOrigin3D.z;
layer < config.copyOrigin3D.z + config.copyExtent3D.depth; ++layer) {
wgpu::BindGroup bindGroup = CreateBindGroupForTest(
renderPipeline.GetBindGroupLayout(0), bcTexture, config.textureDescriptor.format,
layer, config.viewMipmapLevel);
VerifyCompressedTexturePixelValues(renderPipeline, bindGroup, virtualSizeAtLevel,
firstLayerCopyOrigin, noPaddingExtent3D,
expectedData);
}
}
// Create a texture and initialize it with the pre-prepared compressed texture data.
@ -240,17 +248,10 @@ class CompressedTextureBCFormatTest : public DawnTest {
wgpu::Texture dstTexture,
CopyConfig srcConfig,
CopyConfig dstConfig) {
ASSERT(srcConfig.copyOrigin3D.z == 0);
wgpu::Origin3D srcCopyOrigin = srcConfig.copyOrigin3D;
srcCopyOrigin.z = srcConfig.viewArrayLayer;
wgpu::TextureCopyView textureCopyViewSrc =
utils::CreateTextureCopyView(srcTexture, srcConfig.viewMipmapLevel, srcCopyOrigin);
ASSERT(dstConfig.copyOrigin3D.z == 0);
wgpu::Origin3D dstCopyOrigin = dstConfig.copyOrigin3D;
dstCopyOrigin.z = dstConfig.viewArrayLayer;
wgpu::TextureCopyView textureCopyViewDst =
utils::CreateTextureCopyView(dstTexture, dstConfig.viewMipmapLevel, dstCopyOrigin);
wgpu::TextureCopyView textureCopyViewSrc = utils::CreateTextureCopyView(
srcTexture, srcConfig.viewMipmapLevel, srcConfig.copyOrigin3D);
wgpu::TextureCopyView textureCopyViewDst = utils::CreateTextureCopyView(
dstTexture, dstConfig.viewMipmapLevel, dstConfig.copyOrigin3D);
encoder.CopyTextureToTexture(&textureCopyViewSrc, &textureCopyViewDst,
&dstConfig.copyExtent3D);
}
@ -490,7 +491,7 @@ TEST_P(CompressedTextureBCFormatTest, CopyIntoNonZeroArrayLayer) {
constexpr uint32_t kArrayLayerCount = 3;
config.textureDescriptor.size.depth = kArrayLayerCount;
config.viewArrayLayer = kArrayLayerCount - 1;
config.copyOrigin3D.z = kArrayLayerCount - 1;
for (wgpu::TextureFormat format : kBCFormats) {
config.textureDescriptor.format = format;
@ -587,7 +588,7 @@ TEST_P(CompressedTextureBCFormatTest, CopyWholeTextureSubResourceIntoNonZeroMipm
wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest();
wgpu::BindGroup bindGroup =
CreateBindGroupForTest(renderPipeline.GetBindGroupLayout(0), bcTextureDst, format,
config.viewArrayLayer, config.viewMipmapLevel);
config.copyOrigin3D.z, config.viewMipmapLevel);
std::vector<RGBA8> expectedData = GetExpectedData(format, kVirtualSize);
VerifyCompressedTexturePixelValues(renderPipeline, bindGroup, kVirtualSize,
@ -651,7 +652,7 @@ TEST_P(CompressedTextureBCFormatTest, CopyIntoSubresourceWithPhysicalSizeNotEqua
wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest();
wgpu::BindGroup bindGroup =
CreateBindGroupForTest(renderPipeline.GetBindGroupLayout(0), bcTextureDst, format,
dstConfig.viewArrayLayer, dstConfig.viewMipmapLevel);
dstConfig.copyOrigin3D.z, dstConfig.viewMipmapLevel);
std::vector<RGBA8> expectedData = GetExpectedData(format, kDstVirtualSize);
VerifyCompressedTexturePixelValues(renderPipeline, bindGroup, kDstVirtualSize,
@ -711,7 +712,7 @@ TEST_P(CompressedTextureBCFormatTest, CopyFromSubresourceWithPhysicalSizeNotEqua
wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest();
wgpu::BindGroup bindGroup =
CreateBindGroupForTest(renderPipeline.GetBindGroupLayout(0), bcTextureDst, format,
dstConfig.viewArrayLayer, dstConfig.viewMipmapLevel);
dstConfig.copyOrigin3D.z, dstConfig.viewMipmapLevel);
std::vector<RGBA8> expectedData = GetExpectedData(format, kDstVirtualSize);
VerifyCompressedTexturePixelValues(renderPipeline, bindGroup, kDstVirtualSize,
@ -792,7 +793,7 @@ TEST_P(CompressedTextureBCFormatTest, MultipleCopiesWithPhysicalSizeNotEqualToVi
// Verify if we can use bcDstTextures as sampled textures correctly.
wgpu::BindGroup bindGroup0 = CreateBindGroupForTest(
renderPipeline.GetBindGroupLayout(0), bcDstTextures[i], format,
dstConfigs[i].viewArrayLayer, dstConfigs[i].viewMipmapLevel);
dstConfigs[i].copyOrigin3D.z, dstConfigs[i].viewMipmapLevel);
std::vector<RGBA8> expectedData = GetExpectedData(format, dstVirtualSizes[i]);
VerifyCompressedTexturePixelValues(renderPipeline, bindGroup0, dstVirtualSizes[i],
@ -1003,6 +1004,62 @@ TEST_P(CompressedTextureBCFormatTest, LargeImageHeightAndClampedCopyExtent) {
}
}
// Test copying a whole 2D array texture with array layer count > 1 in one copy command works with
// BC formats.
TEST_P(CompressedTextureBCFormatTest, CopyWhole2DArrayTexture) {
// TODO(jiawei.shao@intel.com): find out why this test is flaky on Windows Intel Vulkan
// bots.
DAWN_SKIP_TEST_IF(IsIntel() && IsVulkan() && IsWindows());
// TODO(jiawei.shao@intel.com): find out why this test fails on Windows Intel OpenGL drivers.
DAWN_SKIP_TEST_IF(IsIntel() && IsOpenGL() && IsWindows());
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
constexpr uint32_t kArrayLayerCount = 3;
CopyConfig config;
config.textureDescriptor.usage = kDefaultBCFormatTextureUsage;
config.textureDescriptor.size = {8, 8, kArrayLayerCount};
config.copyExtent3D = config.textureDescriptor.size;
config.copyExtent3D.depth = kArrayLayerCount;
for (wgpu::TextureFormat format : kBCFormats) {
config.textureDescriptor.format = format;
TestCopyRegionIntoBCFormatTextures(config);
}
}
// Test copying a multiple 2D texture array layers in one copy command works with BC formats.
TEST_P(CompressedTextureBCFormatTest, CopyMultiple2DArrayLayers) {
// TODO(jiawei.shao@intel.com): find out why this test is flaky on Windows Intel Vulkan
// bots.
DAWN_SKIP_TEST_IF(IsIntel() && IsVulkan() && IsWindows());
// TODO(jiawei.shao@intel.com): find out why this test fails on Windows Intel OpenGL drivers.
DAWN_SKIP_TEST_IF(IsIntel() && IsOpenGL() && IsWindows());
DAWN_SKIP_TEST_IF(!IsBCFormatSupported());
constexpr uint32_t kArrayLayerCount = 3;
CopyConfig config;
config.textureDescriptor.usage = kDefaultBCFormatTextureUsage;
config.textureDescriptor.size = {8, 8, kArrayLayerCount};
constexpr uint32_t kCopyBaseArrayLayer = 1;
constexpr uint32_t kCopyLayerCount = 2;
config.copyOrigin3D = {0, 0, kCopyBaseArrayLayer};
config.copyExtent3D = config.textureDescriptor.size;
config.copyExtent3D.depth = kCopyLayerCount;
for (wgpu::TextureFormat format : kBCFormats) {
config.textureDescriptor.format = format;
TestCopyRegionIntoBCFormatTextures(config);
}
}
// TODO(jiawei.shao@intel.com): support BC formats on OpenGL backend
DAWN_INSTANTIATE_TEST(CompressedTextureBCFormatTest,
D3D12Backend(),