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