diff options
author | Timothy Liang <timliang@google.com> | 2018-07-02 16:03:28 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-07-02 20:57:57 +0000 |
commit | e886e80e8b204460a78dabf5c671b7f4146d71f7 (patch) | |
tree | bec7b602ec3855000e8d64fe8e3e6025ca7578d1 | |
parent | 389abd50fe74c54a11430f5457d2278cda391132 (diff) |
implemented wrapped backend texture/rendertarget/textureRT for Metal gpu backend
Bug: skia:
Change-Id: I5d84f9f4340023301bf119731d0b544649be7ab0
Reviewed-on: https://skia-review.googlesource.com/137892
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Timothy Liang <timliang@google.com>
-rw-r--r-- | src/gpu/mtl/GrMtlGpu.h | 16 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlGpu.mm | 106 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlRenderTarget.h | 19 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlRenderTarget.mm | 49 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlTexture.h | 8 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlTexture.mm | 37 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlTextureRenderTarget.h | 2 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlTextureRenderTarget.mm | 23 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlUtil.h | 5 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlUtil.mm | 4 |
10 files changed, 197 insertions, 72 deletions
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h index b230ef73d7..22fc733217 100644 --- a/src/gpu/mtl/GrMtlGpu.h +++ b/src/gpu/mtl/GrMtlGpu.h @@ -73,24 +73,16 @@ private: sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, const GrMipLevel texels[], int mipLevelCount) override; - sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override { - return nullptr; - } + sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership) override; sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt, - GrWrapOwnership) override { - return nullptr; - } + GrWrapOwnership) override; - sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override { - return nullptr; - } + sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override; sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&, - int sampleCnt) override { - return nullptr; - } + int sampleCnt) override; GrBuffer* onCreateBuffer(size_t, GrBufferType, GrAccessPattern, const void*) override { return nullptr; diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm index 149e56220e..42b0739548 100644 --- a/src/gpu/mtl/GrMtlGpu.mm +++ b/src/gpu/mtl/GrMtlGpu.mm @@ -8,6 +8,8 @@ #include "GrMtlGpu.h" #include "GrMtlTexture.h" +#include "GrMtlTextureRenderTarget.h" +#include "GrMtlUtil.h" #if !__has_feature(objc_arc) #error This file must be compiled with Arc. Use -fobjc-arc flag @@ -115,18 +117,11 @@ sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted } bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); - if (renderTarget) { - // Current we don't have render target support - return nullptr; - } sk_sp<GrMtlTexture> tex; if (renderTarget) { - // Enable once we have render target support -#if 0 tex = GrMtlTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, - desc, mipLevels); -#endif + desc, mipLevels); } else { tex = GrMtlTexture::CreateNewTexture(this, budgeted, desc, mipLevels); } @@ -144,3 +139,98 @@ sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted } return tex; } + +static id<MTLTexture> get_texture_from_backend(const GrBackendTexture& backendTex, + GrWrapOwnership ownership) { + GrMtlTextureInfo textureInfo; + if (!backendTex.getMtlTextureInfo(&textureInfo)) { + return nil; + } + return GrGetMTLTexture(textureInfo.fTexture, ownership); +} + +static id<MTLTexture> get_texture_from_backend(const GrBackendRenderTarget& backendRT) { + GrMtlTextureInfo textureInfo; + if (!backendRT.getMtlTextureInfo(&textureInfo)) { + return nil; + } + return GrGetMTLTexture(textureInfo.fTexture, GrWrapOwnership::kBorrow_GrWrapOwnership); +} + +static inline void init_surface_desc(GrSurfaceDesc* surfaceDesc, id<MTLTexture> mtlTexture, + bool isRenderTarget, GrPixelConfig config) { + if (isRenderTarget) { + SkASSERT(MTLTextureUsageRenderTarget & mtlTexture.usage); + } + surfaceDesc->fFlags = isRenderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags; + surfaceDesc->fWidth = mtlTexture.width; + surfaceDesc->fHeight = mtlTexture.height; + surfaceDesc->fConfig = config; + surfaceDesc->fSampleCnt = 1; +} + +sk_sp<GrTexture> GrMtlGpu::onWrapBackendTexture(const GrBackendTexture& backendTex, + GrWrapOwnership ownership) { + id<MTLTexture> mtlTexture = get_texture_from_backend(backendTex, ownership); + if (!mtlTexture) { + return nullptr; + } + + GrSurfaceDesc surfDesc; + init_surface_desc(&surfDesc, mtlTexture, false, backendTex.config()); + + return GrMtlTexture::MakeWrappedTexture(this, surfDesc, mtlTexture); +} + +sk_sp<GrTexture> GrMtlGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex, + int sampleCnt, + GrWrapOwnership ownership) { + id<MTLTexture> mtlTexture = get_texture_from_backend(backendTex, ownership); + if (!mtlTexture) { + return nullptr; + } + + GrSurfaceDesc surfDesc; + init_surface_desc(&surfDesc, mtlTexture, true, backendTex.config()); + surfDesc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, surfDesc.fConfig); + if (!surfDesc.fSampleCnt) { + return nullptr; + } + + return GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget(this, surfDesc, mtlTexture); +} + +sk_sp<GrRenderTarget> GrMtlGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) { + // TODO: Revisit this when the Metal backend is completed. It may support MSAA render targets. + if (backendRT.sampleCnt() > 1) { + return nullptr; + } + id<MTLTexture> mtlTexture = get_texture_from_backend(backendRT); + if (!mtlTexture) { + return nullptr; + } + + GrSurfaceDesc surfDesc; + init_surface_desc(&surfDesc, mtlTexture, true, backendRT.config()); + + return GrMtlRenderTarget::MakeWrappedRenderTarget(this, surfDesc, mtlTexture); +} + +sk_sp<GrRenderTarget> GrMtlGpu::onWrapBackendTextureAsRenderTarget( + const GrBackendTexture& backendTex, int sampleCnt) { + id<MTLTexture> mtlTexture = get_texture_from_backend(backendTex, + GrWrapOwnership::kBorrow_GrWrapOwnership); + if (!mtlTexture) { + return nullptr; + } + + GrSurfaceDesc surfDesc; + init_surface_desc(&surfDesc, mtlTexture, true, backendTex.config()); + surfDesc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, surfDesc.fConfig); + if (!surfDesc.fSampleCnt) { + return nullptr; + } + + return GrMtlRenderTarget::MakeWrappedRenderTarget(this, surfDesc, mtlTexture); +} + diff --git a/src/gpu/mtl/GrMtlRenderTarget.h b/src/gpu/mtl/GrMtlRenderTarget.h index c0f0cf57e1..02b0a61a0d 100644 --- a/src/gpu/mtl/GrMtlRenderTarget.h +++ b/src/gpu/mtl/GrMtlRenderTarget.h @@ -18,10 +18,9 @@ class GrMtlGpu; class GrMtlRenderTarget: public GrRenderTarget { public: - static sk_sp<GrMtlRenderTarget> CreateNewRenderTarget(GrMtlGpu*, const GrSurfaceDesc&, - SkBudgeted); - - static sk_sp<GrMtlRenderTarget> MakeWrappedRenderTarget(GrMtlGpu*, const GrSurfaceDesc&); + static sk_sp<GrMtlRenderTarget> MakeWrappedRenderTarget(GrMtlGpu*, + const GrSurfaceDesc&, + id<MTLTexture>); ~GrMtlRenderTarget() override; @@ -40,9 +39,7 @@ public: return true; } - GrBackendRenderTarget getBackendRenderTarget() const override { - return GrBackendRenderTarget(); // invalid - } + GrBackendRenderTarget getBackendRenderTarget() const override; protected: GrMtlRenderTarget(GrMtlGpu* gpu, @@ -62,6 +59,8 @@ protected: // This accounts for the texture's memory and any MSAA renderbuffer's memory. size_t onGpuMemorySize() const override { int numColorSamples = this->numColorSamples(); + // TODO: When used as render targets certain formats may actually have a larger size than + // the base format size. Check to make sure we are reporting the correct value here. // The plus 1 is to account for the resolve texture or if not using msaa the RT itself if (numColorSamples > 1) { ++numColorSamples; @@ -75,19 +74,19 @@ protected: private: GrMtlRenderTarget(GrMtlGpu* gpu, - const GrSurfaceDesc& desc, SkBudgeted, + const GrSurfaceDesc& desc, id<MTLTexture> renderTexture, id<MTLTexture> resolveTexture); GrMtlRenderTarget(GrMtlGpu* gpu, - const GrSurfaceDesc& desc, SkBudgeted, + const GrSurfaceDesc& desc, id<MTLTexture> renderTexture); static sk_sp<GrMtlRenderTarget> Make(GrMtlGpu*, - const GrSurfaceDesc&, SkBudgeted, + const GrSurfaceDesc&, id<MTLTexture> renderTexture, bool isWrapped); diff --git a/src/gpu/mtl/GrMtlRenderTarget.mm b/src/gpu/mtl/GrMtlRenderTarget.mm index 32d612861e..2bf4ae2e18 100644 --- a/src/gpu/mtl/GrMtlRenderTarget.mm +++ b/src/gpu/mtl/GrMtlRenderTarget.mm @@ -11,8 +11,8 @@ #include "GrMtlUtil.h" GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu, - const GrSurfaceDesc& desc, SkBudgeted budgeted, + const GrSurfaceDesc& desc, id<MTLTexture> renderTexture) : GrSurface(gpu, desc) , GrRenderTarget(gpu, desc) @@ -32,37 +32,14 @@ GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu, SkASSERT(1 == desc.fSampleCnt); } -sk_sp<GrMtlRenderTarget> GrMtlRenderTarget::CreateNewRenderTarget(GrMtlGpu* gpu, - const GrSurfaceDesc& desc, - SkBudgeted budgeted) { - MTLPixelFormat format; - if (!GrPixelConfigToMTLFormat(desc.fConfig, &format)) { - return nullptr; - } - - if (desc.fSampleCnt) { - return nullptr; - } - - MTLTextureDescriptor* descriptor = [[MTLTextureDescriptor alloc] init]; - descriptor.textureType = MTLTextureType2D; - descriptor.pixelFormat = format; - descriptor.width = desc.fWidth; - descriptor.height = desc.fHeight; - descriptor.depth = 1; - descriptor.mipmapLevelCount = 1; - descriptor.sampleCount = 1; - descriptor.arrayLength = 1; - // descriptor.resourceOptions This looks to be set by setting cpuCacheMode and storageModes - descriptor.cpuCacheMode = MTLCPUCacheModeWriteCombined; - // RenderTargets never need to be mapped so their storage mode is set to private - descriptor.storageMode = MTLStorageModePrivate; - - descriptor.usage = MTLTextureUsageRenderTarget; - - id<MTLTexture> texture = [gpu->device() newTextureWithDescriptor:descriptor]; - - return sk_sp<GrMtlRenderTarget>(new GrMtlRenderTarget(gpu, desc, budgeted, texture)); +sk_sp<GrMtlRenderTarget> +GrMtlRenderTarget::MakeWrappedRenderTarget(GrMtlGpu* gpu, const GrSurfaceDesc& desc, + id<MTLTexture> renderTexture) { + SkASSERT(nil != renderTexture); + SkASSERT(1 == renderTexture.mipmapLevelCount); + SkASSERT(MTLTextureUsageRenderTarget & renderTexture.usage); + return sk_sp<GrMtlRenderTarget>(new GrMtlRenderTarget(gpu, SkBudgeted::kNo, + desc, renderTexture)); } GrMtlRenderTarget::~GrMtlRenderTarget() { @@ -70,6 +47,13 @@ GrMtlRenderTarget::~GrMtlRenderTarget() { SkASSERT(nil == fResolveTexture); } + +GrBackendRenderTarget GrMtlRenderTarget::getBackendRenderTarget() const { + GrMtlTextureInfo info; + info.fTexture = GrGetPtrFromId(fRenderTexture); + return GrBackendRenderTarget(this->width(), this->height(), fRenderTexture.sampleCount, info); +} + GrMtlGpu* GrMtlRenderTarget::getMtlGpu() const { SkASSERT(!this->wasDestroyed()); return static_cast<GrMtlGpu*>(this->getGpu()); @@ -90,4 +74,3 @@ bool GrMtlRenderTarget::completeStencilAttachment() { return true; } - diff --git a/src/gpu/mtl/GrMtlTexture.h b/src/gpu/mtl/GrMtlTexture.h index 57a7ee5d71..99fb27d6a5 100644 --- a/src/gpu/mtl/GrMtlTexture.h +++ b/src/gpu/mtl/GrMtlTexture.h @@ -20,7 +20,7 @@ public: const GrSurfaceDesc&, int mipLevels); static sk_sp<GrMtlTexture> MakeWrappedTexture(GrMtlGpu*, const GrSurfaceDesc&, - GrWrapOwnership); + id<MTLTexture>); ~GrMtlTexture() override; @@ -57,8 +57,10 @@ protected: private: enum Wrapped { kWrapped }; - GrMtlTexture(GrMtlGpu*, SkBudgeted, const GrSurfaceDesc&, id<MTLTexture>, GrMipMapsStatus); - // GrMtlTexture(GrMtlGpu*, Wrapped, const GrSurfaceDesc&, GrMtlImage::Wrapped wrapped); + GrMtlTexture(GrMtlGpu*, SkBudgeted, const GrSurfaceDesc&, id<MTLTexture>, + GrMipMapsStatus); + + GrMtlTexture(GrMtlGpu*, Wrapped, const GrSurfaceDesc&, id<MTLTexture>, GrMipMapsStatus); id<MTLTexture> fTexture; diff --git a/src/gpu/mtl/GrMtlTexture.mm b/src/gpu/mtl/GrMtlTexture.mm index 90bfcb38fb..87ee28b206 100644 --- a/src/gpu/mtl/GrMtlTexture.mm +++ b/src/gpu/mtl/GrMtlTexture.mm @@ -30,6 +30,19 @@ GrMtlTexture::GrMtlTexture(GrMtlGpu* gpu, } GrMtlTexture::GrMtlTexture(GrMtlGpu* gpu, + Wrapped, + const GrSurfaceDesc& desc, + id<MTLTexture> texture, + GrMipMapsStatus mipMapsStatus) + : GrSurface(gpu, desc) + , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig), + mipMapsStatus) + , fTexture(texture) { + SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == texture.mipmapLevelCount)); + this->registerWithCacheWrapped(); +} + +GrMtlTexture::GrMtlTexture(GrMtlGpu* gpu, const GrSurfaceDesc& desc, id<MTLTexture> texture, GrMipMapsStatus mipMapsStatus) @@ -47,6 +60,11 @@ sk_sp<GrMtlTexture> GrMtlTexture::CreateNewTexture(GrMtlGpu* gpu, SkBudgeted bud return nullptr; } + if (desc.fSampleCnt > 1) { + SkASSERT(false); // Currently we don't support msaa + return nullptr; + } + MTLTextureDescriptor* descriptor = [[MTLTextureDescriptor alloc] init]; descriptor.textureType = MTLTextureType2D; descriptor.pixelFormat = format; @@ -58,7 +76,7 @@ sk_sp<GrMtlTexture> GrMtlTexture::CreateNewTexture(GrMtlGpu* gpu, SkBudgeted bud descriptor.arrayLength = 1; // descriptor.resourceOptions This looks to be set by setting cpuCacheMode and storageModes descriptor.cpuCacheMode = MTLCPUCacheModeWriteCombined; - // Shared is not available on MacOS. Is there a reason to want managed to allow mapping? + // Make all textures have private gpu only access. We can use transfer buffers to copy to them. descriptor.storageMode = MTLStorageModePrivate; descriptor.usage = MTLTextureUsageShaderRead; @@ -70,6 +88,16 @@ sk_sp<GrMtlTexture> GrMtlTexture::CreateNewTexture(GrMtlGpu* gpu, SkBudgeted bud return sk_sp<GrMtlTexture>(new GrMtlTexture(gpu, budgeted, desc, texture, mipMapsStatus)); } +sk_sp<GrMtlTexture> GrMtlTexture::MakeWrappedTexture(GrMtlGpu* gpu, + const GrSurfaceDesc& desc, + id<MTLTexture> texture) { + SkASSERT(nil != texture); + SkASSERT(MTLTextureUsageShaderRead & texture.usage); + GrMipMapsStatus mipMapsStatus = texture.mipmapLevelCount > 1 ? GrMipMapsStatus::kValid + : GrMipMapsStatus::kNotAllocated; + return sk_sp<GrMtlTexture>(new GrMtlTexture(gpu, kWrapped, desc, texture, mipMapsStatus)); +} + GrMtlTexture::~GrMtlTexture() { SkASSERT(nil == fTexture); } @@ -80,5 +108,10 @@ GrMtlGpu* GrMtlTexture::getMtlGpu() const { } GrBackendTexture GrMtlTexture::getBackendTexture() const { - return GrBackendTexture(); // invalid + GrMipMapped mipMapped = fTexture.mipmapLevelCount > 1 ? GrMipMapped::kYes + : GrMipMapped::kNo; + GrMtlTextureInfo info; + info.fTexture = GrGetPtrFromId(fTexture); + return GrBackendTexture(this->width(), this->height(), mipMapped, info); } + diff --git a/src/gpu/mtl/GrMtlTextureRenderTarget.h b/src/gpu/mtl/GrMtlTextureRenderTarget.h index 5137dd0736..74b682a9ec 100644 --- a/src/gpu/mtl/GrMtlTextureRenderTarget.h +++ b/src/gpu/mtl/GrMtlTextureRenderTarget.h @@ -20,7 +20,7 @@ public: static sk_sp<GrMtlTextureRenderTarget> MakeWrappedTextureRenderTarget(GrMtlGpu*, const GrSurfaceDesc&, - GrWrapOwnership); + id<MTLTexture>); protected: void onAbandon() override { diff --git a/src/gpu/mtl/GrMtlTextureRenderTarget.mm b/src/gpu/mtl/GrMtlTextureRenderTarget.mm index 99d1c9e358..c1b36dea83 100644 --- a/src/gpu/mtl/GrMtlTextureRenderTarget.mm +++ b/src/gpu/mtl/GrMtlTextureRenderTarget.mm @@ -20,6 +20,16 @@ GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu, this->registerWithCache(budgeted); } +GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu, + const GrSurfaceDesc& desc, + id<MTLTexture> renderTexture, + GrMipMapsStatus mipMapsStatus) + : GrSurface(gpu, desc) + , GrMtlTexture(gpu, desc, renderTexture, mipMapsStatus) + , GrMtlRenderTarget(gpu, desc, renderTexture) { + this->registerWithCacheWrapped(); +} + sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::Make(GrMtlGpu* gpu, const GrSurfaceDesc& desc, @@ -41,7 +51,10 @@ GrMtlTextureRenderTarget::Make(GrMtlGpu* gpu, renderTexture, mipMapsStatus)); } else { - return nullptr; // Currently don't support wrapped TextureRenderTargets + return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget(gpu, + desc, + renderTexture, + mipMapsStatus)); } } @@ -80,6 +93,10 @@ GrMtlTextureRenderTarget::CreateNewTextureRenderTarget(GrMtlGpu* gpu, sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget(GrMtlGpu* gpu, const GrSurfaceDesc& desc, - GrWrapOwnership wrapOwnership) { - return nullptr; + id<MTLTexture> texture) { + + SkASSERT(nil != texture); + SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & texture.usage); + return Make(gpu, desc, texture, texture.mipmapLevelCount, SkBudgeted::kNo, true); } + diff --git a/src/gpu/mtl/GrMtlUtil.h b/src/gpu/mtl/GrMtlUtil.h index 656b65cd6d..932ebec2b5 100644 --- a/src/gpu/mtl/GrMtlUtil.h +++ b/src/gpu/mtl/GrMtlUtil.h @@ -29,4 +29,9 @@ GrPixelConfig GrMTLFormatToPixelConfig(MTLPixelFormat format); */ id<MTLTexture> GrGetMTLTexture(const void* mtlTexture, GrWrapOwnership); +/** + * Returns a const void* to whatever the id object is pointing to. Always uses __bridge. + */ +const void* GrGetPtrFromId(id idObject); + #endif diff --git a/src/gpu/mtl/GrMtlUtil.mm b/src/gpu/mtl/GrMtlUtil.mm index 3bd3b280a5..c9766597e8 100644 --- a/src/gpu/mtl/GrMtlUtil.mm +++ b/src/gpu/mtl/GrMtlUtil.mm @@ -122,3 +122,7 @@ id<MTLTexture> GrGetMTLTexture(const void* mtlTexture, GrWrapOwnership wrapOwner } } +const void* GrGetPtrFromId(id idObject) { + return (__bridge const void*)idObject; +} + |