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/GrVkAttachment.h"
9
10 #include "src/gpu/vk/GrVkDescriptorSet.h"
11 #include "src/gpu/vk/GrVkGpu.h"
12 #include "src/gpu/vk/GrVkImage.h"
13 #include "src/gpu/vk/GrVkImageView.h"
14 #include "src/gpu/vk/GrVkUtil.h"
15
16 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
17
GrVkAttachment(GrVkGpu * gpu,SkISize dimensions,UsageFlags supportedUsages,const GrVkImageInfo & info,sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,sk_sp<const GrVkImageView> framebufferView,sk_sp<const GrVkImageView> textureView,SkBudgeted budgeted)18 GrVkAttachment::GrVkAttachment(GrVkGpu* gpu,
19 SkISize dimensions,
20 UsageFlags supportedUsages,
21 const GrVkImageInfo& info,
22 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
23 sk_sp<const GrVkImageView> framebufferView,
24 sk_sp<const GrVkImageView> textureView,
25 SkBudgeted budgeted)
26 : GrAttachment(gpu, dimensions, supportedUsages, info.fSampleCount, GrMipmapped::kNo,
27 info.fProtected)
28 , GrVkImage(gpu, info, std::move(mutableState), GrBackendObjectOwnership::kOwned)
29 , fFramebufferView(std::move(framebufferView))
30 , fTextureView(std::move(textureView)) {
31 this->registerWithCache(budgeted);
32 }
33
GrVkAttachment(GrVkGpu * gpu,SkISize dimensions,UsageFlags supportedUsages,const GrVkImageInfo & info,sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,sk_sp<const GrVkImageView> framebufferView,sk_sp<const GrVkImageView> textureView,GrBackendObjectOwnership ownership,GrWrapCacheable cacheable,bool forSecondaryCB)34 GrVkAttachment::GrVkAttachment(GrVkGpu* gpu,
35 SkISize dimensions,
36 UsageFlags supportedUsages,
37 const GrVkImageInfo& info,
38 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
39 sk_sp<const GrVkImageView> framebufferView,
40 sk_sp<const GrVkImageView> textureView,
41 GrBackendObjectOwnership ownership,
42 GrWrapCacheable cacheable,
43 bool forSecondaryCB)
44 : GrAttachment(gpu, dimensions, supportedUsages, info.fSampleCount, GrMipmapped::kNo,
45 info.fProtected)
46 , GrVkImage(gpu, info, std::move(mutableState), ownership, forSecondaryCB)
47 , fFramebufferView(std::move(framebufferView))
48 , fTextureView(std::move(textureView)) {
49 this->registerWithCacheWrapped(cacheable);
50 }
51
MakeStencil(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,VkFormat format)52 sk_sp<GrVkAttachment> GrVkAttachment::MakeStencil(GrVkGpu* gpu,
53 SkISize dimensions,
54 int sampleCnt,
55 VkFormat format) {
56 VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
57 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
58 return GrVkAttachment::Make(gpu, dimensions, UsageFlags::kStencilAttachment, sampleCnt, format,
59 /*mipLevels=*/1, vkUsageFlags, GrProtected::kNo, SkBudgeted::kYes);
60 }
61
MakeMSAA(GrVkGpu * gpu,SkISize dimensions,int numSamples,VkFormat format,GrProtected isProtected)62 sk_sp<GrVkAttachment> GrVkAttachment::MakeMSAA(GrVkGpu* gpu,
63 SkISize dimensions,
64 int numSamples,
65 VkFormat format,
66 GrProtected isProtected) {
67 SkASSERT(numSamples > 1);
68
69 VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
70 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
71 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
72 return GrVkAttachment::Make(gpu, dimensions, UsageFlags::kColorAttachment, numSamples, format,
73 /*mipLevels=*/1, vkUsageFlags, isProtected, SkBudgeted::kYes);
74 }
75
MakeTexture(GrVkGpu * gpu,SkISize dimensions,VkFormat format,uint32_t mipLevels,GrRenderable renderable,int numSamples,SkBudgeted budgeted,GrProtected isProtected)76 sk_sp<GrVkAttachment> GrVkAttachment::MakeTexture(GrVkGpu* gpu,
77 SkISize dimensions,
78 VkFormat format,
79 uint32_t mipLevels,
80 GrRenderable renderable,
81 int numSamples,
82 SkBudgeted budgeted,
83 GrProtected isProtected) {
84 UsageFlags usageFlags = UsageFlags::kTexture;
85 VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT |
86 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
87 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
88 if (renderable == GrRenderable::kYes) {
89 usageFlags |= UsageFlags::kColorAttachment;
90 vkUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
91 // We always make our render targets support being used as input attachments
92 vkUsageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
93 }
94
95 return GrVkAttachment::Make(gpu, dimensions, usageFlags, numSamples, format, mipLevels,
96 vkUsageFlags, isProtected, budgeted);
97 }
98
make_views(GrVkGpu * gpu,const GrVkImageInfo & info,GrAttachment::UsageFlags attachmentUsages,sk_sp<const GrVkImageView> * framebufferView,sk_sp<const GrVkImageView> * textureView)99 static bool make_views(GrVkGpu* gpu, const GrVkImageInfo& info,
100 GrAttachment::UsageFlags attachmentUsages,
101 sk_sp<const GrVkImageView>* framebufferView,
102 sk_sp<const GrVkImageView>* textureView) {
103 GrVkImageView::Type viewType;
104 if (attachmentUsages & GrAttachment::UsageFlags::kStencilAttachment) {
105 // If we have stencil usage then we shouldn't have any other usages
106 SkASSERT(attachmentUsages == GrAttachment::UsageFlags::kStencilAttachment);
107 viewType = GrVkImageView::kStencil_Type;
108 } else {
109 viewType = GrVkImageView::kColor_Type;
110 }
111
112 if (SkToBool(attachmentUsages & GrAttachment::UsageFlags::kStencilAttachment) ||
113 SkToBool(attachmentUsages & GrAttachment::UsageFlags::kColorAttachment)) {
114 // Attachments can only have a mip level of 1
115 *framebufferView = GrVkImageView::Make(gpu, info.fImage, info.fFormat, viewType, 1,
116 info.fYcbcrConversionInfo);
117 if (!*framebufferView) {
118 return false;
119 }
120 }
121
122 if (attachmentUsages & GrAttachment::UsageFlags::kTexture) {
123 *textureView = GrVkImageView::Make(gpu, info.fImage, info.fFormat, viewType,
124 info.fLevelCount, info.fYcbcrConversionInfo);
125 if (!*textureView) {
126 return false;
127 }
128 }
129 return true;
130 }
131
Make(GrVkGpu * gpu,SkISize dimensions,UsageFlags attachmentUsages,int sampleCnt,VkFormat format,uint32_t mipLevels,VkImageUsageFlags vkUsageFlags,GrProtected isProtected,SkBudgeted budgeted)132 sk_sp<GrVkAttachment> GrVkAttachment::Make(GrVkGpu* gpu,
133 SkISize dimensions,
134 UsageFlags attachmentUsages,
135 int sampleCnt,
136 VkFormat format,
137 uint32_t mipLevels,
138 VkImageUsageFlags vkUsageFlags,
139 GrProtected isProtected,
140 SkBudgeted budgeted) {
141 GrVkImage::ImageDesc imageDesc;
142 imageDesc.fImageType = VK_IMAGE_TYPE_2D;
143 imageDesc.fFormat = format;
144 imageDesc.fWidth = dimensions.width();
145 imageDesc.fHeight = dimensions.height();
146 imageDesc.fLevels = mipLevels;
147 imageDesc.fSamples = sampleCnt;
148 imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
149 imageDesc.fUsageFlags = vkUsageFlags;
150 imageDesc.fIsProtected = isProtected;
151
152 GrVkImageInfo info;
153 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
154 return nullptr;
155 }
156
157 sk_sp<const GrVkImageView> framebufferView;
158 sk_sp<const GrVkImageView> textureView;
159 if (!make_views(gpu, info, attachmentUsages, &framebufferView, &textureView)) {
160 GrVkImage::DestroyImageInfo(gpu, &info);
161 return nullptr;
162 }
163
164 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState(
165 new GrBackendSurfaceMutableStateImpl(info.fImageLayout, info.fCurrentQueueFamily));
166 return sk_sp<GrVkAttachment>(new GrVkAttachment(gpu, dimensions, attachmentUsages, info,
167 std::move(mutableState),
168 std::move(framebufferView),
169 std::move(textureView),
170 budgeted));
171 }
172
MakeWrapped(GrVkGpu * gpu,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,UsageFlags attachmentUsages,GrWrapOwnership ownership,GrWrapCacheable cacheable,bool forSecondaryCB)173 sk_sp<GrVkAttachment> GrVkAttachment::MakeWrapped(
174 GrVkGpu* gpu,
175 SkISize dimensions,
176 const GrVkImageInfo& info,
177 sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
178 UsageFlags attachmentUsages,
179 GrWrapOwnership ownership,
180 GrWrapCacheable cacheable,
181 bool forSecondaryCB) {
182 sk_sp<const GrVkImageView> framebufferView;
183 sk_sp<const GrVkImageView> textureView;
184 if (!forSecondaryCB) {
185 if (!make_views(gpu, info, attachmentUsages, &framebufferView, &textureView)) {
186 return nullptr;
187 }
188 }
189
190 GrBackendObjectOwnership backendOwnership = kBorrow_GrWrapOwnership == ownership
191 ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
192
193 return sk_sp<GrVkAttachment>(new GrVkAttachment(gpu, dimensions, attachmentUsages, info,
194 std::move(mutableState),
195 std::move(framebufferView),
196 std::move(textureView),
197 backendOwnership, cacheable, forSecondaryCB));
198 }
199
write_input_desc_set(GrVkGpu * gpu,VkImageView view,VkImageLayout layout,VkDescriptorSet descSet)200 static void write_input_desc_set(GrVkGpu* gpu, VkImageView view, VkImageLayout layout,
201 VkDescriptorSet descSet) {
202 VkDescriptorImageInfo imageInfo;
203 memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
204 imageInfo.sampler = VK_NULL_HANDLE;
205 imageInfo.imageView = view;
206 imageInfo.imageLayout = layout;
207
208 VkWriteDescriptorSet writeInfo;
209 memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
210 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
211 writeInfo.pNext = nullptr;
212 writeInfo.dstSet = descSet;
213 writeInfo.dstBinding = GrVkUniformHandler::kInputBinding;
214 writeInfo.dstArrayElement = 0;
215 writeInfo.descriptorCount = 1;
216 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
217 writeInfo.pImageInfo = &imageInfo;
218 writeInfo.pBufferInfo = nullptr;
219 writeInfo.pTexelBufferView = nullptr;
220
221 GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr));
222 }
223
inputDescSetForBlending(GrVkGpu * gpu)224 gr_rp < const GrVkDescriptorSet> GrVkAttachment::inputDescSetForBlending(GrVkGpu* gpu) {
225 if (!this->supportsInputAttachmentUsage()) {
226 return nullptr;
227 }
228 if (fCachedBlendingInputDescSet) {
229 return fCachedBlendingInputDescSet;
230 }
231
232 fCachedBlendingInputDescSet.reset(gpu->resourceProvider().getInputDescriptorSet());
233 if (!fCachedBlendingInputDescSet) {
234 return nullptr;
235 }
236
237 write_input_desc_set(gpu,
238 this->framebufferView()->imageView(),
239 VK_IMAGE_LAYOUT_GENERAL,
240 *fCachedBlendingInputDescSet->descriptorSet());
241
242 return fCachedBlendingInputDescSet;
243 }
244
inputDescSetForMSAALoad(GrVkGpu * gpu)245 gr_rp<const GrVkDescriptorSet> GrVkAttachment::inputDescSetForMSAALoad(GrVkGpu* gpu) {
246 if (!this->supportsInputAttachmentUsage()) {
247 return nullptr;
248 }
249 if (fCachedMSAALoadInputDescSet) {
250 return fCachedMSAALoadInputDescSet;
251 }
252
253 fCachedMSAALoadInputDescSet.reset(gpu->resourceProvider().getInputDescriptorSet());
254 if (!fCachedMSAALoadInputDescSet) {
255 return nullptr;
256 }
257
258 write_input_desc_set(gpu,
259 this->framebufferView()->imageView(),
260 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
261 *fCachedMSAALoadInputDescSet->descriptorSet());
262
263 return fCachedMSAALoadInputDescSet;
264 }
265
~GrVkAttachment()266 GrVkAttachment::~GrVkAttachment() {
267 // should have been released or abandoned first
268 SkASSERT(!fFramebufferView);
269 SkASSERT(!fTextureView);
270 }
271
release()272 void GrVkAttachment::release() {
273 this->releaseImage();
274 fFramebufferView.reset();
275 fTextureView.reset();
276 fCachedBlendingInputDescSet.reset();
277 fCachedMSAALoadInputDescSet.reset();
278 }
279
onRelease()280 void GrVkAttachment::onRelease() {
281 this->release();
282 GrAttachment::onRelease();
283 }
284
onAbandon()285 void GrVkAttachment::onAbandon() {
286 this->release();
287 GrAttachment::onAbandon();
288 }
289
getVkGpu() const290 GrVkGpu* GrVkAttachment::getVkGpu() const {
291 SkASSERT(!this->wasDestroyed());
292 return static_cast<GrVkGpu*>(this->getGpu());
293 }
294