Vulkan: Add packed RenderPass descriptions.

This change is two-fold: it splits the compatible parts from the
RenderPass description, which allows for correct caching. It also
will allow the pipeline state cache to cache the compatible RenderPass
bits.

In order to do this we introduce a packed version of the RenderPass
description, which uses carefully aligned bit representations so we
can hash the descriptions easily using MurmurHash, and compare them
with memcmp.

Bug: angleproject:2163
Change-Id: I4179c0ff8762df81f29082168bd6e3056ceb1318
Reviewed-on: https://chromium-review.googlesource.com/815816
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index 0176c8c..64ca87f 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -30,7 +30,6 @@
 
 namespace
 {
-
 gl::ErrorOrResult<const gl::InternalFormat *> GetReadAttachmentInfo(
     const gl::Context *context,
     const gl::FramebufferAttachment *readAttachment)
@@ -41,30 +40,6 @@
     GLenum implFormat = renderTarget->format->textureFormat().fboImplementationInternalFormat;
     return &gl::GetSizedInternalFormatInfo(implFormat);
 }
-
-VkSampleCountFlagBits ConvertSamples(GLint sampleCount)
-{
-    switch (sampleCount)
-    {
-        case 0:
-        case 1:
-            return VK_SAMPLE_COUNT_1_BIT;
-        case 2:
-            return VK_SAMPLE_COUNT_2_BIT;
-        case 4:
-            return VK_SAMPLE_COUNT_4_BIT;
-        case 8:
-            return VK_SAMPLE_COUNT_8_BIT;
-        case 16:
-            return VK_SAMPLE_COUNT_16_BIT;
-        case 32:
-            return VK_SAMPLE_COUNT_32_BIT;
-        default:
-            UNREACHABLE();
-            return VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
-    }
-}
-
 }  // anonymous namespace
 
 // static
@@ -386,24 +361,7 @@
         {
             RenderTargetVk *renderTarget = nullptr;
             ANGLE_SWALLOW_ERR(colorAttachment.getRenderTarget(context, &renderTarget));
-
-            VkAttachmentDescription *colorDesc = desc.nextColorAttachment();
-
-            // TODO(jmadill): We would only need this flag for duplicated attachments.
-            colorDesc->flags   = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
-            colorDesc->format  = renderTarget->format->vkTextureFormat;
-            colorDesc->samples = ConvertSamples(colorAttachment.getSamples());
-
-            // The load op controls the prior existing depth/color attachment data.
-            // TODO(jmadill): Proper load ops. Should not be hard coded to clear.
-            colorDesc->loadOp         = VK_ATTACHMENT_LOAD_OP_CLEAR;
-            colorDesc->storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
-            colorDesc->stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
-            colorDesc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-            colorDesc->initialLayout  = VK_IMAGE_LAYOUT_UNDEFINED;
-
-            // We might want to transition directly to PRESENT_SRC for Surface attachments.
-            colorDesc->finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+            desc.packColorAttachment(*renderTarget->format, colorAttachment.getSamples());
         }
     }
 
@@ -413,18 +371,8 @@
     {
         RenderTargetVk *renderTarget = nullptr;
         ANGLE_SWALLOW_ERR(depthStencilAttachment->getRenderTarget(context, &renderTarget));
-
-        VkAttachmentDescription *depthStencilDesc = desc.nextDepthStencilAttachment();
-
-        depthStencilDesc->flags          = 0;
-        depthStencilDesc->format         = renderTarget->format->vkTextureFormat;
-        depthStencilDesc->samples        = ConvertSamples(depthStencilAttachment->getSamples());
-        depthStencilDesc->loadOp         = VK_ATTACHMENT_LOAD_OP_CLEAR;
-        depthStencilDesc->storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
-        depthStencilDesc->stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
-        depthStencilDesc->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-        depthStencilDesc->initialLayout  = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-        depthStencilDesc->finalLayout    = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+        desc.packDepthStencilAttachment(*renderTarget->format,
+                                        depthStencilAttachment->getSamples());
     }
 
     mRenderPassDesc = desc;
@@ -512,6 +460,9 @@
                                          vk::CommandBuffer *commandBuffer,
                                          Serial queueSerial)
 {
+    uint32_t attachmentIndex = 0;
+    vk::AttachmentOpsArray attachmentOps;
+
     // TODO(jmadill): Cache render targets.
     for (const auto &colorAttachment : mState.getColorAttachments())
     {
@@ -520,6 +471,9 @@
             RenderTargetVk *renderTarget = nullptr;
             ANGLE_TRY(colorAttachment.getRenderTarget<RenderTargetVk>(context, &renderTarget));
             renderTarget->resource->setQueueSerial(queueSerial);
+
+            // Fill in some default load and store ops.
+            attachmentOps.initDummyOp(attachmentIndex++, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
         }
     }
 
@@ -529,6 +483,10 @@
         RenderTargetVk *renderTarget = nullptr;
         ANGLE_TRY(depthStencilAttachment->getRenderTarget<RenderTargetVk>(context, &renderTarget));
         renderTarget->resource->setQueueSerial(queueSerial);
+
+        // Fill in some default load and store ops.
+        attachmentOps.initDummyOp(attachmentIndex++,
+                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
     }
 
     vk::Framebuffer *framebuffer = nullptr;
@@ -538,7 +496,7 @@
     const vk::RenderPassDesc &desc = getRenderPassDesc(context);
 
     vk::RenderPass *renderPass = nullptr;
-    ANGLE_TRY(rendererVk->getMatchingRenderPass(desc, &renderPass));
+    ANGLE_TRY(rendererVk->getRenderPassWithOps(desc, attachmentOps, &renderPass));
     ASSERT(renderPass && renderPass->valid());
 
     // TODO(jmadill): Proper clear value implementation.