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