Pipe viewFormats from ExternalImageDXGI to the texture descriptor

Bug: dawn:1470
Change-Id: I14d93d92a56e1b5c124330a992966feb1ddc0944
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112241
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/native/d3d12/ExternalImageDXGIImpl.cpp b/src/dawn/native/d3d12/ExternalImageDXGIImpl.cpp
index 5ffd1c7..b66a37a 100644
--- a/src/dawn/native/d3d12/ExternalImageDXGIImpl.cpp
+++ b/src/dawn/native/d3d12/ExternalImageDXGIImpl.cpp
@@ -38,7 +38,9 @@
       mSize(textureDescriptor->size),
       mFormat(textureDescriptor->format),
       mMipLevelCount(textureDescriptor->mipLevelCount),
-      mSampleCount(textureDescriptor->sampleCount) {
+      mSampleCount(textureDescriptor->sampleCount),
+      mViewFormats(textureDescriptor->viewFormats,
+                   textureDescriptor->viewFormats + textureDescriptor->viewFormatCount) {
     ASSERT(mBackendDevice != nullptr);
     ASSERT(mD3D12Resource != nullptr);
     ASSERT(!textureDescriptor->nextInChain || textureDescriptor->nextInChain->sType ==
@@ -84,6 +86,8 @@
     textureDescriptor.format = mFormat;
     textureDescriptor.mipLevelCount = mMipLevelCount;
     textureDescriptor.sampleCount = mSampleCount;
+    textureDescriptor.viewFormats = mViewFormats.data();
+    textureDescriptor.viewFormatCount = static_cast<uint32_t>(mViewFormats.size());
 
     DawnTextureInternalUsageDescriptor internalDesc = {};
     if (mUsageInternal != wgpu::TextureUsage::None) {
diff --git a/src/dawn/native/d3d12/ExternalImageDXGIImpl.h b/src/dawn/native/d3d12/ExternalImageDXGIImpl.h
index b3b914c..b989564 100644
--- a/src/dawn/native/d3d12/ExternalImageDXGIImpl.h
+++ b/src/dawn/native/d3d12/ExternalImageDXGIImpl.h
@@ -18,6 +18,7 @@
 #include <wrl/client.h>
 
 #include <memory>
+#include <vector>
 
 #include "dawn/common/LinkedList.h"
 #include "dawn/dawn_wsi.h"
@@ -71,6 +72,7 @@
     wgpu::TextureFormat mFormat;
     uint32_t mMipLevelCount;
     uint32_t mSampleCount;
+    std::vector<wgpu::TextureFormat> mViewFormats;
 };
 
 }  // namespace dawn::native::d3d12
diff --git a/src/dawn/tests/end2end/D3D12ResourceWrappingTests.cpp b/src/dawn/tests/end2end/D3D12ResourceWrappingTests.cpp
index 52de5d3..a60e33a 100644
--- a/src/dawn/tests/end2end/D3D12ResourceWrappingTests.cpp
+++ b/src/dawn/tests/end2end/D3D12ResourceWrappingTests.cpp
@@ -1017,6 +1017,47 @@
     EXPECT_BUFFER_U32_EQ(kExpected, buffer, 0);
 }
 
+// Test that texture descriptor view formats are passed to the backend for wrapped external
+// textures, and that contents may be reinterpreted as sRGB.
+TEST_P(D3D12SharedHandleUsageTests, SRGBReinterpretation) {
+    DAWN_TEST_UNSUPPORTED_IF(UsesWire());
+
+    wgpu::Texture texture;
+    ComPtr<ID3D11Texture2D> d3d11Texture;
+    std::unique_ptr<dawn::native::d3d12::ExternalImageDXGI> externalImage;
+
+    // The texture will be reinterpreted as sRGB.
+    wgpu::TextureViewDescriptor viewDesc = {};
+    viewDesc.format = wgpu::TextureFormat::RGBA8UnormSrgb;
+
+    wgpu::TextureDescriptor textureDesc = baseDawnDescriptor;
+    textureDesc.viewFormatCount = 1;
+    textureDesc.viewFormats = &viewDesc.format;
+    // Check that the base format is not sRGB.
+    ASSERT_EQ(textureDesc.format, wgpu::TextureFormat::RGBA8Unorm);
+
+    // Wrap a shared handle as a Dawn texture.
+    WrapSharedHandle(&textureDesc, &baseD3dDescriptor, &texture, &d3d11Texture, &externalImage);
+    ASSERT_NE(texture.Get(), nullptr);
+
+    // Submit a clear operation to sRGB value rgb(234, 51, 35).
+    {
+        utils::ComboRenderPassDescriptor renderPassDescriptor({texture.CreateView(&viewDesc)}, {});
+        renderPassDescriptor.cColorAttachments[0].clearValue = {234.0 / 255.0, 51.0 / 255.0,
+                                                                35.0 / 255.0, 1.0};
+        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+        encoder.BeginRenderPass(&renderPassDescriptor).End();
+
+        wgpu::CommandBuffer commands = encoder.Finish();
+        queue.Submit(1, &commands);
+    }
+
+    // Expect the contents to be approximately rgb(246 124 104)
+    EXPECT_PIXEL_RGBA8_BETWEEN(            //
+        utils::RGBA8(245, 123, 103, 255),  //
+        utils::RGBA8(247, 125, 105, 255), texture, 0, 0);
+}
+
 DAWN_INSTANTIATE_TEST_P(D3D12SharedHandleValidation,
                         {D3D12Backend()},
                         {SyncMode::kKeyedMutex, SyncMode::kFence});