Move the msaa dirty rect to GrRenderTargetProxy
Bug: skia: Change-Id: I01d7932bce23dffafb86e4eb124c27420acefdd3 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/239192 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
parent
c3f6314e70
commit
16a33c6244
@ -32,7 +32,9 @@ private:
|
||||
// If instantiation failed, at flush time we simply will skip doing the copy.
|
||||
void handleInternalAllocationFailure() override {}
|
||||
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
||||
ExpectedOutcome onMakeClosed(const GrCaps&) override {
|
||||
ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) override {
|
||||
targetUpdateBounds->setXYWH(fDstPoint.x(), fDstPoint.y(), fSrcRect.width(),
|
||||
fSrcRect.height());
|
||||
return ExpectedOutcome::kTargetDirty;
|
||||
}
|
||||
bool onExecute(GrOpFlushState*) override;
|
||||
|
@ -531,7 +531,8 @@ GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[],
|
||||
SkASSERT(rtProxy);
|
||||
if (rtProxy->isMSAADirty()) {
|
||||
SkASSERT(rtProxy->peekRenderTarget());
|
||||
gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), GrGpu::ForExternalIO::kYes);
|
||||
gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), rtProxy->msaaDirtyRect(),
|
||||
rtProxy->origin(), GrGpu::ForExternalIO::kYes);
|
||||
rtProxy->markMSAAResolved();
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "src/gpu/GrDataUtils.h"
|
||||
#include "src/gpu/GrGpuResourcePriv.h"
|
||||
#include "src/gpu/GrMesh.h"
|
||||
#include "src/gpu/GrNativeRect.h"
|
||||
#include "src/gpu/GrPathRendering.h"
|
||||
#include "src/gpu/GrPipeline.h"
|
||||
#include "src/gpu/GrRenderTargetPriv.h"
|
||||
@ -580,8 +581,14 @@ bool GrGpu::regenerateMipMapLevels(GrTexture* texture) {
|
||||
SkASSERT(texture);
|
||||
SkASSERT(this->caps()->mipMapSupport());
|
||||
SkASSERT(texture->texturePriv().mipMapped() == GrMipMapped::kYes);
|
||||
SkASSERT(texture->texturePriv().mipMapsAreDirty());
|
||||
SkASSERT(!texture->asRenderTarget() || !texture->asRenderTarget()->needsResolve());
|
||||
if (!texture->texturePriv().mipMapsAreDirty()) {
|
||||
// This can happen when the proxy expects mipmaps to be dirty, but they are not dirty on the
|
||||
// actual target. This may be caused by things that the drawingManager could not predict,
|
||||
// i.e., ops that don't draw anything, aborting a draw for exceptional circumstances, etc.
|
||||
// NOTE: This goes away once we quit tracking mipmap state on the actual texture.
|
||||
return true;
|
||||
}
|
||||
if (texture->readOnly()) {
|
||||
return false;
|
||||
}
|
||||
@ -597,10 +604,24 @@ void GrGpu::resetTextureBindings() {
|
||||
this->onResetTextureBindings();
|
||||
}
|
||||
|
||||
void GrGpu::resolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) {
|
||||
void GrGpu::resolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||
GrSurfaceOrigin origin, ForExternalIO forExternalIO) {
|
||||
SkASSERT(target);
|
||||
if (!target->needsResolve()) {
|
||||
// This can happen when the proxy expects MSAA to be dirty, but it is not dirty on the
|
||||
// actual target. This may be caused by things that the drawingManager could not predict,
|
||||
// i.e., ops that don't draw anything, aborting a draw for exceptional circumstances, etc.
|
||||
// NOTE: This goes away once we quit tracking dirty state on the actual render target.
|
||||
return;
|
||||
}
|
||||
#ifdef SK_DEBUG
|
||||
auto nativeResolveRect = GrNativeRect::MakeRelativeTo(origin, target->height(), resolveRect);
|
||||
// The proxy will often track a tighter resolve rect than GrRenderTarget, but it should never be
|
||||
// the other way around.
|
||||
SkASSERT(target->getResolveRect().contains(nativeResolveRect.asSkIRect()));
|
||||
#endif
|
||||
this->handleDirtyContext();
|
||||
this->onResolveRenderTarget(target, forExternalIO);
|
||||
this->onResolveRenderTarget(target, resolveRect, origin, forExternalIO);
|
||||
}
|
||||
|
||||
void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
|
||||
|
@ -189,7 +189,8 @@ public:
|
||||
/**
|
||||
* Resolves MSAA.
|
||||
*/
|
||||
void resolveRenderTarget(GrRenderTarget*, ForExternalIO);
|
||||
void resolveRenderTarget(GrRenderTarget*, const SkIRect& resolveRect, GrSurfaceOrigin,
|
||||
ForExternalIO);
|
||||
|
||||
/**
|
||||
* Uses the base of the texture to recompute the contents of the other levels.
|
||||
@ -634,7 +635,8 @@ private:
|
||||
GrGpuBuffer* transferBuffer, size_t offset) = 0;
|
||||
|
||||
// overridden by backend-specific derived class to perform the resolve
|
||||
virtual void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) = 0;
|
||||
virtual void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||
GrSurfaceOrigin resolveOrigin, ForExternalIO) = 0;
|
||||
|
||||
// overridden by backend specific derived class to perform mip map level regeneration.
|
||||
virtual bool onRegenerateMipMapLevels(GrTexture*) = 0;
|
||||
|
@ -504,6 +504,9 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) {
|
||||
void GrOpsTask::setColorLoadOp(GrLoadOp op, const SkPMColor4f& color) {
|
||||
fColorLoadOp = op;
|
||||
fLoadClearColor = color;
|
||||
if (GrLoadOp::kClear == fColorLoadOp) {
|
||||
fTotalBounds.setWH(fTarget->width(), fTarget->height());
|
||||
}
|
||||
}
|
||||
|
||||
bool GrOpsTask::resetForFullscreenClear(CanDiscardPreviousOps canDiscardPreviousOps) {
|
||||
@ -534,6 +537,7 @@ void GrOpsTask::discard() {
|
||||
if (this->isEmpty()) {
|
||||
fColorLoadOp = GrLoadOp::kDiscard;
|
||||
fStencilLoadOp = GrLoadOp::kDiscard;
|
||||
fTotalBounds.setEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -671,6 +675,10 @@ void GrOpsTask::recordOp(
|
||||
return;
|
||||
}
|
||||
|
||||
// Account for this op's bounds before we attempt to combine.
|
||||
// NOTE: The caller should have already called "op->setClippedBounds()" by now, if applicable.
|
||||
fTotalBounds.join(op->bounds());
|
||||
|
||||
// Check if there is an op we can combine with by linearly searching back until we either
|
||||
// 1) check every op
|
||||
// 2) intersect with something
|
||||
@ -747,3 +755,15 @@ void GrOpsTask::forwardCombine(const GrCaps& caps) {
|
||||
}
|
||||
}
|
||||
|
||||
GrRenderTask::ExpectedOutcome GrOpsTask::onMakeClosed(
|
||||
const GrCaps& caps, SkIRect* targetUpdateBounds) {
|
||||
this->forwardCombine(caps);
|
||||
if (!this->isNoOp()) {
|
||||
SkRect clippedContentBounds = SkRect::MakeIWH(fTarget->width(), fTarget->height());
|
||||
if (clippedContentBounds.intersect(fTotalBounds)) {
|
||||
clippedContentBounds.roundOut(targetUpdateBounds);
|
||||
return ExpectedOutcome::kTargetDirty;
|
||||
}
|
||||
}
|
||||
return ExpectedOutcome::kTargetUnchanged;
|
||||
}
|
||||
|
@ -229,10 +229,7 @@ private:
|
||||
|
||||
void forwardCombine(const GrCaps&);
|
||||
|
||||
ExpectedOutcome onMakeClosed(const GrCaps& caps) override {
|
||||
this->forwardCombine(caps);
|
||||
return (this->isNoOp()) ? ExpectedOutcome::kTargetUnchanged : ExpectedOutcome::kTargetDirty;
|
||||
}
|
||||
ExpectedOutcome onMakeClosed(const GrCaps& caps, SkIRect* targetUpdateBounds) override;
|
||||
|
||||
friend class GrRenderTargetContextPriv; // for stencil clip state. TODO: this is invasive
|
||||
|
||||
@ -270,6 +267,8 @@ private:
|
||||
// TODO: We could look into this being a set if we find we're adding a lot of duplicates that is
|
||||
// causing slow downs.
|
||||
SkTArray<GrTextureProxy*, true> fSampledProxies;
|
||||
|
||||
SkRect fTotalBounds = SkRect::MakeEmpty();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -63,17 +63,22 @@ public:
|
||||
|
||||
bool wrapsVkSecondaryCB() const { return fWrapsVkSecondaryCB == WrapsVkSecondaryCB::kYes; }
|
||||
|
||||
void markMSAADirty() {
|
||||
void markMSAADirty(const SkIRect& dirtyRect) {
|
||||
SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(dirtyRect));
|
||||
SkASSERT(this->requiresManualMSAAResolve());
|
||||
fIsMSAADirty = true;
|
||||
fMSAADirtyRect.join(dirtyRect);
|
||||
}
|
||||
void markMSAAResolved() {
|
||||
SkASSERT(this->requiresManualMSAAResolve());
|
||||
fIsMSAADirty = false;
|
||||
fMSAADirtyRect.setEmpty();
|
||||
}
|
||||
bool isMSAADirty() const {
|
||||
SkASSERT(!fIsMSAADirty || this->requiresManualMSAAResolve());
|
||||
return fIsMSAADirty;
|
||||
SkASSERT(fMSAADirtyRect.isEmpty() || this->requiresManualMSAAResolve());
|
||||
return this->requiresManualMSAAResolve() && !fMSAADirtyRect.isEmpty();
|
||||
}
|
||||
const SkIRect& msaaDirtyRect() const {
|
||||
SkASSERT(this->requiresManualMSAAResolve());
|
||||
return fMSAADirtyRect;
|
||||
}
|
||||
|
||||
// TODO: move this to a priv class!
|
||||
@ -160,10 +165,7 @@ 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;
|
||||
SkIRect fMSAADirtyRect = SkIRect::MakeEmpty();
|
||||
// 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,10 +51,12 @@ void GrRenderTask::makeClosed(const GrCaps& caps) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps)) {
|
||||
SkIRect targetUpdateBounds;
|
||||
if (ExpectedOutcome::kTargetDirty == this->onMakeClosed(caps, &targetUpdateBounds)) {
|
||||
SkASSERT(SkIRect::MakeWH(fTarget->width(), fTarget->height()).contains(targetUpdateBounds));
|
||||
if (fTarget->requiresManualMSAAResolve()) {
|
||||
SkASSERT(fTarget->asRenderTargetProxy());
|
||||
fTarget->asRenderTargetProxy()->markMSAADirty();
|
||||
fTarget->asRenderTargetProxy()->markMSAADirty(targetUpdateBounds);
|
||||
}
|
||||
GrTextureProxy* textureProxy = fTarget->asTextureProxy();
|
||||
if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) {
|
||||
|
@ -96,7 +96,12 @@ protected:
|
||||
kTargetDirty,
|
||||
};
|
||||
|
||||
virtual ExpectedOutcome onMakeClosed(const GrCaps&) = 0;
|
||||
// Performs any work to finalize this renderTask prior to execution. If returning
|
||||
// ExpectedOutcome::kTargetDiry, the caller is also responsible to fill out the area it will
|
||||
// modify in targetUpdateBounds.
|
||||
//
|
||||
// targetUpdateBounds must not extend beyond the proxy bounds.
|
||||
virtual ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect* targetUpdateBounds) = 0;
|
||||
|
||||
sk_sp<GrSurfaceProxy> fTarget;
|
||||
|
||||
|
@ -392,12 +392,12 @@ protected:
|
||||
private:
|
||||
// For wrapped resources, 'fFormat', 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always
|
||||
// be filled in from the wrapped resource.
|
||||
GrBackendFormat fFormat;
|
||||
GrPixelConfig fConfig;
|
||||
const GrBackendFormat fFormat;
|
||||
const GrPixelConfig fConfig;
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
GrSurfaceOrigin fOrigin;
|
||||
GrSwizzle fTextureSwizzle;
|
||||
const GrSurfaceOrigin fOrigin;
|
||||
const GrSwizzle fTextureSwizzle;
|
||||
|
||||
SkBackingFit fFit; // always kApprox for lazy-callback resources
|
||||
// always kExact for wrapped resources
|
||||
|
@ -22,7 +22,10 @@ GrTextureResolveRenderTask::~GrTextureResolveRenderTask() {
|
||||
}
|
||||
|
||||
void GrTextureResolveRenderTask::addProxy(
|
||||
sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
|
||||
sk_sp<GrSurfaceProxy> proxyHolder, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
|
||||
fResolves.emplace_back(std::move(proxyHolder), flags);
|
||||
GrSurfaceProxy* proxy = fResolves.back().fProxy.get();
|
||||
|
||||
// Ensure the last render task that operated on the proxy is closed. That's where msaa and
|
||||
// mipmaps should have been marked dirty.
|
||||
SkASSERT(!proxy->getLastRenderTask() || proxy->getLastRenderTask()->isClosed());
|
||||
@ -32,6 +35,7 @@ void GrTextureResolveRenderTask::addProxy(
|
||||
GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
|
||||
SkASSERT(renderTargetProxy);
|
||||
SkASSERT(renderTargetProxy->isMSAADirty());
|
||||
fResolves.back().fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
|
||||
renderTargetProxy->markMSAAResolved();
|
||||
}
|
||||
|
||||
@ -44,10 +48,8 @@ void GrTextureResolveRenderTask::addProxy(
|
||||
|
||||
// Add the proxy as a dependency: We will read the existing contents of this texture while
|
||||
// generating mipmap levels and/or resolving MSAA.
|
||||
this->addDependency(proxy.get(), GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
|
||||
this->addDependency(proxy, GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
|
||||
proxy->setLastRenderTask(this);
|
||||
|
||||
fResolves.emplace_back(std::move(proxy), flags);
|
||||
}
|
||||
|
||||
void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
|
||||
@ -69,7 +71,10 @@ bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
|
||||
// peekRenderTarget might be null if there was an instantiation error.
|
||||
GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget();
|
||||
if (renderTarget && renderTarget->needsResolve()) {
|
||||
flushState->gpu()->resolveRenderTarget(renderTarget, GrGpu::ForExternalIO::kNo);
|
||||
flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect,
|
||||
resolve.fProxy->origin(),
|
||||
GrGpu::ForExternalIO::kNo);
|
||||
SkASSERT(!renderTarget->needsResolve());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,6 +85,7 @@ bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
|
||||
GrTexture* texture = resolve.fProxy->peekTexture();
|
||||
if (texture && texture->texturePriv().mipMapsAreDirty()) {
|
||||
flushState->gpu()->regenerateMipMapLevels(texture);
|
||||
SkASSERT(!texture->texturePriv().mipMapsAreDirty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ private:
|
||||
}
|
||||
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
||||
|
||||
ExpectedOutcome onMakeClosed(const GrCaps&) override {
|
||||
ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
|
||||
return ExpectedOutcome::kTargetUnchanged;
|
||||
}
|
||||
|
||||
@ -43,6 +43,7 @@ private:
|
||||
: fProxy(std::move(proxy)), fFlags(flags) {}
|
||||
sk_sp<GrSurfaceProxy> fProxy;
|
||||
GrSurfaceProxy::ResolveFlags fFlags;
|
||||
SkIRect fMSAAResolveRect;
|
||||
};
|
||||
|
||||
SkSTArray<4, Resolve> fResolves;
|
||||
|
@ -36,7 +36,7 @@ private:
|
||||
void handleInternalAllocationFailure() override {}
|
||||
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
||||
|
||||
ExpectedOutcome onMakeClosed(const GrCaps&) override {
|
||||
ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
|
||||
return ExpectedOutcome::kTargetUnchanged;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ private:
|
||||
void handleInternalAllocationFailure() override {}
|
||||
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
||||
|
||||
ExpectedOutcome onMakeClosed(const GrCaps&) override {
|
||||
ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
|
||||
return ExpectedOutcome::kTargetUnchanged;
|
||||
}
|
||||
|
||||
|
@ -154,8 +154,8 @@ private:
|
||||
GrColorType surfaceColorType, GrColorType bufferColorType,
|
||||
GrGpuBuffer* transferBuffer, size_t offset) override;
|
||||
|
||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override {
|
||||
}
|
||||
void onResolveRenderTarget(GrRenderTarget*, const SkIRect&, GrSurfaceOrigin,
|
||||
ForExternalIO) override {}
|
||||
|
||||
bool onRegenerateMipMapLevels(GrTexture*) override;
|
||||
|
||||
|
@ -1957,7 +1957,7 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
|
||||
this->flushRenderTargetNoColorWrites(renderTarget);
|
||||
break;
|
||||
case GrGLRenderTarget::kCanResolve_ResolveType:
|
||||
this->onResolveRenderTarget(renderTarget, ForExternalIO::kNo);
|
||||
SkASSERT(!renderTarget->needsResolve());
|
||||
// we don't track the state of the READ FBO ID.
|
||||
this->bindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID());
|
||||
break;
|
||||
@ -2281,7 +2281,8 @@ void GrGLGpu::sendIndexedInstancedMeshToGpu(GrPrimitiveType primitiveType,
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) {
|
||||
void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||
GrSurfaceOrigin resolveOrigin, ForExternalIO) {
|
||||
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
|
||||
if (rt->needsResolve()) {
|
||||
// Some extensions automatically resolves the texture when it is read.
|
||||
@ -2294,15 +2295,11 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) {
|
||||
// make sure we go through flushRenderTarget() since we've modified
|
||||
// the bound DRAW FBO ID.
|
||||
fHWBoundRenderTargetUniqueID.makeInvalid();
|
||||
const SkIRect dirtyRect = rt->getResolveRect();
|
||||
// The dirty rect tracked on the RT is always stored in the native coordinates of the
|
||||
// surface. Choose kTopLeft so no adjustments are made
|
||||
static constexpr auto kDirtyRectOrigin = kTopLeft_GrSurfaceOrigin;
|
||||
if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
|
||||
// Apple's extension uses the scissor as the blit bounds.
|
||||
GrScissorState scissorState;
|
||||
scissorState.set(dirtyRect);
|
||||
this->flushScissor(scissorState, rt->width(), rt->height(), kDirtyRectOrigin);
|
||||
scissorState.set(resolveRect);
|
||||
this->flushScissor(scissorState, rt->width(), rt->height(), resolveOrigin);
|
||||
this->disableWindowRectangles();
|
||||
GL_CALL(ResolveMultisampleFramebuffer());
|
||||
} else {
|
||||
@ -2315,7 +2312,7 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) {
|
||||
t = target->height();
|
||||
} else {
|
||||
auto rect = GrNativeRect::MakeRelativeTo(
|
||||
kDirtyRectOrigin, rt->height(), dirtyRect);
|
||||
resolveOrigin, rt->height(), resolveRect);
|
||||
l = rect.fX;
|
||||
b = rect.fY;
|
||||
r = rect.fX + rect.fWidth;
|
||||
@ -2536,6 +2533,7 @@ static void get_gl_swizzle_values(const GrSwizzle& swizzle, GrGLenum glValues[4]
|
||||
void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwizzle& swizzle,
|
||||
GrGLTexture* texture) {
|
||||
SkASSERT(texture);
|
||||
SkASSERT(!texture->asRenderTarget() || !texture->asRenderTarget()->needsResolve());
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
if (!this->caps()->npotTextureTileSupport()) {
|
||||
@ -2547,14 +2545,6 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwiz
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we created a rt/tex and rendered to it without using a texture and now we're texturing
|
||||
// from the rt it will still be the last bound texture, but it needs resolving. So keep this
|
||||
// out of the "last != next" check.
|
||||
GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget());
|
||||
if (texRT) {
|
||||
this->onResolveRenderTarget(texRT, ForExternalIO::kNo);
|
||||
}
|
||||
|
||||
GrGpuResource::UniqueID textureID = texture->uniqueID();
|
||||
GrGLenum target = texture->target();
|
||||
if (fHWTextureUnitBindings[unitIdx].boundID(target) != textureID) {
|
||||
|
@ -258,7 +258,8 @@ private:
|
||||
// PIXEL_UNPACK_BUFFER is unbound.
|
||||
void unbindCpuToGpuXferBuffer();
|
||||
|
||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override;
|
||||
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||
GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
|
||||
|
||||
bool onRegenerateMipMapLevels(GrTexture*) override;
|
||||
|
||||
|
@ -118,7 +118,8 @@ private:
|
||||
|
||||
bool onRegenerateMipMapLevels(GrTexture*) override { return true; }
|
||||
|
||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override {
|
||||
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, GrSurfaceOrigin,
|
||||
ForExternalIO) override {
|
||||
target->flagAsResolved();
|
||||
}
|
||||
|
||||
|
@ -108,10 +108,6 @@ public:
|
||||
this->didWriteToSurface(surface, origin, bounds);
|
||||
}
|
||||
|
||||
void resolveRenderTargetNoFlush(GrRenderTarget* target) {
|
||||
this->internalResolveRenderTarget(target, false);
|
||||
}
|
||||
|
||||
private:
|
||||
GrMtlGpu(GrContext* context, const GrContextOptions& options,
|
||||
id<MTLDevice> device, id<MTLCommandQueue> queue, MTLFeatureSet featureSet);
|
||||
@ -185,11 +181,9 @@ private:
|
||||
|
||||
bool onRegenerateMipMapLevels(GrTexture*) override;
|
||||
|
||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) override {
|
||||
this->internalResolveRenderTarget(target, ForExternalIO::kYes == forExternalIO);
|
||||
}
|
||||
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||
GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
|
||||
|
||||
void internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit);
|
||||
void resolveTexture(id<MTLTexture> colorTexture, id<MTLTexture> resolveTexture);
|
||||
|
||||
void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
|
||||
|
@ -1053,7 +1053,7 @@ bool GrMtlGpu::onReadPixels(GrSurface* surface, int left, int top, int width, in
|
||||
mtlTexture = rt->mtlColorTexture();
|
||||
break;
|
||||
case GrMtlRenderTarget::kCanResolve_ResolveType:
|
||||
this->resolveRenderTargetNoFlush(rt);
|
||||
SkASSERT(!rt->needsResolve());
|
||||
mtlTexture = rt->mtlResolveTexture();
|
||||
break;
|
||||
default:
|
||||
@ -1188,13 +1188,17 @@ void GrMtlGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void GrMtlGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
|
||||
void GrMtlGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, GrSurfaceOrigin,
|
||||
ForExternalIO forExternalIO) {
|
||||
if (target->needsResolve()) {
|
||||
this->resolveTexture(static_cast<GrMtlRenderTarget*>(target)->mtlResolveTexture(),
|
||||
static_cast<GrMtlRenderTarget*>(target)->mtlColorTexture());
|
||||
target->flagAsResolved();
|
||||
|
||||
if (requiresSubmit) {
|
||||
if (ForExternalIO::kYes == forExternalIO) {
|
||||
// This resolve is called when we are preparing an msaa surface for external I/O. It is
|
||||
// called after flushing, so we need to make sure we submit the command buffer after
|
||||
// doing the resolve so that the resolve actually happens.
|
||||
this->submitCommandBuffer(kSkip_SyncQueue);
|
||||
}
|
||||
}
|
||||
|
@ -535,18 +535,6 @@ bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int wi
|
||||
if (rt->wrapsSecondaryCommandBuffer()) {
|
||||
return false;
|
||||
}
|
||||
// resolve the render target if necessary
|
||||
switch (rt->getResolveType()) {
|
||||
case GrVkRenderTarget::kCantResolve_ResolveType:
|
||||
return false;
|
||||
case GrVkRenderTarget::kAutoResolves_ResolveType:
|
||||
break;
|
||||
case GrVkRenderTarget::kCanResolve_ResolveType:
|
||||
this->resolveRenderTargetNoFlush(rt);
|
||||
break;
|
||||
default:
|
||||
SK_ABORT("Unknown resolve type");
|
||||
}
|
||||
srcImage = rt;
|
||||
} else {
|
||||
srcImage = static_cast<GrVkTexture*>(surface->asTexture());
|
||||
@ -617,21 +605,24 @@ void GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect&
|
||||
fCurrentCmdBuffer->resolveImage(this, *src->msaaImage(), *dstImage, 1, &resolveInfo);
|
||||
}
|
||||
|
||||
void GrVkGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
|
||||
if (target->needsResolve()) {
|
||||
SkASSERT(target->numSamples() > 1);
|
||||
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
|
||||
SkASSERT(rt->msaaImage());
|
||||
void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||
GrSurfaceOrigin resolveOrigin, ForExternalIO forExternalIO) {
|
||||
SkASSERT(target->numSamples() > 1);
|
||||
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
|
||||
SkASSERT(rt->msaaImage());
|
||||
|
||||
const SkIRect& srcRect = rt->getResolveRect();
|
||||
auto nativeResolveRect = GrNativeRect::MakeRelativeTo(
|
||||
resolveOrigin, target->height(), resolveRect);
|
||||
this->resolveImage(target, rt, nativeResolveRect.asSkIRect(),
|
||||
SkIPoint::Make(nativeResolveRect.fX, nativeResolveRect.fY));
|
||||
|
||||
this->resolveImage(target, rt, srcRect, SkIPoint::Make(srcRect.fLeft, srcRect.fTop));
|
||||
rt->flagAsResolved();
|
||||
|
||||
rt->flagAsResolved();
|
||||
|
||||
if (requiresSubmit) {
|
||||
this->submitCommandBuffer(kSkip_SyncQueue);
|
||||
}
|
||||
if (ForExternalIO::kYes == forExternalIO) {
|
||||
// This resolve is called when we are preparing an msaa surface for external I/O. It is
|
||||
// called after flushing, so we need to make sure we submit the command buffer after doing
|
||||
// the resolve so that the resolve actually happens.
|
||||
this->submitCommandBuffer(kSkip_SyncQueue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2232,18 +2223,6 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int
|
||||
if (rt->wrapsSecondaryCommandBuffer()) {
|
||||
return false;
|
||||
}
|
||||
// resolve the render target if necessary
|
||||
switch (rt->getResolveType()) {
|
||||
case GrVkRenderTarget::kCantResolve_ResolveType:
|
||||
return false;
|
||||
case GrVkRenderTarget::kAutoResolves_ResolveType:
|
||||
break;
|
||||
case GrVkRenderTarget::kCanResolve_ResolveType:
|
||||
this->resolveRenderTargetNoFlush(rt);
|
||||
break;
|
||||
default:
|
||||
SK_ABORT("Unknown resolve type");
|
||||
}
|
||||
image = rt;
|
||||
} else {
|
||||
image = static_cast<GrVkTexture*>(surface->asTexture());
|
||||
|
@ -119,13 +119,8 @@ public:
|
||||
|
||||
bool onRegenerateMipMapLevels(GrTexture* tex) override;
|
||||
|
||||
void resolveRenderTargetNoFlush(GrRenderTarget* target) {
|
||||
this->internalResolveRenderTarget(target, false);
|
||||
}
|
||||
|
||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) override {
|
||||
this->internalResolveRenderTarget(target, ForExternalIO::kYes == forExternalIO);
|
||||
}
|
||||
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||
GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
|
||||
|
||||
void submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer>);
|
||||
|
||||
@ -248,8 +243,6 @@ private:
|
||||
void submitCommandBuffer(SyncQueue sync, GrGpuFinishedProc finishedProc = nullptr,
|
||||
GrGpuFinishedContext finishedContext = nullptr);
|
||||
|
||||
void internalResolveRenderTarget(GrRenderTarget*, bool requiresSubmit);
|
||||
|
||||
void copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
|
||||
GrVkImage* srcImage, const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
|
Loading…
Reference in New Issue
Block a user