55 const PathRendererChain::Options& optionsForPathRendererChain,
56 bool reduceOpsTaskSplitting)
58 , fOptionsForPathRendererChain(optionsForPathRendererChain)
59 , fPathRendererChain(nullptr)
60 , fSoftwarePathRenderer(nullptr)
61 , fReduceOpsTaskSplitting(reduceOpsTaskSplitting) {
65 this->closeAllTasks();
66 this->removeRenderTasks();
69bool GrDrawingManager::wasAbandoned()
const {
74 for (
int i = fOnFlushCBObjects.
size() - 1; i >= 0; --i) {
75 if (!fOnFlushCBObjects[i]->retainOnFreeGpuResources()) {
82 fPathRendererChain =
nullptr;
83 fSoftwarePathRenderer =
nullptr;
93 if (fFlushing || this->wasAbandoned()) {
94 if (
info.fSubmittedProc) {
95 info.fSubmittedProc(
info.fSubmittedContext,
false);
97 if (
info.fFinishedProc) {
98 info.fFinishedProc(
info.fFinishedContext);
106 if (!proxies.
empty() && !
info.fNumSemaphores && !
info.fFinishedProc &&
109 bool used = std::any_of(fDAG.begin(), fDAG.end(), [&](auto& task) {
110 return task && task->isUsed(proxy);
115 if (
info.fSubmittedProc) {
116 info.fSubmittedProc(
info.fSubmittedContext,
true);
122 auto dContext =
fContext->asDirectContext();
124 dContext->priv().clientMappedBufferManager()->process();
126 GrGpu* gpu = dContext->priv().getGpu();
132 auto resourceProvider = dContext->priv().resourceProvider();
133 auto resourceCache = dContext->priv().getResourceCache();
139 this->closeAllTasks();
140 fActiveOpsTask =
nullptr;
144 if (!fCpuBufferCache) {
148 int maxCachedBuffers =
fContext->priv().caps()->preferClientSideDynamicBuffers() ? 2 : 6;
152 GrOpFlushState flushState(gpu, resourceProvider, &fTokenTracker, fCpuBufferCache);
157 bool preFlushSuccessful =
true;
159 preFlushSuccessful &= onFlushCBObject->preFlush(&onFlushProvider);
162 bool cachePurgeNeeded =
false;
164 if (preFlushSuccessful) {
165 bool usingReorderedDAG =
false;
167 if (fReduceOpsTaskSplitting) {
168 usingReorderedDAG = this->reorderTasks(&resourceAllocator);
169 if (!usingReorderedDAG) {
170 resourceAllocator.reset();
177 for (
const auto& task : fDAG) {
182 if (!resourceAllocator.failedInstantiation()) {
183 if (!usingReorderedDAG) {
184 for (
const auto& task : fDAG) {
186 task->gatherProxyIntervals(&resourceAllocator);
188 resourceAllocator.planAssignment();
190 resourceAllocator.assign();
193 cachePurgeNeeded = !resourceAllocator.failedInstantiation() &&
194 this->executeRenderTasks(&flushState);
196 this->removeRenderTasks();
201 if (cachePurgeNeeded) {
202 resourceCache->purgeAsNeeded();
203 cachePurgeNeeded =
false;
206 onFlushCBObject->postFlush(fTokenTracker.nextFlushToken());
207 cachePurgeNeeded =
true;
209 if (cachePurgeNeeded) {
210 resourceCache->purgeAsNeeded();
217bool GrDrawingManager::submitToGpu(
GrSyncCpu sync) {
218 if (fFlushing || this->wasAbandoned()) {
226 GrGpu* gpu = direct->priv().getGpu();
230bool GrDrawingManager::executeRenderTasks(
GrOpFlushState* flushState) {
231#if GR_FLUSH_TIME_OP_SPEW
233 for (
int i = 0; i < fDAG.
size(); ++i) {
237 fDAG[i]->dump(label, {},
true,
true);
242 bool anyRenderTasksExecuted =
false;
244 for (
const auto& renderTask : fDAG) {
245 if (!renderTask || !renderTask->isInstantiated()) {
249 SkASSERT(renderTask->deferredProxiesAreInstantiated());
251 renderTask->prepare(flushState);
262 static constexpr int kMaxRenderTasksBeforeFlush = 100;
263 int numRenderTasksExecuted = 0;
266 for (
const auto& renderTask : fDAG) {
268 if (!renderTask->isInstantiated()) {
272 if (renderTask->execute(flushState)) {
273 anyRenderTasksExecuted =
true;
275 if (++numRenderTasksExecuted >= kMaxRenderTasksBeforeFlush) {
277 numRenderTasksExecuted = 0;
289 return anyRenderTasksExecuted;
292void GrDrawingManager::removeRenderTasks() {
293 for (
const auto& task : fDAG) {
295 if (!task->unique() || task->requiresExplicitCleanup()) {
299 task->endFlush(
this);
304 fReorderBlockerTaskIndices.clear();
305 fLastRenderTasks.
reset();
308void GrDrawingManager::sortTasks() {
311 end = i == fReorderBlockerTaskIndices.size() ? fDAG.
size() : fReorderBlockerTaskIndices[i];
314 SkASSERT(std::none_of(span.begin(), span.end(), [](
const auto& t) {
315 return t->blocksReordering();
323 SkASSERT(GrRenderTask::TopoSortTraits::WasOutput(task) ||
324 std::find_if(span.begin(), span.end(), [task](
const auto& n) {
325 return n.get() == task; }));
326 for (
int i = 0; i < task->fDependencies.
size(); ++i) {
330 for (
const auto& node : span) {
335 bool sorted = GrTTopoSort<GrRenderTask, GrRenderTask::TopoSortTraits>(span,
start);
341 if (sorted && !span.empty()) {
344 auto prevOpsTask = span[0]->asOpsTask();
345 for (
size_t j = 1; j < span.size(); ++j) {
346 auto curOpsTask = span[j]->asOpsTask();
348 if (prevOpsTask && curOpsTask) {
349 SkASSERT(!prevOpsTask->canMerge(curOpsTask));
352 prevOpsTask = curOpsTask;
367 [[maybe_unused]]
T* old = array->at(i).release();
368 array->at(i++).reset(t);
376 bool clustered =
false;
379 end = i == fReorderBlockerTaskIndices.size() ? fDAG.
size() : fReorderBlockerTaskIndices[i];
381 SkASSERT(std::none_of(span.begin(), span.end(), [](
const auto& t) {
382 return t->blocksReordering();
390 if (i < fReorderBlockerTaskIndices.size()) {
391 SkASSERT(fDAG[fReorderBlockerTaskIndices[i]]->blocksReordering());
392 subllist.
addToTail(fDAG[fReorderBlockerTaskIndices[i]].
get());
394 llist.
concat(std::move(subllist));
409 dContext->priv().getGpu()->stats()->incNumReorderedDAGsOverBudget();
415 for (
int i = 0; i < fDAG.
size(); i++) {
417 if (
auto opsTask = task->asOpsTask()) {
418 size_t remaining = fDAG.
size() - i - 1;
420 int removeCount = opsTask->mergeFrom(nextTasks);
421 for (
const auto& removed : nextTasks.first(removeCount)) {
426 fDAG[newCount++] = std::move(task);
432void GrDrawingManager::closeAllTasks() {
433 for (
auto& task : fDAG) {
435 task->makeClosed(fContext);
447 if (!fReorderBlockerTaskIndices.empty() && fReorderBlockerTaskIndices.back() == fDAG.
size()) {
448 fReorderBlockerTaskIndices.back()++;
451 auto& penultimate = fDAG.
fromBack(1);
453 return penultimate.get();
460 if (task->blocksReordering()) {
461 fReorderBlockerTaskIndices.push_back(fDAG.
size());
477 if (rtProxy->isMSAADirty()) {
478 SkASSERT(rtProxy->peekRenderTarget());
481 rtProxy->markMSAAResolved();
489 if (textureProxy->mipmapsAreDirty()) {
490 SkASSERT(textureProxy->peekTexture());
492 textureProxy->markMipmapsClean();
501 if (this->wasAbandoned()) {
502 if (
info.fSubmittedProc) {
503 info.fSubmittedProc(
info.fSubmittedContext,
false);
505 if (
info.fFinishedProc) {
506 info.fFinishedProc(
info.fFinishedContext);
514 GrGpu* gpu = direct->priv().getGpu();
521 bool didFlush = this->
flush(proxies, access,
info, newState);
528 if (!didFlush || (!direct->priv().caps()->backendSemaphoreSupport() &&
info.fNumSemaphores)) {
535 fOnFlushCBObjects.
push_back(onFlushCBObject);
538#if defined(GR_TEST_UTILS)
540 int n = std::find(fOnFlushCBObjects.
begin(), fOnFlushCBObjects.
end(), cb) -
541 fOnFlushCBObjects.
begin();
550 SkASSERT(prior->isClosed() || prior == task);
555 fLastRenderTasks.
set(
key, task);
556 }
else if (fLastRenderTasks.
find(
key)) {
563 return entry ? *entry :
nullptr;
568 return task ? task->
asOpsTask() :
nullptr;
575 this->closeAllTasks();
576 fActiveOpsTask =
nullptr;
580 fDAG.
swap(ddl->fRenderTasks);
582 fReorderBlockerTaskIndices.clear();
584 for (
auto& renderTask : ddl->fRenderTasks) {
585 renderTask->disown(
this);
586 renderTask->prePrepare(fContext);
600 if (fActiveOpsTask) {
605 fActiveOpsTask->makeClosed(fContext);
606 fActiveOpsTask =
nullptr;
610 if (ddl->priv().targetProxy()->isMSAADirty()) {
612 ddl->characterization().origin(),
613 ddl->priv().targetProxy()->backingStoreDimensions().height(),
614 ddl->priv().targetProxy()->msaaDirtyRect());
615 newDest->markMSAADirty(nativeRect);
618 if (newTextureProxy && skgpu::Mipmapped::kYes == newTextureProxy->
mipmapped()) {
624 ddl->fLazyProxyData->fReplayDest = newDest.
get();
627 SkDEBUGCODE(
auto ddlTask =) this->appendTask(sk_make_sp<GrDDLTask>(
this,
636void GrDrawingManager::validate()
const {
637 if (fActiveOpsTask) {
643 for (
int i = 0; i < fDAG.
size(); ++i) {
644 if (fActiveOpsTask != fDAG[i].
get()) {
647 bool isActiveResolveTask =
648 fActiveOpsTask && fActiveOpsTask->fTextureResolveTask == fDAG[i].get();
650 SkASSERT(isActiveResolveTask || isAtlas || fDAG[i]->isClosed());
657 SkASSERT(fActiveOpsTask ==
nullptr);
660 SkASSERT(fActiveOpsTask ==
nullptr);
665 SkASSERT(fActiveOpsTask ==
nullptr);
670void GrDrawingManager::closeActiveOpsTask() {
671 if (fActiveOpsTask) {
676 fActiveOpsTask->makeClosed(fContext);
677 fActiveOpsTask =
nullptr;
686 this->closeActiveOpsTask();
689 this, std::move(surfaceView), fContext->
priv().
auditTrail(), std::move(arenas)));
693 this->appendTask(opsTask);
695 fActiveOpsTask = opsTask.
get();
706 if (previousAtlasTask) {
707 previousAtlasTask->makeClosed(fContext);
713 atlasTask->addDependency(previousAtlasUser);
714 previousAtlasUser->makeClosed(fContext);
715 if (previousAtlasUser == fActiveOpsTask) {
716 fActiveOpsTask =
nullptr;
722 this->insertTaskBeforeLast(std::move(atlasTask));
738 GrRenderTask* task = this->insertTaskBeforeLast(sk_make_sp<GrTextureResolveRenderTask>());
748 if (!proxy->requiresManualMSAAResolve()) {
754 if (!proxy->asRenderTargetProxy()->isMSAADirty() && (!lastTask || lastTask->
isClosed())) {
759 this->closeActiveOpsTask();
761 auto resolveTask = sk_make_sp<GrTextureResolveRenderTask>();
763 resolveTask->addProxy(
this, std::move(proxy),
flags, caps);
765 auto task = this->appendTask(std::move(resolveTask));
766 task->makeClosed(fContext);
775 std::unique_ptr<std::unique_ptr<GrSemaphore>[]> semaphores,
781 std::move(semaphores),
784 if (fActiveOpsTask && (fActiveOpsTask->
target(0) == proxy.
get())) {
786 this->insertTaskBeforeLast(waitTask);
799 waitTask->addDependenciesFromOtherTask(fActiveOpsTask);
808 waitTask->addDependency(lastTask);
811 this->closeActiveOpsTask();
812 this->appendTask(waitTask);
814 waitTask->makeClosed(fContext);
827 this->closeActiveOpsTask();
829 GrRenderTask* task = this->appendTask(sk_make_sp<GrTransferFromRenderTask>(
830 srcProxy, srcRect, surfaceColorType, dstColorType,
831 std::move(dstBuffer), dstOffset));
839 task->makeClosed(fContext);
854 SkASSERT(srcOffset + size <= src->size());
855 SkASSERT(dstOffset + size <= dst->size());
862 this->closeActiveOpsTask();
871 this->appendTask(task);
872 task->makeClosed(fContext);
885 SkASSERT(dstOffset + src->size() <= dst->size());
892 this->closeActiveOpsTask();
899 this->appendTask(task);
900 task->makeClosed(fContext);
923 if (src->framebufferOnly()) {
927 this->closeActiveOpsTask();
940 this->appendTask(task);
947 task->makeClosed(fContext);
965 this->closeActiveOpsTask();
988 task->makeClosed(fContext);
1008 if (!fPathRendererChain) {
1009 fPathRendererChain =
1010 std::make_unique<PathRendererChain>(fContext, fOptionsForPathRendererChain);
1013 auto pr = fPathRendererChain->getPathRenderer(
args, drawType, stencilSupport);
1014 if (!pr && allowSW) {
1021#if GR_PATH_RENDERER_SPEW
1023 SkDebugf(
"getPathRenderer: %s\n", pr->name());
1031 if (!fSoftwarePathRenderer) {
1036 return fSoftwarePathRenderer.
get();
1040 if (!fPathRendererChain) {
1041 fPathRendererChain = std::make_unique<PathRendererChain>(fContext,
1042 fOptionsForPathRendererChain);
1044 return fPathRendererChain->getAtlasPathRenderer();
1048 if (!fPathRendererChain) {
1049 fPathRendererChain = std::make_unique<PathRendererChain>(fContext,
1050 fOptionsForPathRendererChain);
1052 return fPathRendererChain->getTessellationPathRenderer();
1062 if (resourceCache && resourceCache->requestsFlush()) {
1066 resourceCache->purgeAsNeeded();
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static void resolve_and_mipmap(GrGpu *gpu, GrSurfaceProxy *proxy)
static void reorder_array_by_llist(const SkTInternalLList< T > &llist, TArray< sk_sp< T > > *array)
bool GrClusterRenderTasks(SkSpan< const sk_sp< GrRenderTask > > input, SkTInternalLList< GrRenderTask > *llist)
#define GR_CREATE_TRACE_MARKER_CONTEXT(classname, op, context)
#define check(reporter, ref, unref, make, kill)
#define SkDEBUGFAIL(message)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
constexpr size_t SkToSizeT(S x)
const GrCaps * caps() const
static sk_sp< CpuBufferCache > Make(int maxBuffersToCache)
static sk_sp< GrRenderTask > Make(sk_sp< GrGpuBuffer > src, size_t srcOffset, sk_sp< GrGpuBuffer > dst, size_t dstOffset, size_t size)
static sk_sp< GrRenderTask > Make(sk_sp< SkData > src, sk_sp< GrGpuBuffer > dst, size_t dstOffset)
bool preferVRAMUseOverFlushes() const
virtual GrDirectContext * asDirectContext()
static sk_sp< GrRenderTask > Make(GrDrawingManager *, sk_sp< GrSurfaceProxy > dst, SkIRect dstRect, sk_sp< GrSurfaceProxy > src, SkIRect srcRect, GrSamplerState::Filter filter, GrSurfaceOrigin)
GrResourceCache * getResourceCache()
GrDirectContextPriv priv()
void createDDLTask(sk_sp< const GrDeferredDisplayList >, sk_sp< GrRenderTargetProxy > newDest)
skgpu::ganesh::OpsTask * getLastOpsTask(const GrSurfaceProxy *) const
void addOnFlushCallbackObject(GrOnFlushCallbackObject *)
void newTransferFromRenderTask(const sk_sp< GrSurfaceProxy > &srcProxy, const SkIRect &srcRect, GrColorType surfaceColorType, GrColorType dstColorType, sk_sp< GrGpuBuffer > dstBuffer, size_t dstOffset)
sk_sp< skgpu::ganesh::OpsTask > newOpsTask(GrSurfaceProxyView, sk_sp< GrArenas > arenas)
void newWaitRenderTask(const sk_sp< GrSurfaceProxy > &proxy, std::unique_ptr< std::unique_ptr< GrSemaphore >[]>, int numSemaphores)
void moveRenderTasksToDDL(GrDeferredDisplayList *ddl)
void newBufferUpdateTask(sk_sp< SkData > src, sk_sp< GrGpuBuffer > dst, size_t dstOffset)
GrRenderTask * getLastRenderTask(const GrSurfaceProxy *) const
sk_sp< GrRenderTask > newCopyRenderTask(sk_sp< GrSurfaceProxy > dst, SkIRect dstRect, const sk_sp< GrSurfaceProxy > &src, SkIRect srcRect, GrSamplerState::Filter filter, GrSurfaceOrigin)
GrTextureResolveRenderTask * newTextureResolveRenderTaskBefore(const GrCaps &)
void setLastRenderTask(const GrSurfaceProxy *, GrRenderTask *)
skgpu::ganesh::AtlasPathRenderer * getAtlasPathRenderer()
void newTextureResolveRenderTask(sk_sp< GrSurfaceProxy > proxy, GrSurfaceProxy::ResolveFlags, const GrCaps &)
bool flush(SkSpan< GrSurfaceProxy * > proxies, SkSurfaces::BackendSurfaceAccess access, const GrFlushInfo &, const skgpu::MutableTextureState *newState)
PathRenderer * getTessellationPathRenderer()
void addAtlasTask(sk_sp< GrRenderTask > atlasTask, GrRenderTask *previousAtlasTask)
bool newWritePixelsTask(sk_sp< GrSurfaceProxy > dst, SkIRect rect, GrColorType srcColorType, GrColorType dstColorType, const GrMipLevel[], int levelCount)
PathRenderer * getSoftwarePathRenderer()
void newBufferTransferTask(sk_sp< GrGpuBuffer > src, size_t srcOffset, sk_sp< GrGpuBuffer > dst, size_t dstOffset, size_t size)
GrSemaphoresSubmitted flushSurfaces(SkSpan< GrSurfaceProxy * >, SkSurfaces::BackendSurfaceAccess, const GrFlushInfo &, const skgpu::MutableTextureState *newState)
PathRenderer * getPathRenderer(const PathRenderer::CanDrawPathArgs &, bool allowSW, PathRendererChain::DrawType, PathRenderer::StencilSupport *=nullptr)
bool submitToGpu(GrSyncCpu sync)
bool regenerateMipMapLevels(GrTexture *)
void resolveRenderTarget(GrRenderTarget *, const SkIRect &resolveRect)
void executeFlushInfo(SkSpan< GrSurfaceProxy * >, SkSurfaces::BackendSurfaceAccess access, const GrFlushInfo &, const skgpu::MutableTextureState *newState)
const V * set(K key, V val)
const V * find(const K &key) const
GrOpsRenderPass * opsRenderPass()
GrAuditTrail * auditTrail()
GrProxyProvider * proxyProvider()
GrRecordingContext::OwnedArenas && detachArenas()
void detachProgramData(skia_private::TArray< GrRecordingContext::ProgramData > *dst)
GrRecordingContextPriv priv()
bool abandoned() override
GrSurfaceProxy * target(int i) const
bool isSetFlag(uint32_t flag) const
void addDependency(GrDrawingManager *, GrSurfaceProxy *dependedOn, skgpu::Mipmapped, GrTextureResolveManager, const GrCaps &caps)
bool blocksReordering() const
virtual skgpu::ganesh::OpsTask * asOpsTask()
virtual void disown(GrDrawingManager *)
SkSpan< GrRenderTask * > dependents()
@ kAtlas_Flag
This task is atlas.
virtual void gatherProxyIntervals(GrResourceAllocator *) const =0
bool makeBudgetHeadroom()
virtual GrRenderTargetProxy * asRenderTargetProxy()
bool requiresManualMSAAResolve() const
virtual GrTextureProxy * asTextureProxy()
bool isInstantiated() const
UniqueID uniqueID() const
skgpu::Mipmapped mipmapped() const
static sk_sp< GrRenderTask > Make(GrDrawingManager *, sk_sp< GrSurfaceProxy >, SkIRect, GrColorType srcColorType, GrColorType dstColorType, const GrMipLevel[], int levelCount)
constexpr T * begin() const
constexpr T * end() const
constexpr bool empty() const
void printf(const char format[],...) SK_PRINTF_LIKE(2
void concat(SkTInternalLList &&list)
void swap(sk_sp< T > &that)
void reset(T *ptr=nullptr)
AtlasToken nextFlushToken() const
AtlasToken nextDrawToken() const
void resize_back(int newCount)
void removeShuffle(int n)
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
@ kNoAccess
back-end surface will not be used by client
const myers::Point & get(const myers::Segment &)
static SkIRect MakeIRectRelativeTo(GrSurfaceOrigin origin, int rtHeight, SkIRect devRect)
bool fAllowPathMaskCaching