xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlTextureRenderTarget.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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