blob: 1049e53e7b373fcc8489a1464cbcbf71b6015350 [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 Daniel164a9f02016-02-22 09:56:40 -050034 const GrVkImageView* view)
kkinnunen2e6055b2016-04-22 01:48:29 -070035 : GrSurface(gpu, desc)
Greg Daniel1591c382017-08-17 15:37:20 -040036 , GrVkImage(info, GrBackendObjectOwnership::kOwned)
Robert Phillips49081d12017-05-08 13:41:35 -040037 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Brian Osman48c99192017-06-02 08:45:06 -040038 info.fLevelCount > 1)
brianosmanf05ab1b2016-05-12 11:01:10 -070039 , fTextureView(view)
40 , fLinearTextureView(nullptr) {
kkinnunen2e6055b2016-04-22 01:48:29 -070041 this->registerWithCache(budgeted);
42}
43
44GrVkTexture::GrVkTexture(GrVkGpu* gpu,
45 Wrapped,
46 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070047 const GrVkImageInfo& info,
48 const GrVkImageView* view,
Greg Daniel1591c382017-08-17 15:37:20 -040049 GrBackendObjectOwnership ownership)
kkinnunen2e6055b2016-04-22 01:48:29 -070050 : GrSurface(gpu, desc)
Greg Daniel1591c382017-08-17 15:37:20 -040051 , GrVkImage(info, ownership)
Robert Phillips49081d12017-05-08 13:41:35 -040052 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Brian Osman48c99192017-06-02 08:45:06 -040053 info.fLevelCount > 1)
brianosmanf05ab1b2016-05-12 11:01:10 -070054 , fTextureView(view)
55 , fLinearTextureView(nullptr) {
kkinnunen2e6055b2016-04-22 01:48:29 -070056 this->registerWithCacheWrapped();
Greg Daniel164a9f02016-02-22 09:56:40 -050057}
58
59// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
60GrVkTexture::GrVkTexture(GrVkGpu* gpu,
61 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070062 const GrVkImageInfo& info,
63 const GrVkImageView* view,
Greg Daniel1591c382017-08-17 15:37:20 -040064 GrBackendObjectOwnership ownership)
kkinnunen2e6055b2016-04-22 01:48:29 -070065 : GrSurface(gpu, desc)
Greg Daniel1591c382017-08-17 15:37:20 -040066 , GrVkImage(info, ownership)
Robert Phillips49081d12017-05-08 13:41:35 -040067 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Brian Osman48c99192017-06-02 08:45:06 -040068 info.fLevelCount > 1)
brianosmanf05ab1b2016-05-12 11:01:10 -070069 , fTextureView(view)
egdanielb2df0c22016-05-13 11:30:37 -070070 , fLinearTextureView(nullptr) {
Greg Daniel164a9f02016-02-22 09:56:40 -050071}
72
Robert Phillips67d52cf2017-06-05 13:38:13 -040073sk_sp<GrVkTexture> GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
74 const GrSurfaceDesc& desc,
75 const GrVkImage::ImageDesc& imageDesc) {
Greg Daniel164a9f02016-02-22 09:56:40 -050076 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
77
egdanielb2df0c22016-05-13 11:30:37 -070078 GrVkImageInfo info;
79 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
Greg Daniel164a9f02016-02-22 09:56:40 -050080 return nullptr;
81 }
82
egdanielb2df0c22016-05-13 11:30:37 -070083 const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat,
84 GrVkImageView::kColor_Type,
85 info.fLevelCount);
86 if (!imageView) {
87 GrVkImage::DestroyImageInfo(gpu, &info);
88 return nullptr;
89 }
Greg Daniel164a9f02016-02-22 09:56:40 -050090
Robert Phillips67d52cf2017-06-05 13:38:13 -040091 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, desc, info, imageView));
Greg Daniel164a9f02016-02-22 09:56:40 -050092}
93
bungeman6bd52842016-10-27 09:30:08 -070094sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
95 const GrSurfaceDesc& desc,
Greg Daniel1591c382017-08-17 15:37:20 -040096 GrWrapOwnership wrapOwnership,
bungeman6bd52842016-10-27 09:30:08 -070097 const GrVkImageInfo* info) {
jvanverthfd359ca2016-03-18 11:57:24 -070098 SkASSERT(info);
99 // Wrapped textures require both image and allocation (because they can be mapped)
jvanverth1e305ba2016-06-01 09:39:15 -0700100 SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc.fMemory);
Greg Daniel164a9f02016-02-22 09:56:40 -0500101
egdanielb2df0c22016-05-13 11:30:37 -0700102 const GrVkImageView* imageView = GrVkImageView::Create(gpu, info->fImage, info->fFormat,
103 GrVkImageView::kColor_Type,
104 info->fLevelCount);
105 if (!imageView) {
jvanverthfd359ca2016-03-18 11:57:24 -0700106 return nullptr;
107 }
108
Greg Daniel1591c382017-08-17 15:37:20 -0400109 GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
110 ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
111 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, *info, imageView, ownership));
Greg Daniel164a9f02016-02-22 09:56:40 -0500112}
113
114GrVkTexture::~GrVkTexture() {
115 // either release or abandon should have been called by the owner of this object.
116 SkASSERT(!fTextureView);
brianosmanf05ab1b2016-05-12 11:01:10 -0700117 SkASSERT(!fLinearTextureView);
Greg Daniel164a9f02016-02-22 09:56:40 -0500118}
119
120void GrVkTexture::onRelease() {
121 // we create this and don't hand it off, so we should always destroy it
122 if (fTextureView) {
123 fTextureView->unref(this->getVkGpu());
124 fTextureView = nullptr;
125 }
126
brianosmanf05ab1b2016-05-12 11:01:10 -0700127 if (fLinearTextureView) {
128 fLinearTextureView->unref(this->getVkGpu());
129 fLinearTextureView = nullptr;
130 }
131
kkinnunen2e6055b2016-04-22 01:48:29 -0700132 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500133
134 INHERITED::onRelease();
135}
136
137void GrVkTexture::onAbandon() {
138 if (fTextureView) {
139 fTextureView->unrefAndAbandon();
140 fTextureView = nullptr;
141 }
142
brianosmanf05ab1b2016-05-12 11:01:10 -0700143 if (fLinearTextureView) {
144 fLinearTextureView->unrefAndAbandon();
145 fLinearTextureView = nullptr;
146 }
147
Greg Daniel164a9f02016-02-22 09:56:40 -0500148 this->abandonImage();
149 INHERITED::onAbandon();
150}
151
152GrBackendObject GrVkTexture::getTextureHandle() const {
egdanielb2df0c22016-05-13 11:30:37 -0700153 return (GrBackendObject)&fInfo;
Greg Daniel164a9f02016-02-22 09:56:40 -0500154}
155
156GrVkGpu* GrVkTexture::getVkGpu() const {
157 SkASSERT(!this->wasDestroyed());
158 return static_cast<GrVkGpu*>(this->getGpu());
159}
jvanverth62340062016-04-26 08:01:44 -0700160
brianosmanf05ab1b2016-05-12 11:01:10 -0700161const GrVkImageView* GrVkTexture::textureView(bool allowSRGB) {
162 VkFormat linearFormat;
egdanielb2df0c22016-05-13 11:30:37 -0700163 if (allowSRGB || !GrVkFormatIsSRGB(fInfo.fFormat, &linearFormat)) {
brianosmanf05ab1b2016-05-12 11:01:10 -0700164 return fTextureView;
165 }
166
167 if (!fLinearTextureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700168 fLinearTextureView = GrVkImageView::Create(this->getVkGpu(), fInfo.fImage,
brianosmanf05ab1b2016-05-12 11:01:10 -0700169 linearFormat, GrVkImageView::kColor_Type,
egdanielb2df0c22016-05-13 11:30:37 -0700170 fInfo.fLevelCount);
brianosmanf05ab1b2016-05-12 11:01:10 -0700171 SkASSERT(fLinearTextureView);
172 }
173
174 return fLinearTextureView;
175}
176
egdaniel50ead532016-07-13 14:23:26 -0700177bool GrVkTexture::reallocForMipmap(GrVkGpu* gpu, uint32_t mipLevels) {
jvanverth900bd4a2016-04-29 13:53:12 -0700178 if (mipLevels == 1) {
179 // don't need to do anything for a 1x1 texture
180 return false;
181 }
182
egdanielb2df0c22016-05-13 11:30:37 -0700183 const GrVkResource* oldResource = this->resource();
jvanverth62340062016-04-26 08:01:44 -0700184
jvanverth900bd4a2016-04-29 13:53:12 -0700185 // We shouldn't realloc something that doesn't belong to us
egdanielb2df0c22016-05-13 11:30:37 -0700186 if (fIsBorrowed) {
jvanverth900bd4a2016-04-29 13:53:12 -0700187 return false;
188 }
189
Brian Salomond34edf32017-05-19 15:45:48 -0400190 bool renderTarget = SkToBool(this->asRenderTarget());
jvanverth62340062016-04-26 08:01:44 -0700191
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
jvanverth62340062016-04-26 08:01:44 -0700198 GrVkImage::ImageDesc imageDesc;
199 imageDesc.fImageType = VK_IMAGE_TYPE_2D;
egdanielb2df0c22016-05-13 11:30:37 -0700200 imageDesc.fFormat = fInfo.fFormat;
Brian Salomond34edf32017-05-19 15:45:48 -0400201 imageDesc.fWidth = this->width();
202 imageDesc.fHeight = this->height();
jvanverth62340062016-04-26 08:01:44 -0700203 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
egdanielb2df0c22016-05-13 11:30:37 -0700209 GrVkImageInfo info;
210 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
bsalomonc9021642016-05-14 17:55:32 -0700211 return false;
jvanverth62340062016-04-26 08:01:44 -0700212 }
213
214 // have to create a new image view for new resource
215 const GrVkImageView* oldView = fTextureView;
egdanielb2df0c22016-05-13 11:30:37 -0700216 VkImage image = info.fImage;
217 const GrVkImageView* textureView = GrVkImageView::Create(gpu, image, info.fFormat,
jvanverth62340062016-04-26 08:01:44 -0700218 GrVkImageView::kColor_Type, mipLevels);
219 if (!textureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700220 GrVkImage::DestroyImageInfo(gpu, &info);
jvanverth62340062016-04-26 08:01:44 -0700221 return false;
222 }
223
egdaniel50ead532016-07-13 14:23:26 -0700224 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
jvanverth62340062016-04-26 08:01:44 -0700232 oldResource->unref(gpu);
233 oldView->unref(gpu);
brianosmanf05ab1b2016-05-12 11:01:10 -0700234 if (fLinearTextureView) {
235 fLinearTextureView->unref(gpu);
236 fLinearTextureView = nullptr;
237 }
egdanielb2df0c22016-05-13 11:30:37 -0700238
jvanverth6b6ffc42016-06-13 14:28:07 -0700239 this->setNewResource(info.fImage, info.fAlloc, info.fImageTiling);
jvanverth62340062016-04-26 08:01:44 -0700240 fTextureView = textureView;
egdanielb2df0c22016-05-13 11:30:37 -0700241 fInfo = info;
Greg Danielb280d4e2017-09-01 09:40:30 -0400242 // SetMaxMipMapLevel stores the max level not the number of levels
243 this->texturePriv().setMaxMipMapLevel(mipLevels-1);
jvanverth62340062016-04-26 08:01:44 -0700244
245 return true;
246}