D3D11: Support read-only storage texture access

Bug: dawn:1972
Test: dawn_end2end_tests
Change-Id: I7cd590d6aa6e08f0e91d4856ebdb8db2630640a7
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/148182
Reviewed-by: Peng Huang <penghuang@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp b/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
index 4c3deaf..183060f 100644
--- a/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
+++ b/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
@@ -198,8 +198,8 @@
                                 d3d11UAVs.insert(d3d11UAVs.begin(), std::move(d3d11UAV));
                                 break;
                             }
-                            // TODO(dawn:1972): Support ReadOnly storage texture access
                             case wgpu::StorageTextureAccess::ReadOnly:
+                                break;
                             default:
                                 UNREACHABLE();
                                 break;
@@ -393,8 +393,23 @@
                         }
                         break;
                     }
-                    // TODO(dawn:1972): Support ReadOnly storage texture access
-                    case wgpu::StorageTextureAccess::ReadOnly:
+                    case wgpu::StorageTextureAccess::ReadOnly: {
+                        ComPtr<ID3D11ShaderResourceView> d3d11SRV;
+                        DAWN_TRY_ASSIGN(d3d11SRV, view->CreateD3D11ShaderResourceView());
+                        if (bindingVisibility & wgpu::ShaderStage::Vertex) {
+                            deviceContext1->VSSetShaderResources(bindingSlot, 1,
+                                                                 d3d11SRV.GetAddressOf());
+                        }
+                        if (bindingVisibility & wgpu::ShaderStage::Fragment) {
+                            deviceContext1->PSSetShaderResources(bindingSlot, 1,
+                                                                 d3d11SRV.GetAddressOf());
+                        }
+                        if (bindingVisibility & wgpu::ShaderStage::Compute) {
+                            deviceContext1->CSSetShaderResources(bindingSlot, 1,
+                                                                 d3d11SRV.GetAddressOf());
+                        }
+                        break;
+                    }
                     default:
                         UNREACHABLE();
                 }
@@ -519,8 +534,19 @@
                         }
                         break;
                     }
-                    // TODO(dawn:1972): Support ReadOnly storage texture access
-                    case wgpu::StorageTextureAccess::ReadOnly:
+                    case wgpu::StorageTextureAccess::ReadOnly: {
+                        ID3D11ShaderResourceView* nullSRV = nullptr;
+                        if (bindingVisibility & wgpu::ShaderStage::Vertex) {
+                            deviceContext1->VSSetShaderResources(bindingSlot, 1, &nullSRV);
+                        }
+                        if (bindingVisibility & wgpu::ShaderStage::Fragment) {
+                            deviceContext1->PSSetShaderResources(bindingSlot, 1, &nullSRV);
+                        }
+                        if (bindingVisibility & wgpu::ShaderStage::Compute) {
+                            deviceContext1->CSSetShaderResources(bindingSlot, 1, &nullSRV);
+                        }
+                        break;
+                    }
                     default:
                         UNREACHABLE();
                 }
diff --git a/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp b/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp
index b7358b4..e91ff31 100644
--- a/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp
+++ b/src/dawn/native/d3d11/PipelineLayoutD3D11.cpp
@@ -75,11 +75,18 @@
                     break;
 
                 case BindingInfoType::StorageTexture:
-                    // TODO(dawn:1972): Support ReadOnly storage texture access.
-                    ASSERT(bindingInfo.storageTexture.access !=
-                           wgpu::StorageTextureAccess::ReadOnly);
-                    mIndexInfo[group][bindingIndex] = --unorderedAccessViewIndex;
-                    mUAVBindGroups.set(group);
+                    switch (bindingInfo.storageTexture.access) {
+                        case wgpu::StorageTextureAccess::ReadWrite:
+                        case wgpu::StorageTextureAccess::WriteOnly:
+                            mIndexInfo[group][bindingIndex] = --unorderedAccessViewIndex;
+                            mUAVBindGroups.set(group);
+                            break;
+                        case wgpu::StorageTextureAccess::ReadOnly:
+                            mIndexInfo[group][bindingIndex] = shaderResourceViewIndex++;
+                            break;
+                        case wgpu::StorageTextureAccess::Undefined:
+                            UNREACHABLE();
+                    }
                     break;
             }
         }
diff --git a/src/dawn/native/d3d11/TextureD3D11.cpp b/src/dawn/native/d3d11/TextureD3D11.cpp
index 96a22a2..56dfbea 100644
--- a/src/dawn/native/d3d11/TextureD3D11.cpp
+++ b/src/dawn/native/d3d11/TextureD3D11.cpp
@@ -43,7 +43,7 @@
         bindFlags |= D3D11_BIND_SHADER_RESOURCE;
     }
     if (usage & wgpu::TextureUsage::StorageBinding) {
-        bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+        bindFlags |= D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
     }
     if (usage & wgpu::TextureUsage::RenderAttachment) {
         bindFlags |= isDepthOrStencilFormat ? D3D11_BIND_DEPTH_STENCIL : D3D11_BIND_RENDER_TARGET;
diff --git a/src/dawn/tests/end2end/StorageTextureTests.cpp b/src/dawn/tests/end2end/StorageTextureTests.cpp
index fe1d9d9..6eeebc3 100644
--- a/src/dawn/tests/end2end/StorageTextureTests.cpp
+++ b/src/dawn/tests/end2end/StorageTextureTests.cpp
@@ -1156,8 +1156,8 @@
 TEST_P(ReadWriteStorageTextureTests, ReadOnlyStorageTextureInComputeShader) {
     DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
 
-    // TODO(dawn:1972): Support read-only storage texture on D3D11, OpenGL and OpenGL ES backends.
-    DAWN_SUPPRESS_TEST_IF(IsD3D11() || IsOpenGL() || IsOpenGLES());
+    // TODO(dawn:1972): Support read-only storage texture on OpenGL and OpenGL ES backends.
+    DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
 
     constexpr wgpu::TextureFormat kStorageTextureFormat = wgpu::TextureFormat::R32Uint;
     const std::vector<uint8_t> kInitialTextureData = GetExpectedData(kStorageTextureFormat);
@@ -1214,8 +1214,8 @@
 TEST_P(ReadWriteStorageTextureTests, ReadOnlyStorageTextureInVertexShader) {
     DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
 
-    // TODO(dawn:1972): Support read-only storage texture on D3D11, OpenGL and OpenGL ES backends.
-    DAWN_SUPPRESS_TEST_IF(IsD3D11() || IsOpenGL() || IsOpenGLES());
+    // TODO(dawn:1972): Support read-only storage texture on OpenGL and OpenGL ES backends.
+    DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
 
     constexpr wgpu::TextureFormat kStorageTextureFormat = wgpu::TextureFormat::R32Uint;
     const std::vector<uint8_t> kInitialTextureData = GetExpectedData(kStorageTextureFormat);
@@ -1266,8 +1266,8 @@
 TEST_P(ReadWriteStorageTextureTests, ReadOnlyStorageTextureInFragmentShader) {
     DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
 
-    // TODO(dawn:1972): Support read-only storage texture on D3D11, OpenGL and OpenGL ES backends.
-    DAWN_SUPPRESS_TEST_IF(IsD3D11() || IsOpenGL() || IsOpenGLES());
+    // TODO(dawn:1972): Support read-only storage texture on OpenGL and OpenGL ES backends.
+    DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
 
     constexpr wgpu::TextureFormat kStorageTextureFormat = wgpu::TextureFormat::R32Uint;
     const std::vector<uint8_t> kInitialTextureData = GetExpectedData(kStorageTextureFormat);