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/ganesh/vk/GrVkRenderTarget.h"
9
10 #include "include/gpu/GrBackendSurface.h"
11 #include "include/gpu/GrDirectContext.h"
12 #include "include/gpu/MutableTextureState.h"
13 #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
14 #include "include/gpu/vk/GrVkTypes.h"
15 #include "include/gpu/vk/VulkanMutableTextureState.h"
16 #include "include/private/base/SkAssert.h"
17 #include "src/gpu/ganesh/GrDirectContextPriv.h"
18 #include "src/gpu/ganesh/GrResourceProvider.h"
19 #include "src/gpu/ganesh/vk/GrVkBackendSurfacePriv.h"
20 #include "src/gpu/ganesh/vk/GrVkCommandBuffer.h"
21 #include "src/gpu/ganesh/vk/GrVkDescriptorSet.h"
22 #include "src/gpu/ganesh/vk/GrVkFramebuffer.h"
23 #include "src/gpu/ganesh/vk/GrVkGpu.h"
24 #include "src/gpu/ganesh/vk/GrVkImageView.h"
25 #include "src/gpu/ganesh/vk/GrVkResourceProvider.h"
26 #include "src/gpu/ganesh/vk/GrVkUtil.h"
27
28 #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
29
renderpass_features_to_index(bool hasResolve,bool hasStencil,GrVkRenderPass::SelfDependencyFlags selfDepFlags,GrVkRenderPass::LoadFromResolve loadFromReslove)30 static int renderpass_features_to_index(bool hasResolve, bool hasStencil,
31 GrVkRenderPass::SelfDependencyFlags selfDepFlags,
32 GrVkRenderPass::LoadFromResolve loadFromReslove) {
33 int index = 0;
34 if (hasResolve) {
35 index += 1;
36 }
37 if (hasStencil) {
38 index += 2;
39 }
40 if (selfDepFlags & GrVkRenderPass::SelfDependencyFlags::kForInputAttachment) {
41 index += 4;
42 }
43 if (selfDepFlags & GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend) {
44 index += 8;
45 }
46 if (loadFromReslove == GrVkRenderPass::LoadFromResolve::kLoad) {
47 index += 16;
48 }
49 return index;
50 }
51
52 // We're virtually derived from GrSurface (via GrRenderTarget) so its
53 // constructor must be explicitly called.
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkImage> colorAttachment,sk_sp<GrVkImage> resolveAttachment,CreateType createType,std::string_view label)54 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
55 SkISize dimensions,
56 sk_sp<GrVkImage> colorAttachment,
57 sk_sp<GrVkImage> resolveAttachment,
58 CreateType createType,
59 std::string_view label)
60 : GrSurface(gpu,
61 dimensions,
62 colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo,
63 label)
64 // for the moment we only support 1:1 color to stencil
65 , GrRenderTarget(gpu,
66 dimensions,
67 colorAttachment->numSamples(),
68 colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo,
69 label)
70 , fColorAttachment(std::move(colorAttachment))
71 , fResolveAttachment(std::move(resolveAttachment))
72 , fCachedFramebuffers() {
73 SkASSERT(fColorAttachment);
74
75 if (fColorAttachment->numSamples() == 1 && fColorAttachment->supportsInputAttachmentUsage()) {
76 SkASSERT(!fResolveAttachment);
77 // When we have a single sampled color attachment, we set both the color and resolve
78 // to the same attachment. This way if we use DMAA on this render target we will resolve
79 // to the single target attachment.
80 fResolveAttachment = fColorAttachment;
81 }
82
83 SkASSERT(!fResolveAttachment ||
84 (fResolveAttachment->isProtected() == fColorAttachment->isProtected()));
85 SkASSERT(SkToBool(fColorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
86 this->setFlags();
87 if (createType == CreateType::kDirectlyWrapped) {
88 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
89 }
90 }
91
GrVkRenderTarget(GrVkGpu * gpu,SkISize dimensions,sk_sp<GrVkFramebuffer> externalFramebuffer,std::string_view label)92 GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
93 SkISize dimensions,
94 sk_sp<GrVkFramebuffer> externalFramebuffer,
95 std::string_view label)
96 : GrSurface(gpu,
97 dimensions,
98 externalFramebuffer->colorAttachment()->isProtected() ? GrProtected::kYes
99 : GrProtected::kNo,
100 label)
101 , GrRenderTarget(gpu,
102 dimensions,
103 1,
104 externalFramebuffer->colorAttachment()->isProtected() ? GrProtected::kYes
105 : GrProtected::kNo,
106 label)
107 , fCachedFramebuffers()
108 , fExternalFramebuffer(externalFramebuffer) {
109 SkASSERT(fExternalFramebuffer);
110 SkASSERT(!fColorAttachment);
111 SkDEBUGCODE(auto colorAttachment = fExternalFramebuffer->colorAttachment());
112 SkASSERT(colorAttachment);
113 SkASSERT(colorAttachment->numSamples() == 1);
114 SkASSERT(SkToBool(colorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
115 SkASSERT(!SkToBool(colorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT));
116 this->setFlags();
117 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
118 }
119
setFlags()120 void GrVkRenderTarget::setFlags() {
121 if (this->wrapsSecondaryCommandBuffer()) {
122 return;
123 }
124 GrVkImage* nonMSAAAttachment = this->nonMSAAAttachment();
125 if (nonMSAAAttachment && nonMSAAAttachment->supportsInputAttachmentUsage()) {
126 this->setVkRTSupportsInputAttachment();
127 }
128 }
129
MakeWrappedRenderTarget(GrVkGpu * gpu,SkISize dimensions,int sampleCnt,const GrVkImageInfo & info,sk_sp<skgpu::MutableTextureState> mutableState)130 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
131 GrVkGpu* gpu,
132 SkISize dimensions,
133 int sampleCnt,
134 const GrVkImageInfo& info,
135 sk_sp<skgpu::MutableTextureState> mutableState) {
136 SkASSERT(VK_NULL_HANDLE != info.fImage);
137 SkASSERT(1 == info.fLevelCount);
138 SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1);
139
140 int wrappedImageSampleCnt = static_cast<int>(info.fSampleCount);
141 if (sampleCnt != wrappedImageSampleCnt && wrappedImageSampleCnt != 1) {
142 return nullptr;
143 }
144
145 sk_sp<GrVkImage> wrappedAttachment =
146 GrVkImage::MakeWrapped(gpu,
147 dimensions,
148 info,
149 std::move(mutableState),
150 GrAttachment::UsageFlags::kColorAttachment,
151 kBorrow_GrWrapOwnership,
152 GrWrapCacheable::kNo,
153 /*label=*/"VkImage_WrappedAttachment");
154 if (!wrappedAttachment) {
155 return nullptr;
156 }
157
158 sk_sp<GrVkImage> colorAttachment;
159 colorAttachment = std::move(wrappedAttachment);
160
161 if (!colorAttachment) {
162 return nullptr;
163 }
164
165 GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu,
166 dimensions,
167 std::move(colorAttachment),
168 nullptr,
169 CreateType::kDirectlyWrapped,
170 /*label=*/"Vk_MakeWrappedRenderTarget");
171 return sk_sp<GrVkRenderTarget>(vkRT);
172 }
173
MakeSecondaryCBRenderTarget(GrVkGpu * gpu,SkISize dimensions,const GrVkDrawableInfo & vkInfo)174 sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
175 GrVkGpu* gpu, SkISize dimensions, const GrVkDrawableInfo& vkInfo) {
176 const GrVkRenderPass* rp = gpu->resourceProvider().findCompatibleExternalRenderPass(
177 vkInfo.fCompatibleRenderPass, vkInfo.fColorAttachmentIndex);
178 if (!rp) {
179 return nullptr;
180 }
181
182 if (vkInfo.fSecondaryCommandBuffer == VK_NULL_HANDLE) {
183 return nullptr;
184 }
185
186 // We only set the few properties of the GrVkImageInfo that we know like layout and format. The
187 // others we keep at the default "null" values.
188 GrVkImageInfo info;
189 info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
190 info.fFormat = vkInfo.fFormat;
191 info.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
192 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
193
194 auto mutableState =
195 sk_make_sp<skgpu::MutableTextureState>(skgpu::MutableTextureStates::MakeVulkan(
196 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED));
197
198 sk_sp<GrVkImage> colorAttachment =
199 GrVkImage::MakeWrapped(gpu,
200 dimensions,
201 info,
202 std::move(mutableState),
203 GrAttachment::UsageFlags::kColorAttachment,
204 kBorrow_GrWrapOwnership,
205 GrWrapCacheable::kNo,
206 "VkImage_ColorAttachment",
207 true);
208
209 std::unique_ptr<GrVkSecondaryCommandBuffer> scb(
210 GrVkSecondaryCommandBuffer::Create(vkInfo.fSecondaryCommandBuffer, rp));
211 if (!scb) {
212 return nullptr;
213 }
214
215 sk_sp<GrVkFramebuffer> framebuffer(new GrVkFramebuffer(
216 gpu, std::move(colorAttachment), sk_sp<const GrVkRenderPass>(rp),
217 std::move(scb)));
218
219 GrVkRenderTarget* vkRT =
220 new GrVkRenderTarget(gpu, dimensions, std::move(framebuffer),
221 /*label=*/"Vk_MakeSecondaryCBRenderTarget");
222
223 return sk_sp<GrVkRenderTarget>(vkRT);
224 }
225
backendFormat() const226 GrBackendFormat GrVkRenderTarget::backendFormat() const {
227 if (this->wrapsSecondaryCommandBuffer()) {
228 return fExternalFramebuffer->colorAttachment()->backendFormat();
229 }
230 return fColorAttachment->backendFormat();
231 }
232
nonMSAAAttachment() const233 GrVkImage* GrVkRenderTarget::nonMSAAAttachment() const {
234 if (fColorAttachment->numSamples() == 1) {
235 return fColorAttachment.get();
236 } else {
237 return fResolveAttachment.get();
238 }
239 }
240
dynamicMSAAAttachment()241 GrVkImage* GrVkRenderTarget::dynamicMSAAAttachment() {
242 if (fDynamicMSAAAttachment) {
243 return fDynamicMSAAAttachment.get();
244 }
245 const GrVkImage* nonMSAAColorAttachment = this->colorAttachment();
246 SkASSERT(nonMSAAColorAttachment->numSamples() == 1);
247
248 GrVkGpu* gpu = this->getVkGpu();
249 auto rp = gpu->getContext()->priv().resourceProvider();
250
251 const GrBackendFormat& format = nonMSAAColorAttachment->backendFormat();
252
253 GrMemoryless memoryless =
254 gpu->vkCaps().supportsMemorylessAttachments() ? GrMemoryless::kYes : GrMemoryless::kNo;
255
256 sk_sp<GrAttachment> msaaAttachment =
257 rp->getDiscardableMSAAAttachment(nonMSAAColorAttachment->dimensions(),
258 format,
259 gpu->caps()->internalMultisampleCount(format),
260 GrProtected(nonMSAAColorAttachment->isProtected()),
261 memoryless);
262 if (!msaaAttachment) {
263 return nullptr;
264 }
265 fDynamicMSAAAttachment = sk_sp<GrVkImage>(static_cast<GrVkImage*>(msaaAttachment.release()));
266 return fDynamicMSAAAttachment.get();
267 }
268
msaaAttachment()269 GrVkImage* GrVkRenderTarget::msaaAttachment() {
270 return this->colorAttachment()->numSamples() == 1 ? this->dynamicMSAAAttachment()
271 : this->colorAttachment();
272 }
273
canAttemptStencilAttachment(bool useMSAASurface) const274 bool GrVkRenderTarget::canAttemptStencilAttachment(bool useMSAASurface) const {
275 SkASSERT(!useMSAASurface || this->numSamples() > 1 ||
276 this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA());
277 if (!useMSAASurface && this->numSamples() > 1) {
278 return false;
279 }
280 bool validMSAA = true;
281 if (useMSAASurface) {
282 validMSAA = this->numSamples() > 1 ||
283 (this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA() &&
284 this->colorAttachment()->supportsInputAttachmentUsage());
285 }
286 // We don't know the status of the stencil attachment for wrapped external secondary command
287 // buffers so we just assume we don't have one.
288 return validMSAA && !this->wrapsSecondaryCommandBuffer();
289 }
290
completeStencilAttachment(GrAttachment * stencil,bool useMSAASurface)291 bool GrVkRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
292 SkASSERT(!this->wrapsSecondaryCommandBuffer());
293 SkASSERT(!useMSAASurface ||
294 this->numSamples() > 1 ||
295 this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA());
296 return true;
297 }
298
externalFramebuffer() const299 sk_sp<GrVkFramebuffer> GrVkRenderTarget::externalFramebuffer() const {
300 return fExternalFramebuffer;
301 }
302
compatibleRenderPassHandle(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)303 GrVkResourceProvider::CompatibleRPHandle GrVkRenderTarget::compatibleRenderPassHandle(
304 bool withResolve,
305 bool withStencil,
306 SelfDependencyFlags selfDepFlags,
307 LoadFromResolve loadFromResolve) {
308 SkASSERT(!this->wrapsSecondaryCommandBuffer());
309
310 const GrVkFramebuffer* fb =
311 this->getFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
312 if (!fb) {
313 return {};
314 }
315
316 return fb->compatibleRenderPassHandle();
317 }
318
getSimpleRenderPass(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)319 const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withResolve,
320 bool withStencil,
321 SelfDependencyFlags selfDepFlags,
322 LoadFromResolve loadFromResolve) {
323 if (this->wrapsSecondaryCommandBuffer()) {
324 return fExternalFramebuffer->externalRenderPass();
325 }
326
327 const GrVkFramebuffer* fb =
328 this->getFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
329 if (!fb) {
330 return nullptr;
331 }
332
333 return fb->compatibleRenderPass();
334 }
335
336 std::pair<const GrVkRenderPass*, GrVkResourceProvider::CompatibleRPHandle>
createSimpleRenderPass(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)337 GrVkRenderTarget::createSimpleRenderPass(bool withResolve,
338 bool withStencil,
339 SelfDependencyFlags selfDepFlags,
340 LoadFromResolve loadFromResolve) {
341 SkASSERT(!this->wrapsSecondaryCommandBuffer());
342
343 GrVkResourceProvider& rp = this->getVkGpu()->resourceProvider();
344
345 GrVkResourceProvider::CompatibleRPHandle handle;
346 const GrVkRenderPass* renderPass = rp.findCompatibleRenderPass(
347 this, &handle, withResolve, withStencil, selfDepFlags,
348 loadFromResolve);
349 SkASSERT(!renderPass || handle.isValid());
350 return {renderPass, handle};
351 }
352
getFramebuffer(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)353 const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withResolve,
354 bool withStencil,
355 SelfDependencyFlags selfDepFlags,
356 LoadFromResolve loadFromResolve) {
357 int cacheIndex =
358 renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
359 SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);
360 if (auto fb = fCachedFramebuffers[cacheIndex]) {
361 return fb.get();
362 }
363
364 this->createFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
365 return fCachedFramebuffers[cacheIndex].get();
366 }
367
createFramebuffer(bool withResolve,bool withStencil,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)368 void GrVkRenderTarget::createFramebuffer(bool withResolve,
369 bool withStencil,
370 SelfDependencyFlags selfDepFlags,
371 LoadFromResolve loadFromResolve) {
372 SkASSERT(!this->wrapsSecondaryCommandBuffer());
373 GrVkGpu* gpu = this->getVkGpu();
374
375 auto[renderPass, compatibleHandle] =
376 this->createSimpleRenderPass(withResolve, withStencil, selfDepFlags, loadFromResolve);
377 if (!renderPass) {
378 return;
379 }
380 SkASSERT(compatibleHandle.isValid());
381
382 int cacheIndex =
383 renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
384 SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);
385
386 GrVkImage* resolve = withResolve ? this->resolveAttachment() : nullptr;
387 GrVkImage* colorAttachment = withResolve ? this->msaaAttachment() : this->colorAttachment();
388
389 // Stencil attachment view is stored in the base RT stencil attachment
390 bool useMSAA = this->numSamples() > 1 || withResolve;
391 GrVkImage* stencil = withStencil ? static_cast<GrVkImage*>(this->getStencilAttachment(useMSAA))
392 : nullptr;
393 fCachedFramebuffers[cacheIndex] =
394 GrVkFramebuffer::Make(gpu, this->dimensions(),
395 sk_sp<const GrVkRenderPass>(renderPass),
396 colorAttachment, resolve, stencil, compatibleHandle);
397 }
398
getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * attachmentFlags,bool withResolve,bool withStencil)399 bool GrVkRenderTarget::getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
400 GrVkRenderPass::AttachmentFlags* attachmentFlags,
401 bool withResolve,
402 bool withStencil) {
403 SkASSERT(!this->wrapsSecondaryCommandBuffer());
404 const GrVkImage* colorAttachment =
405 withResolve ? this->msaaAttachment() : this->colorAttachment();
406 if (!colorAttachment) {
407 SkDebugf("WARNING: Invalid color attachment -- possibly dmsaa attachment creation failed?");
408 return false;
409 }
410
411 desc->fColor.fFormat = colorAttachment->imageFormat();
412 desc->fColor.fSamples = colorAttachment->numSamples();
413 *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
414 uint32_t attachmentCount = 1;
415
416 if (withResolve) {
417 desc->fResolve.fFormat = desc->fColor.fFormat;
418 desc->fResolve.fSamples = 1;
419 *attachmentFlags |= GrVkRenderPass::kResolve_AttachmentFlag;
420 ++attachmentCount;
421 }
422
423 if (withStencil) {
424 bool useMSAA = this->numSamples() > 1 || withResolve;
425 const GrAttachment* stencil = this->getStencilAttachment(useMSAA);
426 SkASSERT(stencil);
427 const GrVkImage* vkStencil = static_cast<const GrVkImage*>(stencil);
428 desc->fStencil.fFormat = vkStencil->imageFormat();
429 desc->fStencil.fSamples = vkStencil->numSamples();
430 SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
431 *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
432 ++attachmentCount;
433 }
434 desc->fAttachmentCount = attachmentCount;
435
436 return true;
437 }
438
ReconstructAttachmentsDescriptor(const GrVkCaps & vkCaps,const GrProgramInfo & programInfo,GrVkRenderPass::AttachmentsDescriptor * desc,GrVkRenderPass::AttachmentFlags * flags)439 void GrVkRenderTarget::ReconstructAttachmentsDescriptor(const GrVkCaps& vkCaps,
440 const GrProgramInfo& programInfo,
441 GrVkRenderPass::AttachmentsDescriptor* desc,
442 GrVkRenderPass::AttachmentFlags* flags) {
443 VkFormat format;
444 SkAssertResult(GrBackendFormats::AsVkFormat(programInfo.backendFormat(), &format));
445
446 desc->fColor.fFormat = format;
447 desc->fColor.fSamples = programInfo.numSamples();
448 *flags = GrVkRenderPass::kColor_AttachmentFlag;
449 uint32_t attachmentCount = 1;
450
451 if (vkCaps.programInfoWillUseDiscardableMSAA(programInfo)) {
452 desc->fResolve.fFormat = desc->fColor.fFormat;
453 desc->fResolve.fSamples = 1;
454 *flags |= GrVkRenderPass::kResolve_AttachmentFlag;
455 ++attachmentCount;
456 }
457
458 SkASSERT(!programInfo.isStencilEnabled() || programInfo.needsStencil());
459 if (programInfo.needsStencil()) {
460 VkFormat stencilFormat = vkCaps.preferredStencilFormat();
461 desc->fStencil.fFormat = stencilFormat;
462 desc->fStencil.fSamples = programInfo.numSamples();
463 SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
464 *flags |= GrVkRenderPass::kStencil_AttachmentFlag;
465 ++attachmentCount;
466 }
467 desc->fAttachmentCount = attachmentCount;
468 }
469
~GrVkRenderTarget()470 GrVkRenderTarget::~GrVkRenderTarget() {
471 // either release or abandon should have been called by the owner of this object.
472 SkASSERT(!fColorAttachment);
473 SkASSERT(!fResolveAttachment);
474 SkASSERT(!fDynamicMSAAAttachment);
475
476 for (int i = 0; i < kNumCachedFramebuffers; ++i) {
477 SkASSERT(!fCachedFramebuffers[i]);
478 }
479
480 SkASSERT(!fCachedInputDescriptorSet);
481 }
482
releaseInternalObjects()483 void GrVkRenderTarget::releaseInternalObjects() {
484 fColorAttachment.reset();
485 fResolveAttachment.reset();
486 fDynamicMSAAAttachment.reset();
487
488 for (int i = 0; i < kNumCachedFramebuffers; ++i) {
489 if (fCachedFramebuffers[i]) {
490 fCachedFramebuffers[i].reset();
491 }
492 }
493
494 if (fCachedInputDescriptorSet) {
495 fCachedInputDescriptorSet->recycle();
496 fCachedInputDescriptorSet = nullptr;
497 }
498
499 fExternalFramebuffer.reset();
500 }
501
onRelease()502 void GrVkRenderTarget::onRelease() {
503 this->releaseInternalObjects();
504 GrRenderTarget::onRelease();
505 }
506
onAbandon()507 void GrVkRenderTarget::onAbandon() {
508 this->releaseInternalObjects();
509 GrRenderTarget::onAbandon();
510 }
511
getBackendRenderTarget() const512 GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
513 SkASSERT(!this->wrapsSecondaryCommandBuffer());
514 // This should only get called with a non-released GrVkRenderTargets.
515 SkASSERT(!this->wasDestroyed());
516 // If we have a resolve attachment that is what we return for the backend render target
517 const GrVkImage* beAttachment = this->externalAttachment();
518 return GrBackendRenderTargets::MakeVk(beAttachment->width(),
519 beAttachment->height(),
520 beAttachment->vkImageInfo(),
521 beAttachment->getMutableState());
522 }
523
getVkGpu() const524 GrVkGpu* GrVkRenderTarget::getVkGpu() const {
525 SkASSERT(!this->wasDestroyed());
526 return static_cast<GrVkGpu*>(this->getGpu());
527 }
528