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