1 /*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "anv_private.h"
25
26 #include "vk_format.h"
27 #include "vk_util.h"
28
29 static void
anv_render_pass_add_subpass_dep(struct anv_device * device,struct anv_render_pass * pass,const VkSubpassDependency2KHR * dep)30 anv_render_pass_add_subpass_dep(struct anv_device *device,
31 struct anv_render_pass *pass,
32 const VkSubpassDependency2KHR *dep)
33 {
34 /* From the Vulkan 1.2.195 spec:
35 *
36 * "If an instance of VkMemoryBarrier2 is included in the pNext chain,
37 * srcStageMask, dstStageMask, srcAccessMask, and dstAccessMask
38 * parameters are ignored. The synchronization and access scopes instead
39 * are defined by the parameters of VkMemoryBarrier2."
40 */
41 const VkMemoryBarrier2KHR *barrier =
42 vk_find_struct_const(dep->pNext, MEMORY_BARRIER_2_KHR);
43 VkAccessFlags2KHR src_access_mask =
44 barrier ? barrier->srcAccessMask : dep->srcAccessMask;
45 VkAccessFlags2KHR dst_access_mask =
46 barrier ? barrier->dstAccessMask : dep->dstAccessMask;
47
48 if (dep->dstSubpass == VK_SUBPASS_EXTERNAL) {
49 pass->subpass_flushes[pass->subpass_count] |=
50 anv_pipe_invalidate_bits_for_access_flags(device, dst_access_mask);
51 } else {
52 assert(dep->dstSubpass < pass->subpass_count);
53 pass->subpass_flushes[dep->dstSubpass] |=
54 anv_pipe_invalidate_bits_for_access_flags(device, dst_access_mask);
55 }
56
57 if (dep->srcSubpass == VK_SUBPASS_EXTERNAL) {
58 pass->subpass_flushes[0] |=
59 anv_pipe_flush_bits_for_access_flags(device, src_access_mask);
60 } else {
61 assert(dep->srcSubpass < pass->subpass_count);
62 pass->subpass_flushes[dep->srcSubpass + 1] |=
63 anv_pipe_flush_bits_for_access_flags(device, src_access_mask);
64 }
65 }
66
67 /* Do a second "compile" step on a render pass */
68 static void
anv_render_pass_compile(struct anv_render_pass * pass)69 anv_render_pass_compile(struct anv_render_pass *pass)
70 {
71 /* The CreateRenderPass code zeros the entire render pass and also uses a
72 * designated initializer for filling these out. There's no need for us to
73 * do it again.
74 *
75 * for (uint32_t i = 0; i < pass->attachment_count; i++) {
76 * pass->attachments[i].usage = 0;
77 * pass->attachments[i].first_subpass_layout = VK_IMAGE_LAYOUT_UNDEFINED;
78 * }
79 */
80
81 VkImageUsageFlags all_usage = 0;
82 for (uint32_t i = 0; i < pass->subpass_count; i++) {
83 struct anv_subpass *subpass = &pass->subpasses[i];
84
85 /* We don't allow depth_stencil_attachment to be non-NULL and be
86 * VK_ATTACHMENT_UNUSED. This way something can just check for NULL
87 * and be guaranteed that they have a valid attachment.
88 */
89 if (subpass->depth_stencil_attachment &&
90 subpass->depth_stencil_attachment->attachment == VK_ATTACHMENT_UNUSED)
91 subpass->depth_stencil_attachment = NULL;
92
93 if (subpass->ds_resolve_attachment &&
94 subpass->ds_resolve_attachment->attachment == VK_ATTACHMENT_UNUSED)
95 subpass->ds_resolve_attachment = NULL;
96
97 for (uint32_t j = 0; j < subpass->attachment_count; j++) {
98 struct anv_subpass_attachment *subpass_att = &subpass->attachments[j];
99 if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
100 continue;
101
102 struct anv_render_pass_attachment *pass_att =
103 &pass->attachments[subpass_att->attachment];
104
105 pass_att->usage |= subpass_att->usage;
106 pass_att->last_subpass_idx = i;
107
108 all_usage |= subpass_att->usage;
109
110 /* first_subpass_layout only applies to color and depth.
111 * See genX(cmd_buffer_setup_attachments)
112 */
113 if (vk_format_aspects(pass_att->format) != VK_IMAGE_ASPECT_STENCIL_BIT &&
114 pass_att->first_subpass_layout == VK_IMAGE_LAYOUT_UNDEFINED) {
115 pass_att->first_subpass_layout = subpass_att->layout;
116 assert(pass_att->first_subpass_layout != VK_IMAGE_LAYOUT_UNDEFINED);
117 }
118
119 if (subpass_att->usage == VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
120 subpass->depth_stencil_attachment &&
121 subpass_att->attachment == subpass->depth_stencil_attachment->attachment)
122 subpass->has_ds_self_dep = true;
123 }
124
125 /* We have to handle resolve attachments specially */
126 subpass->has_color_resolve = false;
127 if (subpass->resolve_attachments) {
128 for (uint32_t j = 0; j < subpass->color_count; j++) {
129 struct anv_subpass_attachment *color_att =
130 &subpass->color_attachments[j];
131 struct anv_subpass_attachment *resolve_att =
132 &subpass->resolve_attachments[j];
133 if (resolve_att->attachment == VK_ATTACHMENT_UNUSED)
134 continue;
135
136 subpass->has_color_resolve = true;
137
138 assert(color_att->attachment < pass->attachment_count);
139 struct anv_render_pass_attachment *color_pass_att =
140 &pass->attachments[color_att->attachment];
141
142 assert(resolve_att->usage == VK_IMAGE_USAGE_TRANSFER_DST_BIT);
143 assert(color_att->usage == VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
144 color_pass_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
145 }
146 }
147
148 if (subpass->ds_resolve_attachment) {
149 struct anv_subpass_attachment *ds_att =
150 subpass->depth_stencil_attachment;
151 UNUSED struct anv_subpass_attachment *resolve_att =
152 subpass->ds_resolve_attachment;
153
154 assert(ds_att->attachment < pass->attachment_count);
155 struct anv_render_pass_attachment *ds_pass_att =
156 &pass->attachments[ds_att->attachment];
157
158 assert(resolve_att->usage == VK_IMAGE_USAGE_TRANSFER_DST_BIT);
159 assert(ds_att->usage == VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
160 ds_pass_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
161 }
162
163 for (uint32_t j = 0; j < subpass->attachment_count; j++)
164 assert(__builtin_popcount(subpass->attachments[j].usage) == 1);
165 }
166
167 /* From the Vulkan 1.0.39 spec:
168 *
169 * If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the
170 * first subpass that uses an attachment, then an implicit subpass
171 * dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is
172 * used in. The subpass dependency operates as if defined with the
173 * following parameters:
174 *
175 * VkSubpassDependency implicitDependency = {
176 * .srcSubpass = VK_SUBPASS_EXTERNAL;
177 * .dstSubpass = firstSubpass; // First subpass attachment is used in
178 * .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
179 * .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
180 * .srcAccessMask = 0;
181 * .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
182 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
183 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
184 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
185 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
186 * .dependencyFlags = 0;
187 * };
188 *
189 * Similarly, if there is no subpass dependency from the last subpass
190 * that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit
191 * subpass dependency exists from the last subpass it is used in to
192 * VK_SUBPASS_EXTERNAL. The subpass dependency operates as if defined
193 * with the following parameters:
194 *
195 * VkSubpassDependency implicitDependency = {
196 * .srcSubpass = lastSubpass; // Last subpass attachment is used in
197 * .dstSubpass = VK_SUBPASS_EXTERNAL;
198 * .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
199 * .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
200 * .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
201 * VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
202 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
203 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
204 * VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
205 * .dstAccessMask = 0;
206 * .dependencyFlags = 0;
207 * };
208 *
209 * We could implement this by walking over all of the attachments and
210 * subpasses and checking to see if any of them don't have an external
211 * dependency. Or, we could just be lazy and add a couple extra flushes.
212 * We choose to be lazy.
213 *
214 * From the documentation for vkCmdNextSubpass:
215 *
216 * "Moving to the next subpass automatically performs any multisample
217 * resolve operations in the subpass being ended. End-of-subpass
218 * multisample resolves are treated as color attachment writes for the
219 * purposes of synchronization. This applies to resolve operations for
220 * both color and depth/stencil attachments. That is, they are
221 * considered to execute in the
222 * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT pipeline stage and
223 * their writes are synchronized with
224 * VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT."
225 *
226 * Therefore, the above flags concerning color attachments also apply to
227 * color and depth/stencil resolve attachments.
228 */
229 if (all_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
230 pass->subpass_flushes[0] |=
231 ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT;
232 }
233 if (all_usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
234 VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
235 pass->subpass_flushes[pass->subpass_count] |=
236 ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT;
237 }
238 if (all_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
239 pass->subpass_flushes[pass->subpass_count] |=
240 ANV_PIPE_DEPTH_CACHE_FLUSH_BIT;
241 }
242 }
243
244 static unsigned
num_subpass_attachments2(const VkSubpassDescription2KHR * desc)245 num_subpass_attachments2(const VkSubpassDescription2KHR *desc)
246 {
247 const VkSubpassDescriptionDepthStencilResolveKHR *ds_resolve =
248 vk_find_struct_const(desc->pNext,
249 SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR);
250
251 return desc->inputAttachmentCount +
252 desc->colorAttachmentCount +
253 (desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
254 (desc->pDepthStencilAttachment != NULL) +
255 (ds_resolve && ds_resolve->pDepthStencilResolveAttachment);
256 }
257
258 static bool
vk_image_layout_depth_only(VkImageLayout layout)259 vk_image_layout_depth_only(VkImageLayout layout)
260 {
261 switch (layout) {
262 case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
263 case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
264 return true;
265
266 default:
267 return false;
268 }
269 }
270
271 /* From the Vulkan Specification 1.2.166 - VkAttachmentReference2:
272 *
273 * "If layout only specifies the layout of the depth aspect of the
274 * attachment, the layout of the stencil aspect is specified by the
275 * stencilLayout member of a VkAttachmentReferenceStencilLayout structure
276 * included in the pNext chain. Otherwise, layout describes the layout for
277 * all relevant image aspects."
278 */
279 static VkImageLayout
stencil_ref_layout(const VkAttachmentReference2KHR * att_ref)280 stencil_ref_layout(const VkAttachmentReference2KHR *att_ref)
281 {
282 if (!vk_image_layout_depth_only(att_ref->layout))
283 return att_ref->layout;
284
285 const VkAttachmentReferenceStencilLayoutKHR *stencil_ref =
286 vk_find_struct_const(att_ref->pNext,
287 ATTACHMENT_REFERENCE_STENCIL_LAYOUT_KHR);
288 if (!stencil_ref)
289 return VK_IMAGE_LAYOUT_UNDEFINED;
290 return stencil_ref->stencilLayout;
291 }
292
293 /* From the Vulkan Specification 1.2.166 - VkAttachmentDescription2:
294 *
295 * "If format is a depth/stencil format, and initialLayout only specifies
296 * the initial layout of the depth aspect of the attachment, the initial
297 * layout of the stencil aspect is specified by the stencilInitialLayout
298 * member of a VkAttachmentDescriptionStencilLayout structure included in
299 * the pNext chain. Otherwise, initialLayout describes the initial layout
300 * for all relevant image aspects."
301 */
302 static VkImageLayout
stencil_desc_layout(const VkAttachmentDescription2KHR * att_desc,bool final)303 stencil_desc_layout(const VkAttachmentDescription2KHR *att_desc, bool final)
304 {
305 if (!vk_format_has_stencil(att_desc->format))
306 return VK_IMAGE_LAYOUT_UNDEFINED;
307
308 const VkImageLayout main_layout =
309 final ? att_desc->finalLayout : att_desc->initialLayout;
310 if (!vk_image_layout_depth_only(main_layout))
311 return main_layout;
312
313 const VkAttachmentDescriptionStencilLayoutKHR *stencil_desc =
314 vk_find_struct_const(att_desc->pNext,
315 ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT_KHR);
316 assert(stencil_desc);
317 return final ?
318 stencil_desc->stencilFinalLayout :
319 stencil_desc->stencilInitialLayout;
320 }
321
anv_CreateRenderPass2(VkDevice _device,const VkRenderPassCreateInfo2KHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass)322 VkResult anv_CreateRenderPass2(
323 VkDevice _device,
324 const VkRenderPassCreateInfo2KHR* pCreateInfo,
325 const VkAllocationCallbacks* pAllocator,
326 VkRenderPass* pRenderPass)
327 {
328 ANV_FROM_HANDLE(anv_device, device, _device);
329
330 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR);
331
332 VK_MULTIALLOC(ma);
333 VK_MULTIALLOC_DECL(&ma, struct anv_render_pass, pass, 1);
334 VK_MULTIALLOC_DECL(&ma, struct anv_subpass, subpasses,
335 pCreateInfo->subpassCount);
336 VK_MULTIALLOC_DECL(&ma, struct anv_render_pass_attachment, attachments,
337 pCreateInfo->attachmentCount);
338 VK_MULTIALLOC_DECL(&ma, enum anv_pipe_bits, subpass_flushes,
339 pCreateInfo->subpassCount + 1);
340
341 uint32_t subpass_attachment_count = 0;
342 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
343 subpass_attachment_count +=
344 num_subpass_attachments2(&pCreateInfo->pSubpasses[i]);
345 }
346 VK_MULTIALLOC_DECL(&ma, struct anv_subpass_attachment, subpass_attachments,
347 subpass_attachment_count);
348
349 if (!vk_object_multizalloc(&device->vk, &ma, pAllocator,
350 VK_OBJECT_TYPE_RENDER_PASS))
351 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
352
353 /* Clear the subpasses along with the parent pass. This required because
354 * each array member of anv_subpass must be a valid pointer if not NULL.
355 */
356 pass->attachment_count = pCreateInfo->attachmentCount;
357 pass->subpass_count = pCreateInfo->subpassCount;
358 pass->attachments = attachments;
359 pass->subpass_flushes = subpass_flushes;
360
361 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
362 pass->attachments[i] = (struct anv_render_pass_attachment) {
363 .format = pCreateInfo->pAttachments[i].format,
364 .samples = pCreateInfo->pAttachments[i].samples,
365 .load_op = pCreateInfo->pAttachments[i].loadOp,
366 .store_op = pCreateInfo->pAttachments[i].storeOp,
367 .stencil_load_op = pCreateInfo->pAttachments[i].stencilLoadOp,
368 .initial_layout = pCreateInfo->pAttachments[i].initialLayout,
369 .final_layout = pCreateInfo->pAttachments[i].finalLayout,
370
371 .stencil_initial_layout = stencil_desc_layout(&pCreateInfo->pAttachments[i],
372 false),
373 .stencil_final_layout = stencil_desc_layout(&pCreateInfo->pAttachments[i],
374 true),
375 };
376 }
377
378 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
379 const VkSubpassDescription2KHR *desc = &pCreateInfo->pSubpasses[i];
380 struct anv_subpass *subpass = &pass->subpasses[i];
381
382 subpass->input_count = desc->inputAttachmentCount;
383 subpass->color_count = desc->colorAttachmentCount;
384 subpass->attachment_count = num_subpass_attachments2(desc);
385 subpass->attachments = subpass_attachments;
386 subpass->view_mask = desc->viewMask;
387
388 if (desc->inputAttachmentCount > 0) {
389 subpass->input_attachments = subpass_attachments;
390 subpass_attachments += desc->inputAttachmentCount;
391
392 for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
393 subpass->input_attachments[j] = (struct anv_subpass_attachment) {
394 .usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
395 .attachment = desc->pInputAttachments[j].attachment,
396 .layout = desc->pInputAttachments[j].layout,
397 .stencil_layout = stencil_ref_layout(&desc->pInputAttachments[j]),
398 };
399 }
400 }
401
402 if (desc->colorAttachmentCount > 0) {
403 subpass->color_attachments = subpass_attachments;
404 subpass_attachments += desc->colorAttachmentCount;
405
406 for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
407 subpass->color_attachments[j] = (struct anv_subpass_attachment) {
408 .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
409 .attachment = desc->pColorAttachments[j].attachment,
410 .layout = desc->pColorAttachments[j].layout,
411 };
412 }
413 }
414
415 if (desc->pResolveAttachments) {
416 subpass->resolve_attachments = subpass_attachments;
417 subpass_attachments += desc->colorAttachmentCount;
418
419 for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
420 subpass->resolve_attachments[j] = (struct anv_subpass_attachment) {
421 .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
422 .attachment = desc->pResolveAttachments[j].attachment,
423 .layout = desc->pResolveAttachments[j].layout,
424 };
425 }
426 }
427
428 if (desc->pDepthStencilAttachment) {
429 subpass->depth_stencil_attachment = subpass_attachments++;
430
431 *subpass->depth_stencil_attachment = (struct anv_subpass_attachment) {
432 .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
433 .attachment = desc->pDepthStencilAttachment->attachment,
434 .layout = desc->pDepthStencilAttachment->layout,
435 .stencil_layout = stencil_ref_layout(desc->pDepthStencilAttachment),
436 };
437 }
438
439 const VkSubpassDescriptionDepthStencilResolveKHR *ds_resolve =
440 vk_find_struct_const(desc->pNext,
441 SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR);
442
443 if (ds_resolve && ds_resolve->pDepthStencilResolveAttachment) {
444 subpass->ds_resolve_attachment = subpass_attachments++;
445
446 *subpass->ds_resolve_attachment = (struct anv_subpass_attachment) {
447 .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
448 .attachment = ds_resolve->pDepthStencilResolveAttachment->attachment,
449 .layout = ds_resolve->pDepthStencilResolveAttachment->layout,
450 .stencil_layout = stencil_ref_layout(ds_resolve->pDepthStencilResolveAttachment),
451 };
452 subpass->depth_resolve_mode = ds_resolve->depthResolveMode;
453 subpass->stencil_resolve_mode = ds_resolve->stencilResolveMode;
454 }
455 }
456
457 for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
458 anv_render_pass_add_subpass_dep(device, pass,
459 &pCreateInfo->pDependencies[i]);
460 }
461
462 vk_foreach_struct(ext, pCreateInfo->pNext) {
463 switch (ext->sType) {
464 default:
465 anv_debug_ignored_stype(ext->sType);
466 }
467 }
468
469 anv_render_pass_compile(pass);
470
471 *pRenderPass = anv_render_pass_to_handle(pass);
472
473 return VK_SUCCESS;
474 }
475
anv_DestroyRenderPass(VkDevice _device,VkRenderPass _pass,const VkAllocationCallbacks * pAllocator)476 void anv_DestroyRenderPass(
477 VkDevice _device,
478 VkRenderPass _pass,
479 const VkAllocationCallbacks* pAllocator)
480 {
481 ANV_FROM_HANDLE(anv_device, device, _device);
482 ANV_FROM_HANDLE(anv_render_pass, pass, _pass);
483
484 if (!pass)
485 return;
486
487 vk_object_free(&device->vk, pAllocator, pass);
488 }
489
anv_GetRenderAreaGranularity(VkDevice device,VkRenderPass renderPass,VkExtent2D * pGranularity)490 void anv_GetRenderAreaGranularity(
491 VkDevice device,
492 VkRenderPass renderPass,
493 VkExtent2D* pGranularity)
494 {
495 ANV_FROM_HANDLE(anv_render_pass, pass, renderPass);
496
497 /* This granularity satisfies HiZ fast clear alignment requirements
498 * for all sample counts.
499 */
500 for (unsigned i = 0; i < pass->subpass_count; ++i) {
501 if (pass->subpasses[i].depth_stencil_attachment) {
502 *pGranularity = (VkExtent2D) { .width = 8, .height = 4 };
503 return;
504 }
505 }
506
507 *pGranularity = (VkExtent2D) { 1, 1 };
508 }
509