blob: defbe139c56bdbc1cb014a0be05c70c0104a7fc6 [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 Salomon739c5bf2016-11-07 09:53:44 -050037 desc.fIsMipMapped)
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 Salomon739c5bf2016-11-07 09:53:44 -050052 desc.fIsMipMapped)
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 Salomon739c5bf2016-11-07 09:53:44 -050067 desc.fIsMipMapped)
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
kkinnunen2e6055b2016-04-22 01:48:29 -070072GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
73 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -050074 const GrVkImage::ImageDesc& imageDesc) {
75 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
egdanielb2df0c22016-05-13 11:30:37 -070090 return 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 Osman766fcbb2017-03-13 09:33:09 -0400108 if (kAdoptAndCache_GrWrapOwnership == ownership) {
109 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, SkBudgeted::kYes, desc, *info, imageView));
110 } else {
111 GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership
112 ? GrVkImage::kBorrowed_Wrapped : GrVkImage::kAdopted_Wrapped;
113 return sk_sp<GrVkTexture>(new GrVkTexture(gpu, kWrapped, desc, *info, imageView, wrapped));
114 }
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);
brianosmanf05ab1b2016-05-12 11:01:10 -0700120 SkASSERT(!fLinearTextureView);
Greg Daniel164a9f02016-02-22 09:56:40 -0500121}
122
123void GrVkTexture::onRelease() {
124 // we create this and don't hand it off, so we should always destroy it
125 if (fTextureView) {
126 fTextureView->unref(this->getVkGpu());
127 fTextureView = nullptr;
128 }
129
brianosmanf05ab1b2016-05-12 11:01:10 -0700130 if (fLinearTextureView) {
131 fLinearTextureView->unref(this->getVkGpu());
132 fLinearTextureView = nullptr;
133 }
134
kkinnunen2e6055b2016-04-22 01:48:29 -0700135 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500136
137 INHERITED::onRelease();
138}
139
140void GrVkTexture::onAbandon() {
141 if (fTextureView) {
142 fTextureView->unrefAndAbandon();
143 fTextureView = nullptr;
144 }
145
brianosmanf05ab1b2016-05-12 11:01:10 -0700146 if (fLinearTextureView) {
147 fLinearTextureView->unrefAndAbandon();
148 fLinearTextureView = nullptr;
149 }
150
Greg Daniel164a9f02016-02-22 09:56:40 -0500151 this->abandonImage();
152 INHERITED::onAbandon();
153}
154
155GrBackendObject GrVkTexture::getTextureHandle() const {
egdanielb2df0c22016-05-13 11:30:37 -0700156 return (GrBackendObject)&fInfo;
Greg Daniel164a9f02016-02-22 09:56:40 -0500157}
158
Brian Osman2c2bc112017-02-28 10:02:49 -0500159std::unique_ptr<GrExternalTextureData> GrVkTexture::detachBackendTexture() {
160 // Not supported on Vulkan yet
161 // TODO: Add thread-safe memory pools, and implement this.
162 return nullptr;
163}
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
brianosmanf05ab1b2016-05-12 11:01:10 -0700170const GrVkImageView* GrVkTexture::textureView(bool allowSRGB) {
171 VkFormat linearFormat;
egdanielb2df0c22016-05-13 11:30:37 -0700172 if (allowSRGB || !GrVkFormatIsSRGB(fInfo.fFormat, &linearFormat)) {
brianosmanf05ab1b2016-05-12 11:01:10 -0700173 return fTextureView;
174 }
175
176 if (!fLinearTextureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700177 fLinearTextureView = GrVkImageView::Create(this->getVkGpu(), fInfo.fImage,
brianosmanf05ab1b2016-05-12 11:01:10 -0700178 linearFormat, GrVkImageView::kColor_Type,
egdanielb2df0c22016-05-13 11:30:37 -0700179 fInfo.fLevelCount);
brianosmanf05ab1b2016-05-12 11:01:10 -0700180 SkASSERT(fLinearTextureView);
181 }
182
183 return fLinearTextureView;
184}
185
egdaniel50ead532016-07-13 14:23:26 -0700186bool GrVkTexture::reallocForMipmap(GrVkGpu* gpu, uint32_t mipLevels) {
jvanverth900bd4a2016-04-29 13:53:12 -0700187 if (mipLevels == 1) {
188 // don't need to do anything for a 1x1 texture
189 return false;
190 }
191
egdanielb2df0c22016-05-13 11:30:37 -0700192 const GrVkResource* oldResource = this->resource();
jvanverth62340062016-04-26 08:01:44 -0700193
jvanverth900bd4a2016-04-29 13:53:12 -0700194 // We shouldn't realloc something that doesn't belong to us
egdanielb2df0c22016-05-13 11:30:37 -0700195 if (fIsBorrowed) {
jvanverth900bd4a2016-04-29 13:53:12 -0700196 return false;
197 }
198
jvanverth62340062016-04-26 08:01:44 -0700199 bool renderTarget = SkToBool(fDesc.fFlags & kRenderTarget_GrSurfaceFlag);
200
201 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
202 if (renderTarget) {
203 usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
204 }
205 usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
206
jvanverth62340062016-04-26 08:01:44 -0700207 GrVkImage::ImageDesc imageDesc;
208 imageDesc.fImageType = VK_IMAGE_TYPE_2D;
egdanielb2df0c22016-05-13 11:30:37 -0700209 imageDesc.fFormat = fInfo.fFormat;
jvanverth62340062016-04-26 08:01:44 -0700210 imageDesc.fWidth = fDesc.fWidth;
211 imageDesc.fHeight = fDesc.fHeight;
212 imageDesc.fLevels = mipLevels;
213 imageDesc.fSamples = 1;
214 imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
215 imageDesc.fUsageFlags = usageFlags;
216 imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
217
egdanielb2df0c22016-05-13 11:30:37 -0700218 GrVkImageInfo info;
219 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
bsalomonc9021642016-05-14 17:55:32 -0700220 return false;
jvanverth62340062016-04-26 08:01:44 -0700221 }
222
223 // have to create a new image view for new resource
224 const GrVkImageView* oldView = fTextureView;
egdanielb2df0c22016-05-13 11:30:37 -0700225 VkImage image = info.fImage;
226 const GrVkImageView* textureView = GrVkImageView::Create(gpu, image, info.fFormat,
jvanverth62340062016-04-26 08:01:44 -0700227 GrVkImageView::kColor_Type, mipLevels);
228 if (!textureView) {
egdanielb2df0c22016-05-13 11:30:37 -0700229 GrVkImage::DestroyImageInfo(gpu, &info);
jvanverth62340062016-04-26 08:01:44 -0700230 return false;
231 }
232
egdaniel50ead532016-07-13 14:23:26 -0700233 if (renderTarget) {
234 GrVkTextureRenderTarget* texRT = static_cast<GrVkTextureRenderTarget*>(this);
235 if (!texRT->updateForMipmap(gpu, info)) {
236 GrVkImage::DestroyImageInfo(gpu, &info);
237 return false;
238 }
239 }
240
jvanverth62340062016-04-26 08:01:44 -0700241 oldResource->unref(gpu);
242 oldView->unref(gpu);
brianosmanf05ab1b2016-05-12 11:01:10 -0700243 if (fLinearTextureView) {
244 fLinearTextureView->unref(gpu);
245 fLinearTextureView = nullptr;
246 }
egdanielb2df0c22016-05-13 11:30:37 -0700247
jvanverth6b6ffc42016-06-13 14:28:07 -0700248 this->setNewResource(info.fImage, info.fAlloc, info.fImageTiling);
jvanverth62340062016-04-26 08:01:44 -0700249 fTextureView = textureView;
egdanielb2df0c22016-05-13 11:30:37 -0700250 fInfo = info;
jvanverth62340062016-04-26 08:01:44 -0700251 this->texturePriv().setMaxMipMapLevel(mipLevels);
252
253 return true;
254}