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.
|
// If instantiation failed, at flush time we simply will skip doing the copy.
|
||||||
void handleInternalAllocationFailure() override {}
|
void handleInternalAllocationFailure() override {}
|
||||||
void gatherProxyIntervals(GrResourceAllocator*) const 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;
|
return ExpectedOutcome::kTargetDirty;
|
||||||
}
|
}
|
||||||
bool onExecute(GrOpFlushState*) override;
|
bool onExecute(GrOpFlushState*) override;
|
||||||
|
@ -531,7 +531,8 @@ GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[],
|
|||||||
SkASSERT(rtProxy);
|
SkASSERT(rtProxy);
|
||||||
if (rtProxy->isMSAADirty()) {
|
if (rtProxy->isMSAADirty()) {
|
||||||
SkASSERT(rtProxy->peekRenderTarget());
|
SkASSERT(rtProxy->peekRenderTarget());
|
||||||
gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), GrGpu::ForExternalIO::kYes);
|
gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), rtProxy->msaaDirtyRect(),
|
||||||
|
rtProxy->origin(), GrGpu::ForExternalIO::kYes);
|
||||||
rtProxy->markMSAAResolved();
|
rtProxy->markMSAAResolved();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "src/gpu/GrDataUtils.h"
|
#include "src/gpu/GrDataUtils.h"
|
||||||
#include "src/gpu/GrGpuResourcePriv.h"
|
#include "src/gpu/GrGpuResourcePriv.h"
|
||||||
#include "src/gpu/GrMesh.h"
|
#include "src/gpu/GrMesh.h"
|
||||||
|
#include "src/gpu/GrNativeRect.h"
|
||||||
#include "src/gpu/GrPathRendering.h"
|
#include "src/gpu/GrPathRendering.h"
|
||||||
#include "src/gpu/GrPipeline.h"
|
#include "src/gpu/GrPipeline.h"
|
||||||
#include "src/gpu/GrRenderTargetPriv.h"
|
#include "src/gpu/GrRenderTargetPriv.h"
|
||||||
@ -580,8 +581,14 @@ bool GrGpu::regenerateMipMapLevels(GrTexture* texture) {
|
|||||||
SkASSERT(texture);
|
SkASSERT(texture);
|
||||||
SkASSERT(this->caps()->mipMapSupport());
|
SkASSERT(this->caps()->mipMapSupport());
|
||||||
SkASSERT(texture->texturePriv().mipMapped() == GrMipMapped::kYes);
|
SkASSERT(texture->texturePriv().mipMapped() == GrMipMapped::kYes);
|
||||||
SkASSERT(texture->texturePriv().mipMapsAreDirty());
|
|
||||||
SkASSERT(!texture->asRenderTarget() || !texture->asRenderTarget()->needsResolve());
|
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()) {
|
if (texture->readOnly()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -597,10 +604,24 @@ void GrGpu::resetTextureBindings() {
|
|||||||
this->onResetTextureBindings();
|
this->onResetTextureBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGpu::resolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) {
|
void GrGpu::resolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||||
|
GrSurfaceOrigin origin, ForExternalIO forExternalIO) {
|
||||||
SkASSERT(target);
|
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->handleDirtyContext();
|
||||||
this->onResolveRenderTarget(target, forExternalIO);
|
this->onResolveRenderTarget(target, resolveRect, origin, forExternalIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
|
void GrGpu::didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
|
||||||
|
@ -189,7 +189,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Resolves MSAA.
|
* 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.
|
* 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;
|
GrGpuBuffer* transferBuffer, size_t offset) = 0;
|
||||||
|
|
||||||
// overridden by backend-specific derived class to perform the resolve
|
// 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.
|
// overridden by backend specific derived class to perform mip map level regeneration.
|
||||||
virtual bool onRegenerateMipMapLevels(GrTexture*) = 0;
|
virtual bool onRegenerateMipMapLevels(GrTexture*) = 0;
|
||||||
|
@ -504,6 +504,9 @@ bool GrOpsTask::onExecute(GrOpFlushState* flushState) {
|
|||||||
void GrOpsTask::setColorLoadOp(GrLoadOp op, const SkPMColor4f& color) {
|
void GrOpsTask::setColorLoadOp(GrLoadOp op, const SkPMColor4f& color) {
|
||||||
fColorLoadOp = op;
|
fColorLoadOp = op;
|
||||||
fLoadClearColor = color;
|
fLoadClearColor = color;
|
||||||
|
if (GrLoadOp::kClear == fColorLoadOp) {
|
||||||
|
fTotalBounds.setWH(fTarget->width(), fTarget->height());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrOpsTask::resetForFullscreenClear(CanDiscardPreviousOps canDiscardPreviousOps) {
|
bool GrOpsTask::resetForFullscreenClear(CanDiscardPreviousOps canDiscardPreviousOps) {
|
||||||
@ -534,6 +537,7 @@ void GrOpsTask::discard() {
|
|||||||
if (this->isEmpty()) {
|
if (this->isEmpty()) {
|
||||||
fColorLoadOp = GrLoadOp::kDiscard;
|
fColorLoadOp = GrLoadOp::kDiscard;
|
||||||
fStencilLoadOp = GrLoadOp::kDiscard;
|
fStencilLoadOp = GrLoadOp::kDiscard;
|
||||||
|
fTotalBounds.setEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,6 +675,10 @@ void GrOpsTask::recordOp(
|
|||||||
return;
|
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
|
// Check if there is an op we can combine with by linearly searching back until we either
|
||||||
// 1) check every op
|
// 1) check every op
|
||||||
// 2) intersect with something
|
// 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&);
|
void forwardCombine(const GrCaps&);
|
||||||
|
|
||||||
ExpectedOutcome onMakeClosed(const GrCaps& caps) override {
|
ExpectedOutcome onMakeClosed(const GrCaps& caps, SkIRect* targetUpdateBounds) override;
|
||||||
this->forwardCombine(caps);
|
|
||||||
return (this->isNoOp()) ? ExpectedOutcome::kTargetUnchanged : ExpectedOutcome::kTargetDirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class GrRenderTargetContextPriv; // for stencil clip state. TODO: this is invasive
|
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
|
// TODO: We could look into this being a set if we find we're adding a lot of duplicates that is
|
||||||
// causing slow downs.
|
// causing slow downs.
|
||||||
SkTArray<GrTextureProxy*, true> fSampledProxies;
|
SkTArray<GrTextureProxy*, true> fSampledProxies;
|
||||||
|
|
||||||
|
SkRect fTotalBounds = SkRect::MakeEmpty();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,17 +63,22 @@ public:
|
|||||||
|
|
||||||
bool wrapsVkSecondaryCB() const { return fWrapsVkSecondaryCB == WrapsVkSecondaryCB::kYes; }
|
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());
|
SkASSERT(this->requiresManualMSAAResolve());
|
||||||
fIsMSAADirty = true;
|
fMSAADirtyRect.join(dirtyRect);
|
||||||
}
|
}
|
||||||
void markMSAAResolved() {
|
void markMSAAResolved() {
|
||||||
SkASSERT(this->requiresManualMSAAResolve());
|
SkASSERT(this->requiresManualMSAAResolve());
|
||||||
fIsMSAADirty = false;
|
fMSAADirtyRect.setEmpty();
|
||||||
}
|
}
|
||||||
bool isMSAADirty() const {
|
bool isMSAADirty() const {
|
||||||
SkASSERT(!fIsMSAADirty || this->requiresManualMSAAResolve());
|
SkASSERT(fMSAADirtyRect.isEmpty() || this->requiresManualMSAAResolve());
|
||||||
return fIsMSAADirty;
|
return this->requiresManualMSAAResolve() && !fMSAADirtyRect.isEmpty();
|
||||||
|
}
|
||||||
|
const SkIRect& msaaDirtyRect() const {
|
||||||
|
SkASSERT(this->requiresManualMSAAResolve());
|
||||||
|
return fMSAADirtyRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this to a priv class!
|
// TODO: move this to a priv class!
|
||||||
@ -160,10 +165,7 @@ private:
|
|||||||
int8_t fNumStencilSamples = 0;
|
int8_t fNumStencilSamples = 0;
|
||||||
WrapsVkSecondaryCB fWrapsVkSecondaryCB;
|
WrapsVkSecondaryCB fWrapsVkSecondaryCB;
|
||||||
GrSwizzle fOutputSwizzle;
|
GrSwizzle fOutputSwizzle;
|
||||||
// Indicates whether some sub-rectangle of the render target requires MSAA resolve. We currently
|
SkIRect fMSAADirtyRect = SkIRect::MakeEmpty();
|
||||||
// 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
|
// 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
|
// 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
|
// 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;
|
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()) {
|
if (fTarget->requiresManualMSAAResolve()) {
|
||||||
SkASSERT(fTarget->asRenderTargetProxy());
|
SkASSERT(fTarget->asRenderTargetProxy());
|
||||||
fTarget->asRenderTargetProxy()->markMSAADirty();
|
fTarget->asRenderTargetProxy()->markMSAADirty(targetUpdateBounds);
|
||||||
}
|
}
|
||||||
GrTextureProxy* textureProxy = fTarget->asTextureProxy();
|
GrTextureProxy* textureProxy = fTarget->asTextureProxy();
|
||||||
if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) {
|
if (textureProxy && GrMipMapped::kYes == textureProxy->mipMapped()) {
|
||||||
|
@ -96,7 +96,12 @@ protected:
|
|||||||
kTargetDirty,
|
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;
|
sk_sp<GrSurfaceProxy> fTarget;
|
||||||
|
|
||||||
|
@ -392,12 +392,12 @@ protected:
|
|||||||
private:
|
private:
|
||||||
// For wrapped resources, 'fFormat', 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always
|
// For wrapped resources, 'fFormat', 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always
|
||||||
// be filled in from the wrapped resource.
|
// be filled in from the wrapped resource.
|
||||||
GrBackendFormat fFormat;
|
const GrBackendFormat fFormat;
|
||||||
GrPixelConfig fConfig;
|
const GrPixelConfig fConfig;
|
||||||
int fWidth;
|
int fWidth;
|
||||||
int fHeight;
|
int fHeight;
|
||||||
GrSurfaceOrigin fOrigin;
|
const GrSurfaceOrigin fOrigin;
|
||||||
GrSwizzle fTextureSwizzle;
|
const GrSwizzle fTextureSwizzle;
|
||||||
|
|
||||||
SkBackingFit fFit; // always kApprox for lazy-callback resources
|
SkBackingFit fFit; // always kApprox for lazy-callback resources
|
||||||
// always kExact for wrapped resources
|
// always kExact for wrapped resources
|
||||||
|
@ -22,7 +22,10 @@ GrTextureResolveRenderTask::~GrTextureResolveRenderTask() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureResolveRenderTask::addProxy(
|
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
|
// Ensure the last render task that operated on the proxy is closed. That's where msaa and
|
||||||
// mipmaps should have been marked dirty.
|
// mipmaps should have been marked dirty.
|
||||||
SkASSERT(!proxy->getLastRenderTask() || proxy->getLastRenderTask()->isClosed());
|
SkASSERT(!proxy->getLastRenderTask() || proxy->getLastRenderTask()->isClosed());
|
||||||
@ -32,6 +35,7 @@ void GrTextureResolveRenderTask::addProxy(
|
|||||||
GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
|
GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
|
||||||
SkASSERT(renderTargetProxy);
|
SkASSERT(renderTargetProxy);
|
||||||
SkASSERT(renderTargetProxy->isMSAADirty());
|
SkASSERT(renderTargetProxy->isMSAADirty());
|
||||||
|
fResolves.back().fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
|
||||||
renderTargetProxy->markMSAAResolved();
|
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
|
// Add the proxy as a dependency: We will read the existing contents of this texture while
|
||||||
// generating mipmap levels and/or resolving MSAA.
|
// 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);
|
proxy->setLastRenderTask(this);
|
||||||
|
|
||||||
fResolves.emplace_back(std::move(proxy), flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
|
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.
|
// peekRenderTarget might be null if there was an instantiation error.
|
||||||
GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget();
|
GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget();
|
||||||
if (renderTarget && renderTarget->needsResolve()) {
|
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();
|
GrTexture* texture = resolve.fProxy->peekTexture();
|
||||||
if (texture && texture->texturePriv().mipMapsAreDirty()) {
|
if (texture && texture->texturePriv().mipMapsAreDirty()) {
|
||||||
flushState->gpu()->regenerateMipMapLevels(texture);
|
flushState->gpu()->regenerateMipMapLevels(texture);
|
||||||
|
SkASSERT(!texture->texturePriv().mipMapsAreDirty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ private:
|
|||||||
}
|
}
|
||||||
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
||||||
|
|
||||||
ExpectedOutcome onMakeClosed(const GrCaps&) override {
|
ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
|
||||||
return ExpectedOutcome::kTargetUnchanged;
|
return ExpectedOutcome::kTargetUnchanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +43,7 @@ private:
|
|||||||
: fProxy(std::move(proxy)), fFlags(flags) {}
|
: fProxy(std::move(proxy)), fFlags(flags) {}
|
||||||
sk_sp<GrSurfaceProxy> fProxy;
|
sk_sp<GrSurfaceProxy> fProxy;
|
||||||
GrSurfaceProxy::ResolveFlags fFlags;
|
GrSurfaceProxy::ResolveFlags fFlags;
|
||||||
|
SkIRect fMSAAResolveRect;
|
||||||
};
|
};
|
||||||
|
|
||||||
SkSTArray<4, Resolve> fResolves;
|
SkSTArray<4, Resolve> fResolves;
|
||||||
|
@ -36,7 +36,7 @@ private:
|
|||||||
void handleInternalAllocationFailure() override {}
|
void handleInternalAllocationFailure() override {}
|
||||||
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
||||||
|
|
||||||
ExpectedOutcome onMakeClosed(const GrCaps&) override {
|
ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
|
||||||
return ExpectedOutcome::kTargetUnchanged;
|
return ExpectedOutcome::kTargetUnchanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ private:
|
|||||||
void handleInternalAllocationFailure() override {}
|
void handleInternalAllocationFailure() override {}
|
||||||
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
void gatherProxyIntervals(GrResourceAllocator*) const override;
|
||||||
|
|
||||||
ExpectedOutcome onMakeClosed(const GrCaps&) override {
|
ExpectedOutcome onMakeClosed(const GrCaps&, SkIRect*) override {
|
||||||
return ExpectedOutcome::kTargetUnchanged;
|
return ExpectedOutcome::kTargetUnchanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,8 +154,8 @@ private:
|
|||||||
GrColorType surfaceColorType, GrColorType bufferColorType,
|
GrColorType surfaceColorType, GrColorType bufferColorType,
|
||||||
GrGpuBuffer* transferBuffer, size_t offset) override;
|
GrGpuBuffer* transferBuffer, size_t offset) override;
|
||||||
|
|
||||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override {
|
void onResolveRenderTarget(GrRenderTarget*, const SkIRect&, GrSurfaceOrigin,
|
||||||
}
|
ForExternalIO) override {}
|
||||||
|
|
||||||
bool onRegenerateMipMapLevels(GrTexture*) override;
|
bool onRegenerateMipMapLevels(GrTexture*) override;
|
||||||
|
|
||||||
|
@ -1957,7 +1957,7 @@ bool GrGLGpu::readOrTransferPixelsFrom(GrSurface* surface, int left, int top, in
|
|||||||
this->flushRenderTargetNoColorWrites(renderTarget);
|
this->flushRenderTargetNoColorWrites(renderTarget);
|
||||||
break;
|
break;
|
||||||
case GrGLRenderTarget::kCanResolve_ResolveType:
|
case GrGLRenderTarget::kCanResolve_ResolveType:
|
||||||
this->onResolveRenderTarget(renderTarget, ForExternalIO::kNo);
|
SkASSERT(!renderTarget->needsResolve());
|
||||||
// we don't track the state of the READ FBO ID.
|
// we don't track the state of the READ FBO ID.
|
||||||
this->bindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID());
|
this->bindFramebuffer(GR_GL_READ_FRAMEBUFFER, renderTarget->textureFBOID());
|
||||||
break;
|
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);
|
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
|
||||||
if (rt->needsResolve()) {
|
if (rt->needsResolve()) {
|
||||||
// Some extensions automatically resolves the texture when it is read.
|
// 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
|
// make sure we go through flushRenderTarget() since we've modified
|
||||||
// the bound DRAW FBO ID.
|
// the bound DRAW FBO ID.
|
||||||
fHWBoundRenderTargetUniqueID.makeInvalid();
|
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()) {
|
if (GrGLCaps::kES_Apple_MSFBOType == this->glCaps().msFBOType()) {
|
||||||
// Apple's extension uses the scissor as the blit bounds.
|
// Apple's extension uses the scissor as the blit bounds.
|
||||||
GrScissorState scissorState;
|
GrScissorState scissorState;
|
||||||
scissorState.set(dirtyRect);
|
scissorState.set(resolveRect);
|
||||||
this->flushScissor(scissorState, rt->width(), rt->height(), kDirtyRectOrigin);
|
this->flushScissor(scissorState, rt->width(), rt->height(), resolveOrigin);
|
||||||
this->disableWindowRectangles();
|
this->disableWindowRectangles();
|
||||||
GL_CALL(ResolveMultisampleFramebuffer());
|
GL_CALL(ResolveMultisampleFramebuffer());
|
||||||
} else {
|
} else {
|
||||||
@ -2315,7 +2312,7 @@ void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) {
|
|||||||
t = target->height();
|
t = target->height();
|
||||||
} else {
|
} else {
|
||||||
auto rect = GrNativeRect::MakeRelativeTo(
|
auto rect = GrNativeRect::MakeRelativeTo(
|
||||||
kDirtyRectOrigin, rt->height(), dirtyRect);
|
resolveOrigin, rt->height(), resolveRect);
|
||||||
l = rect.fX;
|
l = rect.fX;
|
||||||
b = rect.fY;
|
b = rect.fY;
|
||||||
r = rect.fX + rect.fWidth;
|
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,
|
void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwizzle& swizzle,
|
||||||
GrGLTexture* texture) {
|
GrGLTexture* texture) {
|
||||||
SkASSERT(texture);
|
SkASSERT(texture);
|
||||||
|
SkASSERT(!texture->asRenderTarget() || !texture->asRenderTarget()->needsResolve());
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
if (!this->caps()->npotTextureTileSupport()) {
|
if (!this->caps()->npotTextureTileSupport()) {
|
||||||
@ -2547,14 +2545,6 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwiz
|
|||||||
}
|
}
|
||||||
#endif
|
#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();
|
GrGpuResource::UniqueID textureID = texture->uniqueID();
|
||||||
GrGLenum target = texture->target();
|
GrGLenum target = texture->target();
|
||||||
if (fHWTextureUnitBindings[unitIdx].boundID(target) != textureID) {
|
if (fHWTextureUnitBindings[unitIdx].boundID(target) != textureID) {
|
||||||
|
@ -258,7 +258,8 @@ private:
|
|||||||
// PIXEL_UNPACK_BUFFER is unbound.
|
// PIXEL_UNPACK_BUFFER is unbound.
|
||||||
void unbindCpuToGpuXferBuffer();
|
void unbindCpuToGpuXferBuffer();
|
||||||
|
|
||||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override;
|
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||||
|
GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
|
||||||
|
|
||||||
bool onRegenerateMipMapLevels(GrTexture*) override;
|
bool onRegenerateMipMapLevels(GrTexture*) override;
|
||||||
|
|
||||||
|
@ -118,7 +118,8 @@ private:
|
|||||||
|
|
||||||
bool onRegenerateMipMapLevels(GrTexture*) override { return true; }
|
bool onRegenerateMipMapLevels(GrTexture*) override { return true; }
|
||||||
|
|
||||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO) override {
|
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, GrSurfaceOrigin,
|
||||||
|
ForExternalIO) override {
|
||||||
target->flagAsResolved();
|
target->flagAsResolved();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,10 +108,6 @@ public:
|
|||||||
this->didWriteToSurface(surface, origin, bounds);
|
this->didWriteToSurface(surface, origin, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolveRenderTargetNoFlush(GrRenderTarget* target) {
|
|
||||||
this->internalResolveRenderTarget(target, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrMtlGpu(GrContext* context, const GrContextOptions& options,
|
GrMtlGpu(GrContext* context, const GrContextOptions& options,
|
||||||
id<MTLDevice> device, id<MTLCommandQueue> queue, MTLFeatureSet featureSet);
|
id<MTLDevice> device, id<MTLCommandQueue> queue, MTLFeatureSet featureSet);
|
||||||
@ -185,11 +181,9 @@ private:
|
|||||||
|
|
||||||
bool onRegenerateMipMapLevels(GrTexture*) override;
|
bool onRegenerateMipMapLevels(GrTexture*) override;
|
||||||
|
|
||||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) override {
|
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||||
this->internalResolveRenderTarget(target, ForExternalIO::kYes == forExternalIO);
|
GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
|
||||||
}
|
|
||||||
|
|
||||||
void internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit);
|
|
||||||
void resolveTexture(id<MTLTexture> colorTexture, id<MTLTexture> resolveTexture);
|
void resolveTexture(id<MTLTexture> colorTexture, id<MTLTexture> resolveTexture);
|
||||||
|
|
||||||
void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
|
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();
|
mtlTexture = rt->mtlColorTexture();
|
||||||
break;
|
break;
|
||||||
case GrMtlRenderTarget::kCanResolve_ResolveType:
|
case GrMtlRenderTarget::kCanResolve_ResolveType:
|
||||||
this->resolveRenderTargetNoFlush(rt);
|
SkASSERT(!rt->needsResolve());
|
||||||
mtlTexture = rt->mtlResolveTexture();
|
mtlTexture = rt->mtlResolveTexture();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1188,13 +1188,17 @@ void GrMtlGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrMtlGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
|
void GrMtlGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect&, GrSurfaceOrigin,
|
||||||
|
ForExternalIO forExternalIO) {
|
||||||
if (target->needsResolve()) {
|
if (target->needsResolve()) {
|
||||||
this->resolveTexture(static_cast<GrMtlRenderTarget*>(target)->mtlResolveTexture(),
|
this->resolveTexture(static_cast<GrMtlRenderTarget*>(target)->mtlResolveTexture(),
|
||||||
static_cast<GrMtlRenderTarget*>(target)->mtlColorTexture());
|
static_cast<GrMtlRenderTarget*>(target)->mtlColorTexture());
|
||||||
target->flagAsResolved();
|
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);
|
this->submitCommandBuffer(kSkip_SyncQueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,18 +535,6 @@ bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int wi
|
|||||||
if (rt->wrapsSecondaryCommandBuffer()) {
|
if (rt->wrapsSecondaryCommandBuffer()) {
|
||||||
return false;
|
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;
|
srcImage = rt;
|
||||||
} else {
|
} else {
|
||||||
srcImage = static_cast<GrVkTexture*>(surface->asTexture());
|
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);
|
fCurrentCmdBuffer->resolveImage(this, *src->msaaImage(), *dstImage, 1, &resolveInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrVkGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
|
void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||||
if (target->needsResolve()) {
|
GrSurfaceOrigin resolveOrigin, ForExternalIO forExternalIO) {
|
||||||
SkASSERT(target->numSamples() > 1);
|
SkASSERT(target->numSamples() > 1);
|
||||||
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
|
GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
|
||||||
SkASSERT(rt->msaaImage());
|
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 (ForExternalIO::kYes == forExternalIO) {
|
||||||
|
// This resolve is called when we are preparing an msaa surface for external I/O. It is
|
||||||
if (requiresSubmit) {
|
// called after flushing, so we need to make sure we submit the command buffer after doing
|
||||||
this->submitCommandBuffer(kSkip_SyncQueue);
|
// 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()) {
|
if (rt->wrapsSecondaryCommandBuffer()) {
|
||||||
return false;
|
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;
|
image = rt;
|
||||||
} else {
|
} else {
|
||||||
image = static_cast<GrVkTexture*>(surface->asTexture());
|
image = static_cast<GrVkTexture*>(surface->asTexture());
|
||||||
|
@ -119,13 +119,8 @@ public:
|
|||||||
|
|
||||||
bool onRegenerateMipMapLevels(GrTexture* tex) override;
|
bool onRegenerateMipMapLevels(GrTexture* tex) override;
|
||||||
|
|
||||||
void resolveRenderTargetNoFlush(GrRenderTarget* target) {
|
void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||||
this->internalResolveRenderTarget(target, false);
|
GrSurfaceOrigin resolveOrigin, ForExternalIO) override;
|
||||||
}
|
|
||||||
|
|
||||||
void onResolveRenderTarget(GrRenderTarget* target, ForExternalIO forExternalIO) override {
|
|
||||||
this->internalResolveRenderTarget(target, ForExternalIO::kYes == forExternalIO);
|
|
||||||
}
|
|
||||||
|
|
||||||
void submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer>);
|
void submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer>);
|
||||||
|
|
||||||
@ -248,8 +243,6 @@ private:
|
|||||||
void submitCommandBuffer(SyncQueue sync, GrGpuFinishedProc finishedProc = nullptr,
|
void submitCommandBuffer(SyncQueue sync, GrGpuFinishedProc finishedProc = nullptr,
|
||||||
GrGpuFinishedContext finishedContext = nullptr);
|
GrGpuFinishedContext finishedContext = nullptr);
|
||||||
|
|
||||||
void internalResolveRenderTarget(GrRenderTarget*, bool requiresSubmit);
|
|
||||||
|
|
||||||
void copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
|
void copySurfaceAsCopyImage(GrSurface* dst, GrSurface* src, GrVkImage* dstImage,
|
||||||
GrVkImage* srcImage, const SkIRect& srcRect,
|
GrVkImage* srcImage, const SkIRect& srcRect,
|
||||||
const SkIPoint& dstPoint);
|
const SkIPoint& dstPoint);
|
||||||
|
Loading…
Reference in New Issue
Block a user