Revert "Initiate MSAA resolves during DAG generation"

This reverts commit 804f6a0fe7.

Reason for revert: <INSERT REASONING HERE>

Original change's description:
> 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>

TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com,csmartdalton@google.com

Change-Id: Ife557caa840edfb64cbcafc272dc3012cfb43702
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/237242
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2019-08-26 20:18:44 +00:00 committed by Skia Commit-Bot
parent 03fccf4857
commit 6f31cc3882
14 changed files with 160 additions and 170 deletions

View File

@ -1466,12 +1466,11 @@ 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,
kMSAA = 1 << 0, // Blit and resolve an internal MSAA render buffer into the texture.
kMipMaps = 1 << 1, // Regenerate all mipmap levels.
kMipMaps = 1 << 0, // Regenerate all mipmap levels.
// TODO: kMSAA = 1 << 1 // Blit the MSAA render buffer into a standard texture.
};
GR_MAKE_BITFIELD_CLASS_OPS(GrTextureResolveFlags)

View File

@ -294,10 +294,6 @@ 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());
@ -513,30 +509,19 @@ GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[],
GrSemaphoresSubmitted result = this->flush(proxies, numProxies, access, info,
GrPrepareForExternalIORequests());
for (int i = 0; i < numProxies; ++i) {
GrSurfaceProxy* proxy = proxies[i];
if (!proxy->isInstantiated()) {
if (!proxies[i]->isInstantiated()) {
return result;
}
// 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();
}
GrSurface* surface = proxies[i]->peekSurface();
if (auto* rt = surface->asRenderTarget()) {
gpu->resolveRenderTarget(rt);
}
// 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 = proxy->asTextureProxy()) {
if (auto* textureProxy = proxies[i]->asTextureProxy()) {
if (textureProxy->mipMapsAreDirty()) {
SkASSERT(textureProxy->peekTexture());
gpu->regenerateMipMapLevels(textureProxy->peekTexture());
textureProxy->markMipMapsClean();
}

View File

@ -14,7 +14,6 @@
#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,
@ -41,18 +40,6 @@ 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*);
void addTextureResolveTask(sk_sp<GrTextureProxy>, GrTextureResolveFlags);
std::unique_ptr<GrRenderTargetContext> makeRenderTargetContext(sk_sp<GrSurfaceProxy>,
GrColorType,
sk_sp<SkColorSpace>,
const SkSurfaceProps*);
// Proxy unique key management. See GrProxyProvider.h.
bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);

View File

@ -17,7 +17,6 @@
#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);
@ -34,51 +33,6 @@ 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,
@ -91,12 +45,13 @@ 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) {
@ -125,9 +80,6 @@ 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,19 +63,6 @@ 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;
@ -141,10 +128,6 @@ 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,10 +51,6 @@ 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();
@ -97,11 +93,8 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapp
GrRenderTask* dependedOnTask = dependedOn->getLastRenderTask();
if (dependedOnTask == this) {
// 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.
// self-read - presumably for dst reads. We can't make it closed in the self-read case.
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;
@ -114,16 +107,6 @@ 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);
@ -131,16 +114,14 @@ 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 msaa to resolve and/or mipmaps to regenerate?
if (GrTextureResolveFlags::kNone != textureResolveFlags) {
// Does this proxy have mipmaps that need to be regenerated?
if (GrMipMapped::kYes == mipMapped && textureProxy->mipMapsAreDirty()) {
// Create a renderTask that resolves the texture's mipmap data.
GrRenderTask* textureResolveTask = textureResolveManager.newTextureResolveRenderTask(
sk_ref_sp(textureProxy), textureResolveFlags, caps);
sk_ref_sp(textureProxy), GrTextureResolveFlags::kMipMaps, caps);
// The GrTextureResolveRenderTask factory should have called addDependency (in this
// instance, recursively) on the textureProxy.

View File

@ -10,7 +10,6 @@
#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"
@ -20,24 +19,6 @@ 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.
//
@ -49,7 +30,13 @@ sk_sp<GrRenderTask> GrTextureResolveRenderTask::Make(
// We only resolve the texture; nobody should try to do anything else with this opsTask.
resolveTask->makeClosed(caps);
return std::move(resolveTask);
if (GrTextureResolveFlags::kMipMaps & flags) {
SkASSERT(GrMipMapped::kYes == textureProxyPtr->mipMapped());
SkASSERT(textureProxyPtr->mipMapsAreDirty());
textureProxyPtr->markMipMapsClean();
}
return resolveTask;
}
void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
@ -62,17 +49,10 @@ void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc
}
bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
// Resolve msaa before regenerating mipmaps.
if (GrTextureResolveFlags::kMSAA & fResolveFlags) {
GrRenderTarget* renderTarget = fTarget->peekRenderTarget();
SkASSERT(renderTarget);
SkASSERT(renderTarget->needsResolve());
flushState->gpu()->resolveRenderTarget(renderTarget);
}
GrTexture* texture = fTarget->peekTexture();
SkASSERT(texture);
if (GrTextureResolveFlags::kMipMaps & fResolveFlags) {
GrTexture* texture = fTarget->peekTexture();
SkASSERT(texture);
SkASSERT(texture->texturePriv().mipMapsAreDirty());
flushState->gpu()->regenerateMipMapLevels(texture);
}

View File

@ -588,10 +588,6 @@ 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,6 +1868,51 @@ 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,
@ -1876,23 +1921,28 @@ bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget,
const GrPipeline::DynamicStateArrays* dynamicStateArrays,
int dynamicStateArraysLength,
bool willDrawPoints) {
const GrTextureProxy* const* primProcProxies = nullptr;
const GrTextureProxy* const* primProcProxiesForMipRegen = nullptr;
const GrTextureProxy* const* primProcProxiesToBind = nullptr;
int numPrimProcTextureSets = 1; // number of texture per prim proc sampler.
if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) {
primProcProxies = dynamicStateArrays->fPrimitiveProcessorTextures;
primProcProxiesForMipRegen = dynamicStateArrays->fPrimitiveProcessorTextures;
numPrimProcTextureSets = dynamicStateArraysLength;
} else if (fixedDynamicState && fixedDynamicState->fPrimitiveProcessorTextures) {
primProcProxies = fixedDynamicState->fPrimitiveProcessorTextures;
primProcProxiesForMipRegen = fixedDynamicState->fPrimitiveProcessorTextures;
primProcProxiesToBind = fixedDynamicState->fPrimitiveProcessorTextures;
}
SkASSERT(SkToBool(primProcProxies) == SkToBool(primProc.numTextureSamplers()));
SkASSERT(SkToBool(primProcProxiesForMipRegen) == SkToBool(primProc.numTextureSamplers()));
sk_sp<GrGLProgram> program(fProgramCache->refProgram(
this, renderTarget, origin, primProc, primProcProxies, pipeline, willDrawPoints));
sk_sp<GrGLProgram> program(fProgramCache->refProgram(this, renderTarget, origin, primProc,
primProcProxiesForMipRegen,
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,6 +270,15 @@ 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 { target->flagAsResolved(); }
void onResolveRenderTarget(GrRenderTarget* target) override { return; }
void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
const GrFlushInfo& info, const GrPrepareForExternalIORequests&) override {

View File

@ -10,6 +10,7 @@
#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"
@ -95,6 +96,45 @@ 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,6 +16,7 @@
#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"
@ -615,16 +616,42 @@ 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);
}
}
@ -632,6 +659,7 @@ 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());
}
}