xref: /aosp_15_r20/external/skia/src/gpu/ganesh/vk/GrVkTextureRenderTarget.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2015 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 
8 #include "src/gpu/ganesh/vk/GrVkTextureRenderTarget.h"
9 
10 #include "include/core/SkSize.h"
11 #include "include/core/SkTypes.h"
12 #include "include/gpu/GpuTypes.h"
13 #include "include/gpu/ganesh/GrDirectContext.h"
14 #include "include/gpu/MutableTextureState.h"
15 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
16 #include "include/gpu/ganesh/vk/GrVkTypes.h"
17 #include "include/gpu/vk/VulkanTypes.h"
18 #include "src/gpu/ganesh/GrAttachment.h"
19 #include "src/gpu/ganesh/GrDirectContextPriv.h"
20 #include "src/gpu/ganesh/GrResourceProvider.h"
21 #include "src/gpu/ganesh/GrSurface.h"
22 #include "src/gpu/ganesh/vk/GrVkGpu.h"
23 #include "src/gpu/ganesh/vk/GrVkImage.h"
24 #include "src/gpu/ganesh/vk/GrVkUtil.h"
25 
26 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
27 
GrVkTextureRenderTarget(GrVkGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,sk_sp<GrVkImage> texture,sk_sp<GrVkImage> colorAttachment,sk_sp<GrVkImage> resolveAttachment,GrMipmapStatus mipmapStatus,std::string_view label)28 GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
29                                                  skgpu::Budgeted budgeted,
30                                                  SkISize dimensions,
31                                                  sk_sp<GrVkImage> texture,
32                                                  sk_sp<GrVkImage> colorAttachment,
33                                                  sk_sp<GrVkImage> resolveAttachment,
34                                                  GrMipmapStatus mipmapStatus,
35                                                  std::string_view label)
36         : GrSurface(gpu,
37                     dimensions,
38                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
39                     label)
40         , GrVkTexture(gpu, dimensions, std::move(texture), mipmapStatus, label)
41         , GrVkRenderTarget(gpu,
42                            dimensions,
43                            std::move(colorAttachment),
44                            std::move(resolveAttachment),
45                            CreateType::kFromTextureRT,
46                            label) {
47     this->registerWithCache(budgeted);
48 }
49 
GrVkTextureRenderTarget(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkImage> texture,sk_sp<GrVkImage> colorAttachment,sk_sp<GrVkImage> resolveAttachment,GrMipmapStatus mipmapStatus,GrWrapCacheable cacheable,std::string_view label)50 GrVkTextureRenderTarget::GrVkTextureRenderTarget(
51         GrVkGpu* gpu,
52         SkISize dimensions,
53         sk_sp<GrVkImage> texture,
54         sk_sp<GrVkImage> colorAttachment,
55         sk_sp<GrVkImage> resolveAttachment,
56         GrMipmapStatus mipmapStatus,
57         GrWrapCacheable cacheable,
58         std::string_view label)
59         : GrSurface(gpu,
60                     dimensions,
61                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
62                     label)
63         , GrVkTexture(gpu, dimensions, std::move(texture), mipmapStatus, label)
64         , GrVkRenderTarget(gpu, dimensions, std::move(colorAttachment),
65                            std::move(resolveAttachment), CreateType::kFromTextureRT, label) {
66     this->registerWithCacheWrapped(cacheable);
67 }
68 
create_rt_attachments(GrVkGpu * gpu,SkISize dimensions,VkFormat format,int sampleCnt,GrProtected isProtected,sk_sp<GrVkImage> texture,sk_sp<GrVkImage> * colorAttachment,sk_sp<GrVkImage> * resolveAttachment)69 bool create_rt_attachments(GrVkGpu* gpu, SkISize dimensions, VkFormat format, int sampleCnt,
70                            GrProtected isProtected,
71                            sk_sp<GrVkImage> texture,
72                            sk_sp<GrVkImage>* colorAttachment,
73                            sk_sp<GrVkImage>* resolveAttachment) {
74     if (sampleCnt > 1) {
75         auto rp = gpu->getContext()->priv().resourceProvider();
76         sk_sp<GrAttachment> msaaAttachment = rp->makeMSAAAttachment(
77                 dimensions, GrBackendFormats::MakeVk(format), sampleCnt, isProtected,
78                 GrMemoryless::kNo);
79         if (!msaaAttachment) {
80             return false;
81         }
82         *colorAttachment = sk_sp<GrVkImage>(static_cast<GrVkImage*>(msaaAttachment.release()));
83         *resolveAttachment = std::move(texture);
84     } else {
85         *colorAttachment = std::move(texture);
86     }
87     return true;
88 }
89 
MakeNewTextureRenderTarget(GrVkGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,VkFormat format,uint32_t mipLevels,int sampleCnt,GrMipmapStatus mipmapStatus,GrProtected isProtected,std::string_view label)90 sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeNewTextureRenderTarget(
91         GrVkGpu* gpu,
92         skgpu::Budgeted budgeted,
93         SkISize dimensions,
94         VkFormat format,
95         uint32_t mipLevels,
96         int sampleCnt,
97         GrMipmapStatus mipmapStatus,
98         GrProtected isProtected,
99         std::string_view label) {
100     sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(gpu,
101                                                       dimensions,
102                                                       format,
103                                                       mipLevels,
104                                                       GrRenderable::kYes,
105                                                       /*numSamples=*/1,
106                                                       budgeted,
107                                                       isProtected);
108     if (!texture) {
109         return nullptr;
110     }
111 
112     sk_sp<GrVkImage> colorAttachment;
113     sk_sp<GrVkImage> resolveAttachment;
114     if (!create_rt_attachments(gpu, dimensions, format, sampleCnt, isProtected, texture,
115                                &colorAttachment, &resolveAttachment)) {
116         return nullptr;
117     }
118     SkASSERT(colorAttachment);
119     SkASSERT(sampleCnt == 1 || resolveAttachment);
120     return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(gpu,
121                                                                       budgeted,
122                                                                       dimensions,
123                                                                       std::move(texture),
124                                                                       std::move(colorAttachment),
125                                                                       std::move(resolveAttachment),
126                                                                       mipmapStatus,
127                                                                       label));
128 }
129 
MakeWrappedTextureRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,GrWrapOwnership wrapOwnership,GrWrapCacheable cacheable,const GrVkImageInfo & info,sk_sp<skgpu::MutableTextureState> mutableState)130 sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(
131         GrVkGpu* gpu,
132         SkISize dimensions,
133         int sampleCnt,
134         GrWrapOwnership wrapOwnership,
135         GrWrapCacheable cacheable,
136         const GrVkImageInfo& info,
137         sk_sp<skgpu::MutableTextureState> mutableState) {
138     // Adopted textures require both image and allocation because we're responsible for freeing
139     SkASSERT(VK_NULL_HANDLE != info.fImage &&
140              (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
141 
142     GrAttachment::UsageFlags textureUsageFlags = GrAttachment::UsageFlags::kTexture;
143     if (info.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
144         textureUsageFlags |= GrAttachment::UsageFlags::kColorAttachment;
145     }
146 
147     sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
148                                                       dimensions,
149                                                       info,
150                                                       std::move(mutableState),
151                                                       textureUsageFlags,
152                                                       wrapOwnership,
153                                                       cacheable,
154                                                       "VkImage_MakeWrappedTextureRenderTarget");
155     if (!texture) {
156         return nullptr;
157     }
158 
159     sk_sp<GrVkImage> colorAttachment;
160     sk_sp<GrVkImage> resolveAttachment;
161     if (!create_rt_attachments(gpu, dimensions, info.fFormat, sampleCnt, info.fProtected, texture,
162                                &colorAttachment, &resolveAttachment)) {
163         return nullptr;
164     }
165     SkASSERT(colorAttachment);
166     SkASSERT(sampleCnt == 1 || resolveAttachment);
167 
168     GrMipmapStatus mipmapStatus =
169             info.fLevelCount > 1 ? GrMipmapStatus::kDirty : GrMipmapStatus::kNotAllocated;
170 
171     return sk_sp<GrVkTextureRenderTarget>(
172             new GrVkTextureRenderTarget(gpu,
173                                         dimensions,
174                                         std::move(texture),
175                                         std::move(colorAttachment),
176                                         std::move(resolveAttachment),
177                                         mipmapStatus,
178                                         cacheable,
179                                         /*label=*/"Vk_MakeWrappedTextureRenderTarget"));
180 }
181 
onGpuMemorySize() const182 size_t GrVkTextureRenderTarget::onGpuMemorySize() const {
183     // The GrTexture[RenderTarget] is built up by a bunch of attachments each of which are their
184     // own GrGpuResource. Ideally the GrRenderTarget would not be a GrGpuResource and the GrTexture
185     // would just merge with the new GrSurface/Attachment world. Then we could just depend on each
186     // attachment to give its own size since we don't have GrGpuResources owning other
187     // GrGpuResources. Until we get to that point we need to live in some hybrid world. We will let
188     // the msaa and stencil attachments track their own size because they do get cached separately.
189     // For all GrTexture* based things we will continue to to use the GrTexture* to report size and
190     // the owned attachments will have no size and be uncached.
191 #ifdef SK_DEBUG
192     // The nonMSAA attachment (either color or resolve depending on numSamples should have size of
193     // zero since it is a texture attachment.
194     SkASSERT(this->nonMSAAAttachment()->gpuMemorySize() == 0);
195     if (this->numSamples() > 1) {
196         // Msaa attachment should have a valid size
197         SkASSERT(this->colorAttachment()->gpuMemorySize() ==
198                  GrSurface::ComputeSize(this->backendFormat(),
199                                         this->dimensions(),
200                                         this->numSamples(),
201                                         skgpu::Mipmapped::kNo));
202     }
203 #endif
204     return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
205                                   1 /*colorSamplesPerPixel*/, this->mipmapped());
206 }
207