diff options
author | egdaniel <egdaniel@google.com> | 2016-06-23 08:37:05 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-06-23 08:37:06 -0700 |
commit | 9cb6340a62a5d748e4189d50e51fa527c8c80c03 (patch) | |
tree | 340b581c1463f7983d3aaccea22c2dbf73e49db0 /src | |
parent | de8ae904789ed2fb617134564630d0a97edc69d1 (diff) |
Start using GrGpuCommandBuffer in GrDrawTarget.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2052263003
Review-Url: https://codereview.chromium.org/2078483002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrBatchFlushState.cpp | 1 | ||||
-rw-r--r-- | src/gpu/GrBatchFlushState.h | 6 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.cpp | 31 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 32 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 57 | ||||
-rw-r--r-- | src/gpu/GrGpuCommandBuffer.cpp | 45 | ||||
-rw-r--r-- | src/gpu/GrGpuCommandBuffer.h | 74 | ||||
-rw-r--r-- | src/gpu/batches/GrBatch.h | 1 | ||||
-rw-r--r-- | src/gpu/batches/GrClearBatch.h | 5 | ||||
-rw-r--r-- | src/gpu/batches/GrCopySurfaceBatch.h | 9 | ||||
-rw-r--r-- | src/gpu/batches/GrDiscardBatch.h | 2 | ||||
-rw-r--r-- | src/gpu/batches/GrVertexBatch.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 26 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 38 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpuCommandBuffer.h | 33 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.cpp | 2 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCommandBuffer.cpp | 56 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCommandBuffer.h | 23 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 325 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.h | 34 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpuCommandBuffer.cpp | 364 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpuCommandBuffer.h | 39 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipelineState.cpp | 13 | ||||
-rw-r--r-- | src/gpu/vk/GrVkResourceProvider.cpp | 2 |
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; |