diff --git a/src/dawn/native/CommandValidation.cpp b/src/dawn/native/CommandValidation.cpp index 4fd7a607a2..44fbdf8582 100644 --- a/src/dawn/native/CommandValidation.cpp +++ b/src/dawn/native/CommandValidation.cpp @@ -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 {}; } diff --git a/src/dawn/tests/end2end/DepthStencilCopyTests.cpp b/src/dawn/tests/end2end/DepthStencilCopyTests.cpp index 2dfd8e585a..f037555966 100644 --- a/src/dawn/tests/end2end/DepthStencilCopyTests.cpp +++ b/src/dawn/tests/end2end/DepthStencilCopyTests.cpp @@ -31,6 +31,10 @@ namespace { wgpu::TextureFormat::Depth32Float, wgpu::TextureFormat::Depth32FloatStencil8, }; + + constexpr std::array kValidDepthCopyFromBufferFormats = { + wgpu::TextureFormat::Depth16Unorm, + }; } // namespace class DepthStencilCopyTests : public DawnTestWithParams { @@ -240,6 +244,16 @@ class DepthStencilCopyTests : public DawnTestWithParams(kInitDepth); + std::vector 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 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(kValidDepthCopyTextureFormats.begin(), kValidDepthCopyTextureFormats.end())); +DAWN_INSTANTIATE_TEST_P(DepthCopyFromBufferTests, + {D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), + VulkanBackend()}, + std::vector(kValidDepthCopyFromBufferFormats.begin(), + kValidDepthCopyFromBufferFormats.end())); + DAWN_INSTANTIATE_TEST_P(StencilCopyTests, {D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()}, diff --git a/src/dawn/tests/unittests/validation/CopyCommandsValidationTests.cpp b/src/dawn/tests/unittests/validation/CopyCommandsValidationTests.cpp index 825717122f..a7d26f1d7e 100644 --- a/src/dawn/tests/unittests/validation/CopyCommandsValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/CopyCommandsValidationTests.cpp @@ -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, 3> params = { + // are implemented, e.g. Stencil8. + std::array, 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 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 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, 6> params = { + // are implemented, e.g. Stencil8. + std::array, 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),