1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef OpsTask_DEFINED 9cb93a386Sopenharmony_ci#define OpsTask_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 12cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h" 13cb93a386Sopenharmony_ci#include "include/core/SkSpan.h" 14cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h" 15cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 16cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h" 17cb93a386Sopenharmony_ci#include "include/private/SkTArray.h" 18cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h" 19cb93a386Sopenharmony_ci#include "src/core/SkArenaAlloc.h" 20cb93a386Sopenharmony_ci#include "src/core/SkClipStack.h" 21cb93a386Sopenharmony_ci#include "src/core/SkStringUtils.h" 22cb93a386Sopenharmony_ci#include "src/core/SkTLazy.h" 23cb93a386Sopenharmony_ci#include "src/gpu/GrAppliedClip.h" 24cb93a386Sopenharmony_ci#include "src/gpu/GrDstProxyView.h" 25cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h" 26cb93a386Sopenharmony_ci#include "src/gpu/GrProcessorSet.h" 27cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTask.h" 28cb93a386Sopenharmony_ci#include "src/gpu/ops/GrOp.h" 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ciclass GrAuditTrail; 31cb93a386Sopenharmony_ciclass GrCaps; 32cb93a386Sopenharmony_ciclass GrClearOp; 33cb93a386Sopenharmony_ciclass GrGpuBuffer; 34cb93a386Sopenharmony_ciclass GrRenderTargetProxy; 35cb93a386Sopenharmony_ciclass OpsTaskTestingAccess; 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_cinamespace skgpu::v1 { 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ciclass SurfaceDrawContext; 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ciclass OpsTask : public GrRenderTask { 42cb93a386Sopenharmony_cipublic: 43cb93a386Sopenharmony_ci // Manage the arenas life time by maintaining are reference to it. 44cb93a386Sopenharmony_ci OpsTask(GrDrawingManager*, GrSurfaceProxyView, GrAuditTrail*, sk_sp<GrArenas>); 45cb93a386Sopenharmony_ci ~OpsTask() override; 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci OpsTask* asOpsTask() override { return this; } 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci bool isEmpty() const { return fOpChains.empty(); } 50cb93a386Sopenharmony_ci bool usesMSAASurface() const { return fUsesMSAASurface; } 51cb93a386Sopenharmony_ci GrXferBarrierFlags renderPassXferBarriers() const { return fRenderPassXferBarriers; } 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci /** 54cb93a386Sopenharmony_ci * Empties the draw buffer of any queued up draws. 55cb93a386Sopenharmony_ci */ 56cb93a386Sopenharmony_ci void endFlush(GrDrawingManager*) override; 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci void onPrePrepare(GrRecordingContext*) override; 59cb93a386Sopenharmony_ci /** 60cb93a386Sopenharmony_ci * Together these two functions flush all queued up draws to GrCommandBuffer. The return value 61cb93a386Sopenharmony_ci * of onExecute() indicates whether any commands were actually issued to the GPU. 62cb93a386Sopenharmony_ci */ 63cb93a386Sopenharmony_ci void onPrepare(GrOpFlushState* flushState) override; 64cb93a386Sopenharmony_ci bool onExecute(GrOpFlushState* flushState) override; 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci void addSampledTexture(GrSurfaceProxy* proxy) { 67cb93a386Sopenharmony_ci // This function takes a GrSurfaceProxy because all subsequent uses of the proxy do not 68cb93a386Sopenharmony_ci // require the specifics of GrTextureProxy, so this avoids a number of unnecessary virtual 69cb93a386Sopenharmony_ci // asTextureProxy() calls. However, sampling the proxy implicitly requires that the proxy 70cb93a386Sopenharmony_ci // be a texture. Eventually, when proxies are a unified type with flags, this can just 71cb93a386Sopenharmony_ci // assert that capability. 72cb93a386Sopenharmony_ci SkASSERT(proxy->asTextureProxy()); 73cb93a386Sopenharmony_ci fSampledProxies.push_back(proxy); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci void addOp(GrDrawingManager*, GrOp::Owner, GrTextureResolveManager, const GrCaps&); 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci void addDrawOp(GrDrawingManager*, GrOp::Owner, bool usesMSAA, const GrProcessorSet::Analysis&, 79cb93a386Sopenharmony_ci GrAppliedClip&&, const GrDstProxyView&, GrTextureResolveManager, const GrCaps&); 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci void discard(); 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci enum class CanDiscardPreviousOps : bool { 84cb93a386Sopenharmony_ci kYes = true, 85cb93a386Sopenharmony_ci kNo = false 86cb93a386Sopenharmony_ci }; 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci // Perform book-keeping for a fullscreen clear, regardless of how the clear is implemented later 89cb93a386Sopenharmony_ci // (i.e. setColorLoadOp(), adding a ClearOp, or adding a FillRectOp that covers the device). 90cb93a386Sopenharmony_ci // Returns true if the clear can be converted into a load op (barring device caps). 91cb93a386Sopenharmony_ci bool resetForFullscreenClear(CanDiscardPreviousOps); 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci // Must only be called if native color buffer clearing is enabled. 94cb93a386Sopenharmony_ci void setColorLoadOp(GrLoadOp op, std::array<float, 4> color = {0, 0, 0, 0}); 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci // Returns whether the given opsTask can be appended at the end of this one. 97cb93a386Sopenharmony_ci bool canMerge(const OpsTask*) const; 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci // Merge as many opsTasks as possible from the head of 'tasks'. They should all be 100cb93a386Sopenharmony_ci // renderPass compatible. Return the number of tasks merged into 'this'. 101cb93a386Sopenharmony_ci int mergeFrom(SkSpan<const sk_sp<GrRenderTask>> tasks); 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci#ifdef SK_DEBUG 104cb93a386Sopenharmony_ci int numClips() const override { return fNumClips; } 105cb93a386Sopenharmony_ci void visitProxies_debugOnly(const GrVisitProxyFunc&) const override; 106cb93a386Sopenharmony_ci#endif 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci#if GR_TEST_UTILS 109cb93a386Sopenharmony_ci void dump(const SkString& label, 110cb93a386Sopenharmony_ci SkString indent, 111cb93a386Sopenharmony_ci bool printDependencies, 112cb93a386Sopenharmony_ci bool close) const override; 113cb93a386Sopenharmony_ci const char* name() const final { return "Ops"; } 114cb93a386Sopenharmony_ci int numOpChains() const { return fOpChains.count(); } 115cb93a386Sopenharmony_ci const GrOp* getChain(int index) const { return fOpChains[index].head(); } 116cb93a386Sopenharmony_ci#endif 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ciprotected: 119cb93a386Sopenharmony_ci enum class StencilContent { 120cb93a386Sopenharmony_ci kDontCare, 121cb93a386Sopenharmony_ci kUserBitsCleared, // User bits: cleared 122cb93a386Sopenharmony_ci // Clip bit: don't care (Ganesh always pre-clears the clip bit.) 123cb93a386Sopenharmony_ci kPreserved 124cb93a386Sopenharmony_ci }; 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci // Lets the caller specify what the content of the stencil buffer should be at the beginning 127cb93a386Sopenharmony_ci // of the render pass. 128cb93a386Sopenharmony_ci // 129cb93a386Sopenharmony_ci // When requesting kClear: Tilers will load the stencil buffer with a "clear" op; non-tilers 130cb93a386Sopenharmony_ci // will clear the stencil on first load, and then preserve it on subsequent loads. (Preserving 131cb93a386Sopenharmony_ci // works because SurfaceDrawContexts are required to leave the user bits in a cleared state 132cb93a386Sopenharmony_ci // once finished.) 133cb93a386Sopenharmony_ci // 134cb93a386Sopenharmony_ci // NOTE: initialContent must not be kClear if caps.performStencilClearsAsDraws() is true. 135cb93a386Sopenharmony_ci void setInitialStencilContent(StencilContent initialContent) { 136cb93a386Sopenharmony_ci fInitialStencilContent = initialContent; 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci void recordOp(GrOp::Owner, bool usesMSAA, GrProcessorSet::Analysis, GrAppliedClip*, 140cb93a386Sopenharmony_ci const GrDstProxyView*, const GrCaps&); 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci ExpectedOutcome onMakeClosed(GrRecordingContext*, SkIRect* targetUpdateBounds) override; 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ciprivate: 145cb93a386Sopenharmony_ci bool isColorNoOp() const { 146cb93a386Sopenharmony_ci // TODO: GrLoadOp::kDiscard (i.e., storing a discard) should also be grounds for skipping 147cb93a386Sopenharmony_ci // execution. We currently don't because of Vulkan. See http://skbug.com/9373. 148cb93a386Sopenharmony_ci return fOpChains.empty() && GrLoadOp::kLoad == fColorLoadOp; 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci void deleteOps(); 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_ci // If a surfaceDrawContext splits its opsTask, it uses this method to guarantee stencil values 154cb93a386Sopenharmony_ci // get preserved across its split tasks. 155cb93a386Sopenharmony_ci void setMustPreserveStencil() { fMustPreserveStencil = true; } 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci // Prevents this opsTask from merging backward. This is used by DMSAA when a non-multisampled 158cb93a386Sopenharmony_ci // opsTask cannot be promoted to MSAA, or when we split a multisampled opsTask in order to 159cb93a386Sopenharmony_ci // resolve its texture. 160cb93a386Sopenharmony_ci void setCannotMergeBackward() { fCannotMergeBackward = true; } 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci class OpChain { 163cb93a386Sopenharmony_ci public: 164cb93a386Sopenharmony_ci OpChain(GrOp::Owner, GrProcessorSet::Analysis, GrAppliedClip*, const GrDstProxyView*); 165cb93a386Sopenharmony_ci ~OpChain() { 166cb93a386Sopenharmony_ci // The ops are stored in a GrMemoryPool and must be explicitly deleted via the pool. 167cb93a386Sopenharmony_ci SkASSERT(fList.empty()); 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci OpChain(const OpChain&) = delete; 171cb93a386Sopenharmony_ci OpChain& operator=(const OpChain&) = delete; 172cb93a386Sopenharmony_ci OpChain(OpChain&&) = default; 173cb93a386Sopenharmony_ci OpChain& operator=(OpChain&&) = default; 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ci void visitProxies(const GrVisitProxyFunc&) const; 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci GrOp* head() const { return fList.head(); } 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci GrAppliedClip* appliedClip() const { return fAppliedClip; } 180cb93a386Sopenharmony_ci const GrDstProxyView& dstProxyView() const { return fDstProxyView; } 181cb93a386Sopenharmony_ci const SkRect& bounds() const { return fBounds; } 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci // Deletes all the ops in the chain. 184cb93a386Sopenharmony_ci void deleteOps(); 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ci // Attempts to move the ops from the passed chain to this chain at the head. Also attempts 187cb93a386Sopenharmony_ci // to merge ops between the chains. Upon success the passed chain is empty. 188cb93a386Sopenharmony_ci // Fails when the chains aren't of the same op type, have different clips or dst proxies. 189cb93a386Sopenharmony_ci bool prependChain(OpChain*, const GrCaps&, SkArenaAlloc* opsTaskArena, GrAuditTrail*); 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci // Attempts to add 'op' to this chain either by merging or adding to the tail. Returns 192cb93a386Sopenharmony_ci // 'op' to the caller upon failure, otherwise null. Fails when the op and chain aren't of 193cb93a386Sopenharmony_ci // the same op type, have different clips or dst proxies. 194cb93a386Sopenharmony_ci GrOp::Owner appendOp(GrOp::Owner op, GrProcessorSet::Analysis, const GrDstProxyView*, 195cb93a386Sopenharmony_ci const GrAppliedClip*, const GrCaps&, SkArenaAlloc* opsTaskArena, 196cb93a386Sopenharmony_ci GrAuditTrail*); 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ci bool shouldExecute() const { 199cb93a386Sopenharmony_ci return SkToBool(this->head()); 200cb93a386Sopenharmony_ci } 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ci private: 203cb93a386Sopenharmony_ci class List { 204cb93a386Sopenharmony_ci public: 205cb93a386Sopenharmony_ci List() = default; 206cb93a386Sopenharmony_ci List(GrOp::Owner); 207cb93a386Sopenharmony_ci List(List&&); 208cb93a386Sopenharmony_ci List& operator=(List&& that); 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci bool empty() const { return !SkToBool(fHead); } 211cb93a386Sopenharmony_ci GrOp* head() const { return fHead.get(); } 212cb93a386Sopenharmony_ci GrOp* tail() const { return fTail; } 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci GrOp::Owner popHead(); 215cb93a386Sopenharmony_ci GrOp::Owner removeOp(GrOp* op); 216cb93a386Sopenharmony_ci void pushHead(GrOp::Owner op); 217cb93a386Sopenharmony_ci void pushTail(GrOp::Owner); 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci void validate() const; 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ci private: 222cb93a386Sopenharmony_ci GrOp::Owner fHead{nullptr}; 223cb93a386Sopenharmony_ci GrOp* fTail{nullptr}; 224cb93a386Sopenharmony_ci }; 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci void validate() const; 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_ci bool tryConcat(List*, GrProcessorSet::Analysis, const GrDstProxyView&, const GrAppliedClip*, 229cb93a386Sopenharmony_ci const SkRect& bounds, const GrCaps&, SkArenaAlloc* opsTaskArena, 230cb93a386Sopenharmony_ci GrAuditTrail*); 231cb93a386Sopenharmony_ci static List DoConcat(List, List, const GrCaps&, SkArenaAlloc* opsTaskArena, GrAuditTrail*); 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci List fList; 234cb93a386Sopenharmony_ci GrProcessorSet::Analysis fProcessorAnalysis; 235cb93a386Sopenharmony_ci GrDstProxyView fDstProxyView; 236cb93a386Sopenharmony_ci GrAppliedClip* fAppliedClip; 237cb93a386Sopenharmony_ci SkRect fBounds; 238cb93a386Sopenharmony_ci }; 239cb93a386Sopenharmony_ci 240cb93a386Sopenharmony_ci void onMakeSkippable() override; 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci bool onIsUsed(GrSurfaceProxy*) const override; 243cb93a386Sopenharmony_ci 244cb93a386Sopenharmony_ci void gatherProxyIntervals(GrResourceAllocator*) const override; 245cb93a386Sopenharmony_ci 246cb93a386Sopenharmony_ci void forwardCombine(const GrCaps&); 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci // Remove all ops, proxies, etc. Used in the merging algorithm when tasks can be skipped. 249cb93a386Sopenharmony_ci void reset(); 250cb93a386Sopenharmony_ci 251cb93a386Sopenharmony_ci friend class ::OpsTaskTestingAccess; 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci // The SDC and OpsTask have to work together to handle buffer clears. In most cases, buffer 254cb93a386Sopenharmony_ci // clearing can be done natively, in which case the op list's load ops are sufficient. In other 255cb93a386Sopenharmony_ci // cases, draw ops must be used, which makes the SDC the best place for those decisions. This, 256cb93a386Sopenharmony_ci // however, requires that the SDC be able to coordinate with the op list to achieve similar ends 257cb93a386Sopenharmony_ci friend class skgpu::v1::SurfaceDrawContext; 258cb93a386Sopenharmony_ci 259cb93a386Sopenharmony_ci GrAuditTrail* fAuditTrail; 260cb93a386Sopenharmony_ci 261cb93a386Sopenharmony_ci bool fUsesMSAASurface; 262cb93a386Sopenharmony_ci GrSwizzle fTargetSwizzle; 263cb93a386Sopenharmony_ci GrSurfaceOrigin fTargetOrigin; 264cb93a386Sopenharmony_ci 265cb93a386Sopenharmony_ci GrLoadOp fColorLoadOp = GrLoadOp::kLoad; 266cb93a386Sopenharmony_ci std::array<float, 4> fLoadClearColor = {0, 0, 0, 0}; 267cb93a386Sopenharmony_ci StencilContent fInitialStencilContent = StencilContent::kDontCare; 268cb93a386Sopenharmony_ci bool fMustPreserveStencil = false; 269cb93a386Sopenharmony_ci bool fCannotMergeBackward = false; 270cb93a386Sopenharmony_ci 271cb93a386Sopenharmony_ci uint32_t fLastClipStackGenID = SK_InvalidUniqueID; 272cb93a386Sopenharmony_ci SkIRect fLastDevClipBounds; 273cb93a386Sopenharmony_ci int fLastClipNumAnalyticElements; 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci GrXferBarrierFlags fRenderPassXferBarriers = GrXferBarrierFlags::kNone; 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci // For ops/opsTask we have mean: 5 stdDev: 28 278cb93a386Sopenharmony_ci SkSTArray<25, OpChain> fOpChains; 279cb93a386Sopenharmony_ci 280cb93a386Sopenharmony_ci sk_sp<GrArenas> fArenas; 281cb93a386Sopenharmony_ci SkDEBUGCODE(int fNumClips;) 282cb93a386Sopenharmony_ci 283cb93a386Sopenharmony_ci // TODO: We could look into this being a set if we find we're adding a lot of duplicates that is 284cb93a386Sopenharmony_ci // causing slow downs. 285cb93a386Sopenharmony_ci SkTArray<GrSurfaceProxy*, true> fSampledProxies; 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ci SkRect fTotalBounds = SkRect::MakeEmpty(); 288cb93a386Sopenharmony_ci SkIRect fClippedContentBounds = SkIRect::MakeEmpty(); 289cb93a386Sopenharmony_ci}; 290cb93a386Sopenharmony_ci 291cb93a386Sopenharmony_ci} // namespace skgpu::v1 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci#endif // OpsTask_DEFINED 294