From 3c797eba3b555405f9b16ad5bc0a17a2c28c223c Mon Sep 17 00:00:00 2001 From: Jiawei Shao Date: Wed, 3 Aug 2022 15:54:35 +0000 Subject: [PATCH] Add tests about clearing with big integer values This patch adds several dawn_end2end_tests as a preparation to support clearing color attachments with arbitrary 32-bit integer values on D3D12. Bug: dawn:537 Test: dawn_end2end_tests Change-Id: I5e5232d4ebb2ed0e0da007fea101ed13f972ce9e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/98103 Commit-Queue: Jiawei Shao Reviewed-by: Corentin Wallez Kokoro: Kokoro Reviewed-by: Austin Eng --- .../tests/end2end/RenderPassLoadOpTests.cpp | 219 ++++++++++++++++++ 1 file changed, 219 insertions(+) diff --git a/src/dawn/tests/end2end/RenderPassLoadOpTests.cpp b/src/dawn/tests/end2end/RenderPassLoadOpTests.cpp index cc989a7401..5a2dce9ad8 100644 --- a/src/dawn/tests/end2end/RenderPassLoadOpTests.cpp +++ b/src/dawn/tests/end2end/RenderPassLoadOpTests.cpp @@ -497,6 +497,225 @@ TEST_P(RenderPassLoadOpTests, LoadOpClearNormalizedFormatsOutOfBound) { } } +// Test clearing multiple color attachments with different big integers can still work correctly. +TEST_P(RenderPassLoadOpTests, LoadOpClearWithBigInt32ValuesOnMultipleColorAttachments) { + // TODO(http://crbug.com/dawn/537): Implemement a workaround to enable clearing integer formats + // to large values on D3D12. + DAWN_SUPPRESS_TEST_IF(IsD3D12()); + + // TODO(crbug.com/dawn/1109): Re-enable once fixed on Mac Mini 8,1s w/ 11.5. + DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel() && IsMacOS(11, 5)); + + // TODO(crbug.com/dawn/1463): Re-enable, might be the same as above just on + // 12.4 instead of 11.5. + DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel() && IsMacOS(12, 4)); + + constexpr int32_t kMaxInt32RepresentableInFloat = 1 << std::numeric_limits::digits; + constexpr int32_t kMinInt32RepresentableInFloat = -kMaxInt32RepresentableInFloat; + + using TestCase = std::tuple>; + + constexpr std::array kTestCases = {{ + {wgpu::TextureFormat::R32Sint, + {kMaxInt32RepresentableInFloat, 0, 0, 0}, + {kMaxInt32RepresentableInFloat, 0, 0, 0}}, + {wgpu::TextureFormat::R32Sint, + {kMaxInt32RepresentableInFloat + 1, 0, 0, 0}, + {kMaxInt32RepresentableInFloat + 1, 0, 0, 0}}, + {wgpu::TextureFormat::R32Sint, + {kMinInt32RepresentableInFloat, 0, 0, 0}, + {kMinInt32RepresentableInFloat, 0, 0, 0}}, + {wgpu::TextureFormat::R32Sint, + {kMinInt32RepresentableInFloat - 1, 0, 0, 0}, + {kMinInt32RepresentableInFloat - 1, 0, 0, 0}}, + {wgpu::TextureFormat::RG32Sint, + {kMaxInt32RepresentableInFloat, kMaxInt32RepresentableInFloat + 1, 0, 0}, + {kMaxInt32RepresentableInFloat, kMaxInt32RepresentableInFloat + 1, 0, 0}}, + {wgpu::TextureFormat::RG32Sint, + {kMinInt32RepresentableInFloat, kMinInt32RepresentableInFloat - 1, 0, 0}, + {kMinInt32RepresentableInFloat, kMinInt32RepresentableInFloat - 1, 0, 0}}, + {wgpu::TextureFormat::RGBA32Sint, + {kMaxInt32RepresentableInFloat, kMinInt32RepresentableInFloat, + kMaxInt32RepresentableInFloat + 1, kMinInt32RepresentableInFloat - 1}, + {kMaxInt32RepresentableInFloat, kMinInt32RepresentableInFloat, + kMaxInt32RepresentableInFloat + 1, kMinInt32RepresentableInFloat - 1}}, + {wgpu::TextureFormat::RGBA32Sint, + {kMaxInt32RepresentableInFloat, kMinInt32RepresentableInFloat, + kMaxInt32RepresentableInFloat - 1, kMinInt32RepresentableInFloat + 1}, + {kMaxInt32RepresentableInFloat, kMinInt32RepresentableInFloat, + kMaxInt32RepresentableInFloat - 1, kMinInt32RepresentableInFloat + 1}}, + }}; + + std::array textures; + + wgpu::TextureDescriptor textureDescriptor = {}; + textureDescriptor.size = {1, 1, 1}; + textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment; + + std::array colorAttachmentsInfo; + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { + textureDescriptor.format = std::get<0>(kTestCases[i]); + textures[i] = device.CreateTexture(&textureDescriptor); + + colorAttachmentsInfo[i].view = textures[i].CreateView(); + colorAttachmentsInfo[i].loadOp = wgpu::LoadOp::Clear; + colorAttachmentsInfo[i].storeOp = wgpu::StoreOp::Store; + colorAttachmentsInfo[i].clearValue = std::get<1>(kTestCases[i]); + } + + wgpu::RenderPassDescriptor renderPassDescriptor = {}; + renderPassDescriptor.colorAttachmentCount = kMaxColorAttachments; + renderPassDescriptor.colorAttachments = colorAttachmentsInfo.data(); + wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&renderPassDescriptor); + renderPass.End(); + + std::array outputBuffers; + for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { + wgpu::BufferDescriptor bufferDescriptor = {}; + bufferDescriptor.size = sizeof(int32_t) * 4; + bufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; + outputBuffers[i] = device.CreateBuffer(&bufferDescriptor); + + wgpu::ImageCopyTexture imageCopyTexture = + utils::CreateImageCopyTexture(textures[i], 0, {0, 0, 0}); + wgpu::ImageCopyBuffer imageCopyBuffer = + utils::CreateImageCopyBuffer(outputBuffers[i], 0, kTextureBytesPerRowAlignment); + encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, &textureDescriptor.size); + } + + wgpu::CommandBuffer commandBuffer = encoder.Finish(); + queue.Submit(1, &commandBuffer); + + for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { + const uint8_t* expected = + reinterpret_cast(std::get<2>(kTestCases[i]).data()); + EXPECT_BUFFER_U8_RANGE_EQ(expected, outputBuffers[i], 0, + sizeof(std::get<2>(kTestCases[i]))); + } +} + +// Test clearing multiple color attachments with different big unsigned integers can still work +// correctly. +TEST_P(RenderPassLoadOpTests, LoadOpClearWithBigUInt32ValuesOnMultipleColorAttachments) { + // TODO(http://crbug.com/dawn/537): Implemement a workaround to enable clearing integer formats + // to large values on D3D12. + DAWN_SUPPRESS_TEST_IF(IsD3D12()); + + // TODO(crbug.com/dawn/1109): Re-enable once fixed on Mac Mini 8,1s w/ 11.5. + DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel() && IsMacOS(11, 5)); + + // TODO(crbug.com/dawn/1463): Re-enable, might be the same as above just on + // 12.4 instead of 11.5. + DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel() && IsMacOS(12, 4)); + + constexpr int32_t kMaxUInt32RepresentableInFloat = 1 << std::numeric_limits::digits; + + using TestCase = std::tuple>; + + std::array testColorForRGBA32Float = { + kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat - 1, + kMaxUInt32RepresentableInFloat - 2, kMaxUInt32RepresentableInFloat - 3}; + std::array expectedDataForRGBA32Float; + for (uint32_t i = 0; i < expectedDataForRGBA32Float.size(); ++i) { + expectedDataForRGBA32Float[i] = *(reinterpret_cast(&testColorForRGBA32Float[i])); + } + + const std::array kTestCases = {{ + {wgpu::TextureFormat::R32Uint, + {kMaxUInt32RepresentableInFloat, 0, 0, 0}, + {kMaxUInt32RepresentableInFloat, 0, 0, 0}}, + {wgpu::TextureFormat::R32Uint, + {kMaxUInt32RepresentableInFloat + 1, 0, 0, 0}, + {kMaxUInt32RepresentableInFloat + 1, 0, 0, 0}}, + {wgpu::TextureFormat::RG32Uint, + {kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat, 0, 0}, + {kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat, 0, 0}}, + {wgpu::TextureFormat::RG32Uint, + {kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat + 1, 0, 0}, + {kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat + 1, 0, 0}}, + {wgpu::TextureFormat::RGBA32Uint, + {kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat + 1, + kMaxUInt32RepresentableInFloat - 1, kMaxUInt32RepresentableInFloat - 2}, + {kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat + 1, + kMaxUInt32RepresentableInFloat - 1, kMaxUInt32RepresentableInFloat - 2}}, + {wgpu::TextureFormat::RGBA32Sint, + {kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat - 1, + kMaxUInt32RepresentableInFloat - 2, kMaxUInt32RepresentableInFloat - 3}, + {static_cast(kMaxUInt32RepresentableInFloat), + static_cast(kMaxUInt32RepresentableInFloat - 1), + static_cast(kMaxUInt32RepresentableInFloat - 2), + static_cast(kMaxUInt32RepresentableInFloat - 3)}}, + {wgpu::TextureFormat::RGBA32Float, + {kMaxUInt32RepresentableInFloat, kMaxUInt32RepresentableInFloat - 1, + kMaxUInt32RepresentableInFloat - 2, kMaxUInt32RepresentableInFloat - 3}, + expectedDataForRGBA32Float}, + {wgpu::TextureFormat::Undefined, + {kMaxUInt32RepresentableInFloat + 1, kMaxUInt32RepresentableInFloat + 1, 0, 0}, + {0, 0, 0, 0}}, + }}; + + std::array textures; + + wgpu::TextureDescriptor textureDescriptor = {}; + textureDescriptor.size = {1, 1, 1}; + textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment; + + std::array colorAttachmentsInfo; + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { + wgpu::TextureFormat format = std::get<0>(kTestCases[i]); + if (format == wgpu::TextureFormat::Undefined) { + textures[i] = nullptr; + colorAttachmentsInfo[i].view = nullptr; + continue; + } + + textureDescriptor.format = format; + textures[i] = device.CreateTexture(&textureDescriptor); + + colorAttachmentsInfo[i].view = textures[i].CreateView(); + colorAttachmentsInfo[i].loadOp = wgpu::LoadOp::Clear; + colorAttachmentsInfo[i].storeOp = wgpu::StoreOp::Store; + colorAttachmentsInfo[i].clearValue = std::get<1>(kTestCases[i]); + } + + wgpu::RenderPassDescriptor renderPassDescriptor = {}; + renderPassDescriptor.colorAttachmentCount = kMaxColorAttachments; + renderPassDescriptor.colorAttachments = colorAttachmentsInfo.data(); + wgpu::RenderPassEncoder renderPass = encoder.BeginRenderPass(&renderPassDescriptor); + renderPass.End(); + + std::array outputBuffers; + for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { + wgpu::TextureFormat format = std::get<0>(kTestCases[i]); + if (format == wgpu::TextureFormat::Undefined) { + continue; + } + + wgpu::BufferDescriptor bufferDescriptor = {}; + bufferDescriptor.size = sizeof(int32_t) * 4; + bufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; + outputBuffers[i] = device.CreateBuffer(&bufferDescriptor); + + wgpu::ImageCopyTexture imageCopyTexture = + utils::CreateImageCopyTexture(textures[i], 0, {0, 0, 0}); + wgpu::ImageCopyBuffer imageCopyBuffer = + utils::CreateImageCopyBuffer(outputBuffers[i], 0, kTextureBytesPerRowAlignment); + encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, &textureDescriptor.size); + } + + wgpu::CommandBuffer commandBuffer = encoder.Finish(); + queue.Submit(1, &commandBuffer); + + for (uint32_t i = 0; i < kMaxColorAttachments - 1; ++i) { + const uint8_t* expected = + reinterpret_cast(std::get<2>(kTestCases[i]).data()); + EXPECT_BUFFER_U8_RANGE_EQ(expected, outputBuffers[i], 0, + sizeof(std::get<2>(kTestCases[i]))); + } +} + DAWN_INSTANTIATE_TEST(RenderPassLoadOpTests, D3D12Backend(), MetalBackend(),