1 /*
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 "src/gpu/vk/GrVkTextureRenderTarget.h"
9
10 #include "src/gpu/GrTexturePriv.h"
11 #include "src/gpu/vk/GrVkGpu.h"
12 #include "src/gpu/vk/GrVkImageView.h"
13 #include "src/gpu/vk/GrVkUtil.h"
14
15 #include "src/core/SkMipMap.h"
16
17 #include "include/gpu/vk/GrVkTypes.h"
18
19 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
20
GrVkTextureRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * texView,const GrVkImageInfo & msaaInfo,sk_sp<GrVkImageLayout> msaaLayout,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrMipMapsStatus mipMapsStatus)21 GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
22 SkBudgeted budgeted,
23 SkISize dimensions,
24 int sampleCnt,
25 const GrVkImageInfo& info,
26 sk_sp<GrVkImageLayout> layout,
27 const GrVkImageView* texView,
28 const GrVkImageInfo& msaaInfo,
29 sk_sp<GrVkImageLayout> msaaLayout,
30 const GrVkImageView* colorAttachmentView,
31 const GrVkImageView* resolveAttachmentView,
32 GrMipMapsStatus mipMapsStatus)
33 : GrSurface(gpu, dimensions, info.fProtected)
34 , GrVkImage(info, layout, GrBackendObjectOwnership::kOwned)
35 , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus,
36 GrBackendObjectOwnership::kOwned)
37 , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, layout, msaaInfo,
38 std::move(msaaLayout), colorAttachmentView, resolveAttachmentView,
39 GrBackendObjectOwnership::kOwned) {
40 SkASSERT(info.fProtected == msaaInfo.fProtected);
41 this->registerWithCache(budgeted);
42 }
43
GrVkTextureRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * texView,const GrVkImageView * colorAttachmentView,GrMipMapsStatus mipMapsStatus)44 GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
45 SkBudgeted budgeted,
46 SkISize dimensions,
47 const GrVkImageInfo& info,
48 sk_sp<GrVkImageLayout> layout,
49 const GrVkImageView* texView,
50 const GrVkImageView* colorAttachmentView,
51 GrMipMapsStatus mipMapsStatus)
52 : GrSurface(gpu, dimensions, info.fProtected)
53 , GrVkImage(info, layout, GrBackendObjectOwnership::kOwned)
54 , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus,
55 GrBackendObjectOwnership::kOwned)
56 , GrVkRenderTarget(gpu, dimensions, info, layout, colorAttachmentView,
57 GrBackendObjectOwnership::kOwned) {
58 this->registerWithCache(budgeted);
59 }
60
GrVkTextureRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * texView,const GrVkImageInfo & msaaInfo,sk_sp<GrVkImageLayout> msaaLayout,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrMipMapsStatus mipMapsStatus,GrBackendObjectOwnership ownership,GrWrapCacheable cacheable)61 GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
62 SkISize dimensions,
63 int sampleCnt,
64 const GrVkImageInfo& info,
65 sk_sp<GrVkImageLayout> layout,
66 const GrVkImageView* texView,
67 const GrVkImageInfo& msaaInfo,
68 sk_sp<GrVkImageLayout> msaaLayout,
69 const GrVkImageView* colorAttachmentView,
70 const GrVkImageView* resolveAttachmentView,
71 GrMipMapsStatus mipMapsStatus,
72 GrBackendObjectOwnership ownership,
73 GrWrapCacheable cacheable)
74 : GrSurface(gpu, dimensions, info.fProtected)
75 , GrVkImage(info, layout, ownership)
76 , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus, ownership)
77 , GrVkRenderTarget(gpu, dimensions, sampleCnt, info, layout, msaaInfo,
78 std::move(msaaLayout), colorAttachmentView, resolveAttachmentView,
79 ownership) {
80 SkASSERT(info.fProtected == msaaInfo.fProtected);
81 this->registerWithCacheWrapped(cacheable);
82 }
83
GrVkTextureRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * texView,const GrVkImageView * colorAttachmentView,GrMipMapsStatus mipMapsStatus,GrBackendObjectOwnership ownership,GrWrapCacheable cacheable)84 GrVkTextureRenderTarget::GrVkTextureRenderTarget(GrVkGpu* gpu,
85 SkISize dimensions,
86 const GrVkImageInfo& info,
87 sk_sp<GrVkImageLayout> layout,
88 const GrVkImageView* texView,
89 const GrVkImageView* colorAttachmentView,
90 GrMipMapsStatus mipMapsStatus,
91 GrBackendObjectOwnership ownership,
92 GrWrapCacheable cacheable)
93 : GrSurface(gpu, dimensions, info.fProtected)
94 , GrVkImage(info, layout, ownership)
95 , GrVkTexture(gpu, dimensions, info, layout, texView, mipMapsStatus, ownership)
96 , GrVkRenderTarget(gpu, dimensions, info, layout, colorAttachmentView, ownership) {
97 this->registerWithCacheWrapped(cacheable);
98 }
99
100 namespace {
101 struct Views {
102 const GrVkImageView* imageView = nullptr;
103 const GrVkImageView* colorAttachmentView = nullptr;
104 const GrVkImageView* resolveAttachmentView = nullptr;
105 GrVkImageInfo msInfo;
106 sk_sp<GrVkImageLayout> msLayout;
107 };
108 } // anonymous namespace
109
create_views(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info)110 static Views create_views(GrVkGpu* gpu, SkISize dimensions, int sampleCnt,
111 const GrVkImageInfo& info) {
112 VkImage image = info.fImage;
113 // Create the texture ImageView
114 Views views;
115 views.imageView = GrVkImageView::Create(gpu, image, info.fFormat, GrVkImageView::kColor_Type,
116 info.fLevelCount, info.fYcbcrConversionInfo);
117 if (!views.imageView) {
118 return {};
119 }
120
121 VkFormat pixelFormat = info.fFormat;
122
123 VkImage colorImage;
124
125 // create msaa surface if necessary
126 if (sampleCnt > 1) {
127 GrVkImage::ImageDesc msImageDesc;
128 msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
129 msImageDesc.fFormat = pixelFormat;
130 msImageDesc.fWidth = dimensions.fWidth;
131 msImageDesc.fHeight = dimensions.fHeight;
132 msImageDesc.fLevels = 1;
133 msImageDesc.fSamples = sampleCnt;
134 msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
135 msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
136 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
137 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
138 msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
139
140 if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &views.msInfo)) {
141 views.imageView->unref(gpu);
142 return {};
143 }
144
145 // Set color attachment image
146 colorImage = views.msInfo.fImage;
147
148 // Create resolve attachment view.
149 views.resolveAttachmentView =
150 GrVkImageView::Create(gpu, image, pixelFormat, GrVkImageView::kColor_Type,
151 info.fLevelCount, GrVkYcbcrConversionInfo());
152 if (!views.resolveAttachmentView) {
153 GrVkImage::DestroyImageInfo(gpu, &views.msInfo);
154 views.imageView->unref(gpu);
155 return {};
156 }
157 views.msLayout.reset(new GrVkImageLayout(views.msInfo.fImageLayout));
158 } else {
159 // Set color attachment image
160 colorImage = info.fImage;
161 }
162
163 views.colorAttachmentView = GrVkImageView::Create(
164 gpu, colorImage, pixelFormat, GrVkImageView::kColor_Type, 1, GrVkYcbcrConversionInfo());
165 if (!views.colorAttachmentView) {
166 if (sampleCnt > 1) {
167 views.resolveAttachmentView->unref(gpu);
168 GrVkImage::DestroyImageInfo(gpu, &views.msInfo);
169 }
170 views.imageView->unref(gpu);
171 return {};
172 }
173 return views;
174 }
175
MakeNewTextureRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,SkISize dimensions,int sampleCnt,const GrVkImage::ImageDesc & imageDesc,GrMipMapsStatus mipMapsStatus)176 sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeNewTextureRenderTarget(
177 GrVkGpu* gpu,
178 SkBudgeted budgeted,
179 SkISize dimensions,
180 int sampleCnt,
181 const GrVkImage::ImageDesc& imageDesc,
182 GrMipMapsStatus mipMapsStatus) {
183 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
184 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
185
186 GrVkImageInfo info;
187 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
188 return nullptr;
189 }
190 sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(info.fImageLayout));
191
192 Views views = create_views(gpu, dimensions, sampleCnt, info);
193 if (!views.colorAttachmentView) {
194 GrVkImage::DestroyImageInfo(gpu, &info);
195 return nullptr;
196 }
197 if (sampleCnt > 1) {
198 return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
199 gpu, budgeted, dimensions, sampleCnt, info, std::move(layout), views.imageView,
200 views.msInfo, std::move(views.msLayout), views.colorAttachmentView,
201 views.resolveAttachmentView, mipMapsStatus));
202 } else {
203 return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
204 gpu, budgeted, dimensions, info, std::move(layout), views.imageView,
205 views.colorAttachmentView, mipMapsStatus));
206 }
207 }
208
MakeWrappedTextureRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,GrWrapOwnership wrapOwnership,GrWrapCacheable cacheable,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout)209 sk_sp<GrVkTextureRenderTarget> GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(
210 GrVkGpu* gpu,
211 SkISize dimensions,
212 int sampleCnt,
213 GrWrapOwnership wrapOwnership,
214 GrWrapCacheable cacheable,
215 const GrVkImageInfo& info,
216 sk_sp<GrVkImageLayout> layout) {
217 // Adopted textures require both image and allocation because we're responsible for freeing
218 SkASSERT(VK_NULL_HANDLE != info.fImage &&
219 (kBorrow_GrWrapOwnership == wrapOwnership || VK_NULL_HANDLE != info.fAlloc.fMemory));
220
221 GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kDirty
222 : GrMipMapsStatus::kNotAllocated;
223
224 GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
225 ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
226 Views views = create_views(gpu, dimensions, sampleCnt, info);
227 if (!views.colorAttachmentView) {
228 return nullptr;
229 }
230 if (sampleCnt > 1) {
231 return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
232 gpu, dimensions, sampleCnt, info, std::move(layout), views.imageView, views.msInfo,
233 std::move(views.msLayout), views.colorAttachmentView, views.resolveAttachmentView,
234 mipMapsStatus, ownership, cacheable));
235 } else {
236 return sk_sp<GrVkTextureRenderTarget>(new GrVkTextureRenderTarget(
237 gpu, dimensions, info, std::move(layout), views.imageView,
238 views.colorAttachmentView, mipMapsStatus, ownership, cacheable));
239 }
240 }
241
onGpuMemorySize() const242 size_t GrVkTextureRenderTarget::onGpuMemorySize() const {
243 int numColorSamples = this->numSamples();
244 if (numColorSamples > 1) {
245 // Add one to account for the resolve VkImage.
246 ++numColorSamples;
247 }
248 const GrCaps& caps = *this->getGpu()->caps();
249 return GrSurface::ComputeSize(caps, this->backendFormat(), this->dimensions(),
250 numColorSamples, // TODO: this still correct?
251 this->texturePriv().mipMapped());
252 }
253