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