implemented copy surface as draw then blit for metal gpu backend

Bug: skia:
Change-Id: Ifa2d7ced7c22f74c2829d11b24557dbe851e3473
Reviewed-on: https://skia-review.googlesource.com/142691
Commit-Queue: Timothy Liang <timliang@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Timothy Liang 2018-08-01 09:56:25 -04:00 committed by Skia Commit-Bot
parent 722efde79c
commit 70c787ae5b
6 changed files with 102 additions and 3 deletions

View File

@ -477,6 +477,8 @@
"_",
".SRW",
"--match",
"CopySurface",
"GrTestingBackendTextureUploadTest",
"GrUploadPixelsTests",
"--nonativeFonts",
"--verbose"

View File

@ -817,7 +817,10 @@ def dm_flags(api, bot):
if 'Metal' in bot:
# If we modify the whitelist to include GMs, also update infra/bots/cfg.json
# to remove Metal from no_upload.
match = ['GrUploadPixelsTests']
match = []
match.append('CopySurface')
match.append('GrTestingBackendTextureUploadTest')
match.append('GrUploadPixelsTests')
if match:
args.append('--match')

View File

@ -54,6 +54,9 @@ public:
bool canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable,
GrPixelConfig srcConfig, bool srcIsTextureable) const;
bool canCopyAsDrawThenBlit(GrPixelConfig dstConfig, GrPixelConfig srcConfig,
bool srcIsTextureable) const;
bool canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
const SkIRect& srcRect, const SkIPoint& dstPoint) const override;

View File

@ -143,6 +143,19 @@ bool GrMtlCaps::canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable,
return true;
}
bool GrMtlCaps::canCopyAsDrawThenBlit(GrPixelConfig dstConfig, GrPixelConfig srcConfig,
bool srcIsTextureable) const {
// TODO: Make copySurfaceAsDraw handle the swizzle
if (this->shaderCaps()->configOutputSwizzle(srcConfig) !=
this->shaderCaps()->configOutputSwizzle(dstConfig)) {
return false;
}
if (!srcIsTextureable) {
return false;
}
return true;
}
bool GrMtlCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
const SkIRect& srcRect, const SkIPoint& dstPoint) const {
GrSurfaceOrigin dstOrigin = dst->origin();
@ -163,7 +176,9 @@ bool GrMtlCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy*
src->config(), srcSampleCnt, srcOrigin,
srcRect, dstPoint, dst == src) ||
this->canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTargetProxy()),
src->config(), SkToBool(src->asTextureProxy()));
src->config(), SkToBool(src->asTextureProxy())) ||
this->canCopyAsDrawThenBlit(dst->config(), src->config(),
SkToBool(src->asTextureProxy()));
}
void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {

View File

@ -68,6 +68,13 @@ public:
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint);
// This function is needed when we want to copy between two surfaces with different origins and
// the destination surface is not a render target. We will first draw to a temporary render
// target to adjust for the different origins and then blit from there to the destination.
bool copySurfaceAsDrawThenBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint);
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect,

View File

@ -591,6 +591,71 @@ bool GrMtlGpu::copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
return true;
}
bool GrMtlGpu::copySurfaceAsDrawThenBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect, const SkIPoint& dstPoint) {
#ifdef SK_DEBUG
int dstSampleCnt = get_surface_sample_cnt(dst);
int srcSampleCnt = get_surface_sample_cnt(src);
SkASSERT(dstSampleCnt == 0); // dst shouldn't be a render target
SkASSERT(!this->mtlCaps().canCopyAsBlit(dst->config(), dstSampleCnt, dstOrigin,
src->config(), srcSampleCnt, srcOrigin,
srcRect, dstPoint, dst == src));
SkASSERT(!this->mtlCaps().canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTarget()),
src->config(), SkToBool(src->asTexture())));
SkASSERT(this->mtlCaps().canCopyAsDrawThenBlit(dst->config(),src->config(),
SkToBool(src->asTexture())));
#endif
GrSurfaceDesc surfDesc;
surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
surfDesc.fWidth = srcRect.width();
surfDesc.fHeight = srcRect.height();
surfDesc.fConfig = dst->config();
surfDesc.fSampleCnt = 1;
id<MTLTexture> dstTex = GrGetMTLTextureFromSurface(dst, false);
MTLTextureDescriptor* textureDesc = GrGetMTLTextureDescriptor(dstTex);
textureDesc.width = srcRect.width();
textureDesc.height = srcRect.height();
textureDesc.mipmapLevelCount = 1;
textureDesc.usage |= MTLTextureUsageRenderTarget;
sk_sp<GrMtlTexture> transferTexture =
GrMtlTextureRenderTarget::CreateNewTextureRenderTarget(this,
SkBudgeted::kYes,
surfDesc,
textureDesc,
GrMipMapsStatus::kNotAllocated);
GrSurfaceOrigin transferOrigin = dstOrigin;
SkASSERT(this->mtlCaps().canCopyAsDraw(transferTexture->config(),
SkToBool(transferTexture->asRenderTarget()),
src->config(),
SkToBool(src->asTexture())));
// TODO: Eventually we will need to handle resolves either in this function or make a separate
// copySurfaceAsResolveThenBlit().
if (!this->copySurface(transferTexture.get(), transferOrigin,
src, srcOrigin,
srcRect, SkIPoint::Make(0, 0))) {
return false;
}
SkIRect transferRect = SkIRect::MakeXYWH(0, 0, srcRect.width(), srcRect.height());
SkASSERT(this->mtlCaps().canCopyAsBlit(dst->config(),
get_surface_sample_cnt(dst),
dstOrigin,
transferTexture->config(),
get_surface_sample_cnt(transferTexture.get()),
transferOrigin,
transferRect, dstPoint, false));
if (!this->copySurface(dst, dstOrigin,
transferTexture.get(), transferOrigin,
transferRect, dstPoint)) {
return false;
}
return true;
}
bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
GrSurface* src, GrSurfaceOrigin srcOrigin,
const SkIRect& srcRect,
@ -604,7 +669,7 @@ bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
int srcSampleCnt = get_surface_sample_cnt(src);
if (dstSampleCnt > 1 || srcSampleCnt > 1) {
SkASSERT(false); // Currently dont support MSAA
SkASSERT(false); // Currently dont support MSAA. TODO: add copySurfaceAsResolve().
return false;
}
@ -617,6 +682,10 @@ bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
srcConfig, srcSampleCnt, srcOrigin,
srcRect, dstPoint, dst == src)) {
success = this->copySurfaceAsBlit(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
} else if (this->mtlCaps().canCopyAsDrawThenBlit(dst->config(), src->config(),
SkToBool(src->asTexture()))) {
success = this->copySurfaceAsDrawThenBlit(dst, dstOrigin, src, srcOrigin,
srcRect, dstPoint);
}
if (success) {
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),