Home | History | Annotate | Line # | Download | only in lib
      1 /*
      2  * Copyright (C) 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 FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  *
     23  */
     24 
     25 #include <stdio.h>
     26 #include "pan_bo.h"
     27 #include "pan_shader.h"
     28 #include "pan_scoreboard.h"
     29 #include "pan_encoder.h"
     30 #include "pan_indirect_draw.h"
     31 #include "pan_pool.h"
     32 #include "pan_util.h"
     33 #include "panfrost-quirks.h"
     34 #include "compiler/nir/nir_builder.h"
     35 #include "util/u_memory.h"
     36 #include "util/macros.h"
     37 
     38 #define WORD(x) ((x) * 4)
     39 
     40 #define LOOP \
     41         for (nir_loop *l = nir_push_loop(b); l != NULL; \
     42              nir_pop_loop(b, l), l = NULL)
     43 #define BREAK nir_jump(b, nir_jump_break)
     44 #define CONTINUE nir_jump(b, nir_jump_continue)
     45 
     46 #define IF(cond) nir_push_if(b, cond);
     47 #define ELSE nir_push_else(b, NULL);
     48 #define ENDIF nir_pop_if(b, NULL);
     49 
     50 #define MIN_MAX_JOBS 128
     51 
     52 struct draw_data {
     53         nir_ssa_def *draw_buf;
     54         nir_ssa_def *draw_buf_stride;
     55         nir_ssa_def *index_buf;
     56         nir_ssa_def *restart_index;
     57         nir_ssa_def *vertex_count;
     58         nir_ssa_def *start_instance;
     59         nir_ssa_def *instance_count;
     60         nir_ssa_def *vertex_start;
     61         nir_ssa_def *index_bias;
     62         nir_ssa_def *draw_ctx;
     63         nir_ssa_def *min_max_ctx;
     64 };
     65 
     66 struct instance_size {
     67         nir_ssa_def *raw;
     68         nir_ssa_def *padded;
     69         nir_ssa_def *packed;
     70 };
     71 
     72 struct jobs_data {
     73         nir_ssa_def *vertex_job;
     74         nir_ssa_def *tiler_job;
     75         nir_ssa_def *base_vertex_offset;
     76         nir_ssa_def *first_vertex_sysval;
     77         nir_ssa_def *base_vertex_sysval;
     78         nir_ssa_def *base_instance_sysval;
     79         nir_ssa_def *offset_start;
     80         nir_ssa_def *invocation;
     81 };
     82 
     83 struct varyings_data {
     84         nir_ssa_def *varying_bufs;
     85         nir_ssa_def *pos_ptr;
     86         nir_ssa_def *psiz_ptr;
     87         nir_variable *mem_ptr;
     88 };
     89 
     90 struct attribs_data {
     91         nir_ssa_def *attrib_count;
     92         nir_ssa_def *attrib_bufs;
     93         nir_ssa_def *attribs;
     94 };
     95 
     96 struct indirect_draw_shader_builder {
     97         nir_builder b;
     98         const struct panfrost_device *dev;
     99         unsigned flags;
    100         bool index_min_max_search;
    101         unsigned index_size;
    102         struct draw_data draw;
    103         struct instance_size instance_size;
    104         struct jobs_data jobs;
    105         struct varyings_data varyings;
    106         struct attribs_data attribs;
    107 };
    108 
    109 /* Describes an indirect draw (see glDrawArraysIndirect()) */
    110 
    111 struct indirect_draw_info {
    112         uint32_t count;
    113         uint32_t instance_count;
    114         uint32_t start;
    115         uint32_t start_instance;
    116 };
    117 
    118 struct indirect_indexed_draw_info {
    119         uint32_t count;
    120         uint32_t instance_count;
    121         uint32_t start;
    122         int32_t index_bias;
    123         uint32_t start_instance;
    124 };
    125 
    126 /* Store the min/max index in a separate context. This is not supported yet, but
    127  * the DDK seems to put all min/max search jobs at the beginning of the job chain
    128  * when multiple indirect draws are issued to avoid the serialization caused by
    129  * the draw patching jobs which have the suppress_prefetch flag set. Merging the
    130  * min/max and draw contexts would prevent such optimizations (draw contexts are
    131  * shared by all indirect draw in a batch).
    132  */
    133 
    134 struct min_max_context {
    135         uint32_t min;
    136         uint32_t max;
    137 };
    138 
    139 /* Per-batch context shared by all indirect draws queued to a given batch. */
    140 
    141 struct indirect_draw_context {
    142         /* Pointer to the top of the varying heap. */
    143         mali_ptr varying_mem;
    144 };
    145 
    146 /* Indirect draw shader inputs. Those are stored in a UBO. */
    147 
    148 struct indirect_draw_inputs {
    149         /* indirect_draw_context pointer */
    150         mali_ptr draw_ctx;
    151 
    152         /* min_max_context pointer */
    153         mali_ptr min_max_ctx;
    154 
    155         /* Pointer to an array of indirect_draw_info objects */
    156         mali_ptr draw_buf;
    157 
    158         /* Pointer to an uint32_t containing the number of draws to issue */
    159         mali_ptr draw_count_ptr;
    160 
    161         /* index buffer */
    162         mali_ptr index_buf;
    163 
    164         /* {base,first}_{vertex,instance} sysvals */
    165         mali_ptr first_vertex_sysval;
    166         mali_ptr base_vertex_sysval;
    167         mali_ptr base_instance_sysval;
    168 
    169         /* Pointers to various cmdstream structs that need to be patched */
    170         mali_ptr vertex_job;
    171         mali_ptr tiler_job;
    172         mali_ptr attrib_bufs;
    173         mali_ptr attribs;
    174         mali_ptr varying_bufs;
    175         uint32_t draw_count;
    176         uint32_t draw_buf_stride;
    177         uint32_t restart_index;
    178         uint32_t attrib_count;
    179 };
    180 
    181 static nir_ssa_def *
    182 get_input_data(nir_builder *b, unsigned offset, unsigned size)
    183 {
    184         assert(!(offset & 0x3));
    185         assert(size && !(size & 0x3));
    186 
    187         return nir_load_ubo(b, 1, size,
    188                             nir_imm_int(b, 0),
    189                             nir_imm_int(b, offset),
    190                             .align_mul = 4,
    191                             .align_offset = 0,
    192                             .range_base = 0,
    193                             .range = ~0);
    194 }
    195 
    196 #define get_input_field(b, name) \
    197         get_input_data(b, offsetof(struct indirect_draw_inputs, name), \
    198                        sizeof(((struct indirect_draw_inputs *)0)->name) * 8)
    199 
    200 static nir_ssa_def *
    201 get_address(nir_builder *b, nir_ssa_def *base, nir_ssa_def *offset)
    202 {
    203         return nir_iadd(b, base, nir_u2u64(b, offset));
    204 }
    205 
    206 static nir_ssa_def *
    207 get_address_imm(nir_builder *b, nir_ssa_def *base, unsigned offset)
    208 {
    209         return get_address(b, base, nir_imm_int(b, offset));
    210 }
    211 
    212 static nir_ssa_def *
    213 load_global(nir_builder *b, nir_ssa_def *addr, unsigned ncomps, unsigned bit_size)
    214 {
    215         return nir_load_global(b, addr, 4, ncomps, bit_size);
    216 }
    217 
    218 static void
    219 store_global(nir_builder *b, nir_ssa_def *addr,
    220              nir_ssa_def *value, unsigned ncomps)
    221 {
    222         nir_store_global(b, addr, 4, value, (1 << ncomps) - 1);
    223 }
    224 
    225 static nir_ssa_def *
    226 get_draw_ctx_data(struct indirect_draw_shader_builder *builder,
    227                   unsigned offset, unsigned size)
    228 {
    229         nir_builder *b = &builder->b;
    230         return load_global(b,
    231                            get_address_imm(b, builder->draw.draw_ctx, offset),
    232                            1, size);
    233 }
    234 
    235 static void
    236 set_draw_ctx_data(struct indirect_draw_shader_builder *builder,
    237                   unsigned offset, nir_ssa_def *value, unsigned size)
    238 {
    239         nir_builder *b = &builder->b;
    240         store_global(b,
    241                      get_address_imm(b, builder->draw.draw_ctx, offset),
    242                      value, 1);
    243 }
    244 
    245 #define get_draw_ctx_field(builder, name) \
    246         get_draw_ctx_data(builder, \
    247                           offsetof(struct indirect_draw_context, name), \
    248                           sizeof(((struct indirect_draw_context *)0)->name) * 8)
    249 
    250 #define set_draw_ctx_field(builder, name, val) \
    251         set_draw_ctx_data(builder, \
    252                           offsetof(struct indirect_draw_context, name), \
    253                           val, \
    254                           sizeof(((struct indirect_draw_context *)0)->name) * 8)
    255 
    256 static nir_ssa_def *
    257 get_min_max_ctx_data(struct indirect_draw_shader_builder *builder,
    258                      unsigned offset, unsigned size)
    259 {
    260         nir_builder *b = &builder->b;
    261         return load_global(b,
    262                            get_address_imm(b, builder->draw.min_max_ctx, offset),
    263                            1, size);
    264 }
    265 
    266 #define get_min_max_ctx_field(builder, name) \
    267         get_min_max_ctx_data(builder, \
    268                              offsetof(struct min_max_context, name), \
    269                              sizeof(((struct min_max_context *)0)->name) * 8)
    270 
    271 static void
    272 update_min(struct indirect_draw_shader_builder *builder, nir_ssa_def *val)
    273 {
    274         nir_builder *b = &builder->b;
    275         nir_ssa_def *addr =
    276                 get_address_imm(b,
    277                                 builder->draw.min_max_ctx,
    278                                 offsetof(struct min_max_context, min));
    279         nir_global_atomic_umin(b, 32, addr, val);
    280 }
    281 
    282 static void
    283 update_max(struct indirect_draw_shader_builder *builder, nir_ssa_def *val)
    284 {
    285         nir_builder *b = &builder->b;
    286         nir_ssa_def *addr =
    287                 get_address_imm(b,
    288                                 builder->draw.min_max_ctx,
    289                                 offsetof(struct min_max_context, max));
    290         nir_global_atomic_umax(b, 32, addr, val);
    291 }
    292 
    293 #define get_draw_field(b, draw_ptr, field) \
    294         load_global(b, \
    295                     get_address_imm(b, draw_ptr, \
    296                                     offsetof(struct indirect_draw_info, field)), \
    297                     1, sizeof(((struct indirect_draw_info *)0)->field) * 8)
    298 
    299 #define get_indexed_draw_field(b, draw_ptr, field) \
    300         load_global(b, \
    301                     get_address_imm(b, draw_ptr, \
    302                                     offsetof(struct indirect_indexed_draw_info, field)), \
    303                     1, sizeof(((struct indirect_indexed_draw_info *)0)->field) * 8)
    304 
    305 static void
    306 extract_inputs(struct indirect_draw_shader_builder *builder)
    307 {
    308         nir_builder *b = &builder->b;
    309 
    310         builder->draw.draw_ctx = get_input_field(b, draw_ctx);
    311         builder->draw.draw_buf = get_input_field(b, draw_buf);
    312         builder->draw.draw_buf_stride = get_input_field(b, draw_buf_stride);
    313 
    314         if (builder->index_size) {
    315                 builder->draw.index_buf = get_input_field(b, index_buf);
    316                 builder->draw.min_max_ctx = get_input_field(b, min_max_ctx);
    317                 if (builder->flags & PAN_INDIRECT_DRAW_PRIMITIVE_RESTART) {
    318                         builder->draw.restart_index =
    319                                 get_input_field(b, restart_index);
    320                 }
    321         }
    322 
    323         if (builder->index_min_max_search)
    324                 return;
    325 
    326         builder->jobs.first_vertex_sysval = get_input_field(b, first_vertex_sysval);
    327         builder->jobs.base_vertex_sysval = get_input_field(b, base_vertex_sysval);
    328         builder->jobs.base_instance_sysval = get_input_field(b, base_instance_sysval);
    329         builder->jobs.vertex_job = get_input_field(b, vertex_job);
    330         builder->jobs.tiler_job = get_input_field(b, tiler_job);
    331         builder->attribs.attrib_bufs = get_input_field(b, attrib_bufs);
    332         builder->attribs.attribs = get_input_field(b, attribs);
    333         builder->attribs.attrib_count = get_input_field(b, attrib_count);
    334         builder->varyings.varying_bufs = get_input_field(b, varying_bufs);
    335         builder->varyings.mem_ptr =
    336                 nir_local_variable_create(b->impl,
    337                                           glsl_uint64_t_type(),
    338                                           "var_mem_ptr");
    339         nir_store_var(b, builder->varyings.mem_ptr,
    340                       get_draw_ctx_field(builder, varying_mem), 3);
    341 }
    342 
    343 static void
    344 init_shader_builder(struct indirect_draw_shader_builder *builder,
    345                     const struct panfrost_device *dev,
    346                     unsigned flags, unsigned index_size,
    347                     bool index_min_max_search)
    348 {
    349         memset(builder, 0, sizeof(*builder));
    350         builder->dev = dev;
    351         builder->flags = flags;
    352         builder->index_size = index_size;
    353 
    354         builder->index_min_max_search = index_min_max_search;
    355 
    356         if (index_min_max_search) {
    357                 builder->b =
    358                         nir_builder_init_simple_shader(MESA_SHADER_COMPUTE,
    359                                                        GENX(pan_shader_get_compiler_options)(),
    360                                                        "indirect_draw_min_max_index(index_size=%d)",
    361                                                        builder->index_size);
    362         } else {
    363                 builder->b =
    364                         nir_builder_init_simple_shader(MESA_SHADER_COMPUTE,
    365                                                        GENX(pan_shader_get_compiler_options)(),
    366                                                        "indirect_draw(index_size=%d%s%s%s)",
    367                                                        builder->index_size,
    368                                                        flags & PAN_INDIRECT_DRAW_HAS_PSIZ ?
    369                                                        ",psiz" : "",
    370                                                        flags & PAN_INDIRECT_DRAW_PRIMITIVE_RESTART ?
    371                                                        ",primitive_restart" : "",
    372                                                        flags & PAN_INDIRECT_DRAW_UPDATE_PRIM_SIZE ?
    373                                                        ",update_primitive_size" : "");
    374         }
    375 
    376         nir_builder *b = &builder->b;
    377         b->shader->info.internal = true;
    378         nir_variable_create(b->shader, nir_var_mem_ubo,
    379                             glsl_uint_type(), "inputs");
    380         b->shader->info.num_ubos++;
    381 
    382         extract_inputs(builder);
    383 }
    384 
    385 static void
    386 update_job(struct indirect_draw_shader_builder *builder, enum mali_job_type type)
    387 {
    388         nir_builder *b = &builder->b;
    389         nir_ssa_def *job_ptr =
    390                 type == MALI_JOB_TYPE_VERTEX ?
    391                 builder->jobs.vertex_job : builder->jobs.tiler_job;
    392 
    393         /* Update the invocation words. */
    394         store_global(b, get_address_imm(b, job_ptr, WORD(8)),
    395                      builder->jobs.invocation, 2);
    396 
    397         unsigned draw_offset =
    398                 type == MALI_JOB_TYPE_VERTEX ?
    399                 pan_section_offset(COMPUTE_JOB, DRAW) :
    400                 pan_section_offset(TILER_JOB, DRAW);
    401         unsigned prim_offset = pan_section_offset(TILER_JOB, PRIMITIVE);
    402         unsigned psiz_offset = pan_section_offset(TILER_JOB, PRIMITIVE_SIZE);
    403         unsigned index_size = builder->index_size;
    404 
    405         if (type == MALI_JOB_TYPE_TILER) {
    406                 /* Update PRIMITIVE.{base_vertex_offset,count} */
    407                 store_global(b,
    408                              get_address_imm(b, job_ptr, prim_offset + WORD(1)),
    409                              builder->jobs.base_vertex_offset, 1);
    410                 store_global(b,
    411                              get_address_imm(b, job_ptr, prim_offset + WORD(3)),
    412                              nir_iadd_imm(b, builder->draw.vertex_count, -1), 1);
    413 
    414                 if (index_size) {
    415                         nir_ssa_def *addr =
    416                                 get_address_imm(b, job_ptr, prim_offset + WORD(4));
    417                         nir_ssa_def *indices = load_global(b, addr, 1, 64);
    418                         nir_ssa_def *offset =
    419                                 nir_imul_imm(b, builder->draw.vertex_start, index_size);
    420 
    421                         indices = get_address(b, indices, offset);
    422                         store_global(b, addr, indices, 2);
    423                 }
    424 
    425                 /* Update PRIMITIVE_SIZE.size_array */
    426                 if ((builder->flags & PAN_INDIRECT_DRAW_HAS_PSIZ) &&
    427                     (builder->flags & PAN_INDIRECT_DRAW_UPDATE_PRIM_SIZE)) {
    428                         store_global(b,
    429                                      get_address_imm(b, job_ptr, psiz_offset + WORD(0)),
    430                                      builder->varyings.psiz_ptr, 2);
    431                 }
    432 
    433                 /* Update DRAW.position */
    434                 store_global(b, get_address_imm(b, job_ptr, draw_offset + WORD(4)),
    435                              builder->varyings.pos_ptr, 2);
    436         }
    437 
    438         nir_ssa_def *draw_w01 =
    439                 load_global(b, get_address_imm(b, job_ptr, draw_offset + WORD(0)), 2, 32);
    440         nir_ssa_def *draw_w0 = nir_channel(b, draw_w01, 0);
    441 
    442         /* Update DRAW.{instance_size,offset_start} */
    443         nir_ssa_def *instance_size =
    444                 nir_bcsel(b,
    445                           nir_ult(b, builder->draw.instance_count, nir_imm_int(b, 2)),
    446                           nir_imm_int(b, 0), builder->instance_size.packed);
    447         draw_w01 = nir_vec2(b,
    448                             nir_ior(b, nir_iand_imm(b, draw_w0, 0xffff),
    449                                     nir_ishl(b, instance_size, nir_imm_int(b, 16))),
    450                             builder->jobs.offset_start);
    451         store_global(b, get_address_imm(b, job_ptr, draw_offset + WORD(0)),
    452                      draw_w01, 2);
    453 }
    454 
    455 static void
    456 split_div(nir_builder *b, nir_ssa_def *div, nir_ssa_def **r_e, nir_ssa_def **d)
    457 {
    458         /* TODO: Lower this 64bit div to something GPU-friendly */
    459         nir_ssa_def *r = nir_imax(b, nir_ufind_msb(b, div), nir_imm_int(b, 0));
    460         nir_ssa_def *div64 = nir_u2u64(b, div);
    461         nir_ssa_def *half_div64 = nir_u2u64(b, nir_ushr_imm(b, div, 1));
    462         nir_ssa_def *f0 = nir_iadd(b,
    463                                    nir_ishl(b, nir_imm_int64(b, 1),
    464                                             nir_iadd_imm(b, r, 32)),
    465                                    half_div64);
    466         nir_ssa_def *fi = nir_idiv(b, f0, div64);
    467         nir_ssa_def *ff = nir_isub(b, f0, nir_imul(b, fi, div64));
    468         nir_ssa_def *e = nir_bcsel(b, nir_ult(b, half_div64, ff),
    469                                    nir_imm_int(b, 1 << 5), nir_imm_int(b, 0));
    470         *d = nir_iand_imm(b, nir_u2u32(b, fi), ~(1 << 31));
    471         *r_e = nir_ior(b, r, e);
    472 }
    473 
    474 static void
    475 update_vertex_attrib_buf(struct indirect_draw_shader_builder *builder,
    476                          nir_ssa_def *attrib_buf_ptr,
    477                          enum mali_attribute_type type,
    478                          nir_ssa_def *div1,
    479                          nir_ssa_def *div2)
    480 {
    481         nir_builder *b = &builder->b;
    482         unsigned type_mask = BITFIELD_MASK(6);
    483         nir_ssa_def *w01 = load_global(b, attrib_buf_ptr, 2, 32);
    484         nir_ssa_def *w0 = nir_channel(b, w01, 0);
    485         nir_ssa_def *w1 = nir_channel(b, w01, 1);
    486 
    487         /* Word 0 and 1 of the attribute descriptor contain the type,
    488          * pointer and the the divisor exponent.
    489          */
    490         w0 = nir_iand_imm(b, nir_channel(b, w01, 0), ~type_mask);
    491         w0 = nir_ior(b, w0, nir_imm_int(b, type));
    492         w1 = nir_ior(b, w1, nir_ishl(b, div1, nir_imm_int(b, 24)));
    493 
    494         store_global(b, attrib_buf_ptr, nir_vec2(b, w0, w1), 2);
    495 
    496         if (type == MALI_ATTRIBUTE_TYPE_1D_NPOT_DIVISOR) {
    497                 /* If the divisor is not a power of two, the divisor numerator
    498                  * is passed in word 1 of the continuation attribute (word 5
    499                  * if we consider the attribute and its continuation as a
    500                  * single attribute).
    501                  */
    502                 assert(div2);
    503                 store_global(b, get_address_imm(b, attrib_buf_ptr, WORD(5)),
    504                              div2, 1);
    505         }
    506 }
    507 
    508 static void
    509 zero_attrib_buf_stride(struct indirect_draw_shader_builder *builder,
    510                        nir_ssa_def *attrib_buf_ptr)
    511 {
    512         /* Stride is an unadorned 32-bit uint at word 2 */
    513         nir_builder *b = &builder->b;
    514         store_global(b, get_address_imm(b, attrib_buf_ptr, WORD(2)),
    515                         nir_imm_int(b, 0), 1);
    516 }
    517 
    518 static void
    519 adjust_attrib_offset(struct indirect_draw_shader_builder *builder,
    520                      nir_ssa_def *attrib_ptr, nir_ssa_def *attrib_buf_ptr,
    521                      nir_ssa_def *instance_div)
    522 {
    523         nir_builder *b = &builder->b;
    524         nir_ssa_def *zero = nir_imm_int(b, 0);
    525         nir_ssa_def *two = nir_imm_int(b, 2);
    526         nir_ssa_def *sub_cur_offset =
    527                 nir_iand(b, nir_ine(b, builder->jobs.offset_start, zero),
    528                          nir_uge(b, builder->draw.instance_count, two));
    529 
    530         nir_ssa_def *add_base_inst_offset =
    531                 nir_iand(b, nir_ine(b, builder->draw.start_instance, zero),
    532                          nir_ine(b, instance_div, zero));
    533 
    534         IF (nir_ior(b, sub_cur_offset, add_base_inst_offset)) {
    535                 nir_ssa_def *offset =
    536                         load_global(b, get_address_imm(b, attrib_ptr, WORD(1)), 1, 32);
    537                 nir_ssa_def *stride =
    538                         load_global(b, get_address_imm(b, attrib_buf_ptr, WORD(2)), 1, 32);
    539 
    540                 /* Per-instance data needs to be offset in response to a
    541                  * delayed start in an indexed draw.
    542                  */
    543 
    544                 IF (add_base_inst_offset) {
    545                         offset = nir_iadd(b, offset,
    546                                           nir_idiv(b,
    547                                                    nir_imul(b, stride,
    548                                                             builder->draw.start_instance),
    549                                                    instance_div));
    550                 } ENDIF
    551 
    552                 IF (sub_cur_offset) {
    553                         offset = nir_isub(b, offset,
    554                                           nir_imul(b, stride,
    555                                                    builder->jobs.offset_start));
    556                 } ENDIF
    557 
    558                 store_global(b, get_address_imm(b, attrib_ptr, WORD(1)),
    559                              offset, 1);
    560         } ENDIF
    561 }
    562 
    563 /* x is power of two or zero <===> x has 0 (zero) or 1 (POT) bits set */
    564 
    565 static nir_ssa_def *
    566 nir_is_power_of_two_or_zero(nir_builder *b, nir_ssa_def *x)
    567 {
    568         return nir_ult(b, nir_bit_count(b, x), nir_imm_int(b, 2));
    569 }
    570 
    571 /* Based on panfrost_emit_vertex_data() */
    572 
    573 static void
    574 update_vertex_attribs(struct indirect_draw_shader_builder *builder)
    575 {
    576         nir_builder *b = &builder->b;
    577         nir_variable *attrib_idx_var =
    578                 nir_local_variable_create(b->impl, glsl_uint_type(),
    579                                           "attrib_idx");
    580         nir_store_var(b, attrib_idx_var, nir_imm_int(b, 0), 1);
    581 
    582 #if PAN_ARCH <= 5
    583         nir_ssa_def *single_instance =
    584                 nir_ult(b, builder->draw.instance_count, nir_imm_int(b, 2));
    585 #endif
    586 
    587         LOOP {
    588                 nir_ssa_def *attrib_idx = nir_load_var(b, attrib_idx_var);
    589                 IF (nir_uge(b, attrib_idx, builder->attribs.attrib_count))
    590                         BREAK;
    591                 ENDIF
    592 
    593                 nir_ssa_def *attrib_buf_ptr =
    594                          get_address(b, builder->attribs.attrib_bufs,
    595                                      nir_imul_imm(b, attrib_idx,
    596                                                   2 * pan_size(ATTRIBUTE_BUFFER)));
    597                 nir_ssa_def *attrib_ptr =
    598                          get_address(b, builder->attribs.attribs,
    599                                      nir_imul_imm(b, attrib_idx,
    600                                                   pan_size(ATTRIBUTE)));
    601 
    602                 nir_ssa_def *r_e, *d;
    603 
    604 #if PAN_ARCH <= 5
    605                 IF (nir_ieq_imm(b, attrib_idx, PAN_VERTEX_ID)) {
    606                         nir_ssa_def *r_p =
    607                                 nir_bcsel(b, single_instance,
    608                                           nir_imm_int(b, 0x9f),
    609                                           builder->instance_size.packed);
    610 
    611                         store_global(b,
    612                                      get_address_imm(b, attrib_buf_ptr, WORD(4)),
    613                                      nir_ishl(b, r_p, nir_imm_int(b, 24)), 1);
    614 
    615                         nir_store_var(b, attrib_idx_var,
    616                                       nir_iadd_imm(b, attrib_idx, 1), 1);
    617                         CONTINUE;
    618                 } ENDIF
    619 
    620                 IF (nir_ieq_imm(b, attrib_idx, PAN_INSTANCE_ID)) {
    621                         split_div(b, builder->instance_size.padded,
    622                                   &r_e, &d);
    623                         nir_ssa_def *default_div =
    624                                 nir_ior(b, single_instance,
    625                                         nir_ult(b,
    626                                                 builder->instance_size.padded,
    627                                                 nir_imm_int(b, 2)));
    628                         r_e = nir_bcsel(b, default_div,
    629                                         nir_imm_int(b, 0x3f), r_e);
    630                         d = nir_bcsel(b, default_div,
    631                                       nir_imm_int(b, (1u << 31) - 1), d);
    632                         store_global(b,
    633                                      get_address_imm(b, attrib_buf_ptr, WORD(1)),
    634                                      nir_vec2(b, nir_ishl(b, r_e, nir_imm_int(b, 24)), d),
    635                                      2);
    636                         nir_store_var(b, attrib_idx_var,
    637                                       nir_iadd_imm(b, attrib_idx, 1), 1);
    638                         CONTINUE;
    639                 } ENDIF
    640 #endif
    641 
    642                 nir_ssa_def *instance_div =
    643                         load_global(b, get_address_imm(b, attrib_buf_ptr, WORD(7)), 1, 32);
    644 
    645                 nir_ssa_def *div = nir_imul(b, instance_div, builder->instance_size.padded);
    646 
    647                 nir_ssa_def *multi_instance =
    648                         nir_uge(b, builder->draw.instance_count, nir_imm_int(b, 2));
    649 
    650                 IF (nir_ine(b, div, nir_imm_int(b, 0))) {
    651                         IF (multi_instance) {
    652                                 IF (nir_is_power_of_two_or_zero(b, div)) {
    653                                         nir_ssa_def *exp =
    654                                                 nir_imax(b, nir_ufind_msb(b, div),
    655                                                          nir_imm_int(b, 0));
    656                                         update_vertex_attrib_buf(builder, attrib_buf_ptr,
    657                                                                  MALI_ATTRIBUTE_TYPE_1D_POT_DIVISOR,
    658                                                                  exp, NULL);
    659                                 } ELSE {
    660                                         split_div(b, div, &r_e, &d);
    661                                         update_vertex_attrib_buf(builder, attrib_buf_ptr,
    662                                                                  MALI_ATTRIBUTE_TYPE_1D_NPOT_DIVISOR,
    663                                                                  r_e, d);
    664                                 } ENDIF
    665                         } ELSE {
    666                                 /* Single instance with a non-0 divisor: all
    667                                  * accesses should point to attribute 0 */
    668                                 zero_attrib_buf_stride(builder, attrib_buf_ptr);
    669                         } ENDIF
    670 
    671                         adjust_attrib_offset(builder, attrib_ptr, attrib_buf_ptr, instance_div);
    672                 } ELSE IF (multi_instance) {
    673                         update_vertex_attrib_buf(builder, attrib_buf_ptr,
    674                                         MALI_ATTRIBUTE_TYPE_1D_MODULUS,
    675                                         builder->instance_size.packed, NULL);
    676                 } ENDIF ENDIF
    677 
    678                 nir_store_var(b, attrib_idx_var, nir_iadd_imm(b, attrib_idx, 1), 1);
    679         }
    680 }
    681 
    682 static nir_ssa_def *
    683 update_varying_buf(struct indirect_draw_shader_builder *builder,
    684                    nir_ssa_def *varying_buf_ptr,
    685                    nir_ssa_def *vertex_count)
    686 {
    687         nir_builder *b = &builder->b;
    688 
    689         nir_ssa_def *stride =
    690                 load_global(b, get_address_imm(b, varying_buf_ptr, WORD(2)), 1, 32);
    691         nir_ssa_def *size = nir_imul(b, stride, vertex_count);
    692         nir_ssa_def *aligned_size =
    693                 nir_iand_imm(b, nir_iadd_imm(b, size, 63), ~63);
    694         nir_ssa_def *var_mem_ptr =
    695                 nir_load_var(b, builder->varyings.mem_ptr);
    696         nir_ssa_def *w0 =
    697                 nir_ior(b, nir_unpack_64_2x32_split_x(b, var_mem_ptr),
    698                         nir_imm_int(b, MALI_ATTRIBUTE_TYPE_1D));
    699         nir_ssa_def *w1 = nir_unpack_64_2x32_split_y(b, var_mem_ptr);
    700         store_global(b, get_address_imm(b, varying_buf_ptr, WORD(0)),
    701                      nir_vec4(b, w0, w1, stride, size), 4);
    702 
    703         nir_store_var(b, builder->varyings.mem_ptr,
    704                       get_address(b, var_mem_ptr, aligned_size), 3);
    705 
    706         return var_mem_ptr;
    707 }
    708 
    709 /* Based on panfrost_emit_varying_descriptor() */
    710 
    711 static void
    712 update_varyings(struct indirect_draw_shader_builder *builder)
    713 {
    714         nir_builder *b = &builder->b;
    715         nir_ssa_def *vertex_count =
    716                 nir_imul(b, builder->instance_size.padded,
    717                          builder->draw.instance_count);
    718         nir_ssa_def *buf_ptr =
    719                 get_address_imm(b, builder->varyings.varying_bufs,
    720                                 PAN_VARY_GENERAL *
    721                                 pan_size(ATTRIBUTE_BUFFER));
    722         update_varying_buf(builder, buf_ptr, vertex_count);
    723 
    724         buf_ptr = get_address_imm(b, builder->varyings.varying_bufs,
    725                                   PAN_VARY_POSITION *
    726                                   pan_size(ATTRIBUTE_BUFFER));
    727         builder->varyings.pos_ptr =
    728                 update_varying_buf(builder, buf_ptr, vertex_count);
    729 
    730         if (builder->flags & PAN_INDIRECT_DRAW_HAS_PSIZ) {
    731                 buf_ptr = get_address_imm(b, builder->varyings.varying_bufs,
    732                                           PAN_VARY_PSIZ *
    733                                           pan_size(ATTRIBUTE_BUFFER));
    734                 builder->varyings.psiz_ptr =
    735                         update_varying_buf(builder, buf_ptr, vertex_count);
    736         }
    737 
    738         set_draw_ctx_field(builder, varying_mem,
    739                            nir_load_var(b, builder->varyings.mem_ptr));
    740 }
    741 
    742 /* Based on panfrost_pack_work_groups_compute() */
    743 
    744 static void
    745 get_invocation(struct indirect_draw_shader_builder *builder)
    746 {
    747         nir_builder *b = &builder->b;
    748         nir_ssa_def *one = nir_imm_int(b, 1);
    749         nir_ssa_def *max_vertex =
    750                 nir_usub_sat(b, builder->instance_size.raw, one);
    751         nir_ssa_def *max_instance =
    752                 nir_usub_sat(b, builder->draw.instance_count, one);
    753         nir_ssa_def *split =
    754                 nir_bcsel(b, nir_ieq_imm(b, max_instance, 0),
    755                           nir_imm_int(b, 32),
    756                           nir_iadd_imm(b, nir_ufind_msb(b, max_vertex), 1));
    757 
    758         builder->jobs.invocation =
    759                 nir_vec2(b,
    760                          nir_ior(b, max_vertex,
    761                                  nir_ishl(b, max_instance, split)),
    762                          nir_ior(b, nir_ishl(b, split, nir_imm_int(b, 22)),
    763                                  nir_imm_int(b, 2 << 28)));
    764 }
    765 
    766 /* Based on panfrost_padded_vertex_count() */
    767 
    768 static nir_ssa_def *
    769 get_padded_count(nir_builder *b, nir_ssa_def *val, nir_ssa_def **packed)
    770 {
    771         nir_ssa_def *one = nir_imm_int(b, 1);
    772         nir_ssa_def *zero = nir_imm_int(b, 0);
    773         nir_ssa_def *eleven = nir_imm_int(b, 11);
    774         nir_ssa_def *four = nir_imm_int(b, 4);
    775 
    776         nir_ssa_def *exp =
    777                 nir_usub_sat(b, nir_imax(b, nir_ufind_msb(b, val), zero), four);
    778         nir_ssa_def *base = nir_ushr(b, val, exp);
    779 
    780         base = nir_iadd(b, base,
    781                         nir_bcsel(b, nir_ine(b, val, nir_ishl(b, base, exp)), one, zero));
    782 
    783         nir_ssa_def *rshift = nir_imax(b, nir_find_lsb(b, base), zero);
    784         exp = nir_iadd(b, exp, rshift);
    785         base = nir_ushr(b, base, rshift);
    786         base = nir_iadd(b, base, nir_bcsel(b, nir_uge(b, base, eleven), one, zero));
    787         rshift = nir_imax(b, nir_find_lsb(b, base), zero);
    788         exp = nir_iadd(b, exp, rshift);
    789         base = nir_ushr(b, base, rshift);
    790 
    791         *packed = nir_ior(b, exp,
    792                           nir_ishl(b, nir_ushr_imm(b, base, 1), nir_imm_int(b, 5)));
    793         return nir_ishl(b, base, exp);
    794 }
    795 
    796 static void
    797 update_jobs(struct indirect_draw_shader_builder *builder)
    798 {
    799         get_invocation(builder);
    800         update_job(builder, MALI_JOB_TYPE_VERTEX);
    801         update_job(builder, MALI_JOB_TYPE_TILER);
    802 }
    803 
    804 
    805 static void
    806 set_null_job(struct indirect_draw_shader_builder *builder,
    807              nir_ssa_def *job_ptr)
    808 {
    809         nir_builder *b = &builder->b;
    810         nir_ssa_def *w4 = get_address_imm(b, job_ptr, WORD(4));
    811         nir_ssa_def *val = load_global(b, w4, 1, 32);
    812 
    813         /* Set job type to NULL (AKA NOOP) */
    814         val = nir_ior(b, nir_iand_imm(b, val, 0xffffff01),
    815                       nir_imm_int(b, MALI_JOB_TYPE_NULL << 1));
    816         store_global(b, w4, val, 1);
    817 }
    818 
    819 static void
    820 get_instance_size(struct indirect_draw_shader_builder *builder)
    821 {
    822         nir_builder *b = &builder->b;
    823 
    824         if (!builder->index_size) {
    825                 builder->jobs.base_vertex_offset = nir_imm_int(b, 0);
    826                 builder->jobs.offset_start = builder->draw.vertex_start;
    827                 builder->instance_size.raw = builder->draw.vertex_count;
    828                 return;
    829         }
    830 
    831         unsigned index_size = builder->index_size;
    832         nir_ssa_def *min = get_min_max_ctx_field(builder, min);
    833         nir_ssa_def *max = get_min_max_ctx_field(builder, max);
    834 
    835         /* We handle unaligned indices here to avoid the extra complexity in
    836          * the min/max search job.
    837          */
    838         if (builder->index_size < 4) {
    839                 nir_variable *min_var =
    840                         nir_local_variable_create(b->impl, glsl_uint_type(), "min");
    841                 nir_store_var(b, min_var, min, 1);
    842                 nir_variable *max_var =
    843                         nir_local_variable_create(b->impl, glsl_uint_type(), "max");
    844                 nir_store_var(b, max_var, max, 1);
    845 
    846                 nir_ssa_def *base =
    847                         get_address(b, builder->draw.index_buf,
    848                                     nir_imul_imm(b, builder->draw.vertex_start, index_size));
    849                 nir_ssa_def *offset = nir_iand_imm(b, nir_unpack_64_2x32_split_x(b, base), 3);
    850                 nir_ssa_def *end =
    851                         nir_iadd(b, offset,
    852                                  nir_imul_imm(b, builder->draw.vertex_count, index_size));
    853                 nir_ssa_def *aligned_end = nir_iand_imm(b, end, ~3);
    854                 unsigned shift = index_size * 8;
    855                 unsigned mask = (1 << shift) - 1;
    856 
    857                 base = nir_iand(b, base, nir_imm_int64(b, ~3ULL));
    858 
    859                 /* Unaligned start offset, we need to ignore any data that's
    860                  * outside the requested range. We also handle ranges that are
    861                  * covering less than 2 words here.
    862                  */
    863                 IF (nir_ior(b, nir_ine(b, offset, nir_imm_int(b, 0)), nir_ieq(b, aligned_end, nir_imm_int(b, 0)))) {
    864                         min = nir_load_var(b, min_var);
    865                         max = nir_load_var(b, max_var);
    866 
    867                         nir_ssa_def *val = load_global(b, base, 1, 32);
    868                         for (unsigned i = 0; i < sizeof(uint32_t); i += index_size) {
    869                                 nir_ssa_def *oob =
    870                                         nir_ior(b,
    871                                                 nir_ult(b, nir_imm_int(b, i), offset),
    872                                                 nir_uge(b, nir_imm_int(b, i), end));
    873                                 nir_ssa_def *data = nir_iand_imm(b, val, mask);
    874 
    875                                 min = nir_umin(b, min,
    876                                                nir_bcsel(b, oob, nir_imm_int(b, UINT32_MAX), data));
    877                                 max = nir_umax(b, max,
    878                                                nir_bcsel(b, oob, nir_imm_int(b, 0), data));
    879                                 val = nir_ushr_imm(b, val, shift);
    880                         }
    881 
    882                         nir_store_var(b, min_var, min, 1);
    883                         nir_store_var(b, max_var, max, 1);
    884                 } ENDIF
    885 
    886                 nir_ssa_def *remaining = nir_isub(b, end, aligned_end);
    887 
    888                 /* The last word contains less than 4bytes of data, we need to
    889                  * discard anything falling outside the requested range.
    890                  */
    891                 IF (nir_iand(b, nir_ine(b, end, aligned_end), nir_ine(b, aligned_end, nir_imm_int(b, 0)))) {
    892                         min = nir_load_var(b, min_var);
    893                         max = nir_load_var(b, max_var);
    894 
    895                         nir_ssa_def *val = load_global(b, get_address(b, base, aligned_end), 1, 32);
    896                         for (unsigned i = 0; i < sizeof(uint32_t); i += index_size) {
    897                                 nir_ssa_def *oob = nir_uge(b, nir_imm_int(b, i), remaining);
    898                                 nir_ssa_def *data = nir_iand_imm(b, val, mask);
    899 
    900                                 min = nir_umin(b, min,
    901                                                nir_bcsel(b, oob, nir_imm_int(b, UINT32_MAX), data));
    902                                 max = nir_umax(b, max,
    903                                                nir_bcsel(b, oob, nir_imm_int(b, 0), data));
    904                                 val = nir_ushr_imm(b, val, shift);
    905                         }
    906 
    907                         nir_store_var(b, min_var, min, 1);
    908                         nir_store_var(b, max_var, max, 1);
    909                 } ENDIF
    910 
    911                 min = nir_load_var(b, min_var);
    912                 max = nir_load_var(b, max_var);
    913         }
    914 
    915         builder->jobs.base_vertex_offset = nir_ineg(b, min);
    916         builder->jobs.offset_start = nir_iadd(b, min, builder->draw.index_bias);
    917         builder->instance_size.raw = nir_iadd_imm(b, nir_usub_sat(b, max, min), 1);
    918 }
    919 
    920 /* Patch a draw sequence */
    921 
    922 static void
    923 patch(struct indirect_draw_shader_builder *builder)
    924 {
    925         unsigned index_size = builder->index_size;
    926         nir_builder *b = &builder->b;
    927 
    928         nir_ssa_def *draw_ptr = builder->draw.draw_buf;
    929 
    930         if (index_size) {
    931                 builder->draw.vertex_count = get_indexed_draw_field(b, draw_ptr, count);
    932                 builder->draw.start_instance = get_indexed_draw_field(b, draw_ptr, start_instance);
    933                 builder->draw.instance_count =
    934                         get_indexed_draw_field(b, draw_ptr, instance_count);
    935                 builder->draw.vertex_start = get_indexed_draw_field(b, draw_ptr, start);
    936                 builder->draw.index_bias = get_indexed_draw_field(b, draw_ptr, index_bias);
    937         } else {
    938                 builder->draw.vertex_count = get_draw_field(b, draw_ptr, count);
    939                 builder->draw.start_instance = get_draw_field(b, draw_ptr, start_instance);
    940                 builder->draw.instance_count = get_draw_field(b, draw_ptr, instance_count);
    941                 builder->draw.vertex_start = get_draw_field(b, draw_ptr, start);
    942         }
    943 
    944         assert(builder->draw.vertex_count->num_components);
    945 
    946         nir_ssa_def *num_vertices =
    947                 nir_imul(b, builder->draw.vertex_count, builder->draw.instance_count);
    948 
    949         IF (nir_ieq(b, num_vertices, nir_imm_int(b, 0))) {
    950                 /* If there's nothing to draw, turn the vertex/tiler jobs into
    951                  * null jobs.
    952                  */
    953                 set_null_job(builder, builder->jobs.vertex_job);
    954                 set_null_job(builder, builder->jobs.tiler_job);
    955         } ELSE {
    956                 get_instance_size(builder);
    957 
    958                 builder->instance_size.padded =
    959                         get_padded_count(b, builder->instance_size.raw,
    960                                          &builder->instance_size.packed);
    961 
    962                 update_varyings(builder);
    963                 update_jobs(builder);
    964                 update_vertex_attribs(builder);
    965 
    966                 IF (nir_ine(b, builder->jobs.first_vertex_sysval, nir_imm_int64(b, 0))) {
    967                         store_global(b, builder->jobs.first_vertex_sysval,
    968                                      builder->jobs.offset_start, 1);
    969                 } ENDIF
    970 
    971                 IF (nir_ine(b, builder->jobs.base_vertex_sysval, nir_imm_int64(b, 0))) {
    972                         store_global(b, builder->jobs.base_vertex_sysval,
    973                                      index_size ?
    974                                      builder->draw.index_bias :
    975                                      nir_imm_int(b, 0),
    976                                      1);
    977                 } ENDIF
    978 
    979                 IF (nir_ine(b, builder->jobs.base_instance_sysval, nir_imm_int64(b, 0))) {
    980                         store_global(b, builder->jobs.base_instance_sysval,
    981                                      builder->draw.start_instance, 1);
    982                 } ENDIF
    983         } ENDIF
    984 }
    985 
    986 /* Search the min/max index in the range covered by the indirect draw call */
    987 
    988 static void
    989 get_index_min_max(struct indirect_draw_shader_builder *builder)
    990 {
    991         nir_ssa_def *restart_index = builder->draw.restart_index;
    992         unsigned index_size = builder->index_size;
    993         nir_builder *b = &builder->b;
    994 
    995         nir_ssa_def *draw_ptr = builder->draw.draw_buf;
    996 
    997         builder->draw.vertex_count = get_draw_field(b, draw_ptr, count);
    998         builder->draw.vertex_start = get_draw_field(b, draw_ptr, start);
    999 
   1000         nir_ssa_def *thread_id = nir_channel(b, nir_load_global_invocation_id(b, 32), 0);
   1001         nir_variable *min_var =
   1002                 nir_local_variable_create(b->impl, glsl_uint_type(), "min");
   1003         nir_store_var(b, min_var, nir_imm_int(b, UINT32_MAX), 1);
   1004         nir_variable *max_var =
   1005                 nir_local_variable_create(b->impl, glsl_uint_type(), "max");
   1006         nir_store_var(b, max_var, nir_imm_int(b, 0), 1);
   1007 
   1008         nir_ssa_def *base =
   1009                 get_address(b, builder->draw.index_buf,
   1010                             nir_imul_imm(b, builder->draw.vertex_start, index_size));
   1011 
   1012 
   1013         nir_ssa_def *start = nir_iand_imm(b, nir_unpack_64_2x32_split_x(b, base), 3);
   1014         nir_ssa_def *end =
   1015                 nir_iadd(b, start, nir_imul_imm(b, builder->draw.vertex_count, index_size));
   1016 
   1017         base = nir_iand(b, base, nir_imm_int64(b, ~3ULL));
   1018 
   1019         /* Align on 4 bytes, non-aligned indices are handled in the indirect draw job. */
   1020         start = nir_iand_imm(b, nir_iadd_imm(b, start, 3), ~3);
   1021         end = nir_iand_imm(b, end, ~3);
   1022 
   1023         /* Add the job offset. */
   1024         start = nir_iadd(b, start, nir_imul_imm(b, thread_id, sizeof(uint32_t)));
   1025 
   1026         nir_variable *offset_var =
   1027                 nir_local_variable_create(b->impl, glsl_uint_type(), "offset");
   1028         nir_store_var(b, offset_var, start, 1);
   1029 
   1030         LOOP {
   1031                 nir_ssa_def *offset = nir_load_var(b, offset_var);
   1032                 IF (nir_uge(b, offset, end))
   1033                         BREAK;
   1034                 ENDIF
   1035 
   1036                 nir_ssa_def *val = load_global(b, get_address(b, base, offset), 1, 32);
   1037                 nir_ssa_def *old_min = nir_load_var(b, min_var);
   1038                 nir_ssa_def *old_max = nir_load_var(b, max_var);
   1039                 nir_ssa_def *new_min;
   1040                 nir_ssa_def *new_max;
   1041 
   1042                 /* TODO: use 8/16 bit arithmetic when index_size < 4. */
   1043                 for (unsigned i = 0; i < 4; i += index_size) {
   1044                         nir_ssa_def *data = nir_ushr_imm(b, val, i * 8);
   1045                         data = nir_iand_imm(b, data, (1ULL << (index_size * 8)) - 1);
   1046                         new_min = nir_umin(b, old_min, data);
   1047                         new_max = nir_umax(b, old_max, data);
   1048                         if (restart_index) {
   1049                                 new_min = nir_bcsel(b, nir_ine(b, restart_index, data), new_min, old_min);
   1050                                 new_max = nir_bcsel(b, nir_ine(b, restart_index, data), new_max, old_max);
   1051                         }
   1052                         old_min = new_min;
   1053                         old_max = new_max;
   1054                 }
   1055 
   1056                 nir_store_var(b, min_var, new_min, 1);
   1057                 nir_store_var(b, max_var, new_max, 1);
   1058                 nir_store_var(b, offset_var,
   1059                               nir_iadd_imm(b, offset, MIN_MAX_JOBS * sizeof(uint32_t)), 1);
   1060         }
   1061 
   1062         IF (nir_ult(b, start, end))
   1063                 update_min(builder, nir_load_var(b, min_var));
   1064                 update_max(builder, nir_load_var(b, max_var));
   1065         ENDIF
   1066 }
   1067 
   1068 static unsigned
   1069 get_shader_id(unsigned flags, unsigned index_size, bool index_min_max_search)
   1070 {
   1071         if (!index_min_max_search) {
   1072                 flags &= PAN_INDIRECT_DRAW_FLAGS_MASK;
   1073                 flags &= ~PAN_INDIRECT_DRAW_INDEX_SIZE_MASK;
   1074                 if (index_size)
   1075                         flags |= (util_logbase2(index_size) + 1);
   1076                 return flags;
   1077         }
   1078 
   1079         return ((flags & PAN_INDIRECT_DRAW_PRIMITIVE_RESTART) ?
   1080                 PAN_INDIRECT_DRAW_MIN_MAX_SEARCH_1B_INDEX_PRIM_RESTART :
   1081                 PAN_INDIRECT_DRAW_MIN_MAX_SEARCH_1B_INDEX) +
   1082                util_logbase2(index_size);
   1083 }
   1084 
   1085 static void
   1086 create_indirect_draw_shader(struct panfrost_device *dev,
   1087                             unsigned flags, unsigned index_size,
   1088                             bool index_min_max_search)
   1089 {
   1090         assert(flags < PAN_INDIRECT_DRAW_NUM_SHADERS);
   1091         struct indirect_draw_shader_builder builder;
   1092         init_shader_builder(&builder, dev, flags, index_size, index_min_max_search);
   1093 
   1094         nir_builder *b = &builder.b;
   1095 
   1096         if (index_min_max_search)
   1097                 get_index_min_max(&builder);
   1098         else
   1099                 patch(&builder);
   1100 
   1101         struct panfrost_compile_inputs inputs = { .gpu_id = dev->gpu_id };
   1102         struct pan_shader_info shader_info;
   1103         struct util_dynarray binary;
   1104 
   1105         util_dynarray_init(&binary, NULL);
   1106         GENX(pan_shader_compile)(b->shader, &inputs, &binary, &shader_info);
   1107 
   1108         assert(!shader_info.tls_size);
   1109         assert(!shader_info.wls_size);
   1110         assert(!shader_info.sysvals.sysval_count);
   1111 
   1112         unsigned shader_id = get_shader_id(flags, index_size, index_min_max_search);
   1113         struct pan_indirect_draw_shader *draw_shader =
   1114                 &dev->indirect_draw_shaders.shaders[shader_id];
   1115         void *state = dev->indirect_draw_shaders.states->ptr.cpu +
   1116                       (shader_id * pan_size(RENDERER_STATE));
   1117 
   1118         pthread_mutex_lock(&dev->indirect_draw_shaders.lock);
   1119         if (!draw_shader->rsd) {
   1120                 mali_ptr address =
   1121                         pan_pool_upload_aligned(dev->indirect_draw_shaders.bin_pool,
   1122                                                 binary.data, binary.size,
   1123                                                 PAN_ARCH >= 6 ? 128 : 64);
   1124 
   1125 #if PAN_ARCH <= 5
   1126                 address |= shader_info.midgard.first_tag;
   1127 #endif
   1128 
   1129                 util_dynarray_fini(&binary);
   1130 
   1131                 pan_pack(state, RENDERER_STATE, cfg) {
   1132                         pan_shader_prepare_rsd(&shader_info, address, &cfg);
   1133                 }
   1134 
   1135                 draw_shader->push = shader_info.push;
   1136                 draw_shader->rsd = dev->indirect_draw_shaders.states->ptr.gpu +
   1137                                    (shader_id * pan_size(RENDERER_STATE));
   1138         }
   1139         pthread_mutex_unlock(&dev->indirect_draw_shaders.lock);
   1140 
   1141         ralloc_free(b->shader);
   1142 }
   1143 
   1144 static mali_ptr
   1145 get_renderer_state(struct panfrost_device *dev, unsigned flags,
   1146                    unsigned index_size, bool index_min_max_search)
   1147 {
   1148         unsigned shader_id = get_shader_id(flags, index_size, index_min_max_search);
   1149         struct pan_indirect_draw_shader *info =
   1150                 &dev->indirect_draw_shaders.shaders[shader_id];
   1151 
   1152         if (!info->rsd) {
   1153                 create_indirect_draw_shader(dev, flags, index_size,
   1154                                             index_min_max_search);
   1155                 assert(info->rsd);
   1156         }
   1157 
   1158         return info->rsd;
   1159 }
   1160 
   1161 static mali_ptr
   1162 get_tls(const struct panfrost_device *dev)
   1163 {
   1164         return dev->indirect_draw_shaders.states->ptr.gpu +
   1165                (PAN_INDIRECT_DRAW_NUM_SHADERS * pan_size(RENDERER_STATE));
   1166 }
   1167 
   1168 static mali_ptr
   1169 get_ubos(struct pan_pool *pool,
   1170          const struct indirect_draw_inputs *inputs)
   1171 {
   1172         struct panfrost_ptr inputs_buf =
   1173                 pan_pool_alloc_aligned(pool, sizeof(*inputs), 16);
   1174 
   1175         memcpy(inputs_buf.cpu, inputs, sizeof(*inputs));
   1176 
   1177         struct panfrost_ptr ubos_buf =
   1178                 pan_pool_alloc_desc(pool, UNIFORM_BUFFER);
   1179 
   1180         pan_pack(ubos_buf.cpu, UNIFORM_BUFFER, cfg) {
   1181                 cfg.entries = DIV_ROUND_UP(sizeof(*inputs), 16);
   1182                 cfg.pointer = inputs_buf.gpu;
   1183         }
   1184 
   1185         return ubos_buf.gpu;
   1186 }
   1187 
   1188 static mali_ptr
   1189 get_push_uniforms(struct pan_pool *pool,
   1190                   const struct pan_indirect_draw_shader *shader,
   1191                   const struct indirect_draw_inputs *inputs)
   1192 {
   1193         if (!shader->push.count)
   1194                 return 0;
   1195 
   1196         struct panfrost_ptr push_consts_buf =
   1197                 pan_pool_alloc_aligned(pool, shader->push.count * 4, 16);
   1198         uint32_t *out = push_consts_buf.cpu;
   1199         uint8_t *in = (uint8_t *)inputs;
   1200 
   1201         for (unsigned i = 0; i < shader->push.count; ++i)
   1202                 memcpy(out + i, in + shader->push.words[i].offset, 4);
   1203 
   1204         return push_consts_buf.gpu;
   1205 }
   1206 
   1207 static void
   1208 panfrost_indirect_draw_alloc_deps(struct panfrost_device *dev)
   1209 {
   1210         pthread_mutex_lock(&dev->indirect_draw_shaders.lock);
   1211         if (dev->indirect_draw_shaders.states)
   1212                 goto out;
   1213 
   1214         unsigned state_bo_size = (PAN_INDIRECT_DRAW_NUM_SHADERS *
   1215                                   pan_size(RENDERER_STATE)) +
   1216                                  pan_size(LOCAL_STORAGE);
   1217 
   1218         dev->indirect_draw_shaders.states =
   1219                 panfrost_bo_create(dev, state_bo_size, 0, "Indirect draw states");
   1220 
   1221         /* Prepare the thread storage descriptor now since it's invariant. */
   1222         void *tsd = dev->indirect_draw_shaders.states->ptr.cpu +
   1223                     (PAN_INDIRECT_DRAW_NUM_SHADERS * pan_size(RENDERER_STATE));
   1224         pan_pack(tsd, LOCAL_STORAGE, ls) {
   1225                 ls.wls_instances = MALI_LOCAL_STORAGE_NO_WORKGROUP_MEM;
   1226         };
   1227 
   1228         /* FIXME: Currently allocating 512M of growable memory, meaning that we
   1229          * only allocate what we really use, the problem is:
   1230          * - allocation happens 2M at a time, which might be more than we
   1231          *   actually need
   1232          * - the memory is attached to the device to speed up subsequent
   1233          *   indirect draws, but that also means it's never shrinked
   1234          */
   1235         dev->indirect_draw_shaders.varying_heap =
   1236                 panfrost_bo_create(dev, 512 * 1024 * 1024,
   1237                                    PAN_BO_INVISIBLE | PAN_BO_GROWABLE,
   1238                                    "Indirect draw varying heap");
   1239 
   1240 out:
   1241         pthread_mutex_unlock(&dev->indirect_draw_shaders.lock);
   1242 }
   1243 
   1244 static unsigned
   1245 panfrost_emit_index_min_max_search(struct pan_pool *pool,
   1246                                    struct pan_scoreboard *scoreboard,
   1247                                    const struct pan_indirect_draw_info *draw_info,
   1248                                    const struct indirect_draw_inputs *inputs,
   1249                                    struct indirect_draw_context *draw_ctx,
   1250                                    mali_ptr ubos)
   1251 {
   1252         struct panfrost_device *dev = pool->dev;
   1253         unsigned index_size = draw_info->index_size;
   1254 
   1255         if (!index_size)
   1256                 return 0;
   1257 
   1258         mali_ptr rsd =
   1259                 get_renderer_state(dev, draw_info->flags,
   1260                                    draw_info->index_size, true);
   1261         unsigned shader_id =
   1262                 get_shader_id(draw_info->flags, draw_info->index_size, true);
   1263         const struct pan_indirect_draw_shader *shader =
   1264                 &dev->indirect_draw_shaders.shaders[shader_id];
   1265         struct panfrost_ptr job =
   1266                 pan_pool_alloc_desc(pool, COMPUTE_JOB);
   1267         void *invocation =
   1268                 pan_section_ptr(job.cpu, COMPUTE_JOB, INVOCATION);
   1269         panfrost_pack_work_groups_compute(invocation,
   1270                                           1, 1, 1, MIN_MAX_JOBS, 1, 1,
   1271                                           false, false);
   1272 
   1273         pan_section_pack(job.cpu, COMPUTE_JOB, PARAMETERS, cfg) {
   1274                 cfg.job_task_split = 7;
   1275         }
   1276 
   1277         pan_section_pack(job.cpu, COMPUTE_JOB, DRAW, cfg) {
   1278                 cfg.draw_descriptor_is_64b = true;
   1279                 cfg.state = rsd;
   1280                 cfg.thread_storage = get_tls(pool->dev);
   1281                 cfg.uniform_buffers = ubos;
   1282                 cfg.push_uniforms = get_push_uniforms(pool, shader, inputs);
   1283         }
   1284 
   1285         return panfrost_add_job(pool, scoreboard, MALI_JOB_TYPE_COMPUTE,
   1286                                 false, false, 0, 0, &job, false);
   1287 }
   1288 
   1289 unsigned
   1290 GENX(panfrost_emit_indirect_draw)(struct pan_pool *pool,
   1291                                   struct pan_scoreboard *scoreboard,
   1292                                   const struct pan_indirect_draw_info *draw_info,
   1293                                   struct panfrost_ptr *ctx)
   1294 {
   1295         struct panfrost_device *dev = pool->dev;
   1296 
   1297         /* Currently only tested on Bifrost, but the logic should be the same
   1298          * on Midgard.
   1299          */
   1300         assert(pan_is_bifrost(dev));
   1301 
   1302         panfrost_indirect_draw_alloc_deps(dev);
   1303 
   1304         struct panfrost_ptr job =
   1305                 pan_pool_alloc_desc(pool, COMPUTE_JOB);
   1306         mali_ptr rsd =
   1307                 get_renderer_state(dev, draw_info->flags,
   1308                                    draw_info->index_size, false);
   1309 
   1310         struct indirect_draw_context draw_ctx = {
   1311                 .varying_mem = dev->indirect_draw_shaders.varying_heap->ptr.gpu,
   1312         };
   1313 
   1314         struct panfrost_ptr draw_ctx_ptr = *ctx;
   1315         if (!draw_ctx_ptr.cpu) {
   1316                 draw_ctx_ptr = pan_pool_alloc_aligned(pool,
   1317                                                       sizeof(draw_ctx),
   1318                                                       sizeof(mali_ptr));
   1319         }
   1320 
   1321         struct indirect_draw_inputs inputs = {
   1322                 .draw_ctx = draw_ctx_ptr.gpu,
   1323                 .draw_buf = draw_info->draw_buf,
   1324                 .index_buf = draw_info->index_buf,
   1325                 .first_vertex_sysval = draw_info->first_vertex_sysval,
   1326                 .base_vertex_sysval = draw_info->base_vertex_sysval,
   1327                 .base_instance_sysval = draw_info->base_instance_sysval,
   1328                 .vertex_job = draw_info->vertex_job,
   1329                 .tiler_job = draw_info->tiler_job,
   1330                 .attrib_bufs = draw_info->attrib_bufs,
   1331                 .attribs = draw_info->attribs,
   1332                 .varying_bufs = draw_info->varying_bufs,
   1333                 .attrib_count = draw_info->attrib_count,
   1334         };
   1335 
   1336         if (draw_info->index_size) {
   1337                 inputs.restart_index = draw_info->restart_index;
   1338 
   1339                 struct panfrost_ptr min_max_ctx_ptr =
   1340                         pan_pool_alloc_aligned(pool,
   1341                                                sizeof(struct min_max_context),
   1342                                                4);
   1343                 struct min_max_context *ctx = min_max_ctx_ptr.cpu;
   1344 
   1345                 ctx->min = UINT32_MAX;
   1346                 ctx->max = 0;
   1347                 inputs.min_max_ctx = min_max_ctx_ptr.gpu;
   1348         }
   1349 
   1350         unsigned shader_id =
   1351                 get_shader_id(draw_info->flags, draw_info->index_size, false);
   1352         const struct pan_indirect_draw_shader *shader =
   1353                 &dev->indirect_draw_shaders.shaders[shader_id];
   1354         mali_ptr ubos = get_ubos(pool, &inputs);
   1355 
   1356         void *invocation =
   1357                 pan_section_ptr(job.cpu, COMPUTE_JOB, INVOCATION);
   1358         panfrost_pack_work_groups_compute(invocation,
   1359                                           1, 1, 1, 1, 1, 1,
   1360                                           false, false);
   1361 
   1362         pan_section_pack(job.cpu, COMPUTE_JOB, PARAMETERS, cfg) {
   1363                 cfg.job_task_split = 2;
   1364         }
   1365 
   1366         pan_section_pack(job.cpu, COMPUTE_JOB, DRAW, cfg) {
   1367                 cfg.draw_descriptor_is_64b = true;
   1368                 cfg.state = rsd;
   1369                 cfg.thread_storage = get_tls(pool->dev);
   1370                 cfg.uniform_buffers = ubos;
   1371                 cfg.push_uniforms = get_push_uniforms(pool, shader, &inputs);
   1372         }
   1373 
   1374         unsigned global_dep = draw_info->last_indirect_draw;
   1375         unsigned local_dep =
   1376                 panfrost_emit_index_min_max_search(pool, scoreboard, draw_info,
   1377                                                    &inputs, &draw_ctx, ubos);
   1378 
   1379         if (!ctx->cpu) {
   1380                 *ctx = draw_ctx_ptr;
   1381                 memcpy(ctx->cpu, &draw_ctx, sizeof(draw_ctx));
   1382         }
   1383 
   1384         return panfrost_add_job(pool, scoreboard, MALI_JOB_TYPE_COMPUTE,
   1385                                 false, true, local_dep, global_dep,
   1386                                 &job, false);
   1387 }
   1388 
   1389 void
   1390 GENX(panfrost_init_indirect_draw_shaders)(struct panfrost_device *dev,
   1391                                           struct pan_pool *bin_pool)
   1392 {
   1393         /* We allocate the states and varying_heap BO lazily to avoid
   1394          * reserving memory when indirect draws are not used.
   1395          */
   1396         pthread_mutex_init(&dev->indirect_draw_shaders.lock, NULL);
   1397         dev->indirect_draw_shaders.bin_pool = bin_pool;
   1398 }
   1399 
   1400 void
   1401 GENX(panfrost_cleanup_indirect_draw_shaders)(struct panfrost_device *dev)
   1402 {
   1403         panfrost_bo_unreference(dev->indirect_draw_shaders.states);
   1404         panfrost_bo_unreference(dev->indirect_draw_shaders.varying_heap);
   1405         pthread_mutex_destroy(&dev->indirect_draw_shaders.lock);
   1406 }
   1407