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();
bool usingReorderedDAG = false;
GrResourceAllocator resourceAllocator(dContext);
if (fReduceOpsTaskSplitting) {
this->reorderTasks();
usingReorderedDAG = this->reorderTasks(&resourceAllocator);
if (!usingReorderedDAG) {
resourceAllocator.reset();
}
}
if (!fCpuBufferCache) {
@ -202,25 +207,18 @@ bool GrDrawingManager::flush(
}
#endif
bool flushed = false;
{
GrResourceAllocator alloc(dContext);
for (const auto& task : fDAG) {
SkASSERT(task);
task->gatherProxyIntervals(&alloc);
}
if (alloc.planAssignment()) {
if (fReduceOpsTaskSplitting) {
if (!alloc.makeBudgetHeadroom()) {
// TODO: Switch to the original DAG in this case.
gpu->stats()->incNumReorderedDAGsOverBudget();
}
if (!resourceAllocator.failedInstantiation()) {
if (!usingReorderedDAG) {
for (const auto& task : fDAG) {
SkASSERT(task);
task->gatherProxyIntervals(&resourceAllocator);
}
flushed = alloc.assign() && this->executeRenderTasks(&flushState);
resourceAllocator.planAssignment();
}
resourceAllocator.assign();
}
bool flushed = !resourceAllocator.failedInstantiation() &&
this->executeRenderTasks(&flushState);
this->removeRenderTasks();
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());
}
void GrDrawingManager::reorderTasks() {
bool GrDrawingManager::reorderTasks(GrResourceAllocator* resourceAllocator) {
SkASSERT(fReduceOpsTaskSplitting);
SkTInternalLList<GrRenderTask> llist;
bool clustered = GrClusterRenderTasks(fDAG, &llist);
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.
// 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.resize_back(newCount);
return true;
}
void GrDrawingManager::closeAllTasks() {

View File

@ -30,12 +30,13 @@ class GrOnFlushCallbackObject;
class GrOpFlushState;
class GrOpsTask;
class GrRecordingContext;
class GrSurfaceDrawContext;
class GrRenderTargetProxy;
class GrRenderTask;
class GrResourceAllocator;
class GrSemaphore;
class GrSoftwarePathRenderer;
class GrSurfaceContext;
class GrSurfaceDrawContext;
class GrSurfaceProxyView;
class GrTextureResolveRenderTask;
class SkDeferredDisplayList;
@ -158,7 +159,11 @@ private:
void removeRenderTasks();
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();