[graphite] Add begin/endRenderPass for Vulkan backend.

Uses vkCmdBeginRendering/vkCmdEndRendering as a shortcut to get this
up and running. Eventually we will move to the renderpass/subpass
interface to give us fuller functionality.

Bug: b/237107064
Change-Id: I789055ebb1e7b408e6287c3f6a131eb521e86a70
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/702378
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Nicolette Prevost <nicolettep@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/graphite/vk/VulkanCommandBuffer.cpp b/src/gpu/graphite/vk/VulkanCommandBuffer.cpp
index 7385ca3..35b4e10 100644
--- a/src/gpu/graphite/vk/VulkanCommandBuffer.cpp
+++ b/src/gpu/graphite/vk/VulkanCommandBuffer.cpp
@@ -280,19 +280,127 @@
                                           const Texture* colorTexture,
                                           const Texture* resolveTexture,
                                           const Texture* depthStencilTexture) {
-    // TODO: Implement the following:
-    // Get render pass descriptor
-    // Set up color attachment
-    // Set up depth/stencil attachment
-    // If needed, load MSAA from resolve
+    const static VkAttachmentLoadOp vkLoadOp[] {
+        VK_ATTACHMENT_LOAD_OP_LOAD,
+        VK_ATTACHMENT_LOAD_OP_CLEAR,
+        VK_ATTACHMENT_LOAD_OP_DONT_CARE
+    };
+    static_assert((int)LoadOp::kLoad == 0);
+    static_assert((int)LoadOp::kClear == 1);
+    static_assert((int)LoadOp::kDiscard == 2);
+    static_assert(std::size(vkLoadOp) == kLoadOpCount);
 
-    // Return true despite not being fully completed to allow dm to run.
-    return true;
+    const static VkAttachmentStoreOp vkStoreOp[] {
+        VK_ATTACHMENT_STORE_OP_STORE,
+        VK_ATTACHMENT_STORE_OP_DONT_CARE
+    };
+    static_assert((int)StoreOp::kStore == 0);
+    static_assert((int)StoreOp::kDiscard == 1);
+    static_assert(std::size(vkStoreOp) == kStoreOpCount);
+
+    // Get render pass descriptor
+    VkRenderingInfoKHR renderingInfo;
+    memset(&renderingInfo, 0, sizeof(VkRenderingInfoKHR));
+    renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR;
+    renderingInfo.renderArea = {{ 0, 0 },
+                                { (unsigned int) colorTexture->dimensions().width(),
+                                  (unsigned int) colorTexture->dimensions().height() }};
+    renderingInfo.layerCount = 1;
+
+    // Set up color attachment
+    VkRenderingAttachmentInfoKHR colorAttachment;
+    auto& colorInfo = renderPassDesc.fColorAttachment;
+    if (colorTexture) {
+        memset(&colorAttachment, 0, sizeof(VkRenderingAttachmentInfoKHR));
+        colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR;
+        VulkanTexture* vulkanTexture =
+            const_cast<VulkanTexture*>(static_cast<const VulkanTexture*>(colorTexture));
+        colorAttachment.imageView =
+                vulkanTexture->getImageView(VulkanImageView::Usage::kAttachment)->imageView();
+        colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+        colorAttachment.loadOp = vkLoadOp[static_cast<int>(colorInfo.fLoadOp)];
+        colorAttachment.storeOp = vkStoreOp[static_cast<int>(colorInfo.fStoreOp)];
+        memcpy(&colorAttachment.clearValue.color.float32,
+               &renderPassDesc.fClearColor,
+               4*sizeof(float));
+        vulkanTexture->setImageLayout(this, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                                      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                                      VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, false);
+        // Set up resolve attachment
+        if (resolveTexture) {
+            SkASSERT(renderPassDesc.fColorResolveAttachment.fStoreOp == StoreOp::kStore);
+            // TODO: check Texture matches RenderPassDesc
+            vulkanTexture =
+                const_cast<VulkanTexture*>(static_cast<const VulkanTexture*>(resolveTexture));
+            colorAttachment.resolveImageView =
+                    vulkanTexture->getImageView(VulkanImageView::Usage::kAttachment)->imageView();
+            colorAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+            SkASSERT(colorAttachment.storeOp == VK_ATTACHMENT_STORE_OP_DONT_CARE);
+            vulkanTexture->setImageLayout(this, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                                          VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                                          VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, false);
+        }
+
+        renderingInfo.colorAttachmentCount = 1;
+        renderingInfo.pColorAttachments = &colorAttachment;
+        this->trackResource(sk_ref_sp(colorTexture));
+    }
+
+    // Set up depth/stencil attachments
+    VkRenderingAttachmentInfoKHR depthAttachment;
+    VkRenderingAttachmentInfoKHR stencilAttachment;
+    auto& depthStencilInfo = renderPassDesc.fDepthStencilAttachment;
+    if (depthStencilTexture) {
+        VulkanTexture* vulkanTexture =
+                const_cast<VulkanTexture*>(static_cast<const VulkanTexture*>(depthStencilTexture));
+        VkImageView imageView =
+                vulkanTexture->getImageView(VulkanImageView::Usage::kAttachment)->imageView();
+        VulkanTextureInfo vkTexInfo;
+        depthStencilTexture->textureInfo().getVulkanTextureInfo(&vkTexInfo);
+
+        if (VkFormatIsDepth(vkTexInfo.fFormat)) {
+            memset(&depthAttachment, 0, sizeof(VkRenderingAttachmentInfoKHR));
+            depthAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR;
+            depthAttachment.imageView = imageView;
+            depthAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+            depthAttachment.loadOp = vkLoadOp[static_cast<int>(depthStencilInfo.fLoadOp)];
+            depthAttachment.storeOp = vkStoreOp[static_cast<int>(depthStencilInfo.fStoreOp)];
+            depthAttachment.clearValue.depthStencil.depth = renderPassDesc.fClearDepth;
+
+            renderingInfo.pDepthAttachment = &depthAttachment;
+        }
+
+        if (VkFormatIsStencil(vkTexInfo.fFormat)) {
+            memset(&stencilAttachment, 0, sizeof(VkRenderingAttachmentInfoKHR));
+            stencilAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR;
+            stencilAttachment.imageView = imageView;
+            stencilAttachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+            stencilAttachment.loadOp = vkLoadOp[static_cast<int>(depthStencilInfo.fLoadOp)];
+            stencilAttachment.storeOp = vkStoreOp[static_cast<int>(depthStencilInfo.fStoreOp)];
+            stencilAttachment.clearValue.depthStencil.stencil = renderPassDesc.fClearStencil;
+
+            renderingInfo.pStencilAttachment = &stencilAttachment;
+        }
+
+        vulkanTexture->setImageLayout(this, VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL,
+                                      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, false);
+        this->trackResource(sk_ref_sp(depthStencilTexture));
+    }
+
+    // TODO: If needed, load MSAA from resolve
+    // Only possible with RenderPass interface, not beginRendering()
+
+    VULKAN_CALL(fSharedContext->interface(),
+                CmdBeginRendering(fPrimaryCommandBuffer, &renderingInfo));
+
+     return true;
 }
 
 void VulkanCommandBuffer::endRenderPass() {
     SkASSERT(fActive);
-    // TODO: Implement
+    VULKAN_CALL(fSharedContext->interface(), CmdEndRendering(fPrimaryCommandBuffer));
 }
 
 void VulkanCommandBuffer::addDrawPass(const DrawPass* drawPass) {
diff --git a/src/gpu/vk/VulkanUtilsPriv.h b/src/gpu/vk/VulkanUtilsPriv.h
index 6271eb0..462113f 100644
--- a/src/gpu/vk/VulkanUtilsPriv.h
+++ b/src/gpu/vk/VulkanUtilsPriv.h
@@ -76,6 +76,27 @@
     }
 }
 
+static constexpr int VkFormatIsStencil(VkFormat format) {
+    switch (format) {
+        case VK_FORMAT_S8_UINT:
+        case VK_FORMAT_D24_UNORM_S8_UINT:
+        case VK_FORMAT_D32_SFLOAT_S8_UINT:
+            return true;
+        default:
+            return false;
+    }
+}
+
+static constexpr int VkFormatIsDepth(VkFormat format) {
+    switch (format) {
+        case VK_FORMAT_D24_UNORM_S8_UINT:
+        case VK_FORMAT_D32_SFLOAT_S8_UINT:
+            return true;
+        default:
+            return false;
+    }
+}
+
 static constexpr int VkFormatStencilBits(VkFormat format) {
     switch (format) {
         case VK_FORMAT_S8_UINT: