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 fIdleCallback.reset(); 128 } 129 130 // we create this and don't hand it off, so we should always destroy it 131 if (fTextureView) { 132 fTextureView->unref(this->getVkGpu()); 133 fTextureView = nullptr; 134 } 135 136 this->releaseImage(this->getVkGpu()); 137 138 INHERITED::onRelease(); 139 } 140 141 void GrVkTexture::onAbandon() { 142 // We're about to be severed from our GrVkResource. If there is an idle proc we have to decide 143 // who will handle it. If the resource is still tied to a command buffer we let it handle it. 144 // Otherwise, we handle it. 145 if (this->hasResource() && this->resource()->isOwnedByCommandBuffer()) { 146 fIdleCallback.reset(); 147 } 148 149 // we create this and don't hand it off, so we should always destroy it 150 if (fTextureView) { 151 fTextureView->unrefAndAbandon(); 152 fTextureView = nullptr; 153 } 154 155 this->abandonImage(); 156 INHERITED::onAbandon(); 157 } 158 159 GrBackendTexture GrVkTexture::getBackendTexture() const { 160 return GrBackendTexture(this->width(), this->height(), fInfo, this->grVkImageLayout()); 161 } 162 163 GrVkGpu* GrVkTexture::getVkGpu() const { 164 SkASSERT(!this->wasDestroyed()); 165 return static_cast<GrVkGpu*>(this->getGpu()); 166 } 167 168 const GrVkImageView* GrVkTexture::textureView() { 169 return fTextureView; 170 } 171 172 void GrVkTexture::addIdleProc(sk_sp<GrRefCntedCallback> callback) { 173 INHERITED::addIdleProc(callback); 174 if (auto* resource = this->resource()) { 175 resource->replaceIdleProc(this, fIdleCallback); 176 } 177 } 178 179 void GrVkTexture::willRemoveLastRefOrPendingIO() { 180 if (!fIdleCallback) { 181 return; 182 } 183 // This is called when the GrTexture is purgeable. However, we need to check whether the 184 // Resource is still owned by any command buffers. If it is then it will call the proc. 185 auto* resource = this->hasResource() ? this->resource() : nullptr; 186 if (resource) { 187 if (resource->isOwnedByCommandBuffer()) { 188 return; 189 } 190 resource->replaceIdleProc(this, nullptr); 191 } 192 fIdleCallback.reset(); 193 } 194