• Home
  • History
  • Annotate
  • 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 = nullptr;
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 = nullptr;
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