Remove RenderPassDescriptor from BeginRenderPassCmd

This patch removes RenderPassDescriptor from BeginRenderPassCmd so that
all the backends can get the data of render pass from the non-pointer
field of BeginRenderPassCmd instead. In this patch, RenderPassDescriptor
has been removed from all Dawn backends other than the virtual function
DeviceBase::CreateRenderPassDescriptor().

This patch is one of the preparations on completely removing
RenderPassDescriptorBuilder from Dawn.

BUG=dawn:6

Change-Id: I3a78f0b2d5318c2bf85858d6fbe939b7861a2cf8
Reviewed-on: https://dawn-review.googlesource.com/c/4800
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/CommandBuffer.cpp b/src/dawn_native/CommandBuffer.cpp
index 4f72bcc..7986004 100644
--- a/src/dawn_native/CommandBuffer.cpp
+++ b/src/dawn_native/CommandBuffer.cpp
@@ -24,6 +24,7 @@
 #include "dawn_native/ErrorData.h"
 #include "dawn_native/InputState.h"
 #include "dawn_native/PipelineLayout.h"
+#include "dawn_native/RenderPassDescriptor.h"
 #include "dawn_native/RenderPassEncoder.h"
 #include "dawn_native/RenderPipeline.h"
 #include "dawn_native/Texture.h"
@@ -390,7 +391,7 @@
 
                 case Command::BeginRenderPass: {
                     BeginRenderPassCmd* cmd = mIterator.NextCommand<BeginRenderPassCmd>();
-                    DAWN_TRY(ValidateRenderPass(cmd->info.Get()));
+                    DAWN_TRY(ValidateRenderPass(cmd));
                 } break;
 
                 case Command::CopyBufferToBuffer: {
@@ -527,18 +528,19 @@
         return DAWN_VALIDATION_ERROR("Unfinished compute pass");
     }
 
-    MaybeError CommandBufferBuilder::ValidateRenderPass(RenderPassDescriptorBase* renderPass) {
+    MaybeError CommandBufferBuilder::ValidateRenderPass(BeginRenderPassCmd* renderPass) {
         PassResourceUsageTracker usageTracker;
         CommandBufferStateTracker persistentState;
 
         // Track usage of the render pass attachments
-        for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) {
-            TextureBase* texture = renderPass->GetColorAttachment(i).view->GetTexture();
+        for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+            RenderPassColorAttachmentInfo* colorAttachment = &renderPass->colorAttachments[i];
+            TextureBase* texture = colorAttachment->view->GetTexture();
             usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
         }
 
-        if (renderPass->HasDepthStencilAttachment()) {
-            TextureBase* texture = renderPass->GetDepthStencilAttachment().view->GetTexture();
+        if (renderPass->hasDepthStencilAttachment) {
+            TextureBase* texture = renderPass->depthStencilAttachment.view->GetTexture();
             usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
         }
 
@@ -667,7 +669,24 @@
 
         BeginRenderPassCmd* cmd = mAllocator.Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);
         new (cmd) BeginRenderPassCmd;
-        cmd->info = info;
+
+        for (uint32_t i : IterateBitSet(info->GetColorAttachmentMask())) {
+            const RenderPassColorAttachmentInfo& colorAttachment = info->GetColorAttachment(i);
+            if (colorAttachment.view.Get() != nullptr) {
+                cmd->colorAttachmentsSet.set(i);
+                cmd->colorAttachments[i] = colorAttachment;
+            }
+        }
+
+        cmd->hasDepthStencilAttachment = info->HasDepthStencilAttachment();
+        if (cmd->hasDepthStencilAttachment) {
+            const RenderPassDepthStencilAttachmentInfo& depthStencilAttachment =
+                info->GetDepthStencilAttachment();
+            cmd->depthStencilAttachment = depthStencilAttachment;
+        }
+
+        cmd->width = info->GetWidth();
+        cmd->height = info->GetHeight();
 
         mEncodingState = EncodingState::RenderPass;
         return new RenderPassEncoderBase(GetDevice(), this, &mAllocator);
diff --git a/src/dawn_native/CommandBuffer.h b/src/dawn_native/CommandBuffer.h
index f880324..ecf154c 100644
--- a/src/dawn_native/CommandBuffer.h
+++ b/src/dawn_native/CommandBuffer.h
@@ -29,6 +29,8 @@
 
 namespace dawn_native {
 
+    struct BeginRenderPassCmd;
+
     class BindGroupBase;
     class BufferBase;
     class FramebufferBase;
@@ -99,7 +101,7 @@
         void MoveToIterator();
 
         MaybeError ValidateComputePass();
-        MaybeError ValidateRenderPass(RenderPassDescriptorBase* renderPass);
+        MaybeError ValidateRenderPass(BeginRenderPassCmd* renderPass);
 
         MaybeError ValidateCanRecordTopLevelCommands() const;
 
diff --git a/src/dawn_native/Commands.h b/src/dawn_native/Commands.h
index cfb2a2c..afa006d 100644
--- a/src/dawn_native/Commands.h
+++ b/src/dawn_native/Commands.h
@@ -15,11 +15,15 @@
 #ifndef DAWNNATIVE_COMMANDS_H_
 #define DAWNNATIVE_COMMANDS_H_
 
-#include "dawn_native/RenderPassDescriptor.h"
+#include "common/Constants.h"
+
 #include "dawn_native/Texture.h"
 
 #include "dawn_native/dawn_platform.h"
 
+#include <array>
+#include <bitset>
+
 namespace dawn_native {
 
     // Definition of the commands that are present in the CommandIterator given by the
@@ -50,8 +54,33 @@
 
     struct BeginComputePassCmd {};
 
+    struct RenderPassColorAttachmentInfo {
+        Ref<TextureViewBase> view;
+        Ref<TextureViewBase> resolveTarget;
+        dawn::LoadOp loadOp;
+        dawn::StoreOp storeOp;
+        std::array<float, 4> clearColor = {{0.0f, 0.0f, 0.0f, 0.0f}};
+    };
+
+    struct RenderPassDepthStencilAttachmentInfo {
+        Ref<TextureViewBase> view;
+        dawn::LoadOp depthLoadOp;
+        dawn::StoreOp depthStoreOp;
+        dawn::LoadOp stencilLoadOp;
+        dawn::StoreOp stencilStoreOp;
+        float clearDepth;
+        uint32_t clearStencil;
+    };
+
     struct BeginRenderPassCmd {
-        Ref<RenderPassDescriptorBase> info;
+        std::bitset<kMaxColorAttachments> colorAttachmentsSet;
+        RenderPassColorAttachmentInfo colorAttachments[kMaxColorAttachments];
+        bool hasDepthStencilAttachment;
+        RenderPassDepthStencilAttachmentInfo depthStencilAttachment;
+
+        // Cache the width and height of all attachments for convenience
+        uint32_t width;
+        uint32_t height;
     };
 
     struct BufferCopy {
diff --git a/src/dawn_native/RenderPassDescriptor.h b/src/dawn_native/RenderPassDescriptor.h
index 5d8b322..1d9e145 100644
--- a/src/dawn_native/RenderPassDescriptor.h
+++ b/src/dawn_native/RenderPassDescriptor.h
@@ -17,6 +17,7 @@
 
 #include "common/Constants.h"
 #include "dawn_native/Builder.h"
+#include "dawn_native/Commands.h"
 #include "dawn_native/Forward.h"
 #include "dawn_native/ObjectBase.h"
 
@@ -28,20 +29,6 @@
 
 namespace dawn_native {
 
-    struct RenderPassColorAttachmentInfo {
-        dawn::LoadOp loadOp;
-        std::array<float, 4> clearColor = {{0.0f, 0.0f, 0.0f, 0.0f}};
-        Ref<TextureViewBase> view;
-    };
-
-    struct RenderPassDepthStencilAttachmentInfo {
-        dawn::LoadOp depthLoadOp;
-        dawn::LoadOp stencilLoadOp;
-        float clearDepth = 1.0f;
-        uint32_t clearStencil = 0;
-        Ref<TextureViewBase> view;
-    };
-
     // RenderPassDescriptor contains the list of attachments for a renderpass along with data such
     // as the load operation and the clear values for the attachments.
 
diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp
index 2b84042..ac544a6 100644
--- a/src/dawn_native/RenderPipeline.cpp
+++ b/src/dawn_native/RenderPipeline.cpp
@@ -15,6 +15,7 @@
 #include "dawn_native/RenderPipeline.h"
 
 #include "common/BitSetIterator.h"
+#include "dawn_native/Commands.h"
 #include "dawn_native/Device.h"
 #include "dawn_native/InputState.h"
 #include "dawn_native/RenderPassDescriptor.h"
@@ -260,30 +261,28 @@
         return mDepthStencilState.format;
     }
 
-    bool RenderPipelineBase::IsCompatibleWith(const RenderPassDescriptorBase* renderPass) const {
+    bool RenderPipelineBase::IsCompatibleWith(const BeginRenderPassCmd* renderPass) const {
         ASSERT(!IsError());
         // TODO(cwallez@chromium.org): This is called on every SetPipeline command. Optimize it for
         // example by caching some "attachment compatibility" object that would make the
         // compatibility check a single pointer comparison.
 
-        if (renderPass->GetColorAttachmentMask() != mColorAttachmentsSet) {
+        if (renderPass->colorAttachmentsSet != mColorAttachmentsSet) {
             return false;
         }
 
         for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) {
-            if (renderPass->GetColorAttachment(i).view->GetTexture()->GetFormat() !=
-                mColorStates[i].format) {
+            if (renderPass->colorAttachments[i].view->GetFormat() != mColorStates[i].format) {
                 return false;
             }
         }
 
-        if (renderPass->HasDepthStencilAttachment() != mHasDepthStencilAttachment) {
+        if (renderPass->hasDepthStencilAttachment != mHasDepthStencilAttachment) {
             return false;
         }
 
         if (mHasDepthStencilAttachment &&
-            (renderPass->GetDepthStencilAttachment().view->GetTexture()->GetFormat() !=
-             mDepthStencilState.format)) {
+            (renderPass->depthStencilAttachment.view->GetFormat() != mDepthStencilState.format)) {
             return false;
         }
 
diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h
index 0e95ced..dd87945 100644
--- a/src/dawn_native/RenderPipeline.h
+++ b/src/dawn_native/RenderPipeline.h
@@ -25,6 +25,8 @@
 
 namespace dawn_native {
 
+    struct BeginRenderPassCmd;
+
     class DeviceBase;
 
     MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
@@ -51,7 +53,7 @@
 
         // A pipeline can be used in a render pass if its attachment info matches the actual
         // attachments in the render pass. This returns whether it is the case.
-        bool IsCompatibleWith(const RenderPassDescriptorBase* renderPass) const;
+        bool IsCompatibleWith(const BeginRenderPassCmd* renderPassCmd) const;
 
       private:
         RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index d8e7429..bfaf19a 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -167,10 +167,10 @@
         }
 
         // This function must only be called before calling AllocateRTVAndDSVHeaps().
-        void TrackRenderPass(const RenderPassDescriptor* renderPass) {
+        void TrackRenderPass(const BeginRenderPassCmd* renderPass) {
             DAWN_ASSERT(mRTVHeap.Get() == nullptr && mDSVHeap.Get() == nullptr);
-            mNumRTVs += static_cast<uint32_t>(renderPass->GetColorAttachmentMask().count());
-            if (renderPass->HasDepthStencilAttachment()) {
+            mNumRTVs += static_cast<uint32_t>(renderPass->colorAttachmentsSet.count());
+            if (renderPass->hasDepthStencilAttachment) {
                 ++mNumDSVs;
             }
         }
@@ -189,14 +189,14 @@
 
         // TODO(jiawei.shao@intel.com): use hash map <RenderPass, OMSetRenderTargetArgs> as cache to
         // avoid redundant RTV and DSV memory allocations.
-        OMSetRenderTargetArgs GetSubpassOMSetRenderTargetArgs(RenderPassDescriptor* renderPass) {
+        OMSetRenderTargetArgs GetSubpassOMSetRenderTargetArgs(BeginRenderPassCmd* renderPass) {
             OMSetRenderTargetArgs args = {};
 
             unsigned int rtvIndex = 0;
-            uint32_t rtvCount = static_cast<uint32_t>(renderPass->GetColorAttachmentMask().count());
+            uint32_t rtvCount = static_cast<uint32_t>(renderPass->colorAttachmentsSet.count());
             DAWN_ASSERT(mAllocatedRTVs + rtvCount <= mNumRTVs);
-            for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) {
-                TextureView* view = ToBackend(renderPass->GetColorAttachment(i).view).Get();
+            for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+                TextureView* view = ToBackend(renderPass->colorAttachments[i].view).Get();
                 D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRTVHeap.GetCPUHandle(mAllocatedRTVs);
                 D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = view->GetRTVDescriptor();
                 mDevice->GetD3D12Device()->CreateRenderTargetView(
@@ -208,9 +208,9 @@
             }
             args.numRTVs = rtvIndex;
 
-            if (renderPass->HasDepthStencilAttachment()) {
+            if (renderPass->hasDepthStencilAttachment) {
                 DAWN_ASSERT(mAllocatedDSVs < mNumDSVs);
-                TextureView* view = ToBackend(renderPass->GetDepthStencilAttachment().view).Get();
+                TextureView* view = ToBackend(renderPass->depthStencilAttachment.view).Get();
                 D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDSVHeap.GetCPUHandle(mAllocatedDSVs);
                 D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = view->GetDSVDescriptor();
                 mDevice->GetD3D12Device()->CreateDepthStencilView(
@@ -283,7 +283,7 @@
                         } break;
                         case Command::BeginRenderPass: {
                             BeginRenderPassCmd* cmd = commands->NextCommand<BeginRenderPassCmd>();
-                            renderPassTracker->TrackRenderPass(cmd->info.Get());
+                            renderPassTracker->TrackRenderPass(cmd);
                         } break;
                         default:
                             SkipCommand(commands, type);
@@ -393,7 +393,7 @@
                     TransitionForPass(commandList, passResourceUsages[nextPassNumber]);
                     bindingTracker.SetInComputePass(false);
                     RecordRenderPass(commandList, &bindingTracker, &renderPassTracker,
-                                     ToBackend(beginRenderPassCmd->info.Get()));
+                                     beginRenderPassCmd);
 
                     nextPassNumber++;
                 } break;
@@ -597,13 +597,13 @@
     void CommandBuffer::RecordRenderPass(ComPtr<ID3D12GraphicsCommandList> commandList,
                                          BindGroupStateTracker* bindingTracker,
                                          RenderPassDescriptorHeapTracker* renderPassTracker,
-                                         RenderPassDescriptor* renderPass) {
+                                         BeginRenderPassCmd* renderPass) {
         OMSetRenderTargetArgs args = renderPassTracker->GetSubpassOMSetRenderTargetArgs(renderPass);
 
         // Clear framebuffer attachments as needed and transition to render target
         {
-            for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) {
-                auto& attachmentInfo = renderPass->GetColorAttachment(i);
+            for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+                auto& attachmentInfo = renderPass->colorAttachments[i];
 
                 // Load op - color
                 if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
@@ -613,9 +613,9 @@
                 }
             }
 
-            if (renderPass->HasDepthStencilAttachment()) {
-                auto& attachmentInfo = renderPass->GetDepthStencilAttachment();
-                Texture* texture = ToBackend(attachmentInfo.view->GetTexture());
+            if (renderPass->hasDepthStencilAttachment) {
+                auto& attachmentInfo = renderPass->depthStencilAttachment;
+                Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture());
 
                 // Load op - depth/stencil
                 bool doDepthClear = TextureFormatHasDepth(texture->GetFormat()) &&
@@ -653,8 +653,8 @@
 
         // Set up default dynamic state
         {
-            uint32_t width = renderPass->GetWidth();
-            uint32_t height = renderPass->GetHeight();
+            uint32_t width = renderPass->width;
+            uint32_t height = renderPass->height;
             D3D12_VIEWPORT viewport = {
                 0.f, 0.f, static_cast<float>(width), static_cast<float>(height), 0.f, 1.f};
             D3D12_RECT scissorRect = {0, 0, static_cast<long>(width), static_cast<long>(height)};
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.h b/src/dawn_native/d3d12/CommandBufferD3D12.h
index d1569ce..60d2fc7 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.h
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.h
@@ -22,6 +22,10 @@
 #include "dawn_native/d3d12/InputStateD3D12.h"
 #include "dawn_native/d3d12/d3d12_platform.h"
 
+namespace dawn_native {
+    struct BeginRenderPassCmd;
+}  // namespace dawn_native
+
 namespace dawn_native { namespace d3d12 {
 
     class Device;
@@ -56,7 +60,7 @@
         void RecordRenderPass(ComPtr<ID3D12GraphicsCommandList> commandList,
                               BindGroupStateTracker* bindingTracker,
                               RenderPassDescriptorHeapTracker* renderPassTracker,
-                              RenderPassDescriptor* renderPass);
+                              BeginRenderPassCmd* renderPass);
 
         CommandIterator mCommands;
     };
diff --git a/src/dawn_native/metal/CommandBufferMTL.h b/src/dawn_native/metal/CommandBufferMTL.h
index ab1b13f..c11ab78 100644
--- a/src/dawn_native/metal/CommandBufferMTL.h
+++ b/src/dawn_native/metal/CommandBufferMTL.h
@@ -20,7 +20,7 @@
 #import <Metal/Metal.h>
 
 namespace dawn_native {
-    class RenderPassDescriptorBase;
+    struct BeginRenderPassCmd;
 }
 
 namespace dawn_native { namespace metal {
@@ -36,8 +36,7 @@
 
       private:
         void EncodeComputePass(id<MTLCommandBuffer> commandBuffer);
-        void EncodeRenderPass(id<MTLCommandBuffer> commandBuffer,
-                              RenderPassDescriptorBase* renderPass);
+        void EncodeRenderPass(id<MTLCommandBuffer> commandBuffer, BeginRenderPassCmd* renderPass);
 
         Device* mDevice;
         CommandIterator mCommands;
diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm
index 410875f..c90ee5c 100644
--- a/src/dawn_native/metal/CommandBufferMTL.mm
+++ b/src/dawn_native/metal/CommandBufferMTL.mm
@@ -47,11 +47,11 @@
         };
 
         // Creates an autoreleased MTLRenderPassDescriptor matching desc
-        MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(RenderPassDescriptorBase* desc) {
+        MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(BeginRenderPassCmd* renderPass) {
             MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
 
-            for (uint32_t i : IterateBitSet(desc->GetColorAttachmentMask())) {
-                auto& attachmentInfo = desc->GetColorAttachment(i);
+            for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+                auto& attachmentInfo = renderPass->colorAttachments[i];
 
                 if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
                     descriptor.colorAttachments[i].loadAction = MTLLoadActionClear;
@@ -70,8 +70,8 @@
                 descriptor.colorAttachments[i].storeAction = MTLStoreActionStore;
             }
 
-            if (desc->HasDepthStencilAttachment()) {
-                auto& attachmentInfo = desc->GetDepthStencilAttachment();
+            if (renderPass->hasDepthStencilAttachment) {
+                auto& attachmentInfo = renderPass->depthStencilAttachment;
 
                 // TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.
                 id<MTLTexture> texture =
@@ -229,7 +229,7 @@
                 case Command::BeginRenderPass: {
                     BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
                     encoders.Finish();
-                    EncodeRenderPass(commandBuffer, ToBackend(cmd->info.Get()));
+                    EncodeRenderPass(commandBuffer, cmd);
                 } break;
 
                 case Command::CopyBufferToBuffer: {
@@ -373,7 +373,7 @@
     }
 
     void CommandBuffer::EncodeRenderPass(id<MTLCommandBuffer> commandBuffer,
-                                         RenderPassDescriptorBase* renderPass) {
+                                         BeginRenderPassCmd* renderPassCmd) {
         RenderPipeline* lastPipeline = nullptr;
         id<MTLBuffer> indexBuffer = nil;
         uint32_t indexBufferBaseOffset = 0;
@@ -383,7 +383,7 @@
 
         // This will be autoreleased
         id<MTLRenderCommandEncoder> encoder = [commandBuffer
-            renderCommandEncoderWithDescriptor:CreateMTLRenderPassDescriptor(renderPass)];
+            renderCommandEncoderWithDescriptor:CreateMTLRenderPassDescriptor(renderPassCmd)];
 
         // Set default values for push constants
         vertexPushConstants.fill(0);
diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp
index e3d33f6..2f672d8 100644
--- a/src/dawn_native/opengl/CommandBufferGL.cpp
+++ b/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -300,7 +300,7 @@
 
                 case Command::BeginRenderPass: {
                     auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
-                    ExecuteRenderPass(ToBackend(cmd->info.Get()));
+                    ExecuteRenderPass(cmd);
                 } break;
 
                 case Command::CopyBufferToBuffer: {
@@ -460,7 +460,7 @@
         UNREACHABLE();
     }
 
-    void CommandBuffer::ExecuteRenderPass(RenderPassDescriptorBase* renderPass) {
+    void CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) {
         GLuint fbo = 0;
 
         // Create the framebuffer used for this render pass and calls the correct glDrawBuffers
@@ -483,8 +483,8 @@
             // Construct GL framebuffer
 
             unsigned int attachmentCount = 0;
-            for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) {
-                TextureViewBase* textureView = renderPass->GetColorAttachment(i).view.Get();
+            for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+                TextureViewBase* textureView = renderPass->colorAttachments[i].view.Get();
                 GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
 
                 // Attach color buffers.
@@ -509,8 +509,8 @@
             }
             glDrawBuffers(attachmentCount, drawBuffers.data());
 
-            if (renderPass->HasDepthStencilAttachment()) {
-                TextureViewBase* textureView = renderPass->GetDepthStencilAttachment().view.Get();
+            if (renderPass->hasDepthStencilAttachment) {
+                TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get();
                 GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
                 dawn::TextureFormat format = textureView->GetTexture()->GetFormat();
 
@@ -539,8 +539,8 @@
 
         // Clear framebuffer attachments as needed
         {
-            for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) {
-                const auto& attachmentInfo = renderPass->GetColorAttachment(i);
+            for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+                const auto& attachmentInfo = renderPass->colorAttachments[i];
 
                 // Load op - color
                 if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
@@ -548,8 +548,8 @@
                 }
             }
 
-            if (renderPass->HasDepthStencilAttachment()) {
-                const auto& attachmentInfo = renderPass->GetDepthStencilAttachment();
+            if (renderPass->hasDepthStencilAttachment) {
+                const auto& attachmentInfo = renderPass->depthStencilAttachment;
                 dawn::TextureFormat attachmentFormat =
                     attachmentInfo.view->GetTexture()->GetFormat();
 
@@ -581,8 +581,8 @@
         // Set defaults for dynamic state
         persistentPipelineState.SetDefaultState();
         glBlendColor(0, 0, 0, 0);
-        glViewport(0, 0, renderPass->GetWidth(), renderPass->GetHeight());
-        glScissor(0, 0, renderPass->GetWidth(), renderPass->GetHeight());
+        glViewport(0, 0, renderPass->width, renderPass->height);
+        glScissor(0, 0, renderPass->width, renderPass->height);
 
         Command type;
         while (mCommands.NextCommandId(&type)) {
diff --git a/src/dawn_native/opengl/CommandBufferGL.h b/src/dawn_native/opengl/CommandBufferGL.h
index dc9218b..8ba754a 100644
--- a/src/dawn_native/opengl/CommandBufferGL.h
+++ b/src/dawn_native/opengl/CommandBufferGL.h
@@ -19,7 +19,7 @@
 #include "dawn_native/CommandBuffer.h"
 
 namespace dawn_native {
-    class RenderPassDescriptorBase;
+    struct BeginRenderPassCmd;
 }  // namespace dawn_native
 
 namespace dawn_native { namespace opengl {
@@ -35,7 +35,7 @@
 
       private:
         void ExecuteComputePass();
-        void ExecuteRenderPass(RenderPassDescriptorBase* renderPass);
+        void ExecuteRenderPass(BeginRenderPassCmd* renderPass);
 
         CommandIterator mCommands;
     };
diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp
index f94fb0f..462fb26 100644
--- a/src/dawn_native/vulkan/CommandBufferVk.cpp
+++ b/src/dawn_native/vulkan/CommandBufferVk.cpp
@@ -112,20 +112,19 @@
 
         void RecordBeginRenderPass(VkCommandBuffer commands,
                                    Device* device,
-                                   RenderPassDescriptorBase* renderPass) {
+                                   BeginRenderPassCmd* renderPass) {
             // Query a VkRenderPass from the cache
             VkRenderPass renderPassVK = VK_NULL_HANDLE;
             {
                 RenderPassCacheQuery query;
 
-                for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) {
-                    const auto& attachmentInfo = renderPass->GetColorAttachment(i);
-                    query.SetColor(i, attachmentInfo.view->GetTexture()->GetFormat(),
-                                   attachmentInfo.loadOp);
+                for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+                    const auto& attachmentInfo = renderPass->colorAttachments[i];
+                    query.SetColor(i, attachmentInfo.view->GetFormat(), attachmentInfo.loadOp);
                 }
 
-                if (renderPass->HasDepthStencilAttachment()) {
-                    const auto& attachmentInfo = renderPass->GetDepthStencilAttachment();
+                if (renderPass->hasDepthStencilAttachment) {
+                    const auto& attachmentInfo = renderPass->depthStencilAttachment;
                     query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat(),
                                           attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp);
                 }
@@ -142,8 +141,8 @@
                 // Fill in the attachment info that will be chained in the framebuffer create info.
                 std::array<VkImageView, kMaxColorAttachments + 1> attachments;
 
-                for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) {
-                    auto& attachmentInfo = renderPass->GetColorAttachment(i);
+                for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+                    auto& attachmentInfo = renderPass->colorAttachments[i];
                     TextureView* view = ToBackend(attachmentInfo.view.Get());
 
                     attachments[attachmentCount] = view->GetHandle();
@@ -156,8 +155,8 @@
                     attachmentCount++;
                 }
 
-                if (renderPass->HasDepthStencilAttachment()) {
-                    auto& attachmentInfo = renderPass->GetDepthStencilAttachment();
+                if (renderPass->hasDepthStencilAttachment) {
+                    auto& attachmentInfo = renderPass->depthStencilAttachment;
                     TextureView* view = ToBackend(attachmentInfo.view.Get());
 
                     attachments[attachmentCount] = view->GetHandle();
@@ -176,8 +175,8 @@
                 createInfo.renderPass = renderPassVK;
                 createInfo.attachmentCount = attachmentCount;
                 createInfo.pAttachments = attachments.data();
-                createInfo.width = renderPass->GetWidth();
-                createInfo.height = renderPass->GetHeight();
+                createInfo.width = renderPass->width;
+                createInfo.height = renderPass->height;
                 createInfo.layers = 1;
 
                 if (device->fn.CreateFramebuffer(device->GetVkDevice(), &createInfo, nullptr,
@@ -197,8 +196,8 @@
             beginInfo.framebuffer = framebuffer;
             beginInfo.renderArea.offset.x = 0;
             beginInfo.renderArea.offset.y = 0;
-            beginInfo.renderArea.extent.width = renderPass->GetWidth();
-            beginInfo.renderArea.extent.height = renderPass->GetHeight();
+            beginInfo.renderArea.extent.width = renderPass->width;
+            beginInfo.renderArea.extent.height = renderPass->height;
             beginInfo.clearValueCount = attachmentCount;
             beginInfo.pClearValues = clearValues.data();
 
@@ -303,7 +302,7 @@
                     BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
 
                     TransitionForPass(commands, passResourceUsages[nextPassNumber]);
-                    RecordRenderPass(commands, ToBackend(cmd->info.Get()));
+                    RecordRenderPass(commands, cmd);
 
                     nextPassNumber++;
                 } break;
@@ -365,10 +364,10 @@
         UNREACHABLE();
     }
     void CommandBuffer::RecordRenderPass(VkCommandBuffer commands,
-                                         RenderPassDescriptorBase* renderPass) {
+                                         BeginRenderPassCmd* renderPassCmd) {
         Device* device = ToBackend(GetDevice());
 
-        RecordBeginRenderPass(commands, device, renderPass);
+        RecordBeginRenderPass(commands, device, renderPassCmd);
 
         // Set the default value for the dynamic state
         {
@@ -389,8 +388,8 @@
             VkViewport viewport;
             viewport.x = 0.0f;
             viewport.y = 0.0f;
-            viewport.width = static_cast<float>(renderPass->GetWidth());
-            viewport.height = static_cast<float>(renderPass->GetHeight());
+            viewport.width = static_cast<float>(renderPassCmd->width);
+            viewport.height = static_cast<float>(renderPassCmd->height);
             viewport.minDepth = 0.0f;
             viewport.maxDepth = 1.0f;
             device->fn.CmdSetViewport(commands, 0, 1, &viewport);
@@ -398,8 +397,8 @@
             VkRect2D scissorRect;
             scissorRect.offset.x = 0;
             scissorRect.offset.y = 0;
-            scissorRect.extent.width = renderPass->GetWidth();
-            scissorRect.extent.height = renderPass->GetHeight();
+            scissorRect.extent.width = renderPassCmd->width;
+            scissorRect.extent.height = renderPassCmd->height;
             device->fn.CmdSetScissor(commands, 0, 1, &scissorRect);
         }
 
diff --git a/src/dawn_native/vulkan/CommandBufferVk.h b/src/dawn_native/vulkan/CommandBufferVk.h
index 61d0236..b14f586 100644
--- a/src/dawn_native/vulkan/CommandBufferVk.h
+++ b/src/dawn_native/vulkan/CommandBufferVk.h
@@ -16,10 +16,13 @@
 #define DAWNNATIVE_VULKAN_COMMANDBUFFERVK_H_
 
 #include "dawn_native/CommandBuffer.h"
-#include "dawn_native/RenderPassDescriptor.h"
 
 #include "common/vulkan_platform.h"
 
+namespace dawn_native {
+    struct BeginRenderPassCmd;
+}  // namespace dawn_native
+
 namespace dawn_native { namespace vulkan {
 
     class CommandBuffer : public CommandBufferBase {
@@ -31,7 +34,7 @@
 
       private:
         void RecordComputePass(VkCommandBuffer commands);
-        void RecordRenderPass(VkCommandBuffer commands, RenderPassDescriptorBase* renderPass);
+        void RecordRenderPass(VkCommandBuffer commands, BeginRenderPassCmd* renderPass);
 
         CommandIterator mCommands;
     };
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 5622214..48e526c 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -19,6 +19,7 @@
 #include "dawn_native/Commands.h"
 #include "dawn_native/DynamicUploader.h"
 #include "dawn_native/ErrorData.h"
+#include "dawn_native/RenderPassDescriptor.h"
 #include "dawn_native/vulkan/AdapterVk.h"
 #include "dawn_native/vulkan/BackendVk.h"
 #include "dawn_native/vulkan/BindGroupLayoutVk.h"