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