Reland "Remove the resolve rect and resolve types from GrRenderTarget"

This is a reland of ec85f407bf

Original change's description:
> Remove the resolve rect and resolve types from GrRenderTarget
> 
> Change-Id: Id0c1155130c23e835490714fe1314f4ec4a83015
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/240002
> Reviewed-by: Greg Daniel <egdaniel@google.com>
> Commit-Queue: Chris Dalton <csmartdalton@google.com>

Change-Id: I501b1e1f506cda284876522b0294215030744888
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/244673
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2019-09-26 14:04:24 -06:00 committed by Skia Commit-Bot
parent 988b1e4653
commit c139d08f4f
15 changed files with 68 additions and 221 deletions

View File

@ -581,7 +581,6 @@ bool GrGpu::regenerateMipMapLevels(GrTexture* texture) {
SkASSERT(texture);
SkASSERT(this->caps()->mipMapSupport());
SkASSERT(texture->texturePriv().mipMapped() == GrMipMapped::kYes);
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,
@ -607,19 +606,6 @@ void GrGpu::resetTextureBindings() {
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, resolveRect, origin, forExternalIO);
}
@ -630,15 +616,6 @@ void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const
SkASSERT(!surface->readOnly());
// Mark any MIP chain and resolve buffer as dirty if and only if there is a non-empty bounds.
if (nullptr == bounds || !bounds->isEmpty()) {
if (GrRenderTarget* target = surface->asRenderTarget()) {
SkIRect flippedBounds;
if (kBottomLeft_GrSurfaceOrigin == origin && bounds) {
flippedBounds = {bounds->fLeft, surface->height() - bounds->fBottom,
bounds->fRight, surface->height() - bounds->fTop};
bounds = &flippedBounds;
}
target->flagAsNeedingResolve(bounds);
}
GrTexture* texture = surface->asTexture();
if (texture && 1 == mipLevels) {
texture->texturePriv().markMipMapsDirty();

View File

@ -42,9 +42,6 @@ static void assert_msaa_and_mips_are_resolved(
auto assertResolved = [](GrTexture* tex, const GrSamplerState& sampler) {
SkASSERT(tex);
// Ensure msaa was resolved ahead of time by the DAG.
SkASSERT(!tex->asRenderTarget() || !tex->asRenderTarget()->needsResolve());
// Ensure mipmaps were all resolved ahead of time by the DAG.
if (GrSamplerState::Filter::kMipMap == sampler.filter() &&
(tex->width() != 1 || tex->height() != 1)) {

View File

@ -25,28 +25,10 @@ GrRenderTarget::GrRenderTarget(GrGpu* gpu, const SkISize& size, GrPixelConfig co
, fSampleCnt(sampleCount)
, fSamplePatternKey(GrSamplePatternDictionary::kInvalidSamplePatternKey)
, fStencilAttachment(stencil) {
fResolveRect = SkRectPriv::MakeILargestInverted();
}
GrRenderTarget::~GrRenderTarget() = default;
void GrRenderTarget::flagAsNeedingResolve(const SkIRect* rect) {
if (kCanResolve_ResolveType == getResolveType()) {
if (rect) {
fResolveRect.join(*rect);
if (!fResolveRect.intersect({0, 0, this->width(), this->height()})) {
fResolveRect.setEmpty();
}
} else {
fResolveRect.setLTRB(0, 0, this->width(), this->height());
}
}
}
void GrRenderTarget::flagAsResolved() {
fResolveRect = SkRectPriv::MakeILargestInverted();
}
void GrRenderTarget::onRelease() {
fStencilAttachment = nullptr;

View File

@ -25,8 +25,9 @@ class GrBackendRenderTarget;
*/
class GrRenderTarget : virtual public GrSurface {
public:
// Make setRequiresManualMSAAResolve publicly accessible from GrRenderTarget.
// Make manual MSAA resolve publicly accessible from GrRenderTarget.
using GrSurface::setRequiresManualMSAAResolve;
using GrSurface::requiresManualMSAAResolve;
virtual bool alwaysClearStencil() const { return false; }
@ -39,44 +40,6 @@ public:
*/
int numSamples() const { return fSampleCnt; }
/**
* Call to indicate the multisample contents were modified such that the
* render target needs to be resolved before it can be used as texture. Gr
* tracks this for its own drawing and thus this only needs to be called
* when the render target has been modified outside of Gr. This has no
* effect on wrapped backend render targets.
*
* @param rect a rect bounding the area needing resolve. NULL indicates
* the whole RT needs resolving.
*/
void flagAsNeedingResolve(const SkIRect* rect = nullptr);
/**
* Call to indicate that GrRenderTarget was externally resolved. This may
* allow Gr to skip a redundant resolve step.
*/
void flagAsResolved();
/**
* @return true if the GrRenderTarget requires MSAA resolving
*/
bool needsResolve() const { return !fResolveRect.isEmpty(); }
/**
* Returns a rect bounding the region needing resolving.
*/
const SkIRect& getResolveRect() const { return fResolveRect; }
// a MSAA RT may require explicit resolving , it may auto-resolve (e.g. FBO
// 0 in GL), or be unresolvable because the client didn't give us the
// resolve destination.
enum ResolveType {
kCanResolve_ResolveType,
kAutoResolves_ResolveType,
kCantResolve_ResolveType,
};
virtual ResolveType getResolveType() const = 0;
virtual GrBackendRenderTarget getBackendRenderTarget() const = 0;
// Checked when this object is asked to attach a stencil buffer.
@ -107,7 +70,6 @@ private:
int fSampleCnt;
int fSamplePatternKey;
sk_sp<GrStencilAttachment> fStencilAttachment;
SkIRect fResolveRect;
typedef GrSurface INHERITED;
};

View File

@ -269,9 +269,6 @@ sk_sp<GrTexture> GrResourceProvider::refScratchTexture(const GrSurfaceDesc& desc
if (resource) {
fGpu->stats()->incNumScratchTexturesReused();
GrSurface* surface = static_cast<GrSurface*>(resource);
if (GrRenderTarget* rt = surface->asRenderTarget()) {
rt->flagAsResolved(); // Scratch textures always start without dirty MSAA.
}
return sk_sp<GrTexture>(surface->asTexture());
}
}

View File

@ -69,12 +69,10 @@ bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
for (const auto& resolve : fResolves) {
if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
// peekRenderTarget might be null if there was an instantiation error.
GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget();
if (renderTarget && renderTarget->needsResolve()) {
if (GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget()) {
flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect,
resolve.fProxy->origin(),
GrGpu::ForExternalIO::kNo);
SkASSERT(!renderTarget->needsResolve());
}
}
}

View File

@ -1949,20 +1949,17 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
}
if (renderTarget) {
// resolve the render target if necessary
switch (renderTarget->getResolveType()) {
case GrGLRenderTarget::kCantResolve_ResolveType:
return false;
case GrGLRenderTarget::kAutoResolves_ResolveType:
this->flushRenderTargetNoColorWrites(renderTarget);
break;
case GrGLRenderTarget::kCanResolve_ResolveType:
SkASSERT(!renderTarget->needsResolve());
// we don't track the state of the READ FBO ID.
this->bindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID());
break;
default:
SK_ABORT("Unknown resolve type");
if (renderTarget->numSamples() <= 1 ||
renderTarget->renderFBOID() == renderTarget->textureFBOID()) { // Also catches FBO 0.
SkASSERT(!renderTarget->requiresManualMSAAResolve());
this->flushRenderTargetNoColorWrites(renderTarget);
} else if (GrGLRenderTarget::kUnresolvableFBOID == renderTarget->textureFBOID()) {
SkASSERT(!renderTarget->requiresManualMSAAResolve());
return false;
} else {
SkASSERT(renderTarget->requiresManualMSAAResolve());
// we don't track the state of the READ FBO ID.
this->bindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID());
}
} else {
// Use a temporary FBO.
@ -2283,50 +2280,46 @@ void GrGLGpu::sendIndexedInstancedMeshToGpu(GrPrimitiveType primitiveType,
void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
GrSurfaceOrigin resolveOrigin, ForExternalIO) {
// Some extensions automatically resolves the texture when it is read.
SkASSERT(this->glCaps().usesMSAARenderBuffers());
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
if (rt->needsResolve()) {
// Some extensions automatically resolves the texture when it is read.
if (this->glCaps().usesMSAARenderBuffers()) {
SkASSERT(rt->textureFBOID() != rt->renderFBOID());
SkASSERT(rt->textureFBOID() != 0 && rt->renderFBOID() != 0);
this->bindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID());
this->bindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID());
SkASSERT(rt->textureFBOID() != rt->renderFBOID());
SkASSERT(rt->textureFBOID() != 0 && rt->renderFBOID() != 0);
this->bindFramebuffer(GR_GL_READ_FRAMEBUFFER, rt->renderFBOID());
this->bindFramebuffer(GR_GL_DRAW_FRAMEBUFFER, rt->textureFBOID());
// make sure we go through flushRenderTarget() since we've modified
// the bound DRAW FBO ID.
fHWBoundRenderTargetUniqueID.makeInvalid();
if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
// Apple's extension uses the scissor as the blit bounds.
GrScissorState scissorState;
scissorState.set(resolveRect);
this->flushScissor(scissorState, rt->width(), rt->height(), resolveOrigin);
this->disableWindowRectangles();
GL_CALL(ResolveMultisampleFramebuffer());
} else {
int l, b, r, t;
if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag &
this->glCaps().blitFramebufferSupportFlags()) {
l = 0;
b = 0;
r = target->width();
t = target->height();
} else {
auto rect = GrNativeRect::MakeRelativeTo(
resolveOrigin, rt->height(), resolveRect);
l = rect.fX;
b = rect.fY;
r = rect.fX + rect.fWidth;
t = rect.fY + rect.fHeight;
}
// BlitFrameBuffer respects the scissor, so disable it.
this->disableScissor();
this->disableWindowRectangles();
GL_CALL(BlitFramebuffer(l, b, r, t, l, b, r, t,
GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
}
// make sure we go through flushRenderTarget() since we've modified
// the bound DRAW FBO ID.
fHWBoundRenderTargetUniqueID.makeInvalid();
if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
// Apple's extension uses the scissor as the blit bounds.
GrScissorState scissorState;
scissorState.set(resolveRect);
this->flushScissor(scissorState, rt->width(), rt->height(), resolveOrigin);
this->disableWindowRectangles();
GL_CALL(ResolveMultisampleFramebuffer());
} else {
int l, b, r, t;
if (GrGLCaps::kResolveMustBeFull_BlitFrambufferFlag &
this->glCaps().blitFramebufferSupportFlags()) {
l = 0;
b = 0;
r = target->width();
t = target->height();
} else {
auto rect = GrNativeRect::MakeRelativeTo(
resolveOrigin, rt->height(), resolveRect);
l = rect.fX;
b = rect.fY;
r = rect.fX + rect.fWidth;
t = rect.fY + rect.fHeight;
}
rt->flagAsResolved();
// BlitFrameBuffer respects the scissor, so disable it.
this->disableScissor();
this->disableWindowRectangles();
GL_CALL(BlitFramebuffer(l, b, r, t, l, b, r, t, GR_GL_COLOR_BUFFER_BIT, GR_GL_NEAREST));
}
}
@ -2533,7 +2526,6 @@ static void get_gl_swizzle_values(const GrSwizzle& swizzle, GrGLenum glValues[4]
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()) {

View File

@ -47,20 +47,6 @@ public:
// FBO ID that has texture ID attached.
GrGLuint textureFBOID() const { return fTexFBOID; }
// override of GrRenderTarget
ResolveType getResolveType() const override {
if (this->numSamples() <= 1 || fRTFBOID == fTexFBOID) { // Also catches FBO 0.
SkASSERT(!this->requiresManualMSAAResolve());
return kAutoResolves_ResolveType;
} else if (kUnresolvableFBOID == fTexFBOID) {
SkASSERT(!this->requiresManualMSAAResolve());
return kCantResolve_ResolveType;
} else {
SkASSERT(this->requiresManualMSAAResolve());
return kCanResolve_ResolveType;
}
}
GrBackendRenderTarget getBackendRenderTarget() const override;
GrBackendFormat backendFormat() const override;

View File

@ -119,9 +119,7 @@ private:
bool onRegenerateMipMapLevels(GrTexture*) override { return true; }
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, GrSurfaceOrigin,
ForExternalIO) override {
target->flagAsResolved();
}
ForExternalIO) override {}
void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
const GrFlushInfo& info, const GrPrepareForExternalIORequests&) override {

View File

@ -50,7 +50,6 @@ private:
if (auto* tex = fRenderTarget->asTexture()) {
tex->texturePriv().markMipMapsDirty();
}
fRenderTarget->flagAsNeedingResolve();
}
GrMockGpu* fGpu;

View File

@ -93,10 +93,6 @@ public:
this->registerWithCacheWrapped(GrWrapCacheable::kNo);
}
ResolveType getResolveType() const override {
return (this->requiresManualMSAAResolve()) ?
kCanResolve_ResolveType : kAutoResolves_ResolveType;
}
bool canAttemptStencilAttachment() const override { return true; }
bool completeStencilAttachment() override { return true; }

View File

@ -1048,29 +1048,17 @@ bool GrMtlGpu::onReadPixels(GrSurface* surface, int left, int top, int width, in
size_t transBufferRowBytes = bpp * width;
id<MTLTexture> mtlTexture;
GrMtlRenderTarget* rt = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
if (rt) {
// resolve the render target if necessary
switch (rt->getResolveType()) {
case GrMtlRenderTarget::kCantResolve_ResolveType:
return false;
case GrMtlRenderTarget::kAutoResolves_ResolveType:
mtlTexture = rt->mtlColorTexture();
break;
case GrMtlRenderTarget::kCanResolve_ResolveType:
SkASSERT(!rt->needsResolve());
mtlTexture = rt->mtlResolveTexture();
break;
default:
SK_ABORT("Unknown resolve type");
}
} else {
GrMtlTexture* texture = static_cast<GrMtlTexture*>(surface->asTexture());
if (texture) {
mtlTexture = texture->mtlTexture();
if (GrMtlRenderTarget* rt = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget())) {
if (rt->numSamples() > 1) {
SkASSERT(rt->requiresManualMSAAResolve()); // msaa-render-to-texture not yet supported.
mtlTexture = rt->mtlResolveTexture();
} else {
SkASSERT(!rt->requiresManualMSAAResolve());
mtlTexture = rt->mtlColorTexture();
}
} else if (GrMtlTexture* texture = static_cast<GrMtlTexture*>(surface->asTexture())) {
mtlTexture = texture->mtlTexture();
}
if (!mtlTexture) {
return false;
}
@ -1195,17 +1183,14 @@ void GrMtlGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
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();
this->resolveTexture(static_cast<GrMtlRenderTarget*>(target)->mtlResolveTexture(),
static_cast<GrMtlRenderTarget*>(target)->mtlColorTexture());
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);
}
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);
}
}

View File

@ -25,16 +25,6 @@ public:
~GrMtlRenderTarget() override;
// override of GrRenderTarget
ResolveType getResolveType() const override {
if (this->numSamples() > 1) {
SkASSERT(this->requiresManualMSAAResolve());
return kCanResolve_ResolveType;
}
SkASSERT(!this->requiresManualMSAAResolve());
return kAutoResolves_ResolveType;
}
bool canAttemptStencilAttachment() const override {
return true;
}

View File

@ -616,8 +616,6 @@ void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resol
this->resolveImage(target, rt, nativeResolveRect.asSkIRect(),
SkIPoint::Make(nativeResolveRect.fX, nativeResolveRect.fY));
rt->flagAsResolved();
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

View File

@ -73,16 +73,6 @@ public:
return fSecondaryCommandBuffer;
}
// override of GrRenderTarget
ResolveType getResolveType() const override {
if (this->numSamples() > 1) {
SkASSERT(this->requiresManualMSAAResolve());
return kCanResolve_ResolveType;
}
SkASSERT(!this->requiresManualMSAAResolve());
return kAutoResolves_ResolveType;
}
bool canAttemptStencilAttachment() const override {
// We don't know the status of the stencil attachment for wrapped external secondary command
// buffers so we just assume we don't have one.