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 #include "GrVkGpu.h"
     10 #include "GrVkImageView.h"
     11 #include "GrTexturePriv.h"
     12 #include "GrVkTextureRenderTarget.h"
     13 #include "GrVkUtil.h"
     14 
     15 #include "vk/GrVkTypes.h"
     16 
     17 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
     18 
     19 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
     20 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
     21                          SkBudgeted budgeted,
     22                          const GrSurfaceDesc& desc,
     23                          const GrVkImageInfo& info,
     24                          const GrVkImageView* view)
     25     : GrSurface(gpu, desc)
     26     , GrVkImage(info, GrVkImage::kNot_Wrapped)
     27     , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, GrSamplerParams::kMipMap_FilterMode,
     28                 desc.fIsMipMapped)
     29     , fTextureView(view)
     30     , fLinearTextureView(nullptr) {
     31     this->registerWithCache(budgeted);
     32 }
     33 
     34 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
     35                          Wrapped,
     36                          const GrSurfaceDesc& desc,
     37                          const GrVkImageInfo& info,
     38                          const GrVkImageView* view,
     39                          GrVkImage::Wrapped wrapped)
     40     : GrSurface(gpu, desc)
     41     , GrVkImage(info, wrapped)
     42     , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, GrSamplerParams::kMipMap_FilterMode,
     43                 desc.fIsMipMapped)
     44     , fTextureView(view)
     45     , fLinearTextureView(nullptr) {
     46     this->registerWithCacheWrapped();
     47 }
     48 
     49 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
     50 GrVkTexture::GrVkTexture(GrVkGpu* gpu,
     51                          const GrSurfaceDesc& desc,
     52                          const GrVkImageInfo& info,
     53                          const GrVkImageView* view,
     54                          GrVkImage::Wrapped wrapped)
     55     : GrSurface(gpu, desc)
     56     , GrVkImage(info, wrapped)
     57     , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, GrSamplerParams::kMipMap_FilterMode,
     58                 desc.fIsMipMapped)
     59     , fTextureView(view)
     60     , fLinearTextureView(nullptr) {
     61 }
     62 
     63 GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
     64                                            const GrSurfaceDesc& desc,
     65                                            const GrVkImage::ImageDesc& imageDesc) {
     66     SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
     67 
     68     GrVkImageInfo info;
     69     if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
     70         return nullptr;
     71     }
     72 
     73     const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat,
     74                                                            GrVkImageView::kColor_Type,
     75                                                            info.fLevelCount);
     76     if (!imageView) {
     77         GrVkImage::DestroyImageInfo(gpu, &info);
     78         return nullptr;
     79     }
     80 
     81     return new GrVkTexture(gpu, budgeted, desc, info, imageView);
     82 }
     83 
     84 sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
     85                                                    const GrSurfaceDesc& desc,
     86                                                    GrWrapOwnership ownership,
     87                                                    const GrVkImageInfo* info) {
     88     SkASSERT(info);
     89     // Wrapped textures require both image and allocation (because they can be mapped)
     90     SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc.fMemory);
     91 
     92     const GrVkImageView* imageView = GrVkImageView::Create(gpu, info->fImage, info->fFormat,
     93                                                            GrVkImageView::kColor_Type,
     94                                                            info->fLevelCount);
     95     if (!imageView) {
     96         return nullptr;
     97     }
     98 
     99     if (kAdoptAndCache_GrWrapOwnership == ownership) {
    100         return sk_sp<GrVkTexture>(new GrVkTexture(gpu, SkBudgeted::kYes, desc, *info, imageView));
    101     } else {
    102         GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership
    103                 ? GrVkImage::kBorrowed_Wrapped : GrVkImage::kAdopted_Wrapped;
    104         return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, *info, imageView, wrapped));
    105     }
    106 }
    107 
    108 GrVkTexture::~GrVkTexture() {
    109     // either release or abandon should have been called by the owner of this object.
    110     SkASSERT(!fTextureView);
    111     SkASSERT(!fLinearTextureView);
    112 }
    113 
    114 void GrVkTexture::onRelease() {
    115     // we create this and don't hand it off, so we should always destroy it
    116     if (fTextureView) {
    117         fTextureView->unref(this->getVkGpu());
    118         fTextureView = nullptr;
    119     }
    120 
    121     if (fLinearTextureView) {
    122         fLinearTextureView->unref(this->getVkGpu());
    123         fLinearTextureView = nullptr;
    124     }
    125 
    126     this->releaseImage(this->getVkGpu());
    127 
    128     INHERITED::onRelease();
    129 }
    130 
    131 void GrVkTexture::onAbandon() {
    132     if (fTextureView) {
    133         fTextureView->unrefAndAbandon();
    134         fTextureView = nullptr;
    135     }
    136 
    137     if (fLinearTextureView) {
    138         fLinearTextureView->unrefAndAbandon();
    139         fLinearTextureView = nullptr;
    140     }
    141 
    142     this->abandonImage();
    143     INHERITED::onAbandon();
    144 }
    145 
    146 GrBackendObject GrVkTexture::getTextureHandle() const {
    147     return (GrBackendObject)&fInfo;
    148 }
    149 
    150 std::unique_ptr<GrExternalTextureData> GrVkTexture::detachBackendTexture() {
    151     // Not supported on Vulkan yet
    152     // TODO: Add thread-safe memory pools, and implement this.
    153     return nullptr;
    154 }
    155 
    156 GrVkGpu* GrVkTexture::getVkGpu() const {
    157     SkASSERT(!this->wasDestroyed());
    158     return static_cast<GrVkGpu*>(this->getGpu());
    159 }
    160 
    161 const GrVkImageView* GrVkTexture::textureView(bool allowSRGB) {
    162     VkFormat linearFormat;
    163     if (allowSRGB || !GrVkFormatIsSRGB(fInfo.fFormat, &linearFormat)) {
    164         return fTextureView;
    165     }
    166 
    167     if (!fLinearTextureView) {
    168         fLinearTextureView = GrVkImageView::Create(this->getVkGpu(), fInfo.fImage,
    169                                                    linearFormat, GrVkImageView::kColor_Type,
    170                                                    fInfo.fLevelCount);
    171         SkASSERT(fLinearTextureView);
    172     }
    173 
    174     return fLinearTextureView;
    175 }
    176 
    177 bool GrVkTexture::reallocForMipmap(GrVkGpu* gpu, uint32_t mipLevels) {
    178     if (mipLevels == 1) {
    179         // don't need to do anything for a 1x1 texture
    180         return false;
    181     }
    182 
    183     const GrVkResource* oldResource = this->resource();
    184 
    185     // We shouldn't realloc something that doesn't belong to us
    186     if (fIsBorrowed) {
    187         return false;
    188     }
    189 
    190     bool renderTarget = SkToBool(fDesc.fFlags & kRenderTarget_GrSurfaceFlag);
    191 
    192     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
    193     if (renderTarget) {
    194         usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    195     }
    196     usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    197 
    198     GrVkImage::ImageDesc imageDesc;
    199     imageDesc.fImageType = VK_IMAGE_TYPE_2D;
    200     imageDesc.fFormat = fInfo.fFormat;
    201     imageDesc.fWidth = fDesc.fWidth;
    202     imageDesc.fHeight = fDesc.fHeight;
    203     imageDesc.fLevels = mipLevels;
    204     imageDesc.fSamples = 1;
    205     imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
    206     imageDesc.fUsageFlags = usageFlags;
    207     imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
    208 
    209     GrVkImageInfo info;
    210     if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
    211         return false;
    212     }
    213 
    214     // have to create a new image view for new resource
    215     const GrVkImageView* oldView = fTextureView;
    216     VkImage image = info.fImage;
    217     const GrVkImageView* textureView = GrVkImageView::Create(gpu, image, info.fFormat,
    218                                                              GrVkImageView::kColor_Type, mipLevels);
    219     if (!textureView) {
    220         GrVkImage::DestroyImageInfo(gpu, &info);
    221         return false;
    222     }
    223 
    224     if (renderTarget) {
    225         GrVkTextureRenderTarget* texRT = static_cast<GrVkTextureRenderTarget*>(this);
    226         if (!texRT->updateForMipmap(gpu, info)) {
    227             GrVkImage::DestroyImageInfo(gpu, &info);
    228             return false;
    229         }
    230     }
    231 
    232     oldResource->unref(gpu);
    233     oldView->unref(gpu);
    234     if (fLinearTextureView) {
    235         fLinearTextureView->unref(gpu);
    236         fLinearTextureView = nullptr;
    237     }
    238 
    239     this->setNewResource(info.fImage, info.fAlloc, info.fImageTiling);
    240     fTextureView = textureView;
    241     fInfo = info;
    242     this->texturePriv().setMaxMipMapLevel(mipLevels);
    243 
    244     return true;
    245 }
    246