Reorder msaa and mipmap resolves to happen all at once
Makes it so every renderTask has only one textureResolveTask, and
modifies GrTextureResolveTask to perform multiple resolves
back-to-back.
Bug: skia:9406
Change-Id: I93566cf4b23764bd846a1e0a0848642c9b3a507a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/241936
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrTextureResolveRenderTask.cpp b/src/gpu/GrTextureResolveRenderTask.cpp
index 0b77383..d97e5d5 100644
--- a/src/gpu/GrTextureResolveRenderTask.cpp
+++ b/src/gpu/GrTextureResolveRenderTask.cpp
@@ -14,58 +14,83 @@
#include "src/gpu/GrResourceAllocator.h"
#include "src/gpu/GrTexturePriv.h"
-void GrTextureResolveRenderTask::init(const GrCaps& caps) {
- if (GrSurfaceProxy::ResolveFlags::kMSAA & fResolveFlags) {
- GrRenderTargetProxy* renderTargetProxy = fTarget->asRenderTargetProxy();
+GrTextureResolveRenderTask::~GrTextureResolveRenderTask() {
+ for (const auto& resolve : fResolves) {
+ // Ensure the proxy doesn't keep hold of a dangling back pointer.
+ resolve.fProxy->setLastRenderTask(nullptr);
+ }
+}
+
+void GrTextureResolveRenderTask::addProxy(
+ sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
+ // Ensure the last render task that operated on the proxy is closed. That's where msaa and
+ // mipmaps should have been marked dirty.
+ SkASSERT(!proxy->getLastRenderTask() || proxy->getLastRenderTask()->isClosed());
+ SkASSERT(GrSurfaceProxy::ResolveFlags::kNone != flags);
+
+ if (GrSurfaceProxy::ResolveFlags::kMSAA & flags) {
+ GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
SkASSERT(renderTargetProxy);
SkASSERT(renderTargetProxy->isMSAADirty());
renderTargetProxy->markMSAAResolved();
}
- if (GrSurfaceProxy::ResolveFlags::kMipMaps & fResolveFlags) {
- GrTextureProxy* textureProxy = fTarget->asTextureProxy();
+ if (GrSurfaceProxy::ResolveFlags::kMipMaps & flags) {
+ GrTextureProxy* textureProxy = proxy->asTextureProxy();
SkASSERT(GrMipMapped::kYes == textureProxy->mipMapped());
SkASSERT(textureProxy->mipMapsAreDirty());
textureProxy->markMipMapsClean();
}
- // Add the target as a dependency: We will read the existing contents of this texture while
+ // Add the proxy as a dependency: We will read the existing contents of this texture while
// generating mipmap levels and/or resolving MSAA.
- //
- // NOTE: This must be called before makeClosed.
- this->addDependency(fTarget.get(), GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
- fTarget->setLastRenderTask(this);
+ this->addDependency(proxy.get(), GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
+ proxy->setLastRenderTask(this);
- // We only resolve the texture; nobody should try to do anything else with this opsTask.
- this->makeClosed(caps);
+ fResolves.emplace_back(std::move(proxy), flags);
}
void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
- // This renderTask doesn't have "normal" ops. In this case we still need to add an interval (so
- // fEndOfOpsTaskOpIndices will remain in sync), so we create a fake op# to capture the fact that
- // we manipulate fTarget.
- alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp(),
- GrResourceAllocator::ActualUse::kYes);
+ // This renderTask doesn't have "normal" ops, however we still need to add intervals so
+ // fEndOfOpsTaskOpIndices will remain in sync. We create fake op#'s to capture the fact that we
+ // manipulate the resolve proxies.
+ auto fakeOp = alloc->curOp();
+ for (const auto& resolve : fResolves) {
+ alloc->addInterval(resolve.fProxy.get(), fakeOp, fakeOp,
+ GrResourceAllocator::ActualUse::kYes);
+ }
alloc->incOps();
}
bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
- // Resolve msaa before regenerating mipmaps.
- if (GrSurfaceProxy::ResolveFlags::kMSAA & fResolveFlags) {
- GrRenderTarget* renderTarget = fTarget->peekRenderTarget();
- SkASSERT(renderTarget);
- if (renderTarget->needsResolve()) {
- flushState->gpu()->resolveRenderTarget(renderTarget);
+ // Resolve all msaa back-to-back, before regenerating mipmaps.
+ for (const auto& resolve : fResolves) {
+ if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
+ GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget();
+ SkASSERT(renderTarget);
+ if (renderTarget->needsResolve()) {
+ flushState->gpu()->resolveRenderTarget(renderTarget);
+ }
}
}
-
- if (GrSurfaceProxy::ResolveFlags::kMipMaps & fResolveFlags) {
- GrTexture* texture = fTarget->peekTexture();
- SkASSERT(texture);
- if (texture->texturePriv().mipMapsAreDirty()) {
- flushState->gpu()->regenerateMipMapLevels(texture);
+ // Regenerate all mipmaps back-to-back.
+ for (const auto& resolve : fResolves) {
+ if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
+ GrTexture* texture = resolve.fProxy->peekTexture();
+ SkASSERT(texture);
+ if (texture->texturePriv().mipMapsAreDirty()) {
+ flushState->gpu()->regenerateMipMapLevels(texture);
+ }
}
}
return true;
}
+
+#ifdef SK_DEBUG
+void GrTextureResolveRenderTask::visitProxies_debugOnly(const VisitSurfaceProxyFunc& fn) const {
+ for (const auto& resolve : fResolves) {
+ fn(resolve.fProxy.get(), GrMipMapped::kNo);
+ }
+}
+#endif