From 804f6a0fe7f3c7df5ac69891841ee9cdf6d1121a Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Mon, 26 Aug 2019 12:07:30 -0600 Subject: [PATCH] Initiate MSAA resolves during DAG generation Adds an "fIsMSAADirty" flag to GrRenderTargetProxy and switches to resolving MSAA in GrTextureResolveRenderTask. This completes our push to resolve textures outside of render passes. For the time being, we only store a dirty flag on the proxy and still rely on the GrRenderTarget itself to track the actual dirty rect. This will be followed by a CL that moves the dirty rect out of GrRenderTarget and into the proxy. Bug: skia: Change-Id: I21219a58028bdb4590940210e565133093cd34b3 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235672 Commit-Queue: Chris Dalton Reviewed-by: Robert Phillips --- include/private/GrTypesPriv.h | 5 ++- src/gpu/GrDrawingManager.cpp | 25 ++++++++--- src/gpu/GrOnFlushResourceProvider.cpp | 13 ++++++ src/gpu/GrOnFlushResourceProvider.h | 8 ++-- src/gpu/GrOpsRenderPass.cpp | 52 ++++++++++++++++++++- src/gpu/GrRenderTargetProxy.h | 17 +++++++ src/gpu/GrRenderTask.cpp | 27 +++++++++-- src/gpu/GrTextureResolveRenderTask.cpp | 38 ++++++++++++---- src/gpu/ccpr/GrCCPerFlushResources.cpp | 4 ++ src/gpu/gl/GrGLGpu.cpp | 62 +++----------------------- src/gpu/gl/GrGLGpu.h | 9 ---- src/gpu/mock/GrMockGpu.h | 2 +- src/gpu/mtl/GrMtlOpsRenderPass.mm | 40 ----------------- src/gpu/vk/GrVkOpsRenderPass.cpp | 28 ------------ 14 files changed, 170 insertions(+), 160 deletions(-) diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h index 037dce8f40..f23ae8d1c5 100644 --- a/include/private/GrTypesPriv.h +++ b/include/private/GrTypesPriv.h @@ -1466,11 +1466,12 @@ private: /** * Indicates "resolutions" that need to be done on a texture before it can be sampled from. + * If both types of resolve are requested, the MSAA resolve will happen first. */ enum class GrTextureResolveFlags { kNone = 0, - kMipMaps = 1 << 0, // Regenerate all mipmap levels. - // TODO: kMSAA = 1 << 1 // Blit the MSAA render buffer into a standard texture. + kMSAA = 1 << 0, // Blit and resolve an internal MSAA render buffer into the texture. + kMipMaps = 1 << 1, // Regenerate all mipmap levels. }; GR_MAKE_BITFIELD_CLASS_OPS(GrTextureResolveFlags) diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp index a32240cdf7..e47fb0c38a 100644 --- a/src/gpu/GrDrawingManager.cpp +++ b/src/gpu/GrDrawingManager.cpp @@ -294,6 +294,10 @@ GrSemaphoresSubmitted GrDrawingManager::flush(GrSurfaceProxy* proxies[], int num [](GrSurfaceProxy* p, GrMipMapped mipMapped) { SkASSERT(!p->asTextureProxy() || !p->asTextureProxy()->texPriv().isDeferred()); SkASSERT(GrSurfaceProxy::LazyState::kNot == p->lazyInstantiationState()); + if (p->requiresManualMSAAResolve()) { + // The onFlush callback is responsible for ensuring MSAA gets resolved. + SkASSERT(p->asRenderTargetProxy() && !p->asRenderTargetProxy()->isMSAADirty()); + } if (GrMipMapped::kYes == mipMapped) { // The onFlush callback is responsible for regenerating mips if needed. SkASSERT(p->asTextureProxy() && !p->asTextureProxy()->mipMapsAreDirty()); @@ -509,19 +513,30 @@ GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[], GrSemaphoresSubmitted result = this->flush(proxies, numProxies, access, info, GrPrepareForExternalIORequests()); for (int i = 0; i < numProxies; ++i) { - if (!proxies[i]->isInstantiated()) { + GrSurfaceProxy* proxy = proxies[i]; + if (!proxy->isInstantiated()) { return result; } - GrSurface* surface = proxies[i]->peekSurface(); - if (auto* rt = surface->asRenderTarget()) { - gpu->resolveRenderTarget(rt); + // In the flushSurfaces case, we need to resolve MSAA immediately after flush. This is + // because the client will call through to this method when drawing into a target created by + // wrapBackendTextureAsRenderTarget, and will expect the original texture to be fully + // resolved upon return. + if (proxy->requiresManualMSAAResolve()) { + auto* rtProxy = proxy->asRenderTargetProxy(); + SkASSERT(rtProxy); + if (rtProxy->isMSAADirty()) { + SkASSERT(rtProxy->peekRenderTarget()); + gpu->resolveRenderTarget(rtProxy->peekRenderTarget()); + rtProxy->markMSAAResolved(); + } } // If, after a flush, any of the proxies of interest have dirty mipmaps, regenerate them in // case their backend textures are being stolen. // (This special case is exercised by the ReimportImageTextureWithMipLevels test.) // FIXME: It may be more ideal to plumb down a "we're going to steal the backends" flag. - if (auto* textureProxy = proxies[i]->asTextureProxy()) { + if (auto* textureProxy = proxy->asTextureProxy()) { if (textureProxy->mipMapsAreDirty()) { + SkASSERT(textureProxy->peekTexture()); gpu->regenerateMipMapLevels(textureProxy->peekTexture()); textureProxy->markMipMapsClean(); } diff --git a/src/gpu/GrOnFlushResourceProvider.cpp b/src/gpu/GrOnFlushResourceProvider.cpp index 8d7c95c636..aa27b95b74 100644 --- a/src/gpu/GrOnFlushResourceProvider.cpp +++ b/src/gpu/GrOnFlushResourceProvider.cpp @@ -14,6 +14,7 @@ #include "src/gpu/GrRecordingContextPriv.h" #include "src/gpu/GrRenderTargetContext.h" #include "src/gpu/GrSurfaceProxy.h" +#include "src/gpu/GrTextureResolveRenderTask.h" std::unique_ptr GrOnFlushResourceProvider::makeRenderTargetContext( sk_sp proxy, GrColorType colorType, sk_sp colorSpace, @@ -40,6 +41,18 @@ std::unique_ptr GrOnFlushResourceProvider::makeRenderTarg return renderTargetContext; } +void GrOnFlushResourceProvider::addTextureResolveTask(sk_sp textureProxy, + GrTextureResolveFlags resolveFlags) { + // Since we are bypassing normal DAG operation, we need to ensure the textureProxy's last render + // task gets closed before making a texture resolve task. makeClosed is what will mark msaa and + // mipmaps dirty. + if (GrRenderTask* renderTask = textureProxy->getLastRenderTask()) { + renderTask->makeClosed(*this->caps()); + } + fDrawingMgr->fOnFlushRenderTasks.push_back(GrTextureResolveRenderTask::Make( + std::move(textureProxy), resolveFlags, *this->caps())); +} + bool GrOnFlushResourceProvider::assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy* proxy) { auto proxyProvider = fDrawingMgr->getContext()->priv().proxyProvider(); diff --git a/src/gpu/GrOnFlushResourceProvider.h b/src/gpu/GrOnFlushResourceProvider.h index e4fe6f1d6e..9e86629541 100644 --- a/src/gpu/GrOnFlushResourceProvider.h +++ b/src/gpu/GrOnFlushResourceProvider.h @@ -63,10 +63,10 @@ class GrOnFlushResourceProvider { public: explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {} - std::unique_ptr makeRenderTargetContext(sk_sp, - GrColorType, - sk_sp, - const SkSurfaceProps*); + std::unique_ptr makeRenderTargetContext( + sk_sp, GrColorType, sk_sp, const SkSurfaceProps*); + + void addTextureResolveTask(sk_sp, GrTextureResolveFlags); // Proxy unique key management. See GrProxyProvider.h. bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*); diff --git a/src/gpu/GrOpsRenderPass.cpp b/src/gpu/GrOpsRenderPass.cpp index 3876a42445..dcc53b644e 100644 --- a/src/gpu/GrOpsRenderPass.cpp +++ b/src/gpu/GrOpsRenderPass.cpp @@ -17,6 +17,7 @@ #include "src/gpu/GrPrimitiveProcessor.h" #include "src/gpu/GrRenderTarget.h" #include "src/gpu/GrRenderTargetPriv.h" +#include "src/gpu/GrTexturePriv.h" void GrOpsRenderPass::clear(const GrFixedClip& clip, const SkPMColor4f& color) { SkASSERT(fRenderTarget); @@ -33,6 +34,51 @@ void GrOpsRenderPass::clearStencilClip(const GrFixedClip& clip, bool insideStenc this->onClearStencilClip(clip, insideStencilMask); } +#ifdef SK_DEBUG +static void assert_msaa_and_mips_are_resolved( + const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, + const GrPipeline::FixedDynamicState* fixedDynamicState, + const GrPipeline::DynamicStateArrays* dynamicStateArrays, int meshCount) { + 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)) { + // There are some cases where we might be given a non-mipmapped texture with a mipmap + // filter. See skbug.com/7094. + SkASSERT(tex->texturePriv().mipMapped() != GrMipMapped::kYes || + !tex->texturePriv().mipMapsAreDirty()); + } + }; + + if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) { + for (int m = 0, i = 0; m < meshCount; ++m) { + for (int s = 0; s < primProc.numTextureSamplers(); ++s, ++i) { + auto* tex = dynamicStateArrays->fPrimitiveProcessorTextures[i]->peekTexture(); + assertResolved(tex, primProc.textureSampler(s).samplerState()); + } + } + } else { + for (int i = 0; i < primProc.numTextureSamplers(); ++i) { + auto* tex = fixedDynamicState->fPrimitiveProcessorTextures[i]->peekTexture(); + assertResolved(tex, primProc.textureSampler(i).samplerState()); + } + } + + GrFragmentProcessor::Iter iter(pipeline); + while (const GrFragmentProcessor* fp = iter.next()) { + for (int i = 0; i < fp->numTextureSamplers(); ++i) { + const auto& textureSampler = fp->textureSampler(i); + assertResolved(textureSampler.peekTexture(), textureSampler.samplerState()); + } + } +} +#endif + bool GrOpsRenderPass::draw(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrPipeline::FixedDynamicState* fixedDynamicState, const GrPipeline::DynamicStateArrays* dynamicStateArrays, @@ -45,13 +91,12 @@ bool GrOpsRenderPass::draw(const GrPrimitiveProcessor& primProc, const GrPipelin SkASSERT(primProc.hasVertexAttributes() == meshes[i].hasVertexData()); SkASSERT(primProc.hasInstanceAttributes() == meshes[i].hasInstanceData()); } -#endif + SkASSERT(!pipeline.isScissorEnabled() || fixedDynamicState || (dynamicStateArrays && dynamicStateArrays->fScissorRects)); SkASSERT(!pipeline.isBad()); -#ifdef SK_DEBUG if (fixedDynamicState && fixedDynamicState->fPrimitiveProcessorTextures) { GrTextureProxy** processorProxies = fixedDynamicState->fPrimitiveProcessorTextures; for (int i = 0; i < primProc.numTextureSamplers(); ++i) { @@ -80,6 +125,9 @@ bool GrOpsRenderPass::draw(const GrPrimitiveProcessor& primProc, const GrPipelin } } } + + assert_msaa_and_mips_are_resolved( + primProc, pipeline, fixedDynamicState, dynamicStateArrays, meshCount); #endif if (primProc.numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) { diff --git a/src/gpu/GrRenderTargetProxy.h b/src/gpu/GrRenderTargetProxy.h index 2759a3da50..fd7ae5c8de 100644 --- a/src/gpu/GrRenderTargetProxy.h +++ b/src/gpu/GrRenderTargetProxy.h @@ -63,6 +63,19 @@ public: bool wrapsVkSecondaryCB() const { return fWrapsVkSecondaryCB == WrapsVkSecondaryCB::kYes; } + void markMSAADirty() { + SkASSERT(this->requiresManualMSAAResolve()); + fIsMSAADirty = true; + } + void markMSAAResolved() { + SkASSERT(this->requiresManualMSAAResolve()); + fIsMSAADirty = false; + } + bool isMSAADirty() const { + SkASSERT(!fIsMSAADirty || this->requiresManualMSAAResolve()); + return fIsMSAADirty; + } + // TODO: move this to a priv class! bool refsWrappedObjects() const; @@ -128,6 +141,10 @@ private: 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; // 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 639f4cf565..181a8dd52f 100644 --- a/src/gpu/GrRenderTask.cpp +++ b/src/gpu/GrRenderTask.cpp @@ -51,6 +51,10 @@ void GrRenderTask::makeClosed(const GrCaps& caps) { } if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps)) { + GrRenderTargetProxy* renderTargetProxy = fTarget->asRenderTargetProxy(); + if (renderTargetProxy && renderTargetProxy->requiresManualMSAAResolve()) { + renderTargetProxy->markMSAADirty(); + } GrTextureProxy* textureProxy = fTarget->asTextureProxy(); if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) { textureProxy->markMipMapsDirty(); @@ -93,8 +97,11 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapp GrRenderTask* dependedOnTask = dependedOn->getLastRenderTask(); if (dependedOnTask == this) { - // self-read - presumably for dst reads. We can't make it closed in the self-read case. + // self-read - presumably for dst reads. We don't need to do anything in this case. The + // XferProcessor will detect what is happening and insert a texture barrier. SkASSERT(GrMipMapped::kNo == mipMapped); + // We should never attempt a self-read on a surface that has a separate MSAA renderbuffer. + SkASSERT(!dependedOn->requiresManualMSAAResolve()); SkASSERT(!dependedOn->asTextureProxy() || !dependedOn->asTextureProxy()->texPriv().isDeferred()); return; @@ -107,6 +114,16 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapp dependedOnTask->makeClosed(caps); } + auto textureResolveFlags = GrTextureResolveFlags::kNone; + + if (dependedOn->requiresManualMSAAResolve()) { + auto* renderTargetProxy = dependedOn->asRenderTargetProxy(); + SkASSERT(renderTargetProxy); + if (renderTargetProxy->isMSAADirty()) { + textureResolveFlags |= GrTextureResolveFlags::kMSAA; + } + } + GrTextureProxy* textureProxy = dependedOn->asTextureProxy(); if (GrMipMapped::kYes == mipMapped) { SkASSERT(textureProxy); @@ -114,14 +131,16 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapp // There are some cases where we might be given a non-mipmapped texture with a mipmap // filter. See skbug.com/7094. mipMapped = GrMipMapped::kNo; + } else if (textureProxy->mipMapsAreDirty()) { + textureResolveFlags |= GrTextureResolveFlags::kMipMaps; } } - // Does this proxy have mipmaps that need to be regenerated? - if (GrMipMapped::kYes == mipMapped && textureProxy->mipMapsAreDirty()) { + // Does this proxy have msaa to resolve and/or mipmaps to regenerate? + if (GrTextureResolveFlags::kNone != textureResolveFlags) { // Create a renderTask that resolves the texture's mipmap data. GrRenderTask* textureResolveTask = textureResolveManager.newTextureResolveRenderTask( - sk_ref_sp(textureProxy), GrTextureResolveFlags::kMipMaps, caps); + sk_ref_sp(textureProxy), textureResolveFlags, caps); // The GrTextureResolveRenderTask factory should have called addDependency (in this // instance, recursively) on the textureProxy. diff --git a/src/gpu/GrTextureResolveRenderTask.cpp b/src/gpu/GrTextureResolveRenderTask.cpp index 1e52b8793f..0064fe618d 100644 --- a/src/gpu/GrTextureResolveRenderTask.cpp +++ b/src/gpu/GrTextureResolveRenderTask.cpp @@ -10,6 +10,7 @@ #include "src/gpu/GrGpu.h" #include "src/gpu/GrMemoryPool.h" #include "src/gpu/GrOpFlushState.h" +#include "src/gpu/GrRenderTarget.h" #include "src/gpu/GrResourceAllocator.h" #include "src/gpu/GrTexturePriv.h" @@ -19,6 +20,24 @@ sk_sp GrTextureResolveRenderTask::Make( sk_sp resolveTask( new GrTextureResolveRenderTask(std::move(textureProxy), flags)); + // Ensure the last render task that operated on the textureProxy is closed. That's where msaa + // and mipmaps should have been marked dirty. + SkASSERT(!textureProxyPtr->getLastRenderTask() || + textureProxyPtr->getLastRenderTask()->isClosed()); + + if (GrTextureResolveFlags::kMSAA & flags) { + GrRenderTargetProxy* renderTargetProxy = textureProxyPtr->asRenderTargetProxy(); + SkASSERT(renderTargetProxy); + SkASSERT(renderTargetProxy->isMSAADirty()); + renderTargetProxy->markMSAAResolved(); + } + + if (GrTextureResolveFlags::kMipMaps & flags) { + SkASSERT(GrMipMapped::kYes == textureProxyPtr->mipMapped()); + SkASSERT(textureProxyPtr->mipMapsAreDirty()); + textureProxyPtr->markMipMapsClean(); + } + // Add the target as a dependency: We will read the existing contents of this texture while // generating mipmap levels and/or resolving MSAA. // @@ -30,13 +49,7 @@ sk_sp GrTextureResolveRenderTask::Make( // We only resolve the texture; nobody should try to do anything else with this opsTask. resolveTask->makeClosed(caps); - if (GrTextureResolveFlags::kMipMaps & flags) { - SkASSERT(GrMipMapped::kYes == textureProxyPtr->mipMapped()); - SkASSERT(textureProxyPtr->mipMapsAreDirty()); - textureProxyPtr->markMipMapsClean(); - } - - return resolveTask; + return std::move(resolveTask); } void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const { @@ -49,10 +62,17 @@ void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc } bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) { - GrTexture* texture = fTarget->peekTexture(); - SkASSERT(texture); + // Resolve msaa before regenerating mipmaps. + if (GrTextureResolveFlags::kMSAA & fResolveFlags) { + GrRenderTarget* renderTarget = fTarget->peekRenderTarget(); + SkASSERT(renderTarget); + SkASSERT(renderTarget->needsResolve()); + flushState->gpu()->resolveRenderTarget(renderTarget); + } if (GrTextureResolveFlags::kMipMaps & fResolveFlags) { + GrTexture* texture = fTarget->peekTexture(); + SkASSERT(texture); SkASSERT(texture->texturePriv().mipMapsAreDirty()); flushState->gpu()->regenerateMipMapLevels(texture); } diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp index 72ff29c498..8f565927e5 100644 --- a/src/gpu/ccpr/GrCCPerFlushResources.cpp +++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp @@ -588,6 +588,10 @@ bool GrCCPerFlushResources::finalize(GrOnFlushResourceProvider* onFlushRP) { atlas->getStrokeBatchID(), atlas->drawBounds()); } rtc->addDrawOp(GrNoClip(), std::move(op)); + if (rtc->proxy()->requiresManualMSAAResolve()) { + onFlushRP->addTextureResolveTask(sk_ref_sp(rtc->proxy()->asTextureProxy()), + GrTextureResolveFlags::kMSAA); + } } SkASSERT(atlas->getEndStencilResolveInstance() >= baseStencilResolveInstance); diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 46607933dc..ed722c82d7 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -1868,51 +1868,6 @@ void GrGLGpu::disableWindowRectangles() { #endif } -void GrGLGpu::resolveAndGenerateMipMapsForProcessorTextures( - const GrPrimitiveProcessor& primProc, - const GrPipeline& pipeline, - const GrTextureProxy* const primProcTextures[], - int numPrimitiveProcessorTextureSets) { - auto genLevelsIfNeeded = [this](GrTexture* tex, const GrSamplerState& sampler) { - SkASSERT(tex); - auto* rt = tex->asRenderTarget(); - if (rt && rt->needsResolve()) { - this->resolveRenderTarget(rt); - // TEMPORARY: MSAA resolve will have dirtied mipmaps. This goes away once we switch - // to resolving MSAA from the opsTask as well. - if (GrSamplerState::Filter::kMipMap == sampler.filter() && - (tex->width() != 1 || tex->height() != 1)) { - SkASSERT(tex->texturePriv().mipMapped() == GrMipMapped::kYes); - SkASSERT(tex->texturePriv().mipMapsAreDirty()); - this->regenerateMipMapLevels(tex); - } - } - // Ensure mipmaps were all resolved ahead of time by the opsTask. - if (GrSamplerState::Filter::kMipMap == sampler.filter() && - (tex->width() != 1 || tex->height() != 1)) { - // There are some cases where we might be given a non-mipmapped texture with a mipmap - // filter. See skbug.com/7094. - SkASSERT(tex->texturePriv().mipMapped() != GrMipMapped::kYes || - !tex->texturePriv().mipMapsAreDirty()); - } - }; - - for (int set = 0, tex = 0; set < numPrimitiveProcessorTextureSets; ++set) { - for (int sampler = 0; sampler < primProc.numTextureSamplers(); ++sampler, ++tex) { - GrTexture* texture = primProcTextures[tex]->peekTexture(); - genLevelsIfNeeded(texture, primProc.textureSampler(sampler).samplerState()); - } - } - - GrFragmentProcessor::Iter iter(pipeline); - while (const GrFragmentProcessor* fp = iter.next()) { - for (int i = 0; i < fp->numTextureSamplers(); ++i) { - const auto& textureSampler = fp->textureSampler(i); - genLevelsIfNeeded(textureSampler.peekTexture(), textureSampler.samplerState()); - } - } -} - bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget, GrSurfaceOrigin origin, const GrPrimitiveProcessor& primProc, @@ -1921,28 +1876,23 @@ bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget, const GrPipeline::DynamicStateArrays* dynamicStateArrays, int dynamicStateArraysLength, bool willDrawPoints) { - const GrTextureProxy* const* primProcProxiesForMipRegen = nullptr; + const GrTextureProxy* const* primProcProxies = nullptr; const GrTextureProxy* const* primProcProxiesToBind = nullptr; - int numPrimProcTextureSets = 1; // number of texture per prim proc sampler. if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) { - primProcProxiesForMipRegen = dynamicStateArrays->fPrimitiveProcessorTextures; - numPrimProcTextureSets = dynamicStateArraysLength; + primProcProxies = dynamicStateArrays->fPrimitiveProcessorTextures; } else if (fixedDynamicState && fixedDynamicState->fPrimitiveProcessorTextures) { - primProcProxiesForMipRegen = fixedDynamicState->fPrimitiveProcessorTextures; + primProcProxies = fixedDynamicState->fPrimitiveProcessorTextures; primProcProxiesToBind = fixedDynamicState->fPrimitiveProcessorTextures; } - SkASSERT(SkToBool(primProcProxiesForMipRegen) == SkToBool(primProc.numTextureSamplers())); + SkASSERT(SkToBool(primProcProxies) == SkToBool(primProc.numTextureSamplers())); - sk_sp program(fProgramCache->refProgram(this, renderTarget, origin, primProc, - primProcProxiesForMipRegen, - pipeline, willDrawPoints)); + sk_sp program(fProgramCache->refProgram( + this, renderTarget, origin, primProc, primProcProxies, pipeline, willDrawPoints)); if (!program) { GrCapsDebugf(this->caps(), "Failed to create program!\n"); return false; } - this->resolveAndGenerateMipMapsForProcessorTextures( - primProc, pipeline, primProcProxiesForMipRegen, numPrimProcTextureSets); this->flushProgram(std::move(program)); diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index d274a25360..d494be346a 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -270,15 +270,6 @@ private: // binds texture unit in GL void setTextureUnit(int unitIdx); - /** - * primitiveProcessorTextures must contain GrPrimitiveProcessor::numTextureSamplers() * - * numPrimitiveProcessorTextureSets entries. - */ - void resolveAndGenerateMipMapsForProcessorTextures( - const GrPrimitiveProcessor&, const GrPipeline&, - const GrTextureProxy* const primitiveProcessorTextures[], - int numPrimitiveProcessorTextureSets); - // Flushes state from GrPipeline to GL. Returns false if the state couldn't be set. // willDrawPoints must be true if point primitives will be rendered after setting the GL state. // If DynamicStateArrays is not null then dynamicStateArraysLength is the number of dynamic diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h index c0ab9c5b5b..86efe99744 100644 --- a/src/gpu/mock/GrMockGpu.h +++ b/src/gpu/mock/GrMockGpu.h @@ -115,7 +115,7 @@ private: bool onRegenerateMipMapLevels(GrTexture*) override { return true; } - void onResolveRenderTarget(GrRenderTarget* target) override { return; } + void onResolveRenderTarget(GrRenderTarget* target) override { target->flagAsResolved(); } void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access, const GrFlushInfo& info, const GrPrepareForExternalIORequests&) override { diff --git a/src/gpu/mtl/GrMtlOpsRenderPass.mm b/src/gpu/mtl/GrMtlOpsRenderPass.mm index f9754fe3dc..8b0bcdeaad 100644 --- a/src/gpu/mtl/GrMtlOpsRenderPass.mm +++ b/src/gpu/mtl/GrMtlOpsRenderPass.mm @@ -10,7 +10,6 @@ #include "src/gpu/GrColor.h" #include "src/gpu/GrFixedClip.h" #include "src/gpu/GrRenderTargetPriv.h" -#include "src/gpu/GrTexturePriv.h" #include "src/gpu/mtl/GrMtlCommandBuffer.h" #include "src/gpu/mtl/GrMtlPipelineState.h" #include "src/gpu/mtl/GrMtlPipelineStateBuilder.h" @@ -96,45 +95,6 @@ void GrMtlOpsRenderPass::onDraw(const GrPrimitiveProcessor& primProc, return; } - auto prepareSampledImage = [&](GrTexture* texture, GrSamplerState::Filter filter) { - GrMtlTexture* mtlTexture = static_cast(texture); - // We may need to resolve the texture first if it is also a render target - GrMtlRenderTarget* texRT = static_cast(mtlTexture->asRenderTarget()); - if (texRT) { - fGpu->resolveRenderTargetNoFlush(texRT); - } - - // Check if we need to regenerate any mip maps - if (GrSamplerState::Filter::kMipMap == filter && - (texture->width() != 1 || texture->height() != 1)) { - SkASSERT(texture->texturePriv().mipMapped() == GrMipMapped::kYes); - if (texture->texturePriv().mipMapsAreDirty()) { - fGpu->regenerateMipMapLevels(texture); - } - } - }; - - if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) { - for (int m = 0, i = 0; m < meshCount; ++m) { - for (int s = 0; s < primProc.numTextureSamplers(); ++s, ++i) { - auto texture = dynamicStateArrays->fPrimitiveProcessorTextures[i]->peekTexture(); - prepareSampledImage(texture, primProc.textureSampler(s).samplerState().filter()); - } - } - } else { - for (int i = 0; i < primProc.numTextureSamplers(); ++i) { - auto texture = fixedDynamicState->fPrimitiveProcessorTextures[i]->peekTexture(); - prepareSampledImage(texture, primProc.textureSampler(i).samplerState().filter()); - } - } - GrFragmentProcessor::Iter iter(pipeline); - while (const GrFragmentProcessor* fp = iter.next()) { - for (int i = 0; i < fp->numTextureSamplers(); ++i) { - const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i); - prepareSampledImage(sampler.peekTexture(), sampler.samplerState().filter()); - } - } - GrPrimitiveType primitiveType = meshes[0].primitiveType(); GrMtlPipelineState* pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState, primitiveType); diff --git a/src/gpu/vk/GrVkOpsRenderPass.cpp b/src/gpu/vk/GrVkOpsRenderPass.cpp index 6862436dce..db3d62b557 100644 --- a/src/gpu/vk/GrVkOpsRenderPass.cpp +++ b/src/gpu/vk/GrVkOpsRenderPass.cpp @@ -16,7 +16,6 @@ #include "src/gpu/GrOpFlushState.h" #include "src/gpu/GrPipeline.h" #include "src/gpu/GrRenderTargetPriv.h" -#include "src/gpu/GrTexturePriv.h" #include "src/gpu/vk/GrVkCommandBuffer.h" #include "src/gpu/vk/GrVkCommandPool.h" #include "src/gpu/vk/GrVkGpu.h" @@ -616,42 +615,16 @@ void GrVkOpsRenderPass::onDraw(const GrPrimitiveProcessor& primProc, CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo]; - auto prepareSampledImage = [&](GrTexture* texture, GrSamplerState::Filter filter) { - GrVkTexture* vkTexture = static_cast(texture); - // We may need to resolve the texture first if it is also a render target - GrVkRenderTarget* texRT = static_cast(vkTexture->asRenderTarget()); - if (texRT && texRT->needsResolve()) { - fGpu->resolveRenderTargetNoFlush(texRT); - // TEMPORARY: MSAA resolve will have dirtied mipmaps. This goes away once we switch - // to resolving MSAA from the opsTask as well. - if (GrSamplerState::Filter::kMipMap == filter && - (vkTexture->width() != 1 || vkTexture->height() != 1)) { - SkASSERT(vkTexture->texturePriv().mipMapped() == GrMipMapped::kYes); - SkASSERT(vkTexture->texturePriv().mipMapsAreDirty()); - fGpu->regenerateMipMapLevels(vkTexture); - } - } - - // Ensure mip maps were all resolved ahead of time by the opsTask. - if (GrSamplerState::Filter::kMipMap == filter && - (vkTexture->width() != 1 || vkTexture->height() != 1)) { - SkASSERT(vkTexture->texturePriv().mipMapped() == GrMipMapped::kYes); - SkASSERT(!vkTexture->texturePriv().mipMapsAreDirty()); - } - }; - if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) { for (int m = 0, i = 0; m < meshCount; ++m) { for (int s = 0; s < primProc.numTextureSamplers(); ++s, ++i) { auto texture = dynamicStateArrays->fPrimitiveProcessorTextures[i]->peekTexture(); - prepareSampledImage(texture, primProc.textureSampler(s).samplerState().filter()); this->appendSampledTexture(texture); } } } else { for (int i = 0; i < primProc.numTextureSamplers(); ++i) { auto texture = fixedDynamicState->fPrimitiveProcessorTextures[i]->peekTexture(); - prepareSampledImage(texture, primProc.textureSampler(i).samplerState().filter()); this->appendSampledTexture(texture); } } @@ -659,7 +632,6 @@ void GrVkOpsRenderPass::onDraw(const GrPrimitiveProcessor& primProc, while (const GrFragmentProcessor* fp = iter.next()) { for (int i = 0; i < fp->numTextureSamplers(); ++i) { const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i); - prepareSampledImage(sampler.peekTexture(), sampler.samplerState().filter()); this->appendSampledTexture(sampler.peekTexture()); } }