Allow CopyBufferToTexture with Depth16Unorm

Removes the validation logic that was blocking this copy from being
valid and update tests to ensure that it works properly.

Copy logic worked with this format as-is, so no updates were necessary.

Bug: dawn:1251
Change-Id: Id0ca503ed0f82e79e75f63ad6870389f7f647d22
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/81024
Reviewed-by: Shrek Shao <shrekshao@google.com>
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Brandon Jones 2022-03-18 20:40:08 +00:00 committed by Dawn LUCI CQ
parent f607280a62
commit 39c2029063
3 changed files with 130 additions and 8 deletions

View File

@ -386,8 +386,17 @@ namespace dawn::native {
MaybeError ValidateLinearToDepthStencilCopyRestrictions(const ImageCopyTexture& dst) {
Aspect aspectUsed;
DAWN_TRY_ASSIGN(aspectUsed, SingleAspectUsedByImageCopyTexture(dst));
DAWN_INVALID_IF(aspectUsed == Aspect::Depth, "Cannot copy into the depth aspect of %s.",
dst.texture);
const Format& format = dst.texture->GetFormat();
switch (format.format) {
case wgpu::TextureFormat::Depth16Unorm:
return {};
default:
DAWN_INVALID_IF(aspectUsed == Aspect::Depth,
"Cannot copy into the depth aspect of %s with format %s.",
dst.texture, format.format);
break;
}
return {};
}

View File

@ -31,6 +31,10 @@ namespace {
wgpu::TextureFormat::Depth32Float,
wgpu::TextureFormat::Depth32FloatStencil8,
};
constexpr std::array<wgpu::TextureFormat, 1> kValidDepthCopyFromBufferFormats = {
wgpu::TextureFormat::Depth16Unorm,
};
} // namespace
class DepthStencilCopyTests : public DawnTestWithParams<DepthStencilCopyTestParams> {
@ -240,6 +244,16 @@ class DepthStencilCopyTests : public DawnTestWithParams<DepthStencilCopyTestPara
return dst;
}
uint32_t BufferSizeForTextureCopy(
uint32_t width,
uint32_t height,
uint32_t depth,
wgpu::TextureFormat format = wgpu::TextureFormat::RGBA8Unorm) {
uint32_t bytesPerPixel = utils::GetTexelBlockSizeInBytes(format);
uint32_t bytesPerRow = Align(width * bytesPerPixel, kTextureBytesPerRowAlignment);
return (bytesPerRow * (height - 1) + width * bytesPerPixel) * depth;
}
wgpu::ShaderModule mVertexModule;
private:
@ -522,6 +536,72 @@ TEST_P(DepthCopyTests, FromNonZeroMipDepthAspect) {
}
}
class DepthCopyFromBufferTests : public DepthStencilCopyTests {};
// Test copying the depth-only aspect from a buffer.
TEST_P(DepthCopyFromBufferTests, BufferToDepthAspect) {
// TODO(crbug.com/dawn/1237): Depth16Unorm test failed on OpenGL and OpenGLES which says
// Invalid format and type combination in glReadPixels
DAWN_TEST_UNSUPPORTED_IF(GetParam().mTextureFormat == wgpu::TextureFormat::Depth16Unorm &&
(IsOpenGL() || IsOpenGLES()));
constexpr uint32_t kWidth = 8;
constexpr uint32_t kHeight = 1;
wgpu::Texture destTexture =
CreateTexture(kWidth, kHeight, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
wgpu::BufferDescriptor descriptor;
descriptor.size = BufferSizeForTextureCopy(kWidth, kHeight, 1, GetParam().mTextureFormat);
descriptor.usage = wgpu::BufferUsage::CopySrc;
descriptor.mappedAtCreation = true;
wgpu::Buffer srcBuffer = device.CreateBuffer(&descriptor);
wgpu::ImageCopyBuffer imageCopyBuffer =
utils::CreateImageCopyBuffer(srcBuffer, 0, 256, kHeight);
wgpu::ImageCopyTexture imageCopyTexture =
utils::CreateImageCopyTexture(destTexture, 0, {0, 0, 0}, wgpu::TextureAspect::DepthOnly);
wgpu::Extent3D extent = {kWidth, kHeight, 1};
constexpr float kInitDepth = 0.2f;
// This expectation is the test as it performs the CopyTextureToBuffer.
if (GetParam().mTextureFormat == wgpu::TextureFormat::Depth16Unorm) {
uint16_t expected = FloatToUnorm<uint16_t>(kInitDepth);
std::vector<uint16_t> expectedData = {
0, 0, expected, expected, 0, 0, expected, expected,
};
size_t expectedSize = expectedData.size() * sizeof(uint16_t);
memcpy(srcBuffer.GetMappedRange(0, expectedSize), expectedData.data(), expectedSize);
srcBuffer.Unmap();
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyTexture, &extent);
wgpu::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
EXPECT_TEXTURE_EQ(expectedData.data(), destTexture, {0, 0}, {kWidth, kHeight}, 0,
wgpu::TextureAspect::DepthOnly);
} else {
std::vector<float> expectedData = {
0.0, 0.0, kInitDepth, kInitDepth, 0.0, 0.0, kInitDepth, kInitDepth,
};
size_t expectedSize = expectedData.size() * sizeof(float);
memcpy(srcBuffer.GetMappedRange(0, expectedSize), expectedData.data(), expectedSize);
srcBuffer.Unmap();
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyTexture, &extent);
wgpu::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
EXPECT_TEXTURE_EQ(expectedData.data(), destTexture, {0, 0}, {kWidth, kHeight}, 0,
wgpu::TextureAspect::DepthOnly);
}
}
class StencilCopyTests : public DepthStencilCopyTests {};
// Test copying the stencil-only aspect into a buffer.
@ -696,6 +776,12 @@ DAWN_INSTANTIATE_TEST_P(DepthCopyTests,
std::vector<wgpu::TextureFormat>(kValidDepthCopyTextureFormats.begin(),
kValidDepthCopyTextureFormats.end()));
DAWN_INSTANTIATE_TEST_P(DepthCopyFromBufferTests,
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
VulkanBackend()},
std::vector<wgpu::TextureFormat>(kValidDepthCopyFromBufferFormats.begin(),
kValidDepthCopyFromBufferFormats.end()));
DAWN_INSTANTIATE_TEST_P(StencilCopyTests,
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
VulkanBackend()},

View File

@ -715,8 +715,10 @@ TEST_F(CopyCommandTest_B2T, IncorrectBufferOffsetForColorTexture) {
// Test B2T copies with incorrect buffer offset usage for depth-stencil texture
TEST_F(CopyCommandTest_B2T, IncorrectBufferOffsetForDepthStencilTexture) {
// TODO(dawn:570, dawn:666): List other valid parameters after missing texture formats
// are implemented, e.g. Stencil8 and depth16unorm.
std::array<std::tuple<wgpu::TextureFormat, wgpu::TextureAspect>, 3> params = {
// are implemented, e.g. Stencil8.
std::array<std::tuple<wgpu::TextureFormat, wgpu::TextureAspect>, 5> params = {
std::make_tuple(wgpu::TextureFormat::Depth16Unorm, wgpu::TextureAspect::DepthOnly),
std::make_tuple(wgpu::TextureFormat::Depth16Unorm, wgpu::TextureAspect::All),
std::make_tuple(wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureAspect::StencilOnly),
std::make_tuple(wgpu::TextureFormat::Depth24UnormStencil8,
wgpu::TextureAspect::StencilOnly),
@ -866,12 +868,35 @@ TEST_F(CopyCommandTest_B2T, CopyToMipmapOfNonSquareTexture) {
{0, 0, 0}, {2, 2, 1});
}
// Test it is invalid to copy to a depth texture
// Test whether or not it is valid to copy to a depth texture
TEST_F(CopyCommandTest_B2T, CopyToDepthAspect) {
uint64_t bufferSize = BufferSizeForTextureCopy(16, 16, 1, wgpu::TextureFormat::Depth32Float);
wgpu::Buffer source = CreateBuffer(bufferSize, wgpu::BufferUsage::CopySrc);
for (wgpu::TextureFormat format : utils::kDepthFormats) {
constexpr std::array<wgpu::TextureFormat, 1> kAllowBufferToDepthCopyFormats = {
wgpu::TextureFormat::Depth16Unorm};
for (wgpu::TextureFormat format : kAllowBufferToDepthCopyFormats) {
wgpu::Texture destination =
Create2DTexture(16, 16, 1, 1, format, wgpu::TextureUsage::CopyDst);
// Test it is valid to copy this format from a buffer into a depth texture
TestB2TCopy(utils::Expectation::Success, source, 0, 256, 16, destination, 0, {0, 0, 0},
{16, 16, 1}, wgpu::TextureAspect::DepthOnly);
if (utils::IsDepthOnlyFormat(format)) {
// Test "all" of a depth texture which is only the depth aspect.
TestB2TCopy(utils::Expectation::Success, source, 0, 256, 16, destination, 0, {0, 0, 0},
{16, 16, 1}, wgpu::TextureAspect::All);
}
}
constexpr std::array<wgpu::TextureFormat, 5> kDisallowBufferToDepthCopyFormats = {
wgpu::TextureFormat::Depth32Float, wgpu::TextureFormat::Depth24Plus,
wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureFormat::Depth24UnormStencil8,
wgpu::TextureFormat::Depth32FloatStencil8,
};
for (wgpu::TextureFormat format : kDisallowBufferToDepthCopyFormats) {
wgpu::Texture destination =
Create2DTexture(16, 16, 1, 1, format, wgpu::TextureUsage::CopyDst);
@ -1325,8 +1350,10 @@ TEST_F(CopyCommandTest_T2B, IncorrectBufferOffsetForColorTexture) {
// Test T2B copies with incorrect buffer offset usage for depth-stencil texture
TEST_F(CopyCommandTest_T2B, IncorrectBufferOffsetForDepthStencilTexture) {
// TODO(dawn:570, dawn:666): List other valid parameters after missing texture formats
// are implemented, e.g. Stencil8 and depth16unorm.
std::array<std::tuple<wgpu::TextureFormat, wgpu::TextureAspect>, 6> params = {
// are implemented, e.g. Stencil8.
std::array<std::tuple<wgpu::TextureFormat, wgpu::TextureAspect>, 8> params = {
std::make_tuple(wgpu::TextureFormat::Depth16Unorm, wgpu::TextureAspect::DepthOnly),
std::make_tuple(wgpu::TextureFormat::Depth16Unorm, wgpu::TextureAspect::All),
std::make_tuple(wgpu::TextureFormat::Depth24PlusStencil8, wgpu::TextureAspect::StencilOnly),
std::make_tuple(wgpu::TextureFormat::Depth32Float, wgpu::TextureAspect::DepthOnly),
std::make_tuple(wgpu::TextureFormat::Depth32Float, wgpu::TextureAspect::All),