blob: d6895d25fc757817bb9b6cdae22ef11b148e4c10 [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,
kkinnunen2e6055b2016-04-22 01:48:29 -070025 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -050026 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070027 const GrVkImageInfo& info,
28 const GrVkImageInfo& msaaInfo,
Greg Daniel164a9f02016-02-22 09:56:40 -050029 const GrVkImageView* colorAttachmentView,
egdanielb2df0c22016-05-13 11:30:37 -070030 const GrVkImageView* resolveAttachmentView,
31 GrVkImage::Wrapped wrapped)
kkinnunen2e6055b2016-04-22 01:48:29 -070032 : GrSurface(gpu, desc)
egdanielb2df0c22016-05-13 11:30:37 -070033 , GrVkImage(info, wrapped)
Greg Daniel164a9f02016-02-22 09:56:40 -050034 // for the moment we only support 1:1 color to stencil
csmartdaltonf9635992016-08-10 11:09:07 -070035 , GrRenderTarget(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -050036 , fColorAttachmentView(colorAttachmentView)
egdaniel72ac55f2016-05-13 13:43:44 -070037 , fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped))
Greg Daniel164a9f02016-02-22 09:56:40 -050038 , fResolveAttachmentView(resolveAttachmentView)
egdaniel50ead532016-07-13 14:23:26 -070039 , fFramebuffer(nullptr)
Greg Daniel164a9f02016-02-22 09:56:40 -050040 , fCachedSimpleRenderPass(nullptr) {
41 SkASSERT(desc.fSampleCnt);
42 // The plus 1 is to account for the resolve texture.
43 fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct?
44 this->createFramebuffer(gpu);
kkinnunen2e6055b2016-04-22 01:48:29 -070045 this->registerWithCache(budgeted);
Greg Daniel164a9f02016-02-22 09:56:40 -050046}
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,
egdanielb2df0c22016-05-13 11:30:37 -070052 const GrVkImageInfo& info,
53 const GrVkImageInfo& msaaInfo,
Greg Daniel164a9f02016-02-22 09:56:40 -050054 const GrVkImageView* colorAttachmentView,
egdanielb2df0c22016-05-13 11:30:37 -070055 const GrVkImageView* resolveAttachmentView,
56 GrVkImage::Wrapped wrapped)
kkinnunen2e6055b2016-04-22 01:48:29 -070057 : GrSurface(gpu, desc)
egdanielb2df0c22016-05-13 11:30:37 -070058 , GrVkImage(info, wrapped)
Greg Daniel164a9f02016-02-22 09:56:40 -050059 // for the moment we only support 1:1 color to stencil
csmartdaltonf9635992016-08-10 11:09:07 -070060 , GrRenderTarget(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -050061 , fColorAttachmentView(colorAttachmentView)
egdaniel72ac55f2016-05-13 13:43:44 -070062 , fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped))
Greg Daniel164a9f02016-02-22 09:56:40 -050063 , fResolveAttachmentView(resolveAttachmentView)
egdaniel50ead532016-07-13 14:23:26 -070064 , fFramebuffer(nullptr)
Greg Daniel164a9f02016-02-22 09:56:40 -050065 , fCachedSimpleRenderPass(nullptr) {
66 SkASSERT(desc.fSampleCnt);
67 // The plus 1 is to account for the resolve texture.
68 fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct?
69 this->createFramebuffer(gpu);
Greg Daniel164a9f02016-02-22 09:56:40 -050070}
71
72// We're virtually derived from GrSurface (via GrRenderTarget) so its
73// constructor must be explicitly called.
74GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -070075 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -050076 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070077 const GrVkImageInfo& info,
78 const GrVkImageView* colorAttachmentView,
79 GrVkImage::Wrapped wrapped)
kkinnunen2e6055b2016-04-22 01:48:29 -070080 : GrSurface(gpu, desc)
egdanielb2df0c22016-05-13 11:30:37 -070081 , GrVkImage(info, wrapped)
csmartdaltonf9635992016-08-10 11:09:07 -070082 , GrRenderTarget(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -050083 , fColorAttachmentView(colorAttachmentView)
egdanielb2df0c22016-05-13 11:30:37 -070084 , fMSAAImage(nullptr)
Greg Daniel164a9f02016-02-22 09:56:40 -050085 , fResolveAttachmentView(nullptr)
egdaniel50ead532016-07-13 14:23:26 -070086 , fFramebuffer(nullptr)
Greg Daniel164a9f02016-02-22 09:56:40 -050087 , fCachedSimpleRenderPass(nullptr) {
88 SkASSERT(!desc.fSampleCnt);
89 fColorValuesPerPixel = 1;
90 this->createFramebuffer(gpu);
kkinnunen2e6055b2016-04-22 01:48:29 -070091 this->registerWithCache(budgeted);
Greg Daniel164a9f02016-02-22 09:56:40 -050092}
93
94// We're virtually derived from GrSurface (via GrRenderTarget) so its
95// constructor must be explicitly called.
96GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
97 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -070098 const GrVkImageInfo& info,
99 const GrVkImageView* colorAttachmentView,
100 GrVkImage::Wrapped wrapped)
kkinnunen2e6055b2016-04-22 01:48:29 -0700101 : GrSurface(gpu, desc)
egdanielb2df0c22016-05-13 11:30:37 -0700102 , GrVkImage(info, wrapped)
csmartdaltonf9635992016-08-10 11:09:07 -0700103 , GrRenderTarget(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -0500104 , fColorAttachmentView(colorAttachmentView)
egdanielb2df0c22016-05-13 11:30:37 -0700105 , fMSAAImage(nullptr)
Greg Daniel164a9f02016-02-22 09:56:40 -0500106 , fResolveAttachmentView(nullptr)
egdaniel50ead532016-07-13 14:23:26 -0700107 , fFramebuffer(nullptr)
Greg Daniel164a9f02016-02-22 09:56:40 -0500108 , fCachedSimpleRenderPass(nullptr) {
109 SkASSERT(!desc.fSampleCnt);
110 fColorValuesPerPixel = 1;
111 this->createFramebuffer(gpu);
112}
113
114GrVkRenderTarget*
115GrVkRenderTarget::Create(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -0700116 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -0500117 const GrSurfaceDesc& desc,
egdanielb2df0c22016-05-13 11:30:37 -0700118 const GrVkImageInfo& info,
119 GrVkImage::Wrapped wrapped) {
egdaniel50ead532016-07-13 14:23:26 -0700120 SkASSERT(1 == info.fLevelCount);
Greg Daniel164a9f02016-02-22 09:56:40 -0500121 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
egdanielb2df0c22016-05-13 11:30:37 -0700127 GrVkImageInfo msInfo;
Greg Daniel164a9f02016-02-22 09:56:40 -0500128 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;
egdaniel4bcd62e2016-08-31 07:37:31 -0700138 msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
139 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
140 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
Greg Daniel164a9f02016-02-22 09:56:40 -0500141 msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
142
egdanielb2df0c22016-05-13 11:30:37 -0700143 if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &msInfo)) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500144 return nullptr;
145 }
146
147 // Set color attachment image
egdanielb2df0c22016-05-13 11:30:37 -0700148 colorImage = msInfo.fImage;
Greg Daniel164a9f02016-02-22 09:56:40 -0500149
150 // Create Resolve attachment view
egdanielb2df0c22016-05-13 11:30:37 -0700151 resolveAttachmentView = GrVkImageView::Create(gpu, info.fImage, pixelFormat,
jvanverth62340062016-04-26 08:01:44 -0700152 GrVkImageView::kColor_Type, 1);
Greg Daniel164a9f02016-02-22 09:56:40 -0500153 if (!resolveAttachmentView) {
egdanielb2df0c22016-05-13 11:30:37 -0700154 GrVkImage::DestroyImageInfo(gpu, &msInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500155 return nullptr;
156 }
157 } else {
158 // Set color attachment image
egdanielb2df0c22016-05-13 11:30:37 -0700159 colorImage = info.fImage;
Greg Daniel164a9f02016-02-22 09:56:40 -0500160 }
161
162 // Get color attachment view
163 const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
jvanverth62340062016-04-26 08:01:44 -0700164 GrVkImageView::kColor_Type, 1);
Greg Daniel164a9f02016-02-22 09:56:40 -0500165 if (!colorAttachmentView) {
egdanielb2df0c22016-05-13 11:30:37 -0700166 if (desc.fSampleCnt) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500167 resolveAttachmentView->unref(gpu);
egdanielb2df0c22016-05-13 11:30:37 -0700168 GrVkImage::DestroyImageInfo(gpu, &msInfo);
Greg Daniel164a9f02016-02-22 09:56:40 -0500169 }
egdanielb2df0c22016-05-13 11:30:37 -0700170 return nullptr;
Greg Daniel164a9f02016-02-22 09:56:40 -0500171 }
172
173 GrVkRenderTarget* texRT;
egdanielb2df0c22016-05-13 11:30:37 -0700174 if (desc.fSampleCnt) {
175 texRT = new GrVkRenderTarget(gpu, budgeted, desc, info, msInfo,
176 colorAttachmentView, resolveAttachmentView, wrapped);
Greg Daniel164a9f02016-02-22 09:56:40 -0500177 } else {
egdanielb2df0c22016-05-13 11:30:37 -0700178 texRT = new GrVkRenderTarget(gpu, budgeted, desc, info, colorAttachmentView, wrapped);
Greg Daniel164a9f02016-02-22 09:56:40 -0500179 }
180
181 return texRT;
182}
183
184GrVkRenderTarget*
185GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -0700186 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -0500187 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -0500188 const GrVkImage::ImageDesc& imageDesc) {
189 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
190
egdanielb2df0c22016-05-13 11:30:37 -0700191 GrVkImageInfo info;
192 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
Greg Daniel164a9f02016-02-22 09:56:40 -0500193 return nullptr;
194 }
195
egdanielb2df0c22016-05-13 11:30:37 -0700196 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, budgeted, desc, info,
197 GrVkImage::kNot_Wrapped);
198 if (!rt) {
199 GrVkImage::DestroyImageInfo(gpu, &info);
200 }
Greg Daniel164a9f02016-02-22 09:56:40 -0500201 return rt;
202}
203
204GrVkRenderTarget*
205GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu,
206 const GrSurfaceDesc& desc,
kkinnunen2e6055b2016-04-22 01:48:29 -0700207 GrWrapOwnership ownership,
egdanielb2df0c22016-05-13 11:30:37 -0700208 const GrVkImageInfo* info) {
jvanverthfd359ca2016-03-18 11:57:24 -0700209 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);
jvanverth1e305ba2016-06-01 09:39:15 -0700212 SkASSERT(VK_NULL_HANDLE != info->fAlloc.fMemory || kAdopt_GrWrapOwnership != ownership);
Greg Daniel164a9f02016-02-22 09:56:40 -0500213
egdanielb2df0c22016-05-13 11:30:37 -0700214 GrVkImage::Wrapped wrapped = kBorrow_GrWrapOwnership == ownership ? GrVkImage::kBorrowed_Wrapped
215 : GrVkImage::kAdopted_Wrapped;
jvanverthfd359ca2016-03-18 11:57:24 -0700216
egdanielb2df0c22016-05-13 11:30:37 -0700217 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, SkBudgeted::kNo, desc, *info, wrapped);
jvanverthfe170d22016-03-22 13:15:44 -0700218
jvanverthfd359ca2016-03-18 11:57:24 -0700219 return rt;
Greg Daniel164a9f02016-02-22 09:56:40 -0500220}
221
222bool GrVkRenderTarget::completeStencilAttachment() {
223 this->createFramebuffer(this->getVkGpu());
224 return true;
225}
226
227void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) {
228 if (fFramebuffer) {
229 fFramebuffer->unref(gpu);
230 }
231 if (fCachedSimpleRenderPass) {
232 fCachedSimpleRenderPass->unref(gpu);
233 }
234
235 // Vulkan requires us to create a compatible renderpass before we can create our framebuffer,
236 // so we use this to get a (cached) basic renderpass, only for creation.
egdanield62e28b2016-06-07 08:43:30 -0700237 fCachedSimpleRenderPass =
238 gpu->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
Greg Daniel164a9f02016-02-22 09:56:40 -0500239
240 // Stencil attachment view is stored in the base RT stencil attachment
241 const GrVkImageView* stencilView = this->stencilAttachmentView();
242 fFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
243 fCachedSimpleRenderPass, fColorAttachmentView,
egdanielce3bfb12016-08-26 11:05:13 -0700244 stencilView);
Greg Daniel164a9f02016-02-22 09:56:40 -0500245 SkASSERT(fFramebuffer);
246}
247
248void GrVkRenderTarget::getAttachmentsDescriptor(
249 GrVkRenderPass::AttachmentsDescriptor* desc,
250 GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
251 int colorSamples = this->numColorSamples();
252 VkFormat colorFormat;
253 GrPixelConfigToVkFormat(this->config(), &colorFormat);
254 desc->fColor.fFormat = colorFormat;
255 desc->fColor.fSamples = colorSamples ? colorSamples : 1;
256 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
257 uint32_t attachmentCount = 1;
Greg Daniel164a9f02016-02-22 09:56:40 -0500258
259 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
260 if (stencil) {
261 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
262 desc->fStencil.fFormat = vkStencil->vkFormat();
263 desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 1;
264 // Currently in vulkan stencil and color attachments must all have same number of samples
265 SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples);
266 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
267 ++attachmentCount;
268 }
269 desc->fAttachmentCount = attachmentCount;
270}
271
272GrVkRenderTarget::~GrVkRenderTarget() {
273 // either release or abandon should have been called by the owner of this object.
egdanielb2df0c22016-05-13 11:30:37 -0700274 SkASSERT(!fMSAAImage);
Greg Daniel164a9f02016-02-22 09:56:40 -0500275 SkASSERT(!fResolveAttachmentView);
276 SkASSERT(!fColorAttachmentView);
277 SkASSERT(!fFramebuffer);
278 SkASSERT(!fCachedSimpleRenderPass);
279}
280
281void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const {
282 commandBuffer.addResource(this->framebuffer());
Greg Daniel164a9f02016-02-22 09:56:40 -0500283 commandBuffer.addResource(this->colorAttachmentView());
egdanielce3bfb12016-08-26 11:05:13 -0700284 commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
285 : this->resource());
Greg Daniel164a9f02016-02-22 09:56:40 -0500286 if (this->stencilImageResource()) {
287 commandBuffer.addResource(this->stencilImageResource());
288 commandBuffer.addResource(this->stencilAttachmentView());
289 }
290}
291
292void GrVkRenderTarget::releaseInternalObjects() {
293 GrVkGpu* gpu = this->getVkGpu();
294
egdanielb2df0c22016-05-13 11:30:37 -0700295 if (fMSAAImage) {
296 fMSAAImage->releaseImage(gpu);
297 fMSAAImage = nullptr;
Greg Daniel164a9f02016-02-22 09:56:40 -0500298 }
299
300 if (fResolveAttachmentView) {
301 fResolveAttachmentView->unref(gpu);
302 fResolveAttachmentView = nullptr;
303 }
304 if (fColorAttachmentView) {
305 fColorAttachmentView->unref(gpu);
306 fColorAttachmentView = nullptr;
307 }
308 if (fFramebuffer) {
309 fFramebuffer->unref(gpu);
310 fFramebuffer = nullptr;
311 }
312 if (fCachedSimpleRenderPass) {
313 fCachedSimpleRenderPass->unref(gpu);
314 fCachedSimpleRenderPass = nullptr;
315 }
316}
317
318void GrVkRenderTarget::abandonInternalObjects() {
egdanielb2df0c22016-05-13 11:30:37 -0700319 if (fMSAAImage) {
320 fMSAAImage->abandonImage();
321 fMSAAImage = nullptr;
Greg Daniel164a9f02016-02-22 09:56:40 -0500322 }
323
324 if (fResolveAttachmentView) {
325 fResolveAttachmentView->unrefAndAbandon();
326 fResolveAttachmentView = nullptr;
327 }
328 if (fColorAttachmentView) {
329 fColorAttachmentView->unrefAndAbandon();
330 fColorAttachmentView = nullptr;
331 }
332 if (fFramebuffer) {
333 fFramebuffer->unrefAndAbandon();
334 fFramebuffer = nullptr;
335 }
336 if (fCachedSimpleRenderPass) {
337 fCachedSimpleRenderPass->unrefAndAbandon();
338 fCachedSimpleRenderPass = nullptr;
339 }
340}
341
342void GrVkRenderTarget::onRelease() {
343 this->releaseInternalObjects();
kkinnunen2e6055b2016-04-22 01:48:29 -0700344 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500345 GrRenderTarget::onRelease();
346}
347
348void GrVkRenderTarget::onAbandon() {
349 this->abandonInternalObjects();
350 this->abandonImage();
351 GrRenderTarget::onAbandon();
352}
353
354
355GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const {
egdaniel580fa592016-08-31 11:03:50 -0700356 // If the render target is multisampled, we currently return the ImageInfo for the resolved
357 // image. If we only wrap the msaa target (currently not implemented) we should return a handle
358 // to that instead.
359 return (GrBackendObject)&fInfo;
Greg Daniel164a9f02016-02-22 09:56:40 -0500360}
361
egdanielb2df0c22016-05-13 11:30:37 -0700362const GrVkResource* GrVkRenderTarget::stencilImageResource() const {
Greg Daniel164a9f02016-02-22 09:56:40 -0500363 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
364 if (stencil) {
365 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
366 return vkStencil->imageResource();
367 }
368
369 return nullptr;
370}
371
372const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
373 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
374 if (stencil) {
375 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
376 return vkStencil->stencilView();
377 }
378
379 return nullptr;
380}
381
382
383GrVkGpu* GrVkRenderTarget::getVkGpu() const {
384 SkASSERT(!this->wasDestroyed());
385 return static_cast<GrVkGpu*>(this->getGpu());
386}