Add validation on the sample count of the depth stencil attachment

This patch adds a missing validation on the sample count of the depth
stencil attachment when calling CommandEncoder.BeginRenderPass().

According to D3D SPEC, when MSAA is used, all bound render targets and
depth buffers must have the same sample count and quality.

BUG=dawn:56
TEST=dawn_unittests

Change-Id: I719995b80f89e5139711c97a4bf76ba479919ad1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/5621
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp
index d2c1543..3aae8c9 100644
--- a/src/dawn_native/CommandEncoder.cpp
+++ b/src/dawn_native/CommandEncoder.cpp
@@ -325,7 +325,8 @@
             const DeviceBase* device,
             const RenderPassDepthStencilAttachmentDescriptor* depthStencilAttachment,
             uint32_t* width,
-            uint32_t* height) {
+            uint32_t* height,
+            uint32_t* sampleCount) {
             DAWN_ASSERT(depthStencilAttachment != nullptr);
 
             DAWN_TRY(device->ValidateObject(depthStencilAttachment->attachment));
@@ -337,6 +338,12 @@
                     "depth stencil format");
             }
 
+            // *sampleCount == 0 must only happen when there is no color attachment. In that case we
+            // do not need to validate the sample count of the depth stencil attachment.
+            if (*sampleCount != 0 && (attachment->GetTexture()->GetSampleCount() != *sampleCount)) {
+                return DAWN_VALIDATION_ERROR("Depth stencil attachment sample counts mismatch");
+            }
+
             DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));
             DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height));
 
@@ -359,7 +366,7 @@
 
             if (renderPass->depthStencilAttachment != nullptr) {
                 DAWN_TRY(ValidateRenderPassDepthStencilAttachment(
-                    device, renderPass->depthStencilAttachment, width, height));
+                    device, renderPass->depthStencilAttachment, width, height, &sampleCount));
             }
 
             if (renderPass->colorAttachmentCount == 0 &&
diff --git a/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp b/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
index b8130d3..b532a95 100644
--- a/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
+++ b/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
@@ -583,6 +583,50 @@
     }
 }
 
+// Tests on the sample count of depth stencil attachment.
+TEST_F(MultisampledRenderPassDescriptorValidationTest, DepthStencilAttachmentSampleCount) {
+    constexpr dawn::TextureFormat kDepthStencilFormat = dawn::TextureFormat::D32FloatS8Uint;
+    dawn::Texture multisampledDepthStencilTexture = CreateTexture(
+        device, dawn::TextureDimension::e2D, kDepthStencilFormat, kSize, kSize, kArrayLayers,
+        kLevelCount, kSampleCount);
+    dawn::TextureView multisampledDepthStencilTextureView =
+        multisampledDepthStencilTexture.CreateDefaultTextureView();
+
+    // It is not allowed to use a depth stencil attachment whose sample count is different from the
+    // one of the color attachment.
+    {
+        dawn::Texture depthStencilTexture = CreateTexture(
+            device, dawn::TextureDimension::e2D, kDepthStencilFormat, kSize, kSize, kArrayLayers,
+            kLevelCount);
+        dawn::TextureView depthStencilTextureView = depthStencilTexture.CreateDefaultTextureView();
+
+        utils::ComboRenderPassDescriptor renderPass(
+            {CreateMultisampledColorTextureView()}, depthStencilTextureView);
+        AssertBeginRenderPassError(&renderPass);
+    }
+
+    {
+        utils::ComboRenderPassDescriptor renderPass(
+            {CreateNonMultisampledColorTextureView()}, multisampledDepthStencilTextureView);
+        AssertBeginRenderPassError(&renderPass);
+    }
+
+    // It is allowed to use a multisampled depth stencil attachment whose sample count is equal to
+    // the one of the color attachment.
+    {
+        utils::ComboRenderPassDescriptor renderPass(
+            {CreateMultisampledColorTextureView()}, multisampledDepthStencilTextureView);
+        AssertBeginRenderPassSuccess(&renderPass);
+    }
+
+    // It is allowed to use a multisampled depth stencil attachment while there is no color
+    // attachment.
+    {
+        utils::ComboRenderPassDescriptor renderPass({}, multisampledDepthStencilTextureView);
+        AssertBeginRenderPassSuccess(&renderPass);
+    }
+}
+
 // TODO(cwallez@chromium.org): Constraints on attachment aliasing?
 
 } // anonymous namespace