Start using GrGpuCommandBuffer in GrDrawTarget.
authoregdaniel <egdaniel@google.com>
Thu, 23 Jun 2016 15:37:05 +0000 (08:37 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 23 Jun 2016 15:37:06 +0000 (08:37 -0700)
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2052263003

Review-Url: https://codereview.chromium.org/2078483002

28 files changed:
gyp/gpu.gypi
src/gpu/GrBatchFlushState.cpp
src/gpu/GrBatchFlushState.h
src/gpu/GrDrawTarget.cpp
src/gpu/GrGpu.cpp
src/gpu/GrGpu.h
src/gpu/GrGpuCommandBuffer.cpp [new file with mode: 0644]
src/gpu/GrGpuCommandBuffer.h
src/gpu/batches/GrBatch.h
src/gpu/batches/GrClearBatch.h
src/gpu/batches/GrCopySurfaceBatch.h
src/gpu/batches/GrDiscardBatch.h
src/gpu/batches/GrVertexBatch.cpp
src/gpu/gl/GrGLGpu.cpp
src/gpu/gl/GrGLGpu.h
src/gpu/gl/GrGLGpuCommandBuffer.h
src/gpu/vk/GrVkCaps.cpp
src/gpu/vk/GrVkCommandBuffer.cpp
src/gpu/vk/GrVkCommandBuffer.h
src/gpu/vk/GrVkGpu.cpp
src/gpu/vk/GrVkGpu.h
src/gpu/vk/GrVkGpuCommandBuffer.cpp
src/gpu/vk/GrVkGpuCommandBuffer.h
src/gpu/vk/GrVkPipelineState.cpp
src/gpu/vk/GrVkResourceProvider.cpp
tests/VkClearTests.cpp
tests/VkUploadPixelsTests.cpp
tools/gpu/GrTest.cpp

index 0fbfea1..cd7a78d 100644 (file)
       '<(skia_src_path)/gpu/GrGpu.cpp',
       '<(skia_src_path)/gpu/GrGpu.h',
       '<(skia_src_path)/gpu/GrGpuResourceCacheAccess.h',
+      '<(skia_src_path)/gpu/GrGpuCommandBuffer.cpp',
       '<(skia_src_path)/gpu/GrGpuCommandBuffer.h',
       '<(skia_src_path)/gpu/GrGpuResourcePriv.h',
       '<(skia_src_path)/gpu/GrGpuResource.cpp',
index c4ba264..4e51ae4 100644 (file)
@@ -13,6 +13,7 @@
 GrBatchFlushState::GrBatchFlushState(GrGpu* gpu, GrResourceProvider* resourceProvider)
     : fGpu(gpu)
     , fResourceProvider(resourceProvider)
+    , fCommandBuffer(nullptr)
     , fVertexPool(gpu)
     , fIndexPool(gpu)
     , fLastIssuedToken(GrBatchDrawToken::AlreadyFlushedToken())
index 0b2e2bd..d2d9a4b 100644 (file)
@@ -11,6 +11,7 @@
 #include "GrBufferAllocPool.h"
 #include "batches/GrVertexBatch.h"
 
+class GrGpuCommandBuffer;
 class GrResourceProvider;
 
 /** Tracks the state across all the GrBatches in a GrDrawTarget flush. */
@@ -84,6 +85,9 @@ public:
 
     void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); }
 
+    GrGpuCommandBuffer* commandBuffer() { return fCommandBuffer; }
+    void setCommandBuffer(GrGpuCommandBuffer* buffer) { fCommandBuffer = buffer; }
+
     GrGpu* gpu() { return fGpu; }
 
     void reset() {
@@ -97,6 +101,8 @@ private:
 
     GrResourceProvider*                                 fResourceProvider;
 
+    GrGpuCommandBuffer*                                 fCommandBuffer;
+
     GrVertexBufferAllocPool                             fVertexPool;
     GrIndexBufferAllocPool                              fIndexPool;
 
index 7213a92..d498d49 100644 (file)
@@ -11,6 +11,7 @@
 #include "GrCaps.h"
 #include "GrDrawContext.h"
 #include "GrGpu.h"
+#include "GrGpuCommandBuffer.h"
 #include "GrPath.h"
 #include "GrPipeline.h"
 #include "GrMemoryPool.h"
@@ -209,10 +210,32 @@ void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) {
 void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
     // Draw all the generated geometry.
     SkRandom random;
+    GrRenderTarget* currentRT = nullptr;
+    SkAutoTDelete<GrGpuCommandBuffer> commandBuffer;
     for (int i = 0; i < fBatches.count(); ++i) {
         if (!fBatches[i]) {
             continue;
         }
+        if (fBatches[i]->renderTarget() != currentRT) {
+            if (commandBuffer) {
+                commandBuffer->end();
+                // For now just use size of whole render target, but this should be updated to
+                // only be the actual bounds of the various draws.
+                SkIRect bounds = SkIRect::MakeWH(currentRT->width(), currentRT->height());
+                commandBuffer->submit(bounds);
+                commandBuffer.reset();
+            }
+            currentRT = fBatches[i]->renderTarget();
+            if (currentRT) {
+                static const GrGpuCommandBuffer::LoadAndStoreInfo kBasicLoadStoreInfo
+                    { GrGpuCommandBuffer::LoadOp::kLoad,GrGpuCommandBuffer::StoreOp::kStore,
+                      GrColor_ILLEGAL };
+                commandBuffer.reset(fGpu->createCommandBuffer(currentRT,
+                                                              kBasicLoadStoreInfo,   // Color
+                                                              kBasicLoadStoreInfo)); // Stencil
+            }
+            flushState->setCommandBuffer(commandBuffer);
+        }
         if (fDrawBatchBounds) {
             const SkRect& bounds = fBatches[i]->bounds();
             SkIRect ibounds;
@@ -225,6 +248,14 @@ void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
         }
         fBatches[i]->draw(flushState);
     }
+    if (commandBuffer) {
+        commandBuffer->end();
+        // For now just use size of whole render target, but this should be updated to
+        // only be the actual bounds of the various draws.
+        SkIRect bounds = SkIRect::MakeWH(currentRT->width(), currentRT->height());
+        commandBuffer->submit(bounds);
+        flushState->setCommandBuffer(nullptr);
+    }
 
     fGpu->finishDrawTarget();
 }
index a381f31..0a2592d 100644 (file)
@@ -243,23 +243,6 @@ GrBuffer* GrGpu::createBuffer(size_t size, GrBufferType intendedType,
     return buffer;
 }
 
-void GrGpu::clear(const SkIRect& rect,
-                  GrColor color,
-                  GrRenderTarget* renderTarget) {
-    SkASSERT(renderTarget);
-    SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect));
-    this->handleDirtyContext();
-    this->onClear(renderTarget, rect, color);
-}
-
-void GrGpu::clearStencilClip(const SkIRect& rect,
-                             bool insideClip,
-                             GrRenderTarget* renderTarget) {
-    SkASSERT(renderTarget);
-    this->handleDirtyContext();
-    this->onClearStencilClip(renderTarget, rect, insideClip);
-}
-
 bool GrGpu::copySurface(GrSurface* dst,
                         GrSurface* src,
                         const SkIRect& srcRect,
@@ -489,18 +472,3 @@ const GrGpu::MultisampleSpecs& GrGpu::getMultisampleSpecs(GrRenderTarget* rt,
     return specs;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-
-bool GrGpu::draw(const GrPipeline& pipeline,
-                 const GrPrimitiveProcessor& primProc,
-                 const GrMesh* meshes,
-                 int meshCount) {
-    if (primProc.numAttribs() > this->caps()->maxVertexAttributes()) {
-        fStats.incNumFailedDraws();
-        return false;
-    }
-    this->handleDirtyContext();
-
-    this->onDraw(pipeline, primProc, meshes, meshCount);
-    return true;
-}
index a99ce8f..f8528a1 100644 (file)
@@ -300,20 +300,6 @@ public:
                         size_t offset, size_t rowBytes);
 
     /**
-     * Clear the passed in render target. Ignores the draw state and clip.
-     */
-    void clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget);
-
-
-    void clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* renderTarget);
-
-    /**
-     * Discards the contents render target. nullptr indicates that the current render target should
-     * be discarded.
-     **/
-    virtual void discard(GrRenderTarget* = nullptr) = 0;
-
-    /**
      * This is can be called before allocating a texture to be a dst for copySurface. It will
      * populate the origin, config, and flags fields of the desc such that copySurface can
      * efficiently succeed. It should only succeed if it can allow copySurface to perform a copy
@@ -363,20 +349,10 @@ public:
 
     // Creates a GrGpuCommandBuffer in which the GrDrawTarget can send draw commands to instead of
     // directly to the Gpu object.
-    virtual GrGpuCommandBuffer* createCommandBuffer(const GrRenderTarget& target,
-                                                    GrGpuCommandBuffer::LoadAndStoreOp colorOp,
-                                                    GrColor colorClear,
-                                                    GrGpuCommandBuffer::LoadAndStoreOp stencilOp,
-                                                    GrColor stencilClear) = 0;
-
-    // We pass in an array of meshCount GrMesh to the draw. The backend should loop over each
-    // GrMesh object and emit a draw for it. Each draw will use the same GrPipeline and
-    // GrPrimitiveProcessor. This may fail if the draw would exceed any resource limits (e.g.
-    // number of vertex attributes is too large).
-    bool draw(const GrPipeline&,
-              const GrPrimitiveProcessor&,
-              const GrMesh*,
-              int meshCount);
+    virtual GrGpuCommandBuffer* createCommandBuffer(
+            GrRenderTarget* target,
+            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
+            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) = 0;
 
     // Called by drawtarget when flushing.
     // Provides a hook for post-flush actions (e.g. PLS reset and Vulkan command buffer submits).
@@ -493,6 +469,12 @@ public:
     // This is only to be used by testing code
     virtual void resetShaderCacheForTesting() const {}
 
+    void handleDirtyContext() {
+        if (fResetBits) {
+            this->resetContext();
+        }
+    }
+
 protected:
     static void ElevateDrawPreference(GrGpu::DrawPreference* preference,
                                       GrGpu::DrawPreference elevation) {
@@ -504,12 +486,6 @@ protected:
         *preference = SkTMax(*preference, elevation);
     }
 
-    void handleDirtyContext() {
-        if (fResetBits) {
-            this->resetContext();
-        }
-    }
-
     // Handles cases where a surface will be updated without a call to flushRenderTarget
     void didWriteToSurface(GrSurface* surface, const SkIRect* bounds, uint32_t mipLevels = 1) const;
 
@@ -543,19 +519,6 @@ private:
     virtual GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern,
                                      const void* data) = 0;
 
-    // overridden by backend-specific derived class to perform the clear.
-    virtual void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) = 0;
-
-    // Overridden by backend specific classes to perform a clear of the stencil clip bits.  This is
-    // ONLY used by the the clip target
-    virtual void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) = 0;
-
-    // overridden by backend-specific derived class to perform the draw call.
-    virtual void onDraw(const GrPipeline&,
-                        const GrPrimitiveProcessor&,
-                        const GrMesh*,
-                        int meshCount) = 0;
-
     virtual bool onMakeCopyForTextureParams(GrTexture* texture, const GrTextureParams&,
                                             GrTextureProducer::CopyParams*) const { return false; }
 
diff --git a/src/gpu/GrGpuCommandBuffer.cpp b/src/gpu/GrGpuCommandBuffer.cpp
new file mode 100644 (file)
index 0000000..f79cb0f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+* Copyright 2016 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "GrGpuCommandBuffer.h"
+
+#include "GrGpu.h"
+#include "GrPrimitiveProcessor.h"
+#include "GrRenderTarget.h"
+#include "SkRect.h"
+
+void GrGpuCommandBuffer::submit(const SkIRect& bounds) {
+    this->gpu()->handleDirtyContext();
+    this->onSubmit(bounds);
+}
+
+void GrGpuCommandBuffer::clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget) {
+    SkASSERT(renderTarget);
+    SkASSERT(SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(rect));
+    this->onClear(renderTarget, rect, color);
+}
+
+void GrGpuCommandBuffer::clearStencilClip(const SkIRect& rect,
+                                          bool insideClip,
+                                          GrRenderTarget* renderTarget) {
+    SkASSERT(renderTarget);
+    this->onClearStencilClip(renderTarget, rect, insideClip);
+}
+
+
+bool GrGpuCommandBuffer::draw(const GrPipeline& pipeline,
+                              const GrPrimitiveProcessor& primProc,
+                              const GrMesh* mesh,
+                              int meshCount) {
+    if (primProc.numAttribs() > this->gpu()->caps()->maxVertexAttributes()) {
+        this->gpu()->stats()->incNumFailedDraws();
+        return false;
+    }
+    this->onDraw(pipeline, primProc, mesh, meshCount);
+    return true;
+}
+
index 3c6e611..9abcc20 100644 (file)
 
 #include "GrColor.h"
 
+class GrGpu;
+class GrMesh;
+class GrPipeline;
+class GrPrimitiveProcessor;
 class GrRenderTarget;
+struct SkIRect;
 
+/**
+ * The GrGpuCommandBuffer is a series of commands (draws, clears, and discards), which all target
+ * the same render target. It is possible that these commands execute immediately (GL), or get
+ * buffered up for later execution (Vulkan). GrBatches will execute their draw commands into a
+ * GrGpuCommandBuffer.
+ */
 class GrGpuCommandBuffer {
 public:
-    enum LoadAndStoreOp {
-        kLoadAndStore_LoadAndStoreOp,
-        kLoadAndDiscard_LoadAndStoreOp,
-        kClearAndStore_LoadAndStoreOp,
-        kClearAndDiscard_LoadAndStoreOp,
-        kDiscardAndStore_LoadAndStoreOp,
-        kDiscardAndDiscard_LoadAndStoreOp,
+    enum class LoadOp {
+        kLoad,
+        kClear,
+        kDiscard,
+    };
+
+    enum class StoreOp {
+        kStore,
+        kDiscard,
+    };
+
+    struct LoadAndStoreInfo {
+        LoadOp  fLoadOp;
+        StoreOp fStoreOp;
+        GrColor fClearColor;
     };
 
     GrGpuCommandBuffer() {}
@@ -31,7 +50,46 @@ public:
 
     // Sends the command buffer off to the GPU object to execute the commands built up in the
     // buffer. The gpu object is allowed to defer execution of the commands until it is flushed.
-    virtual void submit() = 0;
+    // The bounds should represent the bounds of all the draws put into the command buffer.
+    void submit(const SkIRect& bounds);
+
+    // We pass in an array of meshCount GrMesh to the draw. The backend should loop over each
+    // GrMesh object and emit a draw for it. Each draw will use the same GrPipeline and
+    // GrPrimitiveProcessor. This may fail if the draw would exceed any resource limits (e.g.
+    // number of vertex attributes is too large).
+    bool draw(const GrPipeline&,
+              const GrPrimitiveProcessor&,
+              const GrMesh*,
+              int meshCount);
+
+    /**
+    * Clear the passed in render target. Ignores the draw state and clip.
+    */
+    void clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget);
+
+    void clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* renderTarget);
+    /**
+    * Discards the contents render target. nullptr indicates that the current render target should
+    * be discarded.
+    **/
+    // TODO: This should be removed in the future to favor using the load and store ops for discard
+    virtual void discard(GrRenderTarget* = nullptr) = 0;
+
+private:
+    virtual GrGpu* gpu() = 0;
+    virtual void onSubmit(const SkIRect& bounds) = 0;
+
+    // overridden by backend-specific derived class to perform the draw call.
+    virtual void onDraw(const GrPipeline&,
+                        const GrPrimitiveProcessor&,
+                        const GrMesh*,
+                        int meshCount) = 0;
+
+    // overridden by backend-specific derived class to perform the clear.
+    virtual void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) = 0;
+
+    virtual void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) = 0;
+
 };
 
 #endif
index f055933..b26cdde 100644 (file)
@@ -16,6 +16,7 @@
 #include <new>
 
 class GrCaps;
+class GrGpuCommandBuffer;
 class GrBatchFlushState;
 class GrRenderTarget;
 
index ba4b6d6..f2249ce 100644 (file)
@@ -11,6 +11,7 @@
 #include "GrBatch.h"
 #include "GrBatchFlushState.h"
 #include "GrGpu.h"
+#include "GrGpuCommandBuffer.h"
 #include "GrRenderTarget.h"
 
 class GrClearBatch final : public GrBatch {
@@ -59,7 +60,7 @@ private:
     void onPrepare(GrBatchFlushState*) override {}
 
     void onDraw(GrBatchFlushState* state) override {
-        state->gpu()->clear(fRect, fColor, fRenderTarget.get());
+        state->commandBuffer()->clear(fRect, fColor, fRenderTarget.get());
     }
 
     SkIRect                                                 fRect;
@@ -100,7 +101,7 @@ private:
     void onPrepare(GrBatchFlushState*) override {}
 
     void onDraw(GrBatchFlushState* state) override {
-        state->gpu()->clearStencilClip(fRect, fInsideClip, fRenderTarget.get());
+        state->commandBuffer()->clearStencilClip(fRect, fInsideClip, fRenderTarget.get());
     }
 
     SkIRect                                                 fRect;
index 3926643..900bcf3 100644 (file)
@@ -36,7 +36,7 @@ public:
         GrRenderTarget* rt = fDst.get()->asRenderTarget();
         return rt ? rt->getUniqueID() : 0;
     }
-    GrRenderTarget* renderTarget() const override { return fDst.get()->asRenderTarget(); }
+    GrRenderTarget* renderTarget() const override { return nullptr; }
 
     SkString dumpInfo() const override {
         SkString string;
@@ -64,7 +64,12 @@ private:
     void onPrepare(GrBatchFlushState*) override {}
 
     void onDraw(GrBatchFlushState* state) override {
-        state->gpu()->copySurface(fDst.get(), fSrc.get(), fSrcRect, fDstPoint);
+        if (!state->commandBuffer()) {
+            state->gpu()->copySurface(fDst.get(), fSrc.get(), fSrcRect, fDstPoint);
+        } else {
+            // currently we are not sending copies through the GrGpuCommandBuffer
+            SkASSERT(false);
+        }
     }
 
     GrPendingIOResource<GrSurface, kWrite_GrIOType> fDst;
index 65b6c4b..3c19b68 100644 (file)
@@ -42,7 +42,7 @@ private:
     void onPrepare(GrBatchFlushState*) override {}
 
     void onDraw(GrBatchFlushState* state) override {
-        state->gpu()->discard(fRenderTarget.get());
+        state->commandBuffer()->discard(fRenderTarget.get());
     }
 
     GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
index 8a5dd62..af3a186 100644 (file)
@@ -75,8 +75,8 @@ void GrVertexBatch::onDraw(GrBatchFlushState* state) {
             state->doUpload(fInlineUploads[currUploadIdx++].fUpload);
         }
         const QueuedDraw &draw = fQueuedDraws[currDrawIdx];
-        state->gpu()->draw(*this->pipeline(), *draw.fGeometryProcessor.get(),
-                           fMeshes.begin() + currMeshIdx, draw.fMeshCnt);
+        state->commandBuffer()->draw(*this->pipeline(), *draw.fGeometryProcessor.get(),
+                                     fMeshes.begin() + currMeshIdx, draw.fMeshCnt);
         currMeshIdx += draw.fMeshCnt;
         state->flushToken();
     }
index b044b7b..acc2e31 100644 (file)
@@ -2150,7 +2150,9 @@ void GrGLGpu::disableScissor() {
     }
 }
 
-void GrGLGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
+void GrGLGpu::clear(const SkIRect& rect, GrColor color, GrRenderTarget* target) {
+    this->handleDirtyContext();
+
     // parent class should never let us get here with no RT
     SkASSERT(target);
     GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(target);
@@ -2238,8 +2240,9 @@ void GrGLGpu::clearStencil(GrRenderTarget* target) {
     fHWStencilSettings.invalidate();
 }
 
-void GrGLGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) {
+void GrGLGpu::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* target) {
     SkASSERT(target);
+    this->handleDirtyContext();
 
     GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
     // this should only be called internally when we know we have a
@@ -2624,11 +2627,10 @@ bool GrGLGpu::onReadPixels(GrSurface* surface,
     return true;
 }
 
-GrGpuCommandBuffer* GrGLGpu::createCommandBuffer(const GrRenderTarget& target,
-                                                 GrGpuCommandBuffer::LoadAndStoreOp colorOp,
-                                                 GrColor colorClear,
-                                                 GrGpuCommandBuffer::LoadAndStoreOp stencilOp,
-                                                 GrColor stencilClear) {
+GrGpuCommandBuffer* GrGLGpu::createCommandBuffer(
+        GrRenderTarget* target,
+        const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
+        const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
     return new GrGLGpuCommandBuffer(this);
 }
 
@@ -2729,10 +2731,12 @@ GrGLenum gPrimitiveType2GLMode[] = {
     #endif
 #endif
 
-void GrGLGpu::onDraw(const GrPipeline& pipeline,
-                     const GrPrimitiveProcessor& primProc,
-                     const GrMesh* meshes,
-                     int meshCount) {
+void GrGLGpu::draw(const GrPipeline& pipeline,
+                   const GrPrimitiveProcessor& primProc,
+                   const GrMesh* meshes,
+                   int meshCount) {
+    this->handleDirtyContext();
+
     if (!this->flushGLState(pipeline, primProc)) {
         return;
     }
index 9cce41c..aead715 100644 (file)
@@ -54,7 +54,7 @@ public:
         return static_cast<GrGLPathRendering*>(pathRendering());
     }
 
-    void discard(GrRenderTarget*) override;
+    void discard(GrRenderTarget*);
 
     // Used by GrGLProgram to configure OpenGL state.
     void bindTexture(int unitIdx, const GrTextureParams& params, bool allowSRGBInputs,
@@ -95,17 +95,34 @@ public:
     // Called by GrGLBuffer after its buffer object has been destroyed.
     void notifyBufferReleased(const GrGLBuffer*);
 
+    // The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
+    // Thus this is the implementation of the draw call for the corresponding passthrough function
+    // on GrGLGpuCommandBuffer.
+    void draw(const GrPipeline&,
+              const GrPrimitiveProcessor&,
+              const GrMesh*,
+              int meshCount);
+
+    // The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
+    // Thus this is the implementation of the clear call for the corresponding passthrough function
+    // on GrGLGpuCommandBuffer.
+    void clear(const SkIRect& rect, GrColor color, GrRenderTarget* renderTarget);
+
+    // The GrGLGpuCommandBuffer does not buffer up draws before submitting them to the gpu.
+    // Thus this is the implementation of the clearStencil call for the corresponding passthrough
+    // function on GrGLGpuCommandBuffer.
+    void clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* renderTarget);
+
     const GrGLContext* glContextForTesting() const override {
         return &this->glContext();
     }
 
     void clearStencil(GrRenderTarget*) override;
 
-    GrGpuCommandBuffer* createCommandBuffer(const GrRenderTarget& target,
-                                            GrGpuCommandBuffer::LoadAndStoreOp colorOp,
-                                            GrColor colorClear,
-                                            GrGpuCommandBuffer::LoadAndStoreOp stencilOp,
-                                            GrColor stencilClear) override;
+    GrGpuCommandBuffer* createCommandBuffer(
+            GrRenderTarget* target,
+            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
+            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override;
 
     void invalidateBoundRenderTarget() {
         fHWBoundRenderTargetUniqueID = SK_InvalidUniqueID;
@@ -159,10 +176,6 @@ private:
                            bool renderTarget, GrGLTexture::TexParams* initialTexParams,
                            const SkTArray<GrMipLevel>& texels);
 
-    void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override;
-
-    void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
-
     bool onMakeCopyForTextureParams(GrTexture*, const GrTextureParams&,
                                     GrTextureProducer::CopyParams*) const override;
 
@@ -199,11 +212,6 @@ private:
 
     void onResolveRenderTarget(GrRenderTarget* target) override;
 
-    void onDraw(const GrPipeline&,
-                const GrPrimitiveProcessor&,
-                const GrMesh*,
-                int meshCount) override;
-
     bool onCopySurface(GrSurface* dst,
                        GrSurface* src,
                        const SkIRect& srcRect,
index 8925322..0591ffd 100644 (file)
 
 #include "GrGpuCommandBuffer.h"
 
-class GrGLGpu;
+#include "GrGLGpu.h"
 
 class GrGLGpuCommandBuffer : public GrGpuCommandBuffer {
+/**
+ * We do not actually buffer up draws or do any work in the this class for GL. Instead commands
+ * are immediately sent to the gpu to execute. Thus all the commands in this class are simply
+ * pass through functions to corresponding calls in the GrGLGpu class.
+ */
 public:
-    GrGLGpuCommandBuffer(GrGLGpu* gpu) /*: fGpu(gpu)*/ {}
+    GrGLGpuCommandBuffer(GrGLGpu* gpu) : fGpu(gpu) {}
 
     virtual ~GrGLGpuCommandBuffer() {}
 
     void end() override {}
 
-    void submit() override {}
+    void discard(GrRenderTarget* rt) override { fGpu->discard(rt); }
 
 private:
-    // commented out to appease clang compiler warning about unused private field
-   // GrGLGpu*                    fGpu;
+    GrGpu* gpu() override { return fGpu; }
+
+    void onSubmit(const SkIRect& bounds) override {}
+
+    void onDraw(const GrPipeline& pipeline,
+                const GrPrimitiveProcessor& primProc,
+                const GrMesh* mesh,
+                int meshCount) override {
+        fGpu->draw(pipeline, primProc, mesh, meshCount);
+    }
+
+    void onClear(GrRenderTarget* rt, const SkIRect& rect, GrColor color) override {
+        fGpu->clear(rect, color, rt);
+    }
+
+    void onClearStencilClip(GrRenderTarget* rt, const SkIRect& rect, bool insideClip) override {
+        fGpu->clearStencilClip(rect, insideClip, rt);
+    }
+
+    GrGLGpu*                    fGpu;
 
     typedef GrGpuCommandBuffer INHERITED;
 };
index 60934de..833dc24 100644 (file)
@@ -31,7 +31,7 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface*
     fCompressedTexSubImageSupport = false; //TODO: figure this out
     fOversizedStencilSupport = false; //TODO: figure this out
 
-    fUseDrawInsteadOfClear = false; //TODO: figure this out
+    fUseDrawInsteadOfClear = false;
 
     fMapBufferFlags = kNone_MapFlags; //TODO: figure this out
     fBufferMapThreshold = SK_MaxS32;  //TODO: figure this out
index 2b636ed..4a469fe 100644 (file)
 #include "GrVkPipelineState.h"
 #include "GrVkTransferBuffer.h"
 #include "GrVkUtil.h"
-
-
-GrVkCommandBuffer::~GrVkCommandBuffer() {
-    // Should have ended any render pass we're in the middle of
-    SkASSERT(!fActiveRenderPass);
-}
+#include "SkRect.h"
 
 void GrVkCommandBuffer::invalidateState() {
     fBoundVertexBuffer = VK_NULL_HANDLE;
@@ -41,18 +36,14 @@ void GrVkCommandBuffer::invalidateState() {
 
 void GrVkCommandBuffer::freeGPUData(const GrVkGpu* gpu) const {
     SkASSERT(!fIsActive);
-    SkASSERT(!fActiveRenderPass);
     for (int i = 0; i < fTrackedResources.count(); ++i) {
         fTrackedResources[i]->unref(gpu);
     }
 
-    // Destroy the fence, if any
-    if (VK_NULL_HANDLE != fSubmitFence) {
-        GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr));
-    }
-
     GR_VK_CALL(gpu->vkInterface(), FreeCommandBuffers(gpu->device(), gpu->cmdPool(),
                                                       1, &fCmdBuffer));
+
+    this->onFreeGPUData(gpu);
 }
 
 void GrVkCommandBuffer::abandonSubResources() const {
@@ -240,6 +231,11 @@ void GrVkCommandBuffer::setBlendConstants(const GrVkGpu* gpu,
 ///////////////////////////////////////////////////////////////////////////////
 // PrimaryCommandBuffer
 ////////////////////////////////////////////////////////////////////////////////
+GrVkPrimaryCommandBuffer::~GrVkPrimaryCommandBuffer() {
+    // Should have ended any render pass we're in the middle of
+    SkASSERT(!fActiveRenderPass);
+}
+
 GrVkPrimaryCommandBuffer* GrVkPrimaryCommandBuffer::Create(const GrVkGpu* gpu,
                                                            VkCommandPool cmdPool) {
     const VkCommandBufferAllocateInfo cmdInfo = {
@@ -283,13 +279,33 @@ void GrVkPrimaryCommandBuffer::end(const GrVkGpu* gpu) {
 }
 
 void GrVkPrimaryCommandBuffer::beginRenderPass(const GrVkGpu* gpu,
-                                        const GrVkRenderPass* renderPass,
-                                        const GrVkRenderTarget& target) {
+                                               const GrVkRenderPass* renderPass,
+                                               uint32_t clearCount,
+                                               const VkClearValue* clearValues,
+                                               const GrVkRenderTarget& target,
+                                               const SkIRect& bounds,
+                                               bool forSecondaryCB) {
     SkASSERT(fIsActive);
     SkASSERT(!fActiveRenderPass);
+    SkASSERT(renderPass->isCompatible(target));
+
     VkRenderPassBeginInfo beginInfo;
-    VkSubpassContents contents;
-    renderPass->getBeginInfo(target, &beginInfo, &contents);
+    VkRect2D renderArea;
+    renderArea.offset = { bounds.fLeft , bounds.fTop };
+    renderArea.extent = { (uint32_t)bounds.width(), (uint32_t)bounds.height() };
+
+    memset(&beginInfo, 0, sizeof(VkRenderPassBeginInfo));
+    beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+    beginInfo.pNext = nullptr;
+    beginInfo.renderPass = renderPass->vkRenderPass();
+    beginInfo.framebuffer = target.framebuffer()->framebuffer();
+    beginInfo.renderArea = renderArea;
+    beginInfo.clearValueCount = clearCount;
+    beginInfo.pClearValues = clearValues;
+
+    VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS
+                                                : VK_SUBPASS_CONTENTS_INLINE;
+
     GR_VK_CALL(gpu->vkInterface(), CmdBeginRenderPass(fCmdBuffer, &beginInfo, contents));
     fActiveRenderPass = renderPass;
     this->addResource(renderPass);
@@ -491,6 +507,14 @@ void GrVkPrimaryCommandBuffer::clearDepthStencilImage(const GrVkGpu* gpu,
                                                              subRanges));
 }
 
+void GrVkPrimaryCommandBuffer::onFreeGPUData(const GrVkGpu* gpu) const {
+    SkASSERT(!fActiveRenderPass);
+    // Destroy the fence, if any
+    if (VK_NULL_HANDLE != fSubmitFence) {
+        GR_VK_CALL(gpu->vkInterface(), DestroyFence(gpu->device(), fSubmitFence, nullptr));
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // SecondaryCommandBuffer
 ////////////////////////////////////////////////////////////////////////////////
index 709e4c6..87c33c0 100644 (file)
@@ -21,8 +21,6 @@ class GrVkTransferBuffer;
 
 class GrVkCommandBuffer : public GrVkResource {
 public:
-    ~GrVkCommandBuffer() override;
-
     void invalidateState();
 
     ////////////////////////////////////////////////////////////////////////////
@@ -125,7 +123,6 @@ protected:
             , fIsActive(false)
             , fActiveRenderPass(rp)
             , fCmdBuffer(cmdBuffer)
-            , fSubmitFence(VK_NULL_HANDLE)
             , fBoundVertexBufferIsValid(false)
             , fBoundIndexBufferIsValid(false) {
             this->invalidateState();
@@ -142,12 +139,12 @@ protected:
         const GrVkRenderPass*     fActiveRenderPass;
 
         VkCommandBuffer           fCmdBuffer;
-        VkFence                   fSubmitFence;
 
 private:
     static const int kInitialTrackedResourcesCount = 32;
 
     void freeGPUData(const GrVkGpu* gpu) const override;
+    virtual void onFreeGPUData(const GrVkGpu* gpu) const = 0;
     void abandonSubResources() const override;
 
     VkBuffer                                fBoundVertexBuffer;
@@ -166,6 +163,8 @@ class GrVkSecondaryCommandBuffer;
 
 class GrVkPrimaryCommandBuffer : public GrVkCommandBuffer {
 public:
+    ~GrVkPrimaryCommandBuffer() override;
+
     static GrVkPrimaryCommandBuffer* Create(const GrVkGpu* gpu, VkCommandPool cmdPool);
 
     void begin(const GrVkGpu* gpu);
@@ -175,7 +174,11 @@ public:
     // in the render pass.
     void beginRenderPass(const GrVkGpu* gpu,
                          const GrVkRenderPass* renderPass,
-                         const GrVkRenderTarget& target);
+                         uint32_t clearCount,
+                         const VkClearValue* clearValues,
+                         const GrVkRenderTarget& target,
+                         const SkIRect& bounds,
+                         bool forSecondaryCB);
     void endRenderPass(const GrVkGpu* gpu);
 
     // Submits the SecondaryCommandBuffer into this command buffer. It is required that we are
@@ -252,7 +255,13 @@ public:
     bool finished(const GrVkGpu* gpu) const;
 
 private:
-    explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer) : INHERITED(cmdBuffer) {}
+    explicit GrVkPrimaryCommandBuffer(VkCommandBuffer cmdBuffer)
+        : INHERITED(cmdBuffer)
+        , fSubmitFence(VK_NULL_HANDLE) {}
+
+    void onFreeGPUData(const GrVkGpu* gpu) const override;
+
+    VkFence                   fSubmitFence;
 
     typedef GrVkCommandBuffer INHERITED;
 };
@@ -271,6 +280,8 @@ private:
         : INHERITED(cmdBuffer, compatibleRenderPass) {
     }
 
+    void onFreeGPUData(const GrVkGpu* gpu) const override {}
+
     friend class GrVkPrimaryCommandBuffer;
 
     typedef GrVkCommandBuffer INHERITED;
index 05aa1de..3343741 100644 (file)
@@ -174,13 +174,12 @@ GrVkGpu::~GrVkGpu() {
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrGpuCommandBuffer* GrVkGpu::createCommandBuffer(const GrRenderTarget& target,
-                                                 GrGpuCommandBuffer::LoadAndStoreOp colorOp,
-                                                 GrColor colorClear,
-                                                 GrGpuCommandBuffer::LoadAndStoreOp stencilOp,
-                                                 GrColor stencilClear) {
-    const GrVkRenderTarget& vkRT = static_cast<const GrVkRenderTarget&>(target);
-    return new GrVkGpuCommandBuffer(this, vkRT, colorOp, colorClear, stencilOp, stencilClear);
+GrGpuCommandBuffer* GrVkGpu::createCommandBuffer(
+            GrRenderTarget* target,
+            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
+            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
+    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
+    return new GrVkGpuCommandBuffer(this, vkRT, colorInfo, stencilInfo);
 }
 
 void GrVkGpu::submitCommandBuffer(SyncQueue sync) {
@@ -819,31 +818,6 @@ void GrVkGpu::generateMipmap(GrVkTexture* tex) const {
     oldResource->unref(this);
 }
 
-
-////////////////////////////////////////////////////////////////////////////////
-
-void GrVkGpu::bindGeometry(const GrPrimitiveProcessor& primProc,
-                           const GrNonInstancedMesh& mesh) {
-    // There is no need to put any memory barriers to make sure host writes have finished here.
-    // When a command buffer is submitted to a queue, there is an implicit memory barrier that
-    // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of
-    // an active RenderPass.
-    GrVkVertexBuffer* vbuf;
-    vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer();
-    SkASSERT(vbuf);
-    SkASSERT(!vbuf->isMapped());
-
-    fCurrentCmdBuffer->bindVertexBuffer(this, vbuf);
-
-    if (mesh.isIndexed()) {
-        GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer();
-        SkASSERT(ibuf);
-        SkASSERT(!ibuf->isMapped());
-
-        fCurrentCmdBuffer->bindIndexBuffer(this, ibuf);
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
@@ -1087,157 +1061,6 @@ void GrVkGpu::clearStencil(GrRenderTarget* target) {
     fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
 }
 
-void GrVkGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) {
-    SkASSERT(target);
-
-    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
-    GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
-    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)sb;
-
-    // this should only be called internally when we know we have a
-    // stencil buffer.
-    SkASSERT(sb);
-    int stencilBitCount = sb->bits();
-
-    // The contract with the callers does not guarantee that we preserve all bits in the stencil
-    // during this clear. Thus we will clear the entire stencil to the desired value.
-
-    VkClearDepthStencilValue vkStencilColor;
-    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
-    if (insideClip) {
-        vkStencilColor.stencil = (1 << (stencilBitCount - 1));
-    } else {
-        vkStencilColor.stencil = 0;
-    }
-
-    vkStencil->setImageLayout(this,
-                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
-                              VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
-                              VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
-                              false);
-
-    // Change layout of our render target so it can be used as the color attachment. This is what
-    // the render pass expects when it begins.
-    vkRT->setImageLayout(this,
-                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
-                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
-                         false);
-
-    VkClearRect clearRect;
-    // Flip rect if necessary
-    SkIRect vkRect = rect;
-
-    if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
-        vkRect.fTop = vkRT->height() - rect.fBottom;
-        vkRect.fBottom = vkRT->height() - rect.fTop;
-    }
-
-    clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
-    clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
-
-    clearRect.baseArrayLayer = 0;
-    clearRect.layerCount = 1;
-
-    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
-    SkASSERT(renderPass);
-    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
-
-    uint32_t stencilIndex;
-    SkAssertResult(renderPass->stencilAttachmentIndex(&stencilIndex));
-
-    VkClearAttachment attachment;
-    attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
-    attachment.colorAttachment = 0; // this value shouldn't matter
-    attachment.clearValue.depthStencil = vkStencilColor;
-
-    fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
-    fCurrentCmdBuffer->endRenderPass(this);
-
-    return;
-}
-
-void GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
-    // parent class should never let us get here with no RT
-    SkASSERT(target);
-
-    VkClearColorValue vkColor;
-    GrColorToRGBAFloat(color, vkColor.float32);
-
-    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
-
-    if (rect.width() != target->width() || rect.height() != target->height()) {
-        vkRT->setImageLayout(this,
-                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
-                             VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
-                             false);
-
-        // If we are using a stencil attachment we also need to change its layout to what the render
-        // pass is expecting.
-        if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment()) {
-            GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
-            vkStencil->setImageLayout(this,
-                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
-                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
-                                      VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
-                                      VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
-                                      false);
-        }
-
-        VkClearRect clearRect;
-        // Flip rect if necessary
-        SkIRect vkRect = rect;
-        if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
-            vkRect.fTop = vkRT->height() - rect.fBottom;
-            vkRect.fBottom = vkRT->height() - rect.fTop;
-        }
-        clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
-        clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
-        clearRect.baseArrayLayer = 0;
-        clearRect.layerCount = 1;
-
-        const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
-        SkASSERT(renderPass);
-        fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
-
-        uint32_t colorIndex;
-        SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex));
-
-        VkClearAttachment attachment;
-        attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-        attachment.colorAttachment = colorIndex;
-        attachment.clearValue.color = vkColor;
-
-        fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
-        fCurrentCmdBuffer->endRenderPass(this);
-        return;
-    }
-
-    vkRT->setImageLayout(this,
-                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                         VK_ACCESS_TRANSFER_WRITE_BIT,
-                         VK_PIPELINE_STAGE_TRANSFER_BIT,
-                         false);
-
-    VkImageSubresourceRange subRange;
-    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
-    subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-    subRange.baseMipLevel = 0;
-    subRange.levelCount = 1;
-    subRange.baseArrayLayer = 0;
-    subRange.layerCount = 1;
-
-    // In the future we may not actually be doing this type of clear at all. If we are inside a
-    // render pass or doing a non full clear then we will use CmdClearColorAttachment. The more
-    // common use case will be clearing an attachment at the start of a render pass, in which case
-    // we will use the clear load ops.
-    fCurrentCmdBuffer->clearColorImage(this,
-                                       vkRT,
-                                       &vkColor,
-                                       1, &subRange);
-}
-
 inline bool can_copy_image(const GrSurface* dst,
                            const GrSurface* src,
                            const GrVkGpu* gpu) {
@@ -1587,132 +1410,16 @@ bool GrVkGpu::onReadPixels(GrSurface* surface,
     return true;
 }
 
-void GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buffer) {
+void GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buffer,
+                                           const GrVkRenderPass* renderPass,
+                                           const VkClearValue* colorClear,
+                                           GrVkRenderTarget* target,
+                                           const SkIRect& bounds) {
+    // Currently it is fine for us to always pass in 1 for the clear count even if no attachment
+    // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the color attachment
+    // which is always at the first attachment.
+    fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target, bounds, true);
     fCurrentCmdBuffer->executeCommands(this, buffer);
-}
-
-sk_sp<GrVkPipelineState> GrVkGpu::prepareDrawState(const GrPipeline& pipeline,
-                                                   const GrPrimitiveProcessor& primProc,
-                                                   GrPrimitiveType primitiveType,
-                                                   const GrVkRenderPass& renderPass) {
-    sk_sp<GrVkPipelineState> pipelineState =
-        fResourceProvider.findOrCreateCompatiblePipelineState(pipeline,
-                                                              primProc,
-                                                              primitiveType,
-                                                              renderPass);
-    if (!pipelineState) {
-        return pipelineState;
-    }
-
-    pipelineState->setData(this, primProc, pipeline);
-
-    pipelineState->bind(this, fCurrentCmdBuffer);
-
-    GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline);
-
-    return pipelineState;
-}
-
-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);
-
-    GrPrimitiveType primitiveType = meshes[0].primitiveType();
-    sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
-                                                                    primProc,
-                                                                    primitiveType,
-                                                                    *renderPass);
-    if (!pipelineState) {
-        return;
-    }
-
-    // Change layout of our render target so it can be used as the color attachment
-    vkRT->setImageLayout(this,
-                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
-                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
-                         false);
-
-    // If we are using a stencil attachment we also need to update its layout
-    if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment()) {
-        GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
-        vkStencil->setImageLayout(this,
-                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
-                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
-                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
-                                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
-                                  false);
-    }
-
-    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
-
-    for (int i = 0; i < meshCount; ++i) {
-        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
-                // pipelineState:setData but this will allow for quicker freeing of resources if the
-                // pipelineState sits in a cache for a while.
-                pipelineState->freeTempResources(this);
-                SkDEBUGCODE(pipelineState = nullptr);
-                primitiveType = nonIdxMesh->primitiveType();
-                pipelineState = this->prepareDrawState(pipeline,
-                                                       primProc,
-                                                       primitiveType,
-                                                       *renderPass);
-                if (!pipelineState) {
-                    return;
-                }
-            }
-            SkASSERT(pipelineState);
-            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);
-
-    // Technically we don't have to call this here (since there is a safety check in
-    // pipelineState:setData but this will allow for quicker freeing of resources if the
-    // pipelineState sits in a cache for a while.
-    pipelineState->freeTempResources(this);
-
-#if SWAP_PER_DRAW
-    glFlush();
-#if defined(SK_BUILD_FOR_MAC)
-    aglSwapBuffers(aglGetCurrentContext());
-    int set_a_break_pt_here = 9;
-    aglSwapBuffers(aglGetCurrentContext());
-#elif defined(SK_BUILD_FOR_WIN32)
-    SwapBuf();
-    int set_a_break_pt_here = 9;
-    SwapBuf();
-#endif
-#endif
 }
+
index b076de2..a9470ae 100644 (file)
@@ -65,8 +65,6 @@ public:
                               GrPixelConfig srcConfig, DrawPreference*,
                               WritePixelTempDrawInfo*) override;
 
-    void discard(GrRenderTarget*) override {}
-
     bool onCopySurface(GrSurface* dst,
                        GrSurface* src,
                        const SkIRect& srcRect,
@@ -92,11 +90,10 @@ public:
 
     void clearStencil(GrRenderTarget* target) override;
 
-    GrGpuCommandBuffer* createCommandBuffer(const GrRenderTarget& target,
-                                            GrGpuCommandBuffer::LoadAndStoreOp colorOp,
-                                            GrColor colorClear,
-                                            GrGpuCommandBuffer::LoadAndStoreOp stencilOp,
-                                            GrColor stencilClear) override;
+    GrGpuCommandBuffer* createCommandBuffer(
+            GrRenderTarget* target,
+            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
+            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override;
 
     void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {}
 
@@ -117,7 +114,11 @@ public:
         return fCompiler;
     }
 
-    void submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer*);
+    void submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer*,
+                                      const GrVkRenderPass*,
+                                      const VkClearValue*,
+                                      GrVkRenderTarget*,
+                                      const SkIRect& bounds);
 
     void finishDrawTarget() override;
 
@@ -165,15 +166,6 @@ private:
     GrBuffer* onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern,
                              const void* data) override;
 
-    void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override;
-
-    void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
-
-    void onDraw(const GrPipeline&,
-                const GrPrimitiveProcessor&,
-                const GrMesh*,
-                int meshCount) override;
-
     bool onReadPixels(GrSurface* surface,
                       int left, int top, int width, int height,
                       GrPixelConfig,
@@ -191,14 +183,6 @@ private:
 
     void onResolveRenderTarget(GrRenderTarget* target) override {}
 
-    sk_sp<GrVkPipelineState> prepareDrawState(const GrPipeline&,
-                                              const GrPrimitiveProcessor&,
-                                              GrPrimitiveType,
-                                              const GrVkRenderPass&);
-
-    // Bind vertex and index buffers
-    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
     // work in the queue to finish before returning.
index f6104a3..f987231 100644 (file)
@@ -7,79 +7,85 @@
 
 #include "GrVkGpuCommandBuffer.h"
 
+#include "GrMesh.h"
+#include "GrPipeline.h"
+#include "GrRenderTargetPriv.h"
+#include "GrTextureAccess.h"
+#include "GrTexturePriv.h"
 #include "GrVkCommandBuffer.h"
 #include "GrVkGpu.h"
+#include "GrVkPipeline.h"
 #include "GrVkRenderPass.h"
 #include "GrVkRenderTarget.h"
 #include "GrVkResourceProvider.h"
+#include "GrVkTexture.h"
 
-void get_vk_load_store_ops(GrGpuCommandBuffer::LoadAndStoreOp op,
+void get_vk_load_store_ops(const GrGpuCommandBuffer::LoadAndStoreInfo& info,
                            VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* storeOp) {
-    switch (op) {
-        case GrGpuCommandBuffer::kLoadAndStore_LoadAndStoreOp:
+    switch (info.fLoadOp) {
+        case GrGpuCommandBuffer::LoadOp::kLoad:
             *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
-            *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
-            break;
-        case GrGpuCommandBuffer::kLoadAndDiscard_LoadAndStoreOp:
-            *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
-            *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
             break;
-        case GrGpuCommandBuffer::kClearAndStore_LoadAndStoreOp:
+        case GrGpuCommandBuffer::LoadOp::kClear:
             *loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
-            *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
             break;
-        case GrGpuCommandBuffer::kClearAndDiscard_LoadAndStoreOp:
-            *loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
-            *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-            break;
-        case GrGpuCommandBuffer::kDiscardAndStore_LoadAndStoreOp:
+        case GrGpuCommandBuffer::LoadOp::kDiscard:
             *loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            break;
+        default:
+            SK_ABORT("Invalid LoadOp");
+            *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+    }
+
+    switch (info.fStoreOp) {
+        case GrGpuCommandBuffer::StoreOp::kStore:
             *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
             break;
-        case GrGpuCommandBuffer::kDiscardAndDiscard_LoadAndStoreOp:
-            *loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+        case GrGpuCommandBuffer::StoreOp::kDiscard:
             *storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
             break;
         default:
-            SK_ABORT("Invalid LoadAndStoreOp");
-            *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+            SK_ABORT("Invalid StoreOp");
             *storeOp = VK_ATTACHMENT_STORE_OP_STORE;
-            break;
     }
 }
 
 GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu,
-                                           const GrVkRenderTarget& target,
-                                           LoadAndStoreOp colorOp, GrColor colorClear,
-                                           LoadAndStoreOp stencilOp, GrColor stencilClear)
-    : fGpu(gpu) {
+                                           GrVkRenderTarget* target,
+                                           const LoadAndStoreInfo& colorInfo,
+                                           const LoadAndStoreInfo& stencilInfo)
+    : fGpu(gpu)
+    , fRenderTarget(target)
+    , fIsEmpty(true) {
     VkAttachmentLoadOp vkLoadOp;
     VkAttachmentStoreOp vkStoreOp;
 
-    get_vk_load_store_ops(colorOp, &vkLoadOp, &vkStoreOp);
+    get_vk_load_store_ops(colorInfo, &vkLoadOp, &vkStoreOp);
     GrVkRenderPass::LoadStoreOps vkColorOps(vkLoadOp, vkStoreOp);
 
-    get_vk_load_store_ops(stencilOp, &vkLoadOp, &vkStoreOp);
+    get_vk_load_store_ops(stencilInfo, &vkLoadOp, &vkStoreOp);
     GrVkRenderPass::LoadStoreOps vkStencilOps(vkLoadOp, vkStoreOp);
-    
+
     GrVkRenderPass::LoadStoreOps vkResolveOps(VK_ATTACHMENT_LOAD_OP_LOAD,
                                               VK_ATTACHMENT_STORE_OP_STORE);
 
-    const GrVkResourceProvider::CompatibleRPHandle& rpHandle = target.compatibleRenderPassHandle();
+    const GrVkResourceProvider::CompatibleRPHandle& rpHandle = target->compatibleRenderPassHandle();
     if (rpHandle.isValid()) {
         fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
                                                               vkColorOps,
                                                               vkResolveOps,
                                                               vkStencilOps);
     } else {
-        fRenderPass = fGpu->resourceProvider().findRenderPass(target,
+        fRenderPass = fGpu->resourceProvider().findRenderPass(*target,
                                                               vkColorOps,
                                                               vkResolveOps,
                                                               vkStencilOps);
     }
 
+    GrColorToRGBAFloat(colorInfo.fClearColor, fColorClearValue.color.float32);
+
     fCommandBuffer = GrVkSecondaryCommandBuffer::Create(gpu, gpu->cmdPool(), fRenderPass);
-    fCommandBuffer->begin(gpu, target.framebuffer());
+    fCommandBuffer->begin(gpu, target->framebuffer());
 }
 
 GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() {
@@ -87,11 +93,305 @@ GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() {
     fRenderPass->unref(fGpu);
 }
 
+GrGpu* GrVkGpuCommandBuffer::gpu() { return fGpu; }
+
 void GrVkGpuCommandBuffer::end() {
     fCommandBuffer->end(fGpu);
 }
 
-void GrVkGpuCommandBuffer::submit() {
-    fGpu->submitSecondaryCommandBuffer(fCommandBuffer);
+void GrVkGpuCommandBuffer::onSubmit(const SkIRect& bounds) {
+    // Change layout of our render target so it can be used as the color attachment
+    fRenderTarget->setImageLayout(fGpu,
+                                  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                                  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                                  false);
+
+    // If we are using a stencil attachment we also need to update its layout
+    if (GrStencilAttachment* stencil = fRenderTarget->renderTargetPriv().getStencilAttachment()) {
+        GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
+        vkStencil->setImageLayout(fGpu,
+                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
+                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
+                                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                                  false);
+    }
+
+    for (int i = 0; i < fSampledImages.count(); ++i) {
+        fSampledImages[i]->setImageLayout(fGpu,
+                                          VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                                          VK_ACCESS_SHADER_READ_BIT,
+                                          VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+                                          false);
+    }
+
+    fGpu->submitSecondaryCommandBuffer(fCommandBuffer, fRenderPass, &fColorClearValue,
+                                       fRenderTarget, bounds);
+}
+
+void GrVkGpuCommandBuffer::onClearStencilClip(GrRenderTarget* target,
+                                              const SkIRect& rect,
+                                              bool insideClip) {
+    SkASSERT(target);
+
+    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
+    GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
+    // this should only be called internally when we know we have a
+    // stencil buffer.
+    SkASSERT(sb);
+    int stencilBitCount = sb->bits();
+
+    // The contract with the callers does not guarantee that we preserve all bits in the stencil
+    // during this clear. Thus we will clear the entire stencil to the desired value.
+
+    VkClearDepthStencilValue vkStencilColor;
+    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
+    if (insideClip) {
+        vkStencilColor.stencil = (1 << (stencilBitCount - 1));
+    } else {
+        vkStencilColor.stencil = 0;
+    }
+
+    VkClearRect clearRect;
+    // Flip rect if necessary
+    SkIRect vkRect = rect;
+
+    if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
+        vkRect.fTop = vkRT->height() - rect.fBottom;
+        vkRect.fBottom = vkRT->height() - rect.fTop;
+    }
+
+    clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
+    clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
+
+    clearRect.baseArrayLayer = 0;
+    clearRect.layerCount = 1;
+
+    uint32_t stencilIndex;
+    SkAssertResult(fRenderPass->stencilAttachmentIndex(&stencilIndex));
+
+    VkClearAttachment attachment;
+    attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
+    attachment.colorAttachment = 0; // this value shouldn't matter
+    attachment.clearValue.depthStencil = vkStencilColor;
+
+    fCommandBuffer->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
+    fIsEmpty = false;
+}
+
+void GrVkGpuCommandBuffer::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
+    // parent class should never let us get here with no RT
+    SkASSERT(target);
+
+    VkClearColorValue vkColor;
+    GrColorToRGBAFloat(color, vkColor.float32);
+
+    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
+
+    if (fIsEmpty) {
+        // We will change the render pass to do a clear load instead
+        GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_CLEAR,
+                                                VK_ATTACHMENT_STORE_OP_STORE);
+        GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
+                                                  VK_ATTACHMENT_STORE_OP_STORE);
+        GrVkRenderPass::LoadStoreOps vkResolveOps(VK_ATTACHMENT_LOAD_OP_LOAD,
+                                                  VK_ATTACHMENT_STORE_OP_STORE);
+
+        const GrVkRenderPass* oldRP = fRenderPass;
+
+        const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
+            vkRT->compatibleRenderPassHandle();
+        if (rpHandle.isValid()) {
+            fRenderPass = fGpu->resourceProvider().findRenderPass(rpHandle,
+                                                                  vkColorOps,
+                                                                  vkResolveOps,
+                                                                  vkStencilOps);
+        } else {
+            fRenderPass = fGpu->resourceProvider().findRenderPass(*vkRT,
+                                                                  vkColorOps,
+                                                                  vkResolveOps,
+                                                                  vkStencilOps);
+        }
+
+        SkASSERT(fRenderPass->isCompatible(*oldRP));
+        oldRP->unref(fGpu);
+
+        GrColorToRGBAFloat(color, fColorClearValue.color.float32);
+        return;
+    }
+
+    // We always do a sub rect clear with clearAttachments since we are inside a render pass
+    VkClearRect clearRect;
+    // Flip rect if necessary
+    SkIRect vkRect = rect;
+    if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
+        vkRect.fTop = vkRT->height() - rect.fBottom;
+        vkRect.fBottom = vkRT->height() - rect.fTop;
+    }
+    clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
+    clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
+    clearRect.baseArrayLayer = 0;
+    clearRect.layerCount = 1;
+
+    uint32_t colorIndex;
+    SkAssertResult(fRenderPass->colorAttachmentIndex(&colorIndex));
+
+    VkClearAttachment attachment;
+    attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    attachment.colorAttachment = colorIndex;
+    attachment.clearValue.color = vkColor;
+
+    fCommandBuffer->clearAttachments(fGpu, 1, &attachment, 1, &clearRect);
+    fIsEmpty = false;
+    return;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrVkGpuCommandBuffer::bindGeometry(const GrPrimitiveProcessor& primProc,
+                                        const GrNonInstancedMesh& mesh) {
+    // There is no need to put any memory barriers to make sure host writes have finished here.
+    // When a command buffer is submitted to a queue, there is an implicit memory barrier that
+    // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of
+    // an active RenderPass.
+    GrVkVertexBuffer* vbuf;
+    vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer();
+    SkASSERT(vbuf);
+    SkASSERT(!vbuf->isMapped());
+
+    fCommandBuffer->bindVertexBuffer(fGpu, vbuf);
+
+    if (mesh.isIndexed()) {
+        GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer();
+        SkASSERT(ibuf);
+        SkASSERT(!ibuf->isMapped());
+
+        fCommandBuffer->bindIndexBuffer(fGpu, ibuf);
+    }
+}
+
+sk_sp<GrVkPipelineState> GrVkGpuCommandBuffer::prepareDrawState(
+                                                               const GrPipeline& pipeline,
+                                                               const GrPrimitiveProcessor& primProc,
+                                                               GrPrimitiveType primitiveType,
+                                                               const GrVkRenderPass& renderPass) {
+    sk_sp<GrVkPipelineState> pipelineState =
+        fGpu->resourceProvider().findOrCreateCompatiblePipelineState(pipeline,
+                                                                     primProc,
+                                                                     primitiveType,
+                                                                     renderPass);
+    if (!pipelineState) {
+        return pipelineState;
+    }
+
+    pipelineState->setData(fGpu, primProc, pipeline);
+
+    pipelineState->bind(fGpu, fCommandBuffer);
+
+    GrVkPipeline::SetDynamicState(fGpu, fCommandBuffer, pipeline);
+
+    return pipelineState;
+}
+
+static void append_sampled_images(const GrProcessor& processor,
+                                  const GrVkGpu* gpu,
+                                  SkTArray<GrVkImage*>* sampledImages) {
+    if (int numTextures = processor.numTextures()) {
+        GrVkImage** images = sampledImages->push_back_n(numTextures);
+        int i = 0;
+        do {
+            const GrTextureAccess& texAccess = processor.textureAccess(i);
+            GrVkTexture* vkTexture = static_cast<GrVkTexture*>(processor.texture(i));
+            SkASSERT(vkTexture);
+            const GrTextureParams& params = texAccess.getParams();
+            // Check if we need to regenerate any mip maps
+            if (GrTextureParams::kMipMap_FilterMode == params.filterMode()) {
+                if (vkTexture->texturePriv().mipMapsAreDirty()) {
+                    gpu->generateMipmap(vkTexture);
+                    vkTexture->texturePriv().dirtyMipMaps(false);
+                }
+            }
+
+            images[i] = vkTexture;
+        } while (++i < numTextures);
+
+    }
+}
+
+void GrVkGpuCommandBuffer::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);
+
+    GrPrimitiveType primitiveType = meshes[0].primitiveType();
+    sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
+                                                                    primProc,
+                                                                    primitiveType,
+                                                                    *renderPass);
+    if (!pipelineState) {
+        return;
+    }
+
+    append_sampled_images(primProc, fGpu, &fSampledImages);
+    for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
+        append_sampled_images(pipeline.getFragmentProcessor(i), fGpu, &fSampledImages);
+    }
+    append_sampled_images(pipeline.getXferProcessor(), fGpu, &fSampledImages);
+
+    for (int i = 0; i < meshCount; ++i) {
+        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
+                // pipelineState:setData but this will allow for quicker freeing of resources if the
+                // pipelineState sits in a cache for a while.
+                pipelineState->freeTempResources(fGpu);
+                SkDEBUGCODE(pipelineState = nullptr);
+                primitiveType = nonIdxMesh->primitiveType();
+                pipelineState = this->prepareDrawState(pipeline,
+                                                       primProc,
+                                                       primitiveType,
+                                                       *renderPass);
+                if (!pipelineState) {
+                    return;
+                }
+            }
+            SkASSERT(pipelineState);
+            this->bindGeometry(primProc, *nonIdxMesh);
+
+            if (nonIdxMesh->isIndexed()) {
+                fCommandBuffer->drawIndexed(fGpu,
+                                            nonIdxMesh->indexCount(),
+                                            1,
+                                            nonIdxMesh->startIndex(),
+                                            nonIdxMesh->startVertex(),
+                                            0);
+            } else {
+                fCommandBuffer->draw(fGpu,
+                                     nonIdxMesh->vertexCount(),
+                                     1,
+                                     nonIdxMesh->startVertex(),
+                                     0);
+            }
+            fIsEmpty = false;
+
+            fGpu->stats()->incNumDraws();
+        } while ((nonIdxMesh = iter.next()));
+    }
+
+    // Technically we don't have to call this here (since there is a safety check in
+    // pipelineState:setData but this will allow for quicker freeing of resources if the
+    // pipelineState sits in a cache for a while.
+    pipelineState->freeTempResources(fGpu);
 }
 
index b68aa03..2daa98c 100644 (file)
 #include "GrGpuCommandBuffer.h"
 
 #include "GrColor.h"
+#include "GrTypes.h"
+#include "GrVkPipelineState.h"
 
+class GrNonInstancedMesh;
 class GrVkGpu;
+class GrVkImage;
 class GrVkRenderPass;
 class GrVkRenderTarget;
 class GrVkSecondaryCommandBuffer;
@@ -20,20 +24,47 @@ class GrVkSecondaryCommandBuffer;
 class GrVkGpuCommandBuffer : public GrGpuCommandBuffer {
 public:
     GrVkGpuCommandBuffer(GrVkGpu* gpu,
-                         const GrVkRenderTarget&,
-                         LoadAndStoreOp colorOp, GrColor colorClear,
-                         LoadAndStoreOp stencilOp, GrColor stencilClear);
+                         GrVkRenderTarget*,
+                         const LoadAndStoreInfo& colorInfo,
+                         const LoadAndStoreInfo& stencilInfo);
 
     virtual ~GrVkGpuCommandBuffer();
 
     void end() override;
 
-    void submit() override;
+    void discard(GrRenderTarget* rt) override {}
 
 private:
+    GrGpu* gpu() override;
+
+    void onSubmit(const SkIRect& bounds) override;
+
+    // Bind vertex and index buffers
+    void bindGeometry(const GrPrimitiveProcessor&, const GrNonInstancedMesh&);
+
+    sk_sp<GrVkPipelineState> prepareDrawState(const GrPipeline&,
+                                              const GrPrimitiveProcessor&,
+                                              GrPrimitiveType,
+                                              const GrVkRenderPass&);
+
+    void onDraw(const GrPipeline& pipeline,
+                const GrPrimitiveProcessor& primProc,
+                const GrMesh* mesh,
+                int meshCount) override;
+
+    void onClear(GrRenderTarget* rt, const SkIRect& rect, GrColor color) override;
+
+    void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override;
+
     const GrVkRenderPass*       fRenderPass;
     GrVkSecondaryCommandBuffer* fCommandBuffer;
     GrVkGpu*                    fGpu;
+    GrVkRenderTarget*           fRenderTarget;
+    VkClearValue                fColorClearValue;
+
+    SkTArray<GrVkImage*>        fSampledImages;
+
+    bool                        fIsEmpty;
 
     typedef GrGpuCommandBuffer INHERITED;
 };
index f27916f..8280e62 100644 (file)
@@ -294,12 +294,6 @@ void GrVkPipelineState::writeSamplers(GrVkGpu* gpu,
         const GrTextureParams& params = textureBindings[i]->getParams();
 
         GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->getTexture());
-        if (GrTextureParams::kMipMap_FilterMode == params.filterMode()) {
-            if (texture->texturePriv().mipMapsAreDirty()) {
-                gpu->generateMipmap(texture);
-                texture->texturePriv().dirtyMipMaps(false);
-            }
-        }
 
         fSamplers.push(gpu->resourceProvider().findOrCreateCompatibleSampler(params,
                                                           texture->texturePriv().maxMipMapLevel()));
@@ -312,13 +306,6 @@ void GrVkPipelineState::writeSamplers(GrVkGpu* gpu,
         textureView->ref();
         fTextureViews.push(textureView);
 
-        // Change texture layout so it can be read in shader
-        texture->setImageLayout(gpu,
-                                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-                                VK_ACCESS_SHADER_READ_BIT,
-                                VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
-                                false);
-
         VkDescriptorImageInfo imageInfo;
         memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
         imageInfo.sampler = fSamplers[i]->sampler();
index a632be4..31d5568 100644 (file)
@@ -339,7 +339,7 @@ GrVkRenderPass* GrVkResourceProvider::CompatibleRenderPassSet::getRenderPass(
             return fRenderPasses[idx];
         }
     }
-    GrVkRenderPass* renderPass = fRenderPasses.push_back();
+    GrVkRenderPass* renderPass = fRenderPasses.emplace_back(new GrVkRenderPass());
     renderPass->init(gpu, *this->getCompatibleRenderPass(), colorOps, resolveOps, stencilOps);
     fLastReturnedIndex = fRenderPasses.count() - 1;
     return renderPass;
index 4a8c966..cced844 100644 (file)
@@ -48,8 +48,8 @@ bool does_full_buffer_contain_correct_color(GrColor* buffer,
 }
 
 void basic_clear_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config) {
+#if 0
     GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());
-    gpu->discard(NULL);
     SkAutoTMalloc<GrColor> buffer(25);
 
     GrSurfaceDesc surfDesc;
@@ -95,15 +95,16 @@ void basic_clear_test(skiatest::Reporter* reporter, GrContext* context, GrPixelC
                                                                      config,
                                                                      5,
                                                                      5));
+#endif
 }
 
 void sub_clear_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config) {
+#if 0
     const int width = 10;
     const int height = 10;
     const int subWidth = width/2;
     const int subHeight = height/2;
     GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());
-    gpu->discard(NULL);
     SkAutoTMalloc<GrColor> buffer(width * height);
     SkAutoTMalloc<GrColor> subBuffer(subWidth * subHeight);
 
@@ -194,6 +195,7 @@ void sub_clear_test(skiatest::Reporter* reporter, GrContext* context, GrPixelCon
                                                                      config,
                                                                      subWidth,
                                                                      subHeight));
+#endif
 }
 
 DEF_GPUTEST_FOR_VULKAN_CONTEXT(VkClearTests, reporter, ctxInfo) {
index ca11c0f..7f00ad2 100644 (file)
@@ -52,7 +52,6 @@ bool does_full_buffer_contain_correct_color(GrColor* srcBuffer,
 void basic_texture_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config,
                         bool renderTarget, bool linearTiling) {
     GrVkGpu* gpu = static_cast<GrVkGpu*>(context->getGpu());
-    gpu->discard(NULL);
 
     const int kWidth = 16;
     const int kHeight = 16;
index e380b34..dca47ba 100644 (file)
@@ -284,8 +284,6 @@ public:
                               GrPixelConfig srcConfig, DrawPreference*,
                               WritePixelTempDrawInfo*) override { return false; }
 
-    void discard(GrRenderTarget*) override {}
-
     bool onCopySurface(GrSurface* dst,
                        GrSurface* src,
                        const SkIRect& srcRect,
@@ -302,11 +300,9 @@ public:
         return false;
     }
 
-    GrGpuCommandBuffer* createCommandBuffer(const GrRenderTarget& target,
-                                            GrGpuCommandBuffer::LoadAndStoreOp colorOp,
-                                            GrColor colorClear,
-                                            GrGpuCommandBuffer::LoadAndStoreOp stencilOp,
-                                            GrColor stencilClear) override {
+    GrGpuCommandBuffer* createCommandBuffer(GrRenderTarget* target,
+                                            const GrGpuCommandBuffer::LoadAndStoreInfo&,
+                                            const GrGpuCommandBuffer::LoadAndStoreInfo&) override {
         return nullptr;
     }
 
@@ -343,15 +339,6 @@ private:
         return nullptr;
     }
 
-    void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override {}
-
-    void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override {}
-
-    void onDraw(const GrPipeline&,
-                const GrPrimitiveProcessor&,
-                const GrMesh*,
-                int meshCount) override {}
-
     bool onReadPixels(GrSurface* surface,
                       int left, int top, int width, int height,
                       GrPixelConfig,