xref: /aosp_15_r20/external/skia/src/gpu/ganesh/vk/GrVkTexture.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/GrVkTexture.h"
9 
10 #include "include/core/SkSize.h"
11 #include "include/gpu/GpuTypes.h"
12 #include "include/gpu/MutableTextureState.h"
13 #include "include/gpu/ganesh/vk/GrVkTypes.h"
14 #include "include/gpu/vk/VulkanTypes.h"
15 #include "include/private/base/SkAssert.h"
16 #include "include/private/base/SkTo.h"
17 #include "src/gpu/ganesh/GrAttachment.h"
18 #include "src/gpu/ganesh/GrSurface.h"
19 #include "src/gpu/ganesh/GrTexture.h"
20 #include "src/gpu/ganesh/vk/GrVkBackendSurfacePriv.h"
21 #include "src/gpu/ganesh/vk/GrVkDescriptorSet.h"
22 #include "src/gpu/ganesh/vk/GrVkGpu.h"
23 #include "src/gpu/ganesh/vk/GrVkUtil.h"
24 #include "src/gpu/vk/VulkanUtilsPriv.h"
25 
26 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
27 
28 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
GrVkTexture(GrVkGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,sk_sp<GrVkImage> texture,GrMipmapStatus mipmapStatus,std::string_view label)29 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
30                          skgpu::Budgeted budgeted,
31                          SkISize dimensions,
32                          sk_sp<GrVkImage> texture,
33                          GrMipmapStatus mipmapStatus,
34                          std::string_view label)
35         : GrSurface(gpu,
36                     dimensions,
37                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
38                     label)
39         , GrTexture(gpu,
40                     dimensions,
41                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
42                     GrTextureType::k2D,
43                     mipmapStatus,
44                     label)
45         , fTexture(std::move(texture))
46         , fDescSetCache(kMaxCachedDescSets) {
47     SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
48     // We don't support creating external GrVkTextures
49     SkASSERT(!fTexture->ycbcrConversionInfo().isValid() ||
50              !fTexture->ycbcrConversionInfo().fExternalFormat);
51     SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
52     this->registerWithCache(budgeted);
53     if (skgpu::VkFormatIsCompressed(fTexture->imageFormat())) {
54         this->setReadOnly();
55     }
56 }
57 
GrVkTexture(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkImage> texture,GrMipmapStatus mipmapStatus,GrWrapCacheable cacheable,GrIOType ioType,bool isExternal,std::string_view label)58 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
59                          SkISize dimensions,
60                          sk_sp<GrVkImage> texture,
61                          GrMipmapStatus mipmapStatus,
62                          GrWrapCacheable cacheable,
63                          GrIOType ioType,
64                          bool isExternal,
65                          std::string_view label)
66         : GrSurface(gpu,
67                     dimensions,
68                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
69                     label)
70         , GrTexture(gpu,
71                     dimensions,
72                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
73                     isExternal ? GrTextureType::kExternal : GrTextureType::k2D,
74                     mipmapStatus,
75                     label)
76         , fTexture(std::move(texture))
77         , fDescSetCache(kMaxCachedDescSets) {
78     SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
79     SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
80     if (ioType == kRead_GrIOType) {
81         this->setReadOnly();
82     }
83     this->registerWithCacheWrapped(cacheable);
84 }
85 
86 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
GrVkTexture(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkImage> texture,GrMipmapStatus mipmapStatus,std::string_view label)87 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
88                          SkISize dimensions,
89                          sk_sp<GrVkImage> texture,
90                          GrMipmapStatus mipmapStatus,
91                          std::string_view label)
92         : GrSurface(gpu,
93                     dimensions,
94                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
95                     label)
96         , GrTexture(gpu,
97                     dimensions,
98                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
99                     GrTextureType::k2D,
100                     mipmapStatus,
101                     label)
102         , fTexture(std::move(texture))
103         , fDescSetCache(kMaxCachedDescSets) {
104     SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
105     // Since this ctor is only called from GrVkTextureRenderTarget, we can't have a ycbcr conversion
106     // since we don't support that on render targets.
107     SkASSERT(!fTexture->ycbcrConversionInfo().isValid());
108     SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
109 }
110 
MakeNewTexture(GrVkGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,VkFormat format,uint32_t mipLevels,GrProtected isProtected,GrMipmapStatus mipmapStatus,std::string_view label)111 sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu,
112                                                skgpu::Budgeted budgeted,
113                                                SkISize dimensions,
114                                                VkFormat format,
115                                                uint32_t mipLevels,
116                                                GrProtected isProtected,
117                                                GrMipmapStatus mipmapStatus,
118                                                std::string_view label) {
119     sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(
120             gpu, dimensions, format, mipLevels, GrRenderable::kNo, /*numSamples=*/1, budgeted,
121             isProtected);
122 
123     if (!texture) {
124         return nullptr;
125     }
126     return sk_sp<GrVkTexture>(new GrVkTexture(
127             gpu, budgeted, dimensions, std::move(texture), mipmapStatus, label));
128 }
129 
MakeWrappedTexture(GrVkGpu * gpu,SkISize dimensions,GrWrapOwnership wrapOwnership,GrWrapCacheable cacheable,GrIOType ioType,const GrVkImageInfo & info,sk_sp<skgpu::MutableTextureState> mutableState)130 sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(
131         GrVkGpu* gpu, SkISize dimensions, GrWrapOwnership wrapOwnership, GrWrapCacheable cacheable,
132         GrIOType ioType, const GrVkImageInfo& info,
133         sk_sp<skgpu::MutableTextureState> mutableState) {
134     // Adopted textures require both image and allocation because we're responsible for freeing
135     SkASSERT(VK_NULL_HANDLE != info.fImage &&
136              (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
137 
138     sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
139                                                       dimensions,
140                                                       info,
141                                                       std::move(mutableState),
142                                                       GrAttachment::UsageFlags::kTexture,
143                                                       wrapOwnership,
144                                                       cacheable,
145                                                       "VkImage_MakeWrappedTexture");
146     if (!texture) {
147         return nullptr;
148     }
149 
150     GrMipmapStatus mipmapStatus = info.fLevelCount > 1 ? GrMipmapStatus::kValid
151                                                        : GrMipmapStatus::kNotAllocated;
152 
153     bool isExternal = info.fYcbcrConversionInfo.isValid() &&
154                       (info.fYcbcrConversionInfo.fExternalFormat != 0);
155     isExternal |= (info.fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
156     return sk_sp<GrVkTexture>(new GrVkTexture(gpu,
157                                               dimensions,
158                                               std::move(texture),
159                                               mipmapStatus,
160                                               cacheable,
161                                               ioType,
162                                               isExternal,
163                                               /*label=*/"Vk_MakeWrappedTexture"));
164 }
165 
~GrVkTexture()166 GrVkTexture::~GrVkTexture() {
167     // either release or abandon should have been called by the owner of this object.
168     SkASSERT(!fTexture);
169 }
170 
onRelease()171 void GrVkTexture::onRelease() {
172     fTexture.reset();
173 
174     fDescSetCache.reset();
175 
176     GrTexture::onRelease();
177 }
178 
179 struct GrVkTexture::DescriptorCacheEntry {
DescriptorCacheEntryGrVkTexture::DescriptorCacheEntry180     DescriptorCacheEntry(const GrVkDescriptorSet* fDescSet, GrVkGpu* gpu)
181             : fDescriptorSet(fDescSet), fGpu(gpu) {}
~DescriptorCacheEntryGrVkTexture::DescriptorCacheEntry182     ~DescriptorCacheEntry() {
183         if (fDescriptorSet) {
184             fDescriptorSet->recycle();
185         }
186     }
187 
188     const GrVkDescriptorSet* fDescriptorSet;
189     GrVkGpu* fGpu;
190 };
191 
onAbandon()192 void GrVkTexture::onAbandon() {
193     fTexture.reset();
194 
195     fDescSetCache.reset();
196 
197     GrTexture::onAbandon();
198 }
199 
getBackendTexture() const200 GrBackendTexture GrVkTexture::getBackendTexture() const {
201     return GrBackendTextures::MakeVk(fTexture->width(),
202                                      fTexture->height(),
203                                      fTexture->vkImageInfo(),
204                                      fTexture->getMutableState());
205 }
206 
getVkGpu() const207 GrVkGpu* GrVkTexture::getVkGpu() const {
208     SkASSERT(!this->wasDestroyed());
209     return static_cast<GrVkGpu*>(this->getGpu());
210 }
211 
textureView()212 const GrVkImageView* GrVkTexture::textureView() { return fTexture->textureView(); }
213 
cachedSingleDescSet(GrSamplerState state)214 const GrVkDescriptorSet* GrVkTexture::cachedSingleDescSet(GrSamplerState state) {
215     if (std::unique_ptr<DescriptorCacheEntry>* e = fDescSetCache.find(state)) {
216         return (*e)->fDescriptorSet;
217     }
218     return nullptr;
219 }
220 
addDescriptorSetToCache(const GrVkDescriptorSet * descSet,GrSamplerState state)221 void GrVkTexture::addDescriptorSetToCache(const GrVkDescriptorSet* descSet, GrSamplerState state) {
222     SkASSERT(!fDescSetCache.find(state));
223     descSet->ref();
224     fDescSetCache.insert(state, std::make_unique<DescriptorCacheEntry>(descSet, this->getVkGpu()));
225 }
226