blob: 0b9862443c5867b53820d75218048e36ed6fcb33 [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
Robert Phillips49081d12017-05-08 13:41:35 -040020// This method parallels GrTextureProxy::highestFilterMode
Brian Salomon2bbdcc42017-09-07 12:36:34 -040021static inline GrSamplerState::Filter highest_filter_mode(GrPixelConfig config) {
Brian Salomon2bbdcc42017-09-07 12:36:34 -040022 return GrSamplerState::Filter::kMipMap;
Robert Phillips49081d12017-05-08 13:41:35 -040023}
24
Greg Daniel164a9f02016-02-22 09:56:40 -050025// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
26GrVkTexture::GrVkTexture(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -070027 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -050028 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070029 const GrVkImageInfo& info,
Greg Daniel52e16d92018-04-10 09:34:07 -040030 sk_sp<GrVkImageLayout> layout,
Greg Daniel834f1202017-10-09 15:06:20 -040031 const GrVkImageView* view,
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040032 GrMipMapsStatus mipMapsStatus)
kkinnunen2e6055b2016-04-22 01:48:29 -070033 : GrSurface(gpu, desc)
Greg Daniel52e16d92018-04-10 09:34:07 -040034 , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kOwned)
Robert Phillips49081d12017-05-08 13:41:35 -040035 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040036 mipMapsStatus)
brianosmanf05ab1b2016-05-12 11:01:10 -070037 , fTextureView(view)
38 , fLinearTextureView(nullptr) {
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040039 SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
kkinnunen2e6055b2016-04-22 01:48:29 -070040 this->registerWithCache(budgeted);
41}
42
43GrVkTexture::GrVkTexture(GrVkGpu* gpu,
44 Wrapped,
45 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070046 const GrVkImageInfo& info,
Greg Daniel52e16d92018-04-10 09:34:07 -040047 sk_sp<GrVkImageLayout> layout,
egdanielb2df0c22016-05-13 11:30:37 -070048 const GrVkImageView* view,
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040049 GrMipMapsStatus mipMapsStatus,
Greg Daniel1591c382017-08-17 15:37:20 -040050 GrBackendObjectOwnership ownership)
kkinnunen2e6055b2016-04-22 01:48:29 -070051 : GrSurface(gpu, desc)
Greg Daniel52e16d92018-04-10 09:34:07 -040052 , GrVkImage(info, std::move(layout), ownership)
Robert Phillips49081d12017-05-08 13:41:35 -040053 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040054 mipMapsStatus)
brianosmanf05ab1b2016-05-12 11:01:10 -070055 , fTextureView(view)
56 , fLinearTextureView(nullptr) {
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040057 SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
kkinnunen2e6055b2016-04-22 01:48:29 -070058 this->registerWithCacheWrapped();
Greg Daniel164a9f02016-02-22 09:56:40 -050059}
60
61// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
62GrVkTexture::GrVkTexture(GrVkGpu* gpu,
63 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070064 const GrVkImageInfo& info,
Greg Daniel52e16d92018-04-10 09:34:07 -040065 sk_sp<GrVkImageLayout> layout,
egdanielb2df0c22016-05-13 11:30:37 -070066 const GrVkImageView* view,
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040067 GrMipMapsStatus mipMapsStatus,
68 GrBackendObjectOwnership ownership)
kkinnunen2e6055b2016-04-22 01:48:29 -070069 : GrSurface(gpu, desc)
Greg Daniel52e16d92018-04-10 09:34:07 -040070 , GrVkImage(info, layout, ownership)
Robert Phillips49081d12017-05-08 13:41:35 -040071 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040072 mipMapsStatus)
brianosmanf05ab1b2016-05-12 11:01:10 -070073 , fTextureView(view)
egdanielb2df0c22016-05-13 11:30:37 -070074 , fLinearTextureView(nullptr) {
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040075 SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
Greg Daniel164a9f02016-02-22 09:56:40 -050076}
77
Robert Phillips67d52cf2017-06-05 13:38:13 -040078sk_sp<GrVkTexture> GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
79 const GrSurfaceDesc& desc,
Greg Daniel834f1202017-10-09 15:06:20 -040080 const GrVkImage::ImageDesc& imageDesc,
Greg Daniel0fc4d2d2017-10-12 11:23:36 -040081 GrMipMapsStatus mipMapsStatus) {
Greg Daniel164a9f02016-02-22 09:56:40 -050082 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
83
egdanielb2df0c22016-05-13 11:30:37 -070084 GrVkImageInfo info;
85 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
Greg Daniel164a9f02016-02-22 09:56:40 -050086 return nullptr;
87 }
88
egdanielb2df0c22016-05-13 11:30:37 -070089 const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat,
90 GrVkImageView::kColor_Type,
91 info.fLevelCount);
92 if (!imageView) {
93 GrVkImage::DestroyImageInfo(gpu, &info);
94 return nullptr;
95 }
Greg Daniel52e16d92018-04-10 09:34:07 -040096 sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout));
Greg Daniel164a9f02016-02-22 09:56:40 -050097
Greg Daniel52e16d92018-04-10 09:34:07 -040098 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, desc, info, std::move(layout),
99 imageView, mipMapsStatus));
Greg Daniel164a9f02016-02-22 09:56:40 -0500100}
101
bungeman6bd52842016-10-27 09:30:08 -0700102sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
103 const GrSurfaceDesc& desc,
Greg Daniel1591c382017-08-17 15:37:20 -0400104 GrWrapOwnership wrapOwnership,
Greg Daniel52e16d92018-04-10 09:34:07 -0400105 const GrVkImageInfo& info,
106 sk_sp<GrVkImageLayout> layout) {
jvanverthfd359ca2016-03-18 11:57:24 -0700107 // Wrapped textures require both image and allocation (because they can be mapped)
Greg Daniel52e16d92018-04-10 09:34:07 -0400108 SkASSERT(VK_NULL_HANDLE != info.fImage && VK_NULL_HANDLE != info.fAlloc.fMemory);
Greg Daniel164a9f02016-02-22 09:56:40 -0500109
Greg Daniel52e16d92018-04-10 09:34:07 -0400110 const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat,
egdanielb2df0c22016-05-13 11:30:37 -0700111 GrVkImageView::kColor_Type,
Greg Daniel52e16d92018-04-10 09:34:07 -0400112 info.fLevelCount);
egdanielb2df0c22016-05-13 11:30:37 -0700113 if (!imageView) {
jvanverthfd359ca2016-03-18 11:57:24 -0700114 return nullptr;
115 }
116
Greg Daniel52e16d92018-04-10 09:34:07 -0400117 GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kValid
118 : GrMipMapsStatus::kNotAllocated;
Greg Daniel0fc4d2d2017-10-12 11:23:36 -0400119
Greg Daniel1591c382017-08-17 15:37:20 -0400120 GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
121 ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
Greg Daniel52e16d92018-04-10 09:34:07 -0400122 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, info, std::move(layout),
123 imageView, mipMapsStatus, ownership));
Greg Daniel164a9f02016-02-22 09:56:40 -0500124}
125
126GrVkTexture::~GrVkTexture() {
127 // either release or abandon should have been called by the owner of this object.
128 SkASSERT(!fTextureView);
brianosmanf05ab1b2016-05-12 11:01:10 -0700129 SkASSERT(!fLinearTextureView);
Greg Daniel164a9f02016-02-22 09:56:40 -0500130}
131
132void GrVkTexture::onRelease() {
133 // we create this and don't hand it off, so we should always destroy it
134 if (fTextureView) {
135 fTextureView->unref(this->getVkGpu());
136 fTextureView = nullptr;
137 }
138
brianosmanf05ab1b2016-05-12 11:01:10 -0700139 if (fLinearTextureView) {
140 fLinearTextureView->unref(this->getVkGpu());
141 fLinearTextureView = nullptr;
142 }
143
kkinnunen2e6055b2016-04-22 01:48:29 -0700144 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500145
146 INHERITED::onRelease();
147}
148
149void GrVkTexture::onAbandon() {
150 if (fTextureView) {
151 fTextureView->unrefAndAbandon();
152 fTextureView = nullptr;
153 }
154
brianosmanf05ab1b2016-05-12 11:01:10 -0700155 if (fLinearTextureView) {
156 fLinearTextureView->unrefAndAbandon();
157 fLinearTextureView = nullptr;
158 }
159
Greg Daniel164a9f02016-02-22 09:56:40 -0500160 this->abandonImage();
161 INHERITED::onAbandon();
162}
163
164GrBackendObject GrVkTexture::getTextureHandle() const {
egdanielb2df0c22016-05-13 11:30:37 -0700165 return (GrBackendObject)&fInfo;
Greg Daniel164a9f02016-02-22 09:56:40 -0500166}
167
Robert Phillipsb67821d2017-12-13 15:00:45 -0500168GrBackendTexture GrVkTexture::getBackendTexture() const {
Greg Daniel52e16d92018-04-10 09:34:07 -0400169 return GrBackendTexture(this->width(), this->height(), fInfo, this->grVkImageLayout());
Robert Phillipsb67821d2017-12-13 15:00:45 -0500170}
171
Greg Daniel164a9f02016-02-22 09:56:40 -0500172GrVkGpu* GrVkTexture::getVkGpu() const {
173 SkASSERT(!this->wasDestroyed());
174 return static_cast<GrVkGpu*>(this->getGpu());
175}
jvanverth62340062016-04-26 08:01:44 -0700176
brianosmanf05ab1b2016-05-12 11:01:10 -0700177const GrVkImageView* GrVkTexture::textureView(bool allowSRGB) {
178 VkFormat linearFormat;
egdanielb2df0c22016-05-13 11:30:37 -0700179 if (allowSRGB || !GrVkFormatIsSRGB(fInfo.fFormat, &linearFormat)) {
brianosmanf05ab1b2016-05-12 11:01:10 -0700180 return fTextureView;
181 }
182
183 if (!fLinearTextureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700184 fLinearTextureView = GrVkImageView::Create(this->getVkGpu(), fInfo.fImage,
brianosmanf05ab1b2016-05-12 11:01:10 -0700185 linearFormat, GrVkImageView::kColor_Type,
egdanielb2df0c22016-05-13 11:30:37 -0700186 fInfo.fLevelCount);
brianosmanf05ab1b2016-05-12 11:01:10 -0700187 SkASSERT(fLinearTextureView);
188 }
189
190 return fLinearTextureView;
191}
192
egdaniel50ead532016-07-13 14:23:26 -0700193bool GrVkTexture::reallocForMipmap(GrVkGpu* gpu, uint32_t mipLevels) {
jvanverth900bd4a2016-04-29 13:53:12 -0700194 if (mipLevels == 1) {
195 // don't need to do anything for a 1x1 texture
196 return false;
197 }
198
egdanielb2df0c22016-05-13 11:30:37 -0700199 const GrVkResource* oldResource = this->resource();
jvanverth62340062016-04-26 08:01:44 -0700200
jvanverth900bd4a2016-04-29 13:53:12 -0700201 // We shouldn't realloc something that doesn't belong to us
egdanielb2df0c22016-05-13 11:30:37 -0700202 if (fIsBorrowed) {
jvanverth900bd4a2016-04-29 13:53:12 -0700203 return false;
204 }
205
Brian Salomond34edf32017-05-19 15:45:48 -0400206 bool renderTarget = SkToBool(this->asRenderTarget());
jvanverth62340062016-04-26 08:01:44 -0700207
208 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
209 if (renderTarget) {
210 usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
211 }
212 usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
213
jvanverth62340062016-04-26 08:01:44 -0700214 GrVkImage::ImageDesc imageDesc;
215 imageDesc.fImageType = VK_IMAGE_TYPE_2D;
egdanielb2df0c22016-05-13 11:30:37 -0700216 imageDesc.fFormat = fInfo.fFormat;
Brian Salomond34edf32017-05-19 15:45:48 -0400217 imageDesc.fWidth = this->width();
218 imageDesc.fHeight = this->height();
jvanverth62340062016-04-26 08:01:44 -0700219 imageDesc.fLevels = mipLevels;
220 imageDesc.fSamples = 1;
221 imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
222 imageDesc.fUsageFlags = usageFlags;
223 imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
224
egdanielb2df0c22016-05-13 11:30:37 -0700225 GrVkImageInfo info;
226 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
bsalomonc9021642016-05-14 17:55:32 -0700227 return false;
jvanverth62340062016-04-26 08:01:44 -0700228 }
229
230 // have to create a new image view for new resource
231 const GrVkImageView* oldView = fTextureView;
egdanielb2df0c22016-05-13 11:30:37 -0700232 VkImage image = info.fImage;
233 const GrVkImageView* textureView = GrVkImageView::Create(gpu, image, info.fFormat,
jvanverth62340062016-04-26 08:01:44 -0700234 GrVkImageView::kColor_Type, mipLevels);
235 if (!textureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700236 GrVkImage::DestroyImageInfo(gpu, &info);
jvanverth62340062016-04-26 08:01:44 -0700237 return false;
238 }
239
egdaniel50ead532016-07-13 14:23:26 -0700240 if (renderTarget) {
241 GrVkTextureRenderTarget* texRT = static_cast<GrVkTextureRenderTarget*>(this);
242 if (!texRT->updateForMipmap(gpu, info)) {
243 GrVkImage::DestroyImageInfo(gpu, &info);
244 return false;
245 }
246 }
247
jvanverth62340062016-04-26 08:01:44 -0700248 oldResource->unref(gpu);
249 oldView->unref(gpu);
brianosmanf05ab1b2016-05-12 11:01:10 -0700250 if (fLinearTextureView) {
251 fLinearTextureView->unref(gpu);
252 fLinearTextureView = nullptr;
253 }
egdanielb2df0c22016-05-13 11:30:37 -0700254
jvanverth6b6ffc42016-06-13 14:28:07 -0700255 this->setNewResource(info.fImage, info.fAlloc, info.fImageTiling);
jvanverth62340062016-04-26 08:01:44 -0700256 fTextureView = textureView;
egdanielb2df0c22016-05-13 11:30:37 -0700257 fInfo = info;
Greg Daniel52e16d92018-04-10 09:34:07 -0400258 this->updateImageLayout(info.fImageLayout);
Greg Danielb280d4e2017-09-01 09:40:30 -0400259 // SetMaxMipMapLevel stores the max level not the number of levels
260 this->texturePriv().setMaxMipMapLevel(mipLevels-1);
jvanverth62340062016-04-26 08:01:44 -0700261
262 return true;
263}