Make DawnLoadResolveTexture compatible with TransientAttachments

Bug: dawn:1710
Change-Id: I3e740fc176083064eb7cbe9d11f04328ef705f44
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/186980
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
diff --git a/src/dawn/native/CommandEncoder.cpp b/src/dawn/native/CommandEncoder.cpp
index 62d0df0..9b84a30 100644
--- a/src/dawn/native/CommandEncoder.cpp
+++ b/src/dawn/native/CommandEncoder.cpp
@@ -552,10 +552,11 @@
     DAWN_INVALID_IF(colorAttachment.loadOp == wgpu::LoadOp::Undefined, "loadOp must be set.");
     DAWN_INVALID_IF(colorAttachment.storeOp == wgpu::StoreOp::Undefined, "storeOp must be set.");
     if (attachment->GetTexture()->GetUsage() & wgpu::TextureUsage::TransientAttachment) {
-        DAWN_INVALID_IF(colorAttachment.loadOp != wgpu::LoadOp::Clear,
+        DAWN_INVALID_IF(colorAttachment.loadOp != wgpu::LoadOp::Clear &&
+                            colorAttachment.loadOp != wgpu::LoadOp::ExpandResolveTexture,
                         "The color attachment %s has the load op set to %s while its usage (%s) "
                         "has the transient attachment bit set.",
-                        attachment, wgpu::LoadOp::Load, attachment->GetTexture()->GetUsage());
+                        attachment, colorAttachment.loadOp, attachment->GetTexture()->GetUsage());
         DAWN_INVALID_IF(colorAttachment.storeOp != wgpu::StoreOp::Discard,
                         "The color attachment %s has the store op set to %s while its usage (%s) "
                         "has the transient attachment bit set.",
diff --git a/src/dawn/tests/end2end/MultisampledRenderingTests.cpp b/src/dawn/tests/end2end/MultisampledRenderingTests.cpp
index 6811905..f7ecf3c 100644
--- a/src/dawn/tests/end2end/MultisampledRenderingTests.cpp
+++ b/src/dawn/tests/end2end/MultisampledRenderingTests.cpp
@@ -1530,6 +1530,9 @@
         if (SupportsFeatures({wgpu::FeatureName::DawnLoadResolveTexture})) {
             requiredFeatures.push_back(wgpu::FeatureName::DawnLoadResolveTexture);
         }
+        if (SupportsFeatures({wgpu::FeatureName::TransientAttachments})) {
+            requiredFeatures.push_back(wgpu::FeatureName::TransientAttachments);
+        }
         return requiredFeatures;
     }
 };
@@ -1538,9 +1541,10 @@
 // LoadOp::ExpandResolveTexture. The resolve texture will have its content preserved between
 // passes.
 TEST_P(DawnLoadResolveTextureTest, DrawThenLoad) {
-    auto multiSampledTexture =
-        CreateTextureForRenderAttachment(kColorFormat, 4, 1, 1, /*transientAttachment=*/false,
-                                         /*supportsTextureBinding=*/false);
+    auto multiSampledTexture = CreateTextureForRenderAttachment(
+        kColorFormat, 4, 1, 1,
+        /*transientAttachment=*/device.HasFeature(wgpu::FeatureName::TransientAttachments),
+        /*supportsTextureBinding=*/false);
     auto multiSampledTextureView = multiSampledTexture.CreateView();
 
     auto singleSampledTexture =
@@ -1572,6 +1576,7 @@
             {multiSampledTextureView}, {singleSampledTextureView},
             wgpu::LoadOp::ExpandResolveTexture, wgpu::LoadOp::Load,
             /*testDepth=*/false);
+        renderPass.cColorAttachments[0].storeOp = wgpu::StoreOp::Discard;
         wgpu::RenderPassEncoder renderPassEncoder = commandEncoder.BeginRenderPass(&renderPass);
         renderPassEncoder.End();
     }
diff --git a/src/dawn/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp b/src/dawn/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
index 0be2ef0..50a97a9 100644
--- a/src/dawn/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
@@ -1830,9 +1830,11 @@
   protected:
     WGPUDevice CreateTestDevice(dawn::native::Adapter dawnAdapter,
                                 wgpu::DeviceDescriptor descriptor) override {
-        wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::DawnLoadResolveTexture};
+        wgpu::FeatureName requiredFeatures[2] = {wgpu::FeatureName::DawnLoadResolveTexture,
+                                                 wgpu::FeatureName::TransientAttachments};
         descriptor.requiredFeatures = requiredFeatures;
-        descriptor.requiredFeatureCount = 1;
+        descriptor.requiredFeatureCount = 2;
+
         return dawnAdapter.CreateDevice(&descriptor);
     }
 
@@ -1862,6 +1864,25 @@
     AssertBeginRenderPassSuccess(&renderPass);
 }
 
+// Test that LoadOp::ExpandResolveTexture can be used even if the MSAA attachment is transient.
+TEST_F(DawnLoadResolveTextureValidationTest, CompatibleWithTransientMSAATexture) {
+    auto multisampledColorTexture = CreateTexture(
+        device, wgpu::TextureDimension::e2D, kColorFormat, kSize, kSize, kArrayLayers, kLevelCount,
+        /*sampleCount=*/kSampleCount,
+        wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TransientAttachment);
+    auto multisampledColorTextureView = multisampledColorTexture.CreateView();
+
+    // Create a resolve texture with sample count = 1.
+    auto resolveTarget = CreateCompatibleResolveTextureView();
+
+    auto renderPass = CreateMultisampledRenderPass();
+    renderPass.cColorAttachments[0].view = multisampledColorTextureView;
+    renderPass.cColorAttachments[0].resolveTarget = resolveTarget;
+    renderPass.cColorAttachments[0].loadOp = wgpu::LoadOp::ExpandResolveTexture;
+    renderPass.cColorAttachments[0].storeOp = wgpu::StoreOp::Discard;
+    AssertBeginRenderPassSuccess(&renderPass);
+}
+
 // When LoadOp::ExpandResolveTexture is used, a resolve texture view must be set.
 TEST_F(DawnLoadResolveTextureValidationTest, ResolveTargetMustBeSet) {
     auto multisampledColorTextureView = CreateMultisampledColorTextureView();