Implement generic draw-as-clear fallback for color and stencil
This will likely have a perf hit for GL devices that trigger the clear-as-draw fallback since
the fillrectop cannot be as optimized as the direct GLSL shader. However, since the Metal
backend now needs to perform something very similar for scissored clears, I think this
improves code maintainability and is worth it.
Bug: skia:
Change-Id: Id87513784e5892c7ff3dc988115da1d39a46d8e0
Reviewed-on: https://skia-review.googlesource.com/c/182971
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 5e4db11..606fe37 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -458,6 +458,12 @@
// TODO: at the very least, we want the stencil store op to always be discard (at this
// level). In Vulkan, sub-command buffers would still need to load & store the stencil buffer.
+
+ // Make sure load ops are not kClear if the GPU needs to use draws for clears
+ SkASSERT(fColorLoadOp != GrLoadOp::kClear ||
+ !flushState->gpu()->caps()->performColorClearsAsDraws());
+ SkASSERT(fStencilLoadOp != GrLoadOp::kClear ||
+ !flushState->gpu()->caps()->performStencilClearsAsDraws());
GrGpuRTCommandBuffer* commandBuffer = create_command_buffer(
flushState->gpu(),
fTarget.get()->peekRenderTarget(),
@@ -513,13 +519,28 @@
}
}
-void GrRenderTargetOpList::fullClear(GrContext* context, const SkPMColor4f& color) {
+void GrRenderTargetOpList::setStencilLoadOp(GrLoadOp op) {
+ fStencilLoadOp = op;
+}
- // This is conservative. If the opList is marked as needing a stencil buffer then there
- // may be a prior op that writes to the stencil buffer. Although the clear will ignore the
- // stencil buffer, following draw ops may not so we can't get rid of all the preceding ops.
- // Beware! If we ever add any ops that have a side effect beyond modifying the stencil
- // buffer we will need a more elaborate tracking system (skbug.com/7002).
+void GrRenderTargetOpList::setColorLoadOp(GrLoadOp op, const SkPMColor4f& color) {
+ fColorLoadOp = op;
+ fLoadClearColor = color;
+}
+
+bool GrRenderTargetOpList::resetForFullscreenClear() {
+ // Mark the color load op as discard (this may be followed by a clearColorOnLoad call to make
+ // the load op kClear, or it may be followed by an explicit op). In the event of an absClear()
+ // after a regular clear(), we could end up with a clear load op and a real clear op in the list
+ // if the load op were not reset here.
+ fColorLoadOp = GrLoadOp::kDiscard;
+
+ // Regardless of how the clear is implemented (native clear or a fullscreen quad), all prior ops
+ // would be overwritten, so discard them entirely. The one exception is if the opList is marked
+ // as needing a stencil buffer then there may be a prior op that writes to the stencil buffer.
+ // Although the clear will ignore the stencil buffer, following draw ops may not so we can't get
+ // rid of all the preceding ops. Beware! If we ever add any ops that have a side effect beyond
+ // modifying the stencil buffer we will need a more elaborate tracking system (skbug.com/7002).
if (this->isEmpty() || !fTarget.get()->asRenderTargetProxy()->needsStencil()) {
this->deleteOps();
fDeferredProxies.reset();
@@ -527,20 +548,11 @@
// If the opList is using a render target which wraps a vulkan command buffer, we can't do a
// clear load since we cannot change the render pass that we are using. Thus we fall back to
// making a clear op in this case.
- if (!fTarget.get()->asRenderTargetProxy()->wrapsVkSecondaryCB()) {
- fColorLoadOp = GrLoadOp::kClear;
- fLoadClearColor = color;
- return;
- }
+ return !fTarget.get()->asRenderTargetProxy()->wrapsVkSecondaryCB();
}
- std::unique_ptr<GrClearOp> op(GrClearOp::Make(context, GrFixedClip::Disabled(),
- color, fTarget.get()));
- if (!op) {
- return;
- }
-
- this->recordOp(std::move(op), *context->contextPriv().caps());
+ // Could not empty the list, so an op must be added to handle the clear
+ return false;
}
////////////////////////////////////////////////////////////////////////////////