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