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 "GrBackendSurface.h"
11 #include "GrRenderTargetPriv.h"
12 #include "GrVkCommandBuffer.h"
13 #include "GrVkFramebuffer.h"
14 #include "GrVkGpu.h"
15 #include "GrVkImageView.h"
16 #include "GrVkResourceProvider.h"
17 #include "GrVkUtil.h"
18
19 #include "vk/GrVkTypes.h"
20
21 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
22
23 // We're virtually derived from GrSurface (via GrRenderTarget) so its
24 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageInfo & msaaInfo,sk_sp<GrVkImageLayout> msaaLayout,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView)25 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
26 const GrSurfaceDesc& desc,
27 const GrVkImageInfo& info,
28 sk_sp<GrVkImageLayout> layout,
29 const GrVkImageInfo& msaaInfo,
30 sk_sp<GrVkImageLayout> msaaLayout,
31 const GrVkImageView* colorAttachmentView,
32 const GrVkImageView* resolveAttachmentView)
33 : GrSurface(gpu, desc)
34 , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
35 // for the moment we only support 1:1 color to stencil
36 , GrRenderTarget(gpu, desc)
37 , fColorAttachmentView(colorAttachmentView)
38 , fMSAAImage(new GrVkImage(msaaInfo, std::move(msaaLayout),
39 GrBackendObjectOwnership::kOwned))
40 , fResolveAttachmentView(resolveAttachmentView)
41 , fFramebuffer(nullptr)
42 , fCachedSimpleRenderPass(nullptr) {
43 SkASSERT(desc.fSampleCnt > 1);
44 this->createFramebuffer(gpu);
45 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
46 }
47
48 // We're virtually derived from GrSurface (via GrRenderTarget) so its
49 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageInfo & msaaInfo,sk_sp<GrVkImageLayout> msaaLayout,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrBackendObjectOwnership ownership)50 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
51 const GrSurfaceDesc& desc,
52 const GrVkImageInfo& info,
53 sk_sp<GrVkImageLayout> layout,
54 const GrVkImageInfo& msaaInfo,
55 sk_sp<GrVkImageLayout> msaaLayout,
56 const GrVkImageView* colorAttachmentView,
57 const GrVkImageView* resolveAttachmentView,
58 GrBackendObjectOwnership ownership)
59 : GrSurface(gpu, desc)
60 , GrVkImage(info, std::move(layout), ownership)
61 // for the moment we only support 1:1 color to stencil
62 , GrRenderTarget(gpu, desc)
63 , fColorAttachmentView(colorAttachmentView)
64 , fMSAAImage(new GrVkImage(msaaInfo, std::move(msaaLayout),
65 GrBackendObjectOwnership::kOwned))
66 , fResolveAttachmentView(resolveAttachmentView)
67 , fFramebuffer(nullptr)
68 , fCachedSimpleRenderPass(nullptr) {
69 SkASSERT(desc.fSampleCnt > 1);
70 this->createFramebuffer(gpu);
71 }
72
73 // We're virtually derived from GrSurface (via GrRenderTarget) so its
74 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * colorAttachmentView)75 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
76 const GrSurfaceDesc& desc,
77 const GrVkImageInfo& info,
78 sk_sp<GrVkImageLayout> layout,
79 const GrVkImageView* colorAttachmentView)
80 : GrSurface(gpu, desc)
81 , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
82 , GrRenderTarget(gpu, desc)
83 , fColorAttachmentView(colorAttachmentView)
84 , fMSAAImage(nullptr)
85 , fResolveAttachmentView(nullptr)
86 , fFramebuffer(nullptr)
87 , fCachedSimpleRenderPass(nullptr) {
88 SkASSERT(1 == desc.fSampleCnt);
89 this->createFramebuffer(gpu);
90 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
91 }
92
93 // We're virtually derived from GrSurface (via GrRenderTarget) so its
94 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * colorAttachmentView,GrBackendObjectOwnership ownership)95 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
96 const GrSurfaceDesc& desc,
97 const GrVkImageInfo& info,
98 sk_sp<GrVkImageLayout> layout,
99 const GrVkImageView* colorAttachmentView,
100 GrBackendObjectOwnership ownership)
101 : GrSurface(gpu, desc)
102 , GrVkImage(info, std::move(layout), ownership)
103 , GrRenderTarget(gpu, desc)
104 , fColorAttachmentView(colorAttachmentView)
105 , fMSAAImage(nullptr)
106 , fResolveAttachmentView(nullptr)
107 , fFramebuffer(nullptr)
108 , fCachedSimpleRenderPass(nullptr) {
109 SkASSERT(1 == desc.fSampleCnt);
110 this->createFramebuffer(gpu);
111 }
112
GrVkRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkRenderPass * renderPass,GrVkSecondaryCommandBuffer * secondaryCommandBuffer)113 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
114 const GrSurfaceDesc& desc,
115 const GrVkImageInfo& info,
116 sk_sp<GrVkImageLayout> layout,
117 const GrVkRenderPass* renderPass,
118 GrVkSecondaryCommandBuffer* secondaryCommandBuffer)
119 : GrSurface(gpu, desc)
120 , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed, true)
121 , GrRenderTarget(gpu, desc)
122 , fColorAttachmentView(nullptr)
123 , fMSAAImage(nullptr)
124 , fResolveAttachmentView(nullptr)
125 , fFramebuffer(nullptr)
126 , fCachedSimpleRenderPass(renderPass)
127 , fSecondaryCommandBuffer(secondaryCommandBuffer) {
128 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
129 }
130
MakeWrappedRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout)131 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
132 GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkImageInfo& info,
133 sk_sp<GrVkImageLayout> layout) {
134 SkASSERT(VK_NULL_HANDLE != info.fImage);
135
136 SkASSERT(1 == info.fLevelCount);
137 VkFormat pixelFormat;
138 GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
139
140 VkImage colorImage;
141
142 // create msaa surface if necessary
143 GrVkImageInfo msInfo;
144 sk_sp<GrVkImageLayout> msLayout;
145 const GrVkImageView* resolveAttachmentView = nullptr;
146 if (desc.fSampleCnt > 1) {
147 GrVkImage::ImageDesc msImageDesc;
148 msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
149 msImageDesc.fFormat = pixelFormat;
150 msImageDesc.fWidth = desc.fWidth;
151 msImageDesc.fHeight = desc.fHeight;
152 msImageDesc.fLevels = 1;
153 msImageDesc.fSamples = desc.fSampleCnt;
154 msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
155 msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
156 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
157 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
158 msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
159
160 if (!GrVkImage::InitImageInfo(gpu, msImageDesc, &msInfo)) {
161 return nullptr;
162 }
163
164 // Set color attachment image
165 colorImage = msInfo.fImage;
166
167 // Create Resolve attachment view
168 resolveAttachmentView = GrVkImageView::Create(gpu, info.fImage, pixelFormat,
169 GrVkImageView::kColor_Type, 1,
170 GrVkYcbcrConversionInfo());
171 if (!resolveAttachmentView) {
172 GrVkImage::DestroyImageInfo(gpu, &msInfo);
173 return nullptr;
174 }
175 msLayout.reset(new GrVkImageLayout(msInfo.fImageLayout));
176 } else {
177 // Set color attachment image
178 colorImage = info.fImage;
179 }
180
181 // Get color attachment view
182 const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
183 GrVkImageView::kColor_Type, 1,
184 GrVkYcbcrConversionInfo());
185 if (!colorAttachmentView) {
186 if (desc.fSampleCnt > 1) {
187 resolveAttachmentView->unref(gpu);
188 GrVkImage::DestroyImageInfo(gpu, &msInfo);
189 }
190 return nullptr;
191 }
192
193 GrVkRenderTarget* vkRT;
194 if (desc.fSampleCnt > 1) {
195 vkRT = new GrVkRenderTarget(gpu, desc, info, std::move(layout), msInfo,
196 std::move(msLayout), colorAttachmentView,
197 resolveAttachmentView);
198 } else {
199 vkRT = new GrVkRenderTarget(gpu, desc, info, std::move(layout), colorAttachmentView);
200 }
201
202 return sk_sp<GrVkRenderTarget>(vkRT);
203 }
204
MakeSecondaryCBRenderTarget(GrVkGpu * gpu,const GrSurfaceDesc & desc,const GrVkDrawableInfo & vkInfo)205 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
206 GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkDrawableInfo& vkInfo) {
207 // We only set the few properties of the GrVkImageInfo that we know like layout and format. The
208 // others we keep at the default "null" values.
209 GrVkImageInfo info;
210 info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
211 info.fFormat = vkInfo.fFormat;
212
213 sk_sp<GrVkImageLayout> layout(new GrVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
214
215 const GrVkRenderPass* rp =
216 gpu->resourceProvider().findCompatibleExternalRenderPass(vkInfo.fCompatibleRenderPass,
217 vkInfo.fColorAttachmentIndex);
218 if (!rp) {
219 return nullptr;
220 }
221
222 GrVkSecondaryCommandBuffer* scb =
223 GrVkSecondaryCommandBuffer::Create(vkInfo.fSecondaryCommandBuffer);
224 if (!scb) {
225 return nullptr;
226 }
227
228 GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, desc, info, std::move(layout), rp, scb);
229
230 return sk_sp<GrVkRenderTarget>(vkRT);
231 }
232
completeStencilAttachment()233 bool GrVkRenderTarget::completeStencilAttachment() {
234 SkASSERT(!this->wrapsSecondaryCommandBuffer());
235 this->createFramebuffer(this->getVkGpu());
236 return true;
237 }
238
createFramebuffer(GrVkGpu * gpu)239 void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) {
240 SkASSERT(!this->wrapsSecondaryCommandBuffer());
241 if (fFramebuffer) {
242 fFramebuffer->unref(gpu);
243 }
244 if (fCachedSimpleRenderPass) {
245 fCachedSimpleRenderPass->unref(gpu);
246 }
247
248 // Vulkan requires us to create a compatible renderpass before we can create our framebuffer,
249 // so we use this to get a (cached) basic renderpass, only for creation.
250 fCachedSimpleRenderPass =
251 gpu->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
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 stencilView);
258 SkASSERT(fFramebuffer);
259 }
260
getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * attachmentFlags) const261 void GrVkRenderTarget::getAttachmentsDescriptor(
262 GrVkRenderPass::AttachmentsDescriptor* desc,
263 GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
264 SkASSERT(!this->wrapsSecondaryCommandBuffer());
265 VkFormat colorFormat;
266 GrPixelConfigToVkFormat(this->config(), &colorFormat);
267 desc->fColor.fFormat = colorFormat;
268 desc->fColor.fSamples = this->numColorSamples();
269 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
270 uint32_t attachmentCount = 1;
271
272 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
273 if (stencil) {
274 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
275 desc->fStencil.fFormat = vkStencil->vkFormat();
276 desc->fStencil.fSamples = vkStencil->numSamples();
277 // Currently in vulkan stencil and color attachments must all have same number of samples
278 SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples);
279 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
280 ++attachmentCount;
281 }
282 desc->fAttachmentCount = attachmentCount;
283 }
284
~GrVkRenderTarget()285 GrVkRenderTarget::~GrVkRenderTarget() {
286 // either release or abandon should have been called by the owner of this object.
287 SkASSERT(!fMSAAImage);
288 SkASSERT(!fResolveAttachmentView);
289 SkASSERT(!fColorAttachmentView);
290 SkASSERT(!fFramebuffer);
291 SkASSERT(!fCachedSimpleRenderPass);
292 SkASSERT(!fSecondaryCommandBuffer);
293 }
294
addResources(GrVkCommandBuffer & commandBuffer) const295 void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const {
296 commandBuffer.addResource(this->framebuffer());
297 commandBuffer.addResource(this->colorAttachmentView());
298 commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
299 : this->resource());
300 if (this->stencilImageResource()) {
301 commandBuffer.addResource(this->stencilImageResource());
302 commandBuffer.addResource(this->stencilAttachmentView());
303 }
304 }
305
releaseInternalObjects()306 void GrVkRenderTarget::releaseInternalObjects() {
307 GrVkGpu* gpu = this->getVkGpu();
308
309 if (fMSAAImage) {
310 fMSAAImage->releaseImage(gpu);
311 fMSAAImage.reset();
312 }
313
314 if (fResolveAttachmentView) {
315 fResolveAttachmentView->unref(gpu);
316 fResolveAttachmentView = nullptr;
317 }
318 if (fColorAttachmentView) {
319 fColorAttachmentView->unref(gpu);
320 fColorAttachmentView = nullptr;
321 }
322 if (fFramebuffer) {
323 fFramebuffer->unref(gpu);
324 fFramebuffer = nullptr;
325 }
326 if (fCachedSimpleRenderPass) {
327 fCachedSimpleRenderPass->unref(gpu);
328 fCachedSimpleRenderPass = nullptr;
329 }
330 if (fSecondaryCommandBuffer) {
331 fSecondaryCommandBuffer->unref(gpu);
332 fSecondaryCommandBuffer = nullptr;
333 }
334 }
335
abandonInternalObjects()336 void GrVkRenderTarget::abandonInternalObjects() {
337 if (fMSAAImage) {
338 fMSAAImage->abandonImage();
339 fMSAAImage.reset();
340 }
341
342 if (fResolveAttachmentView) {
343 fResolveAttachmentView->unrefAndAbandon();
344 fResolveAttachmentView = nullptr;
345 }
346 if (fColorAttachmentView) {
347 fColorAttachmentView->unrefAndAbandon();
348 fColorAttachmentView = nullptr;
349 }
350 if (fFramebuffer) {
351 fFramebuffer->unrefAndAbandon();
352 fFramebuffer = nullptr;
353 }
354 if (fCachedSimpleRenderPass) {
355 fCachedSimpleRenderPass->unrefAndAbandon();
356 fCachedSimpleRenderPass = nullptr;
357 }
358 if (fSecondaryCommandBuffer) {
359 fSecondaryCommandBuffer->unrefAndAbandon();
360 fSecondaryCommandBuffer = nullptr;
361 }
362 }
363
onRelease()364 void GrVkRenderTarget::onRelease() {
365 this->releaseInternalObjects();
366 this->releaseImage(this->getVkGpu());
367 GrRenderTarget::onRelease();
368 }
369
onAbandon()370 void GrVkRenderTarget::onAbandon() {
371 this->abandonInternalObjects();
372 this->abandonImage();
373 GrRenderTarget::onAbandon();
374 }
375
376
getBackendRenderTarget() const377 GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
378 SkASSERT(!this->wrapsSecondaryCommandBuffer());
379 return GrBackendRenderTarget(this->width(), this->height(), this->numColorSamples(),
380 fInfo, this->grVkImageLayout());
381 }
382
stencilImageResource() const383 const GrVkResource* GrVkRenderTarget::stencilImageResource() const {
384 SkASSERT(!this->wrapsSecondaryCommandBuffer());
385 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
386 if (stencil) {
387 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
388 return vkStencil->imageResource();
389 }
390
391 return nullptr;
392 }
393
stencilAttachmentView() const394 const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
395 SkASSERT(!this->wrapsSecondaryCommandBuffer());
396 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
397 if (stencil) {
398 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
399 return vkStencil->stencilView();
400 }
401
402 return nullptr;
403 }
404
getVkGpu() const405 GrVkGpu* GrVkRenderTarget::getVkGpu() const {
406 SkASSERT(!this->wasDestroyed());
407 return static_cast<GrVkGpu*>(this->getGpu());
408 }
409