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