diff --git a/src/gpu/GrOpList.h b/src/gpu/GrOpList.h index 50eaaef31f..b33c298eaf 100644 --- a/src/gpu/GrOpList.h +++ b/src/gpu/GrOpList.h @@ -101,8 +101,7 @@ public: SkDEBUGCODE(virtual int numOps() const = 0;) SkDEBUGCODE(virtual int numClips() const { return 0; }) - void setColorLoadOp(GrLoadOp loadOp) { fColorLoadOp = loadOp; } - void setLoadClearColor(GrColor color) { fLoadClearColor = color; } + // TODO: it would be nice for this to be hidden void setStencilLoadOp(GrLoadOp loadOp) { fStencilLoadOp = loadOp; } protected: diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index cd881b44bd..b83e2530c1 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -220,22 +220,7 @@ void GrRenderTargetContext::discard() { AutoCheckFlush acf(this->drawingManager()); - // Discard calls to in-progress opLists are ignored. Calls at the start update the - // opLists' color & stencil load ops. - if (this->getRTOpList()->isEmpty()) { - if (this->caps()->discardRenderTargetSupport()) { - this->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard); - this->getRTOpList()->setStencilLoadOp(GrLoadOp::kDiscard); - } else { - // skbug.com/6956 (Extra clear confuses Nexus7) -#if 0 - // Surely, if a discard was requested, a clear should be acceptable - this->getRTOpList()->setColorLoadOp(GrLoadOp::kClear); - this->getRTOpList()->setLoadClearColor(0x0); - this->getRTOpList()->setStencilLoadOp(GrLoadOp::kClear); -#endif - } - } + this->getRTOpList()->discard(); } void GrRenderTargetContext::clear(const SkIRect* rect, diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp index ce34be7495..77b6eca3bc 100644 --- a/src/gpu/GrRenderTargetOpList.cpp +++ b/src/gpu/GrRenderTargetOpList.cpp @@ -133,7 +133,7 @@ static inline void finish_command_buffer(GrGpuRTCommandBuffer* buffer) { // is at flush time). However, we need to store the RenderTargetProxy in the // Ops and instantiate them here. bool GrRenderTargetOpList::onExecute(GrOpFlushState* flushState) { - if (0 == fRecordedOps.count()) { + if (0 == fRecordedOps.count() && GrLoadOp::kClear != fColorLoadOp) { return false; } @@ -180,7 +180,6 @@ bool GrRenderTargetOpList::onExecute(GrOpFlushState* flushState) { } void GrRenderTargetOpList::reset() { - fLastFullClearOp = nullptr; fLastClipStackGenID = SK_InvalidUniqueID; fRecordedOps.reset(); if (fInstancedRendering) { @@ -203,30 +202,35 @@ void GrRenderTargetOpList::freeGpuResources() { } } +void GrRenderTargetOpList::discard() { + // Discard calls to in-progress opLists are ignored. Calls at the start update the + // opLists' color & stencil load ops. + if (this->isEmpty()) { + fColorLoadOp = GrLoadOp::kDiscard; + fStencilLoadOp = GrLoadOp::kDiscard; + } +} + void GrRenderTargetOpList::fullClear(const GrCaps& caps, GrColor color) { - // Currently this just inserts or updates the last clear op. However, once in MDB this can - // remove all the previously recorded ops and change the load op to clear with supplied - // color. - if (fLastFullClearOp) { - // As currently implemented, fLastFullClearOp should be the last op because we would - // have cleared it when another op was recorded. - SkASSERT(fRecordedOps.back().fOp.get() == fLastFullClearOp); - GrOP_INFO("opList: %d Fusing clears (opID: %d Color: 0x%08x -> 0x%08x)\n", - this->uniqueID(), - fLastFullClearOp->uniqueID(), - fLastFullClearOp->color(), color); - fLastFullClearOp->setColor(color); + + // This is conservative. If the opList is marked as needing a stencil buffer then there + // may be a prior op that writes to the stencil buffer. Although the clear will ignore the + // stencil buffer, following draw ops may not so we can't get rid of all the preceding ops. + // Beware! If we ever add any ops that have a side effect beyond modifying the stencil + // buffer we will need a more elaborate tracking system (skbug.com/7002). + if (this->isEmpty() || !fTarget.get()->asRenderTargetProxy()->needsStencil()) { + fRecordedOps.reset(); + fColorLoadOp = GrLoadOp::kClear; + fLoadClearColor = color; return; } + std::unique_ptr op(GrClearOp::Make(GrFixedClip::Disabled(), color, fTarget.get())); if (!op) { return; } - if (GrOp* clearOp = this->recordOp(std::move(op), caps)) { - // This is either the clear op we just created or another one that it combined with. - fLastFullClearOp = static_cast(clearOp); - } + this->recordOp(std::move(op), caps); } //////////////////////////////////////////////////////////////////////////////// @@ -277,10 +281,10 @@ bool GrRenderTargetOpList::combineIfPossible(const RecordedOp& a, GrOp* b, return a.fOp->combineIfPossible(b, caps); } -GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr op, - const GrCaps& caps, - GrAppliedClip* clip, - const DstProxy* dstProxy) { +void GrRenderTargetOpList::recordOp(std::unique_ptr op, + const GrCaps& caps, + GrAppliedClip* clip, + const DstProxy* dstProxy) { SkASSERT(fTarget.get()); // A closed GrOpList should never receive new/more ops @@ -313,7 +317,7 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr op, GrOP_INFO("\t\t\tBackward: Combined op info:\n"); GrOP_INFO(SkTabString(candidate.fOp->dumpInfo(), 4).c_str()); GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(fAuditTrail, candidate.fOp.get(), op.get()); - return candidate.fOp.get(); + return; } // Stop going backwards if we would cause a painter's order violation. if (!can_reorder(fRecordedOps.fromBack(i).fOp->bounds(), op->bounds())) { @@ -337,8 +341,6 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr op, } fRecordedOps.emplace_back(std::move(op), clip, dstProxy); fRecordedOps.back().fOp->wasRecorded(this); - fLastFullClearOp = nullptr; - return fRecordedOps.back().fOp.get(); } void GrRenderTargetOpList::forwardCombine(const GrCaps& caps) { diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h index b62cee5531..ef4bdacdd2 100644 --- a/src/gpu/GrRenderTargetOpList.h +++ b/src/gpu/GrRenderTargetOpList.h @@ -45,7 +45,6 @@ public: return; } - fLastFullClearOp = nullptr; this->forwardCombine(caps); INHERITED::makeClosed(caps); @@ -78,6 +77,8 @@ public: return this->uniqueID(); } + void discard(); + /** Clears the entire render target */ void fullClear(const GrCaps& caps, GrColor color); @@ -124,10 +125,8 @@ private: GrAppliedClip* fAppliedClip; }; - // If the input op is combined with an earlier op, this returns the combined op. Otherwise, it - // returns the input op. - GrOp* recordOp(std::unique_ptr, const GrCaps& caps, - GrAppliedClip* = nullptr, const DstProxy* = nullptr); + void recordOp(std::unique_ptr, const GrCaps& caps, + GrAppliedClip* = nullptr, const DstProxy* = nullptr); void forwardCombine(const GrCaps&); @@ -135,8 +134,6 @@ private: bool combineIfPossible(const RecordedOp& a, GrOp* b, const GrAppliedClip* bClip, const DstProxy* bDstTexture, const GrCaps&); - GrClearOp* fLastFullClearOp = nullptr; - std::unique_ptr fInstancedRendering; uint32_t fLastClipStackGenID; diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp index f202c9b709..15fdf4aa78 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -116,7 +116,11 @@ void GrVkGpuRTCommandBuffer::init() { cbInfo.fColorClearValue.color.float32[2] = fClearColor.fRGBA[2]; cbInfo.fColorClearValue.color.float32[3] = fClearColor.fRGBA[3]; - cbInfo.fBounds.setEmpty(); + if (VK_ATTACHMENT_LOAD_OP_CLEAR == fVkColorLoadOp) { + cbInfo.fBounds = SkRect::MakeWH(vkRT->width(), vkRT->height()); + } else { + cbInfo.fBounds.setEmpty(); + } cbInfo.fIsEmpty = true; cbInfo.fStartsWithClear = false;