mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-04 12:16:10 +00:00
Support Noop Copy for B2T, T2B and T2T Copies
In B2T, T2B and T2T copies, copySize has 0 in width, height or depth will trigger errors in D3D12 backend. This patch bypass the command record step for noop copy. But all validation rules still applies to the copy. BUG=dawn:255 Change-Id: I4d01cef2e3c1f78440014c2c6ac63a48310d99af Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/28521 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
a3651d2fe0
commit
75e5ed6161
@ -654,19 +654,22 @@ namespace dawn_native {
|
|||||||
Align(copySize->width * blockInfo.blockByteSize, kTextureBytesPerRowAlignment);
|
Align(copySize->width * blockInfo.blockByteSize, kTextureBytesPerRowAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the copy command.
|
// Skip noop copies.
|
||||||
CopyBufferToTextureCmd* copy =
|
if (copySize->width != 0 && copySize->height != 0 && copySize->depth != 0) {
|
||||||
allocator->Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture);
|
// Record the copy command.
|
||||||
copy->source.buffer = source->buffer;
|
CopyBufferToTextureCmd* copy =
|
||||||
copy->source.offset = source->layout.offset;
|
allocator->Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture);
|
||||||
copy->source.bytesPerRow = bytesPerRow;
|
copy->source.buffer = source->buffer;
|
||||||
copy->source.rowsPerImage = defaultedRowsPerImage;
|
copy->source.offset = source->layout.offset;
|
||||||
copy->destination.texture = destination->texture;
|
copy->source.bytesPerRow = bytesPerRow;
|
||||||
copy->destination.origin = destination->origin;
|
copy->source.rowsPerImage = defaultedRowsPerImage;
|
||||||
copy->destination.mipLevel = destination->mipLevel;
|
copy->destination.texture = destination->texture;
|
||||||
copy->destination.aspect =
|
copy->destination.origin = destination->origin;
|
||||||
ConvertAspect(destination->texture->GetFormat(), destination->aspect);
|
copy->destination.mipLevel = destination->mipLevel;
|
||||||
copy->copySize = *copySize;
|
copy->destination.aspect =
|
||||||
|
ConvertAspect(destination->texture->GetFormat(), destination->aspect);
|
||||||
|
copy->copySize = *copySize;
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
@ -713,18 +716,21 @@ namespace dawn_native {
|
|||||||
Align(copySize->width * blockInfo.blockByteSize, kTextureBytesPerRowAlignment);
|
Align(copySize->width * blockInfo.blockByteSize, kTextureBytesPerRowAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the copy command.
|
// Skip noop copies.
|
||||||
CopyTextureToBufferCmd* copy =
|
if (copySize->width != 0 && copySize->height != 0 && copySize->depth != 0) {
|
||||||
allocator->Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
|
// Record the copy command.
|
||||||
copy->source.texture = source->texture;
|
CopyTextureToBufferCmd* copy =
|
||||||
copy->source.origin = source->origin;
|
allocator->Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer);
|
||||||
copy->source.mipLevel = source->mipLevel;
|
copy->source.texture = source->texture;
|
||||||
copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect);
|
copy->source.origin = source->origin;
|
||||||
copy->destination.buffer = destination->buffer;
|
copy->source.mipLevel = source->mipLevel;
|
||||||
copy->destination.offset = destination->layout.offset;
|
copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect);
|
||||||
copy->destination.bytesPerRow = bytesPerRow;
|
copy->destination.buffer = destination->buffer;
|
||||||
copy->destination.rowsPerImage = defaultedRowsPerImage;
|
copy->destination.offset = destination->layout.offset;
|
||||||
copy->copySize = *copySize;
|
copy->destination.bytesPerRow = bytesPerRow;
|
||||||
|
copy->destination.rowsPerImage = defaultedRowsPerImage;
|
||||||
|
copy->copySize = *copySize;
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
@ -754,18 +760,21 @@ namespace dawn_native {
|
|||||||
mTopLevelTextures.insert(destination->texture);
|
mTopLevelTextures.insert(destination->texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyTextureToTextureCmd* copy =
|
// Skip noop copies.
|
||||||
allocator->Allocate<CopyTextureToTextureCmd>(Command::CopyTextureToTexture);
|
if (copySize->width != 0 && copySize->height != 0 && copySize->depth != 0) {
|
||||||
copy->source.texture = source->texture;
|
CopyTextureToTextureCmd* copy =
|
||||||
copy->source.origin = source->origin;
|
allocator->Allocate<CopyTextureToTextureCmd>(Command::CopyTextureToTexture);
|
||||||
copy->source.mipLevel = source->mipLevel;
|
copy->source.texture = source->texture;
|
||||||
copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect);
|
copy->source.origin = source->origin;
|
||||||
copy->destination.texture = destination->texture;
|
copy->source.mipLevel = source->mipLevel;
|
||||||
copy->destination.origin = destination->origin;
|
copy->source.aspect = ConvertAspect(source->texture->GetFormat(), source->aspect);
|
||||||
copy->destination.mipLevel = destination->mipLevel;
|
copy->destination.texture = destination->texture;
|
||||||
copy->destination.aspect =
|
copy->destination.origin = destination->origin;
|
||||||
ConvertAspect(destination->texture->GetFormat(), destination->aspect);
|
copy->destination.mipLevel = destination->mipLevel;
|
||||||
copy->copySize = *copySize;
|
copy->destination.aspect =
|
||||||
|
ConvertAspect(destination->texture->GetFormat(), destination->aspect);
|
||||||
|
copy->copySize = *copySize;
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
@ -88,6 +88,7 @@ class CopyTests_T2B : public CopyTests {
|
|||||||
void DoTest(const TextureSpec& textureSpec,
|
void DoTest(const TextureSpec& textureSpec,
|
||||||
const BufferSpec& bufferSpec,
|
const BufferSpec& bufferSpec,
|
||||||
const wgpu::Extent3D& copySize) {
|
const wgpu::Extent3D& copySize) {
|
||||||
|
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(kTextureFormat);
|
||||||
// Create a texture that is `width` x `height` with (`level` + 1) mip levels.
|
// Create a texture that is `width` x `height` with (`level` + 1) mip levels.
|
||||||
wgpu::TextureDescriptor descriptor;
|
wgpu::TextureDescriptor descriptor;
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
descriptor.dimension = wgpu::TextureDimension::e2D;
|
||||||
@ -121,13 +122,10 @@ class CopyTests_T2B : public CopyTests {
|
|||||||
// Prepopulating the buffer with empty data ensures that there is not random data in the
|
// Prepopulating the buffer with empty data ensures that there is not random data in the
|
||||||
// expectation and helps ensure that the padding due to the bytes per row is not modified
|
// expectation and helps ensure that the padding due to the bytes per row is not modified
|
||||||
// by the copy.
|
// by the copy.
|
||||||
// TODO(jiawei.shao@intel.com): remove the initialization of the buffer after we support
|
wgpu::BufferDescriptor bufferDesc;
|
||||||
// buffer lazy-initialization.
|
bufferDesc.size = bufferSpec.size;
|
||||||
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(kTextureFormat);
|
bufferDesc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||||
const std::vector<RGBA8> emptyData(bufferSpec.size / bytesPerTexel, RGBA8());
|
wgpu::Buffer buffer = device.CreateBuffer(&bufferDesc);
|
||||||
wgpu::Buffer buffer =
|
|
||||||
utils::CreateBufferFromData(device, emptyData.data(), bufferSpec.size,
|
|
||||||
wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
wgpu::TextureCopyView textureCopyView =
|
wgpu::TextureCopyView textureCopyView =
|
||||||
@ -141,8 +139,11 @@ class CopyTests_T2B : public CopyTests {
|
|||||||
queue.Submit(1, &commands);
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
uint64_t bufferOffset = bufferSpec.offset;
|
uint64_t bufferOffset = bufferSpec.offset;
|
||||||
const uint32_t texelCountInCopyRegion =
|
|
||||||
bufferSpec.bytesPerRow / bytesPerTexel * (copySize.height - 1) + copySize.width;
|
const wgpu::Extent3D copySizePerSlice = {copySize.width, copySize.height, 1};
|
||||||
|
// Texels in single slice.
|
||||||
|
const uint32_t texelCountInCopyRegion = utils::GetTexelCountInCopyRegion(
|
||||||
|
bufferSpec.bytesPerRow, bufferSpec.rowsPerImage, copySizePerSlice, kTextureFormat);
|
||||||
const uint32_t maxArrayLayer = textureSpec.copyOrigin.z + copySize.depth;
|
const uint32_t maxArrayLayer = textureSpec.copyOrigin.z + copySize.depth;
|
||||||
std::vector<RGBA8> expected(texelCountInCopyRegion);
|
std::vector<RGBA8> expected(texelCountInCopyRegion);
|
||||||
for (uint32_t slice = textureSpec.copyOrigin.z; slice < maxArrayLayer; ++slice) {
|
for (uint32_t slice = textureSpec.copyOrigin.z; slice < maxArrayLayer; ++slice) {
|
||||||
@ -298,6 +299,7 @@ class CopyTests_T2T : public CopyTests {
|
|||||||
utils::CreateTextureCopyView(srcTexture, srcSpec.level, {0, 0, srcSpec.copyOrigin.z});
|
utils::CreateTextureCopyView(srcTexture, srcSpec.level, {0, 0, srcSpec.copyOrigin.z});
|
||||||
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Layout.mipSize);
|
encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Layout.mipSize);
|
||||||
|
|
||||||
|
const wgpu::Extent3D copySizePerSlice = {copySize.width, copySize.height, 1};
|
||||||
// Perform the texture to texture copy
|
// Perform the texture to texture copy
|
||||||
wgpu::TextureCopyView srcTextureCopyView =
|
wgpu::TextureCopyView srcTextureCopyView =
|
||||||
utils::CreateTextureCopyView(srcTexture, srcSpec.level, srcSpec.copyOrigin);
|
utils::CreateTextureCopyView(srcTexture, srcSpec.level, srcSpec.copyOrigin);
|
||||||
@ -308,8 +310,10 @@ class CopyTests_T2T : public CopyTests {
|
|||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
queue.Submit(1, &commands);
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
const uint32_t texelCountInCopyRegion =
|
// Texels in single slice.
|
||||||
copyLayout.texelBlocksPerRow * (copySize.height - 1) + copySize.width;
|
const uint32_t texelCountInCopyRegion = utils::GetTexelCountInCopyRegion(
|
||||||
|
copyLayout.bytesPerRow, copyLayout.bytesPerImage / copyLayout.bytesPerRow,
|
||||||
|
copySizePerSlice, kTextureFormat);
|
||||||
std::vector<RGBA8> expected(texelCountInCopyRegion);
|
std::vector<RGBA8> expected(texelCountInCopyRegion);
|
||||||
for (uint32_t slice = 0; slice < copySize.depth; ++slice) {
|
for (uint32_t slice = 0; slice < copySize.depth; ++slice) {
|
||||||
std::fill(expected.begin(), expected.end(), RGBA8());
|
std::fill(expected.begin(), expected.end(), RGBA8());
|
||||||
@ -395,6 +399,21 @@ TEST_P(CopyTests_T2B, FullTextureAligned) {
|
|||||||
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {kWidth, kHeight, 1});
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {kWidth, kHeight, 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test noop copies
|
||||||
|
TEST_P(CopyTests_T2B, ZeroSizedCopy) {
|
||||||
|
constexpr uint32_t kWidth = 256;
|
||||||
|
constexpr uint32_t kHeight = 128;
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.textureSize = {kWidth, kHeight, 1};
|
||||||
|
textureSpec.copyOrigin = {0, 0, 0};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {0, kHeight, 1});
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {kWidth, 0, 1});
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {kWidth, kHeight, 0});
|
||||||
|
}
|
||||||
|
|
||||||
// Test that copying an entire texture without 256-byte aligned dimensions works
|
// Test that copying an entire texture without 256-byte aligned dimensions works
|
||||||
TEST_P(CopyTests_T2B, FullTextureUnaligned) {
|
TEST_P(CopyTests_T2B, FullTextureUnaligned) {
|
||||||
constexpr uint32_t kWidth = 259;
|
constexpr uint32_t kWidth = 259;
|
||||||
@ -830,6 +849,21 @@ TEST_P(CopyTests_B2T, FullTextureAligned) {
|
|||||||
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {kWidth, kHeight, 1});
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {kWidth, kHeight, 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test noop copies.
|
||||||
|
TEST_P(CopyTests_B2T, ZeroSizedCopy) {
|
||||||
|
constexpr uint32_t kWidth = 256;
|
||||||
|
constexpr uint32_t kHeight = 128;
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.textureSize = {kWidth, kHeight, 1};
|
||||||
|
textureSpec.copyOrigin = {0, 0, 0};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {0, kHeight, 1});
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {kWidth, 0, 1});
|
||||||
|
DoTest(textureSpec, MinimumBufferSpec(kWidth, kHeight), {kWidth, kHeight, 0});
|
||||||
|
}
|
||||||
|
|
||||||
// Test that copying an entire texture without 256-byte aligned dimensions works
|
// Test that copying an entire texture without 256-byte aligned dimensions works
|
||||||
TEST_P(CopyTests_B2T, FullTextureUnaligned) {
|
TEST_P(CopyTests_B2T, FullTextureUnaligned) {
|
||||||
constexpr uint32_t kWidth = 259;
|
constexpr uint32_t kWidth = 259;
|
||||||
@ -1244,6 +1278,20 @@ TEST_P(CopyTests_T2T, Texture) {
|
|||||||
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test noop copies.
|
||||||
|
TEST_P(CopyTests_T2T, ZeroSizedCopy) {
|
||||||
|
constexpr uint32_t kWidth = 256;
|
||||||
|
constexpr uint32_t kHeight = 128;
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.copyOrigin = {0, 0, 0};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
textureSpec.textureSize = {kWidth, kHeight, 1};
|
||||||
|
DoTest(textureSpec, textureSpec, {0, kHeight, 1});
|
||||||
|
DoTest(textureSpec, textureSpec, {kWidth, 0, 1});
|
||||||
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 0});
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(CopyTests_T2T, TextureRegion) {
|
TEST_P(CopyTests_T2T, TextureRegion) {
|
||||||
constexpr uint32_t kWidth = 256;
|
constexpr uint32_t kWidth = 256;
|
||||||
constexpr uint32_t kHeight = 128;
|
constexpr uint32_t kHeight = 128;
|
||||||
|
@ -87,6 +87,14 @@ namespace utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t GetTexelCountInCopyRegion(uint64_t bytesPerRow,
|
||||||
|
uint64_t rowsPerImage,
|
||||||
|
wgpu::Extent3D copyExtent,
|
||||||
|
wgpu::TextureFormat textureFormat) {
|
||||||
|
return RequiredBytesInCopy(bytesPerRow, rowsPerImage, copyExtent, textureFormat) /
|
||||||
|
utils::GetTexelBlockSizeInBytes(textureFormat);
|
||||||
|
}
|
||||||
|
|
||||||
void UnalignDynamicUploader(wgpu::Device device) {
|
void UnalignDynamicUploader(wgpu::Device device) {
|
||||||
std::vector<uint8_t> data = {1};
|
std::vector<uint8_t> data = {1};
|
||||||
|
|
||||||
|
@ -46,6 +46,11 @@ namespace utils {
|
|||||||
wgpu::Extent3D copyExtent,
|
wgpu::Extent3D copyExtent,
|
||||||
wgpu::TextureFormat textureFormat);
|
wgpu::TextureFormat textureFormat);
|
||||||
|
|
||||||
|
uint64_t GetTexelCountInCopyRegion(uint64_t bytesPerRow,
|
||||||
|
uint64_t rowsPerImage,
|
||||||
|
wgpu::Extent3D copyExtent,
|
||||||
|
wgpu::TextureFormat textureFormat);
|
||||||
|
|
||||||
// A helper function used for testing DynamicUploader offset alignment.
|
// A helper function used for testing DynamicUploader offset alignment.
|
||||||
// A call of this function will do a Queue::WriteTexture with 1 byte of data,
|
// A call of this function will do a Queue::WriteTexture with 1 byte of data,
|
||||||
// so that assuming that WriteTexture uses DynamicUploader, the first RingBuffer
|
// so that assuming that WriteTexture uses DynamicUploader, the first RingBuffer
|
||||||
|
Loading…
x
Reference in New Issue
Block a user