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:
parent
464eb78e44
commit
804f6a0fe7
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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*);
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user