Handle merging ops tasks with color clears better
This fixes the reduceOpsTaskSplitting bot.
Bug: skia:10877
Change-Id: Ief0343f5ce62121edd8f87aa57c68b74b736bd80
Docs-Preview: https://skia.org/?cl=363941
Cq-Include-Trybots: luci.skia.skia.primary:Test-Debian10-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Debug-All-ASAN_ReduceOpsTaskSplitting_Vulkan
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/363941
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Adlai Holler <adlai@google.com>
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index d9f5749..8eb03cc 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -673,10 +673,18 @@
}
}
+void GrOpsTask::reset() {
+ fSampledProxies.reset();
+ fClipAllocators.reset();
+ fClippedContentBounds = SkIRect::MakeEmpty();
+ fTotalBounds = SkRect::MakeEmpty();
+ fOpChains.reset();
+ fRenderPassXferBarriers = GrXferBarrierFlags::kNone;
+}
+
int GrOpsTask::mergeFrom(SkSpan<const sk_sp<GrRenderTask>> tasks) {
- GrOpsTask* last = this;
- int addlProxyCount = 0;
- int addlOpChainCount = 0;
+ // Find the index of the last color-clearing task. -1 indicates this or "there are none."
+ int indexOfLastColorClear = -1;
int mergedCount = 0;
for (const sk_sp<GrRenderTask>& task : tasks) {
auto opsTask = task->asOpsTask();
@@ -685,24 +693,51 @@
}
SkASSERT(fTargetSwizzle == opsTask->fTargetSwizzle);
SkASSERT(fTargetOrigin == opsTask->fTargetOrigin);
+ if (GrLoadOp::kClear == opsTask->fColorLoadOp) {
+ indexOfLastColorClear = &task - tasks.begin();
+ }
mergedCount += 1;
+ }
+ if (0 == mergedCount) {
+ return 0;
+ }
+
+ SkSpan<const sk_sp<GrOpsTask>> opsTasks(reinterpret_cast<const sk_sp<GrOpsTask>*>(tasks.data()),
+ SkToSizeT(mergedCount));
+ if (indexOfLastColorClear >= 0) {
+ // If any dropped task needs to preserve stencil, for now just bail on the merge.
+ // Could keep the merge and insert a clear op, but might be tricky due to closed task.
+ if (fMustPreserveStencil) {
+ return 0;
+ }
+ for (const auto& opsTask : opsTasks.first(indexOfLastColorClear)) {
+ if (opsTask->fMustPreserveStencil) {
+ return 0;
+ }
+ }
+ // Clear `this` and forget about the tasks pre-color-clear.
+ this->reset();
+ opsTasks = opsTasks.last(opsTasks.count() - indexOfLastColorClear);
+ // Copy the color-clear into `this`.
+ fColorLoadOp = GrLoadOp::kClear;
+ fLoadClearColor = opsTasks.front()->fLoadClearColor;
+ }
+ int addlProxyCount = 0;
+ int addlOpChainCount = 0;
+ for (const auto& opsTask : opsTasks) {
addlProxyCount += opsTask->fSampledProxies.count();
addlOpChainCount += opsTask->fOpChains.count();
fClippedContentBounds.join(opsTask->fClippedContentBounds);
fTotalBounds.join(opsTask->fTotalBounds);
fRenderPassXferBarriers |= opsTask->fRenderPassXferBarriers;
SkDEBUGCODE(fNumClips += opsTask->fNumClips);
- last = opsTask;
}
- if (last == this) {
- return 0;
- }
+
fLastClipStackGenID = SK_InvalidUniqueID;
fSampledProxies.reserve_back(addlProxyCount);
fOpChains.reserve_back(addlOpChainCount);
- fClipAllocators.reserve_back(mergedCount);
- for (const sk_sp<GrRenderTask>& task : tasks.first(mergedCount)) {
- auto opsTask = reinterpret_cast<GrOpsTask*>(task.get());
+ fClipAllocators.reserve_back(opsTasks.count());
+ for (const auto& opsTask : opsTasks) {
fSampledProxies.move_back_n(opsTask->fSampledProxies.count(),
opsTask->fSampledProxies.data());
fOpChains.move_back_n(opsTask->fOpChains.count(),
@@ -713,7 +748,7 @@
opsTask->fSampledProxies.reset();
opsTask->fOpChains.reset();
}
- fMustPreserveStencil = last->fMustPreserveStencil;
+ fMustPreserveStencil = opsTasks.back()->fMustPreserveStencil;
return mergedCount;
}