xref: /aosp_15_r20/external/mesa3d/src/vulkan/runtime/vk_meta_clear.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Collabora Ltd
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 "vk_meta_private.h"
25 
26 #include "vk_command_buffer.h"
27 #include "vk_device.h"
28 #include "vk_format.h"
29 #include "vk_image.h"
30 #include "vk_pipeline.h"
31 #include "vk_util.h"
32 
33 #include "nir_builder.h"
34 
35 struct vk_meta_clear_key {
36    enum vk_meta_object_key_type key_type;
37    struct vk_meta_rendering_info render;
38    uint8_t color_attachments_cleared;
39    bool clear_depth;
40    bool clear_stencil;
41 };
42 
43 struct vk_meta_clear_push_data {
44    VkClearColorValue color_values[MESA_VK_MAX_COLOR_ATTACHMENTS];
45 };
46 
47 static nir_shader *
build_clear_shader(const struct vk_meta_clear_key * key)48 build_clear_shader(const struct vk_meta_clear_key *key)
49 {
50    nir_builder build = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
51                                                       NULL, "vk-meta-clear");
52    nir_builder *b = &build;
53 
54    struct glsl_struct_field push_field = {
55       .type = glsl_array_type(glsl_vec4_type(),
56                               MESA_VK_MAX_COLOR_ATTACHMENTS,
57                               16 /* explicit_stride */),
58       .name = "color_values",
59    };
60    const struct glsl_type *push_iface_type =
61       glsl_interface_type(&push_field, 1, GLSL_INTERFACE_PACKING_STD140,
62                           false /* row_major */, "push");
63 
64    nir_variable *push = nir_variable_create(b->shader, nir_var_mem_push_const,
65                                             push_iface_type, "push");
66    nir_deref_instr *push_arr =
67       nir_build_deref_struct(b, nir_build_deref_var(b, push), 0);
68 
69    u_foreach_bit(a, key->color_attachments_cleared) {
70       nir_def *color_value =
71          nir_load_deref(b, nir_build_deref_array_imm(b, push_arr, a));
72 
73       const struct glsl_type *out_type;
74       if (vk_format_is_sint(key->render.color_attachment_formats[a]))
75          out_type = glsl_ivec4_type();
76       else if (vk_format_is_uint(key->render.color_attachment_formats[a]))
77          out_type = glsl_uvec4_type();
78       else
79          out_type = glsl_vec4_type();
80 
81       char out_name[8];
82       snprintf(out_name, sizeof(out_name), "color%u", a);
83 
84       nir_variable *out = nir_variable_create(b->shader, nir_var_shader_out,
85                                               out_type, out_name);
86       out->data.location = FRAG_RESULT_DATA0 + a;
87 
88       nir_store_var(b, out, color_value, 0xf);
89    }
90 
91    return b->shader;
92 }
93 
94 static VkResult
get_clear_pipeline_layout(struct vk_device * device,struct vk_meta_device * meta,VkPipelineLayout * layout_out)95 get_clear_pipeline_layout(struct vk_device *device,
96                           struct vk_meta_device *meta,
97                           VkPipelineLayout *layout_out)
98 {
99    const char key[] = "vk-meta-clear-pipeline-layout";
100 
101    VkPipelineLayout from_cache =
102       vk_meta_lookup_pipeline_layout(meta, key, sizeof(key));
103    if (from_cache != VK_NULL_HANDLE) {
104       *layout_out = from_cache;
105       return VK_SUCCESS;
106    }
107 
108    const VkPushConstantRange push_range = {
109       .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
110       .offset = 0,
111       .size = sizeof(struct vk_meta_clear_push_data),
112    };
113 
114    const VkPipelineLayoutCreateInfo info = {
115       .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
116       .pushConstantRangeCount = 1,
117       .pPushConstantRanges = &push_range,
118    };
119 
120    return vk_meta_create_pipeline_layout(device, meta, &info,
121                                          key, sizeof(key), layout_out);
122 }
123 
124 static VkResult
get_clear_pipeline(struct vk_device * device,struct vk_meta_device * meta,const struct vk_meta_clear_key * key,VkPipelineLayout layout,VkPipeline * pipeline_out)125 get_clear_pipeline(struct vk_device *device,
126                    struct vk_meta_device *meta,
127                    const struct vk_meta_clear_key *key,
128                    VkPipelineLayout layout,
129                    VkPipeline *pipeline_out)
130 {
131    VkPipeline from_cache = vk_meta_lookup_pipeline(meta, key, sizeof(*key));
132    if (from_cache != VK_NULL_HANDLE) {
133       *pipeline_out = from_cache;
134       return VK_SUCCESS;
135    }
136 
137    const VkPipelineShaderStageNirCreateInfoMESA fs_nir_info = {
138       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_NIR_CREATE_INFO_MESA,
139       .nir = build_clear_shader(key),
140    };
141    const VkPipelineShaderStageCreateInfo fs_info = {
142       .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
143       .pNext = &fs_nir_info,
144       .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
145       .pName = "main",
146    };
147 
148    VkPipelineDepthStencilStateCreateInfo ds_info = {
149       .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
150    };
151    const VkDynamicState dyn_stencil_ref = VK_DYNAMIC_STATE_STENCIL_REFERENCE;
152    VkPipelineDynamicStateCreateInfo dyn_info = {
153       .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
154    };
155    if (key->clear_depth) {
156       ds_info.depthTestEnable = VK_TRUE;
157       ds_info.depthWriteEnable = VK_TRUE;
158       ds_info.depthCompareOp = VK_COMPARE_OP_ALWAYS;
159    }
160    if (key->clear_stencil) {
161       ds_info.stencilTestEnable = VK_TRUE;
162       ds_info.front.compareOp = VK_COMPARE_OP_ALWAYS;
163       ds_info.front.passOp = VK_STENCIL_OP_REPLACE;
164       ds_info.front.compareMask = ~0u;
165       ds_info.front.writeMask = ~0u;
166       ds_info.back = ds_info.front;
167       dyn_info.dynamicStateCount = 1;
168       dyn_info.pDynamicStates = &dyn_stencil_ref;
169    }
170 
171    const VkGraphicsPipelineCreateInfo info = {
172       .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
173       .stageCount = 1,
174       .pStages = &fs_info,
175       .pDepthStencilState = &ds_info,
176       .pDynamicState = &dyn_info,
177       .layout = layout,
178    };
179 
180    VkResult result = vk_meta_create_graphics_pipeline(device, meta, &info,
181                                                       &key->render,
182                                                       key, sizeof(*key),
183                                                       pipeline_out);
184    ralloc_free(fs_nir_info.nir);
185 
186    return result;
187 }
188 
189 static int
vk_meta_rect_cmp_layer(const void * _a,const void * _b)190 vk_meta_rect_cmp_layer(const void *_a, const void *_b)
191 {
192    const struct vk_meta_rect *a = _a, *b = _b;
193    assert(a->layer <= INT_MAX && b->layer <= INT_MAX);
194    return a->layer - b->layer;
195 }
196 
197 void
vk_meta_clear_attachments(struct vk_command_buffer * cmd,struct vk_meta_device * meta,const struct vk_meta_rendering_info * render,uint32_t attachment_count,const VkClearAttachment * attachments,uint32_t clear_rect_count,const VkClearRect * clear_rects)198 vk_meta_clear_attachments(struct vk_command_buffer *cmd,
199                           struct vk_meta_device *meta,
200                           const struct vk_meta_rendering_info *render,
201                           uint32_t attachment_count,
202                           const VkClearAttachment *attachments,
203                           uint32_t clear_rect_count,
204                           const VkClearRect *clear_rects)
205 {
206    struct vk_device *device = cmd->base.device;
207    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
208    VkResult result;
209 
210    struct vk_meta_clear_key key;
211    memset(&key, 0, sizeof(key));
212    key.key_type = VK_META_OBJECT_KEY_CLEAR_PIPELINE;
213    vk_meta_rendering_info_copy(&key.render, render);
214 
215    struct vk_meta_clear_push_data push = {0};
216    float depth_value = 1.0f;
217    uint32_t stencil_value = 0;
218 
219    for (uint32_t i = 0; i < attachment_count; i++) {
220       if (attachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
221          const uint32_t a = attachments[i].colorAttachment;
222          if (a == VK_ATTACHMENT_UNUSED)
223             continue;
224 
225          assert(a < MESA_VK_MAX_COLOR_ATTACHMENTS);
226          if (render->color_attachment_formats[a] == VK_FORMAT_UNDEFINED)
227             continue;
228 
229          key.color_attachments_cleared |= BITFIELD_BIT(a);
230          push.color_values[a] = attachments[i].clearValue.color;
231       }
232       if (attachments[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
233          key.clear_depth = true;
234          depth_value = attachments[i].clearValue.depthStencil.depth;
235       }
236       if (attachments[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) {
237          key.clear_stencil = true;
238          stencil_value = attachments[i].clearValue.depthStencil.stencil;
239       }
240    }
241 
242    VkPipelineLayout layout;
243    result = get_clear_pipeline_layout(device, meta, &layout);
244    if (unlikely(result != VK_SUCCESS)) {
245       /* TODO: Report error */
246       return;
247    }
248 
249    VkPipeline pipeline;
250    result = get_clear_pipeline(device, meta, &key, layout, &pipeline);
251    if (unlikely(result != VK_SUCCESS)) {
252       /* TODO: Report error */
253       return;
254    }
255 
256    disp->CmdBindPipeline(vk_command_buffer_to_handle(cmd),
257                          VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
258 
259    if (key.clear_stencil) {
260       disp->CmdSetStencilReference(vk_command_buffer_to_handle(cmd),
261                                    VK_STENCIL_FACE_FRONT_AND_BACK,
262                                    stencil_value);
263    }
264 
265    disp->CmdPushConstants(vk_command_buffer_to_handle(cmd),
266                           layout, VK_SHADER_STAGE_FRAGMENT_BIT,
267                           0, sizeof(push), &push);
268 
269    if (render->view_mask == 0) {
270       if (clear_rect_count == 1 && clear_rects[0].layerCount > 1) {
271          struct vk_meta_rect rect = {
272             .x0 = clear_rects[0].rect.offset.x,
273             .x1 = clear_rects[0].rect.offset.x +
274                   clear_rects[0].rect.extent.width,
275             .y0 = clear_rects[0].rect.offset.y,
276             .y1 = clear_rects[0].rect.offset.y +
277                   clear_rects[0].rect.extent.height,
278             .z = depth_value,
279             .layer = clear_rects[0].baseArrayLayer,
280          };
281 
282          meta->cmd_draw_volume(cmd, meta, &rect, clear_rects[0].layerCount);
283       } else {
284          uint32_t max_rect_count = 0;
285          for (uint32_t r = 0; r < clear_rect_count; r++)
286             max_rect_count += clear_rects[r].layerCount;
287 
288          STACK_ARRAY(struct vk_meta_rect, rects, max_rect_count);
289 
290          uint32_t rect_count = 0;
291          for (uint32_t r = 0; r < clear_rect_count; r++) {
292             struct vk_meta_rect rect = {
293                .x0 = clear_rects[r].rect.offset.x,
294                .x1 = clear_rects[r].rect.offset.x +
295                      clear_rects[r].rect.extent.width,
296                .y0 = clear_rects[r].rect.offset.y,
297                .y1 = clear_rects[r].rect.offset.y +
298                      clear_rects[r].rect.extent.height,
299                .z = depth_value,
300             };
301             for (uint32_t a = 0; a < clear_rects[r].layerCount; a++) {
302                rect.layer = clear_rects[r].baseArrayLayer + a;
303                rects[rect_count++] = rect;
304             }
305          }
306          assert(rect_count <= max_rect_count);
307 
308          /* If we have more than one clear rect, sort by layer in the hopes
309           * the hardware more or less does all the clears for one layer before
310           * moving on to the next, thus reducing cache thrashing.
311           */
312          qsort(rects, rect_count, sizeof(*rects), vk_meta_rect_cmp_layer);
313 
314          meta->cmd_draw_rects(cmd, meta, rect_count, rects);
315 
316          STACK_ARRAY_FINISH(rects);
317       }
318    } else {
319       const uint32_t rect_count = clear_rect_count *
320                                   util_bitcount(render->view_mask);
321       STACK_ARRAY(struct vk_meta_rect, rects, rect_count);
322 
323       uint32_t rect_idx = 0;
324       u_foreach_bit(v, render->view_mask) {
325          for (uint32_t r = 0; r < clear_rect_count; r++) {
326             assert(clear_rects[r].baseArrayLayer == 0);
327             assert(clear_rects[r].layerCount == 1);
328             rects[rect_idx++] = (struct vk_meta_rect) {
329                .x0 = clear_rects[r].rect.offset.x,
330                .x1 = clear_rects[r].rect.offset.x +
331                      clear_rects[r].rect.extent.width,
332                .y0 = clear_rects[r].rect.offset.y,
333                .y1 = clear_rects[r].rect.offset.y +
334                      clear_rects[r].rect.extent.height,
335                .z = depth_value,
336                .layer = v,
337             };
338          }
339       }
340       assert(rect_idx == rect_count);
341 
342       meta->cmd_draw_rects(cmd, meta, rect_count, rects);
343 
344       STACK_ARRAY_FINISH(rects);
345    }
346 }
347 
348 void
vk_meta_clear_rendering(struct vk_meta_device * meta,struct vk_command_buffer * cmd,const VkRenderingInfo * pRenderingInfo)349 vk_meta_clear_rendering(struct vk_meta_device *meta,
350                         struct vk_command_buffer *cmd,
351                         const VkRenderingInfo *pRenderingInfo)
352 {
353    assert(!(pRenderingInfo->flags & VK_RENDERING_RESUMING_BIT));
354 
355    struct vk_meta_rendering_info render = {
356       .view_mask = pRenderingInfo->viewMask,
357       .color_attachment_count = pRenderingInfo->colorAttachmentCount,
358    };
359 
360    uint32_t clear_count = 0;
361    VkClearAttachment clear_att[MESA_VK_MAX_COLOR_ATTACHMENTS + 1];
362    for (uint32_t i = 0; i < pRenderingInfo->colorAttachmentCount; i++) {
363       const VkRenderingAttachmentInfo *att_info =
364          &pRenderingInfo->pColorAttachments[i];
365       if (att_info->imageView == VK_NULL_HANDLE ||
366           att_info->loadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
367          continue;
368 
369       VK_FROM_HANDLE(vk_image_view, iview, att_info->imageView);
370       render.color_attachment_formats[i] = iview->format;
371       render.color_attachment_write_masks[i] =
372          VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
373          VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
374       assert(render.samples == 0 || render.samples == iview->image->samples);
375       render.samples = MAX2(render.samples, iview->image->samples);
376 
377       clear_att[clear_count++] = (VkClearAttachment) {
378          .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
379          .colorAttachment = i,
380          .clearValue = att_info->clearValue,
381       };
382    }
383 
384    /* One more for depth/stencil, if needed */
385    clear_att[clear_count] = (VkClearAttachment) { .aspectMask = 0, };
386 
387    const VkRenderingAttachmentInfo *d_att_info =
388       pRenderingInfo->pDepthAttachment;
389    if (d_att_info != NULL && d_att_info->imageView != VK_NULL_HANDLE &&
390        d_att_info->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
391       VK_FROM_HANDLE(vk_image_view, iview, d_att_info->imageView);
392       render.depth_attachment_format = iview->format;
393       render.samples = MAX2(render.samples, iview->image->samples);
394 
395       clear_att[clear_count].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
396       clear_att[clear_count].clearValue.depthStencil.depth =
397          d_att_info->clearValue.depthStencil.depth;
398    }
399 
400    const VkRenderingAttachmentInfo *s_att_info =
401       pRenderingInfo->pStencilAttachment;
402    if (s_att_info != NULL && s_att_info->imageView != VK_NULL_HANDLE &&
403        s_att_info->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
404       VK_FROM_HANDLE(vk_image_view, iview, s_att_info->imageView);
405       render.stencil_attachment_format = iview->format;
406       render.samples = MAX2(render.samples, iview->image->samples);
407 
408       clear_att[clear_count].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
409       clear_att[clear_count].clearValue.depthStencil.stencil =
410          s_att_info->clearValue.depthStencil.depth;
411    }
412    if (clear_att[clear_count].aspectMask != 0)
413       clear_count++;
414 
415    if (clear_count > 0) {
416       const VkClearRect clear_rect = {
417          .rect = pRenderingInfo->renderArea,
418          .baseArrayLayer = 0,
419          .layerCount = pRenderingInfo->viewMask ?
420                        1 : pRenderingInfo->layerCount,
421       };
422       vk_meta_clear_attachments(cmd, meta, &render,
423                                 clear_count, clear_att,
424                                 1, &clear_rect);
425    }
426 }
427 
428 static void
clear_image_level_layers(struct vk_command_buffer * cmd,struct vk_meta_device * meta,struct vk_image * image,VkImageLayout image_layout,VkFormat format,const VkClearValue * clear_value,VkImageAspectFlags aspects,uint32_t level,uint32_t base_array_layer,uint32_t layer_count)429 clear_image_level_layers(struct vk_command_buffer *cmd,
430                          struct vk_meta_device *meta,
431                          struct vk_image *image,
432                          VkImageLayout image_layout,
433                          VkFormat format,
434                          const VkClearValue *clear_value,
435                          VkImageAspectFlags aspects,
436                          uint32_t level,
437                          uint32_t base_array_layer,
438                          uint32_t layer_count)
439 {
440    struct vk_device *device = cmd->base.device;
441    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
442    VkCommandBuffer _cmd = vk_command_buffer_to_handle(cmd);
443    VkResult result;
444 
445    const VkImageViewCreateInfo view_info = {
446       .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
447       .image = vk_image_to_handle(image),
448       .viewType = vk_image_render_view_type(image, layer_count),
449       .format = format,
450       .subresourceRange = {
451          .aspectMask = aspects,
452          .baseMipLevel = level,
453          .levelCount = 1,
454          .baseArrayLayer = base_array_layer,
455          .layerCount = layer_count,
456       }
457    };
458 
459    VkImageView image_view;
460    result = vk_meta_create_image_view(cmd, meta, &view_info, &image_view);
461    if (unlikely(result != VK_SUCCESS)) {
462       /* TODO: Report error */
463       return;
464    }
465 
466    const VkExtent3D level_extent = vk_image_mip_level_extent(image, level);
467 
468    VkRenderingAttachmentInfo vk_att = {
469       .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
470       .imageView = image_view,
471       .imageLayout = image_layout,
472       .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
473       .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
474    };
475    VkRenderingInfo vk_render = {
476       .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
477       .renderArea = {
478          .offset = { 0, 0 },
479          .extent = { level_extent.width, level_extent.height },
480       },
481       .layerCount = layer_count,
482    };
483    struct vk_meta_rendering_info meta_render = {
484       .samples = image->samples,
485    };
486 
487    if (image->aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
488       vk_render.colorAttachmentCount = 1;
489       vk_render.pColorAttachments = &vk_att;
490       meta_render.color_attachment_count = 1;
491       meta_render.color_attachment_formats[0] = format;
492       meta_render.color_attachment_write_masks[0] =
493          VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
494          VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
495    }
496 
497    if (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
498       vk_render.pDepthAttachment = &vk_att;
499       meta_render.depth_attachment_format = format;
500    }
501 
502    if (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
503       vk_render.pStencilAttachment = &vk_att;
504       meta_render.stencil_attachment_format = format;
505    }
506 
507    const VkClearAttachment clear_att = {
508       .aspectMask = aspects,
509       .colorAttachment = 0,
510       .clearValue = *clear_value,
511    };
512 
513    const VkClearRect clear_rect = {
514       .rect = {
515          .offset = { 0, 0 },
516          .extent = { level_extent.width, level_extent.height },
517       },
518       .baseArrayLayer = 0,
519       .layerCount = layer_count,
520    };
521 
522    disp->CmdBeginRendering(_cmd, &vk_render);
523 
524    vk_meta_clear_attachments(cmd, meta, &meta_render,
525                              1, &clear_att, 1, &clear_rect);
526 
527    disp->CmdEndRendering(_cmd);
528 }
529 
530 static void
clear_image_level(struct vk_command_buffer * cmd,struct vk_meta_device * meta,struct vk_image * image,VkImageLayout image_layout,VkFormat format,const VkClearValue * clear_value,uint32_t level,const VkImageSubresourceRange * range)531 clear_image_level(struct vk_command_buffer *cmd,
532                   struct vk_meta_device *meta,
533                   struct vk_image *image,
534                   VkImageLayout image_layout,
535                   VkFormat format,
536                   const VkClearValue *clear_value,
537                   uint32_t level,
538                   const VkImageSubresourceRange *range)
539 {
540    const VkExtent3D level_extent = vk_image_mip_level_extent(image, level);
541 
542    uint32_t base_array_layer, layer_count;
543    if (image->image_type == VK_IMAGE_TYPE_3D) {
544       base_array_layer = 0;
545       layer_count = level_extent.depth;
546    } else {
547       base_array_layer = range->baseArrayLayer;
548       layer_count = vk_image_subresource_layer_count(image, range);
549    }
550 
551    if (layer_count > 1 && !meta->use_layered_rendering) {
552       for (uint32_t a = 0; a < layer_count; a++) {
553          clear_image_level_layers(cmd, meta, image, image_layout,
554                                   format, clear_value,
555                                   range->aspectMask, level,
556                                   base_array_layer + a, 1);
557       }
558    } else {
559       clear_image_level_layers(cmd, meta, image, image_layout,
560                                format, clear_value,
561                                range->aspectMask, level,
562                                base_array_layer, layer_count);
563    }
564 }
565 
566 void
vk_meta_clear_color_image(struct vk_command_buffer * cmd,struct vk_meta_device * meta,struct vk_image * image,VkImageLayout image_layout,VkFormat format,const VkClearColorValue * color,uint32_t range_count,const VkImageSubresourceRange * ranges)567 vk_meta_clear_color_image(struct vk_command_buffer *cmd,
568                           struct vk_meta_device *meta,
569                           struct vk_image *image,
570                           VkImageLayout image_layout,
571                           VkFormat format,
572                           const VkClearColorValue *color,
573                           uint32_t range_count,
574                           const VkImageSubresourceRange *ranges)
575 {
576    const VkClearValue clear_value = {
577       .color = *color,
578    };
579    for (uint32_t r = 0; r < range_count; r++) {
580       const uint32_t level_count =
581          vk_image_subresource_level_count(image, &ranges[r]);
582 
583       for (uint32_t l = 0; l < level_count; l++) {
584          clear_image_level(cmd, meta, image, image_layout,
585                            format, &clear_value,
586                            ranges[r].baseMipLevel + l,
587                            &ranges[r]);
588       }
589    }
590 }
591 
592 void
vk_meta_clear_depth_stencil_image(struct vk_command_buffer * cmd,struct vk_meta_device * meta,struct vk_image * image,VkImageLayout image_layout,const VkClearDepthStencilValue * depth_stencil,uint32_t range_count,const VkImageSubresourceRange * ranges)593 vk_meta_clear_depth_stencil_image(struct vk_command_buffer *cmd,
594                                   struct vk_meta_device *meta,
595                                   struct vk_image *image,
596                                   VkImageLayout image_layout,
597                                   const VkClearDepthStencilValue *depth_stencil,
598                                   uint32_t range_count,
599                                   const VkImageSubresourceRange *ranges)
600 {
601    const VkClearValue clear_value = {
602       .depthStencil = *depth_stencil,
603    };
604    for (uint32_t r = 0; r < range_count; r++) {
605       const uint32_t level_count =
606          vk_image_subresource_level_count(image, &ranges[r]);
607 
608       for (uint32_t l = 0; l < level_count; l++) {
609          clear_image_level(cmd, meta, image, image_layout,
610                            image->format, &clear_value,
611                            ranges[r].baseMipLevel + l,
612                            &ranges[r]);
613       }
614    }
615 }
616