Fall back to unordered DAG if we go over budget

This case is exceedingly rare, but we need to handle it anyway.

Bug: skia:10877
Change-Id: I6ba219487e4616ff24f2c087b3fcac957d2523f7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/396816
Commit-Queue: Adlai Holler <adlai@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
Auto-Submit: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Adlai Holler 2021-04-15 15:03:27 -04:00 committed by Skia Commit-Bot
parent f35853a4a2
commit 387309c8bb
2 changed files with 38 additions and 21 deletions

View File

@ -139,8 +139,13 @@ bool GrDrawingManager::flush(
this->sortTasks(); this->sortTasks();
bool usingReorderedDAG = false;
GrResourceAllocator resourceAllocator(dContext);
if (fReduceOpsTaskSplitting) { if (fReduceOpsTaskSplitting) {
this->reorderTasks(); usingReorderedDAG = this->reorderTasks(&resourceAllocator);
if (!usingReorderedDAG) {
resourceAllocator.reset();
}
} }
if (!fCpuBufferCache) { if (!fCpuBufferCache) {
@ -202,25 +207,18 @@ bool GrDrawingManager::flush(
} }
#endif #endif
bool flushed = false; if (!resourceAllocator.failedInstantiation()) {
if (!usingReorderedDAG) {
{
GrResourceAllocator alloc(dContext);
for (const auto& task : fDAG) { for (const auto& task : fDAG) {
SkASSERT(task); SkASSERT(task);
task->gatherProxyIntervals(&alloc); task->gatherProxyIntervals(&resourceAllocator);
} }
resourceAllocator.planAssignment();
if (alloc.planAssignment()) {
if (fReduceOpsTaskSplitting) {
if (!alloc.makeBudgetHeadroom()) {
// TODO: Switch to the original DAG in this case.
gpu->stats()->incNumReorderedDAGsOverBudget();
}
}
flushed = alloc.assign() && this->executeRenderTasks(&flushState);
} }
resourceAllocator.assign();
} }
bool flushed = !resourceAllocator.failedInstantiation() &&
this->executeRenderTasks(&flushState);
this->removeRenderTasks(); this->removeRenderTasks();
gpu->executeFlushInfo(proxies, access, info, newState); gpu->executeFlushInfo(proxies, access, info, newState);
@ -390,12 +388,25 @@ static void reorder_array_by_llist(const SkTInternalLList<T>& llist, SkTArray<sk
SkASSERT(i == array->count()); SkASSERT(i == array->count());
} }
void GrDrawingManager::reorderTasks() { bool GrDrawingManager::reorderTasks(GrResourceAllocator* resourceAllocator) {
SkASSERT(fReduceOpsTaskSplitting); SkASSERT(fReduceOpsTaskSplitting);
SkTInternalLList<GrRenderTask> llist; SkTInternalLList<GrRenderTask> llist;
bool clustered = GrClusterRenderTasks(fDAG, &llist); bool clustered = GrClusterRenderTasks(fDAG, &llist);
if (!clustered) { if (!clustered) {
return; return false;
}
for (GrRenderTask* task : llist) {
task->gatherProxyIntervals(resourceAllocator);
}
if (!resourceAllocator->planAssignment()) {
return false;
}
if (!resourceAllocator->makeBudgetHeadroom()) {
auto dContext = fContext->asDirectContext();
SkASSERT(dContext);
dContext->priv().getGpu()->stats()->incNumReorderedDAGsOverBudget();
return false;
} }
// TODO: Handle case where proposed order would blow our memory budget. // TODO: Handle case where proposed order would blow our memory budget.
// Such cases are currently pathological, so we could just return here and keep current order. // Such cases are currently pathological, so we could just return here and keep current order.
@ -416,6 +427,7 @@ void GrDrawingManager::reorderTasks() {
fDAG[newCount++] = std::move(task); fDAG[newCount++] = std::move(task);
} }
fDAG.resize_back(newCount); fDAG.resize_back(newCount);
return true;
} }
void GrDrawingManager::closeAllTasks() { void GrDrawingManager::closeAllTasks() {

View File

@ -30,12 +30,13 @@ class GrOnFlushCallbackObject;
class GrOpFlushState; class GrOpFlushState;
class GrOpsTask; class GrOpsTask;
class GrRecordingContext; class GrRecordingContext;
class GrSurfaceDrawContext;
class GrRenderTargetProxy; class GrRenderTargetProxy;
class GrRenderTask; class GrRenderTask;
class GrResourceAllocator;
class GrSemaphore; class GrSemaphore;
class GrSoftwarePathRenderer; class GrSoftwarePathRenderer;
class GrSurfaceContext; class GrSurfaceContext;
class GrSurfaceDrawContext;
class GrSurfaceProxyView; class GrSurfaceProxyView;
class GrTextureResolveRenderTask; class GrTextureResolveRenderTask;
class SkDeferredDisplayList; class SkDeferredDisplayList;
@ -158,7 +159,11 @@ private:
void removeRenderTasks(); void removeRenderTasks();
void sortTasks(); void sortTasks();
void reorderTasks();
// Attempt to reorder tasks to reduce render passes, and check the memory budget of the
// resulting intervals. Returns whether the reordering was successful & the memory budget
// acceptable. If it returns true, fDAG has been updated to reflect the reordered tasks.
bool reorderTasks(GrResourceAllocator*);
void closeAllTasks(); void closeAllTasks();