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