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