OLD | NEW |
| (Empty) |
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. | |
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. | |
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. | |
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. | |
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* | |
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, colorI
mage, pixelFormat, | |
162 GrVkImageVi
ew::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, msaaRe
source, | |
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* | |
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, im
ageDesc); | |
192 if (!imageResource) { | |
193 return nullptr; | |
194 } | |
195 | |
196 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageR
esource); | |
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* | |
204 GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu, | |
205 const GrSurfaceDesc& desc, | |
206 GrGpuResource::LifeCycle lifeCycle, | |
207 const GrVkImage::Resource* imageReso
urce) { | |
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 wit
h it | |
212 return GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource); | |
213 } | |
214 | |
215 bool GrVkRenderTarget::completeStencilAttachment() { | |
216 this->createFramebuffer(this->getVkGpu()); | |
217 return true; | |
218 } | |
219 | |
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().findOrCreateCompatibleRend
erPass(*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, fColorAttach
mentView, | |
236 fResolveAttachmentView, stencilView); | |
237 SkASSERT(fFramebuffer); | |
238 } | |
239 | |
240 void GrVkRenderTarget::getAttachmentsDescriptor( | |
241 GrVkRenderPass::AttachmentsDescriptor
* desc, | |
242 GrVkRenderPass::AttachmentFlags* atta
chmentFlags) 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().getStencilAtta
chment(); | |
258 if (stencil) { | |
259 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAt
tachment*>(stencil); | |
260 desc->fStencil.fFormat = vkStencil->vkFormat(); | |
261 desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSample
s() : 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 | |
270 GrVkRenderTarget::~GrVkRenderTarget() { | |
271 // either release or abandon should have been called by the owner of this ob
ject. | |
272 SkASSERT(!fMSAAImageResource); | |
273 SkASSERT(!fResolveAttachmentView); | |
274 SkASSERT(!fColorAttachmentView); | |
275 SkASSERT(!fFramebuffer); | |
276 SkASSERT(!fCachedSimpleRenderPass); | |
277 } | |
278 | |
279 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 | |
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 | |
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 | |
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 | |
354 void GrVkRenderTarget::onAbandon() { | |
355 this->abandonInternalObjects(); | |
356 this->abandonImage(); | |
357 GrRenderTarget::onAbandon(); | |
358 } | |
359 | |
360 | |
361 GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const { | |
362 // Currently just passing back the pointer to the main Image::Resource as th
e handle | |
363 return (GrBackendObject)&fResource; | |
364 } | |
365 | |
366 const GrVkImage::Resource* GrVkRenderTarget::stencilImageResource() const { | |
367 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAtta
chment(); | |
368 if (stencil) { | |
369 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAt
tachment*>(stencil); | |
370 return vkStencil->imageResource(); | |
371 } | |
372 | |
373 return nullptr; | |
374 } | |
375 | |
376 const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const { | |
377 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAtta
chment(); | |
378 if (stencil) { | |
379 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAt
tachment*>(stencil); | |
380 return vkStencil->stencilView(); | |
381 } | |
382 | |
383 return nullptr; | |
384 } | |
385 | |
386 | |
387 GrVkGpu* GrVkRenderTarget::getVkGpu() const { | |
388 SkASSERT(!this->wasDestroyed()); | |
389 return static_cast<GrVkGpu*>(this->getGpu()); | |
390 } | |
391 | |
OLD | NEW |