D3D12: Use same format for null RTV in render pass and unused RTV in PSO

This patch uses same format (currently RGBA8Unorm) as the DXGI format
of both null RTV used in render pass and unused RTV when creating render
pipeline state object. Without this patch D3D12 debug layer will generate
below error message when we use a PSO that uses RTV at slot 1 and remain
empty at slot 0 in a D3D12 render pass:

The current render pass binds a different render target format compared
to what the pipeline state object describes. Render pass is predicted to
bind DXGI_FORMAT_R8G8B8A8_UNORM at [0], but PSO describes
DXGI_FORMAT_UNKNOWN at [0]. [ EXECUTION ERROR #1170: RENDER_PASS_ERROR]

Bug: chromium:381742470
Test: dawn_end2end_tests
Change-Id: I437211babe5492b821280cb97408b33a8d10d5ad
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/218074
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/src/dawn/native/d3d12/CommandBufferD3D12.cpp b/src/dawn/native/d3d12/CommandBufferD3D12.cpp
index 8c9fd6a..64bd74f 100644
--- a/src/dawn/native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn/native/d3d12/CommandBufferD3D12.cpp
@@ -1407,7 +1407,7 @@
                     device->GetRenderTargetViewAllocator()->AllocateTransientCPUDescriptors());
                 nullRTV = nullRTVAllocation.GetBaseDescriptor();
                 D3D12_RENDER_TARGET_VIEW_DESC nullRTVDesc;
-                nullRTVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+                nullRTVDesc.Format = GetNullRTVDXGIFormatForD3D12RenderPass();
                 nullRTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
                 nullRTVDesc.Texture2D.MipSlice = 0;
                 nullRTVDesc.Texture2D.PlaneSlice = 0;
diff --git a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
index 7fd9e76..a517dc3 100644
--- a/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
+++ b/src/dawn/native/d3d12/RenderPipelineD3D12.cpp
@@ -404,11 +404,15 @@
     }
 
     static_assert(kMaxColorAttachments == 8);
+    auto highestColorAttachmentIndexPlusOne = GetHighestBitIndexPlusOne(GetColorAttachmentsMask());
     for (uint8_t i = 0; i < kMaxColorAttachments; i++) {
-        descriptorD3D12.RTVFormats[i] = DXGI_FORMAT_UNKNOWN;
+        if (i < static_cast<uint8_t>(highestColorAttachmentIndexPlusOne)) {
+            descriptorD3D12.RTVFormats[i] = GetNullRTVDXGIFormatForD3D12RenderPass();
+        } else {
+            descriptorD3D12.RTVFormats[i] = DXGI_FORMAT_UNKNOWN;
+        }
         descriptorD3D12.BlendState.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_NOOP;
     }
-    auto highestColorAttachmentIndexPlusOne = GetHighestBitIndexPlusOne(GetColorAttachmentsMask());
     for (auto i : IterateBitSet(GetColorAttachmentsMask())) {
         descriptorD3D12.RTVFormats[static_cast<uint8_t>(i)] =
             d3d::DXGITextureFormat(device, GetColorAttachmentFormat(i));
diff --git a/src/dawn/native/d3d12/UtilsD3D12.h b/src/dawn/native/d3d12/UtilsD3D12.h
index ec0b7c8..8682c4d 100644
--- a/src/dawn/native/d3d12/UtilsD3D12.h
+++ b/src/dawn/native/d3d12/UtilsD3D12.h
@@ -72,6 +72,10 @@
 
 void SetDebugName(Device* device, ID3D12Object* object, const char* prefix, std::string label = "");
 
+constexpr DXGI_FORMAT GetNullRTVDXGIFormatForD3D12RenderPass() {
+    return DXGI_FORMAT_R8G8B8A8_UNORM;
+}
+
 }  // namespace dawn::native::d3d12
 
 #endif  // SRC_DAWN_NATIVE_D3D12_UTILSD3D12_H_