Move the msaa dirty rect to GrRenderTargetProxy
Bug: skia:
Change-Id: I01d7932bce23dffafb86e4eb124c27420acefdd3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/239192
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrCopyRenderTask.h b/src/gpu/GrCopyRenderTask.h
index 13f502a..8093e69 100644
--- a/src/gpu/GrCopyRenderTask.h
+++ b/src/gpu/GrCopyRenderTask.h
@@ -32,7 +32,9 @@
// If instantiation failed, at flush time we simply will skip doing the copy.
void handleInternalAllocationFailure() override {}
void gatherProxyIntervals(GrResourceAllocator*) const override;
- ExpectedOutcome onMakeClosed(const GrCaps&) override {
+ ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) override {
+ targetUpdateBounds->setXYWH(fDstPoint.x(), fDstPoint.y(), fSrcRect.width(),
+ fSrcRect.height());
return ExpectedOutcome::kTargetDirty;
}
bool onExecute(GrOpFlushState*) override;
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 8a24682..07d2066 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -531,7 +531,8 @@
SkASSERT(rtProxy);
if (rtProxy->isMSAADirty()) {
SkASSERT(rtProxy->peekRenderTarget());
- gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), GrGpu::ForExternalIO::kYes);
+ gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), rtProxy->msaaDirtyRect(),
+ rtProxy->origin(), GrGpu::ForExternalIO::kYes);
rtProxy->markMSAAResolved();
}
}
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index c7e004d..cb80efa 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -19,6 +19,7 @@
#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrMesh.h"
+#include "src/gpu/GrNativeRect.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrRenderTargetPriv.h"
@@ -580,8 +581,14 @@
SkASSERT(texture);
SkASSERT(this->caps()->mipMapSupport());
SkASSERT(texture->texturePriv().mipMapped() == GrMipMapped::kYes);
- SkASSERT(texture->texturePriv().mipMapsAreDirty());
SkASSERT(!texture->asRenderTarget() || !texture->asRenderTarget()->needsResolve());
+ if (!texture->texturePriv().mipMapsAreDirty()) {
+ // This can happen when the proxy expects mipmaps to be dirty, but they are not dirty on the
+ // actual target. This may be caused by things that the drawingManager could not predict,
+ // i.e., ops that don't draw anything, aborting a draw for exceptional circumstances, etc.
+ // NOTE: This goes away once we quit tracking mipmap state on the actual texture.
+ return true;
+ }
if (texture->readOnly()) {
return false;
}
@@ -597,10 +604,24 @@
this->onResetTextureBindings();
}
-void GrGpu::resolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) {
+void GrGpu::resolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
+ GrSurfaceOrigin origin, ForExternalIO forExternalIO) {
SkASSERT(target);
+ if (!target->needsResolve()) {
+ // This can happen when the proxy expects MSAA to be dirty, but it is not dirty on the
+ // actual target. This may be caused by things that the drawingManager could not predict,
+ // i.e., ops that don't draw anything, aborting a draw for exceptional circumstances, etc.
+ // NOTE: This goes away once we quit tracking dirty state on the actual render target.
+ return;
+ }
+#ifdef SK_DEBUG
+ auto nativeResolveRect = GrNativeRect::MakeRelativeTo(origin, target->height(), resolveRect);
+ // The proxy will often track a tighter resolve rect than GrRenderTarget, but it should never be
+ // the other way around.
+ SkASSERT(target->getResolveRect().contains(nativeResolveRect.asSkIRect()));
+#endif
this->handleDirtyContext();
- this->onResolveRenderTarget(target, forExternalIO);
+ this->onResolveRenderTarget(target, resolveRect, origin, forExternalIO);
}
void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 625a10a..19a8f9a 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -189,7 +189,8 @@
/**
* Resolves MSAA.
*/
- void resolveRenderTarget(GrRenderTarget*, ForExternalIO);
+ void resolveRenderTarget(GrRenderTarget*, const SkIRect& resolveRect, GrSurfaceOrigin,
+ ForExternalIO);
/**
* Uses the base of the texture to recompute the contents of the other levels.
@@ -634,7 +635,8 @@
GrGpuBuffer* transferBuffer, size_t offset) = 0;
// overridden by backend-specific derived class to perform the resolve
- virtual void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) = 0;
+ virtual void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
+ GrSurfaceOrigin resolveOrigin, ForExternalIO) = 0;
// overridden by backend specific derived class to perform mip map level regeneration.
virtual bool onRegenerateMipMapLevels(GrTexture*) = 0;
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index cab3e8e..b621dd4 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -504,6 +504,9 @@
void GrOpsTask::setColorLoadOp(GrLoadOp op, const SkPMColor4f& color) {
fColorLoadOp = op;
fLoadClearColor = color;
+ if (GrLoadOp::kClear == fColorLoadOp) {
+ fTotalBounds.setWH(fTarget->width(), fTarget->height());
+ }
}
bool GrOpsTask::resetForFullscreenClear(CanDiscardPreviousOps canDiscardPreviousOps) {
@@ -534,6 +537,7 @@
if (this->isEmpty()) {
fColorLoadOp = GrLoadOp::kDiscard;
fStencilLoadOp = GrLoadOp::kDiscard;
+ fTotalBounds.setEmpty();
}
}
@@ -671,6 +675,10 @@
return;
}
+ // Account for this op's bounds before we attempt to combine.
+ // NOTE: The caller should have already called "op->setClippedBounds()" by now, if applicable.
+ fTotalBounds.join(op->bounds());
+
// Check if there is an op we can combine with by linearly searching back until we either
// 1) check every op
// 2) intersect with something
@@ -747,3 +755,15 @@
}
}
+GrRenderTask::ExpectedOutcome GrOpsTask::onMakeClosed(
+ const GrCaps& caps, SkIRect* targetUpdateBounds) {
+ this->forwardCombine(caps);
+ if (!this->isNoOp()) {
+ SkRect clippedContentBounds = SkRect::MakeIWH(fTarget->width(), fTarget->height());
+ if (clippedContentBounds.intersect(fTotalBounds)) {
+ clippedContentBounds.roundOut(targetUpdateBounds);
+ return ExpectedOutcome::kTargetDirty;
+ }
+ }
+ return ExpectedOutcome::kTargetUnchanged;
+}
diff --git a/src/gpu/GrOpsTask.h b/src/gpu/GrOpsTask.h
index e2f2682..0539eab 100644
--- a/src/gpu/GrOpsTask.h
+++ b/src/gpu/GrOpsTask.h
@@ -229,10 +229,7 @@
void forwardCombine(const GrCaps&);
- ExpectedOutcome onMakeClosed(const GrCaps& caps) override {
- this->forwardCombine(caps);
- return (this->isNoOp()) ? ExpectedOutcome::kTargetUnchanged : ExpectedOutcome::kTargetDirty;
- }
+ ExpectedOutcome onMakeClosed(const GrCaps& caps, SkIRect* targetUpdateBounds) override;
friend class GrRenderTargetContextPriv; // for stencil clip state. TODO: this is invasive
@@ -270,6 +267,8 @@
// TODO: We could look into this being a set if we find we're adding a lot of duplicates that is
// causing slow downs.
SkTArray<GrTextureProxy*, true> fSampledProxies;
+
+ SkRect fTotalBounds = SkRect::MakeEmpty();
};
#endif
diff --git a/src/gpu/GrRenderTargetProxy.h b/src/gpu/GrRenderTargetProxy.h
index 50ebcd7e..f0b8d27 100644
--- a/src/gpu/GrRenderTargetProxy.h
+++ b/src/gpu/GrRenderTargetProxy.h
@@ -63,17 +63,22 @@
bool wrapsVkSecondaryCB() const { return fWrapsVkSecondaryCB == WrapsVkSecondaryCB::kYes; }
- void markMSAADirty() {
+ void markMSAADirty(const SkIRect& dirtyRect) {
+ SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(dirtyRect));
SkASSERT(this->requiresManualMSAAResolve());
- fIsMSAADirty = true;
+ fMSAADirtyRect.join(dirtyRect);
}
void markMSAAResolved() {
SkASSERT(this->requiresManualMSAAResolve());
- fIsMSAADirty = false;
+ fMSAADirtyRect.setEmpty();
}
bool isMSAADirty() const {
- SkASSERT(!fIsMSAADirty || this->requiresManualMSAAResolve());
- return fIsMSAADirty;
+ SkASSERT(fMSAADirtyRect.isEmpty() || this->requiresManualMSAAResolve());
+ return this->requiresManualMSAAResolve() && !fMSAADirtyRect.isEmpty();
+ }
+ const SkIRect& msaaDirtyRect() const {
+ SkASSERT(this->requiresManualMSAAResolve());
+ return fMSAADirtyRect;
}
// TODO: move this to a priv class!
@@ -160,10 +165,7 @@
int8_t fNumStencilSamples = 0;
WrapsVkSecondaryCB fWrapsVkSecondaryCB;
GrSwizzle fOutputSwizzle;
- // Indicates whether some sub-rectangle of the render target requires MSAA resolve. We currently
- // rely on the GrRenderTarget itself to track the actual dirty rect.
- // TODO: In the future, convert the flag to a dirty rect and quit tracking it in GrRenderTarget.
- bool fIsMSAADirty = false;
+ SkIRect fMSAADirtyRect = SkIRect::MakeEmpty();
// This is to fix issue in large comment above. Without the padding we end 6 bytes into a 16
// byte range, so the GrTextureProxy ends up starting 8 byte aligned by not 16. We add the
// padding here to get us right up to the 16 byte alignment (technically any padding of 3-10
diff --git a/src/gpu/GrRenderTask.cpp b/src/gpu/GrRenderTask.cpp
index db7cd4f..a69c48b 100644
--- a/src/gpu/GrRenderTask.cpp
+++ b/src/gpu/GrRenderTask.cpp
@@ -51,10 +51,12 @@
return;
}
- if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps)) {
+ SkIRect targetUpdateBounds;
+ if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps, &targetUpdateBounds)) {
+ SkASSERT(SkIRect::MakeWH(fTarget->width(), fTarget->height()).contains(targetUpdateBounds));
if (fTarget->requiresManualMSAAResolve()) {
SkASSERT(fTarget->asRenderTargetProxy());
- fTarget->asRenderTargetProxy()->markMSAADirty();
+ fTarget->asRenderTargetProxy()->markMSAADirty(targetUpdateBounds);
}
GrTextureProxy* textureProxy = fTarget->asTextureProxy();
if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) {
diff --git a/src/gpu/GrRenderTask.h b/src/gpu/GrRenderTask.h
index 0cb006f..801713c 100644
--- a/src/gpu/GrRenderTask.h
+++ b/src/gpu/GrRenderTask.h
@@ -96,7 +96,12 @@
kTargetDirty,
};
- virtual ExpectedOutcome onMakeClosed(const GrCaps&) = 0;
+ // Performs any work to finalize this renderTask prior to execution. If returning
+ // ExpectedOutcome::kTargetDiry, the caller is also responsible to fill out the area it will
+ // modify in targetUpdateBounds.
+ //
+ // targetUpdateBounds must not extend beyond the proxy bounds.
+ virtual ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) = 0;
sk_sp<GrSurfaceProxy> fTarget;
diff --git a/src/gpu/GrSurfaceProxy.h b/src/gpu/GrSurfaceProxy.h
index ad29e0a..d2c6a98 100644
--- a/src/gpu/GrSurfaceProxy.h
+++ b/src/gpu/GrSurfaceProxy.h
@@ -392,12 +392,12 @@
private:
// For wrapped resources, 'fFormat', 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always
// be filled in from the wrapped resource.
- GrBackendFormat fFormat;
- GrPixelConfig fConfig;
+ const GrBackendFormat fFormat;
+ const GrPixelConfig fConfig;
int fWidth;
int fHeight;
- GrSurfaceOrigin fOrigin;
- GrSwizzle fTextureSwizzle;
+ const GrSurfaceOrigin fOrigin;
+ const GrSwizzle fTextureSwizzle;
SkBackingFit fFit; // always kApprox for lazy-callback resources
// always kExact for wrapped resources
diff --git a/src/gpu/GrTextureResolveRenderTask.cpp b/src/gpu/GrTextureResolveRenderTask.cpp
index 39eb68f..92e505e 100644
--- a/src/gpu/GrTextureResolveRenderTask.cpp
+++ b/src/gpu/GrTextureResolveRenderTask.cpp
@@ -22,7 +22,10 @@
}
void GrTextureResolveRenderTask::addProxy(
- sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
+ sk_sp<GrSurfaceProxy> proxyHolder, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
+ fResolves.emplace_back(std::move(proxyHolder), flags);
+ GrSurfaceProxy* proxy = fResolves.back().fProxy.get();
+
// 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());
@@ -32,6 +35,7 @@
GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
SkASSERT(renderTargetProxy);
SkASSERT(renderTargetProxy->isMSAADirty());
+ fResolves.back().fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
renderTargetProxy->markMSAAResolved();
}
@@ -44,10 +48,8 @@
// Add the proxy as a dependency: We will read the existing contents of this texture while
// generating mipmap levels and/or resolving MSAA.
- this->addDependency(proxy.get(), GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
+ this->addDependency(proxy, GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
proxy->setLastRenderTask(this);
-
- fResolves.emplace_back(std::move(proxy), flags);
}
void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
@@ -69,7 +71,10 @@
// peekRenderTarget might be null if there was an instantiation error.
GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget();
if (renderTarget && renderTarget->needsResolve()) {
- flushState->gpu()->resolveRenderTarget(renderTarget, GrGpu::ForExternalIO::kNo);
+ flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect,
+ resolve.fProxy->origin(),
+ GrGpu::ForExternalIO::kNo);
+ SkASSERT(!renderTarget->needsResolve());
}
}
}
@@ -80,6 +85,7 @@
GrTexture* texture = resolve.fProxy->peekTexture();
if (texture && texture->texturePriv().mipMapsAreDirty()) {
flushState->gpu()->regenerateMipMapLevels(texture);
+ SkASSERT(!texture->texturePriv().mipMapsAreDirty());
}
}
}
diff --git a/src/gpu/GrTextureResolveRenderTask.h b/src/gpu/GrTextureResolveRenderTask.h
index 0a511c6..913f250 100644
--- a/src/gpu/GrTextureResolveRenderTask.h
+++ b/src/gpu/GrTextureResolveRenderTask.h
@@ -28,7 +28,7 @@
}
void gatherProxyIntervals(GrResourceAllocator*) const override;
- ExpectedOutcome onMakeClosed(const GrCaps&) override {
+ ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
return ExpectedOutcome::kTargetUnchanged;
}
@@ -43,6 +43,7 @@
: fProxy(std::move(proxy)), fFlags(flags) {}
sk_sp<GrSurfaceProxy> fProxy;
GrSurfaceProxy::ResolveFlags fFlags;
+ SkIRect fMSAAResolveRect;
};
SkSTArray<4, Resolve> fResolves;
diff --git a/src/gpu/GrTransferFromRenderTask.h b/src/gpu/GrTransferFromRenderTask.h
index 421206e..08437c7 100644
--- a/src/gpu/GrTransferFromRenderTask.h
+++ b/src/gpu/GrTransferFromRenderTask.h
@@ -36,7 +36,7 @@
void handleInternalAllocationFailure() override {}
void gatherProxyIntervals(GrResourceAllocator*) const override;
- ExpectedOutcome onMakeClosed(const GrCaps&) override {
+ ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
return ExpectedOutcome::kTargetUnchanged;
}
diff --git a/src/gpu/GrWaitRenderTask.h b/src/gpu/GrWaitRenderTask.h
index fa6b02c..46c2edf 100644
--- a/src/gpu/GrWaitRenderTask.h
+++ b/src/gpu/GrWaitRenderTask.h
@@ -28,7 +28,7 @@
void handleInternalAllocationFailure() override {}
void gatherProxyIntervals(GrResourceAllocator*) const override;
- ExpectedOutcome onMakeClosed(const GrCaps&) override {
+ ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
return ExpectedOutcome::kTargetUnchanged;
}
diff --git a/src/gpu/dawn/GrDawnGpu.h b/src/gpu/dawn/GrDawnGpu.h
index 2f1b26c..7b17424 100644
--- a/src/gpu/dawn/GrDawnGpu.h
+++ b/src/gpu/dawn/GrDawnGpu.h
@@ -154,8 +154,8 @@
GrColorType surfaceColorType, GrColorType bufferColorType,
GrGpuBuffer* transferBuffer, size_t offset) override;
- void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override {
- }
+ void onResolveRenderTarget(GrRenderTarget*, const SkIRect&, GrSurfaceOrigin,
+ ForExternalIO) override {}
bool onRegenerateMipMapLevels(GrTexture*) override;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index ea5e87d..632f82f 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1957,7 +1957,7 @@
this->flushRenderTargetNoColorWrites(renderTarget);
break;
case GrGLRenderTarget::kCanResolve_ResolveType:
- this->onResolveRenderTarget(renderTarget, ForExternalIO::kNo);
+ SkASSERT(!renderTarget->needsResolve());
// we don't track the state of the READ FBO ID.
this->bindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID());
break;
@@ -2281,7 +2281,8 @@
}
}
-void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) {
+void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
+ GrSurfaceOrigin resolveOrigin, ForExternalIO) {
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
if (rt->needsResolve()) {
// Some extensions automatically resolves the texture when it is read.
@@ -2294,15 +2295,11 @@
// make sure we go through flushRenderTarget() since we've modified
// the bound DRAW FBO ID.
fHWBoundRenderTargetUniqueID.makeInvalid();
- const SkIRect dirtyRect = rt->getResolveRect();
- // The dirty rect tracked on the RT is always stored in the native coordinates of the
- // surface. Choose kTopLeft so no adjustments are made
- static constexpr auto kDirtyRectOrigin = kTopLeft_GrSurfaceOrigin;
if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
// Apple's extension uses the scissor as the blit bounds.
GrScissorState scissorState;
- scissorState.set(dirtyRect);
- this->flushScissor(scissorState, rt->width(), rt->height(), kDirtyRectOrigin);
+ scissorState.set(resolveRect);
+ this->flushScissor(scissorState, rt->width(), rt->height(), resolveOrigin);
this->disableWindowRectangles();
GL_CALL(ResolveMultisampleFramebuffer());
} else {
@@ -2315,7 +2312,7 @@
t = target->height();
} else {
auto rect = GrNativeRect::MakeRelativeTo(
- kDirtyRectOrigin, rt->height(), dirtyRect);
+ resolveOrigin, rt->height(), resolveRect);
l = rect.fX;
b = rect.fY;
r = rect.fX + rect.fWidth;
@@ -2536,6 +2533,7 @@
void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwizzle& swizzle,
GrGLTexture* texture) {
SkASSERT(texture);
+ SkASSERT(!texture->asRenderTarget() || !texture->asRenderTarget()->needsResolve());
#ifdef SK_DEBUG
if (!this->caps()->npotTextureTileSupport()) {
@@ -2547,14 +2545,6 @@
}
#endif
- // If we created a rt/tex and rendered to it without using a texture and now we're texturing
- // from the rt it will still be the last bound texture, but it needs resolving. So keep this
- // out of the "last != next" check.
- GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
- if (texRT) {
- this->onResolveRenderTarget(texRT, ForExternalIO::kNo);
- }
-
GrGpuResource::UniqueID textureID = texture->uniqueID();
GrGLenum target = texture->target();
if (fHWTextureUnitBindings[unitIdx].boundID(target) != textureID) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index d20909c..30bc989 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -258,7 +258,8 @@
// PIXEL_UNPACK_BUFFER is unbound.
void unbindCpuToGpuXferBuffer();
- void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override;
+ void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
+ GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
bool onRegenerateMipMapLevels(GrTexture*) override;
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 9d6f2f2..3dd2682 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -118,7 +118,8 @@
bool onRegenerateMipMapLevels(GrTexture*) override { return true; }
- void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override {
+ void onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, GrSurfaceOrigin,
+ ForExternalIO) override {
target->flagAsResolved();
}
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 6cb4bb8..d3067ee 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -108,10 +108,6 @@
this->didWriteToSurface(surface, origin, bounds);
}
- void resolveRenderTargetNoFlush(GrRenderTarget* target) {
- this->internalResolveRenderTarget(target, false);
- }
-
private:
GrMtlGpu(GrContext* context, const GrContextOptions& options,
id<MTLDevice> device, id<MTLCommandQueue> queue, MTLFeatureSet featureSet);
@@ -185,11 +181,9 @@
bool onRegenerateMipMapLevels(GrTexture*) override;
- void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) override {
- this->internalResolveRenderTarget(target, ForExternalIO::kYes == forExternalIO);
- }
+ void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
+ GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
- void internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit);
void resolveTexture(id<MTLTexture> colorTexture, id<MTLTexture> resolveTexture);
void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index e99abf1..10666a4 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -1053,7 +1053,7 @@
mtlTexture = rt->mtlColorTexture();
break;
case GrMtlRenderTarget::kCanResolve_ResolveType:
- this->resolveRenderTargetNoFlush(rt);
+ SkASSERT(!rt->needsResolve());
mtlTexture = rt->mtlResolveTexture();
break;
default:
@@ -1188,13 +1188,17 @@
#endif
}
-void GrMtlGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
+void GrMtlGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, GrSurfaceOrigin,
+ ForExternalIO forExternalIO) {
if (target->needsResolve()) {
this->resolveTexture(static_cast<GrMtlRenderTarget*>(target)->mtlResolveTexture(),
static_cast<GrMtlRenderTarget*>(target)->mtlColorTexture());
target->flagAsResolved();
- if (requiresSubmit) {
+ if (ForExternalIO::kYes == forExternalIO) {
+ // This resolve is called when we are preparing an msaa surface for external I/O. It is
+ // called after flushing, so we need to make sure we submit the command buffer after
+ // doing the resolve so that the resolve actually happens.
this->submitCommandBuffer(kSkip_SyncQueue);
}
}
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 47f9573..a5577a8 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -535,18 +535,6 @@
if (rt->wrapsSecondaryCommandBuffer()) {
return false;
}
- // resolve the render target if necessary
- switch (rt->getResolveType()) {
- case GrVkRenderTarget::kCantResolve_ResolveType:
- return false;
- case GrVkRenderTarget::kAutoResolves_ResolveType:
- break;
- case GrVkRenderTarget::kCanResolve_ResolveType:
- this->resolveRenderTargetNoFlush(rt);
- break;
- default:
- SK_ABORT("Unknown resolve type");
- }
srcImage = rt;
} else {
srcImage = static_cast<GrVkTexture*>(surface->asTexture());
@@ -617,21 +605,24 @@
fCurrentCmdBuffer->resolveImage(this, *src->msaaImage(), *dstImage, 1, &resolveInfo);
}
-void GrVkGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
- if (target->needsResolve()) {
- SkASSERT(target->numSamples() > 1);
- GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
- SkASSERT(rt->msaaImage());
+void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
+ GrSurfaceOrigin resolveOrigin, ForExternalIO forExternalIO) {
+ SkASSERT(target->numSamples() > 1);
+ GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
+ SkASSERT(rt->msaaImage());
- const SkIRect& srcRect = rt->getResolveRect();
+ auto nativeResolveRect = GrNativeRect::MakeRelativeTo(
+ resolveOrigin, target->height(), resolveRect);
+ this->resolveImage(target, rt, nativeResolveRect.asSkIRect(),
+ SkIPoint::Make(nativeResolveRect.fX, nativeResolveRect.fY));
- this->resolveImage(target, rt, srcRect, SkIPoint::Make(srcRect.fLeft, srcRect.fTop));
+ rt->flagAsResolved();
- rt->flagAsResolved();
-
- if (requiresSubmit) {
- this->submitCommandBuffer(kSkip_SyncQueue);
- }
+ if (ForExternalIO::kYes == forExternalIO) {
+ // This resolve is called when we are preparing an msaa surface for external I/O. It is
+ // called after flushing, so we need to make sure we submit the command buffer after doing
+ // the resolve so that the resolve actually happens.
+ this->submitCommandBuffer(kSkip_SyncQueue);
}
}
@@ -2232,18 +2223,6 @@
if (rt->wrapsSecondaryCommandBuffer()) {
return false;
}
- // resolve the render target if necessary
- switch (rt->getResolveType()) {
- case GrVkRenderTarget::kCantResolve_ResolveType:
- return false;
- case GrVkRenderTarget::kAutoResolves_ResolveType:
- break;
- case GrVkRenderTarget::kCanResolve_ResolveType:
- this->resolveRenderTargetNoFlush(rt);
- break;
- default:
- SK_ABORT("Unknown resolve type");
- }
image = rt;
} else {
image = static_cast<GrVkTexture*>(surface->asTexture());
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index f041cab..d0b7787 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -119,13 +119,8 @@
bool onRegenerateMipMapLevels(GrTexture* tex) override;
- void resolveRenderTargetNoFlush(GrRenderTarget* target) {
- this->internalResolveRenderTarget(target, false);
- }
-
- void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) override {
- this->internalResolveRenderTarget(target, ForExternalIO::kYes == forExternalIO);
- }
+ void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
+ GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
void submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer>);
@@ -248,8 +243,6 @@
void submitCommandBuffer(SyncQueue sync, GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
- void internalResolveRenderTarget(GrRenderTarget*, bool requiresSubmit);
-
void copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
GrVkImage* srcImage, const SkIRect& srcRect,
const SkIPoint& dstPoint);