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