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