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 "src/gpu/vk/GrVkRenderTarget.h"
9
10 #include "include/gpu/GrBackendSurface.h"
11 #include "src/gpu/GrRenderTargetPriv.h"
12 #include "src/gpu/vk/GrVkCommandBuffer.h"
13 #include "src/gpu/vk/GrVkFramebuffer.h"
14 #include "src/gpu/vk/GrVkGpu.h"
15 #include "src/gpu/vk/GrVkImageView.h"
16 #include "src/gpu/vk/GrVkResourceProvider.h"
17 #include "src/gpu/vk/GrVkUtil.h"
18
19 #include "include/gpu/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,SkISize dimensions,int sampleCnt,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 SkISize dimensions,
27 int sampleCnt,
28 const GrVkImageInfo& info,
29 sk_sp<GrVkImageLayout> layout,
30 const GrVkImageInfo& msaaInfo,
31 sk_sp<GrVkImageLayout> msaaLayout,
32 const GrVkImageView* colorAttachmentView,
33 const GrVkImageView* resolveAttachmentView)
34 : GrSurface(gpu, dimensions, info.fProtected)
35 , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
36 // for the moment we only support 1:1 color to stencil
37 , GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected)
38 , fColorAttachmentView(colorAttachmentView)
39 , fMSAAImage(new GrVkImage(msaaInfo, std::move(msaaLayout),
40 GrBackendObjectOwnership::kOwned))
41 , fResolveAttachmentView(resolveAttachmentView)
42 , fCachedFramebuffer(nullptr)
43 , fCachedSimpleRenderPass(nullptr) {
44 SkASSERT(info.fProtected == msaaInfo.fProtected);
45 SkASSERT(sampleCnt > 1);
46 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
47 }
48
49 // We're virtually derived from GrSurface (via GrRenderTarget) so its
50 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageInfo & msaaInfo,sk_sp<GrVkImageLayout> msaaLayout,const GrVkImageView * colorAttachmentView,const GrVkImageView * resolveAttachmentView,GrBackendObjectOwnership ownership)51 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
52 SkISize dimensions,
53 int sampleCnt,
54 const GrVkImageInfo& info,
55 sk_sp<GrVkImageLayout> layout,
56 const GrVkImageInfo& msaaInfo,
57 sk_sp<GrVkImageLayout> msaaLayout,
58 const GrVkImageView* colorAttachmentView,
59 const GrVkImageView* resolveAttachmentView,
60 GrBackendObjectOwnership ownership)
61 : GrSurface(gpu, dimensions, info.fProtected)
62 , GrVkImage(info, std::move(layout), ownership)
63 // for the moment we only support 1:1 color to stencil
64 , GrRenderTarget(gpu, dimensions, sampleCnt, info.fProtected)
65 , fColorAttachmentView(colorAttachmentView)
66 , fMSAAImage(
67 new GrVkImage(msaaInfo, std::move(msaaLayout), GrBackendObjectOwnership::kOwned))
68 , fResolveAttachmentView(resolveAttachmentView)
69 , fCachedFramebuffer(nullptr)
70 , fCachedSimpleRenderPass(nullptr) {
71 SkASSERT(info.fProtected == msaaInfo.fProtected);
72 SkASSERT(sampleCnt > 1);
73 }
74
75 // We're virtually derived from GrSurface (via GrRenderTarget) so its
76 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * colorAttachmentView)77 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
78 SkISize dimensions,
79 const GrVkImageInfo& info,
80 sk_sp<GrVkImageLayout> layout,
81 const GrVkImageView* colorAttachmentView)
82 : GrSurface(gpu, dimensions, info.fProtected)
83 , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed)
84 , GrRenderTarget(gpu, dimensions, 1, info.fProtected)
85 , fColorAttachmentView(colorAttachmentView)
86 , fMSAAImage(nullptr)
87 , fResolveAttachmentView(nullptr)
88 , fCachedFramebuffer(nullptr)
89 , fCachedSimpleRenderPass(nullptr) {
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,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkImageView * colorAttachmentView,GrBackendObjectOwnership ownership)95 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
96 SkISize dimensions,
97 const GrVkImageInfo& info,
98 sk_sp<GrVkImageLayout> layout,
99 const GrVkImageView* colorAttachmentView,
100 GrBackendObjectOwnership ownership)
101 : GrSurface(gpu, dimensions, info.fProtected)
102 , GrVkImage(info, std::move(layout), ownership)
103 , GrRenderTarget(gpu, dimensions, 1, info.fProtected)
104 , fColorAttachmentView(colorAttachmentView)
105 , fMSAAImage(nullptr)
106 , fResolveAttachmentView(nullptr)
107 , fCachedFramebuffer(nullptr)
108 , fCachedSimpleRenderPass(nullptr) {}
109
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout,const GrVkRenderPass * renderPass,VkCommandBuffer secondaryCommandBuffer)110 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
111 SkISize dimensions,
112 const GrVkImageInfo& info,
113 sk_sp<GrVkImageLayout> layout,
114 const GrVkRenderPass* renderPass,
115 VkCommandBuffer secondaryCommandBuffer)
116 : GrSurface(gpu, dimensions, info.fProtected)
117 , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kBorrowed, true)
118 , GrRenderTarget(gpu, dimensions, 1, info.fProtected)
119 , fColorAttachmentView(nullptr)
120 , fMSAAImage(nullptr)
121 , fResolveAttachmentView(nullptr)
122 , fCachedFramebuffer(nullptr)
123 , fCachedSimpleRenderPass(renderPass)
124 , fSecondaryCommandBuffer(secondaryCommandBuffer) {
125 SkASSERT(fSecondaryCommandBuffer != VK_NULL_HANDLE);
126 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
127 }
128
MakeWrappedRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info,sk_sp<GrVkImageLayout> layout)129 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(GrVkGpu* gpu,
130 SkISize dimensions,
131 int sampleCnt,
132 const GrVkImageInfo& info,
133 sk_sp<GrVkImageLayout> layout) {
134 SkASSERT(VK_NULL_HANDLE != info.fImage);
135
136 SkASSERT(1 == info.fLevelCount);
137 VkFormat pixelFormat = info.fFormat;
138
139 VkImage colorImage;
140
141 // create msaa surface if necessary
142 GrVkImageInfo msInfo;
143 sk_sp<GrVkImageLayout> msLayout;
144 const GrVkImageView* resolveAttachmentView = nullptr;
145 if (sampleCnt > 1) {
146 GrVkImage::ImageDesc msImageDesc;
147 msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
148 msImageDesc.fFormat = pixelFormat;
149 msImageDesc.fWidth = dimensions.fWidth;
150 msImageDesc.fHeight = dimensions.fHeight;
151 msImageDesc.fLevels = 1;
152 msImageDesc.fSamples = sampleCnt;
153 msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
154 msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
155 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
156 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
157 msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
158 msImageDesc.fIsProtected = info.fProtected;
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 (sampleCnt > 1) {
187 resolveAttachmentView->unref(gpu);
188 GrVkImage::DestroyImageInfo(gpu, &msInfo);
189 }
190 return nullptr;
191 }
192
193 GrVkRenderTarget* vkRT;
194 if (sampleCnt > 1) {
195 vkRT = new GrVkRenderTarget(gpu, dimensions, sampleCnt, info, std::move(layout), msInfo,
196 std::move(msLayout), colorAttachmentView,
197 resolveAttachmentView);
198 } else {
199 vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(layout), colorAttachmentView);
200 }
201
202 return sk_sp<GrVkRenderTarget>(vkRT);
203 }
204
MakeSecondaryCBRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkDrawableInfo & vkInfo)205 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
206 GrVkGpu* gpu, SkISize dimensions, 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 if (vkInfo.fSecondaryCommandBuffer == VK_NULL_HANDLE) {
223 return nullptr;
224 }
225
226 GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu, dimensions, info, std::move(layout), rp,
227 vkInfo.fSecondaryCommandBuffer);
228
229 return sk_sp<GrVkRenderTarget>(vkRT);
230 }
231
completeStencilAttachment()232 bool GrVkRenderTarget::completeStencilAttachment() {
233 SkASSERT(!this->wrapsSecondaryCommandBuffer());
234 // If we have a previous renderpass or framebuffer it will have been made without stencil, so
235 // we set it to null to trigger creating a new one the next time we need it.
236 if (fCachedSimpleRenderPass) {
237 fCachedSimpleRenderPass->unref(this->getVkGpu());
238 fCachedSimpleRenderPass = nullptr;
239 }
240 if (fCachedFramebuffer) {
241 fCachedFramebuffer->unref(this->getVkGpu());
242 fCachedFramebuffer = nullptr;
243 }
244 fCompatibleRPHandle = GrVkResourceProvider::CompatibleRPHandle();
245 return true;
246 }
247
getSimpleRenderPass()248 const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass() {
249 if (fCachedSimpleRenderPass) {
250 return fCachedSimpleRenderPass;
251 }
252 return this->createSimpleRenderPass();
253 }
254
createSimpleRenderPass()255 const GrVkRenderPass* GrVkRenderTarget::createSimpleRenderPass() {
256 SkASSERT(!this->wrapsSecondaryCommandBuffer());
257 SkASSERT(!fCachedSimpleRenderPass);
258
259 fCachedSimpleRenderPass =
260 this->getVkGpu()->resourceProvider().findCompatibleRenderPass(*this, &fCompatibleRPHandle);
261 return fCachedSimpleRenderPass;
262 }
263
getFramebuffer()264 const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer() {
265 if (fCachedFramebuffer) {
266 return fCachedFramebuffer;
267 }
268 return this->createFramebuffer();
269 }
270
createFramebuffer()271 const GrVkFramebuffer* GrVkRenderTarget::createFramebuffer() {
272 SkASSERT(!this->wrapsSecondaryCommandBuffer());
273 SkASSERT(!fCachedFramebuffer);
274
275 GrVkGpu* gpu = this->getVkGpu();
276 // Stencil attachment view is stored in the base RT stencil attachment
277 const GrVkImageView* stencilView = this->stencilAttachmentView();
278 const GrVkRenderPass* renderPass = this->getSimpleRenderPass();
279 if (!renderPass) {
280 return nullptr;
281 }
282 fCachedFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), renderPass,
283 fColorAttachmentView, stencilView);
284 return fCachedFramebuffer;
285 }
286
getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * attachmentFlags) const287 void GrVkRenderTarget::getAttachmentsDescriptor(
288 GrVkRenderPass::AttachmentsDescriptor* desc,
289 GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
290 SkASSERT(!this->wrapsSecondaryCommandBuffer());
291 desc->fColor.fFormat = this->imageFormat();
292 desc->fColor.fSamples = this->numSamples();
293 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
294 uint32_t attachmentCount = 1;
295
296 const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
297 if (stencil) {
298 const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
299 desc->fStencil.fFormat = vkStencil->vkFormat();
300 desc->fStencil.fSamples = vkStencil->numSamples();
301 #ifdef SK_DEBUG
302 if (this->getVkGpu()->caps()->mixedSamplesSupport()) {
303 SkASSERT(desc->fStencil.fSamples >= desc->fColor.fSamples);
304 } else {
305 SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
306 }
307 #endif
308 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
309 ++attachmentCount;
310 }
311 desc->fAttachmentCount = attachmentCount;
312 }
313
~GrVkRenderTarget()314 GrVkRenderTarget::~GrVkRenderTarget() {
315 // either release or abandon should have been called by the owner of this object.
316 SkASSERT(!fMSAAImage);
317 SkASSERT(!fResolveAttachmentView);
318 SkASSERT(!fColorAttachmentView);
319 SkASSERT(!fCachedFramebuffer);
320 SkASSERT(!fCachedSimpleRenderPass);
321 }
322
addResources(GrVkCommandBuffer & commandBuffer)323 void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) {
324 commandBuffer.addResource(this->getFramebuffer());
325 commandBuffer.addResource(this->colorAttachmentView());
326 commandBuffer.addResource(this->msaaImageResource() ? this->msaaImageResource()
327 : this->resource());
328 if (this->stencilImageResource()) {
329 commandBuffer.addResource(this->stencilImageResource());
330 commandBuffer.addResource(this->stencilAttachmentView());
331 }
332 }
333
releaseInternalObjects()334 void GrVkRenderTarget::releaseInternalObjects() {
335 GrVkGpu* gpu = this->getVkGpu();
336
337 if (fMSAAImage) {
338 fMSAAImage->releaseImage(gpu);
339 fMSAAImage.reset();
340 }
341
342 if (fResolveAttachmentView) {
343 fResolveAttachmentView->unref(gpu);
344 fResolveAttachmentView = nullptr;
345 }
346 if (fColorAttachmentView) {
347 fColorAttachmentView->unref(gpu);
348 fColorAttachmentView = nullptr;
349 }
350 if (fCachedFramebuffer) {
351 fCachedFramebuffer->unref(gpu);
352 fCachedFramebuffer = nullptr;
353 }
354 if (fCachedSimpleRenderPass) {
355 fCachedSimpleRenderPass->unref(gpu);
356 fCachedSimpleRenderPass = nullptr;
357 }
358 for (int i = 0; i < fGrSecondaryCommandBuffers.count(); ++i) {
359 SkASSERT(fGrSecondaryCommandBuffers[i]);
360 fGrSecondaryCommandBuffers[i]->releaseResources(gpu);
361 }
362 fGrSecondaryCommandBuffers.reset();
363 }
364
onRelease()365 void GrVkRenderTarget::onRelease() {
366 this->releaseInternalObjects();
367 this->releaseImage(this->getVkGpu());
368 GrRenderTarget::onRelease();
369 }
370
onAbandon()371 void GrVkRenderTarget::onAbandon() {
372 this->releaseInternalObjects();
373 this->releaseImage(this->getVkGpu());
374 GrRenderTarget::onAbandon();
375 }
376
getBackendRenderTarget() const377 GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
378 SkASSERT(!this->wrapsSecondaryCommandBuffer());
379 return GrBackendRenderTarget(this->width(), this->height(), this->numSamples(), fInfo,
380 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