Compat: Fix GL queue.writeTexture impl

Set GL_UNPACK_ALIGNMENT to blockInfo.byteSize during writeTexture.

Expand QueueWriteTextureTests for R8Unorm and RG8Unorm.

This fix should fix some copyTextureToTexture and image_copy
CTS failures.

Bug: dawn:2208, dawn:2209
Change-Id: Ic3f94d96d4082281321d97e069950da96311fdd4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/160721
Reviewed-by: Stephen White <senorblanco@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Shrek Shao <shrekshao@google.com>
diff --git a/src/dawn/native/opengl/CommandBufferGL.cpp b/src/dawn/native/opengl/CommandBufferGL.cpp
index be89cf9..4b304da 100644
--- a/src/dawn/native/opengl/CommandBufferGL.cpp
+++ b/src/dawn/native/opengl/CommandBufferGL.cpp
@@ -1456,6 +1456,8 @@
         uint32_t width = copySize.width;
         uint32_t height = copySize.height;
         if (dataLayout.bytesPerRow % blockInfo.byteSize == 0) {
+            // Valid values for GL_UNPACK_ALIGNMENT are 1, 2, 4, 8
+            gl.PixelStorei(GL_UNPACK_ALIGNMENT, std::min(8u, blockInfo.byteSize));
             gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
                            dataLayout.bytesPerRow / blockInfo.byteSize * blockInfo.width);
             if (texture->GetArrayLayers() == 1 && Is1DOr2D(texture->GetDimension())) {
@@ -1468,6 +1470,7 @@
                 gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
             }
             gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+            gl.PixelStorei(GL_UNPACK_ALIGNMENT, 4);  // Reset to default
         } else {
             if (texture->GetArrayLayers() == 1 && Is1DOr2D(texture->GetDimension())) {
                 const uint8_t* d = static_cast<const uint8_t*>(data);
diff --git a/src/dawn/tests/end2end/QueueTests.cpp b/src/dawn/tests/end2end/QueueTests.cpp
index d281298..446a917 100644
--- a/src/dawn/tests/end2end/QueueTests.cpp
+++ b/src/dawn/tests/end2end/QueueTests.cpp
@@ -227,10 +227,13 @@
 // For MinimumDataSpec bytesPerRow and rowsPerImage, compute a default from the copy extent.
 constexpr uint32_t kStrideComputeDefault = 0xFFFF'FFFEul;
 
-class QueueWriteTextureTests : public DawnTest {
-  protected:
-    static constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::RGBA8Unorm;
+namespace {
+using TextureFormat = wgpu::TextureFormat;
+DAWN_TEST_PARAM_STRUCT(WriteTextureFormatParams, TextureFormat);
+}  // namespace
 
+class QueueWriteTextureTests : public DawnTestWithParams<WriteTextureFormatParams> {
+  protected:
     struct TextureSpec {
         wgpu::Origin3D copyOrigin;
         wgpu::Extent3D textureSize;
@@ -247,7 +250,8 @@
     static DataSpec MinimumDataSpec(wgpu::Extent3D writeSize,
                                     uint32_t overrideBytesPerRow = kStrideComputeDefault,
                                     uint32_t overrideRowsPerImage = kStrideComputeDefault) {
-        uint32_t bytesPerRow = writeSize.width * utils::GetTexelBlockSizeInBytes(kTextureFormat);
+        uint32_t bytesPerRow =
+            writeSize.width * utils::GetTexelBlockSizeInBytes(GetParam().mTextureFormat);
         if (overrideBytesPerRow != kStrideComputeDefault) {
             bytesPerRow = overrideBytesPerRow;
         }
@@ -256,8 +260,8 @@
             rowsPerImage = overrideRowsPerImage;
         }
 
-        uint32_t totalDataSize =
-            utils::RequiredBytesInCopy(bytesPerRow, rowsPerImage, writeSize, kTextureFormat);
+        uint32_t totalDataSize = utils::RequiredBytesInCopy(bytesPerRow, rowsPerImage, writeSize,
+                                                            GetParam().mTextureFormat);
         return {totalDataSize, 0, bytesPerRow, rowsPerImage};
     }
 
@@ -265,15 +269,17 @@
                                 uint32_t width,
                                 uint32_t height,
                                 uint32_t srcBytesPerRow,
-                                utils::RGBA8* dstData,
-                                uint32_t dstTexelPerRow,
-                                uint32_t texelBlockSize) {
+                                uint8_t* dstData,
+                                uint32_t dstBytesPerRow,
+                                uint32_t bytesPerTexel) {
         for (uint64_t y = 0; y < height; ++y) {
             for (uint64_t x = 0; x < width; ++x) {
-                uint64_t src = x * texelBlockSize + y * srcBytesPerRow;
-                uint64_t dst = x + y * dstTexelPerRow;
+                uint64_t src = x * bytesPerTexel + y * srcBytesPerRow;
+                uint64_t dst = x * bytesPerTexel + y * dstBytesPerRow;
 
-                dstData[dst] = {srcData[src], srcData[src + 1], srcData[src + 2], srcData[src + 3]};
+                for (uint64_t i = 0; i < bytesPerTexel; i++) {
+                    dstData[dst + i] = srcData[src + i];
+                }
             }
         }
     }
@@ -295,7 +301,7 @@
         wgpu::TextureDescriptor descriptor = {};
         descriptor.dimension = wgpu::TextureDimension::e2D;
         descriptor.size = textureSpec.textureSize;
-        descriptor.format = kTextureFormat;
+        descriptor.format = GetParam().mTextureFormat;
         descriptor.mipLevelCount = textureSpec.level + 1;
         descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc;
         wgpu::Texture texture = device.CreateTexture(&descriptor);
@@ -309,7 +315,7 @@
         queue.WriteTexture(&imageCopyTexture, data.data(), dataSpec.size, &textureDataLayout,
                            &copySize);
 
-        const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(kTextureFormat);
+        const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(GetParam().mTextureFormat);
         wgpu::Extent3D mipSize = {textureSpec.textureSize.width >> textureSpec.level,
                                   textureSpec.textureSize.height >> textureSpec.level,
                                   textureSpec.textureSize.depthOrArrayLayers};
@@ -325,18 +331,21 @@
         const uint32_t maxArrayLayer = textureSpec.copyOrigin.z + copySize.depthOrArrayLayers;
 
         uint64_t dataOffset = dataSpec.offset;
-        const uint32_t texelCountLastLayer =
-            (alignedBytesPerRow / bytesPerTexel) * (mipSize.height - 1) + mipSize.width;
+        const uint32_t byteSizeLastLayer =
+            alignedBytesPerRow * (mipSize.height - 1) + mipSize.width * bytesPerTexel;
+
         for (uint32_t slice = textureSpec.copyOrigin.z; slice < maxArrayLayer; ++slice) {
             // Pack the data in the specified copy region to have the same
             // format as the expected texture data.
-            std::vector<utils::RGBA8> expected(texelCountLastLayer);
+            std::vector<uint8_t> expected(byteSizeLastLayer, 0);
             PackTextureData(data.data() + dataOffset, copySize.width, copySize.height,
-                            dataSpec.bytesPerRow, expected.data(), copySize.width, bytesPerTexel);
+                            dataSpec.bytesPerRow, expected.data(), copySize.width * bytesPerTexel,
+                            bytesPerTexel);
 
             EXPECT_TEXTURE_EQ(expected.data(), texture,
                               {textureSpec.copyOrigin.x, textureSpec.copyOrigin.y, slice},
-                              {copySize.width, copySize.height}, textureSpec.level)
+                              {copySize.width, copySize.height, 1}, descriptor.format,
+                              static_cast<uint8_t>(0), textureSpec.level)
                 << "Write to texture failed copying " << dataSpec.size << "-byte data with offset "
                 << dataSpec.offset << " and bytes per row " << dataSpec.bytesPerRow << " to [("
                 << textureSpec.copyOrigin.x << ", " << textureSpec.copyOrigin.y << "), ("
@@ -551,7 +560,7 @@
 
     for (unsigned int b : {1, 2, 3, 4}) {
         uint32_t bytesPerRow =
-            copyExtent.width * utils::GetTexelBlockSizeInBytes(kTextureFormat) + b;
+            copyExtent.width * utils::GetTexelBlockSizeInBytes(GetParam().mTextureFormat) + b;
         DoTest(textureSpec, MinimumDataSpec(copyExtent, bytesPerRow), copyExtent);
     }
 }
@@ -596,7 +605,7 @@
     // Test with bytesPerRow divisible by blockWidth
     for (unsigned int b : {1, 2, 3, 65, 300}) {
         uint32_t bytesPerRow =
-            (copyExtent.width + b) * utils::GetTexelBlockSizeInBytes(kTextureFormat);
+            (copyExtent.width + b) * utils::GetTexelBlockSizeInBytes(GetParam().mTextureFormat);
         uint32_t rowsPerImage = 23;
         DoTest(textureSpec, MinimumDataSpec(copyExtent, bytesPerRow, rowsPerImage), copyExtent);
     }
@@ -604,7 +613,7 @@
     // Test with bytesPerRow not divisible by blockWidth
     for (unsigned int b : {1, 2, 3, 19, 301}) {
         uint32_t bytesPerRow =
-            copyExtent.width * utils::GetTexelBlockSizeInBytes(kTextureFormat) + b;
+            copyExtent.width * utils::GetTexelBlockSizeInBytes(GetParam().mTextureFormat) + b;
         uint32_t rowsPerImage = 23;
         DoTest(textureSpec, MinimumDataSpec(copyExtent, bytesPerRow, rowsPerImage), copyExtent);
     }
@@ -807,17 +816,19 @@
                       wgpu::TextureAspect::StencilOnly);
 }
 
-DAWN_INSTANTIATE_TEST(QueueWriteTextureTests,
-                      D3D11Backend(),
-                      D3D12Backend(),
-                      D3D12Backend({"d3d12_use_temp_buffer_in_depth_stencil_texture_and_buffer_"
-                                    "copy_with_non_zero_buffer_offset"}),
-                      MetalBackend(),
-                      MetalBackend({"use_blit_for_buffer_to_depth_texture_copy",
-                                    "use_blit_for_buffer_to_stencil_texture_copy"}),
-                      OpenGLBackend(),
-                      OpenGLESBackend(),
-                      VulkanBackend());
+DAWN_INSTANTIATE_TEST_P(QueueWriteTextureTests,
+                        {D3D11Backend(), D3D12Backend(),
+                         D3D12Backend({"d3d12_use_temp_buffer_in_depth_stencil_texture_and_buffer_"
+                                       "copy_with_non_zero_buffer_offset"}),
+                         MetalBackend(),
+                         MetalBackend({"use_blit_for_buffer_to_depth_texture_copy",
+                                       "use_blit_for_buffer_to_stencil_texture_copy"}),
+                         OpenGLBackend(), OpenGLESBackend(), VulkanBackend()},
+                        {
+                            wgpu::TextureFormat::R8Unorm,
+                            wgpu::TextureFormat::RG8Unorm,
+                            wgpu::TextureFormat::RGBA8Unorm,
+                        });
 
 }  // anonymous namespace
 }  // namespace dawn