blob: 2b1655f23d6b506ab5bc1602ad5bf84ca20521fa [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"
9#include "GrVkGpu.h"
10#include "GrVkImageView.h"
jvanverth62340062016-04-26 08:01:44 -070011#include "GrTexturePriv.h"
egdaniel50ead532016-07-13 14:23:26 -070012#include "GrVkTextureRenderTarget.h"
Greg Daniel164a9f02016-02-22 09:56:40 -050013#include "GrVkUtil.h"
14
jvanverthfd359ca2016-03-18 11:57:24 -070015#include "vk/GrVkTypes.h"
16
Greg Daniel164a9f02016-02-22 09:56:40 -050017#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
18
Robert Phillips49081d12017-05-08 13:41:35 -040019// This method parallels GrTextureProxy::highestFilterMode
20static inline GrSamplerParams::FilterMode highest_filter_mode(GrPixelConfig config) {
21 if (GrPixelConfigIsSint(config)) {
22 // We only ever want to nearest-neighbor sample signed int textures.
23 return GrSamplerParams::kNone_FilterMode;
24 }
25 return GrSamplerParams::kMipMap_FilterMode;
26}
27
Greg Daniel164a9f02016-02-22 09:56:40 -050028// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
29GrVkTexture::GrVkTexture(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -070030 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -050031 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070032 const GrVkImageInfo& info,
Greg Daniel164a9f02016-02-22 09:56:40 -050033 const GrVkImageView* view)
kkinnunen2e6055b2016-04-22 01:48:29 -070034 : GrSurface(gpu, desc)
egdanielb2df0c22016-05-13 11:30:37 -070035 , GrVkImage(info, GrVkImage::kNot_Wrapped)
Robert Phillips49081d12017-05-08 13:41:35 -040036 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Brian Osman48c99192017-06-02 08:45:06 -040037 info.fLevelCount > 1)
brianosmanf05ab1b2016-05-12 11:01:10 -070038 , fTextureView(view)
39 , fLinearTextureView(nullptr) {
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,
47 const GrVkImageView* view,
48 GrVkImage::Wrapped wrapped)
kkinnunen2e6055b2016-04-22 01:48:29 -070049 : GrSurface(gpu, desc)
egdanielb2df0c22016-05-13 11:30:37 -070050 , GrVkImage(info, wrapped)
Robert Phillips49081d12017-05-08 13:41:35 -040051 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Brian Osman48c99192017-06-02 08:45:06 -040052 info.fLevelCount > 1)
brianosmanf05ab1b2016-05-12 11:01:10 -070053 , fTextureView(view)
54 , fLinearTextureView(nullptr) {
kkinnunen2e6055b2016-04-22 01:48:29 -070055 this->registerWithCacheWrapped();
Greg Daniel164a9f02016-02-22 09:56:40 -050056}
57
58// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
59GrVkTexture::GrVkTexture(GrVkGpu* gpu,
60 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070061 const GrVkImageInfo& info,
62 const GrVkImageView* view,
63 GrVkImage::Wrapped wrapped)
kkinnunen2e6055b2016-04-22 01:48:29 -070064 : GrSurface(gpu, desc)
egdanielb2df0c22016-05-13 11:30:37 -070065 , GrVkImage(info, wrapped)
Robert Phillips49081d12017-05-08 13:41:35 -040066 , INHERITED(gpu, desc, kTexture2DSampler_GrSLType, highest_filter_mode(desc.fConfig),
Brian Osman48c99192017-06-02 08:45:06 -040067 info.fLevelCount > 1)
brianosmanf05ab1b2016-05-12 11:01:10 -070068 , fTextureView(view)
egdanielb2df0c22016-05-13 11:30:37 -070069 , fLinearTextureView(nullptr) {
Greg Daniel164a9f02016-02-22 09:56:40 -050070}
71
Robert Phillips67d52cf2017-06-05 13:38:13 -040072sk_sp<GrVkTexture> GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
73 const GrSurfaceDesc& desc,
74 const GrVkImage::ImageDesc& imageDesc) {
Greg Daniel164a9f02016-02-22 09:56:40 -050075 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
76
egdanielb2df0c22016-05-13 11:30:37 -070077 GrVkImageInfo info;
78 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
Greg Daniel164a9f02016-02-22 09:56:40 -050079 return nullptr;
80 }
81
egdanielb2df0c22016-05-13 11:30:37 -070082 const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat,
83 GrVkImageView::kColor_Type,
84 info.fLevelCount);
85 if (!imageView) {
86 GrVkImage::DestroyImageInfo(gpu, &info);
87 return nullptr;
88 }
Greg Daniel164a9f02016-02-22 09:56:40 -050089
Robert Phillips67d52cf2017-06-05 13:38:13 -040090 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, budgeted, desc, info, imageView));
Greg Daniel164a9f02016-02-22 09:56:40 -050091}
92
bungeman6bd52842016-10-27 09:30:08 -070093sk_sp<GrVkTexture> GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu,
94 const GrSurfaceDesc& desc,
95 GrWrapOwnership ownership,
96 const GrVkImageInfo* info) {
jvanverthfd359ca2016-03-18 11:57:24 -070097 SkASSERT(info);
98 // Wrapped textures require both image and allocation (because they can be mapped)
jvanverth1e305ba2016-06-01 09:39:15 -070099 SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc.fMemory);
Greg Daniel164a9f02016-02-22 09:56:40 -0500100
egdanielb2df0c22016-05-13 11:30:37 -0700101 const GrVkImageView* imageView = GrVkImageView::Create(gpu, info->fImage, info->fFormat,
102 GrVkImageView::kColor_Type,
103 info->fLevelCount);
104 if (!imageView) {
jvanverthfd359ca2016-03-18 11:57:24 -0700105 return nullptr;
106 }
107
Brian Osman85d34b22017-05-10 12:06:26 -0400108 GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership
109 ? GrVkImage::kBorrowed_Wrapped : GrVkImage::kAdopted_Wrapped;
110 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, *info, imageView, wrapped));
Greg Daniel164a9f02016-02-22 09:56:40 -0500111}
112
113GrVkTexture::~GrVkTexture() {
114 // either release or abandon should have been called by the owner of this object.
115 SkASSERT(!fTextureView);
brianosmanf05ab1b2016-05-12 11:01:10 -0700116 SkASSERT(!fLinearTextureView);
Greg Daniel164a9f02016-02-22 09:56:40 -0500117}
118
119void GrVkTexture::onRelease() {
120 // we create this and don't hand it off, so we should always destroy it
121 if (fTextureView) {
122 fTextureView->unref(this->getVkGpu());
123 fTextureView = nullptr;
124 }
125
brianosmanf05ab1b2016-05-12 11:01:10 -0700126 if (fLinearTextureView) {
127 fLinearTextureView->unref(this->getVkGpu());
128 fLinearTextureView = nullptr;
129 }
130
kkinnunen2e6055b2016-04-22 01:48:29 -0700131 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500132
133 INHERITED::onRelease();
134}
135
136void GrVkTexture::onAbandon() {
137 if (fTextureView) {
138 fTextureView->unrefAndAbandon();
139 fTextureView = nullptr;
140 }
141
brianosmanf05ab1b2016-05-12 11:01:10 -0700142 if (fLinearTextureView) {
143 fLinearTextureView->unrefAndAbandon();
144 fLinearTextureView = nullptr;
145 }
146
Greg Daniel164a9f02016-02-22 09:56:40 -0500147 this->abandonImage();
148 INHERITED::onAbandon();
149}
150
151GrBackendObject GrVkTexture::getTextureHandle() const {
egdanielb2df0c22016-05-13 11:30:37 -0700152 return (GrBackendObject)&fInfo;
Greg Daniel164a9f02016-02-22 09:56:40 -0500153}
154
155GrVkGpu* GrVkTexture::getVkGpu() const {
156 SkASSERT(!this->wasDestroyed());
157 return static_cast<GrVkGpu*>(this->getGpu());
158}
jvanverth62340062016-04-26 08:01:44 -0700159
brianosmanf05ab1b2016-05-12 11:01:10 -0700160const GrVkImageView* GrVkTexture::textureView(bool allowSRGB) {
161 VkFormat linearFormat;
egdanielb2df0c22016-05-13 11:30:37 -0700162 if (allowSRGB || !GrVkFormatIsSRGB(fInfo.fFormat, &linearFormat)) {
brianosmanf05ab1b2016-05-12 11:01:10 -0700163 return fTextureView;
164 }
165
166 if (!fLinearTextureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700167 fLinearTextureView = GrVkImageView::Create(this->getVkGpu(), fInfo.fImage,
brianosmanf05ab1b2016-05-12 11:01:10 -0700168 linearFormat, GrVkImageView::kColor_Type,
egdanielb2df0c22016-05-13 11:30:37 -0700169 fInfo.fLevelCount);
brianosmanf05ab1b2016-05-12 11:01:10 -0700170 SkASSERT(fLinearTextureView);
171 }
172
173 return fLinearTextureView;
174}
175
egdaniel50ead532016-07-13 14:23:26 -0700176bool GrVkTexture::reallocForMipmap(GrVkGpu* gpu, uint32_t mipLevels) {
jvanverth900bd4a2016-04-29 13:53:12 -0700177 if (mipLevels == 1) {
178 // don't need to do anything for a 1x1 texture
179 return false;
180 }
181
egdanielb2df0c22016-05-13 11:30:37 -0700182 const GrVkResource* oldResource = this->resource();
jvanverth62340062016-04-26 08:01:44 -0700183
jvanverth900bd4a2016-04-29 13:53:12 -0700184 // We shouldn't realloc something that doesn't belong to us
egdanielb2df0c22016-05-13 11:30:37 -0700185 if (fIsBorrowed) {
jvanverth900bd4a2016-04-29 13:53:12 -0700186 return false;
187 }
188
Brian Salomond34edf32017-05-19 15:45:48 -0400189 bool renderTarget = SkToBool(this->asRenderTarget());
jvanverth62340062016-04-26 08:01:44 -0700190
191 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
192 if (renderTarget) {
193 usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
194 }
195 usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
196
jvanverth62340062016-04-26 08:01:44 -0700197 GrVkImage::ImageDesc imageDesc;
198 imageDesc.fImageType = VK_IMAGE_TYPE_2D;
egdanielb2df0c22016-05-13 11:30:37 -0700199 imageDesc.fFormat = fInfo.fFormat;
Brian Salomond34edf32017-05-19 15:45:48 -0400200 imageDesc.fWidth = this->width();
201 imageDesc.fHeight = this->height();
jvanverth62340062016-04-26 08:01:44 -0700202 imageDesc.fLevels = mipLevels;
203 imageDesc.fSamples = 1;
204 imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
205 imageDesc.fUsageFlags = usageFlags;
206 imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
207
egdanielb2df0c22016-05-13 11:30:37 -0700208 GrVkImageInfo info;
209 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
bsalomonc9021642016-05-14 17:55:32 -0700210 return false;
jvanverth62340062016-04-26 08:01:44 -0700211 }
212
213 // have to create a new image view for new resource
214 const GrVkImageView* oldView = fTextureView;
egdanielb2df0c22016-05-13 11:30:37 -0700215 VkImage image = info.fImage;
216 const GrVkImageView* textureView = GrVkImageView::Create(gpu, image, info.fFormat,
jvanverth62340062016-04-26 08:01:44 -0700217 GrVkImageView::kColor_Type, mipLevels);
218 if (!textureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700219 GrVkImage::DestroyImageInfo(gpu, &info);
jvanverth62340062016-04-26 08:01:44 -0700220 return false;
221 }
222
egdaniel50ead532016-07-13 14:23:26 -0700223 if (renderTarget) {
224 GrVkTextureRenderTarget* texRT = static_cast<GrVkTextureRenderTarget*>(this);
225 if (!texRT->updateForMipmap(gpu, info)) {
226 GrVkImage::DestroyImageInfo(gpu, &info);
227 return false;
228 }
229 }
230
jvanverth62340062016-04-26 08:01:44 -0700231 oldResource->unref(gpu);
232 oldView->unref(gpu);
brianosmanf05ab1b2016-05-12 11:01:10 -0700233 if (fLinearTextureView) {
234 fLinearTextureView->unref(gpu);
235 fLinearTextureView = nullptr;
236 }
egdanielb2df0c22016-05-13 11:30:37 -0700237
jvanverth6b6ffc42016-06-13 14:28:07 -0700238 this->setNewResource(info.fImage, info.fAlloc, info.fImageTiling);
jvanverth62340062016-04-26 08:01:44 -0700239 fTextureView = textureView;
egdanielb2df0c22016-05-13 11:30:37 -0700240 fInfo = info;
jvanverth62340062016-04-26 08:01:44 -0700241 this->texturePriv().setMaxMipMapLevel(mipLevels);
242
243 return true;
244}