blob: 87f1f77e392fb3832cc30556349e8e1fa8e8dd1c [file] [log] [blame]
Greg Daniel48cf2682016-02-22 09:11:32 -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
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.
22GrVkRenderTarget::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.
48GrVkRenderTarget::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.
74GrVkRenderTarget::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.
95GrVkRenderTarget::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
114GrVkRenderTarget*
115GrVkRenderTarget::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, colorImage, pixelFormat,
162 GrVkImageView::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, msaaResource,
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
184GrVkRenderTarget*
185GrVkRenderTarget::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, imageDesc);
192 if (!imageResource) {
193 return nullptr;
194 }
195
196 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
197 // Create() will increment the refCount of the image resource if it succeeds
198 imageResource->unref(gpu);
199
200 return rt;
201}
202
203GrVkRenderTarget*
204GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu,
205 const GrSurfaceDesc& desc,
206 GrGpuResource::LifeCycle lifeCycle,
207 const GrVkImage::Resource* imageResource) {
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 with it
212 return GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
213}
214
215bool GrVkRenderTarget::completeStencilAttachment() {
216 this->createFramebuffer(this->getVkGpu());
217 return true;
218}
219
220void 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().findOrCreateCompatibleRenderPass(*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, fColorAttachmentView,
236 fResolveAttachmentView, stencilView);
237 SkASSERT(fFramebuffer);
238}
239
240void GrVkRenderTarget::getAttachmentsDescriptor(
241 GrVkRenderPass::AttachmentsDescriptor* desc,
242 GrVkRenderPass::AttachmentFlags* attachmentFlags) 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().getStencilAttachment();
258 if (stencil) {
259 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
260 desc->fStencil.fFormat = vkStencil->vkFormat();
261 desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 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
270GrVkRenderTarget::~GrVkRenderTarget() {
271 // either release or abandon should have been called by the owner of this object.
272 SkASSERT(!fMSAAImageResource);
273 SkASSERT(!fResolveAttachmentView);
274 SkASSERT(!fColorAttachmentView);
275 SkASSERT(!fFramebuffer);
276 SkASSERT(!fCachedSimpleRenderPass);
277}
278
279void 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
293void 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
319void 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
343void 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
354void GrVkRenderTarget::onAbandon() {
355 this->abandonInternalObjects();
356 this->abandonImage();
357 GrRenderTarget::onAbandon();
358}
359
360
361GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const {
362 // Currently just passing back the pointer to the main Image::Resource as the handle
363 return (GrBackendObject)&fResource;
364}
365
366const GrVkImage::Resource* GrVkRenderTarget::stencilImageResource() const {
367 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
368 if (stencil) {
369 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
370 return vkStencil->imageResource();
371 }
372
373 return nullptr;
374}
375
376const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
377 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
378 if (stencil) {
379 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
380 return vkStencil->stencilView();
381 }
382
383 return nullptr;
384}
385
386
387GrVkGpu* GrVkRenderTarget::getVkGpu() const {
388 SkASSERT(!this->wasDestroyed());
389 return static_cast<GrVkGpu*>(this->getGpu());
390}
391