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_int(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       assert(render.samples == 0 || render.samples == iview->image->samples);
372       render.samples = MAX2(render.samples, iview->image->samples);
373 
374       clear_att[clear_count++] = (VkClearAttachment) {
375          .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
376          .colorAttachment = i,
377          .clearValue = att_info->clearValue,
378       };
379    }
380 
381    /* One more for depth/stencil, if needed */
382    clear_att[clear_count] = (VkClearAttachment) { .aspectMask = 0, };
383 
384    const VkRenderingAttachmentInfo *d_att_info =
385       pRenderingInfo->pDepthAttachment;
386    if (d_att_info != NULL && d_att_info->imageView != VK_NULL_HANDLE &&
387        d_att_info->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
388       VK_FROM_HANDLE(vk_image_view, iview, d_att_info->imageView);
389       render.depth_attachment_format = iview->format;
390       render.samples = MAX2(render.samples, iview->image->samples);
391 
392       clear_att[clear_count].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
393       clear_att[clear_count].clearValue.depthStencil.depth =
394          d_att_info->clearValue.depthStencil.depth;
395    }
396 
397    const VkRenderingAttachmentInfo *s_att_info =
398       pRenderingInfo->pStencilAttachment;
399    if (s_att_info != NULL && s_att_info->imageView != VK_NULL_HANDLE &&
400        s_att_info->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) {
401       VK_FROM_HANDLE(vk_image_view, iview, s_att_info->imageView);
402       render.stencil_attachment_format = iview->format;
403       render.samples = MAX2(render.samples, iview->image->samples);
404 
405       clear_att[clear_count].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
406       clear_att[clear_count].clearValue.depthStencil.stencil =
407          s_att_info->clearValue.depthStencil.depth;
408    }
409    if (clear_att[clear_count].aspectMask != 0)
410       clear_count++;
411 
412    if (clear_count > 0) {
413       const VkClearRect clear_rect = {
414          .rect = pRenderingInfo->renderArea,
415          .baseArrayLayer = 0,
416          .layerCount = pRenderingInfo->viewMask ?
417                        1 : pRenderingInfo->layerCount,
418       };
419       vk_meta_clear_attachments(cmd, meta, &render,
420                                 clear_count, clear_att,
421                                 1, &clear_rect);
422    }
423 }
424 
425 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)426 clear_image_level_layers(struct vk_command_buffer *cmd,
427                          struct vk_meta_device *meta,
428                          struct vk_image *image,
429                          VkImageLayout image_layout,
430                          VkFormat format,
431                          const VkClearValue *clear_value,
432                          VkImageAspectFlags aspects,
433                          uint32_t level,
434                          uint32_t base_array_layer,
435                          uint32_t layer_count)
436 {
437    struct vk_device *device = cmd->base.device;
438    const struct vk_device_dispatch_table *disp = &device->dispatch_table;
439    VkCommandBuffer _cmd = vk_command_buffer_to_handle(cmd);
440    VkResult result;
441 
442    const VkImageViewCreateInfo view_info = {
443       .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
444       .image = vk_image_to_handle(image),
445       .viewType = vk_image_render_view_type(image, layer_count),
446       .format = format,
447       .subresourceRange = {
448          .aspectMask = aspects,
449          .baseMipLevel = level,
450          .levelCount = 1,
451          .baseArrayLayer = base_array_layer,
452          .layerCount = layer_count,
453       }
454    };
455 
456    VkImageView image_view;
457    result = vk_meta_create_image_view(cmd, meta, &view_info, &image_view);
458    if (unlikely(result != VK_SUCCESS)) {
459       /* TODO: Report error */
460       return;
461    }
462 
463    const VkExtent3D level_extent = vk_image_mip_level_extent(image, level);
464 
465    VkRenderingAttachmentInfo vk_att = {
466       .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
467       .imageView = image_view,
468       .imageLayout = image_layout,
469       .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
470       .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
471    };
472    VkRenderingInfo vk_render = {
473       .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
474       .renderArea = {
475          .offset = { 0, 0 },
476          .extent = { level_extent.width, level_extent.height },
477       },
478       .layerCount = layer_count,
479    };
480    struct vk_meta_rendering_info meta_render = {
481       .samples = image->samples,
482    };
483 
484    if (image->aspects == VK_IMAGE_ASPECT_COLOR_BIT) {
485       vk_render.colorAttachmentCount = 1;
486       vk_render.pColorAttachments = &vk_att;
487       meta_render.color_attachment_count = 1;
488       meta_render.color_attachment_formats[0] = format;
489    }
490 
491    if (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
492       vk_render.pDepthAttachment = &vk_att;
493       meta_render.depth_attachment_format = format;
494    }
495 
496    if (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
497       vk_render.pStencilAttachment = &vk_att;
498       meta_render.stencil_attachment_format = format;
499    }
500 
501    const VkClearAttachment clear_att = {
502       .aspectMask = aspects,
503       .colorAttachment = 0,
504       .clearValue = *clear_value,
505    };
506 
507    const VkClearRect clear_rect = {
508       .rect = {
509          .offset = { 0, 0 },
510          .extent = { level_extent.width, level_extent.height },
511       },
512       .baseArrayLayer = 0,
513       .layerCount = layer_count,
514    };
515 
516    disp->CmdBeginRendering(_cmd, &vk_render);
517 
518    vk_meta_clear_attachments(cmd, meta, &meta_render,
519                              1, &clear_att, 1, &clear_rect);
520 
521    disp->CmdEndRendering(_cmd);
522 }
523 
524 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)525 clear_image_level(struct vk_command_buffer *cmd,
526                   struct vk_meta_device *meta,
527                   struct vk_image *image,
528                   VkImageLayout image_layout,
529                   VkFormat format,
530                   const VkClearValue *clear_value,
531                   uint32_t level,
532                   const VkImageSubresourceRange *range)
533 {
534    const VkExtent3D level_extent = vk_image_mip_level_extent(image, level);
535 
536    uint32_t base_array_layer, layer_count;
537    if (image->image_type == VK_IMAGE_TYPE_3D) {
538       base_array_layer = 0;
539       layer_count = level_extent.depth;
540    } else {
541       base_array_layer = range->baseArrayLayer;
542       layer_count = vk_image_subresource_layer_count(image, range);
543    }
544 
545    if (layer_count > 1 && !meta->use_layered_rendering) {
546       for (uint32_t a = 0; a < layer_count; a++) {
547          clear_image_level_layers(cmd, meta, image, image_layout,
548                                   format, clear_value,
549                                   range->aspectMask, level,
550                                   base_array_layer + a, 1);
551       }
552    } else {
553       clear_image_level_layers(cmd, meta, image, image_layout,
554                                format, clear_value,
555                                range->aspectMask, level,
556                                base_array_layer, layer_count);
557    }
558 }
559 
560 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)561 vk_meta_clear_color_image(struct vk_command_buffer *cmd,
562                           struct vk_meta_device *meta,
563                           struct vk_image *image,
564                           VkImageLayout image_layout,
565                           VkFormat format,
566                           const VkClearColorValue *color,
567                           uint32_t range_count,
568                           const VkImageSubresourceRange *ranges)
569 {
570    const VkClearValue clear_value = {
571       .color = *color,
572    };
573    for (uint32_t r = 0; r < range_count; r++) {
574       const uint32_t level_count =
575          vk_image_subresource_level_count(image, &ranges[r]);
576 
577       for (uint32_t l = 0; l < level_count; l++) {
578          clear_image_level(cmd, meta, image, image_layout,
579                            format, &clear_value,
580                            ranges[r].baseMipLevel + l,
581                            &ranges[r]);
582       }
583    }
584 }
585 
586 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)587 vk_meta_clear_depth_stencil_image(struct vk_command_buffer *cmd,
588                                   struct vk_meta_device *meta,
589                                   struct vk_image *image,
590                                   VkImageLayout image_layout,
591                                   const VkClearDepthStencilValue *depth_stencil,
592                                   uint32_t range_count,
593                                   const VkImageSubresourceRange *ranges)
594 {
595    const VkClearValue clear_value = {
596       .depthStencil = *depth_stencil,
597    };
598    for (uint32_t r = 0; r < range_count; r++) {
599       const uint32_t level_count =
600          vk_image_subresource_level_count(image, &ranges[r]);
601 
602       for (uint32_t l = 0; l < level_count; l++) {
603          clear_image_level(cmd, meta, image, image_layout,
604                            image->format, &clear_value,
605                            ranges[r].baseMipLevel + l,
606                            &ranges[r]);
607       }
608    }
609 }
610