• 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 "src/gpu/vk/GrVkRenderTarget.h"
9 
10 #include "include/gpu/GrBackendSurface.h"
11 #include "src/gpu/GrRenderTargetPriv.h"
12 #include "src/gpu/vk/GrVkCommandBuffer.h"
13 #include "src/gpu/vk/GrVkFramebuffer.h"
14 #include "src/gpu/vk/GrVkGpu.h"
15 #include "src/gpu/vk/GrVkImageView.h"
16 #include "src/gpu/vk/GrVkResourceProvider.h"
17 #include "src/gpu/vk/GrVkUtil.h"
18 
19 #include "include/gpu/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,SkISize dimensions,int sampleCnt,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                                    SkISize dimensions,
27                                    int sampleCnt,
28                                    const GrVkImageInfo& info,
29                                    sk_sp<GrVkImageLayout> layout,
30                                    const GrVkImageInfo& msaaInfo,
31                                    sk_sp<GrVkImageLayout> msaaLayout,
32                                    const GrVkImageView* colorAttachmentView,
33                                    const GrVkImageView* resolveAttachmentView)
34         : GrSurface(gpu, dimensions, info.fProtected)
35         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
36         // for the moment we only support 1:1 color to stencil
37         , GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected)
38         , fColorAttachmentView(colorAttachmentView)
39         , fMSAAImage(new GrVkImage(msaaInfo, std::move(msaaLayout),
40                                    GrBackendObjectOwnership::kOwned))
41         , fResolveAttachmentView(resolveAttachmentView)
42         , fCachedFramebuffer(nullptr)
43         , fCachedSimpleRenderPass(nullptr) {
44     SkASSERT(info.fProtected == msaaInfo.fProtected);
45     SkASSERT(sampleCnt > 1);
46     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
47 }
48 
49 // We're virtually derived from GrSurface (via GrRenderTarget) so its
50 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageInfo & msaaInfo,sk_sp<GrVkImageLayout> msaaLayout,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrBackendObjectOwnership ownership)51 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
52                                    SkISize dimensions,
53                                    int sampleCnt,
54                                    const GrVkImageInfo& info,
55                                    sk_sp<GrVkImageLayout> layout,
56                                    const GrVkImageInfo& msaaInfo,
57                                    sk_sp<GrVkImageLayout> msaaLayout,
58                                    const GrVkImageView* colorAttachmentView,
59                                    const GrVkImageView* resolveAttachmentView,
60                                    GrBackendObjectOwnership ownership)
61         : GrSurface(gpu, dimensions, info.fProtected)
62         , GrVkImage(info, std::move(layout), ownership)
63         // for the moment we only support 1:1 color to stencil
64         , GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected)
65         , fColorAttachmentView(colorAttachmentView)
66         , fMSAAImage(
67                   new GrVkImage(msaaInfo, std::move(msaaLayout), GrBackendObjectOwnership::kOwned))
68         , fResolveAttachmentView(resolveAttachmentView)
69         , fCachedFramebuffer(nullptr)
70         , fCachedSimpleRenderPass(nullptr) {
71     SkASSERT(info.fProtected == msaaInfo.fProtected);
72     SkASSERT(sampleCnt > 1);
73 }
74 
75 // We're virtually derived from GrSurface (via GrRenderTarget) so its
76 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * colorAttachmentView)77 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
78                                    SkISize dimensions,
79                                    const GrVkImageInfo& info,
80                                    sk_sp<GrVkImageLayout> layout,
81                                    const GrVkImageView* colorAttachmentView)
82         : GrSurface(gpu, dimensions, info.fProtected)
83         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
84         , GrRenderTarget(gpu, dimensions, 1, info.fProtected)
85         , fColorAttachmentView(colorAttachmentView)
86         , fMSAAImage(nullptr)
87         , fResolveAttachmentView(nullptr)
88         , fCachedFramebuffer(nullptr)
89         , fCachedSimpleRenderPass(nullptr) {
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,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * colorAttachmentView,GrBackendObjectOwnership ownership)95 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
96                                    SkISize dimensions,
97                                    const GrVkImageInfo& info,
98                                    sk_sp<GrVkImageLayout> layout,
99                                    const GrVkImageView* colorAttachmentView,
100                                    GrBackendObjectOwnership ownership)
101         : GrSurface(gpu, dimensions, info.fProtected)
102         , GrVkImage(info, std::move(layout), ownership)
103         , GrRenderTarget(gpu, dimensions, 1, info.fProtected)
104         , fColorAttachmentView(colorAttachmentView)
105         , fMSAAImage(nullptr)
106         , fResolveAttachmentView(nullptr)
107         , fCachedFramebuffer(nullptr)
108         , fCachedSimpleRenderPass(nullptr) {}
109 
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkRenderPass * renderPass,VkCommandBuffer secondaryCommandBuffer)110 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
111                                    SkISize dimensions,
112                                    const GrVkImageInfo& info,
113                                    sk_sp<GrVkImageLayout> layout,
114                                    const GrVkRenderPass* renderPass,
115                                    VkCommandBuffer secondaryCommandBuffer)
116         : GrSurface(gpu, dimensions, info.fProtected)
117         , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed, true)
118         , GrRenderTarget(gpu, dimensions, 1, info.fProtected)
119         , fColorAttachmentView(nullptr)
120         , fMSAAImage(nullptr)
121         , fResolveAttachmentView(nullptr)
122         , fCachedFramebuffer(nullptr)
123         , fCachedSimpleRenderPass(renderPass)
124         , fSecondaryCommandBuffer(secondaryCommandBuffer) {
125     SkASSERT(fSecondaryCommandBuffer != VK_NULL_HANDLE);
126     this->registerWithCacheWrapped(GrWrapCacheable::kNo);
127 }
128 
MakeWrappedRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout)129 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu,
130                                                                   SkISize dimensions,
131                                                                   int sampleCnt,
132                                                                   const GrVkImageInfo& info,
133                                                                   sk_sp<GrVkImageLayout> layout) {
134     SkASSERT(VK_NULL_HANDLE != info.fImage);
135 
136     SkASSERT(1 == info.fLevelCount);
137     VkFormat pixelFormat = info.fFormat;
138 
139     VkImage colorImage;
140 
141     // create msaa surface if necessary
142     GrVkImageInfo msInfo;
143     sk_sp<GrVkImageLayout> msLayout;
144     const GrVkImageView* resolveAttachmentView = nullptr;
145     if (sampleCnt > 1) {
146         GrVkImage::ImageDesc msImageDesc;
147         msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
148         msImageDesc.fFormat = pixelFormat;
149         msImageDesc.fWidth = dimensions.fWidth;
150         msImageDesc.fHeight = dimensions.fHeight;
151         msImageDesc.fLevels = 1;
152         msImageDesc.fSamples = sampleCnt;
153         msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
154         msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
155                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT |
156                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
157         msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
158         msImageDesc.fIsProtected = info.fProtected;
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 (sampleCnt > 1) {
187             resolveAttachmentView->unref(gpu);
188             GrVkImage::DestroyImageInfo(gpu, &msInfo);
189         }
190         return nullptr;
191     }
192 
193     GrVkRenderTarget* vkRT;
194     if (sampleCnt > 1) {
195         vkRT = new GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(layout), msInfo,
196                                     std::move(msLayout), colorAttachmentView,
197                                     resolveAttachmentView);
198     } else {
199         vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(layout), colorAttachmentView);
200     }
201 
202     return sk_sp<GrVkRenderTarget>(vkRT);
203 }
204 
MakeSecondaryCBRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkDrawableInfo & vkInfo)205 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
206         GrVkGpu* gpu, SkISize dimensions, 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     if (vkInfo.fSecondaryCommandBuffer == VK_NULL_HANDLE) {
223         return nullptr;
224     }
225 
226     GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(layout), rp,
227                                                   vkInfo.fSecondaryCommandBuffer);
228 
229     return sk_sp<GrVkRenderTarget>(vkRT);
230 }
231 
completeStencilAttachment()232 bool GrVkRenderTarget::completeStencilAttachment() {
233     SkASSERT(!this->wrapsSecondaryCommandBuffer());
234     // If we have a previous renderpass or framebuffer it will have been made without stencil, so
235     // we set it to null to trigger creating a new one the next time we need it.
236     if (fCachedSimpleRenderPass) {
237         fCachedSimpleRenderPass->unref(this->getVkGpu());
238         fCachedSimpleRenderPass = nullptr;
239     }
240     if (fCachedFramebuffer) {
241         fCachedFramebuffer->unref(this->getVkGpu());
242         fCachedFramebuffer = nullptr;
243     }
244     fCompatibleRPHandle = GrVkResourceProvider::CompatibleRPHandle();
245     return true;
246 }
247 
getSimpleRenderPass()248 const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass() {
249     if (fCachedSimpleRenderPass) {
250         return fCachedSimpleRenderPass;
251     }
252     return this->createSimpleRenderPass();
253 }
254 
createSimpleRenderPass()255 const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass() {
256     SkASSERT(!this->wrapsSecondaryCommandBuffer());
257     SkASSERT(!fCachedSimpleRenderPass);
258 
259     fCachedSimpleRenderPass =
260         this->getVkGpu()->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
261     return fCachedSimpleRenderPass;
262 }
263 
getFramebuffer()264 const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer() {
265     if (fCachedFramebuffer) {
266         return fCachedFramebuffer;
267     }
268     return this->createFramebuffer();
269 }
270 
createFramebuffer()271 const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer() {
272     SkASSERT(!this->wrapsSecondaryCommandBuffer());
273     SkASSERT(!fCachedFramebuffer);
274 
275     GrVkGpu* gpu = this->getVkGpu();
276     // Stencil attachment view is stored in the base RT stencil attachment
277     const GrVkImageView* stencilView = this->stencilAttachmentView();
278     const GrVkRenderPass* renderPass = this->getSimpleRenderPass();
279     if (!renderPass) {
280         return nullptr;
281     }
282     fCachedFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), renderPass,
283                                                  fColorAttachmentView, stencilView);
284     return fCachedFramebuffer;
285 }
286 
getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * attachmentFlags) const287 void GrVkRenderTarget::getAttachmentsDescriptor(
288                                            GrVkRenderPass::AttachmentsDescriptor* desc,
289                                            GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
290     SkASSERT(!this->wrapsSecondaryCommandBuffer());
291     desc->fColor.fFormat = this->imageFormat();
292     desc->fColor.fSamples = this->numSamples();
293     *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
294     uint32_t attachmentCount = 1;
295 
296     const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
297     if (stencil) {
298         const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
299         desc->fStencil.fFormat = vkStencil->vkFormat();
300         desc->fStencil.fSamples = vkStencil->numSamples();
301 #ifdef SK_DEBUG
302         if (this->getVkGpu()->caps()->mixedSamplesSupport()) {
303             SkASSERT(desc->fStencil.fSamples >= desc->fColor.fSamples);
304         } else {
305             SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
306         }
307 #endif
308         *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
309         ++attachmentCount;
310     }
311     desc->fAttachmentCount = attachmentCount;
312 }
313 
~GrVkRenderTarget()314 GrVkRenderTarget::~GrVkRenderTarget() {
315     // either release or abandon should have been called by the owner of this object.
316     SkASSERT(!fMSAAImage);
317     SkASSERT(!fResolveAttachmentView);
318     SkASSERT(!fColorAttachmentView);
319     SkASSERT(!fCachedFramebuffer);
320     SkASSERT(!fCachedSimpleRenderPass);
321 }
322 
addResources(GrVkCommandBuffer & commandBuffer)323 void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) {
324     commandBuffer.addResource(this->getFramebuffer());
325     commandBuffer.addResource(this->colorAttachmentView());
326     commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
327                                                         : this->resource());
328     if (this->stencilImageResource()) {
329         commandBuffer.addResource(this->stencilImageResource());
330         commandBuffer.addResource(this->stencilAttachmentView());
331     }
332 }
333 
releaseInternalObjects()334 void GrVkRenderTarget::releaseInternalObjects() {
335     GrVkGpu* gpu = this->getVkGpu();
336 
337     if (fMSAAImage) {
338         fMSAAImage->releaseImage(gpu);
339         fMSAAImage.reset();
340     }
341 
342     if (fResolveAttachmentView) {
343         fResolveAttachmentView->unref(gpu);
344         fResolveAttachmentView = nullptr;
345     }
346     if (fColorAttachmentView) {
347         fColorAttachmentView->unref(gpu);
348         fColorAttachmentView = nullptr;
349     }
350     if (fCachedFramebuffer) {
351         fCachedFramebuffer->unref(gpu);
352         fCachedFramebuffer = nullptr;
353     }
354     if (fCachedSimpleRenderPass) {
355         fCachedSimpleRenderPass->unref(gpu);
356         fCachedSimpleRenderPass = nullptr;
357     }
358     for (int i = 0; i < fGrSecondaryCommandBuffers.count(); ++i) {
359         SkASSERT(fGrSecondaryCommandBuffers[i]);
360         fGrSecondaryCommandBuffers[i]->releaseResources(gpu);
361     }
362     fGrSecondaryCommandBuffers.reset();
363 }
364 
onRelease()365 void GrVkRenderTarget::onRelease() {
366     this->releaseInternalObjects();
367     this->releaseImage(this->getVkGpu());
368     GrRenderTarget::onRelease();
369 }
370 
onAbandon()371 void GrVkRenderTarget::onAbandon() {
372     this->releaseInternalObjects();
373     this->releaseImage(this->getVkGpu());
374     GrRenderTarget::onAbandon();
375 }
376 
getBackendRenderTarget() const377 GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
378     SkASSERT(!this->wrapsSecondaryCommandBuffer());
379     return GrBackendRenderTarget(this->width(), this->height(), this->numSamples(), fInfo,
380                                  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