pan/midgard: Lower SSBOs in NIR
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Tue, 5 Nov 2019 13:59:49 +0000 (08:59 -0500)
committerMarge Bot <eric+marge@anholt.net>
Mon, 24 Feb 2020 13:56:59 +0000 (13:56 +0000)
We need to lower SSBOs to globals regardless. Rather than do this in our
backend like we do now, use the common NIR pass, which will support
bounds checking.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3775>

src/panfrost/midgard/midgard_compile.c

index 8aa54bfb0a21dcac047b0ea06a745c894cf8cf71..8f1911d22ef2a3a371a7ba6538eeb773747555e1 100644 (file)
@@ -295,14 +295,11 @@ midgard_nir_lower_fdot2_body(nir_builder *b, nir_alu_instr *alu)
         nir_ssa_def_rewrite_uses(&alu->dest.dest.ssa, nir_src_for_ssa(sum));
 }
 
+/* TODO: ssbo_size */
 static int
 midgard_sysval_for_ssbo(nir_intrinsic_instr *instr)
 {
-        /* This is way too meta */
-        bool is_store = instr->intrinsic == nir_intrinsic_store_ssbo;
-        unsigned idx_idx = is_store ? 1 : 0;
-
-        nir_src index = instr->src[idx_idx];
+        nir_src index = instr->src[0];
         assert(nir_src_is_const(index));
         uint32_t uindex = nir_src_as_uint(index);
 
@@ -320,7 +317,7 @@ midgard_sysval_for_sampler(nir_intrinsic_instr *instr)
         return PAN_SYSVAL(SAMPLER, uindex);
 }
 
-static int
+static unsigned
 midgard_nir_sysval_for_intrinsic(nir_intrinsic_instr *instr)
 {
         switch (instr->intrinsic) {
@@ -330,8 +327,7 @@ midgard_nir_sysval_for_intrinsic(nir_intrinsic_instr *instr)
                 return PAN_SYSVAL_VIEWPORT_OFFSET;
         case nir_intrinsic_load_num_work_groups:
                 return PAN_SYSVAL_NUM_WORK_GROUPS;
-        case nir_intrinsic_load_ssbo: 
-        case nir_intrinsic_store_ssbo: 
+        case nir_intrinsic_load_ssbo_address: 
                 return midgard_sysval_for_ssbo(instr);
         case nir_intrinsic_load_sampler_lod_parameters_pan:
                 return midgard_sysval_for_sampler(instr);
@@ -346,16 +342,13 @@ static int sysval_for_instr(compiler_context *ctx, nir_instr *instr,
         nir_intrinsic_instr *intr;
         nir_dest *dst = NULL;
         nir_tex_instr *tex;
-        int sysval = -1;
-
-        bool is_store = false;
+        unsigned sysval = ~0;
 
         switch (instr->type) {
         case nir_instr_type_intrinsic:
                 intr = nir_instr_as_intrinsic(instr);
                 sysval = midgard_nir_sysval_for_intrinsic(intr);
                 dst = &intr->dest;
-                is_store |= intr->intrinsic == nir_intrinsic_store_ssbo;
                 break;
         case nir_instr_type_tex:
                 tex = nir_instr_as_tex(instr);
@@ -373,7 +366,7 @@ static int sysval_for_instr(compiler_context *ctx, nir_instr *instr,
                 break;
         }
 
-        if (dest && dst && !is_store)
+        if (dest && dst)
                 *dest = nir_dest_index(ctx, dst);
 
         return sysval;
@@ -1265,29 +1258,21 @@ emit_ubo_read(
 /* SSBO reads are like UBO reads if you squint */
 
 static void
-emit_ssbo_access(
+emit_global(
         compiler_context *ctx,
         nir_instr *instr,
         bool is_read,
         unsigned srcdest,
-        unsigned offset,
-        nir_src *indirect_offset,
-        unsigned index)
+        nir_src *indirect_offset)
 {
         /* TODO: types */
 
         midgard_instruction ins; 
 
         if (is_read)
-                ins = m_ld_int4(srcdest, offset);
+                ins = m_ld_int4(srcdest, 0);
         else
-                ins = m_st_int4(srcdest, offset);
-
-        /* SSBO reads use a generic memory read interface, so we need the
-         * address of the SSBO as the first argument. This is a sysval. */
-
-        unsigned addr = make_compiler_temp(ctx);
-        emit_sysval_read(ctx, instr, addr, 2);
+                ins = m_st_int4(srcdest, 0);
 
         /* The source array:
          *
@@ -1299,25 +1284,9 @@ emit_ssbo_access(
          * arg_2 = the offset.
          */
 
-        ins.src[1] = addr;
-
-        /* TODO: What is this? It looks superficially like a shift << 5, but
-         * arg_1 doesn't take a shift Should it be E0 or A0? We also need the
-         * indirect offset. */
-
-        if (indirect_offset) {
-                ins.load_store.arg_1 |= 0xE0;
-                ins.src[2] = nir_src_index(ctx, indirect_offset);
-        } else {
-                ins.load_store.arg_2 = 0x7E;
-        }
-
-        /* TODO: Bounds check */
-
-        /* Finally, we emit the direct offset */
-
-        ins.load_store.varying_parameters = (offset & 0x1FF) << 1;
-        ins.load_store.address = (offset >> 9);
+        /* TODO: What is this? */
+        ins.load_store.arg_1 = 0x7E;
+        ins.src[2] = nir_src_index(ctx, indirect_offset);
         mir_set_intr_mask(instr, &ins, is_read);
 
         emit_mir_instruction(ctx, ins);
@@ -1558,25 +1527,25 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
 
         case nir_intrinsic_load_uniform:
         case nir_intrinsic_load_ubo:
-        case nir_intrinsic_load_ssbo:
+        case nir_intrinsic_load_global:
         case nir_intrinsic_load_input:
         case nir_intrinsic_load_interpolated_input: {
                 bool is_uniform = instr->intrinsic == nir_intrinsic_load_uniform;
                 bool is_ubo = instr->intrinsic == nir_intrinsic_load_ubo;
-                bool is_ssbo = instr->intrinsic == nir_intrinsic_load_ssbo;
+                bool is_global = instr->intrinsic == nir_intrinsic_load_global;
                 bool is_flat = instr->intrinsic == nir_intrinsic_load_input;
                 bool is_interp = instr->intrinsic == nir_intrinsic_load_interpolated_input;
 
                 /* Get the base type of the intrinsic */
                 /* TODO: Infer type? Does it matter? */
                 nir_alu_type t =
-                        (is_ubo || is_ssbo) ? nir_type_uint :
+                        (is_ubo || is_global) ? nir_type_uint :
                         (is_interp) ? nir_type_float :
                         nir_intrinsic_type(instr);
 
                 t = nir_alu_type_get_base_type(t);
 
-                if (!(is_ubo || is_ssbo)) {
+                if (!(is_ubo || is_global)) {
                         offset = nir_intrinsic_base(instr);
                 }
 
@@ -1605,12 +1574,8 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
 
                         uint32_t uindex = nir_src_as_uint(index) + 1;
                         emit_ubo_read(ctx, &instr->instr, reg, offset, indirect_offset, 0, uindex);
-                } else if (is_ssbo) {
-                        nir_src index = instr->src[0];
-                        assert(nir_src_is_const(index));
-                        uint32_t uindex = nir_src_as_uint(index);
-
-                        emit_ssbo_access(ctx, &instr->instr, true, reg, offset, indirect_offset, uindex);
+                } else if (is_global) {
+                        emit_global(ctx, &instr->instr, true, reg, indirect_offset);
                 } else if (ctx->stage == MESA_SHADER_FRAGMENT && !ctx->is_blend) {
                         emit_varying_read(ctx, reg, offset, nr_comp, component, indirect_offset, t, is_flat);
                 } else if (ctx->is_blend) {
@@ -1802,20 +1767,16 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
 
                 break;
 
-        case nir_intrinsic_store_ssbo:
-                assert(nir_src_is_const(instr->src[1]));
-
-                bool direct_offset = nir_src_is_const(instr->src[2]);
-                offset = direct_offset ? nir_src_as_uint(instr->src[2]) : 0;
-                nir_src *indirect_offset = direct_offset ? NULL : &instr->src[2];
+        case nir_intrinsic_store_global:
                 reg = nir_src_index(ctx, &instr->src[0]);
-
-                uint32_t uindex = nir_src_as_uint(instr->src[1]);
-
                 emit_explicit_constant(ctx, reg, reg);
-                emit_ssbo_access(ctx, &instr->instr, false, reg, offset, indirect_offset, uindex);
+                emit_global(ctx, &instr->instr, false, reg, &instr->src[1]);
                 break;
 
+        case nir_intrinsic_load_ssbo_address:
+                emit_sysval_read(ctx, &instr->instr, ~0, 1);
+                break;
         case nir_intrinsic_load_viewport_scale:
         case nir_intrinsic_load_viewport_offset:
         case nir_intrinsic_load_num_work_groups:
@@ -2856,6 +2817,7 @@ midgard_compile_shader_nir(nir_shader *nir, midgard_program *program, bool is_bl
         NIR_PASS_V(nir, nir_lower_vars_to_ssa);
 
         NIR_PASS_V(nir, nir_lower_io, nir_var_all, glsl_type_size, 0);
+        NIR_PASS_V(nir, nir_lower_ssbo);
         NIR_PASS_V(nir, midgard_nir_lower_zs_store);
 
         /* Optimisation passes */