Vulkan: Cache pipelines with Shader Programs.

This allows for a few nice things. First and foremost it reduces the
size of the PipelineDesc, which is now 232 bytes. It also allows us
to completely forego pipeline caches for compute shaders.

We also allow sharing vertex and fragment shaders among multiple
programs for internal shaders. This is good for memory savings. To
allow this we keep the shaders as ref counted objects.

Bug: angleproject:2522
Change-Id: I2322be5061979d9669a0b25c152359561eeb80ee
Reviewed-on: https://chromium-review.googlesource.com/c/1344449
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.h b/src/libANGLE/renderer/vulkan/ProgramVk.h
index 45b407c..cd3c4a3 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.h
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.h
@@ -13,6 +13,7 @@
 #include <array>
 
 #include "libANGLE/renderer/ProgramImpl.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
 #include "libANGLE/renderer/vulkan/RendererVk.h"
 #include "libANGLE/renderer/vulkan/vk_helpers.h"
 
@@ -96,11 +97,6 @@
                                  const GLfloat *coeffs) override;
 
     // Also initializes the pipeline layout, descriptor set layouts, and used descriptor ranges.
-    angle::Result initShaders(ContextVk *contextVk,
-                              gl::PrimitiveMode mode,
-                              const vk::ShaderAndSerial **vertexShaderAndSerialOut,
-                              const vk::ShaderAndSerial **fragmentShaderAndSerialOut,
-                              const vk::PipelineLayout **pipelineLayoutOut);
 
     angle::Result updateUniforms(ContextVk *contextVk);
     angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
@@ -116,6 +112,19 @@
 
     bool dirtyUniforms() const { return mDefaultUniformBlocksDirty.any(); }
 
+    angle::Result getGraphicsPipeline(ContextVk *contextVk,
+                                      gl::PrimitiveMode mode,
+                                      const vk::GraphicsPipelineDesc &desc,
+                                      const gl::AttributesMask &activeAttribLocations,
+                                      vk::PipelineAndSerial **pipelineOut)
+    {
+        vk::ShaderProgramHelper *shaderProgram;
+        ANGLE_TRY(initShaders(contextVk, mode, &shaderProgram));
+        ASSERT(shaderProgram->isGraphicsProgram());
+        return shaderProgram->getGraphicsPipeline(contextVk, mPipelineLayout.get(), desc,
+                                                  activeAttribLocations, pipelineOut);
+    }
+
   private:
     template <int cols, int rows>
     void setUniformMatrixfv(GLint location,
@@ -123,7 +132,7 @@
                             GLboolean transpose,
                             const GLfloat *value);
 
-    angle::Result reset(ContextVk *contextVk);
+    void reset(RendererVk *renderer);
     angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
     angle::Result initDefaultUniformBlocks(const gl::Context *glContext);
 
@@ -138,6 +147,10 @@
                            const gl::ProgramLinkedResources &resources,
                            gl::InfoLog &infoLog);
 
+    angle::Result initShaders(ContextVk *contextVk,
+                              gl::PrimitiveMode mode,
+                              vk::ShaderProgramHelper **shaderProgramOut);
+
     // State for the default uniform blocks.
     struct DefaultUniformBlock final : private angle::NonCopyable
     {
@@ -182,18 +195,18 @@
         ShaderInfo();
         ~ShaderInfo();
 
-        angle::Result getShaders(ContextVk *contextVk,
-                                 const std::string &vertexSource,
-                                 const std::string &fragmentSource,
-                                 bool enableLineRasterEmulation,
-                                 const vk::ShaderAndSerial **vertexShaderAndSerialOut,
-                                 const vk::ShaderAndSerial **fragmentShaderAndSerialOut);
-        void destroy(VkDevice device);
+        angle::Result initShaders(ContextVk *contextVk,
+                                  const std::string &vertexSource,
+                                  const std::string &fragmentSource,
+                                  bool enableLineRasterEmulation);
+        void release(RendererVk *renderer);
         bool valid() const;
 
+        vk::ShaderProgramHelper &getShaderProgram() { return mProgramHelper; }
+
       private:
-        vk::ShaderAndSerial mVertexShaderAndSerial;
-        vk::ShaderAndSerial mFragmentShaderAndSerial;
+        vk::ShaderProgramHelper mProgramHelper;
+        gl::ShaderMap<vk::RefCounted<vk::ShaderAndSerial>> mShaders;
     };
 
     ShaderInfo mDefaultShaderInfo;