1/* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7#include "src/gpu/ganesh/mtl/GrMtlTextureRenderTarget.h" 8 9#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h" 10#include "src/gpu/ganesh/GrDirectContextPriv.h" 11#include "src/gpu/ganesh/GrResourceProvider.h" 12#include "src/gpu/ganesh/mtl/GrMtlGpu.h" 13#include "src/gpu/ganesh/mtl/GrMtlUtil.h" 14 15#if !__has_feature(objc_arc) 16#error This file must be compiled with Arc. Use -fobjc-arc flag 17#endif 18 19GR_NORETAIN_BEGIN 20 21GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu, 22 skgpu::Budgeted budgeted, 23 SkISize dimensions, 24 sk_sp<GrMtlAttachment> texture, 25 sk_sp<GrMtlAttachment> colorAttachment, 26 sk_sp<GrMtlAttachment> resolveAttachment, 27 GrMipmapStatus mipmapStatus, 28 std::string_view label) 29 : GrSurface(gpu, dimensions, GrProtected::kNo, label) 30 , GrMtlTexture(gpu, dimensions, std::move(texture), mipmapStatus, label) 31 , GrMtlRenderTarget(gpu, dimensions, std::move(colorAttachment), 32 std::move(resolveAttachment), label) { 33 this->registerWithCache(budgeted); 34} 35 36GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu, 37 SkISize dimensions, 38 sk_sp<GrMtlAttachment> texture, 39 sk_sp<GrMtlAttachment> colorAttachment, 40 sk_sp<GrMtlAttachment> resolveAttachment, 41 GrMipmapStatus mipmapStatus, 42 GrWrapCacheable cacheable, 43 std::string_view label) 44 : GrSurface(gpu, dimensions, GrProtected::kNo, label) 45 , GrMtlTexture(gpu, dimensions, std::move(texture), mipmapStatus, label) 46 , GrMtlRenderTarget(gpu, dimensions, std::move(colorAttachment), 47 std::move(resolveAttachment), label) { 48 this->registerWithCacheWrapped(cacheable); 49} 50 51bool create_rt_attachments(GrMtlGpu* gpu, SkISize dimensions, MTLPixelFormat format, int sampleCnt, 52 sk_sp<GrMtlAttachment> texture, sk_sp<GrMtlAttachment>* colorAttachment, 53 sk_sp<GrMtlAttachment>* resolveAttachment) { 54 if (sampleCnt > 1) { 55 auto rp = gpu->getContext()->priv().resourceProvider(); 56 sk_sp<GrAttachment> msaaAttachment = 57 rp->makeMSAAAttachment(dimensions, 58 GrBackendFormats::MakeMtl(format), 59 sampleCnt, 60 GrProtected::kNo, 61 GrMemoryless::kNo); 62 if (!msaaAttachment) { 63 return false; 64 } 65 *colorAttachment = 66 sk_sp<GrMtlAttachment>(static_cast<GrMtlAttachment*>(msaaAttachment.release())); 67 *resolveAttachment = std::move(texture); 68 } else { 69 *colorAttachment = std::move(texture); 70 } 71 return true; 72} 73 74sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeNewTextureRenderTarget( 75 GrMtlGpu* gpu, 76 skgpu::Budgeted budgeted, 77 SkISize dimensions, 78 int sampleCnt, 79 MTLPixelFormat format, 80 uint32_t mipLevels, 81 GrMipmapStatus mipmapStatus, 82 std::string_view label) { 83 sk_sp<GrMtlAttachment> textureAttachment = 84 GrMtlAttachment::MakeTexture(gpu, dimensions, format, mipLevels, GrRenderable::kYes, 85 /*numSamples=*/1, budgeted); 86 if (!textureAttachment) { 87 return nullptr; 88 } 89 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 90 SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & 91 textureAttachment->mtlTexture().usage); 92 } 93 94 sk_sp<GrMtlAttachment> colorAttachment; 95 sk_sp<GrMtlAttachment> resolveAttachment; 96 if (!create_rt_attachments(gpu, dimensions, format, sampleCnt, textureAttachment, 97 &colorAttachment, &resolveAttachment)) { 98 return nullptr; 99 } 100 SkASSERT(colorAttachment); 101 SkASSERT(sampleCnt == 1 || resolveAttachment); 102 103 return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget( 104 gpu, budgeted, dimensions, std::move(textureAttachment), std::move(colorAttachment), 105 std::move(resolveAttachment), mipmapStatus, label)); 106} 107 108sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget( 109 GrMtlGpu* gpu, 110 SkISize dimensions, 111 int sampleCnt, 112 id<MTLTexture> texture, 113 GrWrapCacheable cacheable) { 114 SkASSERT(nil != texture); 115 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 116 SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & texture.usage); 117 } 118 GrMipmapStatus mipmapStatus = texture.mipmapLevelCount > 1 119 ? GrMipmapStatus::kDirty 120 : GrMipmapStatus::kNotAllocated; 121 GrAttachment::UsageFlags textureUsageFlags = GrAttachment::UsageFlags::kTexture | 122 GrAttachment::UsageFlags::kColorAttachment; 123 sk_sp<GrMtlAttachment> textureAttachment = 124 GrMtlAttachment::MakeWrapped(gpu, dimensions, texture, textureUsageFlags, cacheable, 125 /*label=*/"MtlAttachment_TextureAttachment"); 126 if (!textureAttachment) { 127 return nullptr; 128 } 129 130 sk_sp<GrMtlAttachment> colorAttachment; 131 sk_sp<GrMtlAttachment> resolveAttachment; 132 if (!create_rt_attachments(gpu, dimensions, texture.pixelFormat, sampleCnt, textureAttachment, 133 &colorAttachment, &resolveAttachment)) { 134 return nullptr; 135 } 136 SkASSERT(colorAttachment); 137 SkASSERT(sampleCnt == 1 || resolveAttachment); 138 139 return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget( 140 gpu, dimensions, std::move(textureAttachment), std::move(colorAttachment), 141 std::move(resolveAttachment), mipmapStatus, cacheable, 142 /*label=*/"MtlWrappedTextureRenderTarget")); 143} 144 145size_t GrMtlTextureRenderTarget::onGpuMemorySize() const { 146 // The GrTexture[RenderTarget] is built up by a bunch of attachments each of which are their 147 // own GrGpuResource. Ideally the GrRenderTarget would not be a GrGpuResource and the GrTexture 148 // would just merge with the new GrSurface/Attachment world. Then we could just depend on each 149 // attachment to give its own size since we don't have GrGpuResources owning other 150 // GrGpuResources. Until we get to that point we need to live in some hybrid world. We will let 151 // the msaa and stencil attachments track their own size because they do get cached separately. 152 // For all GrTexture* based things we will continue to to use the GrTexture* to report size and 153 // the owned attachments will have no size and be uncached. 154#ifdef SK_DEBUG 155 // The nonMSAA attachment (either color or resolve depending on numSamples should have size of 156 // zero since it is a texture attachment. 157 SkASSERT(this->nonMSAAAttachment()->gpuMemorySize() == 0); 158 if (this->numSamples() > 1) { 159 // Msaa attachment should have a valid size 160 SkASSERT(this->colorAttachment()->gpuMemorySize() == 161 GrSurface::ComputeSize(this->backendFormat(), 162 this->dimensions(), 163 this->numSamples(), 164 skgpu::Mipmapped::kNo)); 165 } 166#endif 167 return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(), 168 1 /*colorSamplesPerPixel*/, this->mipmapped()); 169} 170 171void GrMtlTextureRenderTarget::onSetLabel() { 172 GrMtlRenderTarget::onSetLabel(); 173 GrMtlTexture::onSetLabel(); 174} 175 176GR_NORETAIN_END 177