1/*
2 * Copyright © 2021 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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "nir/nir_builder.h"
25#include "pan_blitter.h"
26#include "pan_encoder.h"
27#include "pan_shader.h"
28
29#include "panvk_private.h"
30#include "panvk_vX_meta.h"
31
32#include "vk_format.h"
33
34static mali_ptr
35panvk_meta_clear_color_attachment_shader(struct panfrost_device *pdev,
36                                         struct pan_pool *bin_pool,
37                                         unsigned rt,
38                                         enum glsl_base_type base_type,
39                                         struct pan_shader_info *shader_info)
40{
41   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
42                                     GENX(pan_shader_get_compiler_options)(),
43                                     "panvk_meta_clear_rt%d_attachment(base_type=%d)",
44                                     rt, base_type);
45
46   b.shader->info.internal = true;
47   b.shader->info.num_ubos = 1;
48
49   const struct glsl_type *out_type = glsl_vector_type(base_type, 4);
50   nir_variable *out =
51      nir_variable_create(b.shader, nir_var_shader_out, out_type, "out");
52   out->data.location = FRAG_RESULT_DATA0 + rt;
53
54   nir_ssa_def *clear_values = nir_load_ubo(&b, 4, 32, nir_imm_int(&b, 0),
55                                            nir_imm_int(&b, 0),
56                                            .align_mul = 4,
57                                            .align_offset = 0,
58                                            .range_base = 0,
59                                            .range = ~0);
60   nir_store_var(&b, out, clear_values, 0xff);
61
62   struct panfrost_compile_inputs inputs = {
63      .gpu_id = pdev->gpu_id,
64      .is_blit = true,
65   };
66
67   struct util_dynarray binary;
68
69   util_dynarray_init(&binary, NULL);
70   GENX(pan_shader_compile)(b.shader, &inputs, &binary, shader_info);
71
72   /* Make sure UBO words have been upgraded to push constants */
73   assert(shader_info->ubo_mask == 0);
74
75   mali_ptr shader =
76      pan_pool_upload_aligned(bin_pool, binary.data, binary.size,
77                              PAN_ARCH >= 6 ? 128 : 64);
78
79   util_dynarray_fini(&binary);
80   ralloc_free(b.shader);
81
82   return shader;
83}
84
85static mali_ptr
86panvk_meta_clear_zs_attachment_shader(struct panfrost_device *pdev,
87                                      struct pan_pool *bin_pool,
88                                      bool clear_z, bool clear_s,
89                                      enum glsl_base_type base_type,
90                                      struct pan_shader_info *shader_info)
91{
92   nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT,
93                                     GENX(pan_shader_get_compiler_options)(),
94                                     "panvk_meta_clear_%s%s_attachment()",
95                                     clear_z ? "z" : "", clear_s ? "s" : "");
96
97   b.shader->info.internal = true;
98   b.shader->info.num_ubos = 1;
99
100   unsigned drv_loc = 0;
101   nir_variable *z_out =
102      clear_z ?
103      nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(), "depth") :
104      NULL;
105   nir_variable *s_out =
106      clear_s ?
107      nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(), "stencil") :
108      NULL;
109
110   nir_ssa_def *clear_values = nir_load_ubo(&b, 2, 32, nir_imm_int(&b, 0),
111                                            nir_imm_int(&b, 0),
112                                            .align_mul = 4,
113                                            .align_offset = 0,
114                                            .range_base = 0,
115                                            .range = ~0);
116
117   if (z_out) {
118      z_out->data.location = FRAG_RESULT_DEPTH;
119      z_out->data.driver_location = drv_loc++;
120      nir_store_var(&b, z_out, nir_channel(&b, clear_values, 0), 1);
121   }
122
123   if (s_out) {
124      s_out->data.location = FRAG_RESULT_STENCIL;
125      s_out->data.driver_location = drv_loc++;
126      nir_store_var(&b, s_out, nir_channel(&b, clear_values, 1), 1);
127   }
128
129   struct panfrost_compile_inputs inputs = {
130      .gpu_id = pdev->gpu_id,
131      .is_blit = true,
132   };
133
134   struct util_dynarray binary;
135
136   util_dynarray_init(&binary, NULL);
137   GENX(pan_shader_compile)(b.shader, &inputs, &binary, shader_info);
138
139   /* Make sure UBO words have been upgraded to push constants */
140   assert(shader_info->ubo_mask == 0);
141
142   mali_ptr shader =
143      pan_pool_upload_aligned(bin_pool, binary.data, binary.size,
144                              PAN_ARCH >= 6 ? 128 : 64);
145
146   util_dynarray_fini(&binary);
147   ralloc_free(b.shader);
148
149   return shader;
150}
151
152static mali_ptr
153panvk_meta_clear_attachments_emit_rsd(struct panfrost_device *pdev,
154                                      struct pan_pool *desc_pool,
155                                      enum pipe_format format,
156                                      unsigned rt, bool z, bool s,
157                                      struct pan_shader_info *shader_info,
158                                      mali_ptr shader)
159{
160   struct panfrost_ptr rsd_ptr =
161      pan_pool_alloc_desc_aggregate(desc_pool,
162                                    PAN_DESC(RENDERER_STATE),
163                                    PAN_DESC_ARRAY(rt + 1, BLEND));
164   bool zs = z | s;
165
166   pan_pack(rsd_ptr.cpu, RENDERER_STATE, cfg) {
167      pan_shader_prepare_rsd(shader_info, shader, &cfg);
168      cfg.properties.depth_source =
169         z ?
170	 MALI_DEPTH_SOURCE_SHADER :
171	 MALI_DEPTH_SOURCE_FIXED_FUNCTION;
172      cfg.multisample_misc.depth_write_mask = z;
173      cfg.multisample_misc.sample_mask = UINT16_MAX;
174      cfg.multisample_misc.depth_function = MALI_FUNC_ALWAYS;
175      cfg.stencil_mask_misc.stencil_enable = s;
176      cfg.properties.stencil_from_shader = s;
177      cfg.stencil_mask_misc.stencil_mask_front = 0xFF;
178      cfg.stencil_mask_misc.stencil_mask_back = 0xFF;
179      cfg.stencil_front.compare_function = MALI_FUNC_ALWAYS;
180      cfg.stencil_front.stencil_fail = MALI_STENCIL_OP_REPLACE;
181      cfg.stencil_front.depth_fail = MALI_STENCIL_OP_REPLACE;
182      cfg.stencil_front.depth_pass = MALI_STENCIL_OP_REPLACE;
183      cfg.stencil_front.mask = 0xFF;
184      cfg.stencil_back = cfg.stencil_front;
185
186#if PAN_ARCH >= 6
187      cfg.properties.allow_forward_pixel_to_be_killed = PAN_ARCH >= 7 || !zs;
188      cfg.properties.allow_forward_pixel_to_kill = !zs;
189      if (zs) {
190         cfg.properties.zs_update_operation =
191            MALI_PIXEL_KILL_FORCE_LATE;
192         cfg.properties.pixel_kill_operation =
193            MALI_PIXEL_KILL_FORCE_LATE;
194      } else {
195         cfg.properties.zs_update_operation =
196            MALI_PIXEL_KILL_STRONG_EARLY;
197         cfg.properties.pixel_kill_operation =
198            MALI_PIXEL_KILL_FORCE_EARLY;
199      }
200#else
201      cfg.properties.shader_reads_tilebuffer = false;
202      cfg.properties.work_register_count = shader_info->work_reg_count;
203      cfg.properties.force_early_z = !zs;
204      cfg.stencil_mask_misc.alpha_test_compare_function = MALI_FUNC_ALWAYS;
205#endif
206   }
207
208   void *bd = rsd_ptr.cpu + pan_size(RENDERER_STATE);
209
210   /* Disable all RTs except the one we're interested in. */
211   for (unsigned i = 0; i < rt; i++) {
212      pan_pack(bd, BLEND, cfg) {
213         cfg.enable = false;
214#if PAN_ARCH >= 6
215         cfg.internal.mode = MALI_BLEND_MODE_OFF;
216#endif
217      }
218
219      bd += pan_size(BLEND);
220   }
221
222   if (zs) {
223      /* We write the depth/stencil, disable blending on RT0. */
224      pan_pack(bd, BLEND, cfg) {
225         cfg.enable = false;
226#if PAN_ARCH >= 6
227         cfg.internal.mode = MALI_BLEND_MODE_OFF;
228#endif
229      }
230   } else {
231      pan_pack(bd, BLEND, cfg) {
232         cfg.round_to_fb_precision = true;
233         cfg.load_destination = false;
234         cfg.equation.rgb.a = MALI_BLEND_OPERAND_A_SRC;
235         cfg.equation.rgb.b = MALI_BLEND_OPERAND_B_SRC;
236         cfg.equation.rgb.c = MALI_BLEND_OPERAND_C_ZERO;
237         cfg.equation.alpha.a = MALI_BLEND_OPERAND_A_SRC;
238         cfg.equation.alpha.b = MALI_BLEND_OPERAND_B_SRC;
239         cfg.equation.alpha.c = MALI_BLEND_OPERAND_C_ZERO;
240#if PAN_ARCH >= 6
241         cfg.internal.mode = MALI_BLEND_MODE_OPAQUE;
242         cfg.equation.color_mask = 0xf;
243         cfg.internal.fixed_function.num_comps = 4;
244         cfg.internal.fixed_function.conversion.memory_format =
245            panfrost_format_to_bifrost_blend(pdev, format, false);
246         cfg.internal.fixed_function.conversion.register_format =
247            shader_info->bifrost.blend[rt].format;
248#else
249         cfg.equation.color_mask =
250            (1 << util_format_get_nr_components(format)) - 1;
251#endif
252      }
253   }
254
255   return rsd_ptr.gpu;
256}
257
258static mali_ptr
259panvk_meta_clear_attachment_emit_push_constants(struct panfrost_device *pdev,
260                                                const struct panfrost_ubo_push *pushmap,
261                                                struct pan_pool *pool,
262                                                const VkClearValue *clear_value)
263{
264   assert(pushmap->count <= (sizeof(*clear_value) / 4));
265
266   uint32_t *in = (uint32_t *)clear_value;
267   uint32_t pushvals[sizeof(*clear_value) / 4];
268
269   for (unsigned i = 0; i < pushmap->count; i++) {
270      assert(i < ARRAY_SIZE(pushvals));
271      assert(pushmap->words[i].ubo == 0);
272      assert(pushmap->words[i].offset < sizeof(*clear_value));
273      pushvals[i] = in[pushmap->words[i].offset / 4];
274   }
275
276   return pan_pool_upload_aligned(pool, pushvals, sizeof(pushvals), 16);
277}
278
279static mali_ptr
280panvk_meta_clear_attachment_emit_ubo(struct panfrost_device *pdev,
281                                     const struct panfrost_ubo_push *pushmap,
282                                     struct pan_pool *pool,
283                                     const VkClearValue *clear_value)
284{
285   struct panfrost_ptr ubo = pan_pool_alloc_desc(pool, UNIFORM_BUFFER);
286
287   pan_pack(ubo.cpu, UNIFORM_BUFFER, cfg) {
288      cfg.entries = DIV_ROUND_UP(sizeof(*clear_value), 16);
289      cfg.pointer = pan_pool_upload_aligned(pool, clear_value, sizeof(*clear_value), 16);
290   }
291
292   return ubo.gpu;
293}
294
295static void
296panvk_meta_clear_attachment_emit_dcd(struct pan_pool *pool,
297                                     mali_ptr coords,
298                                     mali_ptr ubo, mali_ptr push_constants,
299                                     mali_ptr vpd, mali_ptr tsd, mali_ptr rsd,
300                                     void *out)
301{
302   pan_pack(out, DRAW, cfg) {
303      cfg.four_components_per_vertex = true;
304      cfg.draw_descriptor_is_64b = true;
305      cfg.thread_storage = tsd;
306      cfg.state = rsd;
307      cfg.uniform_buffers = ubo;
308      cfg.push_uniforms = push_constants;
309      cfg.position = coords;
310      cfg.viewport = vpd;
311   }
312}
313
314static struct panfrost_ptr
315panvk_meta_clear_attachment_emit_tiler_job(struct pan_pool *desc_pool,
316                                           struct pan_scoreboard *scoreboard,
317                                           mali_ptr coords,
318                                           mali_ptr ubo, mali_ptr push_constants,
319                                           mali_ptr vpd, mali_ptr rsd,
320                                           mali_ptr tsd, mali_ptr tiler)
321{
322   struct panfrost_ptr job =
323      pan_pool_alloc_desc(desc_pool, TILER_JOB);
324
325   panvk_meta_clear_attachment_emit_dcd(desc_pool,
326                                        coords,
327                                        ubo, push_constants,
328                                        vpd, tsd, rsd,
329                                        pan_section_ptr(job.cpu, TILER_JOB, DRAW));
330
331   pan_section_pack(job.cpu, TILER_JOB, PRIMITIVE, cfg) {
332      cfg.draw_mode = MALI_DRAW_MODE_TRIANGLE_STRIP;
333      cfg.index_count = 4;
334      cfg.job_task_split = 6;
335   }
336
337   pan_section_pack(job.cpu, TILER_JOB, PRIMITIVE_SIZE, cfg) {
338      cfg.constant = 1.0f;
339   }
340
341   void *invoc = pan_section_ptr(job.cpu,
342                                 TILER_JOB,
343                                 INVOCATION);
344   panfrost_pack_work_groups_compute(invoc, 1, 4,
345                                     1, 1, 1, 1, true, false);
346
347#if PAN_ARCH >= 6
348   pan_section_pack(job.cpu, TILER_JOB, PADDING, cfg);
349   pan_section_pack(job.cpu, TILER_JOB, TILER, cfg) {
350      cfg.address = tiler;
351   }
352#endif
353
354   panfrost_add_job(desc_pool, scoreboard, MALI_JOB_TYPE_TILER,
355                    false, false, 0, 0, &job, false);
356   return job;
357}
358
359static enum glsl_base_type
360panvk_meta_get_format_type(enum pipe_format format)
361{
362   const struct util_format_description *desc = util_format_description(format);
363   int i;
364
365   i = util_format_get_first_non_void_channel(format);
366   assert(i >= 0);
367
368   if (desc->channel[i].normalized)
369      return GLSL_TYPE_FLOAT;
370
371   switch(desc->channel[i].type) {
372
373   case UTIL_FORMAT_TYPE_UNSIGNED:
374      return GLSL_TYPE_UINT;
375
376   case UTIL_FORMAT_TYPE_SIGNED:
377      return GLSL_TYPE_INT;
378
379   case UTIL_FORMAT_TYPE_FLOAT:
380      return GLSL_TYPE_FLOAT;
381
382   default:
383      unreachable("Unhandled format");
384      return GLSL_TYPE_FLOAT;
385   }
386}
387
388static void
389panvk_meta_clear_attachment(struct panvk_cmd_buffer *cmdbuf,
390                            unsigned attachment, unsigned rt,
391                            VkImageAspectFlags mask,
392                            const VkClearValue *clear_value,
393                            const VkClearRect *clear_rect)
394{
395   struct panvk_physical_device *dev = cmdbuf->device->physical_device;
396   struct panfrost_device *pdev = &dev->pdev;
397   struct panvk_meta *meta = &cmdbuf->device->physical_device->meta;
398   struct panvk_batch *batch = cmdbuf->state.batch;
399   const struct panvk_render_pass *pass = cmdbuf->state.pass;
400   const struct panvk_render_pass_attachment *att = &pass->attachments[attachment];
401   unsigned minx = MAX2(clear_rect->rect.offset.x, 0);
402   unsigned miny = MAX2(clear_rect->rect.offset.y, 0);
403   unsigned maxx = MAX2(clear_rect->rect.offset.x + clear_rect->rect.extent.width - 1, 0);
404   unsigned maxy = MAX2(clear_rect->rect.offset.y + clear_rect->rect.extent.height - 1, 0);
405
406   panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf);
407   panvk_per_arch(cmd_alloc_tls_desc)(cmdbuf, true);
408   panvk_per_arch(cmd_prepare_tiler_context)(cmdbuf);
409
410   mali_ptr vpd =
411      panvk_per_arch(meta_emit_viewport)(&cmdbuf->desc_pool.base,
412                                         minx, miny, maxx, maxy);
413
414   float rect[] = {
415      minx, miny, 0.0, 1.0,
416      maxx + 1, miny, 0.0, 1.0,
417      minx, maxy + 1, 0.0, 1.0,
418      maxx + 1, maxy + 1, 0.0, 1.0,
419   };
420   mali_ptr coordinates = pan_pool_upload_aligned(&cmdbuf->desc_pool.base,
421                                                  rect, sizeof(rect), 64);
422
423   enum glsl_base_type base_type = panvk_meta_get_format_type(att->format);
424   struct pan_shader_info *shader_info;
425   bool clear_z = false, clear_s = false;
426   mali_ptr shader;
427
428   switch (mask) {
429   case VK_IMAGE_ASPECT_COLOR_BIT:
430      shader = meta->clear_attachment.color[rt][base_type].shader;
431      shader_info = &meta->clear_attachment.color[rt][base_type].shader_info;
432      break;
433   case VK_IMAGE_ASPECT_DEPTH_BIT:
434      shader = meta->clear_attachment.z.shader;
435      shader_info = &meta->clear_attachment.z.shader_info;
436      clear_z = true;
437      break;
438   case VK_IMAGE_ASPECT_STENCIL_BIT:
439      shader = meta->clear_attachment.s.shader;
440      shader_info = &meta->clear_attachment.s.shader_info;
441      clear_s = true;
442      break;
443   case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
444      shader = meta->clear_attachment.zs.shader;
445      shader_info = &meta->clear_attachment.zs.shader_info;
446      clear_s = clear_z = true;
447      break;
448   default:
449      unreachable("Invalid aspect mask\n");
450   }
451
452   mali_ptr rsd =
453      panvk_meta_clear_attachments_emit_rsd(pdev,
454                                            &cmdbuf->desc_pool.base,
455                                            att->format, rt, clear_z, clear_s,
456                                            shader_info,
457                                            shader);
458
459   mali_ptr pushconsts =
460      panvk_meta_clear_attachment_emit_push_constants(pdev, &shader_info->push,
461                                                      &cmdbuf->desc_pool.base,
462                                                      clear_value);
463   mali_ptr ubo =
464      panvk_meta_clear_attachment_emit_ubo(pdev, &shader_info->push,
465                                           &cmdbuf->desc_pool.base,
466                                           clear_value);
467
468   mali_ptr tsd = PAN_ARCH >= 6 ? batch->tls.gpu : batch->fb.desc.gpu;
469   mali_ptr tiler = PAN_ARCH >= 6 ? batch->tiler.descs.gpu : 0;
470
471   struct panfrost_ptr job;
472
473   job = panvk_meta_clear_attachment_emit_tiler_job(&cmdbuf->desc_pool.base,
474                                                    &batch->scoreboard,
475                                                    coordinates,
476                                                    ubo, pushconsts,
477                                                    vpd, rsd, tsd, tiler);
478
479   util_dynarray_append(&batch->jobs, void *, job.cpu);
480}
481
482static void
483panvk_meta_clear_color_img(struct panvk_cmd_buffer *cmdbuf,
484                           struct panvk_image *img,
485                           const VkClearColorValue *color,
486                           const VkImageSubresourceRange *range)
487{
488   struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info;
489   struct pan_image_view view = {
490      .format = img->pimage.layout.format,
491      .dim = MALI_TEXTURE_DIMENSION_2D,
492      .image = &img->pimage,
493      .nr_samples = img->pimage.layout.nr_samples,
494      .swizzle = { PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W },
495   };
496
497   cmdbuf->state.fb.crc_valid[0] = false;
498   *fbinfo = (struct pan_fb_info){
499      .nr_samples = img->pimage.layout.nr_samples,
500      .rt_count = 1,
501      .rts[0].view = &view,
502      .rts[0].clear = true,
503      .rts[0].crc_valid = &cmdbuf->state.fb.crc_valid[0],
504   };
505
506   uint32_t clearval[4];
507   pan_pack_color(clearval, (union pipe_color_union *)color,
508                  img->pimage.layout.format, false);
509   memcpy(fbinfo->rts[0].clear_value, clearval, sizeof(fbinfo->rts[0].clear_value));
510
511   for (unsigned level = range->baseMipLevel;
512        level < range->baseMipLevel + range->levelCount; level++) {
513      view.first_level = view.last_level = level;
514      fbinfo->width = u_minify(img->pimage.layout.width, level);
515      fbinfo->height = u_minify(img->pimage.layout.height, level);
516      fbinfo->extent.maxx = fbinfo->width - 1;
517      fbinfo->extent.maxy = fbinfo->height - 1;
518
519      for (unsigned layer = range->baseArrayLayer;
520           layer < range->baseArrayLayer + range->layerCount; layer++) {
521         view.first_layer = view.last_layer = layer;
522         panvk_cmd_open_batch(cmdbuf);
523         panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf);
524         panvk_per_arch(cmd_close_batch)(cmdbuf);
525      }
526   }
527}
528
529void
530panvk_per_arch(CmdClearColorImage)(VkCommandBuffer commandBuffer,
531                                   VkImage image,
532                                   VkImageLayout imageLayout,
533                                   const VkClearColorValue *pColor,
534                                   uint32_t rangeCount,
535                                   const VkImageSubresourceRange *pRanges)
536{
537   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
538   VK_FROM_HANDLE(panvk_image, img, image);
539
540   panvk_per_arch(cmd_close_batch)(cmdbuf);
541
542   for (unsigned i = 0; i < rangeCount; i++)
543      panvk_meta_clear_color_img(cmdbuf, img, pColor, &pRanges[i]);
544}
545
546static void
547panvk_meta_clear_zs_img(struct panvk_cmd_buffer *cmdbuf,
548                        struct panvk_image *img,
549                        const VkClearDepthStencilValue *value,
550                        const VkImageSubresourceRange *range)
551{
552   struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info;
553   struct pan_image_view view = {
554      .format = img->pimage.layout.format,
555      .dim = MALI_TEXTURE_DIMENSION_2D,
556      .image = &img->pimage,
557      .nr_samples = img->pimage.layout.nr_samples,
558      .swizzle = { PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W },
559   };
560
561   cmdbuf->state.fb.crc_valid[0] = false;
562   *fbinfo = (struct pan_fb_info){
563      .nr_samples = img->pimage.layout.nr_samples,
564      .rt_count = 1,
565   };
566
567   const struct util_format_description *fdesc =
568      util_format_description(view.format);
569
570   if (util_format_has_depth(fdesc)) {
571      fbinfo->zs.view.zs = &view;
572      fbinfo->zs.clear.z = range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT;
573      if (util_format_has_stencil(fdesc)) {
574         fbinfo->zs.clear.s = range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT;
575         fbinfo->zs.preload.z = !fbinfo->zs.clear.z && fbinfo->zs.clear.s;
576         fbinfo->zs.preload.s = !fbinfo->zs.clear.s && fbinfo->zs.clear.z;
577      }
578   } else {
579      fbinfo->zs.view.s = &view;
580      fbinfo->zs.clear.s = range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT;
581   }
582
583   if (fbinfo->zs.clear.z)
584      fbinfo->zs.clear_value.depth = value->depth;
585
586   if (fbinfo->zs.clear.s)
587      fbinfo->zs.clear_value.stencil = value->stencil;
588
589   for (unsigned level = range->baseMipLevel;
590        level < range->baseMipLevel + range->levelCount; level++) {
591      view.first_level = view.last_level = level;
592      fbinfo->width = u_minify(img->pimage.layout.width, level);
593      fbinfo->height = u_minify(img->pimage.layout.height, level);
594      fbinfo->extent.maxx = fbinfo->width - 1;
595      fbinfo->extent.maxy = fbinfo->height - 1;
596
597      for (unsigned layer = range->baseArrayLayer;
598           layer < range->baseArrayLayer + range->layerCount; layer++) {
599         view.first_layer = view.last_layer = layer;
600         panvk_cmd_open_batch(cmdbuf);
601         panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf);
602         panvk_per_arch(cmd_close_batch)(cmdbuf);
603      }
604   }
605}
606
607void
608panvk_per_arch(CmdClearDepthStencilImage)(VkCommandBuffer commandBuffer,
609                                          VkImage image,
610                                          VkImageLayout imageLayout,
611                                          const VkClearDepthStencilValue *pDepthStencil,
612                                          uint32_t rangeCount,
613                                          const VkImageSubresourceRange *pRanges)
614{
615   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
616   VK_FROM_HANDLE(panvk_image, img, image);
617
618   panvk_per_arch(cmd_close_batch)(cmdbuf);
619
620   for (unsigned i = 0; i < rangeCount; i++)
621      panvk_meta_clear_zs_img(cmdbuf, img, pDepthStencil, &pRanges[i]);
622}
623
624void
625panvk_per_arch(CmdClearAttachments)(VkCommandBuffer commandBuffer,
626                                    uint32_t attachmentCount,
627                                    const VkClearAttachment *pAttachments,
628                                    uint32_t rectCount,
629                                    const VkClearRect *pRects)
630{
631   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
632   const struct panvk_subpass *subpass = cmdbuf->state.subpass;
633
634   for (unsigned i = 0; i < attachmentCount; i++) {
635      for (unsigned j = 0; j < rectCount; j++) {
636
637         uint32_t attachment, rt = 0;
638         if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
639            rt = pAttachments[i].colorAttachment;
640            attachment = subpass->color_attachments[rt].idx;
641         } else {
642            attachment = subpass->zs_attachment.idx;
643         }
644
645         if (attachment == VK_ATTACHMENT_UNUSED)
646               continue;
647
648         panvk_meta_clear_attachment(cmdbuf, attachment, rt,
649                                     pAttachments[i].aspectMask,
650                                     &pAttachments[i].clearValue,
651                                     &pRects[j]);
652      }
653   }
654}
655
656static void
657panvk_meta_clear_attachment_init(struct panvk_physical_device *dev)
658{
659   for (unsigned rt = 0; rt < MAX_RTS; rt++) {
660      dev->meta.clear_attachment.color[rt][GLSL_TYPE_UINT].shader =
661         panvk_meta_clear_color_attachment_shader(
662               &dev->pdev,
663               &dev->meta.bin_pool.base,
664               rt,
665               GLSL_TYPE_UINT,
666               &dev->meta.clear_attachment.color[rt][GLSL_TYPE_UINT].shader_info);
667
668      dev->meta.clear_attachment.color[rt][GLSL_TYPE_INT].shader =
669         panvk_meta_clear_color_attachment_shader(
670               &dev->pdev,
671               &dev->meta.bin_pool.base,
672               rt,
673               GLSL_TYPE_INT,
674               &dev->meta.clear_attachment.color[rt][GLSL_TYPE_INT].shader_info);
675
676      dev->meta.clear_attachment.color[rt][GLSL_TYPE_FLOAT].shader =
677         panvk_meta_clear_color_attachment_shader(
678               &dev->pdev,
679               &dev->meta.bin_pool.base,
680               rt,
681               GLSL_TYPE_FLOAT,
682               &dev->meta.clear_attachment.color[rt][GLSL_TYPE_FLOAT].shader_info);
683   }
684
685   dev->meta.clear_attachment.z.shader =
686         panvk_meta_clear_zs_attachment_shader(
687               &dev->pdev,
688               &dev->meta.bin_pool.base,
689               true, false,
690               GLSL_TYPE_FLOAT,
691               &dev->meta.clear_attachment.z.shader_info);
692   dev->meta.clear_attachment.s.shader =
693         panvk_meta_clear_zs_attachment_shader(
694               &dev->pdev,
695               &dev->meta.bin_pool.base,
696               false, true,
697               GLSL_TYPE_FLOAT,
698               &dev->meta.clear_attachment.s.shader_info);
699   dev->meta.clear_attachment.zs.shader =
700         panvk_meta_clear_zs_attachment_shader(
701               &dev->pdev,
702               &dev->meta.bin_pool.base,
703               true, true,
704               GLSL_TYPE_FLOAT,
705               &dev->meta.clear_attachment.zs.shader_info);
706}
707
708void
709panvk_per_arch(meta_clear_init)(struct panvk_physical_device *dev)
710{
711   panvk_meta_clear_attachment_init(dev);
712}
713