Update how we send draws to gpu backend to reduce state setting.

The main change here is that we pull primitive type off of the vertices, we set the gpu state on gpu once per pipeline/prim proc draw batch, and we create the ProgramDescriptor only for the Cache/ProgramBuilder.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1806983002

Review URL: https://codereview.chromium.org/1806983002
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index fce7173..180ba3b 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -10,11 +10,11 @@
 #include "GrContextOptions.h"
 #include "GrGeometryProcessor.h"
 #include "GrGpuResourceCacheAccess.h"
+#include "GrMesh.h"
 #include "GrPipeline.h"
 #include "GrRenderTargetPriv.h"
 #include "GrSurfacePriv.h"
 #include "GrTexturePriv.h"
-#include "GrVertices.h"
 
 #include "GrVkCommandBuffer.h"
 #include "GrVkImage.h"
@@ -650,9 +650,9 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrVkGpu::bindGeometry(const GrPrimitiveProcessor& primProc,
-                           const GrNonInstancedVertices& vertices) {
+                           const GrNonInstancedMesh& mesh) {
     GrVkVertexBuffer* vbuf;
-    vbuf = (GrVkVertexBuffer*)vertices.vertexBuffer();
+    vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer();
     SkASSERT(vbuf);
     SkASSERT(!vbuf->isMapped());
 
@@ -665,8 +665,8 @@
 
     fCurrentCmdBuffer->bindVertexBuffer(this, vbuf);
 
-    if (vertices.isIndexed()) {
-        GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)vertices.indexBuffer();
+    if (mesh.isIndexed()) {
+        GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer();
         SkASSERT(ibuf);
         SkASSERT(!ibuf->isMapped());
 
@@ -681,14 +681,6 @@
     }
 }
 
-void GrVkGpu::buildProgramDesc(GrProgramDesc* desc,
-                               const GrPrimitiveProcessor& primProc,
-                               const GrPipeline& pipeline) const {
-    if (!GrVkProgramDescBuilder::Build(desc, primProc, pipeline, *this->vkCaps().glslCaps())) {
-        SkDEBUGFAIL("Failed to generate GL program descriptor");
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
@@ -1323,28 +1315,52 @@
     return true;
 }
 
-void GrVkGpu::onDraw(const DrawArgs& args, const GrNonInstancedVertices& vertices) {
-    GrRenderTarget* rt = args.fPipeline->getRenderTarget();
+bool GrVkGpu::prepareDrawState(const GrPipeline& pipeline,
+                               const GrPrimitiveProcessor& primProc,
+                               GrPrimitiveType primitiveType,
+                               const GrVkRenderPass& renderPass,
+                               GrVkProgram** program) {
+    // Get GrVkProgramDesc
+    GrVkProgramDesc desc;
+    if (!GrVkProgramDescBuilder::Build(&desc, primProc, pipeline, *this->vkCaps().glslCaps())) {
+        GrCapsDebugf(this->caps(), "Failed to vk program descriptor!\n");
+        return false;
+    }
+
+    *program = GrVkProgramBuilder::CreateProgram(this,
+                                                 pipeline,
+                                                 primProc,
+                                                 primitiveType,
+                                                 desc,
+                                                 renderPass);
+    if (!program) {
+        return false;
+    }
+
+    (*program)->setData(this, primProc, pipeline);
+
+    (*program)->bind(this, fCurrentCmdBuffer);
+    return true;
+}
+
+void GrVkGpu::onDraw(const GrPipeline& pipeline,
+                     const GrPrimitiveProcessor& primProc,
+                     const GrMesh* meshes,
+                     int meshCount) {
+    if (!meshCount) {
+        return;
+    }
+    GrRenderTarget* rt = pipeline.getRenderTarget();
     GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
     const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
     SkASSERT(renderPass);
 
-    GrVkProgram* program = GrVkProgramBuilder::CreateProgram(this, args,
-                                                             vertices.primitiveType(),
-                                                             *renderPass);
-
-    if (!program) {
+    GrVkProgram* program = nullptr;
+    GrPrimitiveType primitiveType = meshes[0].primitiveType();
+    if (!this->prepareDrawState(pipeline, primProc, primitiveType, *renderPass, &program)) {
         return;
     }
 
-    program->setData(this, *args.fPrimitiveProcessor, *args.fPipeline);
-
-    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
-
-    program->bind(this, fCurrentCmdBuffer);
-
-    this->bindGeometry(*args.fPrimitiveProcessor, vertices);
-
     // Change layout of our render target so it can be used as the color attachment
     VkImageLayout layout = vkRT->currentLayout();
     // Our color attachment is purely a destination and won't be read so don't need to flush or
@@ -1362,13 +1378,13 @@
                          false);
 
     // If we are using a stencil attachment we also need to update its layout
-    if (!args.fPipeline->getStencil().isDisabled()) {
+    if (!pipeline.getStencil().isDisabled()) {
         GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment();
         GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
         VkImageLayout origDstLayout = vkStencil->currentLayout();
         VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
         VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
-                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
         VkPipelineStageFlags srcStageMask =
             GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
         VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
@@ -1381,15 +1397,53 @@
                                   false);
     }
 
-    if (vertices.isIndexed()) {
-        fCurrentCmdBuffer->drawIndexed(this,
-                                       vertices.indexCount(),
-                                       1,
-                                       vertices.startIndex(),
-                                       vertices.startVertex(),
-                                       0);
-    } else {
-        fCurrentCmdBuffer->draw(this, vertices.vertexCount(), 1, vertices.startVertex(),  0);
+    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
+
+    for (int i = 0; i < meshCount; ++i) {
+        if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
+            this->xferBarrier(pipeline.getRenderTarget(), barrierType);
+        }
+
+        const GrMesh& mesh = meshes[i];
+        GrMesh::Iterator iter;
+        const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh);
+        do {
+            if (nonIdxMesh->primitiveType() != primitiveType) {
+                // Technically we don't have to call this here (since there is a safety check in
+                // program:setData but this will allow for quicker freeing of resources if the
+                // program sits in a cache for a while.
+                program->freeTempResources(this);
+                // This free will go away once we setup a program cache, and then the cache will be
+                // responsible for call freeGpuResources.
+                program->freeGPUResources(this);
+                program->unref();
+                SkDEBUGCODE(program = nullptr);
+                primitiveType = nonIdxMesh->primitiveType();
+                if (!this->prepareDrawState(pipeline, primProc, primitiveType, *renderPass,
+                                            &program)) {
+                    return;
+                }
+            }
+            SkASSERT(program);
+            this->bindGeometry(primProc, *nonIdxMesh);
+
+            if (nonIdxMesh->isIndexed()) {
+                fCurrentCmdBuffer->drawIndexed(this,
+                                               nonIdxMesh->indexCount(),
+                                               1,
+                                               nonIdxMesh->startIndex(),
+                                               nonIdxMesh->startVertex(),
+                                               0);
+            } else {
+                fCurrentCmdBuffer->draw(this,
+                                        nonIdxMesh->vertexCount(),
+                                        1,
+                                        nonIdxMesh->startVertex(),
+                                        0);
+            }
+
+            fStats.incNumDraws();
+        } while ((nonIdxMesh = iter.next()));
     }
 
     fCurrentCmdBuffer->endRenderPass(this);
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 723d714..3785b15 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -21,7 +21,7 @@
 #include "vulkan/vulkan.h"
 
 class GrPipeline;
-class GrNonInstancedVertices;
+class GrNonInstancedMesh;
 
 class GrVkBufferImpl;
 class GrVkCommandBuffer;
@@ -64,9 +64,6 @@
                               GrPixelConfig srcConfig, DrawPreference*,
                               WritePixelTempDrawInfo*) override;
 
-    void buildProgramDesc(GrProgramDesc*, const GrPrimitiveProcessor&,
-                          const GrPipeline&) const override;
-
     void discard(GrRenderTarget*) override {
         SkDebugf("discard not yet implemented for Vulkan\n");
     }
@@ -154,7 +151,10 @@
 
     void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
 
-    void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override;
+    void onDraw(const GrPipeline&,
+                const GrPrimitiveProcessor&,
+                const GrMesh*,
+                int meshCount) override;
 
     bool onReadPixels(GrSurface* surface,
                       int left, int top, int width, int height,
@@ -178,8 +178,14 @@
         SkDebugf("onResolveRenderTarget not yet implemented for Vulkan\n");
     }
 
+    bool prepareDrawState(const GrPipeline&,
+                          const GrPrimitiveProcessor&,
+                          GrPrimitiveType,
+                          const GrVkRenderPass&,
+                          GrVkProgram** program);
+
     // Bind vertex and index buffers
-    void bindGeometry(const GrPrimitiveProcessor&, const GrNonInstancedVertices&);
+    void bindGeometry(const GrPrimitiveProcessor&, const GrNonInstancedMesh&);
 
     // Ends and submits the current command buffer to the queue and then creates a new command
     // buffer and begins it. If sync is set to kForce_SyncQueue, the function will wait for all 
diff --git a/src/gpu/vk/GrVkProgramBuilder.cpp b/src/gpu/vk/GrVkProgramBuilder.cpp
index 06de3a0..1b56054 100644
--- a/src/gpu/vk/GrVkProgramBuilder.cpp
+++ b/src/gpu/vk/GrVkProgramBuilder.cpp
@@ -12,12 +12,14 @@
 #include "vk/GrVkProgram.h"
 
 GrVkProgram* GrVkProgramBuilder::CreateProgram(GrVkGpu* gpu,
-                                               const DrawArgs& args,
+                                               const GrPipeline& pipeline,
+                                               const GrPrimitiveProcessor& primProc,
                                                GrPrimitiveType primitiveType,
+                                               const GrVkProgramDesc& desc,
                                                const GrVkRenderPass& renderPass) {
     // create a builder.  This will be handed off to effects so they can use it to add
     // uniforms, varyings, textures, etc
-    GrVkProgramBuilder builder(gpu, args);
+    GrVkProgramBuilder builder(gpu, pipeline, primProc, desc);
 
     GrGLSLExpr4 inputColor;
     GrGLSLExpr4 inputCoverage;
@@ -27,11 +29,14 @@
         return nullptr;
     }
 
-    return builder.finalize(args, primitiveType, renderPass);
+    return builder.finalize(primitiveType, renderPass);
 }
 
-GrVkProgramBuilder::GrVkProgramBuilder(GrVkGpu* gpu, const DrawArgs& args)
-    : INHERITED(args) 
+GrVkProgramBuilder::GrVkProgramBuilder(GrVkGpu* gpu,
+                                       const GrPipeline& pipeline,
+                                       const GrPrimitiveProcessor& primProc,
+                                       const GrVkProgramDesc& desc)
+    : INHERITED(pipeline, primProc, desc) 
     , fGpu(gpu)
     , fVaryingHandler(this) 
     , fUniformHandler(this) {
@@ -135,8 +140,7 @@
     return true;
 }
 
-GrVkProgram* GrVkProgramBuilder::finalize(const DrawArgs& args,
-                                          GrPrimitiveType primitiveType,
+GrVkProgram* GrVkProgramBuilder::finalize(GrPrimitiveType primitiveType,
                                           const GrVkRenderPass& renderPass) {
     VkDescriptorSetLayout dsLayout[2];
     VkPipelineLayout pipelineLayout;
@@ -246,8 +250,8 @@
                                         &shaderStageInfo[1]));
 
     GrVkResourceProvider& resourceProvider = fGpu->resourceProvider();
-    GrVkPipeline* pipeline = resourceProvider.createPipeline(*args.fPipeline,
-                                                             *args.fPrimitiveProcessor,
+    GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
+                                                             fPrimProc,
                                                              shaderStageInfo,
                                                              2,
                                                              primitiveType,
diff --git a/src/gpu/vk/GrVkProgramBuilder.h b/src/gpu/vk/GrVkProgramBuilder.h
index 83a7adf..65fe546 100644
--- a/src/gpu/vk/GrVkProgramBuilder.h
+++ b/src/gpu/vk/GrVkProgramBuilder.h
@@ -20,6 +20,7 @@
 class GrVkGpu;
 class GrVkRenderPass;
 class GrVkProgram;
+class GrVkProgramDesc;
 
 class GrVkProgramBuilder : public GrGLSLProgramBuilder {
 public:
@@ -31,8 +32,10 @@
     * @return true if generation was successful.
     */
     static GrVkProgram* CreateProgram(GrVkGpu*,
-                                      const DrawArgs&,
+                                      const GrPipeline&,
+                                      const GrPrimitiveProcessor&,
                                       GrPrimitiveType,
+                                      const GrVkProgramDesc&,
                                       const GrVkRenderPass& renderPass);
 
     const GrCaps* caps() const override;
@@ -43,11 +46,12 @@
     void finalizeFragmentOutputColor(GrGLSLShaderVar& outputColor) override;
 
 private:
-    GrVkProgramBuilder(GrVkGpu*, const DrawArgs&);
+    GrVkProgramBuilder(GrVkGpu*,
+                       const GrPipeline&,
+                       const GrPrimitiveProcessor&,
+                       const GrVkProgramDesc&);
 
-    GrVkProgram* finalize(const DrawArgs& args,
-                          GrPrimitiveType primitiveType,
-                          const GrVkRenderPass& renderPass);
+    GrVkProgram* finalize(GrPrimitiveType primitiveType, const GrVkRenderPass& renderPass);
 
     static bool CreateVkShaderModule(const GrVkGpu* gpu,
                                      VkShaderStageFlagBits stage,
@@ -63,8 +67,6 @@
     GrVkVaryingHandler        fVaryingHandler;
     GrVkUniformHandler        fUniformHandler;
 
-    SkTArray<UniformHandle>   fSamplerUniforms;
-
     typedef GrGLSLProgramBuilder INHERITED;
 };