Home | History | Annotate | Line # | Download | only in vulkan
      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
     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_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 
     85 static mali_ptr
     86 panvk_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 
    152 static mali_ptr
    153 panvk_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 
    258 static mali_ptr
    259 panvk_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 
    279 static mali_ptr
    280 panvk_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 
    295 static void
    296 panvk_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 
    314 static struct panfrost_ptr
    315 panvk_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 
    359 static enum glsl_base_type
    360 panvk_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 
    388 static void
    389 panvk_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 
    482 static void
    483 panvk_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 
    529 void
    530 panvk_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 
    546 static void
    547 panvk_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 
    607 void
    608 panvk_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 
    624 void
    625 panvk_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 
    656 static void
    657 panvk_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 
    708 void
    709 panvk_per_arch(meta_clear_init)(struct panvk_physical_device *dev)
    710 {
    711    panvk_meta_clear_attachment_init(dev);
    712 }
    713