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