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 <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Chris Dalton 2019-08-26 12:07:30 -06:00 committed by Skia Commit-Bot
parent 464eb78e44
commit 804f6a0fe7
14 changed files with 170 additions and 160 deletions

View File

@ -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)

View File

@ -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();
}

View File

@ -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<GrRenderTargetContext> GrOnFlushResourceProvider::makeRenderTargetContext(
sk_sp<GrSurfaceProxy> proxy, GrColorType colorType, sk_sp<SkColorSpace> colorSpace,
@ -40,6 +41,18 @@ std::unique_ptr<GrRenderTargetContext> GrOnFlushResourceProvider::makeRenderTarg
return renderTargetContext;
}
void GrOnFlushResourceProvider::addTextureResolveTask(sk_sp<GrTextureProxy> 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();

View File

@ -63,10 +63,10 @@ class GrOnFlushResourceProvider {
public:
explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {}
std::unique_ptr<GrRenderTargetContext> makeRenderTargetContext(sk_sp<GrSurfaceProxy>,
GrColorType,
sk_sp<SkColorSpace>,
const SkSurfaceProps*);
std::unique_ptr<GrRenderTargetContext> makeRenderTargetContext(
sk_sp<GrSurfaceProxy>, GrColorType, sk_sp<SkColorSpace>, const SkSurfaceProps*);
void addTextureResolveTask(sk_sp<GrTextureProxy>, GrTextureResolveFlags);
// Proxy unique key management. See GrProxyProvider.h.
bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);

View File

@ -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()) {

View File

@ -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

View File

@ -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.

View File

@ -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<GrRenderTask> GrTextureResolveRenderTask::Make(
sk_sp<GrTextureResolveRenderTask> 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<GrRenderTask> 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);
}

View File

@ -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);

View File

@ -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<GrGLProgram> program(fProgramCache->refProgram(this, renderTarget, origin, primProc,
primProcProxiesForMipRegen,
pipeline, willDrawPoints));
sk_sp<GrGLProgram> 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));

View File

@ -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

View File

@ -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 {

View File

@ -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<GrMtlTexture*>(texture);
// We may need to resolve the texture first if it is also a render target
GrMtlRenderTarget* texRT = static_cast<GrMtlRenderTarget*>(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);

View File

@ -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<GrVkTexture*>(texture);
// We may need to resolve the texture first if it is also a render target
GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(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());
}
}