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