blob: c2a30a27f4184bb00317c963bcb776a51a85bd7c [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"
Greg Daniel164a9f02016-02-22 09:56:40 -050012#include "GrVkUtil.h"
13
jvanverthfd359ca2016-03-18 11:57:24 -070014#include "vk/GrVkTypes.h"
15
Greg Daniel164a9f02016-02-22 09:56:40 -050016#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
17
18// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
19GrVkTexture::GrVkTexture(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -070020 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -050021 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -050022 const GrVkImage::Resource* imageResource,
23 const GrVkImageView* view)
kkinnunen2e6055b2016-04-22 01:48:29 -070024 : GrSurface(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -050025 , GrVkImage(imageResource)
jvanverth900bd4a2016-04-29 13:53:12 -070026 , INHERITED(gpu, desc, kSampler2D_GrSLType, desc.fIsMipMapped)
brianosmanf05ab1b2016-05-12 11:01:10 -070027 , fTextureView(view)
28 , fLinearTextureView(nullptr) {
kkinnunen2e6055b2016-04-22 01:48:29 -070029 this->registerWithCache(budgeted);
30}
31
32GrVkTexture::GrVkTexture(GrVkGpu* gpu,
33 Wrapped,
34 const GrSurfaceDesc& desc,
35 const GrVkImage::Resource* imageResource,
36 const GrVkImageView* view)
37 : GrSurface(gpu, desc)
38 , GrVkImage(imageResource)
jvanverth900bd4a2016-04-29 13:53:12 -070039 , INHERITED(gpu, desc, kSampler2D_GrSLType, desc.fIsMipMapped)
brianosmanf05ab1b2016-05-12 11:01:10 -070040 , fTextureView(view)
41 , fLinearTextureView(nullptr) {
kkinnunen2e6055b2016-04-22 01:48:29 -070042 this->registerWithCacheWrapped();
Greg Daniel164a9f02016-02-22 09:56:40 -050043}
44
45// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
46GrVkTexture::GrVkTexture(GrVkGpu* gpu,
47 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -050048 const GrVkImage::Resource* imageResource,
kkinnunen2e6055b2016-04-22 01:48:29 -070049 const GrVkImageView* view)
50 : GrSurface(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -050051 , GrVkImage(imageResource)
jvanverth900bd4a2016-04-29 13:53:12 -070052 , INHERITED(gpu, desc, kSampler2D_GrSLType, desc.fIsMipMapped)
brianosmanf05ab1b2016-05-12 11:01:10 -070053 , fTextureView(view)
54 , fLinearTextureView(nullptr) {}
Greg Daniel164a9f02016-02-22 09:56:40 -050055
56
kkinnunen2e6055b2016-04-22 01:48:29 -070057template<typename ResourceType>
Greg Daniel164a9f02016-02-22 09:56:40 -050058GrVkTexture* GrVkTexture::Create(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -070059 ResourceType type,
Greg Daniel164a9f02016-02-22 09:56:40 -050060 const GrSurfaceDesc& desc,
jvanverth2af0f1b2016-05-03 10:36:49 -070061 VkFormat format,
Greg Daniel164a9f02016-02-22 09:56:40 -050062 const GrVkImage::Resource* imageResource) {
63 VkImage image = imageResource->fImage;
jvanverth62340062016-04-26 08:01:44 -070064
Greg Daniel164a9f02016-02-22 09:56:40 -050065 const GrVkImageView* imageView = GrVkImageView::Create(gpu, image, format,
jvanverth900bd4a2016-04-29 13:53:12 -070066 GrVkImageView::kColor_Type,
jvanverth2af0f1b2016-05-03 10:36:49 -070067 imageResource->fLevelCount);
Greg Daniel164a9f02016-02-22 09:56:40 -050068 if (!imageView) {
69 return nullptr;
70 }
71
kkinnunen2e6055b2016-04-22 01:48:29 -070072 return new GrVkTexture(gpu, type, desc, imageResource, imageView);
Greg Daniel164a9f02016-02-22 09:56:40 -050073}
74
kkinnunen2e6055b2016-04-22 01:48:29 -070075GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
76 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -050077 const GrVkImage::ImageDesc& imageDesc) {
78 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
79
80 const GrVkImage::Resource* imageResource = GrVkImage::CreateResource(gpu, imageDesc);
81 if (!imageResource) {
82 return nullptr;
83 }
84
jvanverth2af0f1b2016-05-03 10:36:49 -070085 GrVkTexture* texture = Create(gpu, budgeted, desc, imageDesc.fFormat, imageResource);
Greg Daniel164a9f02016-02-22 09:56:40 -050086 // Create() will increment the refCount of the image resource if it succeeds
87 imageResource->unref(gpu);
88
89 return texture;
90}
91
kkinnunen2e6055b2016-04-22 01:48:29 -070092GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu,
93 const GrSurfaceDesc& desc,
94 GrWrapOwnership ownership,
halcanary9d524f22016-03-29 09:03:52 -070095 VkFormat format,
jvanverthfd359ca2016-03-18 11:57:24 -070096 const GrVkTextureInfo* info) {
97 SkASSERT(info);
98 // Wrapped textures require both image and allocation (because they can be mapped)
99 SkASSERT(VK_NULL_HANDLE != info->fImage && VK_NULL_HANDLE != info->fAlloc);
Greg Daniel164a9f02016-02-22 09:56:40 -0500100
jvanverthfd359ca2016-03-18 11:57:24 -0700101 GrVkImage::Resource::Flags flags = (VK_IMAGE_TILING_LINEAR == info->fImageTiling)
102 ? Resource::kLinearTiling_Flag : Resource::kNo_Flags;
103
jvanverthfe170d22016-03-22 13:15:44 -0700104 const GrVkImage::Resource* imageResource;
kkinnunen2e6055b2016-04-22 01:48:29 -0700105 if (kBorrow_GrWrapOwnership == ownership) {
egdaniel58a8d922016-04-21 08:03:10 -0700106 imageResource = new GrVkImage::BorrowedResource(info->fImage,
107 info->fAlloc,
jvanverth2af0f1b2016-05-03 10:36:49 -0700108 info->fFormat,
109 info->fLevelCount,
110 flags);
jvanverthfe170d22016-03-22 13:15:44 -0700111 } else {
jvanverth2af0f1b2016-05-03 10:36:49 -0700112 imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, info->fFormat,
113 info->fLevelCount, flags);
jvanverthfe170d22016-03-22 13:15:44 -0700114 }
jvanverthfd359ca2016-03-18 11:57:24 -0700115 if (!imageResource) {
116 return nullptr;
117 }
118
jvanverth2af0f1b2016-05-03 10:36:49 -0700119 GrVkTexture* texture = Create(gpu, kWrapped, desc, format, imageResource);
jvanverthfd359ca2016-03-18 11:57:24 -0700120 if (texture) {
121 texture->fCurrentLayout = info->fImageLayout;
122 }
123 // Create() will increment the refCount of the image resource if it succeeds
124 imageResource->unref(gpu);
125
126 return texture;
Greg Daniel164a9f02016-02-22 09:56:40 -0500127}
128
129GrVkTexture::~GrVkTexture() {
130 // either release or abandon should have been called by the owner of this object.
131 SkASSERT(!fTextureView);
brianosmanf05ab1b2016-05-12 11:01:10 -0700132 SkASSERT(!fLinearTextureView);
Greg Daniel164a9f02016-02-22 09:56:40 -0500133}
134
135void GrVkTexture::onRelease() {
136 // we create this and don't hand it off, so we should always destroy it
137 if (fTextureView) {
138 fTextureView->unref(this->getVkGpu());
139 fTextureView = nullptr;
140 }
141
brianosmanf05ab1b2016-05-12 11:01:10 -0700142 if (fLinearTextureView) {
143 fLinearTextureView->unref(this->getVkGpu());
144 fLinearTextureView = nullptr;
145 }
146
kkinnunen2e6055b2016-04-22 01:48:29 -0700147 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500148
149 INHERITED::onRelease();
150}
151
152void GrVkTexture::onAbandon() {
153 if (fTextureView) {
154 fTextureView->unrefAndAbandon();
155 fTextureView = nullptr;
156 }
157
brianosmanf05ab1b2016-05-12 11:01:10 -0700158 if (fLinearTextureView) {
159 fLinearTextureView->unrefAndAbandon();
160 fLinearTextureView = nullptr;
161 }
162
Greg Daniel164a9f02016-02-22 09:56:40 -0500163 this->abandonImage();
164 INHERITED::onAbandon();
165}
166
167GrBackendObject GrVkTexture::getTextureHandle() const {
168 // Currently just passing back the pointer to the Resource as the handle
169 return (GrBackendObject)&fResource;
170}
171
172GrVkGpu* 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;
179 if (allowSRGB || !GrVkFormatIsSRGB(fResource->fFormat, &linearFormat)) {
180 return fTextureView;
181 }
182
183 if (!fLinearTextureView) {
184 fLinearTextureView = GrVkImageView::Create(this->getVkGpu(), fResource->fImage,
185 linearFormat, GrVkImageView::kColor_Type,
186 fResource->fLevelCount);
187 SkASSERT(fLinearTextureView);
188 }
189
190 return fLinearTextureView;
191}
192
jvanverth900bd4a2016-04-29 13:53:12 -0700193bool GrVkTexture::reallocForMipmap(const GrVkGpu* gpu, uint32_t mipLevels) {
194 if (mipLevels == 1) {
195 // don't need to do anything for a 1x1 texture
196 return false;
197 }
198
jvanverth62340062016-04-26 08:01:44 -0700199 const GrVkImage::Resource* oldResource = fResource;
200
jvanverth900bd4a2016-04-29 13:53:12 -0700201 // We shouldn't realloc something that doesn't belong to us
202 if (GrVkImage::Resource::kBorrowed_Flag & oldResource->fFlags) {
203 return false;
204 }
205
jvanverth62340062016-04-26 08:01:44 -0700206 // Does this even make sense for rendertargets?
207 bool renderTarget = SkToBool(fDesc.fFlags & kRenderTarget_GrSurfaceFlag);
208
209 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
210 if (renderTarget) {
211 usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
212 }
213 usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
214
jvanverth62340062016-04-26 08:01:44 -0700215 GrVkImage::ImageDesc imageDesc;
216 imageDesc.fImageType = VK_IMAGE_TYPE_2D;
217 imageDesc.fFormat = oldResource->fFormat;
218 imageDesc.fWidth = fDesc.fWidth;
219 imageDesc.fHeight = fDesc.fHeight;
220 imageDesc.fLevels = mipLevels;
221 imageDesc.fSamples = 1;
222 imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
223 imageDesc.fUsageFlags = usageFlags;
224 imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
225
226 const GrVkImage::Resource* imageResource = GrVkImage::CreateResource(gpu, imageDesc);
227 if (!imageResource) {
228 return false;
229 }
230
231 // have to create a new image view for new resource
232 const GrVkImageView* oldView = fTextureView;
233 VkImage image = imageResource->fImage;
234 const GrVkImageView* textureView = GrVkImageView::Create(gpu, image, imageResource->fFormat,
235 GrVkImageView::kColor_Type, mipLevels);
236 if (!textureView) {
237 imageResource->unref(gpu);
238 return false;
239 }
240
241 oldResource->unref(gpu);
242 oldView->unref(gpu);
brianosmanf05ab1b2016-05-12 11:01:10 -0700243 if (fLinearTextureView) {
244 fLinearTextureView->unref(gpu);
245 fLinearTextureView = nullptr;
246 }
jvanverth62340062016-04-26 08:01:44 -0700247 fResource = imageResource;
248 fTextureView = textureView;
egdaniel97a23362016-05-09 08:53:59 -0700249 fCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
jvanverth62340062016-04-26 08:01:44 -0700250 this->texturePriv().setMaxMipMapLevel(mipLevels);
251
252 return true;
253}