1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkTexture.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/MutableTextureState.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/vk/GrVkTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanTypes.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrAttachment.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkBackendSurfacePriv.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkDescriptorSet.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkGpu.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkUtil.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanUtilsPriv.h"
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker // 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)29*c8dee2aaSAndroid Build Coastguard Worker GrVkTexture::GrVkTexture(GrVkGpu* gpu,
30*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
31*c8dee2aaSAndroid Build Coastguard Worker SkISize dimensions,
32*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrVkImage> texture,
33*c8dee2aaSAndroid Build Coastguard Worker GrMipmapStatus mipmapStatus,
34*c8dee2aaSAndroid Build Coastguard Worker std::string_view label)
35*c8dee2aaSAndroid Build Coastguard Worker : GrSurface(gpu,
36*c8dee2aaSAndroid Build Coastguard Worker dimensions,
37*c8dee2aaSAndroid Build Coastguard Worker texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
38*c8dee2aaSAndroid Build Coastguard Worker label)
39*c8dee2aaSAndroid Build Coastguard Worker , GrTexture(gpu,
40*c8dee2aaSAndroid Build Coastguard Worker dimensions,
41*c8dee2aaSAndroid Build Coastguard Worker texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
42*c8dee2aaSAndroid Build Coastguard Worker GrTextureType::k2D,
43*c8dee2aaSAndroid Build Coastguard Worker mipmapStatus,
44*c8dee2aaSAndroid Build Coastguard Worker label)
45*c8dee2aaSAndroid Build Coastguard Worker , fTexture(std::move(texture))
46*c8dee2aaSAndroid Build Coastguard Worker , fDescSetCache(kMaxCachedDescSets) {
47*c8dee2aaSAndroid Build Coastguard Worker SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
48*c8dee2aaSAndroid Build Coastguard Worker // We don't support creating external GrVkTextures
49*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fTexture->ycbcrConversionInfo().isValid() ||
50*c8dee2aaSAndroid Build Coastguard Worker !fTexture->ycbcrConversionInfo().fExternalFormat);
51*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
52*c8dee2aaSAndroid Build Coastguard Worker this->registerWithCache(budgeted);
53*c8dee2aaSAndroid Build Coastguard Worker if (skgpu::VkFormatIsCompressed(fTexture->imageFormat())) {
54*c8dee2aaSAndroid Build Coastguard Worker this->setReadOnly();
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker
GrVkTexture(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkImage> texture,GrMipmapStatus mipmapStatus,GrWrapCacheable cacheable,GrIOType ioType,bool isExternal,std::string_view label)58*c8dee2aaSAndroid Build Coastguard Worker GrVkTexture::GrVkTexture(GrVkGpu* gpu,
59*c8dee2aaSAndroid Build Coastguard Worker SkISize dimensions,
60*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrVkImage> texture,
61*c8dee2aaSAndroid Build Coastguard Worker GrMipmapStatus mipmapStatus,
62*c8dee2aaSAndroid Build Coastguard Worker GrWrapCacheable cacheable,
63*c8dee2aaSAndroid Build Coastguard Worker GrIOType ioType,
64*c8dee2aaSAndroid Build Coastguard Worker bool isExternal,
65*c8dee2aaSAndroid Build Coastguard Worker std::string_view label)
66*c8dee2aaSAndroid Build Coastguard Worker : GrSurface(gpu,
67*c8dee2aaSAndroid Build Coastguard Worker dimensions,
68*c8dee2aaSAndroid Build Coastguard Worker texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
69*c8dee2aaSAndroid Build Coastguard Worker label)
70*c8dee2aaSAndroid Build Coastguard Worker , GrTexture(gpu,
71*c8dee2aaSAndroid Build Coastguard Worker dimensions,
72*c8dee2aaSAndroid Build Coastguard Worker texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
73*c8dee2aaSAndroid Build Coastguard Worker isExternal ? GrTextureType::kExternal : GrTextureType::k2D,
74*c8dee2aaSAndroid Build Coastguard Worker mipmapStatus,
75*c8dee2aaSAndroid Build Coastguard Worker label)
76*c8dee2aaSAndroid Build Coastguard Worker , fTexture(std::move(texture))
77*c8dee2aaSAndroid Build Coastguard Worker , fDescSetCache(kMaxCachedDescSets) {
78*c8dee2aaSAndroid Build Coastguard Worker SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
79*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
80*c8dee2aaSAndroid Build Coastguard Worker if (ioType == kRead_GrIOType) {
81*c8dee2aaSAndroid Build Coastguard Worker this->setReadOnly();
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker this->registerWithCacheWrapped(cacheable);
84*c8dee2aaSAndroid Build Coastguard Worker }
85*c8dee2aaSAndroid Build Coastguard Worker
86*c8dee2aaSAndroid Build Coastguard Worker // 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)87*c8dee2aaSAndroid Build Coastguard Worker GrVkTexture::GrVkTexture(GrVkGpu* gpu,
88*c8dee2aaSAndroid Build Coastguard Worker SkISize dimensions,
89*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrVkImage> texture,
90*c8dee2aaSAndroid Build Coastguard Worker GrMipmapStatus mipmapStatus,
91*c8dee2aaSAndroid Build Coastguard Worker std::string_view label)
92*c8dee2aaSAndroid Build Coastguard Worker : GrSurface(gpu,
93*c8dee2aaSAndroid Build Coastguard Worker dimensions,
94*c8dee2aaSAndroid Build Coastguard Worker texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
95*c8dee2aaSAndroid Build Coastguard Worker label)
96*c8dee2aaSAndroid Build Coastguard Worker , GrTexture(gpu,
97*c8dee2aaSAndroid Build Coastguard Worker dimensions,
98*c8dee2aaSAndroid Build Coastguard Worker texture->isProtected() ? GrProtected::kYes : GrProtected::kNo,
99*c8dee2aaSAndroid Build Coastguard Worker GrTextureType::k2D,
100*c8dee2aaSAndroid Build Coastguard Worker mipmapStatus,
101*c8dee2aaSAndroid Build Coastguard Worker label)
102*c8dee2aaSAndroid Build Coastguard Worker , fTexture(std::move(texture))
103*c8dee2aaSAndroid Build Coastguard Worker , fDescSetCache(kMaxCachedDescSets) {
104*c8dee2aaSAndroid Build Coastguard Worker SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == fTexture->mipLevels()));
105*c8dee2aaSAndroid Build Coastguard Worker // Since this ctor is only called from GrVkTextureRenderTarget, we can't have a ycbcr conversion
106*c8dee2aaSAndroid Build Coastguard Worker // since we don't support that on render targets.
107*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fTexture->ycbcrConversionInfo().isValid());
108*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkToBool(fTexture->vkUsageFlags() & VK_IMAGE_USAGE_SAMPLED_BIT));
109*c8dee2aaSAndroid Build Coastguard Worker }
110*c8dee2aaSAndroid Build Coastguard Worker
MakeNewTexture(GrVkGpu * gpu,skgpu::Budgeted budgeted,SkISize dimensions,VkFormat format,uint32_t mipLevels,GrProtected isProtected,GrMipmapStatus mipmapStatus,std::string_view label)111*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu,
112*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted,
113*c8dee2aaSAndroid Build Coastguard Worker SkISize dimensions,
114*c8dee2aaSAndroid Build Coastguard Worker VkFormat format,
115*c8dee2aaSAndroid Build Coastguard Worker uint32_t mipLevels,
116*c8dee2aaSAndroid Build Coastguard Worker GrProtected isProtected,
117*c8dee2aaSAndroid Build Coastguard Worker GrMipmapStatus mipmapStatus,
118*c8dee2aaSAndroid Build Coastguard Worker std::string_view label) {
119*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrVkImage> texture = GrVkImage::MakeTexture(
120*c8dee2aaSAndroid Build Coastguard Worker gpu, dimensions, format, mipLevels, GrRenderable::kNo, /*numSamples=*/1, budgeted,
121*c8dee2aaSAndroid Build Coastguard Worker isProtected);
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker if (!texture) {
124*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
125*c8dee2aaSAndroid Build Coastguard Worker }
126*c8dee2aaSAndroid Build Coastguard Worker return sk_sp<GrVkTexture>(new GrVkTexture(
127*c8dee2aaSAndroid Build Coastguard Worker gpu, budgeted, dimensions, std::move(texture), mipmapStatus, label));
128*c8dee2aaSAndroid Build Coastguard Worker }
129*c8dee2aaSAndroid Build Coastguard Worker
MakeWrappedTexture(GrVkGpu * gpu,SkISize dimensions,GrWrapOwnership wrapOwnership,GrWrapCacheable cacheable,GrIOType ioType,const GrVkImageInfo & info,sk_sp<skgpu::MutableTextureState> mutableState)130*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(
131*c8dee2aaSAndroid Build Coastguard Worker GrVkGpu* gpu, SkISize dimensions, GrWrapOwnership wrapOwnership, GrWrapCacheable cacheable,
132*c8dee2aaSAndroid Build Coastguard Worker GrIOType ioType, const GrVkImageInfo& info,
133*c8dee2aaSAndroid Build Coastguard Worker sk_sp<skgpu::MutableTextureState> mutableState) {
134*c8dee2aaSAndroid Build Coastguard Worker // Adopted textures require both image and allocation because we're responsible for freeing
135*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(VK_NULL_HANDLE != info.fImage &&
136*c8dee2aaSAndroid Build Coastguard Worker (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
137*c8dee2aaSAndroid Build Coastguard Worker
138*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(gpu,
139*c8dee2aaSAndroid Build Coastguard Worker dimensions,
140*c8dee2aaSAndroid Build Coastguard Worker info,
141*c8dee2aaSAndroid Build Coastguard Worker std::move(mutableState),
142*c8dee2aaSAndroid Build Coastguard Worker GrAttachment::UsageFlags::kTexture,
143*c8dee2aaSAndroid Build Coastguard Worker wrapOwnership,
144*c8dee2aaSAndroid Build Coastguard Worker cacheable,
145*c8dee2aaSAndroid Build Coastguard Worker "VkImage_MakeWrappedTexture");
146*c8dee2aaSAndroid Build Coastguard Worker if (!texture) {
147*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker
150*c8dee2aaSAndroid Build Coastguard Worker GrMipmapStatus mipmapStatus = info.fLevelCount > 1 ? GrMipmapStatus::kValid
151*c8dee2aaSAndroid Build Coastguard Worker : GrMipmapStatus::kNotAllocated;
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker bool isExternal = info.fYcbcrConversionInfo.isValid() &&
154*c8dee2aaSAndroid Build Coastguard Worker (info.fYcbcrConversionInfo.fExternalFormat != 0);
155*c8dee2aaSAndroid Build Coastguard Worker isExternal |= (info.fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
156*c8dee2aaSAndroid Build Coastguard Worker return sk_sp<GrVkTexture>(new GrVkTexture(gpu,
157*c8dee2aaSAndroid Build Coastguard Worker dimensions,
158*c8dee2aaSAndroid Build Coastguard Worker std::move(texture),
159*c8dee2aaSAndroid Build Coastguard Worker mipmapStatus,
160*c8dee2aaSAndroid Build Coastguard Worker cacheable,
161*c8dee2aaSAndroid Build Coastguard Worker ioType,
162*c8dee2aaSAndroid Build Coastguard Worker isExternal,
163*c8dee2aaSAndroid Build Coastguard Worker /*label=*/"Vk_MakeWrappedTexture"));
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker
~GrVkTexture()166*c8dee2aaSAndroid Build Coastguard Worker GrVkTexture::~GrVkTexture() {
167*c8dee2aaSAndroid Build Coastguard Worker // either release or abandon should have been called by the owner of this object.
168*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fTexture);
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker
onRelease()171*c8dee2aaSAndroid Build Coastguard Worker void GrVkTexture::onRelease() {
172*c8dee2aaSAndroid Build Coastguard Worker fTexture.reset();
173*c8dee2aaSAndroid Build Coastguard Worker
174*c8dee2aaSAndroid Build Coastguard Worker fDescSetCache.reset();
175*c8dee2aaSAndroid Build Coastguard Worker
176*c8dee2aaSAndroid Build Coastguard Worker GrTexture::onRelease();
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker struct GrVkTexture::DescriptorCacheEntry {
DescriptorCacheEntryGrVkTexture::DescriptorCacheEntry180*c8dee2aaSAndroid Build Coastguard Worker DescriptorCacheEntry(const GrVkDescriptorSet* fDescSet, GrVkGpu* gpu)
181*c8dee2aaSAndroid Build Coastguard Worker : fDescriptorSet(fDescSet), fGpu(gpu) {}
~DescriptorCacheEntryGrVkTexture::DescriptorCacheEntry182*c8dee2aaSAndroid Build Coastguard Worker ~DescriptorCacheEntry() {
183*c8dee2aaSAndroid Build Coastguard Worker if (fDescriptorSet) {
184*c8dee2aaSAndroid Build Coastguard Worker fDescriptorSet->recycle();
185*c8dee2aaSAndroid Build Coastguard Worker }
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker const GrVkDescriptorSet* fDescriptorSet;
189*c8dee2aaSAndroid Build Coastguard Worker GrVkGpu* fGpu;
190*c8dee2aaSAndroid Build Coastguard Worker };
191*c8dee2aaSAndroid Build Coastguard Worker
onAbandon()192*c8dee2aaSAndroid Build Coastguard Worker void GrVkTexture::onAbandon() {
193*c8dee2aaSAndroid Build Coastguard Worker fTexture.reset();
194*c8dee2aaSAndroid Build Coastguard Worker
195*c8dee2aaSAndroid Build Coastguard Worker fDescSetCache.reset();
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker GrTexture::onAbandon();
198*c8dee2aaSAndroid Build Coastguard Worker }
199*c8dee2aaSAndroid Build Coastguard Worker
getBackendTexture() const200*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture GrVkTexture::getBackendTexture() const {
201*c8dee2aaSAndroid Build Coastguard Worker return GrBackendTextures::MakeVk(fTexture->width(),
202*c8dee2aaSAndroid Build Coastguard Worker fTexture->height(),
203*c8dee2aaSAndroid Build Coastguard Worker fTexture->vkImageInfo(),
204*c8dee2aaSAndroid Build Coastguard Worker fTexture->getMutableState());
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker
getVkGpu() const207*c8dee2aaSAndroid Build Coastguard Worker GrVkGpu* GrVkTexture::getVkGpu() const {
208*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!this->wasDestroyed());
209*c8dee2aaSAndroid Build Coastguard Worker return static_cast<GrVkGpu*>(this->getGpu());
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker
textureView()212*c8dee2aaSAndroid Build Coastguard Worker const GrVkImageView* GrVkTexture::textureView() { return fTexture->textureView(); }
213*c8dee2aaSAndroid Build Coastguard Worker
cachedSingleDescSet(GrSamplerState state)214*c8dee2aaSAndroid Build Coastguard Worker const GrVkDescriptorSet* GrVkTexture::cachedSingleDescSet(GrSamplerState state) {
215*c8dee2aaSAndroid Build Coastguard Worker if (std::unique_ptr<DescriptorCacheEntry>* e = fDescSetCache.find(state)) {
216*c8dee2aaSAndroid Build Coastguard Worker return (*e)->fDescriptorSet;
217*c8dee2aaSAndroid Build Coastguard Worker }
218*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker
addDescriptorSetToCache(const GrVkDescriptorSet * descSet,GrSamplerState state)221*c8dee2aaSAndroid Build Coastguard Worker void GrVkTexture::addDescriptorSetToCache(const GrVkDescriptorSet* descSet, GrSamplerState state) {
222*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fDescSetCache.find(state));
223*c8dee2aaSAndroid Build Coastguard Worker descSet->ref();
224*c8dee2aaSAndroid Build Coastguard Worker fDescSetCache.insert(state, std::make_unique<DescriptorCacheEntry>(descSet, this->getVkGpu()));
225*c8dee2aaSAndroid Build Coastguard Worker }
226