xref: /aosp_15_r20/external/skia/src/gpu/ganesh/vk/GrVkRenderPass.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/GrVkRenderPass.h"
9 
10 #include "include/core/SkTypes.h"
11 #include "include/private/base/SkTArray.h"
12 #include "include/private/base/SkTo.h"
13 #include "src/gpu/KeyBuilder.h"
14 #include "src/gpu/ganesh/GrCaps.h"
15 #include "src/gpu/ganesh/vk/GrVkCaps.h"
16 #include "src/gpu/ganesh/vk/GrVkGpu.h"
17 #include "src/gpu/ganesh/vk/GrVkRenderTarget.h"
18 #include "src/gpu/ganesh/vk/GrVkUtil.h"
19 #include "src/gpu/vk/VulkanUtilsPriv.h"
20 
21 #include <string.h>
22 #include <algorithm>
23 
24 using namespace skia_private;
25 
26 typedef GrVkRenderPass::AttachmentsDescriptor::AttachmentDesc AttachmentDesc;
27 
setup_vk_attachment_description(VkAttachmentDescription * attachment,const AttachmentDesc & desc,VkImageLayout startLayout,VkImageLayout endLayout)28 void setup_vk_attachment_description(VkAttachmentDescription* attachment,
29                                      const AttachmentDesc& desc,
30                                      VkImageLayout startLayout,
31                                      VkImageLayout endLayout) {
32     attachment->flags = 0;
33     attachment->format = desc.fFormat;
34     SkAssertResult(skgpu::SampleCountToVkSampleCount(desc.fSamples, &attachment->samples));
35     switch (startLayout) {
36         case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
37         case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
38         case VK_IMAGE_LAYOUT_GENERAL:
39             attachment->loadOp = desc.fLoadStoreOps.fLoadOp;
40             attachment->storeOp = desc.fLoadStoreOps.fStoreOp;
41             attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
42             attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
43             break;
44         case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
45             attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
46             attachment->storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
47             attachment->stencilLoadOp = desc.fLoadStoreOps.fLoadOp;
48             attachment->stencilStoreOp = desc.fLoadStoreOps.fStoreOp;
49             break;
50         default:
51             SK_ABORT("Unexpected attachment layout");
52     }
53 
54     attachment->initialLayout = startLayout;
55     attachment->finalLayout = endLayout == VK_IMAGE_LAYOUT_UNDEFINED ? startLayout : endLayout;
56 }
57 
CreateSimple(GrVkGpu * gpu,AttachmentsDescriptor * attachmentsDescriptor,AttachmentFlags attachmentFlags,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)58 GrVkRenderPass* GrVkRenderPass::CreateSimple(GrVkGpu* gpu,
59                                              AttachmentsDescriptor* attachmentsDescriptor,
60                                              AttachmentFlags attachmentFlags,
61                                              SelfDependencyFlags selfDepFlags,
62                                              LoadFromResolve loadFromResolve) {
63     static const GrVkRenderPass::LoadStoreOps kBasicLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD,
64                                                                  VK_ATTACHMENT_STORE_OP_STORE);
65     switch (loadFromResolve) {
66         case LoadFromResolve::kNo:
67             return Create(gpu, attachmentFlags, attachmentsDescriptor, kBasicLoadStoreOps,
68                           kBasicLoadStoreOps, kBasicLoadStoreOps, selfDepFlags, loadFromResolve);
69         case LoadFromResolve::kLoad: {
70             static const GrVkRenderPass::LoadStoreOps kDiscardLoadStoreOps(
71                     VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE);
72             return Create(gpu, attachmentFlags, attachmentsDescriptor, kDiscardLoadStoreOps,
73                           kBasicLoadStoreOps, kBasicLoadStoreOps, selfDepFlags, loadFromResolve);
74         }
75     }
76     SkUNREACHABLE;
77 }
78 
Create(GrVkGpu * gpu,const GrVkRenderPass & compatibleRenderPass,const LoadStoreOps & colorOp,const LoadStoreOps & resolveOp,const LoadStoreOps & stencilOp)79 GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
80                                        const GrVkRenderPass& compatibleRenderPass,
81                                        const LoadStoreOps& colorOp,
82                                        const LoadStoreOps& resolveOp,
83                                        const LoadStoreOps& stencilOp) {
84     AttachmentFlags attachmentFlags = compatibleRenderPass.fAttachmentFlags;
85     AttachmentsDescriptor attachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor;
86     SelfDependencyFlags selfDepFlags = compatibleRenderPass.fSelfDepFlags;
87     LoadFromResolve loadFromResolve = compatibleRenderPass.fLoadFromResolve;
88     return Create(gpu, attachmentFlags, &attachmentsDescriptor, colorOp, resolveOp, stencilOp,
89                   selfDepFlags, loadFromResolve);
90 }
91 
Create(GrVkGpu * gpu,AttachmentFlags attachmentFlags,AttachmentsDescriptor * attachmentsDescriptor,const LoadStoreOps & colorOp,const LoadStoreOps & resolveOp,const LoadStoreOps & stencilOp,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve)92 GrVkRenderPass* GrVkRenderPass::Create(GrVkGpu* gpu,
93                                        AttachmentFlags attachmentFlags,
94                                        AttachmentsDescriptor* attachmentsDescriptor,
95                                        const LoadStoreOps& colorOp,
96                                        const LoadStoreOps& resolveOp,
97                                        const LoadStoreOps& stencilOp,
98                                        SelfDependencyFlags selfDepFlags,
99                                        LoadFromResolve loadFromResolve) {
100     SkASSERT(!SkToBool(selfDepFlags & SelfDependencyFlags::kForNonCoherentAdvBlend) ||
101              gpu->caps()->advancedBlendEquationSupport());
102     SkASSERT(!SkToBool(selfDepFlags & SelfDependencyFlags::kForInputAttachment) ||
103              gpu->caps()->textureBarrierSupport());
104 
105     // If we have a resolve attachment, we will always do a resolve into it. Thus it doesn't make
106     // sense not to store the resolve attachment at the end of the render pass.
107     //
108     // Currently today (when not using discardable msaa images) we load and store the the msaa image
109     // and then use the copy resolve command to handle the resolving. If instead we moved to doing
110     // the resolving at the end of the last render pass, we would probably want a separate flag
111     // for having a resolve attachment versus actually doing the resolving. This would allow us to
112     // use the same VkPiplines for render passes where we resolve and those we don't since each will
113     // always have the resolve attachment. The actual resolving or not does not affect render pass
114     // compatibility if there is only one sub pass, just the presence of the attachment or not.
115     SkASSERT(!SkToBool(attachmentFlags & kResolve_AttachmentFlag) ||
116              resolveOp.fStoreOp == VK_ATTACHMENT_STORE_OP_STORE);
117 
118     SkASSERT(loadFromResolve == LoadFromResolve::kNo ||
119              (SkToBool(attachmentFlags & kColor_AttachmentFlag) &&
120               SkToBool(attachmentFlags & kResolve_AttachmentFlag)));
121 
122 #ifdef SK_DEBUG
123     if (loadFromResolve == LoadFromResolve::kLoad) {
124         // If we are loading the resolve image into the msaa color attachment then we should not be
125         // loading or storing the msaa attachment. Additionally we need to make sure we are loading
126         // the resolve so it can be copied into the msaa color attachment.
127         SkASSERT(colorOp.fLoadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE);
128         SkASSERT(colorOp.fStoreOp == VK_ATTACHMENT_STORE_OP_DONT_CARE);
129         SkASSERT(resolveOp.fLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD);
130     }
131 #endif
132 
133     uint32_t numAttachments = attachmentsDescriptor->fAttachmentCount;
134     // Attachment descriptions to be set on the render pass
135     TArray<VkAttachmentDescription> attachments(numAttachments);
136     attachments.reset(numAttachments);
137     memset(attachments.begin(), 0, numAttachments * sizeof(VkAttachmentDescription));
138 
139     // Refs to attachments on the render pass (as described by the VkAttachmentDescription above),
140     // that are used by the subpass.
141     VkAttachmentReference colorRef;
142     VkAttachmentReference resolveRef;
143     VkAttachmentReference resolveLoadInputRef;
144     VkAttachmentReference stencilRef;
145     uint32_t currentAttachment = 0;
146 
147     // Go through each of the attachment types (color, stencil) and set the necessary
148     // on the various Vk structs.
149     VkSubpassDescription subpassDescs[2];
150     memset(subpassDescs, 0, 2*sizeof(VkSubpassDescription));
151     const int mainSubpass = loadFromResolve == LoadFromResolve::kLoad ? 1 : 0;
152     VkSubpassDescription& subpassDescMain = subpassDescs[mainSubpass];
153     subpassDescMain.flags = 0;
154     subpassDescMain.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
155     subpassDescMain.inputAttachmentCount = 0;
156     subpassDescMain.pInputAttachments = nullptr;
157     subpassDescMain.pResolveAttachments = nullptr;
158 
159     uint32_t clearValueCount = 0;
160 
161     VkSubpassDependency dependencies[2];
162     int currentDependency = 0;
163 
164     if (attachmentFlags & kColor_AttachmentFlag) {
165         // set up color attachment
166         bool needsGeneralLayout = SkToBool(selfDepFlags & SelfDependencyFlags::kForInputAttachment);
167         VkImageLayout layout = needsGeneralLayout ? VK_IMAGE_LAYOUT_GENERAL
168                                                   : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
169 
170         attachmentsDescriptor->fColor.fLoadStoreOps = colorOp;
171 
172         setup_vk_attachment_description(&attachments[currentAttachment],
173                                         attachmentsDescriptor->fColor,
174                                         layout, layout);
175         // setup subpass use of attachment
176         colorRef.attachment = currentAttachment++;
177         colorRef.layout = layout;
178         subpassDescMain.colorAttachmentCount = 1;
179 
180         if (selfDepFlags != SelfDependencyFlags::kNone) {
181             VkSubpassDependency& dependency = dependencies[currentDependency++];
182             dependency.srcSubpass = mainSubpass;
183             dependency.dstSubpass = mainSubpass;
184             dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
185             dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
186             dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
187             dependency.dstStageMask = 0;
188             dependency.dstAccessMask = 0;
189 
190             if (selfDepFlags & SelfDependencyFlags::kForNonCoherentAdvBlend) {
191                 // If we have coherent support we shouldn't be needing a self dependency
192                 SkASSERT(!gpu->caps()->advancedCoherentBlendEquationSupport());
193                 dependency.dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
194                 dependency.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
195             }
196             if (selfDepFlags & SelfDependencyFlags::kForInputAttachment) {
197                 SkASSERT(gpu->vkCaps().maxInputAttachmentDescriptors());
198 
199                 subpassDescMain.inputAttachmentCount = 1;
200                 subpassDescMain.pInputAttachments = &colorRef;
201 
202                 dependency.dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
203                 dependency.dstAccessMask |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
204             }
205         }
206 
207         if (VK_ATTACHMENT_LOAD_OP_CLEAR == colorOp.fLoadOp) {
208             clearValueCount = colorRef.attachment + 1;
209         }
210     } else {
211         // I don't think there should ever be a time where we don't have a color attachment
212         SkASSERT(false);
213         SkASSERT(selfDepFlags == SelfDependencyFlags::kNone);
214         colorRef.attachment = VK_ATTACHMENT_UNUSED;
215         colorRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
216         subpassDescMain.colorAttachmentCount = 0;
217     }
218 
219     subpassDescMain.pColorAttachments = &colorRef;
220 
221     if (attachmentFlags & kResolve_AttachmentFlag) {
222         attachmentsDescriptor->fResolve.fLoadStoreOps = resolveOp;
223 
224         VkImageLayout layout = loadFromResolve == LoadFromResolve::kLoad
225                                        ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
226                                        : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
227 
228         setup_vk_attachment_description(&attachments[currentAttachment],
229                                         attachmentsDescriptor->fResolve,
230                                         layout,
231                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
232 
233         // setup main subpass use of attachment
234         resolveRef.attachment = currentAttachment++;
235         resolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
236 
237         subpassDescMain.pResolveAttachments = &resolveRef;
238 
239         // Setup the load subpass and set subpass dependendcies
240         if (loadFromResolve == LoadFromResolve::kLoad) {
241             resolveLoadInputRef.attachment = resolveRef.attachment;
242             resolveLoadInputRef.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
243 
244             // The load subpass will always be the first
245             VkSubpassDescription& subpassDescLoad = subpassDescs[0];
246             subpassDescLoad.flags = 0;
247             subpassDescLoad.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
248             subpassDescLoad.inputAttachmentCount = 1;
249             subpassDescLoad.pInputAttachments = &resolveLoadInputRef;
250             subpassDescLoad.colorAttachmentCount = 1;
251             subpassDescLoad.pColorAttachments = &colorRef;
252             subpassDescLoad.pResolveAttachments = nullptr;
253             subpassDescLoad.pDepthStencilAttachment = nullptr;
254             subpassDescLoad.preserveAttachmentCount = 0;
255             subpassDescLoad.pPreserveAttachments = nullptr;
256 
257             VkSubpassDependency& dependency = dependencies[currentDependency++];
258             dependency.srcSubpass = 0;
259             dependency.dstSubpass = mainSubpass;
260             dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
261             dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
262             dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
263             dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
264             dependency.dstAccessMask =
265                     VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
266         }
267     }
268 
269 
270     if (attachmentFlags & kStencil_AttachmentFlag) {
271         // set up stencil attachment
272         attachmentsDescriptor->fStencil.fLoadStoreOps = stencilOp;
273         setup_vk_attachment_description(&attachments[currentAttachment],
274                                         attachmentsDescriptor->fStencil,
275                                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
276                                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
277         // setup subpass use of attachment
278         stencilRef.attachment = currentAttachment++;
279         stencilRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
280         if (VK_ATTACHMENT_LOAD_OP_CLEAR == stencilOp.fLoadOp) {
281             clearValueCount = std::max(clearValueCount, stencilRef.attachment + 1);
282         }
283     } else {
284         stencilRef.attachment = VK_ATTACHMENT_UNUSED;
285         stencilRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
286     }
287     subpassDescMain.pDepthStencilAttachment = &stencilRef;
288 
289     subpassDescMain.preserveAttachmentCount = 0;
290     subpassDescMain.pPreserveAttachments = nullptr;
291 
292     SkASSERT(numAttachments == currentAttachment);
293 
294     uint32_t subpassCount = loadFromResolve == LoadFromResolve::kLoad ? 2 : 1;
295 
296     // Create the VkRenderPass compatible with the attachment descriptions above
297     VkRenderPassCreateInfo createInfo;
298     memset(&createInfo, 0, sizeof(VkRenderPassCreateInfo));
299     createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
300     createInfo.pNext = nullptr;
301     createInfo.flags = 0;
302     createInfo.attachmentCount = numAttachments;
303     createInfo.pAttachments = attachments.begin();
304     createInfo.subpassCount = subpassCount;
305     createInfo.pSubpasses = subpassDescs;
306     createInfo.dependencyCount = currentDependency;
307     createInfo.pDependencies = dependencies;
308 
309     VkResult result;
310     VkRenderPass renderPass;
311     GR_VK_CALL_RESULT(gpu, result, CreateRenderPass(gpu->device(),
312                                                     &createInfo,
313                                                     nullptr,
314                                                     &renderPass));
315     if (result != VK_SUCCESS) {
316         return nullptr;
317     }
318 
319     VkExtent2D granularity;
320     // Get granularity for this render pass
321     GR_VK_CALL(gpu->vkInterface(), GetRenderAreaGranularity(gpu->device(),
322                                                             renderPass,
323                                                             &granularity));
324 
325     return new GrVkRenderPass(gpu, renderPass, attachmentFlags, *attachmentsDescriptor,
326                               selfDepFlags, loadFromResolve, granularity, clearValueCount);
327 }
328 
GrVkRenderPass(const GrVkGpu * gpu,VkRenderPass renderPass,AttachmentFlags flags,const AttachmentsDescriptor & descriptor,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve,const VkExtent2D & granularity,uint32_t clearValueCount)329 GrVkRenderPass::GrVkRenderPass(const GrVkGpu* gpu, VkRenderPass renderPass, AttachmentFlags flags,
330                                const AttachmentsDescriptor& descriptor,
331                                SelfDependencyFlags selfDepFlags,
332                                LoadFromResolve loadFromResolve,
333                                const VkExtent2D& granularity, uint32_t clearValueCount)
334         : INHERITED(gpu)
335         , fRenderPass(renderPass)
336         , fAttachmentFlags(flags)
337         , fAttachmentsDescriptor(descriptor)
338         , fSelfDepFlags(selfDepFlags)
339         , fLoadFromResolve(loadFromResolve)
340         , fGranularity(granularity)
341         , fClearValueCount(clearValueCount) {
342 }
343 
freeGPUData() const344 void GrVkRenderPass::freeGPUData() const {
345     if (!(fAttachmentFlags & kExternal_AttachmentFlag)) {
346         GR_VK_CALL(fGpu->vkInterface(), DestroyRenderPass(fGpu->device(), fRenderPass, nullptr));
347     }
348 }
349 
colorAttachmentIndex(uint32_t * index) const350 bool GrVkRenderPass::colorAttachmentIndex(uint32_t* index) const {
351     *index = fColorAttachmentIndex;
352     if ((fAttachmentFlags & kColor_AttachmentFlag) ||
353         (fAttachmentFlags & kExternal_AttachmentFlag)) {
354         return true;
355     }
356     return false;
357 }
358 
359 // Works under the assumption that stencil attachment will always be after the color and resolve
360 // attachments.
stencilAttachmentIndex(uint32_t * index) const361 bool GrVkRenderPass::stencilAttachmentIndex(uint32_t* index) const {
362     *index = 0;
363     if (fAttachmentFlags & kColor_AttachmentFlag) {
364         ++(*index);
365     }
366     if (fAttachmentFlags & kStencil_AttachmentFlag) {
367         return true;
368     }
369     return false;
370 }
371 
isCompatible(const AttachmentsDescriptor & desc,const AttachmentFlags & flags,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve) const372 bool GrVkRenderPass::isCompatible(const AttachmentsDescriptor& desc,
373                                   const AttachmentFlags& flags,
374                                   SelfDependencyFlags selfDepFlags,
375                                   LoadFromResolve loadFromResolve) const {
376     SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
377     if (flags != fAttachmentFlags) {
378         return false;
379     }
380 
381     if (fAttachmentFlags & kColor_AttachmentFlag) {
382         if (!fAttachmentsDescriptor.fColor.isCompatible(desc.fColor)) {
383             return false;
384         }
385     }
386     if (fAttachmentFlags & kResolve_AttachmentFlag) {
387         if (!fAttachmentsDescriptor.fResolve.isCompatible(desc.fResolve)) {
388             return false;
389         }
390     }
391     if (fAttachmentFlags & kStencil_AttachmentFlag) {
392         if (!fAttachmentsDescriptor.fStencil.isCompatible(desc.fStencil)) {
393             return false;
394         }
395     }
396 
397     if (fSelfDepFlags != selfDepFlags) {
398         return false;
399     }
400 
401     if (fLoadFromResolve != loadFromResolve) {
402         return false;
403     }
404 
405     return true;
406 }
407 
isCompatible(GrVkRenderTarget * target,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve) const408 bool GrVkRenderPass::isCompatible(GrVkRenderTarget* target,
409                                   SelfDependencyFlags selfDepFlags,
410                                   LoadFromResolve loadFromResolve) const {
411     SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
412 
413     AttachmentsDescriptor desc;
414     AttachmentFlags flags;
415     if (!target->getAttachmentsDescriptor(&desc, &flags, this->hasResolveAttachment(),
416                                           this->hasStencilAttachment())) {
417         return false;
418     }
419 
420     return this->isCompatible(desc, flags, selfDepFlags, loadFromResolve);
421 }
422 
isCompatible(const GrVkRenderPass & renderPass) const423 bool GrVkRenderPass::isCompatible(const GrVkRenderPass& renderPass) const {
424     SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
425     return this->isCompatible(renderPass.fAttachmentsDescriptor, renderPass.fAttachmentFlags,
426                               renderPass.fSelfDepFlags, renderPass.fLoadFromResolve);
427 }
428 
isCompatibleExternalRP(VkRenderPass renderPass) const429 bool GrVkRenderPass::isCompatibleExternalRP(VkRenderPass renderPass) const {
430     SkASSERT(fAttachmentFlags & kExternal_AttachmentFlag);
431     return fRenderPass == renderPass;
432 }
433 
equalLoadStoreOps(const LoadStoreOps & colorOps,const LoadStoreOps & resolveOps,const LoadStoreOps & stencilOps) const434 bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps,
435                                        const LoadStoreOps& resolveOps,
436                                        const LoadStoreOps& stencilOps) const {
437     SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
438     if (fAttachmentFlags & kColor_AttachmentFlag) {
439         if (fAttachmentsDescriptor.fColor.fLoadStoreOps != colorOps) {
440             return false;
441         }
442     }
443     if (fAttachmentFlags & kResolve_AttachmentFlag) {
444         if (fAttachmentsDescriptor.fResolve.fLoadStoreOps != resolveOps) {
445             return false;
446         }
447     }
448     if (fAttachmentFlags & kStencil_AttachmentFlag) {
449         if (fAttachmentsDescriptor.fStencil.fLoadStoreOps != stencilOps) {
450             return false;
451         }
452     }
453     return true;
454 }
455 
genKey(skgpu::KeyBuilder * b) const456 void GrVkRenderPass::genKey(skgpu::KeyBuilder* b) const {
457     GenKey(b, fAttachmentFlags, fAttachmentsDescriptor, fSelfDepFlags,
458            fLoadFromResolve, (uint64_t)fRenderPass);
459 }
460 
GenKey(skgpu::KeyBuilder * b,AttachmentFlags attachmentFlags,const AttachmentsDescriptor & attachmentsDescriptor,SelfDependencyFlags selfDepFlags,LoadFromResolve loadFromResolve,uint64_t externalRenderPass)461 void GrVkRenderPass::GenKey(skgpu::KeyBuilder* b,
462                             AttachmentFlags attachmentFlags,
463                             const AttachmentsDescriptor& attachmentsDescriptor,
464                             SelfDependencyFlags selfDepFlags,
465                             LoadFromResolve loadFromResolve,
466                             uint64_t externalRenderPass) {
467     b->add32(attachmentFlags);
468     if (attachmentFlags & kColor_AttachmentFlag) {
469         b->add32(attachmentsDescriptor.fColor.fFormat);
470         b->add32(attachmentsDescriptor.fColor.fSamples);
471     }
472     if (attachmentFlags & kResolve_AttachmentFlag) {
473         b->add32(attachmentsDescriptor.fResolve.fFormat);
474         b->add32(attachmentsDescriptor.fResolve.fSamples);
475     }
476     if (attachmentFlags & kStencil_AttachmentFlag) {
477         b->add32(attachmentsDescriptor.fStencil.fFormat);
478         b->add32(attachmentsDescriptor.fStencil.fSamples);
479     }
480 
481     uint32_t extraFlags = (uint32_t)selfDepFlags;
482     SkASSERT(extraFlags < (1 << 30));
483     SkASSERT((uint32_t)loadFromResolve <= 2);
484     extraFlags |= ((uint32_t)loadFromResolve << 30);
485 
486     b->add32(extraFlags);
487 
488     if (attachmentFlags & kExternal_AttachmentFlag) {
489         SkASSERT(!(attachmentFlags & ~kExternal_AttachmentFlag));
490         b->add32((uint32_t)(externalRenderPass & 0xFFFFFFFF));
491         b->add32((uint32_t)(externalRenderPass>>32));
492     }
493 }
494