Flutter Engine
The Flutter Engine
Classes | Public Types | Public Member Functions | Protected Types | Protected Member Functions | Friends | List of all members
skgpu::ganesh::OpsTask Class Reference

#include <OpsTask.h>

Inheritance diagram for skgpu::ganesh::OpsTask:
GrRenderTask SkRefCnt SkRefCntBase skgpu::ganesh::AtlasRenderTask

Public Types

enum class  CanDiscardPreviousOps : bool { kYes = true , kNo = false }
 

Public Member Functions

 OpsTask (GrDrawingManager *, GrSurfaceProxyView, GrAuditTrail *, sk_sp< GrArenas >)
 
 ~OpsTask () override
 
OpsTaskasOpsTask () override
 
bool isEmpty () const
 
bool usesMSAASurface () const
 
GrXferBarrierFlags renderPassXferBarriers () const
 
void endFlush (GrDrawingManager *) override
 
void onPrePrepare (GrRecordingContext *) override
 
void onPrepare (GrOpFlushState *flushState) override
 
bool onExecute (GrOpFlushState *flushState) override
 
void addSampledTexture (GrSurfaceProxy *proxy)
 
void addOp (GrDrawingManager *, GrOp::Owner, GrTextureResolveManager, const GrCaps &)
 
void addDrawOp (GrDrawingManager *, GrOp::Owner, bool usesMSAA, const GrProcessorSet::Analysis &, GrAppliedClip &&, const GrDstProxyView &, GrTextureResolveManager, const GrCaps &)
 
void discard ()
 
bool resetForFullscreenClear (CanDiscardPreviousOps)
 
void setColorLoadOp (GrLoadOp op, std::array< float, 4 > color={0, 0, 0, 0})
 
bool canMerge (const OpsTask *) const
 
int mergeFrom (SkSpan< const sk_sp< GrRenderTask > > tasks)
 
- Public Member Functions inherited from GrRenderTask
 GrRenderTask ()
 
 SkDEBUGCODE (~GrRenderTask() override;) void makeClosed(GrRecordingContext *)
 
void prePrepare (GrRecordingContext *context)
 
void prepare (GrOpFlushState *flushState)
 
bool execute (GrOpFlushState *flushState)
 
virtual bool requiresExplicitCleanup () const
 
virtual void endFlush (GrDrawingManager *)
 
virtual void disown (GrDrawingManager *)
 
bool isClosed () const
 
void makeSkippable ()
 
bool isSkippable () const
 
bool blocksReordering () const
 
void addDependency (GrDrawingManager *, GrSurfaceProxy *dependedOn, skgpu::Mipmapped, GrTextureResolveManager, const GrCaps &caps)
 
void addDependenciesFromOtherTask (GrRenderTask *otherTask)
 
SkSpan< GrRenderTask * > dependencies ()
 
SkSpan< GrRenderTask * > dependents ()
 
void replaceDependency (const GrRenderTask *toReplace, GrRenderTask *replaceWith)
 
void replaceDependent (const GrRenderTask *toReplace, GrRenderTask *replaceWith)
 
bool dependsOn (const GrRenderTask *dependedOn) const
 
uint32_t uniqueID () const
 
int numTargets () const
 
GrSurfaceProxytarget (int i) const
 
virtual skgpu::ganesh::OpsTaskasOpsTask ()
 
bool isUsed (GrSurfaceProxy *proxy) const
 
virtual void gatherProxyIntervals (GrResourceAllocator *) const =0
 
bool isInstantiated () const
 
 SK_DECLARE_INTERNAL_LLIST_INTERFACE (GrRenderTask)
 
- Public Member Functions inherited from SkRefCntBase
 SkRefCntBase ()
 
virtual ~SkRefCntBase ()
 
bool unique () const
 
void ref () const
 
void unref () const
 

Protected Types

enum class  StencilContent { kDontCare , kUserBitsCleared , kPreserved }
 
- Protected Types inherited from GrRenderTask
enum class  ExpectedOutcome : bool { kTargetUnchanged , kTargetDirty }
 
enum  Flags {
  kClosed_Flag = 0x01 , kDisowned_Flag = 0x02 , kSkippable_Flag = 0x04 , kAtlas_Flag = 0x08 ,
  kBlocksReordering_Flag = 0x10 , kWasOutput_Flag = 0x20 , kTempMark_Flag = 0x40
}
 

Protected Member Functions

void setInitialStencilContent (StencilContent initialContent)
 
void recordOp (GrOp::Owner, bool usesMSAA, GrProcessorSet::Analysis, GrAppliedClip *, const GrDstProxyView *, const GrCaps &)
 
ExpectedOutcome onMakeClosed (GrRecordingContext *, SkIRect *targetUpdateBounds) override
 
- Protected Member Functions inherited from GrRenderTask
 SkDEBUGCODE (bool deferredProxiesAreInstantiated() const ;) void addTarget(GrDrawingManager *
 
void addTarget (GrDrawingManager *dm, const GrSurfaceProxyView &view)
 
virtual ExpectedOutcome onMakeClosed (GrRecordingContext *, SkIRect *targetUpdateBounds)=0
 
void setFlag (uint32_t flag)
 
void resetFlag (uint32_t flag)
 
bool isSetFlag (uint32_t flag) const
 
void setIndex (uint32_t index)
 
uint32_t getIndex () const
 

Friends

class ::OpsTaskTestingAccess
 
class skgpu::ganesh::SurfaceDrawContext
 

Additional Inherited Members

- Protected Attributes inherited from GrRenderTask
 sk_sp< GrSurfaceProxy >
 
skia_private::STArray< 1, sk_sp< GrSurfaceProxy > > fTargets
 
skia_private::TArray< GrTextureProxy *, truefDeferredProxies
 

Detailed Description

Definition at line 42 of file OpsTask.h.

Member Enumeration Documentation

◆ CanDiscardPreviousOps

Enumerator
kYes 
kNo 

Definition at line 84 of file OpsTask.h.

84 : bool {
85 kYes = true,
86 kNo = false
87 };
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.

◆ StencilContent

enum class skgpu::ganesh::OpsTask::StencilContent
strongprotected
Enumerator
kDontCare 
kUserBitsCleared 
kPreserved 

Definition at line 120 of file OpsTask.h.

120 {
121 kDontCare,
122 kUserBitsCleared, // User bits: cleared
123 // Clip bit: don't care (Ganesh always pre-clears the clip bit.)
124 kPreserved
125 };

Constructor & Destructor Documentation

◆ OpsTask()

skgpu::ganesh::OpsTask::OpsTask ( GrDrawingManager drawingMgr,
GrSurfaceProxyView  view,
GrAuditTrail auditTrail,
sk_sp< GrArenas arenas 
)

Definition at line 392 of file OpsTask.cpp.

396 : GrRenderTask()
397 , fAuditTrail(auditTrail)
398 , fUsesMSAASurface(view.asRenderTargetProxy()->numSamples() > 1)
399 , fTargetSwizzle(view.swizzle())
400 , fTargetOrigin(view.origin())
401 , fArenas{std::move(arenas)}
402 SkDEBUGCODE(, fNumClips(0)) {
403 this->addTarget(drawingMgr, view.detachProxy());
404}
void addTarget(GrDrawingManager *dm, const GrSurfaceProxyView &view)
Definition: GrRenderTask.h:166
SkDEBUGCODE(~GrRenderTask() override;) void makeClosed(GrRecordingContext *)
skgpu::Swizzle swizzle() const
sk_sp< GrSurfaceProxy > detachProxy()
GrSurfaceOrigin origin() const
GrRenderTargetProxy * asRenderTargetProxy() const

◆ ~OpsTask()

skgpu::ganesh::OpsTask::~OpsTask ( )
override

Definition at line 413 of file OpsTask.cpp.

413 {
414 this->deleteOps();
415}

Member Function Documentation

◆ addDrawOp()

void skgpu::ganesh::OpsTask::addDrawOp ( GrDrawingManager drawingMgr,
GrOp::Owner  op,
bool  usesMSAA,
const GrProcessorSet::Analysis processorAnalysis,
GrAppliedClip &&  clip,
const GrDstProxyView dstProxyView,
GrTextureResolveManager  textureResolveManager,
const GrCaps caps 
)

Definition at line 429 of file OpsTask.cpp.

432 {
433 auto addDependency = [&](GrSurfaceProxy* p, skgpu::Mipmapped mipmapped) {
434 this->addSampledTexture(p);
435 this->addDependency(drawingMgr, p, mipmapped, textureResolveManager, caps);
436 };
437
438 op->visitProxies(addDependency);
439 clip.visitProxies(addDependency);
440 if (dstProxyView.proxy()) {
442 this->addSampledTexture(dstProxyView.proxy());
443 }
445 fRenderPassXferBarriers |= GrXferBarrierFlags::kTexture;
446 }
449 dstProxyView.offset().isZero());
450 }
451
452 if (processorAnalysis.usesNonCoherentHWBlending()) {
453 fRenderPassXferBarriers |= GrXferBarrierFlags::kBlend;
454 }
455
456 this->recordOp(std::move(op), usesMSAA, processorAnalysis, clip.doesClip() ? &clip : nullptr,
457 &dstProxyView, caps);
458}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
GrDstSampleFlags dstSampleFlags() const
const SkIPoint & offset() const
GrSurfaceProxy * proxy() const
bool usesNonCoherentHWBlending() const
void addDependency(GrDrawingManager *, GrSurfaceProxy *dependedOn, skgpu::Mipmapped, GrTextureResolveManager, const GrCaps &caps)
void recordOp(GrOp::Owner, bool usesMSAA, GrProcessorSet::Analysis, GrAppliedClip *, const GrDstProxyView *, const GrCaps &)
Definition: OpsTask.cpp:955
void addSampledTexture(GrSurfaceProxy *proxy)
Definition: OpsTask.h:67
Mipmapped
Definition: GpuTypes.h:53
bool isZero() const
Definition: SkPoint_impl.h:58

◆ addOp()

void skgpu::ganesh::OpsTask::addOp ( GrDrawingManager drawingMgr,
GrOp::Owner  op,
GrTextureResolveManager  textureResolveManager,
const GrCaps caps 
)

Definition at line 417 of file OpsTask.cpp.

418 {
419 auto addDependency = [&](GrSurfaceProxy* p, skgpu::Mipmapped mipmapped) {
420 this->addDependency(drawingMgr, p, mipmapped, textureResolveManager, caps);
421 };
422
423 op->visitProxies(addDependency);
424
425 this->recordOp(std::move(op), false/*usesMSAA*/, GrProcessorSet::EmptySetAnalysis(), nullptr,
426 nullptr, caps);
427}
static constexpr Analysis EmptySetAnalysis()

◆ addSampledTexture()

void skgpu::ganesh::OpsTask::addSampledTexture ( GrSurfaceProxy proxy)
inline

Definition at line 67 of file OpsTask.h.

67 {
68 // This function takes a GrSurfaceProxy because all subsequent uses of the proxy do not
69 // require the specifics of GrTextureProxy, so this avoids a number of unnecessary virtual
70 // asTextureProxy() calls. However, sampling the proxy implicitly requires that the proxy
71 // be a texture. Eventually, when proxies are a unified type with flags, this can just
72 // assert that capability.
73 SkASSERT(proxy->asTextureProxy());
74 fSampledProxies.push_back(proxy);
75 }
virtual GrTextureProxy * asTextureProxy()

◆ asOpsTask()

OpsTask * skgpu::ganesh::OpsTask::asOpsTask ( )
inlineoverridevirtual

Reimplemented from GrRenderTask.

Definition at line 48 of file OpsTask.h.

48{ return this; }

◆ canMerge()

bool skgpu::ganesh::OpsTask::canMerge ( const OpsTask opsTask) const

Definition at line 678 of file OpsTask.cpp.

678 {
679 return this->target(0) == opsTask->target(0) &&
680 fArenas == opsTask->fArenas &&
681 !opsTask->fCannotMergeBackward;
682}
GrSurfaceProxy * target(int i) const
Definition: GrRenderTask.h:104

◆ discard()

void skgpu::ganesh::OpsTask::discard ( )

Definition at line 773 of file OpsTask.cpp.

773 {
774 // Discard calls to in-progress opsTasks are ignored. Calls at the start update the
775 // opsTasks' color & stencil load ops.
776 if (this->isEmpty()) {
777 fColorLoadOp = GrLoadOp::kDiscard;
778 fInitialStencilContent = StencilContent::kDontCare;
779 fTotalBounds.setEmpty();
780 }
781}
bool isEmpty() const
Definition: OpsTask.h:50
void setEmpty()
Definition: SkRect.h:842

◆ endFlush()

void skgpu::ganesh::OpsTask::endFlush ( GrDrawingManager drawingMgr)
overridevirtual

Empties the draw buffer of any queued up draws.

Reimplemented from GrRenderTask.

Definition at line 460 of file OpsTask.cpp.

460 {
461 fLastClipStackGenID = SK_InvalidUniqueID;
462 this->deleteOps();
463
465 fSampledProxies.clear();
466 fAuditTrail = nullptr;
467
468 GrRenderTask::endFlush(drawingMgr);
469}
static constexpr uint32_t SK_InvalidUniqueID
Definition: SkTypes.h:196
virtual void endFlush(GrDrawingManager *)
Definition: GrRenderTask.h:49
skia_private::TArray< GrTextureProxy *, true > fDeferredProxies
Definition: GrRenderTask.h:187

◆ isEmpty()

bool skgpu::ganesh::OpsTask::isEmpty ( ) const
inline

Definition at line 50 of file OpsTask.h.

50{ return fOpChains.empty(); }
bool empty() const
Definition: SkTArray.h:199

◆ mergeFrom()

int skgpu::ganesh::OpsTask::mergeFrom ( SkSpan< const sk_sp< GrRenderTask > >  tasks)

Definition at line 684 of file OpsTask.cpp.

684 {
685 int mergedCount = 0;
686 for (const sk_sp<GrRenderTask>& task : tasks) {
687 auto opsTask = task->asOpsTask();
688 if (!opsTask || !this->canMerge(opsTask)) {
689 break;
690 }
691 SkASSERT(fTargetSwizzle == opsTask->fTargetSwizzle);
692 SkASSERT(fTargetOrigin == opsTask->fTargetOrigin);
693 if (GrLoadOp::kClear == opsTask->fColorLoadOp) {
694 // TODO(11903): Go back to actually dropping ops tasks when we are merged with
695 // color clear.
696 return 0;
697 }
698 mergedCount += 1;
699 }
700 if (0 == mergedCount) {
701 return 0;
702 }
703
704 SkSpan<const sk_sp<OpsTask>> mergingNodes(
705 reinterpret_cast<const sk_sp<OpsTask>*>(tasks.data()), SkToSizeT(mergedCount));
706 int addlDeferredProxyCount = 0;
707 int addlProxyCount = 0;
708 int addlOpChainCount = 0;
709 for (const auto& toMerge : mergingNodes) {
710 addlDeferredProxyCount += toMerge->fDeferredProxies.size();
711 addlProxyCount += toMerge->fSampledProxies.size();
712 addlOpChainCount += toMerge->fOpChains.size();
713 fClippedContentBounds.join(toMerge->fClippedContentBounds);
714 fTotalBounds.join(toMerge->fTotalBounds);
715 fRenderPassXferBarriers |= toMerge->fRenderPassXferBarriers;
716 if (fInitialStencilContent == StencilContent::kDontCare) {
717 // Propogate the first stencil content that isn't kDontCare.
718 //
719 // Once the stencil has any kind of initial content that isn't kDontCare, then the
720 // inital contents of subsequent opsTasks that get merged in don't matter.
721 //
722 // (This works because the opsTask all target the same render target and are in
723 // painter's order. kPreserved obviously happens automatically with a merge, and kClear
724 // is also automatic because the contract is for ops to leave the stencil buffer in a
725 // cleared state when finished.)
726 fInitialStencilContent = toMerge->fInitialStencilContent;
727 }
728 fUsesMSAASurface |= toMerge->fUsesMSAASurface;
729 SkDEBUGCODE(fNumClips += toMerge->fNumClips);
730 }
731
732 fLastClipStackGenID = SK_InvalidUniqueID;
733 fDeferredProxies.reserve_exact(fDeferredProxies.size() + addlDeferredProxyCount);
734 fSampledProxies.reserve_exact(fSampledProxies.size() + addlProxyCount);
735 fOpChains.reserve_exact(fOpChains.size() + addlOpChainCount);
736 for (const auto& toMerge : mergingNodes) {
737 for (GrRenderTask* renderTask : toMerge->dependents()) {
738 renderTask->replaceDependency(toMerge.get(), this);
739 }
740 for (GrRenderTask* renderTask : toMerge->dependencies()) {
741 renderTask->replaceDependent(toMerge.get(), this);
742 }
743 fDeferredProxies.move_back_n(toMerge->fDeferredProxies.size(),
744 toMerge->fDeferredProxies.data());
745 fSampledProxies.move_back_n(toMerge->fSampledProxies.size(),
746 toMerge->fSampledProxies.data());
747 fOpChains.move_back_n(toMerge->fOpChains.size(),
748 toMerge->fOpChains.data());
749 toMerge->fDeferredProxies.clear();
750 toMerge->fSampledProxies.clear();
751 toMerge->fOpChains.clear();
752 }
753 fMustPreserveStencil = mergingNodes.back()->fMustPreserveStencil;
754 return mergedCount;
755}
constexpr size_t SkToSizeT(S x)
Definition: SkTo.h:31
SkSpan< GrRenderTask * > dependencies()
Definition: GrRenderTask.h:90
SkSpan< GrRenderTask * > dependents()
Definition: GrRenderTask.h:91
bool canMerge(const OpsTask *) const
Definition: OpsTask.cpp:678
T * move_back_n(int n, T *t)
Definition: SkTArray.h:307
int size() const
Definition: SkTArray.h:421
void reserve_exact(int n)
Definition: SkTArray.h:181
void join(const SkIRect &r)
Definition: SkRect.cpp:31
void join(const SkRect &r)
Definition: SkRect.cpp:126

◆ onExecute()

bool skgpu::ganesh::OpsTask::onExecute ( GrOpFlushState flushState)
overridevirtual

Implements GrRenderTask.

Definition at line 540 of file OpsTask.cpp.

540 {
541 SkASSERT(this->numTargets() == 1);
543 SkASSERT(proxy);
545
546 if (this->isColorNoOp() || fClippedContentBounds.isEmpty()) {
547 return false;
548 }
549 TRACE_EVENT0_ALWAYS("skia.gpu", TRACE_FUNC);
550
551 // Make sure load ops are not kClear if the GPU needs to use draws for clears
552 SkASSERT(fColorLoadOp != GrLoadOp::kClear ||
553 !flushState->gpu()->caps()->performColorClearsAsDraws());
554
555 const GrCaps& caps = *flushState->gpu()->caps();
556 GrRenderTarget* renderTarget = proxy->peekRenderTarget();
557 SkASSERT(renderTarget);
558
559 GrAttachment* stencil = nullptr;
560 if (proxy->needsStencil()) {
561 SkASSERT(proxy->canUseStencil(caps));
562 if (!flushState->resourceProvider()->attachStencilAttachment(renderTarget,
563 fUsesMSAASurface)) {
564 SkDebugf("WARNING: failed to attach a stencil buffer. Rendering will be skipped.\n");
565 return false;
566 }
567 stencil = renderTarget->getStencilAttachment(fUsesMSAASurface);
568 }
569
570 GrLoadOp stencilLoadOp;
571 switch (fInitialStencilContent) {
573 stencilLoadOp = GrLoadOp::kDiscard;
574 break;
577 SkASSERT(stencil);
579 // Always clear the stencil if it is being discarded after render passes. This is
580 // also an optimization because we are on a tiler and it avoids loading the values
581 // from memory.
582 stencilLoadOp = GrLoadOp::kClear;
583 break;
584 }
585 if (!stencil->hasPerformedInitialClear()) {
586 stencilLoadOp = GrLoadOp::kClear;
588 break;
589 }
590 // SurfaceDrawContexts are required to leave the user stencil bits in a cleared state
591 // once finished, meaning the stencil values will always remain cleared after the
592 // initial clear. Just fall through to reloading the existing (cleared) stencil values
593 // from memory.
594 [[fallthrough]];
596 SkASSERT(stencil);
597 stencilLoadOp = GrLoadOp::kLoad;
598 break;
599 }
600
601 // NOTE: If fMustPreserveStencil is set, then we are executing a surfaceDrawContext that split
602 // its opsTask.
603 //
604 // FIXME: We don't currently flag render passes that don't use stencil at all. In that case
605 // their store op might be "discard", and we currently make the assumption that a discard will
606 // not invalidate what's already in main memory. This is probably ok for now, but certainly
607 // something we want to address soon.
608 GrStoreOp stencilStoreOp = (caps.discardStencilValuesAfterRenderPass() && !fMustPreserveStencil)
611
612 GrOpsRenderPass* renderPass = create_render_pass(flushState->gpu(),
613 proxy->peekRenderTarget(),
614 fUsesMSAASurface,
615 stencil,
616 fTargetOrigin,
617 fClippedContentBounds,
618 fColorLoadOp,
619 fLoadClearColor,
620 stencilLoadOp,
621 stencilStoreOp,
622 fSampledProxies,
623 fRenderPassXferBarriers);
624
625 if (!renderPass) {
626 return false;
627 }
628 flushState->setOpsRenderPass(renderPass);
629 renderPass->begin();
630
631 GrSurfaceProxyView dstView(sk_ref_sp(this->target(0)), fTargetOrigin, fTargetSwizzle);
632
633 // Draw all the generated geometry.
634 for (const auto& chain : fOpChains) {
635 if (!chain.shouldExecute()) {
636 continue;
637 }
638
639 GrOpFlushState::OpArgs opArgs(chain.head(),
640 dstView,
641 fUsesMSAASurface,
642 chain.appliedClip(),
643 chain.dstProxyView(),
644 fRenderPassXferBarriers,
645 fColorLoadOp);
646
647 flushState->setOpArgs(&opArgs);
648 chain.head()->execute(flushState, chain.bounds());
649 flushState->setOpArgs(nullptr);
650 }
651
652 renderPass->end();
653 flushState->gpu()->submit(renderPass);
654 flushState->setOpsRenderPass(nullptr);
655
656 return true;
657}
GrStoreOp
Definition: GrTypesPriv.h:165
GrLoadOp
Definition: GrTypesPriv.h:155
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
#define SK_AT_SCOPE_EXIT(stmt)
Definition: SkScopeExit.h:56
#define TRACE_EVENT0_ALWAYS(category_group, name)
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
bool hasPerformedInitialClear() const
Definition: GrAttachment.h:42
void markHasPerformedInitialClear()
Definition: GrAttachment.h:43
Definition: GrCaps.h:57
bool discardStencilValuesAfterRenderPass() const
Definition: GrCaps.h:122
bool performColorClearsAsDraws() const
Definition: GrCaps.h:431
bool performStencilClearsAsDraws() const
Definition: GrCaps.h:438
const GrCaps * caps() const
Definition: GrGpu.h:73
virtual void submit(GrOpsRenderPass *)=0
void setOpArgs(OpArgs *opArgs)
void setOpsRenderPass(GrOpsRenderPass *renderPass)
GrResourceProvider * resourceProvider() const final
bool canUseStencil(const GrCaps &caps) const
GrAttachment * getStencilAttachment(bool useMSAASurface) const
int numTargets() const
Definition: GrRenderTask.h:103
bool attachStencilAttachment(GrRenderTarget *rt, bool useMSAASurface)
virtual GrRenderTargetProxy * asRenderTargetProxy()
GrRenderTarget * peekRenderTarget() const
bool isEmpty() const
Definition: SkRect.h:202

◆ onMakeClosed()

GrRenderTask::ExpectedOutcome skgpu::ganesh::OpsTask::onMakeClosed ( GrRecordingContext rContext,
SkIRect targetUpdateBounds 
)
overrideprotectedvirtual

Implements GrRenderTask.

Definition at line 1057 of file OpsTask.cpp.

1058 {
1059 this->forwardCombine(*rContext->priv().caps());
1060 if (!this->isColorNoOp()) {
1061 GrSurfaceProxy* proxy = this->target(0);
1062 // Use the entire backing store bounds since the GPU doesn't clip automatically to the
1063 // logical dimensions.
1064 SkRect clippedContentBounds = proxy->backingStoreBoundsRect();
1065 // TODO: If we can fix up GLPrograms test to always intersect the target proxy bounds
1066 // then we can simply assert here that the bounds intersect.
1067 if (clippedContentBounds.intersect(fTotalBounds)) {
1068 clippedContentBounds.roundOut(&fClippedContentBounds);
1069 *targetUpdateBounds = GrNativeRect::MakeIRectRelativeTo(
1070 fTargetOrigin,
1071 this->target(0)->backingStoreDimensions().height(),
1072 fClippedContentBounds);
1074 }
1075 }
1077}
const GrCaps * caps() const
GrRecordingContextPriv priv()
SkRect backingStoreBoundsRect() const
int32_t height
static SkIRect MakeIRectRelativeTo(GrSurfaceOrigin origin, int rtHeight, SkIRect devRect)
Definition: GrNativeRect.h:31
bool intersect(const SkRect &r)
Definition: SkRect.cpp:114
void roundOut(SkIRect *dst) const
Definition: SkRect.h:1241

◆ onPrepare()

void skgpu::ganesh::OpsTask::onPrepare ( GrOpFlushState flushState)
overridevirtual

Together these two functions flush all queued up draws to GrCommandBuffer. The return value of onExecute() indicates whether any commands were actually issued to the GPU.

Reimplemented from GrRenderTask.

Definition at line 496 of file OpsTask.cpp.

496 {
497 SkASSERT(this->target(0)->peekRenderTarget());
498 SkASSERT(this->isClosed());
499 // TODO: remove the check for discard here once reduced op splitting is turned on. Currently we
500 // can end up with OpsTasks that only have a discard load op and no ops. For vulkan validation
501 // we need to keep that discard and not drop it. Once we have reduce op list splitting enabled
502 // we shouldn't end up with OpsTasks with only discard.
503 if (this->isColorNoOp() ||
504 (fClippedContentBounds.isEmpty() && fColorLoadOp != GrLoadOp::kDiscard)) {
505 return;
506 }
507 TRACE_EVENT0_ALWAYS("skia.gpu", TRACE_FUNC);
508
509 flushState->setSampledProxyArray(&fSampledProxies);
510 GrSurfaceProxyView dstView(sk_ref_sp(this->target(0)), fTargetOrigin, fTargetSwizzle);
511 // Loop over the ops that haven't yet been prepared.
512 for (const auto& chain : fOpChains) {
513 if (chain.shouldExecute()) {
514 GrOpFlushState::OpArgs opArgs(chain.head(),
515 dstView,
516 fUsesMSAASurface,
517 chain.appliedClip(),
518 chain.dstProxyView(),
519 fRenderPassXferBarriers,
520 fColorLoadOp);
521
522 flushState->setOpArgs(&opArgs);
523
524 // Temporary debugging helper: for debugging prePrepare w/o going through DDLs
525 // Delete once most of the GrOps have an onPrePrepare.
526 // chain.head()->prePrepare(flushState->gpu()->getContext(), &this->target(0),
527 // chain.appliedClip());
528
529 // GrOp::prePrepare may or may not have been called at this point
530 chain.head()->prepare(flushState);
531 flushState->setOpArgs(nullptr);
532 }
533 }
534 flushState->setSampledProxyArray(nullptr);
535}
void setSampledProxyArray(skia_private::TArray< GrSurfaceProxy *, true > *sampledProxies)
bool isClosed() const
Definition: GrRenderTask.h:56

◆ onPrePrepare()

void skgpu::ganesh::OpsTask::onPrePrepare ( GrRecordingContext context)
overridevirtual

Reimplemented from GrRenderTask.

Definition at line 471 of file OpsTask.cpp.

471 {
472 SkASSERT(this->isClosed());
473 // TODO: remove the check for discard here once reduced op splitting is turned on. Currently we
474 // can end up with OpsTasks that only have a discard load op and no ops. For vulkan validation
475 // we need to keep that discard and not drop it. Once we have reduce op list splitting enabled
476 // we shouldn't end up with OpsTasks with only discard.
477 if (this->isColorNoOp() ||
478 (fClippedContentBounds.isEmpty() && fColorLoadOp != GrLoadOp::kDiscard)) {
479 return;
480 }
481 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
482
483 GrSurfaceProxyView dstView(sk_ref_sp(this->target(0)), fTargetOrigin, fTargetSwizzle);
484 for (const auto& chain : fOpChains) {
485 if (chain.shouldExecute()) {
486 chain.head()->prePrepare(context,
487 dstView,
488 chain.appliedClip(),
489 chain.dstProxyView(),
490 fRenderPassXferBarriers,
491 fColorLoadOp);
492 }
493 }
494}
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131

◆ recordOp()

void skgpu::ganesh::OpsTask::recordOp ( GrOp::Owner  op,
bool  usesMSAA,
GrProcessorSet::Analysis  processorAnalysis,
GrAppliedClip clip,
const GrDstProxyView dstProxyView,
const GrCaps caps 
)
protected

Definition at line 955 of file OpsTask.cpp.

957 {
958 GrSurfaceProxy* proxy = this->target(0);
959#ifdef SK_DEBUG
960 op->validate();
961 SkASSERT(processorAnalysis.requiresDstTexture() == (dstProxyView && dstProxyView->proxy()));
962 SkASSERT(proxy);
963 // A closed OpsTask should never receive new/more ops
964 SkASSERT(!this->isClosed());
965 // Ensure we can support dynamic msaa if the caller is trying to trigger it.
966 if (proxy->asRenderTargetProxy()->numSamples() == 1 && usesMSAA) {
968 }
969#endif
970
971 if (!op->bounds().isFinite()) {
972 return;
973 }
974
975 fUsesMSAASurface |= usesMSAA;
976
977 // Account for this op's bounds before we attempt to combine.
978 // NOTE: The caller should have already called "op->setClippedBounds()" by now, if applicable.
979 fTotalBounds.join(op->bounds());
980
981 // Check if there is an op we can combine with by linearly searching back until we either
982 // 1) check every op
983 // 2) intersect with something
984 // 3) find a 'blocker'
985 GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), proxy->uniqueID());
986 GrOP_INFO("opsTask: %d Recording (%s, opID: %u)\n"
987 "\tBounds [L: %.2f, T: %.2f R: %.2f B: %.2f]\n",
988 this->uniqueID(),
989 op->name(),
990 op->uniqueID(),
991 op->bounds().fLeft, op->bounds().fTop,
992 op->bounds().fRight, op->bounds().fBottom);
993 GrOP_INFO(SkTabString(op->dumpInfo(), 1).c_str());
994 GrOP_INFO("\tOutcome:\n");
995 int maxCandidates = std::min(kMaxOpChainDistance, fOpChains.size());
996 if (maxCandidates) {
997 int i = 0;
998 while (true) {
999 OpChain& candidate = fOpChains.fromBack(i);
1000 op = candidate.appendOp(std::move(op), processorAnalysis, dstProxyView, clip, caps,
1001 fArenas->arenaAlloc(), fAuditTrail);
1002 if (!op) {
1003 return;
1004 }
1005 // Stop going backwards if we would cause a painter's order violation.
1006 if (!can_reorder(candidate.bounds(), op->bounds())) {
1007 GrOP_INFO("\t\tBackward: Intersects with chain (%s, head opID: %u)\n",
1008 candidate.head()->name(), candidate.head()->uniqueID());
1009 break;
1010 }
1011 if (++i == maxCandidates) {
1012 GrOP_INFO("\t\tBackward: Reached max lookback or beginning of op array %d\n", i);
1013 break;
1014 }
1015 }
1016 } else {
1017 GrOP_INFO("\t\tBackward: FirstOp\n");
1018 }
1019 if (clip) {
1020 clip = fArenas->arenaAlloc()->make<GrAppliedClip>(std::move(*clip));
1021 SkDEBUGCODE(fNumClips++;)
1022 }
1023 fOpChains.emplace_back(std::move(op), processorAnalysis, clip, dstProxyView);
1024}
#define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, proxy_id)
Definition: GrAuditTrail.h:170
#define GrOP_INFO(...)
Definition: GrOp.h:57
SkString SkTabString(const SkString &string, int tabCnt)
SkArenaAlloc * arenaAlloc()
bool supportsDynamicMSAA(const GrRenderTargetProxy *) const
Definition: GrCaps.cpp:470
bool requiresDstTexture() const
uint32_t uniqueID() const
Definition: GrRenderTask.h:102
UniqueID uniqueID() const
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
Definition: SkArenaAlloc.h:120
const char * c_str() const
Definition: SkString.h:133
T & fromBack(int i)
Definition: SkTArray.h:493
T & emplace_back(Args &&... args)
Definition: SkTArray.h:248
static float min(float r, float g, float b)
Definition: hsl.cpp:48

◆ renderPassXferBarriers()

GrXferBarrierFlags skgpu::ganesh::OpsTask::renderPassXferBarriers ( ) const
inline

Definition at line 52 of file OpsTask.h.

52{ return fRenderPassXferBarriers; }

◆ resetForFullscreenClear()

bool skgpu::ganesh::OpsTask::resetForFullscreenClear ( CanDiscardPreviousOps  canDiscardPreviousOps)

Definition at line 757 of file OpsTask.cpp.

757 {
758 if (CanDiscardPreviousOps::kYes == canDiscardPreviousOps || this->isEmpty()) {
759 this->deleteOps();
761 fSampledProxies.clear();
762
763 // If the opsTask is using a render target which wraps a vulkan command buffer, we can't do
764 // a clear load since we cannot change the render pass that we are using. Thus we fall back
765 // to making a clear op in this case.
766 return !this->target(0)->asRenderTargetProxy()->wrapsVkSecondaryCB();
767 }
768
769 // Could not empty the task, so an op must be added to handle the clear
770 return false;
771}
bool wrapsVkSecondaryCB() const

◆ setColorLoadOp()

void skgpu::ganesh::OpsTask::setColorLoadOp ( GrLoadOp  op,
std::array< float, 4 >  color = {0, 0, 0, 0} 
)

Definition at line 659 of file OpsTask.cpp.

659 {
660 fColorLoadOp = op;
661 fLoadClearColor = color;
662 if (GrLoadOp::kClear == fColorLoadOp) {
663 GrSurfaceProxy* proxy = this->target(0);
664 SkASSERT(proxy);
665 fTotalBounds = proxy->backingStoreBoundsRect();
666 }
667}
DlColor color

◆ setInitialStencilContent()

void skgpu::ganesh::OpsTask::setInitialStencilContent ( StencilContent  initialContent)
inlineprotected

Definition at line 136 of file OpsTask.h.

136 {
137 fInitialStencilContent = initialContent;
138 }

◆ usesMSAASurface()

bool skgpu::ganesh::OpsTask::usesMSAASurface ( ) const
inline

Definition at line 51 of file OpsTask.h.

51{ return fUsesMSAASurface; }

Friends And Related Function Documentation

◆ ::OpsTaskTestingAccess

friend class ::OpsTaskTestingAccess
friend

Definition at line 264 of file OpsTask.h.

◆ skgpu::ganesh::SurfaceDrawContext

friend class skgpu::ganesh::SurfaceDrawContext
friend

Definition at line 270 of file OpsTask.h.


The documentation for this class was generated from the following files: