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