From 952144753dc31d9d935683123cae43fca483bade Mon Sep 17 00:00:00 2001 From: Robert Phillips Date: Tue, 8 Aug 2017 18:00:03 -0400 Subject: Add explicit clear of stencil buffer before opLists that use them Change-Id: I9e2468e1331c6593dbc6da3ad510f08d1c589e8d Reviewed-on: https://skia-review.googlesource.com/32041 Commit-Queue: Stan Iliev Reviewed-by: Greg Daniel Reviewed-by: Brian Salomon --- src/gpu/GrGpu.h | 7 ++++--- src/gpu/GrGpuCommandBuffer.h | 8 ++++++++ src/gpu/GrOpList.h | 5 +++++ src/gpu/GrRenderTargetContext.cpp | 2 ++ src/gpu/GrRenderTargetOpList.cpp | 33 ++++++++++++++++++++++++++++----- src/gpu/GrResourceProvider.cpp | 18 +++++------------- src/gpu/gl/GrGLGpu.cpp | 13 +++++++------ src/gpu/gl/GrGLGpu.h | 7 ++++--- src/gpu/gl/GrGLGpuCommandBuffer.h | 13 ++++++++++++- src/gpu/mock/GrMockGpu.cpp | 6 ++++-- src/gpu/mock/GrMockGpu.h | 8 +++++--- src/gpu/mock/GrMockGpuCommandBuffer.h | 1 + src/gpu/mtl/GrMtlGpu.h | 8 +++++--- src/gpu/vk/GrVkCommandBuffer.cpp | 12 ++++++++++-- src/gpu/vk/GrVkCommandBuffer.h | 2 +- src/gpu/vk/GrVkGpu.cpp | 28 ++++++++++++++++++++++------ src/gpu/vk/GrVkGpu.h | 9 +++++---- src/gpu/vk/GrVkGpuCommandBuffer.cpp | 35 ++++++++++++++++++++++++++--------- src/gpu/vk/GrVkGpuCommandBuffer.h | 8 +++++--- 19 files changed, 159 insertions(+), 64 deletions(-) (limited to 'src/gpu') diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 1da8d0e501..fa5f372e14 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -371,8 +371,9 @@ public: // awkward workaround that goes away after MDB is complete and the render target is known from // the GrRenderTargetOpList. virtual GrGpuCommandBuffer* createCommandBuffer( - const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo, - const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) = 0; + GrRenderTarget*, GrSurfaceOrigin, + const GrGpuCommandBuffer::LoadAndStoreInfo&, + const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) = 0; // Called by GrDrawingManager when flushing. // Provides a hook for post-flush actions (e.g. Vulkan command buffer submits). This will also @@ -479,7 +480,7 @@ public: int width, int height) = 0; // clears target's entire stencil buffer to 0 - virtual void clearStencil(GrRenderTarget* target) = 0; + virtual void clearStencil(GrRenderTarget* target, int clearValue) = 0; // Determines whether a texture will need to be rescaled in order to be used with the // GrSamplerParams. This variation is called when the caller will create a new texture using the diff --git a/src/gpu/GrGpuCommandBuffer.h b/src/gpu/GrGpuCommandBuffer.h index a50901ac58..1be361f81d 100644 --- a/src/gpu/GrGpuCommandBuffer.h +++ b/src/gpu/GrGpuCommandBuffer.h @@ -53,9 +53,17 @@ public: GrColor fClearColor; }; + // Load-time clears of the stencil buffer are always to 0 so we don't store + // an 'fStencilClearValue' + struct StencilLoadAndStoreInfo { + LoadOp fLoadOp; + StoreOp fStoreOp; + }; + GrGpuCommandBuffer() {} virtual ~GrGpuCommandBuffer() {} + virtual void begin() = 0; // Signals the end of recording to the command buffer and that it can now be submitted. virtual void end() = 0; diff --git a/src/gpu/GrOpList.h b/src/gpu/GrOpList.h index 2d80386fad..00dc344a07 100644 --- a/src/gpu/GrOpList.h +++ b/src/gpu/GrOpList.h @@ -82,6 +82,9 @@ public: int32_t uniqueID() const { return fUniqueID; } + void setRequiresStencil() { this->setFlag(kClearStencilBuffer_Flag); } + bool requiresStencil() { return this->isSetFlag(kClearStencilBuffer_Flag); } + /* * Dump out the GrOpList dependency DAG */ @@ -104,6 +107,8 @@ private: kWasOutput_Flag = 0x02, //!< Flag for topological sorting kTempMark_Flag = 0x04, //!< Flag for topological sorting + + kClearStencilBuffer_Flag = 0x08 //!< Clear the SB before executing the ops }; void setFlag(uint32_t flag) { diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index dfea8f9637..e76b5ff26e 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1761,6 +1761,8 @@ uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptrgetOpList()->setRequiresStencil(); + // This forces instantiation of the render target. GrRenderTarget* rt = this->accessRenderTarget(); if (!rt) { diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp index f0c97e48f5..ffa1e43746 100644 --- a/src/gpu/GrRenderTargetOpList.cpp +++ b/src/gpu/GrRenderTargetOpList.cpp @@ -84,16 +84,30 @@ void GrRenderTargetOpList::prepareOps(GrOpFlushState* flushState) { } } -static std::unique_ptr create_command_buffer(GrGpu* gpu) { +static std::unique_ptr create_command_buffer(GrGpu* gpu, + GrRenderTarget* rt, + GrSurfaceOrigin origin, + bool clearSB) { static const GrGpuCommandBuffer::LoadAndStoreInfo kBasicLoadStoreInfo { GrGpuCommandBuffer::LoadOp::kLoad, GrGpuCommandBuffer::StoreOp::kStore, GrColor_ILLEGAL }; + // TODO: + // We would like to (at this level) only ever clear & discard. We would need + // to stop splitting up higher level opLists for copyOps to achieve that. + // Note: we would still need SB loads and stores but they would happen at a + // lower level (inside the VK command buffer). + const GrGpuCommandBuffer::StencilLoadAndStoreInfo stencilLoadAndStoreInfo { + clearSB ? GrGpuCommandBuffer::LoadOp::kClear : GrGpuCommandBuffer::LoadOp::kLoad, + GrGpuCommandBuffer::StoreOp::kStore, + }; + std::unique_ptr buffer( - gpu->createCommandBuffer(kBasicLoadStoreInfo, // Color - kBasicLoadStoreInfo)); // Stencil + gpu->createCommandBuffer(rt, origin, + kBasicLoadStoreInfo, // Color + stencilLoadAndStoreInfo)); // Stencil return buffer; } @@ -116,8 +130,13 @@ bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) { SkASSERT(fTarget.get()->priv().peekRenderTarget()); - std::unique_ptr commandBuffer = create_command_buffer(flushState->gpu()); + std::unique_ptr commandBuffer = create_command_buffer( + flushState->gpu(), + fTarget.get()->priv().peekRenderTarget(), + fTarget.get()->origin(), + this->requiresStencil()); flushState->setCommandBuffer(commandBuffer.get()); + commandBuffer->begin(); // Draw all the generated geometry. for (int i = 0; i < fRecordedOps.count(); ++i) { @@ -133,8 +152,12 @@ bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) { commandBuffer.reset(); flushState->setCommandBuffer(commandBuffer.get()); } else if (!commandBuffer) { - commandBuffer = create_command_buffer(flushState->gpu()); + commandBuffer = create_command_buffer(flushState->gpu(), + fTarget.get()->priv().peekRenderTarget(), + fTarget.get()->origin(), + false); flushState->setCommandBuffer(commandBuffer.get()); + commandBuffer->begin(); } GrOpFlushState::DrawOpArgs opArgs { diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp index 6061b33e1b..1979570fe0 100644 --- a/src/gpu/GrResourceProvider.cpp +++ b/src/gpu/GrResourceProvider.cpp @@ -450,7 +450,6 @@ GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget* height = SkNextPow2(height); } #endif - bool newStencil = false; GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height, rt->numStencilSamples(), &sbKey); GrStencilAttachment* stencil = static_cast( @@ -460,21 +459,14 @@ GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget* stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height); if (stencil) { this->assignUniqueKeyToResource(sbKey, stencil); - newStencil = true; } } if (rt->renderTargetPriv().attachStencilAttachment(stencil)) { - if (newStencil) { - // Right now we're clearing the stencil attachment here after it is - // attached to a RT for the first time. When we start matching - // stencil buffers with smaller color targets this will no longer - // be correct because it won't be guaranteed to clear the entire - // sb. - // We used to clear down in the GL subclass using a special purpose - // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported - // FBO status. - this->gpu()->clearStencil(rt); - } +#ifdef SK_DEBUG + // Fill the SB with an inappropriate value. opLists that use the + // SB should clear it properly. + this->gpu()->clearStencil(rt, 0xFFFF); +#endif } } return rt->renderTargetPriv().getStencilAttachment(); diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index bfa8ee48ee..7eb49525e3 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2004,8 +2004,8 @@ void GrGLGpu::clear(const GrFixedClip& clip, GrColor color, GrRenderTarget* targ GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT)); } -void GrGLGpu::clearStencil(GrRenderTarget* target) { - if (nullptr == target) { +void GrGLGpu::clearStencil(GrRenderTarget* target, int clearValue) { + if (!target) { return; } GrGLRenderTarget* glRT = static_cast(target); @@ -2015,7 +2015,7 @@ void GrGLGpu::clearStencil(GrRenderTarget* target) { this->disableWindowRectangles(); GL_CALL(StencilMask(0xffffffff)); - GL_CALL(ClearStencil(0)); + GL_CALL(ClearStencil(clearValue)); GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); fHWStencilSettings.invalidate(); } @@ -2448,9 +2448,10 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, } GrGpuCommandBuffer* GrGLGpu::createCommandBuffer( - const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo, - const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) { - return new GrGLGpuCommandBuffer(this); + GrRenderTarget* rt, GrSurfaceOrigin, + const GrGpuCommandBuffer::LoadAndStoreInfo&, + const GrGpuCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) { + return new GrGLGpuCommandBuffer(this, rt, stencilInfo); } void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bounds, bool disableSRGB) { diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 1d362fa9eb..5b6cda76ee 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -142,11 +142,12 @@ public: return &this->glContext(); } - void clearStencil(GrRenderTarget*) override; + void clearStencil(GrRenderTarget*, int clearValue) override; GrGpuCommandBuffer* createCommandBuffer( - const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo, - const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override; + GrRenderTarget*, GrSurfaceOrigin, + const GrGpuCommandBuffer::LoadAndStoreInfo&, + const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) override; void invalidateBoundRenderTarget() { fHWBoundRenderTargetUniqueID.makeInvalid(); diff --git a/src/gpu/gl/GrGLGpuCommandBuffer.h b/src/gpu/gl/GrGLGpuCommandBuffer.h index 531251b03d..85dfbe8a30 100644 --- a/src/gpu/gl/GrGLGpuCommandBuffer.h +++ b/src/gpu/gl/GrGLGpuCommandBuffer.h @@ -24,10 +24,20 @@ class GrGLGpuCommandBuffer : public GrGpuCommandBuffer { * pass through functions to corresponding calls in the GrGLGpu class. */ public: - GrGLGpuCommandBuffer(GrGLGpu* gpu) : fGpu(gpu), fRenderTarget(nullptr) {} + GrGLGpuCommandBuffer(GrGLGpu* gpu, GrRenderTarget* rt, + const GrGpuCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) + : fGpu(gpu) + , fRenderTarget(static_cast(rt)) { + fClearSB = LoadOp::kClear == stencilInfo.fLoadOp; + } ~GrGLGpuCommandBuffer() override {} + void begin() override { + if (fClearSB) { + fGpu->clearStencil(fRenderTarget, 0x0); + } + } void end() override {} void discard(GrRenderTargetProxy* proxy) override { @@ -94,6 +104,7 @@ private: GrGLGpu* fGpu; GrGLRenderTarget* fRenderTarget; + bool fClearSB; typedef GrGpuCommandBuffer INHERITED; }; diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp index 614e627867..d97c789158 100644 --- a/src/gpu/mock/GrMockGpu.cpp +++ b/src/gpu/mock/GrMockGpu.cpp @@ -39,8 +39,10 @@ GrGpu* GrMockGpu::Create(const GrMockOptions* mockOptions, const GrContextOption } -GrGpuCommandBuffer* GrMockGpu::createCommandBuffer(const GrGpuCommandBuffer::LoadAndStoreInfo&, - const GrGpuCommandBuffer::LoadAndStoreInfo&) { +GrGpuCommandBuffer* GrMockGpu::createCommandBuffer( + GrRenderTarget*, GrSurfaceOrigin, + const GrGpuCommandBuffer::LoadAndStoreInfo&, + const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) { return new GrMockGpuCommandBuffer(this); } diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h index f5a187e335..6d72399be7 100644 --- a/src/gpu/mock/GrMockGpu.h +++ b/src/gpu/mock/GrMockGpu.h @@ -43,8 +43,10 @@ public: *effectiveSampleCnt = rt->numStencilSamples(); } - GrGpuCommandBuffer* createCommandBuffer(const GrGpuCommandBuffer::LoadAndStoreInfo&, - const GrGpuCommandBuffer::LoadAndStoreInfo&) override; + GrGpuCommandBuffer* createCommandBuffer( + GrRenderTarget*, GrSurfaceOrigin, + const GrGpuCommandBuffer::LoadAndStoreInfo&, + const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) override; GrFence SK_WARN_UNUSED_RESULT insertFence() override { return 0; } bool waitFence(GrFence, uint64_t) override { return true; } @@ -129,7 +131,7 @@ private: GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*, int width, int height) override; - void clearStencil(GrRenderTarget* target) override {} + void clearStencil(GrRenderTarget*, int clearValue) override {} GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig, bool isRT) override; diff --git a/src/gpu/mock/GrMockGpuCommandBuffer.h b/src/gpu/mock/GrMockGpuCommandBuffer.h index 0213cb9c14..d2f6baf400 100644 --- a/src/gpu/mock/GrMockGpuCommandBuffer.h +++ b/src/gpu/mock/GrMockGpuCommandBuffer.h @@ -20,6 +20,7 @@ public: GrRenderTargetProxy*) override {} void discard(GrRenderTargetProxy*) override {} void insertEventMarker(GrRenderTargetProxy*, const char*) override {} + void begin() override {} void end() override {} int numDraws() const { return fNumDraws; } diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h index 06c2b2fc5e..e6f2ccabb7 100644 --- a/src/gpu/mtl/GrMtlGpu.h +++ b/src/gpu/mtl/GrMtlGpu.h @@ -47,8 +47,10 @@ public: void onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&, int* effectiveSampleCnt, SamplePattern*) override {} - GrGpuCommandBuffer* createCommandBuffer(const GrGpuCommandBuffer::LoadAndStoreInfo&, - const GrGpuCommandBuffer::LoadAndStoreInfo&) override { + GrGpuCommandBuffer* createCommandBuffer( + GrRenderTarget*, GrSurfaceOrigin, + const GrGpuCommandBuffer::LoadAndStoreInfo&, + const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) override { return nullptr; } @@ -138,7 +140,7 @@ private: return nullptr; } - void clearStencil(GrRenderTarget* target) override {} + void clearStencil(GrRenderTarget* target, int clearValue) override {} GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig config, bool isRT) override { diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp index d4fe80caf9..3713bfeba0 100644 --- a/src/gpu/vk/GrVkCommandBuffer.cpp +++ b/src/gpu/vk/GrVkCommandBuffer.cpp @@ -384,7 +384,7 @@ void GrVkPrimaryCommandBuffer::end(const GrVkGpu* gpu) { void GrVkPrimaryCommandBuffer::beginRenderPass(const GrVkGpu* gpu, const GrVkRenderPass* renderPass, - const VkClearValue* clearValues, + const VkClearValue clearValues[], const GrVkRenderTarget& target, const SkIRect& bounds, bool forSecondaryCB) { @@ -403,7 +403,15 @@ void GrVkPrimaryCommandBuffer::beginRenderPass(const GrVkGpu* gpu, beginInfo.renderPass = renderPass->vkRenderPass(); beginInfo.framebuffer = target.framebuffer()->framebuffer(); beginInfo.renderArea = renderArea; - beginInfo.clearValueCount = renderPass->clearValueCount(); + + // TODO: have clearValueCount return the index of the last attachment that + // requires a clear instead of the number of total clears. + uint32_t stencilIndex; + if (renderPass->stencilAttachmentIndex(&stencilIndex)) { + beginInfo.clearValueCount = renderPass->clearValueCount() ? 2 : 0; + } else { + beginInfo.clearValueCount = renderPass->clearValueCount(); + } beginInfo.pClearValues = clearValues; VkSubpassContents contents = forSecondaryCB ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h index e602e4d574..548efad8a2 100644 --- a/src/gpu/vk/GrVkCommandBuffer.h +++ b/src/gpu/vk/GrVkCommandBuffer.h @@ -185,7 +185,7 @@ public: // in the render pass. void beginRenderPass(const GrVkGpu* gpu, const GrVkRenderPass* renderPass, - const VkClearValue* clearValues, + const VkClearValue clearValues[], const GrVkRenderTarget& target, const SkIRect& bounds, bool forSecondaryCB); diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 6da40e510b..f15258281a 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -258,9 +258,10 @@ void GrVkGpu::disconnect(DisconnectType type) { /////////////////////////////////////////////////////////////////////////////// GrGpuCommandBuffer* GrVkGpu::createCommandBuffer( + GrRenderTarget* rt, GrSurfaceOrigin origin, const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo, - const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) { - return new GrVkGpuCommandBuffer(this, colorInfo, stencilInfo); + const GrGpuCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) { + return new GrVkGpuCommandBuffer(this, rt, origin, colorInfo, stencilInfo); } void GrVkGpu::submitCommandBuffer(SyncQueue sync) { @@ -1474,8 +1475,8 @@ void GrVkGpu::onFinishFlush(bool insertedSemaphore) { this->submitCommandBuffer(kSkip_SyncQueue); } -void GrVkGpu::clearStencil(GrRenderTarget* target) { - if (nullptr == target) { +void GrVkGpu::clearStencil(GrRenderTarget* target, int clearValue) { + if (!target) { return; } GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment(); @@ -1483,7 +1484,8 @@ void GrVkGpu::clearStencil(GrRenderTarget* target) { VkClearDepthStencilValue vkStencilColor; - memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue)); + vkStencilColor.depth = 0.0f; + vkStencilColor.stencil = clearValue; vkStencil->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, @@ -1971,6 +1973,7 @@ void adjust_bounds_to_granularity(SkIRect* dstBounds, const SkIRect& srcBounds, void GrVkGpu::submitSecondaryCommandBuffer(const SkTArray& buffers, const GrVkRenderPass* renderPass, const VkClearValue* colorClear, + const VkClearValue* stencilClear, GrVkRenderTarget* target, const SkIRect& bounds) { const SkIRect* pBounds = &bounds; @@ -1993,7 +1996,20 @@ void GrVkGpu::submitSecondaryCommandBuffer(const SkTArraybeginRenderPass(this, renderPass, colorClear, *target, *pBounds, true); +#ifdef SK_DEBUG + uint32_t index; + bool result = renderPass->colorAttachmentIndex(&index); + SkASSERT(result && 0 == index); + result = renderPass->stencilAttachmentIndex(&index); + if (result) { + SkASSERT(1 == index); + } +#endif + VkClearValue clears[2]; + clears[0].color = colorClear->color; + clears[1].depthStencil = stencilClear->depthStencil; + + fCurrentCmdBuffer->beginRenderPass(this, renderPass, clears, *target, *pBounds, true); for (int i = 0; i < buffers.count(); ++i) { fCurrentCmdBuffer->executeCommands(this, buffers[i]); } diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index 2a4478562f..976c95a661 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -94,11 +94,12 @@ public: int width, int height) override; - void clearStencil(GrRenderTarget* target) override; + void clearStencil(GrRenderTarget* target, int clearValue) override; GrGpuCommandBuffer* createCommandBuffer( - const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo, - const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override; + GrRenderTarget*, GrSurfaceOrigin, + const GrGpuCommandBuffer::LoadAndStoreInfo&, + const GrGpuCommandBuffer::StencilLoadAndStoreInfo&) override; void addMemoryBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, @@ -123,7 +124,7 @@ public: void submitSecondaryCommandBuffer(const SkTArray&, const GrVkRenderPass*, - const VkClearValue*, + const VkClearValue*, const VkClearValue*, GrVkRenderTarget*, const SkIRect& bounds); diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp index 6a01d3f18d..2528fce38f 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -22,9 +22,10 @@ #include "GrVkTexture.h" #include "SkRect.h" -void get_vk_load_store_ops(const GrGpuCommandBuffer::LoadAndStoreInfo& info, +void get_vk_load_store_ops(GrGpuCommandBuffer::LoadOp loadOpIn, + GrGpuCommandBuffer::StoreOp storeOpIn, VkAttachmentLoadOp* loadOp, VkAttachmentStoreOp* storeOp) { - switch (info.fLoadOp) { + switch (loadOpIn) { case GrGpuCommandBuffer::LoadOp::kLoad: *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; break; @@ -39,7 +40,7 @@ void get_vk_load_store_ops(const GrGpuCommandBuffer::LoadAndStoreInfo& info, *loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; } - switch (info.fStoreOp) { + switch (storeOpIn) { case GrGpuCommandBuffer::StoreOp::kStore: *storeOp = VK_ATTACHMENT_STORE_OP_STORE; break; @@ -53,19 +54,22 @@ void get_vk_load_store_ops(const GrGpuCommandBuffer::LoadAndStoreInfo& info, } GrVkGpuCommandBuffer::GrVkGpuCommandBuffer(GrVkGpu* gpu, + GrRenderTarget* rt, GrSurfaceOrigin origin, const LoadAndStoreInfo& colorInfo, - const LoadAndStoreInfo& stencilInfo) + const StencilLoadAndStoreInfo& stencilInfo) : fGpu(gpu) , fRenderTarget(nullptr) , fOrigin(kTopLeft_GrSurfaceOrigin) , fClearColor(GrColor4f::FromGrColor(colorInfo.fClearColor)) , fLastPipelineState(nullptr) { + get_vk_load_store_ops(colorInfo.fLoadOp, colorInfo.fStoreOp, + &fVkColorLoadOp, &fVkColorStoreOp); - get_vk_load_store_ops(colorInfo, &fVkColorLoadOp, &fVkColorStoreOp); - - get_vk_load_store_ops(stencilInfo, &fVkStencilLoadOp, &fVkStencilStoreOp); - + get_vk_load_store_ops(stencilInfo.fLoadOp, stencilInfo.fStoreOp, + &fVkStencilLoadOp, &fVkStencilStoreOp); fCurrentCmdInfo = -1; + + this->init(static_cast(rt), origin); } void GrVkGpuCommandBuffer::init(GrVkRenderTarget* target, GrSurfaceOrigin origin) { @@ -96,6 +100,9 @@ void GrVkGpuCommandBuffer::init(GrVkRenderTarget* target, GrSurfaceOrigin origin cbInfo.fColorClearValue.color.float32[2] = fClearColor.fRGBA[2]; cbInfo.fColorClearValue.color.float32[3] = fClearColor.fRGBA[3]; + cbInfo.fStencilClearValue.depthStencil.depth = 0; + cbInfo.fStencilClearValue.depthStencil.stencil = 0; + cbInfo.fBounds.setEmpty(); cbInfo.fIsEmpty = true; cbInfo.fStartsWithClear = false; @@ -118,6 +125,13 @@ GrVkGpuCommandBuffer::~GrVkGpuCommandBuffer() { GrGpu* GrVkGpuCommandBuffer::gpu() { return fGpu; } GrRenderTarget* GrVkGpuCommandBuffer::renderTarget() { return fRenderTarget; } +void GrVkGpuCommandBuffer::begin() { + // TODO: remove this - see skbug.com/6936 + if (VK_ATTACHMENT_LOAD_OP_CLEAR == fVkStencilLoadOp) { + fGpu->clearStencil(fRenderTarget, 0x0); + } +} + void GrVkGpuCommandBuffer::end() { if (fCurrentCmdInfo >= 0) { fCommandBufferInfos[fCurrentCmdInfo].currentCmdBuf()->end(fGpu); @@ -178,7 +192,9 @@ void GrVkGpuCommandBuffer::onSubmit() { cbInfo.fBounds.roundOut(&iBounds); fGpu->submitSecondaryCommandBuffer(cbInfo.fCommandBuffers, cbInfo.fRenderPass, - &cbInfo.fColorClearValue, fRenderTarget, iBounds); + &cbInfo.fColorClearValue, + &cbInfo.fStencilClearValue, + fRenderTarget, iBounds); } } } @@ -410,6 +426,7 @@ void GrVkGpuCommandBuffer::addAdditionalRenderPass() { // It shouldn't matter what we set the clear color to here since we will assume loading of the // attachment. memset(&cbInfo.fColorClearValue, 0, sizeof(VkClearValue)); + memset(&cbInfo.fStencilClearValue, 0, sizeof(VkClearValue)); cbInfo.fBounds.setEmpty(); cbInfo.fIsEmpty = true; cbInfo.fStartsWithClear = false; diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.h b/src/gpu/vk/GrVkGpuCommandBuffer.h index 6031788711..cafb015148 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.h +++ b/src/gpu/vk/GrVkGpuCommandBuffer.h @@ -23,12 +23,13 @@ class GrVkSecondaryCommandBuffer; class GrVkGpuCommandBuffer : public GrGpuCommandBuffer, private GrMesh::SendToGpuImpl { public: - GrVkGpuCommandBuffer(GrVkGpu* gpu, - const LoadAndStoreInfo& colorInfo, - const LoadAndStoreInfo& stencilInfo); + GrVkGpuCommandBuffer(GrVkGpu*, GrRenderTarget*, GrSurfaceOrigin, + const LoadAndStoreInfo&, + const StencilLoadAndStoreInfo&); ~GrVkGpuCommandBuffer() override; + void begin() override; void end() override; void discard(GrRenderTargetProxy*) override; @@ -111,6 +112,7 @@ private: const GrVkRenderPass* fRenderPass; SkTArray fCommandBuffers; VkClearValue fColorClearValue; + VkClearValue fStencilClearValue; SkRect fBounds; bool fIsEmpty; bool fStartsWithClear; -- cgit v1.2.3