freedreno/ir3: pass variant to postsched
[mesa.git] / src / freedreno / ir3 / ir3_nir_lower_tex_prefetch.c
index 1a6fbb4ba5d81003b4b4c4c0ef30235bfca1b883..38474749955e1d47cd9223621c8b5e21a17d5f4a 100644 (file)
@@ -45,22 +45,25 @@ coord_offset(nir_ssa_def *ssa)
                if (alu->op != nir_op_vec2)
                        return -1;
 
-               for (int i = 0; i < 2; i++) {
+               if (!alu->src[0].src.is_ssa)
+                       return -1;
+
+               int base_offset = coord_offset(alu->src[0].src.ssa) +
+                               alu->src[0].swizzle[0];
+
+               /* NOTE it might be possible to support more than 2D? */
+               for (int i = 1; i < 2; i++) {
                        if (!alu->src[i].src.is_ssa)
                                return -1;
 
-                       if (alu->src[i].swizzle[0] != (alu->src[0].swizzle[0] + i))
-                               return -1;
+                       int nth_offset = coord_offset(alu->src[i].src.ssa) +
+                                       alu->src[i].swizzle[0];
 
-                       if (alu->src[i].src.ssa != alu->src[0].src.ssa)
+                       if (nth_offset != (base_offset + i))
                                return -1;
                }
 
-               int off = coord_offset(alu->src[0].src.ssa);
-               if (off < 0)
-                       return -1;
-
-               return off + alu->src[0].swizzle[0];
+               return base_offset;
        }
 
        if (parent_instr->type != nir_instr_type_intrinsic)
@@ -96,13 +99,8 @@ coord_offset(nir_ssa_def *ssa)
 int
 ir3_nir_coord_offset(nir_ssa_def *ssa)
 {
-       /* only prefetch for simple 2d tex fetch case.  Note this check only
-        * applies to the tex coord src itself, and not in the case where
-        * we recursively chase a vecN's src.
-        */
-       if (ssa->num_components != 2)
-               return -1;
 
+       assert (ssa->num_components == 2);
        return coord_offset(ssa);
 }
 
@@ -112,12 +110,52 @@ has_src(nir_tex_instr *tex, nir_tex_src_type type)
        return nir_tex_instr_src_index(tex, type) > 0;
 }
 
+static bool
+ok_bindless_src(nir_tex_instr *tex, nir_tex_src_type type)
+{
+       int idx = nir_tex_instr_src_index(tex, type);
+       assert(idx >= 0);
+       nir_intrinsic_instr *bindless = ir3_bindless_resource(tex->src[idx].src);
+
+       /* TODO from SP_FS_BINDLESS_PREFETCH[n] it looks like this limit should
+        * be 1<<8 ?
+        */
+       return nir_src_is_const(bindless->src[0]) &&
+                       (nir_src_as_uint(bindless->src[0]) < (1 << 16));
+}
+
+/**
+ * Check that we will be able to encode the tex/samp parameters
+ * successfully.  These limits are based on the layout of
+ * SP_FS_PREFETCH[n] and SP_FS_BINDLESS_PREFETCH[n], so at some
+ * point (if those regs changes) they may become generation
+ * specific.
+ */
+static bool
+ok_tex_samp(nir_tex_instr *tex)
+{
+       if (has_src(tex, nir_tex_src_texture_handle)) {
+               /* bindless case: */
+
+               assert(has_src(tex, nir_tex_src_sampler_handle));
+
+               return ok_bindless_src(tex, nir_tex_src_texture_handle) &&
+                               ok_bindless_src(tex, nir_tex_src_sampler_handle);
+       } else {
+               assert(!has_src(tex, nir_tex_src_texture_offset));
+               assert(!has_src(tex, nir_tex_src_sampler_offset));
+
+               return (tex->texture_index <= 0x1f) &&
+                               (tex->sampler_index <= 0xf);
+       }
+}
+
 static bool
 lower_tex_prefetch_block(nir_block *block)
 {
        bool progress = false;
 
-       nir_foreach_instr_safe(instr, block) {
+       nir_foreach_instr_safe (instr, block) {
                if (instr->type != nir_instr_type_tex)
                        continue;
 
@@ -137,6 +175,13 @@ lower_tex_prefetch_block(nir_block *block)
                                has_src(tex, nir_tex_src_sampler_offset))
                        continue;
 
+               /* only prefetch for simple 2d tex fetch case */
+               if (tex->sampler_dim != GLSL_SAMPLER_DIM_2D || tex->is_array)
+                       continue;
+
+               if (!ok_tex_samp(tex))
+                       continue;
+
                int idx = nir_tex_instr_src_index(tex, nir_tex_src_coord);
                /* First source should be the sampling coordinate. */
                nir_tex_src *coord = &tex->src[idx];
@@ -181,7 +226,7 @@ ir3_nir_lower_tex_prefetch(nir_shader *shader)
 
        assert(shader->info.stage == MESA_SHADER_FRAGMENT);
 
-       nir_foreach_function(function, shader) {
+       nir_foreach_function (function, shader) {
                /* Only texture sampling instructions inside the main function
                 * are eligible for pre-dispatch.
                 */