aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2016-06-23 08:37:05 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-06-23 08:37:06 -0700
commit9cb6340a62a5d748e4189d50e51fa527c8c80c03 (patch)
tree340b581c1463f7983d3aaccea22c2dbf73e49db0 /src
parentde8ae904789ed2fb617134564630d0a97edc69d1 (diff)
Start using GrGpuCommandBuffer in GrDrawTarget.
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrBatchFlushState.cpp1
-rw-r--r--src/gpu/GrBatchFlushState.h6
-rw-r--r--src/gpu/GrDrawTarget.cpp31
-rw-r--r--src/gpu/GrGpu.cpp32
-rw-r--r--src/gpu/GrGpu.h57
-rw-r--r--src/gpu/GrGpuCommandBuffer.cpp45
-rw-r--r--src/gpu/GrGpuCommandBuffer.h74
-rw-r--r--src/gpu/batches/GrBatch.h1
-rw-r--r--src/gpu/batches/GrClearBatch.h5
-rw-r--r--src/gpu/batches/GrCopySurfaceBatch.h9
-rw-r--r--src/gpu/batches/GrDiscardBatch.h2
-rw-r--r--src/gpu/batches/GrVertexBatch.cpp4
-rw-r--r--src/gpu/gl/GrGLGpu.cpp26
-rw-r--r--src/gpu/gl/GrGLGpu.h38
-rw-r--r--src/gpu/gl/GrGLGpuCommandBuffer.h33
-rw-r--r--src/gpu/vk/GrVkCaps.cpp2
-rw-r--r--src/gpu/vk/GrVkCommandBuffer.cpp56
-rw-r--r--src/gpu/vk/GrVkCommandBuffer.h23
-rw-r--r--src/gpu/vk/GrVkGpu.cpp325
-rw-r--r--src/gpu/vk/GrVkGpu.h34
-rw-r--r--src/gpu/vk/GrVkGpuCommandBuffer.cpp364
-rw-r--r--src/gpu/vk/GrVkGpuCommandBuffer.h39
-rw-r--r--src/gpu/vk/GrVkPipelineState.cpp13
-rw-r--r--src/gpu/vk/GrVkResourceProvider.cpp2
24 files changed, 690 insertions, 532 deletions
diff --git a/src/gpu/GrBatchFlushState.cpp b/src/gpu/GrBatchFlushState.cpp
index c4ba2644a9..4e51ae4ddd 100644
--- a/src/gpu/GrBatchFlushState.cpp
+++ b/src/gpu/GrBatchFlushState.cpp
@@ -13,6 +13,7 @@
GrBatchFlushState::GrBatchFlushState(GrGpu* gpu, GrResourceProvider* resourceProvider)
: fGpu(gpu)
, fResourceProvider(resourceProvider)
+ , fCommandBuffer(nullptr)
, fVertexPool(gpu)
, fIndexPool(gpu)
, fLastIssuedToken(GrBatchDrawToken::AlreadyFlushedToken())
diff --git a/src/gpu/GrBatchFlushState.h b/src/gpu/GrBatchFlushState.h
index 0b2e2bd239..d2d9a4b488 100644
--- a/src/gpu/GrBatchFlushState.h
+++ b/src/gpu/GrBatchFlushState.h
@@ -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;
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 7213a92152..d498d49a3d 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -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();
}
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index a381f311aa..0a2592d380 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -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;
-}
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index a99ce8f45e..f8528a1550 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -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
index 0000000000..f79cb0f1e6
--- /dev/null
+++ b/src/gpu/GrGpuCommandBuffer.cpp
@@ -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;
+}
+
diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h
index 3c6e6116fb..9abcc20fc7 100644
--- a/src/gpu/GrGpuCommandBuffer.h
+++ b/src/gpu/GrGpuCommandBuffer.h
@@ -10,17 +10,36 @@
#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
diff --git a/src/gpu/batches/GrBatch.h b/src/gpu/batches/GrBatch.h
index f0559330fe..b26cdde73c 100644
--- a/src/gpu/batches/GrBatch.h
+++ b/src/gpu/batches/GrBatch.h
@@ -16,6 +16,7 @@
#include <new>
class GrCaps;
+class GrGpuCommandBuffer;
class GrBatchFlushState;
class GrRenderTarget;
diff --git a/src/gpu/batches/GrClearBatch.h b/src/gpu/batches/GrClearBatch.h
index ba4b6d6dae..f2249cedb2 100644
--- a/src/gpu/batches/GrClearBatch.h
+++ b/src/gpu/batches/GrClearBatch.h
@@ -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;
diff --git a/src/gpu/batches/GrCopySurfaceBatch.h b/src/gpu/batches/GrCopySurfaceBatch.h
index 3926643f8a..900bcf3fda 100644
--- a/src/gpu/batches/GrCopySurfaceBatch.h
+++ b/src/gpu/batches/GrCopySurfaceBatch.h
@@ -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;
diff --git a/src/gpu/batches/GrDiscardBatch.h b/src/gpu/batches/GrDiscardBatch.h
index 65b6c4bf7d..3c19b68246 100644
--- a/src/gpu/batches/GrDiscardBatch.h
+++ b/src/gpu/batches/GrDiscardBatch.h
@@ -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;
diff --git a/src/gpu/batches/GrVertexBatch.cpp b/src/gpu/batches/GrVertexBatch.cpp
index 8a5dd6289b..af3a186e13 100644
--- a/src/gpu/batches/GrVertexBatch.cpp
+++ b/src/gpu/batches/GrVertexBatch.cpp
@@ -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();
}
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index b044b7b888..acc2e31e88 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -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;
}
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 9cce41c76d..aead715d1e 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -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,
diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h
index 8925322d4a..0591ffde3b 100644
--- a/src/gpu/gl/GrGLGpuCommandBuffer.h
+++ b/src/gpu/gl/GrGLGpuCommandBuffer.h
@@ -10,21 +10,44 @@
#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;
};
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 60934de2a7..833dc246c0 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -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
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp
index 2b636edf20..4a469fe42e 100644
--- a/src/gpu/vk/GrVkCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkCommandBuffer.cpp
@@ -15,12 +15,7 @@
#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
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h
index 709e4c6044..87c33c057a 100644
--- a/src/gpu/vk/GrVkCommandBuffer.h
+++ b/src/gpu/vk/GrVkCommandBuffer.h
@@ -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;
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 05aa1de152..33437415a9 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -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
}
+
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index b076de29ff..a9470aee14 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -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.
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
index f6104a3308..f987231940 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp
@@ -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);
}
diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h
index b68aa0334c..2daa98ce10 100644
--- a/src/gpu/vk/GrVkGpuCommandBuffer.h
+++ b/src/gpu/vk/GrVkGpuCommandBuffer.h
@@ -11,8 +11,12 @@
#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;
};
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index f27916f714..8280e62c2a 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -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();
diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp
index a632be44e2..31d5568b60 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -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;