blob: 7d8f017fec790dabe910c1de676b3501d57cbf26 [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) {
Robert Phillips49081d12017-05-08 13:41:35 -040022 if (GrPixelConfigIsSint(config)) {
23 // We only ever want to nearest-neighbor sample signed int textures.
Brian Salomon2bbdcc42017-09-07 12:36:34 -040024 return GrSamplerState::Filter::kNearest;
Robert Phillips49081d12017-05-08 13:41:35 -040025 }
Brian Salomon2bbdcc42017-09-07 12:36:34 -040026 return GrSamplerState::Filter::kMipMap;
Robert Phillips49081d12017-05-08 13:41:35 -040027}
28
Greg Daniel164a9f02016-02-22 09:56:40 -050029// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
30GrVkTexture::GrVkTexture(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -070031 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -050032 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070033 const GrVkImageInfo& info,
Greg Daniel834f1202017-10-09 15:06:20 -040034 const GrVkImageView* view,
35 bool wasFullMipMapDataProvided)
kkinnunen2e6055b2016-04-22 01:48:29 -070036 : GrSurface(gpu, desc)
Greg Daniel1591c382017-08-17 15:37:20 -040037 , GrVkImage(info, GrBackendObjectOwnership::kOwned)
Robert Phillips49081d12017-05-08 13:41:35 -040038 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Greg Daniel834f1202017-10-09 15:06:20 -040039 info.fLevelCount > 1, wasFullMipMapDataProvided)
brianosmanf05ab1b2016-05-12 11:01:10 -070040 , fTextureView(view)
41 , fLinearTextureView(nullptr) {
kkinnunen2e6055b2016-04-22 01:48:29 -070042 this->registerWithCache(budgeted);
43}
44
45GrVkTexture::GrVkTexture(GrVkGpu* gpu,
46 Wrapped,
47 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070048 const GrVkImageInfo& info,
49 const GrVkImageView* view,
Greg Daniel1591c382017-08-17 15:37:20 -040050 GrBackendObjectOwnership ownership)
kkinnunen2e6055b2016-04-22 01:48:29 -070051 : GrSurface(gpu, desc)
Greg Daniel1591c382017-08-17 15:37:20 -040052 , GrVkImage(info, ownership)
Robert Phillips49081d12017-05-08 13:41:35 -040053 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Greg Daniel834f1202017-10-09 15:06:20 -040054 info.fLevelCount > 1, false)
brianosmanf05ab1b2016-05-12 11:01:10 -070055 , fTextureView(view)
56 , fLinearTextureView(nullptr) {
kkinnunen2e6055b2016-04-22 01:48:29 -070057 this->registerWithCacheWrapped();
Greg Daniel164a9f02016-02-22 09:56:40 -050058}
59
60// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
61GrVkTexture::GrVkTexture(GrVkGpu* gpu,
62 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070063 const GrVkImageInfo& info,
64 const GrVkImageView* view,
Greg Daniel834f1202017-10-09 15:06:20 -040065 GrBackendObjectOwnership ownership,
66 bool wasFullMipMapDataProvided)
kkinnunen2e6055b2016-04-22 01:48:29 -070067 : GrSurface(gpu, desc)
Greg Daniel1591c382017-08-17 15:37:20 -040068 , GrVkImage(info, ownership)
Robert Phillips49081d12017-05-08 13:41:35 -040069 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Greg Daniel834f1202017-10-09 15:06:20 -040070 info.fLevelCount > 1, wasFullMipMapDataProvided)
brianosmanf05ab1b2016-05-12 11:01:10 -070071 , fTextureView(view)
egdanielb2df0c22016-05-13 11:30:37 -070072 , fLinearTextureView(nullptr) {
Greg Daniel164a9f02016-02-22 09:56:40 -050073}
74
Robert Phillips67d52cf2017-06-05 13:38:13 -040075sk_sp<GrVkTexture> GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
76 const GrSurfaceDesc& desc,
Greg Daniel834f1202017-10-09 15:06:20 -040077 const GrVkImage::ImageDesc& imageDesc,
78 bool fullMipMapDataProvided) {
Greg Daniel164a9f02016-02-22 09:56:40 -050079 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
80
egdanielb2df0c22016-05-13 11:30:37 -070081 GrVkImageInfo info;
82 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
Greg Daniel164a9f02016-02-22 09:56:40 -050083 return nullptr;
84 }
85
egdanielb2df0c22016-05-13 11:30:37 -070086 const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat,
87 GrVkImageView::kColor_Type,
88 info.fLevelCount);
89 if (!imageView) {
90 GrVkImage::DestroyImageInfo(gpu, &info);
91 return nullptr;
92 }
Greg Daniel164a9f02016-02-22 09:56:40 -050093
Greg Daniel834f1202017-10-09 15:06:20 -040094 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, desc, info, imageView,
95 fullMipMapDataProvided));
Greg Daniel164a9f02016-02-22 09:56:40 -050096}
97
bungeman6bd52842016-10-27 09:30:08 -070098sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
99 const GrSurfaceDesc& desc,
Greg Daniel1591c382017-08-17 15:37:20 -0400100 GrWrapOwnership wrapOwnership,
bungeman6bd52842016-10-27 09:30:08 -0700101 const GrVkImageInfo* info) {
jvanverthfd359ca2016-03-18 11:57:24 -0700102 SkASSERT(info);
103 // Wrapped textures require both image and allocation (because they can be mapped)
jvanverth1e305ba2016-06-01 09:39:15 -0700104 SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc.fMemory);
Greg Daniel164a9f02016-02-22 09:56:40 -0500105
egdanielb2df0c22016-05-13 11:30:37 -0700106 const GrVkImageView* imageView = GrVkImageView::Create(gpu, info->fImage, info->fFormat,
107 GrVkImageView::kColor_Type,
108 info->fLevelCount);
109 if (!imageView) {
jvanverthfd359ca2016-03-18 11:57:24 -0700110 return nullptr;
111 }
112
Greg Daniel1591c382017-08-17 15:37:20 -0400113 GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
114 ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
115 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, *info, imageView, ownership));
Greg Daniel164a9f02016-02-22 09:56:40 -0500116}
117
118GrVkTexture::~GrVkTexture() {
119 // either release or abandon should have been called by the owner of this object.
120 SkASSERT(!fTextureView);
brianosmanf05ab1b2016-05-12 11:01:10 -0700121 SkASSERT(!fLinearTextureView);
Greg Daniel164a9f02016-02-22 09:56:40 -0500122}
123
124void GrVkTexture::onRelease() {
125 // we create this and don't hand it off, so we should always destroy it
126 if (fTextureView) {
127 fTextureView->unref(this->getVkGpu());
128 fTextureView = nullptr;
129 }
130
brianosmanf05ab1b2016-05-12 11:01:10 -0700131 if (fLinearTextureView) {
132 fLinearTextureView->unref(this->getVkGpu());
133 fLinearTextureView = nullptr;
134 }
135
kkinnunen2e6055b2016-04-22 01:48:29 -0700136 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500137
138 INHERITED::onRelease();
139}
140
141void GrVkTexture::onAbandon() {
142 if (fTextureView) {
143 fTextureView->unrefAndAbandon();
144 fTextureView = nullptr;
145 }
146
brianosmanf05ab1b2016-05-12 11:01:10 -0700147 if (fLinearTextureView) {
148 fLinearTextureView->unrefAndAbandon();
149 fLinearTextureView = nullptr;
150 }
151
Greg Daniel164a9f02016-02-22 09:56:40 -0500152 this->abandonImage();
153 INHERITED::onAbandon();
154}
155
156GrBackendObject GrVkTexture::getTextureHandle() const {
egdanielb2df0c22016-05-13 11:30:37 -0700157 return (GrBackendObject)&fInfo;
Greg Daniel164a9f02016-02-22 09:56:40 -0500158}
159
160GrVkGpu* GrVkTexture::getVkGpu() const {
161 SkASSERT(!this->wasDestroyed());
162 return static_cast<GrVkGpu*>(this->getGpu());
163}
jvanverth62340062016-04-26 08:01:44 -0700164
brianosmanf05ab1b2016-05-12 11:01:10 -0700165const GrVkImageView* GrVkTexture::textureView(bool allowSRGB) {
166 VkFormat linearFormat;
egdanielb2df0c22016-05-13 11:30:37 -0700167 if (allowSRGB || !GrVkFormatIsSRGB(fInfo.fFormat, &linearFormat)) {
brianosmanf05ab1b2016-05-12 11:01:10 -0700168 return fTextureView;
169 }
170
171 if (!fLinearTextureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700172 fLinearTextureView = GrVkImageView::Create(this->getVkGpu(), fInfo.fImage,
brianosmanf05ab1b2016-05-12 11:01:10 -0700173 linearFormat, GrVkImageView::kColor_Type,
egdanielb2df0c22016-05-13 11:30:37 -0700174 fInfo.fLevelCount);
brianosmanf05ab1b2016-05-12 11:01:10 -0700175 SkASSERT(fLinearTextureView);
176 }
177
178 return fLinearTextureView;
179}
180
egdaniel50ead532016-07-13 14:23:26 -0700181bool GrVkTexture::reallocForMipmap(GrVkGpu* gpu, uint32_t mipLevels) {
jvanverth900bd4a2016-04-29 13:53:12 -0700182 if (mipLevels == 1) {
183 // don't need to do anything for a 1x1 texture
184 return false;
185 }
186
egdanielb2df0c22016-05-13 11:30:37 -0700187 const GrVkResource* oldResource = this->resource();
jvanverth62340062016-04-26 08:01:44 -0700188
jvanverth900bd4a2016-04-29 13:53:12 -0700189 // We shouldn't realloc something that doesn't belong to us
egdanielb2df0c22016-05-13 11:30:37 -0700190 if (fIsBorrowed) {
jvanverth900bd4a2016-04-29 13:53:12 -0700191 return false;
192 }
193
Brian Salomond34edf32017-05-19 15:45:48 -0400194 bool renderTarget = SkToBool(this->asRenderTarget());
jvanverth62340062016-04-26 08:01:44 -0700195
196 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
197 if (renderTarget) {
198 usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
199 }
200 usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
201
jvanverth62340062016-04-26 08:01:44 -0700202 GrVkImage::ImageDesc imageDesc;
203 imageDesc.fImageType = VK_IMAGE_TYPE_2D;
egdanielb2df0c22016-05-13 11:30:37 -0700204 imageDesc.fFormat = fInfo.fFormat;
Brian Salomond34edf32017-05-19 15:45:48 -0400205 imageDesc.fWidth = this->width();
206 imageDesc.fHeight = this->height();
jvanverth62340062016-04-26 08:01:44 -0700207 imageDesc.fLevels = mipLevels;
208 imageDesc.fSamples = 1;
209 imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
210 imageDesc.fUsageFlags = usageFlags;
211 imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
212
egdanielb2df0c22016-05-13 11:30:37 -0700213 GrVkImageInfo info;
214 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
bsalomonc9021642016-05-14 17:55:32 -0700215 return false;
jvanverth62340062016-04-26 08:01:44 -0700216 }
217
218 // have to create a new image view for new resource
219 const GrVkImageView* oldView = fTextureView;
egdanielb2df0c22016-05-13 11:30:37 -0700220 VkImage image = info.fImage;
221 const GrVkImageView* textureView = GrVkImageView::Create(gpu, image, info.fFormat,
jvanverth62340062016-04-26 08:01:44 -0700222 GrVkImageView::kColor_Type, mipLevels);
223 if (!textureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700224 GrVkImage::DestroyImageInfo(gpu, &info);
jvanverth62340062016-04-26 08:01:44 -0700225 return false;
226 }
227
egdaniel50ead532016-07-13 14:23:26 -0700228 if (renderTarget) {
229 GrVkTextureRenderTarget* texRT = static_cast<GrVkTextureRenderTarget*>(this);
230 if (!texRT->updateForMipmap(gpu, info)) {
231 GrVkImage::DestroyImageInfo(gpu, &info);
232 return false;
233 }
234 }
235
jvanverth62340062016-04-26 08:01:44 -0700236 oldResource->unref(gpu);
237 oldView->unref(gpu);
brianosmanf05ab1b2016-05-12 11:01:10 -0700238 if (fLinearTextureView) {
239 fLinearTextureView->unref(gpu);
240 fLinearTextureView = nullptr;
241 }
egdanielb2df0c22016-05-13 11:30:37 -0700242
jvanverth6b6ffc42016-06-13 14:28:07 -0700243 this->setNewResource(info.fImage, info.fAlloc, info.fImageTiling);
jvanverth62340062016-04-26 08:01:44 -0700244 fTextureView = textureView;
egdanielb2df0c22016-05-13 11:30:37 -0700245 fInfo = info;
Greg Danielb280d4e2017-09-01 09:40:30 -0400246 // SetMaxMipMapLevel stores the max level not the number of levels
247 this->texturePriv().setMaxMipMapLevel(mipLevels-1);
jvanverth62340062016-04-26 08:01:44 -0700248
249 return true;
250}