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