• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef SKIA_OHOS
53     if (fTexture->GetBudgeted() == skgpu::Budgeted::kYes) {
54         this->registerWithCache(skgpu::Budgeted::kNo);
55     } else {
56         this->registerWithCache(budgeted);
57     }
58 #else
59     this->registerWithCache(budgeted);
60 #endif
61     if (skgpu::VkFormatIsCompressed(fTexture->imageFormat())) {
62         this->setReadOnly();
63     }
64 }
65 
GrVkTexture(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkImage> texture,GrMipmapStatus mipmapStatus,GrWrapCacheable cacheable,GrIOType ioType,bool isExternal,std::string_view label)66 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
67                          SkISize dimensions,
68                          sk_sp<GrVkImage> texture,
69                          GrMipmapStatus mipmapStatus,
70                          GrWrapCacheable cacheable,
71                          GrIOType ioType,
72                          bool isExternal,
73                          std::string_view label)
74         : GrSurface(gpu,
75                     dimensions,
76                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
77                     label)
78         , GrTexture(gpu,
79                     dimensions,
80                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
81                     isExternal ? GrTextureType::kExternal : GrTextureType::k2D,
82                     mipmapStatus,
83                     label)
84         , fTexture(std::move(texture))
85         , fDescSetCache(kMaxCachedDescSets) {
86     SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
87     SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
88     if (ioType == kRead_GrIOType) {
89         this->setReadOnly();
90     }
91     this->registerWithCacheWrapped(cacheable);
92 }
93 
94 // 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)95 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
96                          SkISize dimensions,
97                          sk_sp<GrVkImage> texture,
98                          GrMipmapStatus mipmapStatus,
99                          std::string_view label)
100         : GrSurface(gpu,
101                     dimensions,
102                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
103                     label)
104         , GrTexture(gpu,
105                     dimensions,
106                     texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
107                     GrTextureType::k2D,
108                     mipmapStatus,
109                     label)
110         , fTexture(std::move(texture))
111         , fDescSetCache(kMaxCachedDescSets) {
112     SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
113     // Since this ctor is only called from GrVkTextureRenderTarget, we can't have a ycbcr conversion
114     // since we don't support that on render targets.
115     SkASSERT(!fTexture->ycbcrConversionInfo().isValid());
116     SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
117 }
118 
MakeNewTexture(GrVkGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,VkFormat format,uint32_t mipLevels,GrProtected isProtected,GrMipmapStatus mipmapStatus,std::string_view label)119 sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu,
120                                                skgpu::Budgeted budgeted,
121                                                SkISize dimensions,
122                                                VkFormat format,
123                                                uint32_t mipLevels,
124                                                GrProtected isProtected,
125                                                GrMipmapStatus mipmapStatus,
126                                                std::string_view label) {
127     sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(
128             gpu, dimensions, format, mipLevels, GrRenderable::kNo, /*numSamples=*/1, budgeted,
129             isProtected);
130 
131     if (!texture) {
132         return nullptr;
133     }
134     return sk_sp<GrVkTexture>(new GrVkTexture(
135             gpu, budgeted, dimensions, std::move(texture), mipmapStatus, label));
136 }
137 
MakeWrappedTexture(GrVkGpu * gpu,SkISize dimensions,GrWrapOwnership wrapOwnership,GrWrapCacheable cacheable,GrIOType ioType,const GrVkImageInfo & info,sk_sp<skgpu::MutableTextureState> mutableState)138 sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(
139         GrVkGpu* gpu, SkISize dimensions, GrWrapOwnership wrapOwnership, GrWrapCacheable cacheable,
140         GrIOType ioType, const GrVkImageInfo& info,
141         sk_sp<skgpu::MutableTextureState> mutableState) {
142     // Adopted textures require both image and allocation because we're responsible for freeing
143     SkASSERT(VK_NULL_HANDLE != info.fImage &&
144              (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
145 
146     sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
147                                                       dimensions,
148                                                       info,
149                                                       std::move(mutableState),
150                                                       GrAttachment::UsageFlags::kTexture,
151                                                       wrapOwnership,
152                                                       cacheable,
153                                                       "VkImage_MakeWrappedTexture");
154     if (!texture) {
155         return nullptr;
156     }
157 
158     GrMipmapStatus mipmapStatus = info.fLevelCount > 1 ? GrMipmapStatus::kValid
159                                                        : GrMipmapStatus::kNotAllocated;
160 
161     bool isExternal = info.fYcbcrConversionInfo.isValid() &&
162                       (info.fYcbcrConversionInfo.fExternalFormat != 0);
163     isExternal |= (info.fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
164     return sk_sp<GrVkTexture>(new GrVkTexture(gpu,
165                                               dimensions,
166                                               std::move(texture),
167                                               mipmapStatus,
168                                               cacheable,
169                                               ioType,
170                                               isExternal,
171                                               /*label=*/"Vk_MakeWrappedTexture"));
172 }
173 
~GrVkTexture()174 GrVkTexture::~GrVkTexture() {
175     // either release or abandon should have been called by the owner of this object.
176     SkASSERT(!fTexture);
177 }
178 
onRelease()179 void GrVkTexture::onRelease() {
180     fTexture.reset();
181 
182     fDescSetCache.reset();
183 
184     GrTexture::onRelease();
185 }
186 
187 struct GrVkTexture::DescriptorCacheEntry {
DescriptorCacheEntryGrVkTexture::DescriptorCacheEntry188     DescriptorCacheEntry(const GrVkDescriptorSet* fDescSet, GrVkGpu* gpu)
189             : fDescriptorSet(fDescSet), fGpu(gpu) {}
~DescriptorCacheEntryGrVkTexture::DescriptorCacheEntry190     ~DescriptorCacheEntry() {
191         if (fDescriptorSet) {
192             fDescriptorSet->recycle();
193         }
194     }
195 
196     const GrVkDescriptorSet* fDescriptorSet;
197     GrVkGpu* fGpu;
198 };
199 
onAbandon()200 void GrVkTexture::onAbandon() {
201     fTexture.reset();
202 
203     fDescSetCache.reset();
204 
205     GrTexture::onAbandon();
206 }
207 
getBackendTexture() const208 GrBackendTexture GrVkTexture::getBackendTexture() const {
209     return GrBackendTextures::MakeVk(fTexture->width(),
210                                      fTexture->height(),
211                                      fTexture->vkImageInfo(),
212                                      fTexture->getMutableState());
213 }
214 
getVkGpu() const215 GrVkGpu* GrVkTexture::getVkGpu() const {
216     SkASSERT(!this->wasDestroyed());
217     return static_cast<GrVkGpu*>(this->getGpu());
218 }
219 
textureView()220 const GrVkImageView* GrVkTexture::textureView() { return fTexture->textureView(); }
221 
cachedSingleDescSet(GrSamplerState state)222 const GrVkDescriptorSet* GrVkTexture::cachedSingleDescSet(GrSamplerState state) {
223     if (std::unique_ptr<DescriptorCacheEntry>* e = fDescSetCache.find(state)) {
224         return (*e)->fDescriptorSet;
225     }
226     return nullptr;
227 }
228 
addDescriptorSetToCache(const GrVkDescriptorSet * descSet,GrSamplerState state)229 void GrVkTexture::addDescriptorSetToCache(const GrVkDescriptorSet* descSet, GrSamplerState state) {
230     SkASSERT(!fDescSetCache.find(state));
231     descSet->ref();
232     fDescSetCache.insert(state, std::make_unique<DescriptorCacheEntry>(descSet, this->getVkGpu()));
233 }
234 
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const235 void GrVkTexture::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
236     size_t size = GrSurface::ComputeSize(this->backendFormat(), this->dimensions(), 1,
237                                          this->mipmapped());
238     SkString resourceName = this->getResourceName();
239     resourceName.append("/texture");
240     if (fTexture->isBorrowed() && !fTexture->isRealAlloc()) {
241         this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "External Texture", size);
242     } else {
243         this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "Texture", size);
244     }
245 }
246 
247 #ifdef SKIA_DFX_FOR_RECORD_VKIMAGE
updateNodeId(uint64_t nodeId)248 void GrVkTexture::updateNodeId(uint64_t nodeId) {
249     if (fTexture != nullptr) {
250         fTexture->updateNodeId(nodeId);
251     }
252 }
253 #endif
254