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