1 /*
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 #include "vk/GrVkTypes.h"
19
20 #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.
GrVkRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageInfo & msaaInfo,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrVkImage::Wrapped wrapped)24 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
25 SkBudgeted budgeted,
26 const GrSurfaceDesc& desc,
27 const GrVkImageInfo& info,
28 const GrVkImageInfo& msaaInfo,
29 const GrVkImageView* colorAttachmentView,
30 const GrVkImageView* resolveAttachmentView,
31 GrVkImage::Wrapped wrapped)
32 : GrSurface(gpu, desc)
33 , GrVkImage(info, wrapped)
34 // for the moment we only support 1:1 color to stencil
35 , GrRenderTarget(gpu, desc)
36 , fColorAttachmentView(colorAttachmentView)
37 , fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped))
38 , fResolveAttachmentView(resolveAttachmentView)
39 , fFramebuffer(nullptr)
40 , fCachedSimpleRenderPass(nullptr) {
41 SkASSERT(desc.fSampleCnt);
42 this->createFramebuffer(gpu);
43 this->registerWithCache(budgeted);
44 }
45
46 // We're virtually derived from GrSurface (via GrRenderTarget) so its
47 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageInfo & msaaInfo,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrVkImage::Wrapped wrapped)48 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
49 const GrSurfaceDesc& desc,
50 const GrVkImageInfo& info,
51 const GrVkImageInfo& msaaInfo,
52 const GrVkImageView* colorAttachmentView,
53 const GrVkImageView* resolveAttachmentView,
54 GrVkImage::Wrapped wrapped)
55 : GrSurface(gpu, desc)
56 , GrVkImage(info, wrapped)
57 // for the moment we only support 1:1 color to stencil
58 , GrRenderTarget(gpu, desc)
59 , fColorAttachmentView(colorAttachmentView)
60 , fMSAAImage(new GrVkImage(msaaInfo, GrVkImage::kNot_Wrapped))
61 , fResolveAttachmentView(resolveAttachmentView)
62 , fFramebuffer(nullptr)
63 , fCachedSimpleRenderPass(nullptr) {
64 SkASSERT(desc.fSampleCnt);
65 this->createFramebuffer(gpu);
66 }
67
68 // We're virtually derived from GrSurface (via GrRenderTarget) so its
69 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageView * colorAttachmentView,GrVkImage::Wrapped wrapped)70 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
71 SkBudgeted budgeted,
72 const GrSurfaceDesc& desc,
73 const GrVkImageInfo& info,
74 const GrVkImageView* colorAttachmentView,
75 GrVkImage::Wrapped wrapped)
76 : GrSurface(gpu, desc)
77 , GrVkImage(info, wrapped)
78 , GrRenderTarget(gpu, desc)
79 , fColorAttachmentView(colorAttachmentView)
80 , fMSAAImage(nullptr)
81 , fResolveAttachmentView(nullptr)
82 , fFramebuffer(nullptr)
83 , fCachedSimpleRenderPass(nullptr) {
84 SkASSERT(!desc.fSampleCnt);
85 this->createFramebuffer(gpu);
86 this->registerWithCache(budgeted);
87 }
88
89 // We're virtually derived from GrSurface (via GrRenderTarget) so its
90 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,const GrVkImageView * colorAttachmentView,GrVkImage::Wrapped wrapped)91 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
92 const GrSurfaceDesc& desc,
93 const GrVkImageInfo& info,
94 const GrVkImageView* colorAttachmentView,
95 GrVkImage::Wrapped wrapped)
96 : GrSurface(gpu, desc)
97 , GrVkImage(info, wrapped)
98 , GrRenderTarget(gpu, desc)
99 , fColorAttachmentView(colorAttachmentView)
100 , fMSAAImage(nullptr)
101 , fResolveAttachmentView(nullptr)
102 , fFramebuffer(nullptr)
103 , fCachedSimpleRenderPass(nullptr) {
104 SkASSERT(!desc.fSampleCnt);
105 this->createFramebuffer(gpu);
106 }
107
108 GrVkRenderTarget*
Create(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImageInfo & info,GrVkImage::Wrapped wrapped)109 GrVkRenderTarget::Create(GrVkGpu* gpu,
110 SkBudgeted budgeted,
111 const GrSurfaceDesc& desc,
112 const GrVkImageInfo& info,
113 GrVkImage::Wrapped wrapped) {
114 SkASSERT(1 == info.fLevelCount);
115 VkFormat pixelFormat;
116 GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
117
118 VkImage colorImage;
119
120 // create msaa surface if necessary
121 GrVkImageInfo msInfo;
122 const GrVkImageView* resolveAttachmentView = nullptr;
123 if (desc.fSampleCnt) {
124 GrVkImage::ImageDesc msImageDesc;
125 msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
126 msImageDesc.fFormat = pixelFormat;
127 msImageDesc.fWidth = desc.fWidth;
128 msImageDesc.fHeight = desc.fHeight;
129 msImageDesc.fLevels = 1;
130 msImageDesc.fSamples = desc.fSampleCnt;
131 msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
132 msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
133 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
134 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
135 msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
136
137 if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &msInfo)) {
138 return nullptr;
139 }
140
141 // Set color attachment image
142 colorImage = msInfo.fImage;
143
144 // Create Resolve attachment view
145 resolveAttachmentView = GrVkImageView::Create(gpu, info.fImage, pixelFormat,
146 GrVkImageView::kColor_Type, 1);
147 if (!resolveAttachmentView) {
148 GrVkImage::DestroyImageInfo(gpu, &msInfo);
149 return nullptr;
150 }
151 } else {
152 // Set color attachment image
153 colorImage = info.fImage;
154 }
155
156 // Get color attachment view
157 const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
158 GrVkImageView::kColor_Type, 1);
159 if (!colorAttachmentView) {
160 if (desc.fSampleCnt) {
161 resolveAttachmentView->unref(gpu);
162 GrVkImage::DestroyImageInfo(gpu, &msInfo);
163 }
164 return nullptr;
165 }
166
167 GrVkRenderTarget* texRT;
168 if (desc.fSampleCnt) {
169 texRT = new GrVkRenderTarget(gpu, budgeted, desc, info, msInfo,
170 colorAttachmentView, resolveAttachmentView, wrapped);
171 } else {
172 texRT = new GrVkRenderTarget(gpu, budgeted, desc, info, colorAttachmentView, wrapped);
173 }
174
175 return texRT;
176 }
177
178 GrVkRenderTarget*
CreateNewRenderTarget(GrVkGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const GrVkImage::ImageDesc & imageDesc)179 GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu,
180 SkBudgeted budgeted,
181 const GrSurfaceDesc& desc,
182 const GrVkImage::ImageDesc& imageDesc) {
183 SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
184
185 GrVkImageInfo info;
186 if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) {
187 return nullptr;
188 }
189
190 GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, budgeted, desc, info,
191 GrVkImage::kNot_Wrapped);
192 if (!rt) {
193 GrVkImage::DestroyImageInfo(gpu, &info);
194 }
195 return rt;
196 }
197
198 sk_sp<GrVkRenderTarget>
MakeWrappedRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo * info)199 GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu,
200 const GrSurfaceDesc& desc,
201 const GrVkImageInfo* info) {
202 SkASSERT(info);
203 SkASSERT(VK_NULL_HANDLE != info->fImage);
204
205 return sk_sp<GrVkRenderTarget>(
206 GrVkRenderTarget::Create(gpu, SkBudgeted::kNo, desc, *info, GrVkImage::kBorrowed_Wrapped));
207 }
208
completeStencilAttachment()209 bool GrVkRenderTarget::completeStencilAttachment() {
210 this->createFramebuffer(this->getVkGpu());
211 return true;
212 }
213
createFramebuffer(GrVkGpu * gpu)214 void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) {
215 if (fFramebuffer) {
216 fFramebuffer->unref(gpu);
217 }
218 if (fCachedSimpleRenderPass) {
219 fCachedSimpleRenderPass->unref(gpu);
220 }
221
222 // Vulkan requires us to create a compatible renderpass before we can create our framebuffer,
223 // so we use this to get a (cached) basic renderpass, only for creation.
224 fCachedSimpleRenderPass =
225 gpu->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
226
227 // Stencil attachment view is stored in the base RT stencil attachment
228 const GrVkImageView* stencilView = this->stencilAttachmentView();
229 fFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
230 fCachedSimpleRenderPass, fColorAttachmentView,
231 stencilView);
232 SkASSERT(fFramebuffer);
233 }
234
getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * attachmentFlags) const235 void GrVkRenderTarget::getAttachmentsDescriptor(
236 GrVkRenderPass::AttachmentsDescriptor* desc,
237 GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
238 int colorSamples = this->numColorSamples();
239 VkFormat colorFormat;
240 GrPixelConfigToVkFormat(this->config(), &colorFormat);
241 desc->fColor.fFormat = colorFormat;
242 desc->fColor.fSamples = colorSamples ? colorSamples : 1;
243 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
244 uint32_t attachmentCount = 1;
245
246 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
247 if (stencil) {
248 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
249 desc->fStencil.fFormat = vkStencil->vkFormat();
250 desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 1;
251 // Currently in vulkan stencil and color attachments must all have same number of samples
252 SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples);
253 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
254 ++attachmentCount;
255 }
256 desc->fAttachmentCount = attachmentCount;
257 }
258
~GrVkRenderTarget()259 GrVkRenderTarget::~GrVkRenderTarget() {
260 // either release or abandon should have been called by the owner of this object.
261 SkASSERT(!fMSAAImage);
262 SkASSERT(!fResolveAttachmentView);
263 SkASSERT(!fColorAttachmentView);
264 SkASSERT(!fFramebuffer);
265 SkASSERT(!fCachedSimpleRenderPass);
266 }
267
addResources(GrVkCommandBuffer & commandBuffer) const268 void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const {
269 commandBuffer.addResource(this->framebuffer());
270 commandBuffer.addResource(this->colorAttachmentView());
271 commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
272 : this->resource());
273 if (this->stencilImageResource()) {
274 commandBuffer.addResource(this->stencilImageResource());
275 commandBuffer.addResource(this->stencilAttachmentView());
276 }
277 }
278
releaseInternalObjects()279 void GrVkRenderTarget::releaseInternalObjects() {
280 GrVkGpu* gpu = this->getVkGpu();
281
282 if (fMSAAImage) {
283 fMSAAImage->releaseImage(gpu);
284 fMSAAImage.reset();
285 }
286
287 if (fResolveAttachmentView) {
288 fResolveAttachmentView->unref(gpu);
289 fResolveAttachmentView = nullptr;
290 }
291 if (fColorAttachmentView) {
292 fColorAttachmentView->unref(gpu);
293 fColorAttachmentView = nullptr;
294 }
295 if (fFramebuffer) {
296 fFramebuffer->unref(gpu);
297 fFramebuffer = nullptr;
298 }
299 if (fCachedSimpleRenderPass) {
300 fCachedSimpleRenderPass->unref(gpu);
301 fCachedSimpleRenderPass = nullptr;
302 }
303 }
304
abandonInternalObjects()305 void GrVkRenderTarget::abandonInternalObjects() {
306 if (fMSAAImage) {
307 fMSAAImage->abandonImage();
308 fMSAAImage.reset();
309 }
310
311 if (fResolveAttachmentView) {
312 fResolveAttachmentView->unrefAndAbandon();
313 fResolveAttachmentView = nullptr;
314 }
315 if (fColorAttachmentView) {
316 fColorAttachmentView->unrefAndAbandon();
317 fColorAttachmentView = nullptr;
318 }
319 if (fFramebuffer) {
320 fFramebuffer->unrefAndAbandon();
321 fFramebuffer = nullptr;
322 }
323 if (fCachedSimpleRenderPass) {
324 fCachedSimpleRenderPass->unrefAndAbandon();
325 fCachedSimpleRenderPass = nullptr;
326 }
327 }
328
onRelease()329 void GrVkRenderTarget::onRelease() {
330 this->releaseInternalObjects();
331 this->releaseImage(this->getVkGpu());
332 GrRenderTarget::onRelease();
333 }
334
onAbandon()335 void GrVkRenderTarget::onAbandon() {
336 this->abandonInternalObjects();
337 this->abandonImage();
338 GrRenderTarget::onAbandon();
339 }
340
341
getRenderTargetHandle() const342 GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const {
343 // If the render target is multisampled, we currently return the ImageInfo for the resolved
344 // image. If we only wrap the msaa target (currently not implemented) we should return a handle
345 // to that instead.
346 return (GrBackendObject)&fInfo;
347 }
348
stencilImageResource() const349 const GrVkResource* GrVkRenderTarget::stencilImageResource() const {
350 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
351 if (stencil) {
352 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
353 return vkStencil->imageResource();
354 }
355
356 return nullptr;
357 }
358
stencilAttachmentView() const359 const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
360 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
361 if (stencil) {
362 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
363 return vkStencil->stencilView();
364 }
365
366 return nullptr;
367 }
368
369
getVkGpu() const370 GrVkGpu* GrVkRenderTarget::getVkGpu() const {
371 SkASSERT(!this->wasDestroyed());
372 return static_cast<GrVkGpu*>(this->getGpu());
373 }
374