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