• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrVkRenderTarget.h"
9 
10 #include "GrBackendSurface.h"
11 #include "GrRenderTargetPriv.h"
12 #include "GrVkCommandBuffer.h"
13 #include "GrVkFramebuffer.h"
14 #include "GrVkGpu.h"
15 #include "GrVkImageView.h"
16 #include "GrVkResourceProvider.h"
17 #include "GrVkUtil.h"
18 
19 #include "vk/GrVkTypes.h"
20 
21 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
22 
23 // We're virtually derived from GrSurface (via GrRenderTarget) so its
24 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageInfo & msaaInfo,sk_sp<GrVkImageLayout> msaaLayout,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView)25 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
26                                    const GrSurfaceDesc& desc,
27                                    const GrVkImageInfo& info,
28                                    sk_sp<GrVkImageLayout> layout,
29                                    const GrVkImageInfo& msaaInfo,
30                                    sk_sp<GrVkImageLayout> msaaLayout,
31                                    const GrVkImageView* colorAttachmentView,
32                                    const GrVkImageView* resolveAttachmentView)
33         : GrSurface(gpu, desc)
34         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
35         // for the moment we only support 1:1 color to stencil
36         , GrRenderTarget(gpu, desc)
37         , fColorAttachmentView(colorAttachmentView)
38         , fMSAAImage(new GrVkImage(msaaInfo, std::move(msaaLayout),
39                                    GrBackendObjectOwnership::kOwned))
40         , fResolveAttachmentView(resolveAttachmentView)
41         , fFramebuffer(nullptr)
42         , fCachedSimpleRenderPass(nullptr) {
43     SkASSERT(desc.fSampleCnt > 1);
44     this->createFramebuffer(gpu);
45     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
46 }
47 
48 // We're virtually derived from GrSurface (via GrRenderTarget) so its
49 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageInfo & msaaInfo,sk_sp<GrVkImageLayout> msaaLayout,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrBackendObjectOwnership ownership)50 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
51                                    const GrSurfaceDesc& desc,
52                                    const GrVkImageInfo& info,
53                                    sk_sp<GrVkImageLayout> layout,
54                                    const GrVkImageInfo& msaaInfo,
55                                    sk_sp<GrVkImageLayout> msaaLayout,
56                                    const GrVkImageView* colorAttachmentView,
57                                    const GrVkImageView* resolveAttachmentView,
58                                    GrBackendObjectOwnership ownership)
59         : GrSurface(gpu, desc)
60         , GrVkImage(info, std::move(layout), ownership)
61         // for the moment we only support 1:1 color to stencil
62         , GrRenderTarget(gpu, desc)
63         , fColorAttachmentView(colorAttachmentView)
64         , fMSAAImage(new GrVkImage(msaaInfo, std::move(msaaLayout),
65                                    GrBackendObjectOwnership::kOwned))
66         , fResolveAttachmentView(resolveAttachmentView)
67         , fFramebuffer(nullptr)
68         , fCachedSimpleRenderPass(nullptr) {
69     SkASSERT(desc.fSampleCnt > 1);
70     this->createFramebuffer(gpu);
71 }
72 
73 // We're virtually derived from GrSurface (via GrRenderTarget) so its
74 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * colorAttachmentView)75 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
76                                    const GrSurfaceDesc& desc,
77                                    const GrVkImageInfo& info,
78                                    sk_sp<GrVkImageLayout> layout,
79                                    const GrVkImageView* colorAttachmentView)
80         : GrSurface(gpu, desc)
81         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
82         , GrRenderTarget(gpu, desc)
83         , fColorAttachmentView(colorAttachmentView)
84         , fMSAAImage(nullptr)
85         , fResolveAttachmentView(nullptr)
86         , fFramebuffer(nullptr)
87         , fCachedSimpleRenderPass(nullptr) {
88     SkASSERT(1 == desc.fSampleCnt);
89     this->createFramebuffer(gpu);
90     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
91 }
92 
93 // We're virtually derived from GrSurface (via GrRenderTarget) so its
94 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * colorAttachmentView,GrBackendObjectOwnership ownership)95 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
96                                    const GrSurfaceDesc& desc,
97                                    const GrVkImageInfo& info,
98                                    sk_sp<GrVkImageLayout> layout,
99                                    const GrVkImageView* colorAttachmentView,
100                                    GrBackendObjectOwnership ownership)
101         : GrSurface(gpu, desc)
102         , GrVkImage(info, std::move(layout), ownership)
103         , GrRenderTarget(gpu, desc)
104         , fColorAttachmentView(colorAttachmentView)
105         , fMSAAImage(nullptr)
106         , fResolveAttachmentView(nullptr)
107         , fFramebuffer(nullptr)
108         , fCachedSimpleRenderPass(nullptr) {
109     SkASSERT(1 == desc.fSampleCnt);
110     this->createFramebuffer(gpu);
111 }
112 
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkRenderPass * renderPass,GrVkSecondaryCommandBuffer * secondaryCommandBuffer)113 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
114                                    const GrSurfaceDesc& desc,
115                                    const GrVkImageInfo& info,
116                                    sk_sp<GrVkImageLayout> layout,
117                                    const GrVkRenderPass* renderPass,
118                                    GrVkSecondaryCommandBuffer* secondaryCommandBuffer)
119         : GrSurface(gpu, desc)
120         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed, true)
121         , GrRenderTarget(gpu, desc)
122         , fColorAttachmentView(nullptr)
123         , fMSAAImage(nullptr)
124         , fResolveAttachmentView(nullptr)
125         , fFramebuffer(nullptr)
126         , fCachedSimpleRenderPass(renderPass)
127         , fSecondaryCommandBuffer(secondaryCommandBuffer) {
128     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
129 }
130 
MakeWrappedRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout)131 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
132         GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkImageInfo& info,
133         sk_sp<GrVkImageLayout> layout) {
134     SkASSERT(VK_NULL_HANDLE != info.fImage);
135 
136     SkASSERT(1 == info.fLevelCount);
137     VkFormat pixelFormat;
138     GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
139 
140     VkImage colorImage;
141 
142     // create msaa surface if necessary
143     GrVkImageInfo msInfo;
144     sk_sp<GrVkImageLayout> msLayout;
145     const GrVkImageView* resolveAttachmentView = nullptr;
146     if (desc.fSampleCnt > 1) {
147         GrVkImage::ImageDesc msImageDesc;
148         msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
149         msImageDesc.fFormat = pixelFormat;
150         msImageDesc.fWidth = desc.fWidth;
151         msImageDesc.fHeight = desc.fHeight;
152         msImageDesc.fLevels = 1;
153         msImageDesc.fSamples = desc.fSampleCnt;
154         msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
155         msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
156                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT |
157                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
158         msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
159 
160         if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &msInfo)) {
161             return nullptr;
162         }
163 
164         // Set color attachment image
165         colorImage = msInfo.fImage;
166 
167         // Create Resolve attachment view
168         resolveAttachmentView = GrVkImageView::Create(gpu, info.fImage, pixelFormat,
169                                                       GrVkImageView::kColor_Type, 1,
170                                                       GrVkYcbcrConversionInfo());
171         if (!resolveAttachmentView) {
172             GrVkImage::DestroyImageInfo(gpu, &msInfo);
173             return nullptr;
174         }
175         msLayout.reset(new GrVkImageLayout(msInfo.fImageLayout));
176     } else {
177         // Set color attachment image
178         colorImage = info.fImage;
179     }
180 
181     // Get color attachment view
182     const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
183                                                                      GrVkImageView::kColor_Type, 1,
184                                                                      GrVkYcbcrConversionInfo());
185     if (!colorAttachmentView) {
186         if (desc.fSampleCnt > 1) {
187             resolveAttachmentView->unref(gpu);
188             GrVkImage::DestroyImageInfo(gpu, &msInfo);
189         }
190         return nullptr;
191     }
192 
193     GrVkRenderTarget* vkRT;
194     if (desc.fSampleCnt > 1) {
195         vkRT = new GrVkRenderTarget(gpu, desc, info, std::move(layout), msInfo,
196                                     std::move(msLayout), colorAttachmentView,
197                                     resolveAttachmentView);
198     } else {
199         vkRT = new GrVkRenderTarget(gpu, desc, info, std::move(layout), colorAttachmentView);
200     }
201 
202     return sk_sp<GrVkRenderTarget>(vkRT);
203 }
204 
MakeSecondaryCBRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkDrawableInfo & vkInfo)205 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
206         GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkDrawableInfo& vkInfo) {
207     // We only set the few properties of the GrVkImageInfo that we know like layout and format. The
208     // others we keep at the default "null" values.
209     GrVkImageInfo info;
210     info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
211     info.fFormat = vkInfo.fFormat;
212 
213     sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
214 
215     const GrVkRenderPass* rp =
216             gpu->resourceProvider().findCompatibleExternalRenderPass(vkInfo.fCompatibleRenderPass,
217                                                                      vkInfo.fColorAttachmentIndex);
218     if (!rp) {
219         return nullptr;
220     }
221 
222     GrVkSecondaryCommandBuffer* scb =
223             GrVkSecondaryCommandBuffer::Create(vkInfo.fSecondaryCommandBuffer);
224     if (!scb) {
225         return nullptr;
226     }
227 
228     GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, desc, info, std::move(layout), rp, scb);
229 
230     return sk_sp<GrVkRenderTarget>(vkRT);
231 }
232 
completeStencilAttachment()233 bool GrVkRenderTarget::completeStencilAttachment() {
234     SkASSERT(!this->wrapsSecondaryCommandBuffer());
235     this->createFramebuffer(this->getVkGpu());
236     return true;
237 }
238 
createFramebuffer(GrVkGpu * gpu)239 void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) {
240     SkASSERT(!this->wrapsSecondaryCommandBuffer());
241     if (fFramebuffer) {
242         fFramebuffer->unref(gpu);
243     }
244     if (fCachedSimpleRenderPass) {
245         fCachedSimpleRenderPass->unref(gpu);
246     }
247 
248     // Vulkan requires us to create a compatible renderpass before we can create our framebuffer,
249     // so we use this to get a (cached) basic renderpass, only for creation.
250     fCachedSimpleRenderPass =
251         gpu->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
252 
253     // Stencil attachment view is stored in the base RT stencil attachment
254     const GrVkImageView* stencilView = this->stencilAttachmentView();
255     fFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
256                                            fCachedSimpleRenderPass, fColorAttachmentView,
257                                            stencilView);
258     SkASSERT(fFramebuffer);
259 }
260 
getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * attachmentFlags) const261 void GrVkRenderTarget::getAttachmentsDescriptor(
262                                            GrVkRenderPass::AttachmentsDescriptor* desc,
263                                            GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
264     SkASSERT(!this->wrapsSecondaryCommandBuffer());
265     VkFormat colorFormat;
266     GrPixelConfigToVkFormat(this->config(), &colorFormat);
267     desc->fColor.fFormat = colorFormat;
268     desc->fColor.fSamples = this->numColorSamples();
269     *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
270     uint32_t attachmentCount = 1;
271 
272     const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
273     if (stencil) {
274         const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
275         desc->fStencil.fFormat = vkStencil->vkFormat();
276         desc->fStencil.fSamples = vkStencil->numSamples();
277         // Currently in vulkan stencil and color attachments must all have same number of samples
278         SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples);
279         *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
280         ++attachmentCount;
281     }
282     desc->fAttachmentCount = attachmentCount;
283 }
284 
~GrVkRenderTarget()285 GrVkRenderTarget::~GrVkRenderTarget() {
286     // either release or abandon should have been called by the owner of this object.
287     SkASSERT(!fMSAAImage);
288     SkASSERT(!fResolveAttachmentView);
289     SkASSERT(!fColorAttachmentView);
290     SkASSERT(!fFramebuffer);
291     SkASSERT(!fCachedSimpleRenderPass);
292     SkASSERT(!fSecondaryCommandBuffer);
293 }
294 
addResources(GrVkCommandBuffer & commandBuffer) const295 void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const {
296     commandBuffer.addResource(this->framebuffer());
297     commandBuffer.addResource(this->colorAttachmentView());
298     commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
299                                                         : this->resource());
300     if (this->stencilImageResource()) {
301         commandBuffer.addResource(this->stencilImageResource());
302         commandBuffer.addResource(this->stencilAttachmentView());
303     }
304 }
305 
releaseInternalObjects()306 void GrVkRenderTarget::releaseInternalObjects() {
307     GrVkGpu* gpu = this->getVkGpu();
308 
309     if (fMSAAImage) {
310         fMSAAImage->releaseImage(gpu);
311         fMSAAImage.reset();
312     }
313 
314     if (fResolveAttachmentView) {
315         fResolveAttachmentView->unref(gpu);
316         fResolveAttachmentView = nullptr;
317     }
318     if (fColorAttachmentView) {
319         fColorAttachmentView->unref(gpu);
320         fColorAttachmentView = nullptr;
321     }
322     if (fFramebuffer) {
323         fFramebuffer->unref(gpu);
324         fFramebuffer = nullptr;
325     }
326     if (fCachedSimpleRenderPass) {
327         fCachedSimpleRenderPass->unref(gpu);
328         fCachedSimpleRenderPass = nullptr;
329     }
330     if (fSecondaryCommandBuffer) {
331         fSecondaryCommandBuffer->unref(gpu);
332         fSecondaryCommandBuffer = nullptr;
333     }
334 }
335 
abandonInternalObjects()336 void GrVkRenderTarget::abandonInternalObjects() {
337     if (fMSAAImage) {
338         fMSAAImage->abandonImage();
339         fMSAAImage.reset();
340     }
341 
342     if (fResolveAttachmentView) {
343         fResolveAttachmentView->unrefAndAbandon();
344         fResolveAttachmentView = nullptr;
345     }
346     if (fColorAttachmentView) {
347         fColorAttachmentView->unrefAndAbandon();
348         fColorAttachmentView = nullptr;
349     }
350     if (fFramebuffer) {
351         fFramebuffer->unrefAndAbandon();
352         fFramebuffer = nullptr;
353     }
354     if (fCachedSimpleRenderPass) {
355         fCachedSimpleRenderPass->unrefAndAbandon();
356         fCachedSimpleRenderPass = nullptr;
357     }
358     if (fSecondaryCommandBuffer) {
359         fSecondaryCommandBuffer->unrefAndAbandon();
360         fSecondaryCommandBuffer = nullptr;
361     }
362 }
363 
onRelease()364 void GrVkRenderTarget::onRelease() {
365     this->releaseInternalObjects();
366     this->releaseImage(this->getVkGpu());
367     GrRenderTarget::onRelease();
368 }
369 
onAbandon()370 void GrVkRenderTarget::onAbandon() {
371     this->abandonInternalObjects();
372     this->abandonImage();
373     GrRenderTarget::onAbandon();
374 }
375 
376 
getBackendRenderTarget() const377 GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
378     SkASSERT(!this->wrapsSecondaryCommandBuffer());
379     return GrBackendRenderTarget(this->width(), this->height(), this->numColorSamples(),
380                                  fInfo, this->grVkImageLayout());
381 }
382 
stencilImageResource() const383 const GrVkResource* GrVkRenderTarget::stencilImageResource() const {
384     SkASSERT(!this->wrapsSecondaryCommandBuffer());
385     const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
386     if (stencil) {
387         const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
388         return vkStencil->imageResource();
389     }
390 
391     return nullptr;
392 }
393 
stencilAttachmentView() const394 const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
395     SkASSERT(!this->wrapsSecondaryCommandBuffer());
396     const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
397     if (stencil) {
398         const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
399         return vkStencil->stencilView();
400     }
401 
402     return nullptr;
403 }
404 
getVkGpu() const405 GrVkGpu* GrVkRenderTarget::getVkGpu() const {
406     SkASSERT(!this->wasDestroyed());
407     return static_cast<GrVkGpu*>(this->getGpu());
408 }
409