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