blob: 4d844553fa5e848d1fbca9c21195fdc81dbe335e [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) {
egdaniel58a8d922016-04-21 08:03:10 -0700219 imageResource = new GrVkImage::BorrowedResource(info->fImage,
220 info->fAlloc,
221 flags,
222 info->fFormat);
jvanverthfe170d22016-03-22 13:15:44 -0700223 } else {
egdaniel58a8d922016-04-21 08:03:10 -0700224 imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, flags, info->fFormat);
jvanverthfe170d22016-03-22 13:15:44 -0700225 }
jvanverthfd359ca2016-03-18 11:57:24 -0700226 if (!imageResource) {
227 return nullptr;
228 }
229
230 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
231 if (rt) {
232 rt->fCurrentLayout = info->fImageLayout;
233 }
234 // Create() will increment the refCount of the image resource if it succeeds
235 imageResource->unref(gpu);
jvanverthfe170d22016-03-22 13:15:44 -0700236
jvanverthfd359ca2016-03-18 11:57:24 -0700237 return rt;
Greg Daniel164a9f02016-02-22 09:56:40 -0500238}
239
240bool GrVkRenderTarget::completeStencilAttachment() {
241 this->createFramebuffer(this->getVkGpu());
242 return true;
243}
244
245void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) {
246 if (fFramebuffer) {
247 fFramebuffer->unref(gpu);
248 }
249 if (fCachedSimpleRenderPass) {
250 fCachedSimpleRenderPass->unref(gpu);
251 }
252
253 // Vulkan requires us to create a compatible renderpass before we can create our framebuffer,
254 // so we use this to get a (cached) basic renderpass, only for creation.
255 fCachedSimpleRenderPass = gpu->resourceProvider().findOrCreateCompatibleRenderPass(*this);
256
257 // Stencil attachment view is stored in the base RT stencil attachment
258 const GrVkImageView* stencilView = this->stencilAttachmentView();
259 fFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
260 fCachedSimpleRenderPass, fColorAttachmentView,
261 fResolveAttachmentView, stencilView);
262 SkASSERT(fFramebuffer);
263}
264
265void GrVkRenderTarget::getAttachmentsDescriptor(
266 GrVkRenderPass::AttachmentsDescriptor* desc,
267 GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
268 int colorSamples = this->numColorSamples();
269 VkFormat colorFormat;
270 GrPixelConfigToVkFormat(this->config(), &colorFormat);
271 desc->fColor.fFormat = colorFormat;
272 desc->fColor.fSamples = colorSamples ? colorSamples : 1;
273 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
274 uint32_t attachmentCount = 1;
275 if (colorSamples > 0) {
276 desc->fResolve.fFormat = colorFormat;
277 desc->fResolve.fSamples = 1;
278 *attachmentFlags |= GrVkRenderPass::kResolve_AttachmentFlag;
279 ++attachmentCount;
280 }
281
282 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
283 if (stencil) {
284 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
285 desc->fStencil.fFormat = vkStencil->vkFormat();
286 desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 1;
287 // Currently in vulkan stencil and color attachments must all have same number of samples
288 SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples);
289 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
290 ++attachmentCount;
291 }
292 desc->fAttachmentCount = attachmentCount;
293}
294
295GrVkRenderTarget::~GrVkRenderTarget() {
296 // either release or abandon should have been called by the owner of this object.
297 SkASSERT(!fMSAAImageResource);
298 SkASSERT(!fResolveAttachmentView);
299 SkASSERT(!fColorAttachmentView);
300 SkASSERT(!fFramebuffer);
301 SkASSERT(!fCachedSimpleRenderPass);
302}
303
304void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const {
305 commandBuffer.addResource(this->framebuffer());
306 commandBuffer.addResource(this->resource());
307 commandBuffer.addResource(this->colorAttachmentView());
308 if (this->msaaImageResource()) {
309 commandBuffer.addResource(this->msaaImageResource());
310 commandBuffer.addResource(this->resolveAttachmentView());
311 }
312 if (this->stencilImageResource()) {
313 commandBuffer.addResource(this->stencilImageResource());
314 commandBuffer.addResource(this->stencilAttachmentView());
315 }
316}
317
318void GrVkRenderTarget::releaseInternalObjects() {
319 GrVkGpu* gpu = this->getVkGpu();
320
321 if (fMSAAImageResource) {
322 fMSAAImageResource->unref(gpu);
323 fMSAAImageResource = nullptr;
324 }
325
326 if (fResolveAttachmentView) {
327 fResolveAttachmentView->unref(gpu);
328 fResolveAttachmentView = nullptr;
329 }
330 if (fColorAttachmentView) {
331 fColorAttachmentView->unref(gpu);
332 fColorAttachmentView = nullptr;
333 }
334 if (fFramebuffer) {
335 fFramebuffer->unref(gpu);
336 fFramebuffer = nullptr;
337 }
338 if (fCachedSimpleRenderPass) {
339 fCachedSimpleRenderPass->unref(gpu);
340 fCachedSimpleRenderPass = nullptr;
341 }
342}
343
344void GrVkRenderTarget::abandonInternalObjects() {
345 if (fMSAAImageResource) {
346 fMSAAImageResource->unrefAndAbandon();
347 fMSAAImageResource = nullptr;
348 }
349
350 if (fResolveAttachmentView) {
351 fResolveAttachmentView->unrefAndAbandon();
352 fResolveAttachmentView = nullptr;
353 }
354 if (fColorAttachmentView) {
355 fColorAttachmentView->unrefAndAbandon();
356 fColorAttachmentView = nullptr;
357 }
358 if (fFramebuffer) {
359 fFramebuffer->unrefAndAbandon();
360 fFramebuffer = nullptr;
361 }
362 if (fCachedSimpleRenderPass) {
363 fCachedSimpleRenderPass->unrefAndAbandon();
364 fCachedSimpleRenderPass = nullptr;
365 }
366}
367
368void GrVkRenderTarget::onRelease() {
369 this->releaseInternalObjects();
370 if (this->shouldFreeResources()) {
371 this->releaseImage(this->getVkGpu());
372 } else {
373 this->abandonImage();
374 }
375
376 GrRenderTarget::onRelease();
377}
378
379void GrVkRenderTarget::onAbandon() {
380 this->abandonInternalObjects();
381 this->abandonImage();
382 GrRenderTarget::onAbandon();
383}
384
385
386GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const {
387 // Currently just passing back the pointer to the main Image::Resource as the handle
388 return (GrBackendObject)&fResource;
389}
390
391const GrVkImage::Resource* GrVkRenderTarget::stencilImageResource() const {
392 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
393 if (stencil) {
394 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
395 return vkStencil->imageResource();
396 }
397
398 return nullptr;
399}
400
401const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
402 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
403 if (stencil) {
404 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
405 return vkStencil->stencilView();
406 }
407
408 return nullptr;
409}
410
411
412GrVkGpu* GrVkRenderTarget::getVkGpu() const {
413 SkASSERT(!this->wasDestroyed());
414 return static_cast<GrVkGpu*>(this->getGpu());
415}