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 this->registerWithCache(budgeted);
41 if (GrVkFormatIsCompressed(fTexture->imageFormat())) {
42 this->setReadOnly();
43 }
44 }
45
GrVkTexture(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkImage> texture,GrMipmapStatus mipmapStatus,GrWrapCacheable cacheable,GrIOType ioType,bool isExternal)46 GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkISize dimensions,
47 sk_sp<GrVkImage> texture, GrMipmapStatus mipmapStatus,
48 GrWrapCacheable cacheable, GrIOType ioType, bool isExternal)
49 : GrSurface(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
50 , GrTexture(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
51 isExternal ? GrTextureType::kExternal : GrTextureType::k2D, mipmapStatus)
52 , fTexture(std::move(texture))
53 , fDescSetCache(kMaxCachedDescSets) {
54 SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
55 SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
56 if (ioType == kRead_GrIOType) {
57 this->setReadOnly();
58 }
59 this->registerWithCacheWrapped(cacheable);
60 }
61
62 // 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)63 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
64 SkISize dimensions,
65 sk_sp<GrVkImage> texture,
66 GrMipmapStatus mipmapStatus)
67 : GrSurface(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo)
68 , GrTexture(gpu, dimensions, texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
69 GrTextureType::k2D, mipmapStatus)
70 , fTexture(std::move(texture))
71 , fDescSetCache(kMaxCachedDescSets) {
72 SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
73 // Since this ctor is only called from GrVkTextureRenderTarget, we can't have a ycbcr conversion
74 // since we don't support that on render targets.
75 SkASSERT(!fTexture->ycbcrConversionInfo().isValid());
76 SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
77 }
78
MakeNewTexture(GrVkGpu * gpu,SkBudgeted budgeted,SkISize dimensions,VkFormat format,uint32_t mipLevels,GrProtected isProtected,GrMipmapStatus mipmapStatus)79 sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
80 SkISize dimensions,
81 VkFormat format, uint32_t mipLevels,
82 GrProtected isProtected,
83 GrMipmapStatus mipmapStatus) {
84 sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(
85 gpu, dimensions, format, mipLevels, GrRenderable::kNo, /*numSamples=*/1, budgeted,
86 isProtected);
87
88 if (!texture) {
89 return nullptr;
90 }
91 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, dimensions, std::move(texture),
92 mipmapStatus));
93 }
94
MakeWrappedTexture(GrVkGpu * gpu,SkISize dimensions,GrWrapOwnership wrapOwnership,GrWrapCacheable cacheable,GrIOType ioType,const GrVkImageInfo & info,sk_sp<GrBackendSurfaceMutableStateImpl> mutableState)95 sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(
96 GrVkGpu* gpu, SkISize dimensions, GrWrapOwnership wrapOwnership, GrWrapCacheable cacheable,
97 GrIOType ioType, const GrVkImageInfo& info,
98 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState) {
99 // Adopted textures require both image and allocation because we're responsible for freeing
100 SkASSERT(VK_NULL_HANDLE != info.fImage &&
101 (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
102
103 sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
104 dimensions,
105 info,
106 std::move(mutableState),
107 GrAttachment::UsageFlags::kTexture,
108 wrapOwnership,
109 cacheable);
110 if (!texture) {
111 return nullptr;
112 }
113
114 GrMipmapStatus mipmapStatus = info.fLevelCount > 1 ? GrMipmapStatus::kValid
115 : GrMipmapStatus::kNotAllocated;
116
117 bool isExternal = info.fYcbcrConversionInfo.isValid() &&
118 (info.fYcbcrConversionInfo.fExternalFormat != 0);
119 isExternal |= (info.fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
120 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, dimensions, std::move(texture), mipmapStatus,
121 cacheable, ioType, isExternal));
122 }
123
~GrVkTexture()124 GrVkTexture::~GrVkTexture() {
125 // either release or abandon should have been called by the owner of this object.
126 SkASSERT(!fTexture);
127 }
128
onRelease()129 void GrVkTexture::onRelease() {
130 fTexture.reset();
131
132 fDescSetCache.reset();
133
134 GrTexture::onRelease();
135 }
136
137 struct GrVkTexture::DescriptorCacheEntry {
DescriptorCacheEntryGrVkTexture::DescriptorCacheEntry138 DescriptorCacheEntry(const GrVkDescriptorSet* fDescSet, GrVkGpu* gpu)
139 : fDescriptorSet(fDescSet), fGpu(gpu) {}
~DescriptorCacheEntryGrVkTexture::DescriptorCacheEntry140 ~DescriptorCacheEntry() {
141 if (fDescriptorSet) {
142 fDescriptorSet->recycle();
143 }
144 }
145
146 const GrVkDescriptorSet* fDescriptorSet;
147 GrVkGpu* fGpu;
148 };
149
onAbandon()150 void GrVkTexture::onAbandon() {
151 fTexture.reset();
152
153 fDescSetCache.reset();
154
155 GrTexture::onAbandon();
156 }
157
getBackendTexture() const158 GrBackendTexture GrVkTexture::getBackendTexture() const {
159 return GrBackendTexture(fTexture->width(), fTexture->height(), fTexture->vkImageInfo(),
160 fTexture->getMutableState());
161 }
162
getVkGpu() const163 GrVkGpu* GrVkTexture::getVkGpu() const {
164 SkASSERT(!this->wasDestroyed());
165 return static_cast<GrVkGpu*>(this->getGpu());
166 }
167
textureView()168 const GrVkImageView* GrVkTexture::textureView() { return fTexture->textureView(); }
169
cachedSingleDescSet(GrSamplerState state)170 const GrVkDescriptorSet* GrVkTexture::cachedSingleDescSet(GrSamplerState state) {
171 if (std::unique_ptr<DescriptorCacheEntry>* e = fDescSetCache.find(state)) {
172 return (*e)->fDescriptorSet;
173 }
174 return nullptr;
175 }
176
addDescriptorSetToCache(const GrVkDescriptorSet * descSet,GrSamplerState state)177 void GrVkTexture::addDescriptorSetToCache(const GrVkDescriptorSet* descSet, GrSamplerState state) {
178 SkASSERT(!fDescSetCache.find(state));
179 descSet->ref();
180 fDescSetCache.insert(state, std::make_unique<DescriptorCacheEntry>(descSet, this->getVkGpu()));
181 }
182
dumpMemoryStatistics(SkTraceMemoryDump * traceMemoryDump) const183 void GrVkTexture::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
184 size_t size = GrSurface::ComputeSize(this->backendFormat(), this->dimensions(), 1,
185 this->mipmapped());
186 SkString resourceName = this->getResourceName();
187 resourceName.append("/texture");
188 this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "Texture", size);
189 }
190