Home | History | Annotate | Download | only in vk
      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 "GrVkTexture.h"
      9 
     10 #include "GrTexturePriv.h"
     11 #include "GrVkGpu.h"
     12 #include "GrVkImageView.h"
     13 #include "GrVkTextureRenderTarget.h"
     14 #include "GrVkUtil.h"
     15 
     16 #include "vk/GrVkTypes.h"
     17 
     18 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
     19 
     20 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
     21 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
     22                          SkBudgeted budgeted,
     23                          const GrSurfaceDesc& desc,
     24                          const GrVkImageInfo& info,
     25                          sk_sp<GrVkImageLayout> layout,
     26                          const GrVkImageView* view,
     27                          GrMipMapsStatus mipMapsStatus)
     28         : GrSurface(gpu, desc)
     29         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kOwned)
     30         , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
     31         , fTextureView(view) {
     32     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
     33     this->registerWithCache(budgeted);
     34     if (GrPixelConfigIsCompressed(desc.fConfig)) {
     35         this->setReadOnly();
     36     }
     37 }
     38 
     39 GrVkTexture::GrVkTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkImageInfo& info,
     40                          sk_sp<GrVkImageLayout> layout, const GrVkImageView* view,
     41                          GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership,
     42                          GrWrapCacheable cacheable, GrIOType ioType)
     43         : GrSurface(gpu, desc)
     44         , GrVkImage(info, std::move(layout), ownership)
     45         , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
     46         , fTextureView(view) {
     47     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
     48     if (ioType == kRead_GrIOType) {
     49         this->setReadOnly();
     50     }
     51     this->registerWithCacheWrapped(cacheable);
     52 }
     53 
     54 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
     55 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
     56                          const GrSurfaceDesc& desc,
     57                          const GrVkImageInfo& info,
     58                          sk_sp<GrVkImageLayout> layout,
     59                          const GrVkImageView* view,
     60                          GrMipMapsStatus mipMapsStatus,
     61                          GrBackendObjectOwnership ownership)
     62         : GrSurface(gpu, desc)
     63         , GrVkImage(info, layout, ownership)
     64         , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
     65         , fTextureView(view) {
     66     SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
     67 }
     68 
     69 sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
     70                                                const GrSurfaceDesc& desc,
     71                                                const GrVkImage::ImageDesc& imageDesc,
     72                                                GrMipMapsStatus mipMapsStatus) {
     73     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
     74 
     75     GrVkImageInfo info;
     76     if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
     77         return nullptr;
     78     }
     79 
     80     const GrVkImageView* imageView = GrVkImageView::Create(
     81             gpu, info.fImage, info.fFormat, GrVkImageView::kColor_Type, info.fLevelCount,
     82             info.fYcbcrConversionInfo);
     83     if (!imageView) {
     84         GrVkImage::DestroyImageInfo(gpu, &info);
     85         return nullptr;
     86     }
     87     sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout));
     88 
     89     return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, desc, info, std::move(layout),
     90                                               imageView, mipMapsStatus));
     91 }
     92 
     93 sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
     94                                                    GrWrapOwnership wrapOwnership,
     95                                                    GrWrapCacheable cacheable, GrIOType ioType,
     96                                                    const GrVkImageInfo& info,
     97                                                    sk_sp<GrVkImageLayout> layout) {
     98     // Wrapped textures require both image and allocation (because they can be mapped)
     99     SkASSERT(VK_NULL_HANDLE != info.fImage && VK_NULL_HANDLE != info.fAlloc.fMemory);
    100 
    101     const GrVkImageView* imageView = GrVkImageView::Create(
    102             gpu, info.fImage, info.fFormat, GrVkImageView::kColor_Type, info.fLevelCount,
    103             info.fYcbcrConversionInfo);
    104     if (!imageView) {
    105         return nullptr;
    106     }
    107 
    108     GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kValid
    109                                                          : GrMipMapsStatus::kNotAllocated;
    110 
    111     GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
    112             ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
    113     return sk_sp<GrVkTexture>(new GrVkTexture(gpu, desc, info, std::move(layout), imageView,
    114                                               mipMapsStatus, ownership, cacheable, ioType));
    115 }
    116 
    117 GrVkTexture::~GrVkTexture() {
    118     // either release or abandon should have been called by the owner of this object.
    119     SkASSERT(!fTextureView);
    120 }
    121 
    122 void GrVkTexture::onRelease() {
    123     // We're about to be severed from our GrVkResource. If there is an idle proc we have to decide
    124     // who will handle it. If the resource is still tied to a command buffer we let it handle it.
    125     // Otherwise, we handle it.
    126     if (this->hasResource() && this->resource()->isOwnedByCommandBuffer()) {
    127         fIdleProc = nullptr;
    128         fIdleProcContext = nullptr;
    129     }
    130 
    131     // we create this and don't hand it off, so we should always destroy it
    132     if (fTextureView) {
    133         fTextureView->unref(this->getVkGpu());
    134         fTextureView = nullptr;
    135     }
    136 
    137     this->releaseImage(this->getVkGpu());
    138 
    139     INHERITED::onRelease();
    140 }
    141 
    142 void GrVkTexture::onAbandon() {
    143     // We're about to be severed from our GrVkResource. If there is an idle proc we have to decide
    144     // who will handle it. If the resource is still tied to a command buffer we let it handle it.
    145     // Otherwise, we handle it.
    146     if (this->hasResource() && this->resource()->isOwnedByCommandBuffer()) {
    147         fIdleProc = nullptr;
    148         fIdleProcContext = nullptr;
    149     }
    150 
    151     // we create this and don't hand it off, so we should always destroy it
    152     if (fTextureView) {
    153         fTextureView->unrefAndAbandon();
    154         fTextureView = nullptr;
    155     }
    156 
    157     this->abandonImage();
    158     INHERITED::onAbandon();
    159 }
    160 
    161 GrBackendTexture GrVkTexture::getBackendTexture() const {
    162     return GrBackendTexture(this->width(), this->height(), fInfo, this->grVkImageLayout());
    163 }
    164 
    165 GrVkGpu* GrVkTexture::getVkGpu() const {
    166     SkASSERT(!this->wasDestroyed());
    167     return static_cast<GrVkGpu*>(this->getGpu());
    168 }
    169 
    170 const GrVkImageView* GrVkTexture::textureView() {
    171     return fTextureView;
    172 }
    173 
    174 void GrVkTexture::setIdleProc(IdleProc proc, void* context) {
    175     fIdleProc = proc;
    176     fIdleProcContext = context;
    177     if (auto* resource = this->resource()) {
    178         resource->setIdleProc(proc ? this : nullptr, proc, context);
    179     }
    180 }
    181 
    182 void GrVkTexture::removedLastRefOrPendingIO() {
    183     if (!fIdleProc) {
    184         return;
    185     }
    186     // This is called when the GrTexture is purgeable. However, we need to check whether the
    187     // Resource is still owned by any command buffers. If it is then it will call the proc.
    188     auto* resource = this->hasResource() ? this->resource() : nullptr;
    189     if (resource && resource->isOwnedByCommandBuffer()) {
    190         return;
    191     }
    192     fIdleProc(fIdleProcContext);
    193     fIdleProc = nullptr;
    194     fIdleProcContext = nullptr;
    195     if (resource) {
    196         resource->setIdleProc(nullptr, nullptr, nullptr);
    197     }
    198 }
    199