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