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