blob: 6e8fe67fd1a3c7d42bef38de34380bc9627c2376 [file] [log] [blame]
Greg Daniel164a9f02016-02-22 09:56:40 -05001/*
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"
Robert Phillipsf95b1752017-08-31 08:56:07 -04009
10#include "GrTexturePriv.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050011#include "GrVkGpu.h"
12#include "GrVkImageView.h"
egdaniel50ead532016-07-13 14:23:26 -070013#include "GrVkTextureRenderTarget.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050014#include "GrVkUtil.h"
15
jvanverthfd359ca2016-03-18 11:57:24 -070016#include "vk/GrVkTypes.h"
17
Greg Daniel164a9f02016-02-22 09:56:40 -050018#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.
21GrVkTexture::GrVkTexture(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -070022 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -050023 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070024 const GrVkImageInfo& info,
Greg Daniel52e16d92018-04-10 09:34:07 -040025 sk_sp<GrVkImageLayout> layout,
Greg Daniel834f1202017-10-09 15:06:20 -040026 const GrVkImageView* view,
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040027 GrMipMapsStatus mipMapsStatus)
Brian Salomon60dd8c72018-07-30 10:24:13 -040028 : GrSurface(gpu, desc)
29 , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kOwned)
Brian Salomone632dfc2018-08-01 13:01:16 -040030 , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
Brian Salomon60dd8c72018-07-30 10:24:13 -040031 , fTextureView(view) {
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040032 SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
kkinnunen2e6055b2016-04-22 01:48:29 -070033 this->registerWithCache(budgeted);
Jim Van Verth1676cb92019-01-15 13:24:45 -050034 if (GrPixelConfigIsCompressed(desc.fConfig)) {
35 this->setReadOnly();
36 }
kkinnunen2e6055b2016-04-22 01:48:29 -070037}
38
Brian Salomonfa2ebea2019-01-24 15:58:58 -050039GrVkTexture::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)
Brian Salomon60dd8c72018-07-30 10:24:13 -040043 : GrSurface(gpu, desc)
44 , GrVkImage(info, std::move(layout), ownership)
Brian Salomone632dfc2018-08-01 13:01:16 -040045 , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
Brian Salomon60dd8c72018-07-30 10:24:13 -040046 , fTextureView(view) {
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040047 SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
Brian Salomonc67c31c2018-12-06 10:00:03 -050048 if (ioType == kRead_GrIOType) {
49 this->setReadOnly();
50 }
Brian Salomonfa2ebea2019-01-24 15:58:58 -050051 this->registerWithCacheWrapped(cacheable);
Greg Daniel164a9f02016-02-22 09:56:40 -050052}
53
54// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
55GrVkTexture::GrVkTexture(GrVkGpu* gpu,
56 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070057 const GrVkImageInfo& info,
Greg Daniel52e16d92018-04-10 09:34:07 -040058 sk_sp<GrVkImageLayout> layout,
egdanielb2df0c22016-05-13 11:30:37 -070059 const GrVkImageView* view,
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040060 GrMipMapsStatus mipMapsStatus,
61 GrBackendObjectOwnership ownership)
Brian Salomon60dd8c72018-07-30 10:24:13 -040062 : GrSurface(gpu, desc)
63 , GrVkImage(info, layout, ownership)
Brian Salomone632dfc2018-08-01 13:01:16 -040064 , INHERITED(gpu, desc, GrTextureType::k2D, mipMapsStatus)
Brian Salomon60dd8c72018-07-30 10:24:13 -040065 , fTextureView(view) {
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040066 SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
Greg Daniel164a9f02016-02-22 09:56:40 -050067}
68
Greg Daniel475eb702018-09-28 14:16:50 -040069sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
70 const GrSurfaceDesc& desc,
71 const GrVkImage::ImageDesc& imageDesc,
72 GrMipMapsStatus mipMapsStatus) {
Greg Daniel164a9f02016-02-22 09:56:40 -050073 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
74
egdanielb2df0c22016-05-13 11:30:37 -070075 GrVkImageInfo info;
76 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
Greg Daniel164a9f02016-02-22 09:56:40 -050077 return nullptr;
78 }
79
Greg Daniel7e000222018-12-03 10:08:21 -050080 const GrVkImageView* imageView = GrVkImageView::Create(
81 gpu, info.fImage, info.fFormat, GrVkImageView::kColor_Type, info.fLevelCount,
82 info.fYcbcrConversionInfo);
egdanielb2df0c22016-05-13 11:30:37 -070083 if (!imageView) {
84 GrVkImage::DestroyImageInfo(gpu, &info);
85 return nullptr;
86 }
Greg Daniel52e16d92018-04-10 09:34:07 -040087 sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout));
Greg Daniel164a9f02016-02-22 09:56:40 -050088
Greg Daniel52e16d92018-04-10 09:34:07 -040089 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, desc, info, std::move(layout),
90 imageView, mipMapsStatus));
Greg Daniel164a9f02016-02-22 09:56:40 -050091}
92
Brian Salomonfa2ebea2019-01-24 15:58:58 -050093sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
Greg Daniel1591c382017-08-17 15:37:20 -040094 GrWrapOwnership wrapOwnership,
Brian Salomonfa2ebea2019-01-24 15:58:58 -050095 GrWrapCacheable cacheable, GrIOType ioType,
Greg Daniel52e16d92018-04-10 09:34:07 -040096 const GrVkImageInfo& info,
97 sk_sp<GrVkImageLayout> layout) {
jvanverthfd359ca2016-03-18 11:57:24 -070098 // Wrapped textures require both image and allocation (because they can be mapped)
Greg Daniel52e16d92018-04-10 09:34:07 -040099 SkASSERT(VK_NULL_HANDLE != info.fImage && VK_NULL_HANDLE != info.fAlloc.fMemory);
Greg Daniel164a9f02016-02-22 09:56:40 -0500100
Greg Daniel7e000222018-12-03 10:08:21 -0500101 const GrVkImageView* imageView = GrVkImageView::Create(
102 gpu, info.fImage, info.fFormat, GrVkImageView::kColor_Type, info.fLevelCount,
103 info.fYcbcrConversionInfo);
egdanielb2df0c22016-05-13 11:30:37 -0700104 if (!imageView) {
jvanverthfd359ca2016-03-18 11:57:24 -0700105 return nullptr;
106 }
107
Greg Daniel52e16d92018-04-10 09:34:07 -0400108 GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kValid
109 : GrMipMapsStatus::kNotAllocated;
Greg Daniel0fc4d2d2017-10-12 11:23:36 -0400110
Greg Daniel1591c382017-08-17 15:37:20 -0400111 GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
112 ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500113 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, desc, info, std::move(layout), imageView,
114 mipMapsStatus, ownership, cacheable, ioType));
Greg Daniel164a9f02016-02-22 09:56:40 -0500115}
116
117GrVkTexture::~GrVkTexture() {
118 // either release or abandon should have been called by the owner of this object.
119 SkASSERT(!fTextureView);
120}
121
122void GrVkTexture::onRelease() {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500123 // 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 }
Brian Salomon614c1a82018-12-19 15:42:06 -0500130
Greg Daniel164a9f02016-02-22 09:56:40 -0500131 // 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
kkinnunen2e6055b2016-04-22 01:48:29 -0700137 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500138
139 INHERITED::onRelease();
140}
141
142void GrVkTexture::onAbandon() {
Brian Salomon9bc76d92019-01-24 12:18:33 -0500143 // 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
Brian Salomon614c1a82018-12-19 15:42:06 -0500151 // we create this and don't hand it off, so we should always destroy it
Greg Daniel164a9f02016-02-22 09:56:40 -0500152 if (fTextureView) {
153 fTextureView->unrefAndAbandon();
154 fTextureView = nullptr;
155 }
156
157 this->abandonImage();
158 INHERITED::onAbandon();
159}
160
Robert Phillipsb67821d2017-12-13 15:00:45 -0500161GrBackendTexture GrVkTexture::getBackendTexture() const {
Greg Daniel52e16d92018-04-10 09:34:07 -0400162 return GrBackendTexture(this->width(), this->height(), fInfo, this->grVkImageLayout());
Robert Phillipsb67821d2017-12-13 15:00:45 -0500163}
164
Greg Daniel164a9f02016-02-22 09:56:40 -0500165GrVkGpu* GrVkTexture::getVkGpu() const {
166 SkASSERT(!this->wasDestroyed());
167 return static_cast<GrVkGpu*>(this->getGpu());
168}
jvanverth62340062016-04-26 08:01:44 -0700169
Brian Osman2b23c4b2018-06-01 12:25:08 -0400170const GrVkImageView* GrVkTexture::textureView() {
171 return fTextureView;
brianosmanf05ab1b2016-05-12 11:01:10 -0700172}
173
Brian Salomon614c1a82018-12-19 15:42:06 -0500174void 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
Brian Salomon9bc76d92019-01-24 12:18:33 -0500182void GrVkTexture::removedLastRefOrPendingIO() {
Brian Salomon614c1a82018-12-19 15:42:06 -0500183 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.
Brian Salomon9bc76d92019-01-24 12:18:33 -0500188 auto* resource = this->hasResource() ? this->resource() : nullptr;
189 if (resource && resource->isOwnedByCommandBuffer()) {
Brian Salomon614c1a82018-12-19 15:42:06 -0500190 return;
191 }
192 fIdleProc(fIdleProcContext);
193 fIdleProc = nullptr;
194 fIdleProcContext = nullptr;
Brian Salomon9bc76d92019-01-24 12:18:33 -0500195 if (resource) {
196 resource->setIdleProc(nullptr, nullptr, nullptr);
197 }
Brian Salomon614c1a82018-12-19 15:42:06 -0500198}