blob: 46099f2bd8eb53276188214b78af03bc77cf2412 [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,
Greg Daniel164a9f02016-02-22 09:56:40 -050027 const GrVkImage::Resource* imageResource,
28 const GrVkImage::Resource* msaaResource,
29 const GrVkImageView* colorAttachmentView,
30 const GrVkImageView* resolveAttachmentView)
kkinnunen2e6055b2016-04-22 01:48:29 -070031 : GrSurface(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -050032 , GrVkImage(imageResource)
33 // for the moment we only support 1:1 color to stencil
kkinnunen2e6055b2016-04-22 01:48:29 -070034 , GrRenderTarget(gpu, desc, kUnified_SampleConfig)
Greg Daniel164a9f02016-02-22 09:56:40 -050035 , 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);
kkinnunen2e6055b2016-04-22 01:48:29 -070044 this->registerWithCache(budgeted);
Greg Daniel164a9f02016-02-22 09:56:40 -050045 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,
Greg Daniel164a9f02016-02-22 09:56:40 -050052 const GrVkImage::Resource* imageResource,
53 const GrVkImage::Resource* msaaResource,
54 const GrVkImageView* colorAttachmentView,
kkinnunen2e6055b2016-04-22 01:48:29 -070055 const GrVkImageView* resolveAttachmentView)
56 : GrSurface(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -050057 , GrVkImage(imageResource)
58 // for the moment we only support 1:1 color to stencil
kkinnunen2e6055b2016-04-22 01:48:29 -070059 , GrRenderTarget(gpu, desc, kUnified_SampleConfig)
Greg Daniel164a9f02016-02-22 09:56:40 -050060 , 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.
74GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -070075 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -050076 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -050077 const GrVkImage::Resource* imageResource,
78 const GrVkImageView* colorAttachmentView)
kkinnunen2e6055b2016-04-22 01:48:29 -070079 : GrSurface(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -050080 , GrVkImage(imageResource)
kkinnunen2e6055b2016-04-22 01:48:29 -070081 , GrRenderTarget(gpu, desc, kUnified_SampleConfig)
Greg Daniel164a9f02016-02-22 09:56:40 -050082 , 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);
kkinnunen2e6055b2016-04-22 01:48:29 -070090 this->registerWithCache(budgeted);
Greg Daniel164a9f02016-02-22 09:56:40 -050091}
92
93// We're virtually derived from GrSurface (via GrRenderTarget) so its
94// constructor must be explicitly called.
95GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
96 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -050097 const GrVkImage::Resource* imageResource,
kkinnunen2e6055b2016-04-22 01:48:29 -070098 const GrVkImageView* colorAttachmentView)
99 : GrSurface(gpu, desc)
Greg Daniel164a9f02016-02-22 09:56:40 -0500100 , GrVkImage(imageResource)
kkinnunen2e6055b2016-04-22 01:48:29 -0700101 , GrRenderTarget(gpu, desc, kUnified_SampleConfig)
Greg Daniel164a9f02016-02-22 09:56:40 -0500102 , fFramebuffer(nullptr)
103 , fColorAttachmentView(colorAttachmentView)
104 , fMSAAImageResource(nullptr)
105 , fResolveAttachmentView(nullptr)
106 , fCachedSimpleRenderPass(nullptr) {
107 SkASSERT(!desc.fSampleCnt);
108 fColorValuesPerPixel = 1;
109 this->createFramebuffer(gpu);
110}
111
112GrVkRenderTarget*
113GrVkRenderTarget::Create(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -0700114 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -0500115 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -0500116 const GrVkImage::Resource* imageResource) {
117 VkFormat pixelFormat;
118 GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
halcanary9d524f22016-03-29 09:03:52 -0700119
Greg Daniel164a9f02016-02-22 09:56:40 -0500120 VkImage colorImage;
121
122 // create msaa surface if necessary
123 const GrVkImage::Resource* msaaResource = nullptr;
124 const GrVkImageView* resolveAttachmentView = nullptr;
125 if (desc.fSampleCnt) {
126 GrVkImage::ImageDesc msImageDesc;
127 msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
128 msImageDesc.fFormat = pixelFormat;
129 msImageDesc.fWidth = desc.fWidth;
130 msImageDesc.fHeight = desc.fHeight;
131 msImageDesc.fLevels = 1;
132 msImageDesc.fSamples = desc.fSampleCnt;
133 msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
134 msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
135 msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
136
137 msaaResource = GrVkImage::CreateResource(gpu, msImageDesc);
138
139 if (!msaaResource) {
140 return nullptr;
141 }
142
143 // Set color attachment image
144 colorImage = msaaResource->fImage;
145
146 // Create Resolve attachment view
147 resolveAttachmentView = GrVkImageView::Create(gpu, imageResource->fImage, pixelFormat,
jvanverth62340062016-04-26 08:01:44 -0700148 GrVkImageView::kColor_Type, 1);
Greg Daniel164a9f02016-02-22 09:56:40 -0500149 if (!resolveAttachmentView) {
150 msaaResource->unref(gpu);
151 return nullptr;
152 }
153 } else {
154 // Set color attachment image
155 colorImage = imageResource->fImage;
156 }
157
158 // Get color attachment view
159 const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
jvanverth62340062016-04-26 08:01:44 -0700160 GrVkImageView::kColor_Type, 1);
Greg Daniel164a9f02016-02-22 09:56:40 -0500161 if (!colorAttachmentView) {
162 if (msaaResource) {
163 resolveAttachmentView->unref(gpu);
164 msaaResource->unref(gpu);
165 }
166 return NULL;
167 }
168
169 GrVkRenderTarget* texRT;
170 if (msaaResource) {
kkinnunen2e6055b2016-04-22 01:48:29 -0700171 texRT = new GrVkRenderTarget(gpu, budgeted, desc, imageResource, msaaResource,
Greg Daniel164a9f02016-02-22 09:56:40 -0500172 colorAttachmentView, resolveAttachmentView);
173 msaaResource->unref(gpu);
174 } else {
kkinnunen2e6055b2016-04-22 01:48:29 -0700175 texRT = new GrVkRenderTarget(gpu, budgeted, desc, imageResource,
Greg Daniel164a9f02016-02-22 09:56:40 -0500176 colorAttachmentView);
177 }
178
179 return texRT;
180}
181
182GrVkRenderTarget*
183GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu,
kkinnunen2e6055b2016-04-22 01:48:29 -0700184 SkBudgeted budgeted,
Greg Daniel164a9f02016-02-22 09:56:40 -0500185 const GrSurfaceDesc& desc,
Greg Daniel164a9f02016-02-22 09:56:40 -0500186 const GrVkImage::ImageDesc& imageDesc) {
187 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
188
189 const GrVkImage::Resource* imageResource = GrVkImage::CreateResource(gpu, imageDesc);
190 if (!imageResource) {
191 return nullptr;
192 }
193
kkinnunen2e6055b2016-04-22 01:48:29 -0700194 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, budgeted, desc, imageResource);
Greg Daniel164a9f02016-02-22 09:56:40 -0500195 // Create() will increment the refCount of the image resource if it succeeds
196 imageResource->unref(gpu);
Greg Daniel164a9f02016-02-22 09:56:40 -0500197 return rt;
198}
199
200GrVkRenderTarget*
201GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu,
202 const GrSurfaceDesc& desc,
kkinnunen2e6055b2016-04-22 01:48:29 -0700203 GrWrapOwnership ownership,
jvanverthfd359ca2016-03-18 11:57:24 -0700204 const GrVkTextureInfo* info) {
205 SkASSERT(info);
206 // We can wrap a rendertarget without its allocation, as long as we don't take ownership
207 SkASSERT(VK_NULL_HANDLE != info->fImage);
kkinnunen2e6055b2016-04-22 01:48:29 -0700208 SkASSERT(VK_NULL_HANDLE != info->fAlloc || kAdopt_GrWrapOwnership != ownership);
Greg Daniel164a9f02016-02-22 09:56:40 -0500209
halcanary9d524f22016-03-29 09:03:52 -0700210 GrVkImage::Resource::Flags flags = (VK_IMAGE_TILING_LINEAR == info->fImageTiling)
jvanverthfd359ca2016-03-18 11:57:24 -0700211 ? Resource::kLinearTiling_Flag : Resource::kNo_Flags;
212
jvanverthfe170d22016-03-22 13:15:44 -0700213 const GrVkImage::Resource* imageResource;
kkinnunen2e6055b2016-04-22 01:48:29 -0700214 if (kBorrow_GrWrapOwnership == ownership) {
egdaniel58a8d922016-04-21 08:03:10 -0700215 imageResource = new GrVkImage::BorrowedResource(info->fImage,
216 info->fAlloc,
217 flags,
218 info->fFormat);
jvanverthfe170d22016-03-22 13:15:44 -0700219 } else {
egdaniel58a8d922016-04-21 08:03:10 -0700220 imageResource = new GrVkImage::Resource(info->fImage, info->fAlloc, flags, info->fFormat);
jvanverthfe170d22016-03-22 13:15:44 -0700221 }
jvanverthfd359ca2016-03-18 11:57:24 -0700222 if (!imageResource) {
223 return nullptr;
224 }
225
kkinnunen2e6055b2016-04-22 01:48:29 -0700226 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, SkBudgeted::kNo, desc, imageResource);
jvanverthfd359ca2016-03-18 11:57:24 -0700227 if (rt) {
228 rt->fCurrentLayout = info->fImageLayout;
229 }
230 // Create() will increment the refCount of the image resource if it succeeds
231 imageResource->unref(gpu);
jvanverthfe170d22016-03-22 13:15:44 -0700232
jvanverthfd359ca2016-03-18 11:57:24 -0700233 return rt;
Greg Daniel164a9f02016-02-22 09:56:40 -0500234}
235
236bool GrVkRenderTarget::completeStencilAttachment() {
237 this->createFramebuffer(this->getVkGpu());
238 return true;
239}
240
241void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) {
242 if (fFramebuffer) {
243 fFramebuffer->unref(gpu);
244 }
245 if (fCachedSimpleRenderPass) {
246 fCachedSimpleRenderPass->unref(gpu);
247 }
248
249 // Vulkan requires us to create a compatible renderpass before we can create our framebuffer,
250 // so we use this to get a (cached) basic renderpass, only for creation.
251 fCachedSimpleRenderPass = gpu->resourceProvider().findOrCreateCompatibleRenderPass(*this);
252
253 // Stencil attachment view is stored in the base RT stencil attachment
254 const GrVkImageView* stencilView = this->stencilAttachmentView();
255 fFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
256 fCachedSimpleRenderPass, fColorAttachmentView,
257 fResolveAttachmentView, stencilView);
258 SkASSERT(fFramebuffer);
259}
260
261void GrVkRenderTarget::getAttachmentsDescriptor(
262 GrVkRenderPass::AttachmentsDescriptor* desc,
263 GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
264 int colorSamples = this->numColorSamples();
265 VkFormat colorFormat;
266 GrPixelConfigToVkFormat(this->config(), &colorFormat);
267 desc->fColor.fFormat = colorFormat;
268 desc->fColor.fSamples = colorSamples ? colorSamples : 1;
269 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
270 uint32_t attachmentCount = 1;
271 if (colorSamples > 0) {
272 desc->fResolve.fFormat = colorFormat;
273 desc->fResolve.fSamples = 1;
274 *attachmentFlags |= GrVkRenderPass::kResolve_AttachmentFlag;
275 ++attachmentCount;
276 }
277
278 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
279 if (stencil) {
280 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
281 desc->fStencil.fFormat = vkStencil->vkFormat();
282 desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 1;
283 // Currently in vulkan stencil and color attachments must all have same number of samples
284 SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples);
285 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
286 ++attachmentCount;
287 }
288 desc->fAttachmentCount = attachmentCount;
289}
290
291GrVkRenderTarget::~GrVkRenderTarget() {
292 // either release or abandon should have been called by the owner of this object.
293 SkASSERT(!fMSAAImageResource);
294 SkASSERT(!fResolveAttachmentView);
295 SkASSERT(!fColorAttachmentView);
296 SkASSERT(!fFramebuffer);
297 SkASSERT(!fCachedSimpleRenderPass);
298}
299
300void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const {
301 commandBuffer.addResource(this->framebuffer());
302 commandBuffer.addResource(this->resource());
303 commandBuffer.addResource(this->colorAttachmentView());
304 if (this->msaaImageResource()) {
305 commandBuffer.addResource(this->msaaImageResource());
306 commandBuffer.addResource(this->resolveAttachmentView());
307 }
308 if (this->stencilImageResource()) {
309 commandBuffer.addResource(this->stencilImageResource());
310 commandBuffer.addResource(this->stencilAttachmentView());
311 }
312}
313
314void GrVkRenderTarget::releaseInternalObjects() {
315 GrVkGpu* gpu = this->getVkGpu();
316
317 if (fMSAAImageResource) {
318 fMSAAImageResource->unref(gpu);
319 fMSAAImageResource = nullptr;
320 }
321
322 if (fResolveAttachmentView) {
323 fResolveAttachmentView->unref(gpu);
324 fResolveAttachmentView = nullptr;
325 }
326 if (fColorAttachmentView) {
327 fColorAttachmentView->unref(gpu);
328 fColorAttachmentView = nullptr;
329 }
330 if (fFramebuffer) {
331 fFramebuffer->unref(gpu);
332 fFramebuffer = nullptr;
333 }
334 if (fCachedSimpleRenderPass) {
335 fCachedSimpleRenderPass->unref(gpu);
336 fCachedSimpleRenderPass = nullptr;
337 }
338}
339
340void GrVkRenderTarget::abandonInternalObjects() {
341 if (fMSAAImageResource) {
342 fMSAAImageResource->unrefAndAbandon();
343 fMSAAImageResource = nullptr;
344 }
345
346 if (fResolveAttachmentView) {
347 fResolveAttachmentView->unrefAndAbandon();
348 fResolveAttachmentView = nullptr;
349 }
350 if (fColorAttachmentView) {
351 fColorAttachmentView->unrefAndAbandon();
352 fColorAttachmentView = nullptr;
353 }
354 if (fFramebuffer) {
355 fFramebuffer->unrefAndAbandon();
356 fFramebuffer = nullptr;
357 }
358 if (fCachedSimpleRenderPass) {
359 fCachedSimpleRenderPass->unrefAndAbandon();
360 fCachedSimpleRenderPass = nullptr;
361 }
362}
363
364void GrVkRenderTarget::onRelease() {
365 this->releaseInternalObjects();
kkinnunen2e6055b2016-04-22 01:48:29 -0700366 this->releaseImage(this->getVkGpu());
Greg Daniel164a9f02016-02-22 09:56:40 -0500367 GrRenderTarget::onRelease();
368}
369
370void GrVkRenderTarget::onAbandon() {
371 this->abandonInternalObjects();
372 this->abandonImage();
373 GrRenderTarget::onAbandon();
374}
375
376
377GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const {
378 // Currently just passing back the pointer to the main Image::Resource as the handle
379 return (GrBackendObject)&fResource;
380}
381
382const GrVkImage::Resource* GrVkRenderTarget::stencilImageResource() const {
383 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
384 if (stencil) {
385 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
386 return vkStencil->imageResource();
387 }
388
389 return nullptr;
390}
391
392const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
393 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
394 if (stencil) {
395 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
396 return vkStencil->stencilView();
397 }
398
399 return nullptr;
400}
401
402
403GrVkGpu* GrVkRenderTarget::getVkGpu() const {
404 SkASSERT(!this->wasDestroyed());
405 return static_cast<GrVkGpu*>(this->getGpu());
406}