• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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