Mesa (main): lima: add native txp support

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Nov 16 19:26:27 UTC 2021


Module: Mesa
Branch: main
Commit: 764760314d041bb898bfa6a0f6f052baebb1bef6
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=764760314d041bb898bfa6a0f6f052baebb1bef6

Author: Vasily Khoruzhick <anarsoul at gmail.com>
Date:   Wed Sep 29 21:34:01 2021 -0700

lima: add native txp support

Currently lima uses generic TXP lowering that results in downgrading
coords precision to FP16 since we have to do some calculations with
coords instead of loading them directly from varying.

Mali4x0 has native TXP support, however coords and projector have to
come from a single source.

Add NIR lowering pass that combines coords and projector into a single
backend-specific source and use it instead of generic lowering.

Unfortunately this change regresses one test, but it also fails in blob and
disassembly is now identical.

shader-db diff:

total instructions in shared programs: 15623 -> 15603 (-0.13%)
instructions in affected programs: 877 -> 857 (-2.28%)
helped: 7
HURT: 0
helped stats (abs) min: 2 max: 8 x̄: 2.86 x̃: 2
helped stats (rel) min: 0.87% max: 10.53% x̄: 4.93% x̃: 1.85%
95% mean confidence interval for instructions value: -4.95 -0.76
95% mean confidence interval for instructions %-change: -9.31% -0.55%
Instructions are helped.

total loops in shared programs: 3 -> 3 (0.00%)
loops in affected programs: 0 -> 0
helped: 0
HURT: 0

total spills in shared programs: 136 -> 137 (0.74%)
spills in affected programs: 0 -> 1
helped: 0
HURT: 1

total fills in shared programs: 598 -> 602 (0.67%)
fills in affected programs: 0 -> 4
helped: 0
HURT: 1

Tested-by: Denis Pauk <pauk.denis at gmail.com>
Reviewed-by: Andreas Baierl <ichgeh at imkreisrum.de>
Signed-off-by: Vasily Khoruzhick <anarsoul at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13111>

---

 src/gallium/drivers/lima/ci/lima-fails.txt       |   1 +
 src/gallium/drivers/lima/ir/lima_ir.h            |   2 +
 src/gallium/drivers/lima/ir/lima_nir_lower_txp.c | 172 +++++++++++++++++++++++
 src/gallium/drivers/lima/ir/pp/codegen.c         |  38 ++++-
 src/gallium/drivers/lima/ir/pp/nir.c             |  16 ++-
 src/gallium/drivers/lima/ir/pp/ppir.h            |   7 +
 src/gallium/drivers/lima/lima_program.c          |   2 +-
 src/gallium/drivers/lima/meson.build             |   1 +
 8 files changed, 233 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/lima/ci/lima-fails.txt b/src/gallium/drivers/lima/ci/lima-fails.txt
index ec9b634fc1e..5e36f9cfe87 100644
--- a/src/gallium/drivers/lima/ci/lima-fails.txt
+++ b/src/gallium/drivers/lima/ci/lima-fails.txt
@@ -41,6 +41,7 @@ dEQP-GLES2.functional.shaders.indexing.varying_array.vec4_dynamic_loop_write_dyn
 dEQP-GLES2.functional.shaders.indexing.varying_array.vec4_dynamic_loop_write_static_loop_read,Fail
 dEQP-GLES2.functional.shaders.indexing.varying_array.vec4_dynamic_loop_write_static_read,Fail
 dEQP-GLES2.functional.shaders.texture_functions.fragment.texture2d_bias,Fail
+dEQP-GLES2.functional.shaders.texture_functions.fragment.texture2dproj_vec3_bias,Fail
 dEQP-GLES2.functional.shaders.texture_functions.fragment.texture2dproj_vec4_bias,Fail
 dEQP-GLES2.functional.texture.filtering.2d.linear_mipmap_linear_linear_clamp_rgba8888,Fail
 dEQP-GLES2.functional.texture.filtering.2d.linear_mipmap_linear_linear_mirror_rgba8888,Fail
diff --git a/src/gallium/drivers/lima/ir/lima_ir.h b/src/gallium/drivers/lima/ir/lima_ir.h
index 41d363a5550..573c745c026 100644
--- a/src/gallium/drivers/lima/ir/lima_ir.h
+++ b/src/gallium/drivers/lima/ir/lima_ir.h
@@ -73,4 +73,6 @@ void lima_nir_duplicate_load_consts(nir_shader *shader);
 void lima_nir_duplicate_load_inputs(nir_shader *shader);
 void lima_nir_duplicate_load_uniforms(nir_shader *shader);
 
+bool lima_nir_lower_txp(nir_shader *shader);
+
 #endif
diff --git a/src/gallium/drivers/lima/ir/lima_nir_lower_txp.c b/src/gallium/drivers/lima/ir/lima_nir_lower_txp.c
new file mode 100644
index 00000000000..b0109074bba
--- /dev/null
+++ b/src/gallium/drivers/lima/ir/lima_nir_lower_txp.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2021 Lima Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "nir.h"
+#include "nir_builder.h"
+#include "lima_ir.h"
+
+static nir_ssa_def *
+get_proj_index(nir_instr *coord_instr, nir_instr *proj_instr,
+               int coord_components, int *proj_idx)
+{
+   *proj_idx = -1;
+   if (coord_instr->type != nir_instr_type_alu ||
+       proj_instr->type != nir_instr_type_alu)
+      return NULL;
+
+   nir_alu_instr *coord_alu = nir_instr_as_alu(coord_instr);
+   nir_alu_instr *proj_alu = nir_instr_as_alu(proj_instr);
+
+   if (coord_alu->op != nir_op_mov ||
+       proj_alu->op != nir_op_mov)
+      return NULL;
+
+   if (!coord_alu->dest.dest.is_ssa ||
+       !proj_alu->dest.dest.is_ssa)
+      return NULL;
+
+   if (!coord_alu->src[0].src.is_ssa ||
+       !proj_alu->src[0].src.is_ssa)
+      return NULL;
+
+   nir_ssa_def *coord_src_ssa = coord_alu->src[0].src.ssa;
+   nir_ssa_def *proj_src_ssa = proj_alu->src[0].src.ssa;
+
+   if (coord_src_ssa != proj_src_ssa)
+      return NULL;
+
+   if (coord_src_ssa->parent_instr->type != nir_instr_type_intrinsic)
+      return NULL;
+
+   nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(coord_src_ssa->parent_instr);
+   if (intrin->intrinsic != nir_intrinsic_load_input)
+      return NULL;
+
+   if (nir_dest_num_components(intrin->dest) != 4)
+      return NULL;
+
+   /* Coords must be in .xyz */
+   for (int i = 0; i < coord_components; i++) {
+      if (coord_alu->src[0].swizzle[i] != i)
+         return NULL;
+   }
+
+   *proj_idx = proj_alu->src[0].swizzle[0];
+
+   return coord_src_ssa;
+}
+
+static bool
+lima_nir_lower_txp_instr(nir_builder *b, nir_instr *instr,
+                         UNUSED void *cb_data)
+{
+   if (instr->type != nir_instr_type_tex)
+      return false;
+
+   nir_tex_instr *tex = nir_instr_as_tex(instr);
+
+   int proj_idx = nir_tex_instr_src_index(tex, nir_tex_src_projector);
+   int coords_idx = nir_tex_instr_src_index(tex, nir_tex_src_coord);
+
+   if (proj_idx < 0)
+      return false;
+
+   switch (tex->sampler_dim) {
+   case GLSL_SAMPLER_DIM_RECT:
+   case GLSL_SAMPLER_DIM_1D:
+   case GLSL_SAMPLER_DIM_2D:
+   case GLSL_SAMPLER_DIM_3D:
+      break;
+   default:
+      return false;
+   }
+
+   b->cursor = nir_before_instr(&tex->instr);
+
+   /* Merge coords and projector into single backend-specific source.
+    * It's easy if texture2DProj argument is vec3, it's more tricky with
+    * vec4 since NIR just drops Z component that we need, so we have to
+    * step back and use load_input SSA instead of mov as a source for
+    * newly constructed vec4
+    */
+   nir_ssa_def *proj_ssa = nir_ssa_for_src(b, tex->src[proj_idx].src, 1);
+   nir_ssa_def *coords_ssa = nir_ssa_for_src(b, tex->src[coords_idx].src,
+                                             nir_tex_instr_src_size(tex, coords_idx));
+
+   int proj_idx_in_vec = -1;
+   nir_ssa_def *load_input = get_proj_index(coords_ssa->parent_instr,
+                                            proj_ssa->parent_instr,
+                                            tex->coord_components,
+                                            &proj_idx_in_vec);
+   nir_ssa_def *combined;
+   if (load_input && proj_idx_in_vec == 3) {
+      unsigned xyzw[] = { 0, 1, 2, 3 };
+      combined = nir_swizzle(b, load_input, xyzw, 4);
+      tex->coord_components = 4;
+   } else if (load_input && proj_idx_in_vec == 2) {
+      unsigned xyz[] = { 0, 1, 2 };
+      combined = nir_swizzle(b, load_input, xyz, 3);
+      tex->coord_components = 3;
+   } else {
+      switch (tex->coord_components) {
+      default:
+      case 1:
+         /* We still need vec3 for 1D textures, so duplicate coordinate */
+         combined = nir_vec3(b,
+                             nir_channel(b, coords_ssa, 0),
+                             nir_channel(b, coords_ssa, 0),
+                             nir_channel(b, proj_ssa, 0));
+         tex->coord_components = 3;
+         break;
+      case 2:
+         combined = nir_vec3(b,
+                             nir_channel(b, coords_ssa, 0),
+                             nir_channel(b, coords_ssa, 1),
+                             nir_channel(b, proj_ssa, 0));
+         tex->coord_components = 3;
+         break;
+      case 3:
+         combined = nir_vec4(b,
+                             nir_channel(b, coords_ssa, 0),
+                             nir_channel(b, coords_ssa, 1),
+                             nir_channel(b, coords_ssa, 2),
+                             nir_channel(b, proj_ssa, 0));
+         tex->coord_components = 4;
+      }
+   }
+
+   nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_coord));
+   nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_projector));
+   nir_tex_instr_add_src(tex, nir_tex_src_backend1, nir_src_for_ssa(combined));
+
+   return true;
+}
+
+bool
+lima_nir_lower_txp(nir_shader *shader)
+{
+   return nir_shader_instructions_pass(shader, lima_nir_lower_txp_instr,
+                                       nir_metadata_block_index |
+                                       nir_metadata_dominance,
+                                       NULL);
+}
diff --git a/src/gallium/drivers/lima/ir/pp/codegen.c b/src/gallium/drivers/lima/ir/pp/codegen.c
index 63ac9c0935d..8c39c688148 100644
--- a/src/gallium/drivers/lima/ir/pp/codegen.c
+++ b/src/gallium/drivers/lima/ir/pp/codegen.c
@@ -91,8 +91,25 @@ static void ppir_codegen_encode_varying(ppir_node *node, void *code)
             f->imm.perspective = 1;
             break;
          case ppir_op_load_coords:
-            /* num_components == 3 implies cubemap as we don't support 3D textures */
-            f->imm.source_type = num_components == 3 ? 2 : 0;
+            /* num_components == 3 and no perspective implies cubemap
+             * as we don't support 3D textures */
+            if (num_components == 3 &&
+                load->perspective == ppir_perspective_none)
+               f->imm.source_type = 2;
+            else
+               f->imm.source_type = 0;
+
+            switch (load->perspective) {
+            case ppir_perspective_none:
+               f->imm.perspective = 0;
+               break;
+            case ppir_perspective_z:
+               f->imm.perspective = 2;
+               break;
+            case ppir_perspective_w:
+               f->imm.perspective = 3;
+               break;
+            }
             break;
          default:
             break;
@@ -103,12 +120,25 @@ static void ppir_codegen_encode_varying(ppir_node *node, void *code)
       f->reg.mask = dest->write_mask << (index & 0x3);
 
       if (load->num_src) {
-         /* num_components == 3 implies cubemap as we don't support 3D textures */
-         if (num_components == 3) {
+         /* num_components == 3 and no perspective implies cubemap
+          * as we don't support 3D textures */
+         if (num_components == 3 &&
+             load->perspective == ppir_perspective_none) {
             f->reg.source_type = 2;
             f->reg.perspective = 1;
          } else {
             f->reg.source_type = 1;
+            switch (load->perspective) {
+            case ppir_perspective_none:
+               f->reg.perspective = 0;
+               break;
+            case ppir_perspective_z:
+               f->reg.perspective = 2;
+               break;
+            case ppir_perspective_w:
+               f->reg.perspective = 3;
+               break;
+            }
          }
          ppir_src *src = &load->src;
          index = ppir_target_get_src_reg_index(src);
diff --git a/src/gallium/drivers/lima/ir/pp/nir.c b/src/gallium/drivers/lima/ir/pp/nir.c
index 5d2d2282233..14f848d175d 100644
--- a/src/gallium/drivers/lima/ir/pp/nir.c
+++ b/src/gallium/drivers/lima/ir/pp/nir.c
@@ -473,8 +473,13 @@ static bool ppir_emit_tex(ppir_block *block, nir_instr *ni)
    for (int i = 0; i < instr->coord_components; i++)
          node->src[0].swizzle[i] = i;
 
+   bool perspective = false;
+
    for (int i = 0; i < instr->num_srcs; i++) {
       switch (instr->src[i].src_type) {
+      case nir_tex_src_backend1:
+         perspective = true;
+         FALLTHROUGH;
       case nir_tex_src_coord: {
          nir_src *ns = &instr->src[i].src;
          if (ns->is_ssa) {
@@ -482,7 +487,8 @@ static bool ppir_emit_tex(ppir_block *block, nir_instr *ni)
             if (child->op == ppir_op_load_varying) {
                /* If the successor is load_texture, promote it to load_coords */
                nir_tex_src *nts = (nir_tex_src *)ns;
-               if (nts->src_type == nir_tex_src_coord)
+               if (nts->src_type == nir_tex_src_coord ||
+                   nts->src_type == nir_tex_src_backend1)
                   child->op = ppir_op_load_coords;
             }
          }
@@ -543,6 +549,14 @@ static bool ppir_emit_tex(ppir_block *block, nir_instr *ni)
    }
 
    assert(load);
+
+   if (perspective) {
+      if (instr->coord_components == 3)
+         load->perspective = ppir_perspective_z;
+      else
+         load->perspective = ppir_perspective_w;
+   }
+
    node->src[0].type = load->dest.type = ppir_target_pipeline;
    node->src[0].pipeline = load->dest.pipeline = ppir_pipeline_reg_discard;
 
diff --git a/src/gallium/drivers/lima/ir/pp/ppir.h b/src/gallium/drivers/lima/ir/pp/ppir.h
index 480fca9e689..62ffb0fc2d9 100644
--- a/src/gallium/drivers/lima/ir/pp/ppir.h
+++ b/src/gallium/drivers/lima/ir/pp/ppir.h
@@ -252,6 +252,12 @@ typedef struct {
    ppir_dest dest;
 } ppir_const_node;
 
+typedef enum {
+   ppir_perspective_none = 0,
+   ppir_perspective_z,
+   ppir_perspective_w,
+} ppir_perspective;
+
 typedef struct {
    ppir_node node;
    int index;
@@ -259,6 +265,7 @@ typedef struct {
    ppir_dest dest;
    ppir_src src;
    int num_src;
+   ppir_perspective perspective;
 } ppir_load_node;
 
 typedef struct {
diff --git a/src/gallium/drivers/lima/lima_program.c b/src/gallium/drivers/lima/lima_program.c
index a4d9b8a0ef9..a07c7251bef 100644
--- a/src/gallium/drivers/lima/lima_program.c
+++ b/src/gallium/drivers/lima/lima_program.c
@@ -216,6 +216,7 @@ lima_program_optimize_fs_nir(struct nir_shader *s,
 	      nir_var_shader_in | nir_var_shader_out, type_size, 0);
    NIR_PASS_V(s, nir_lower_regs_to_ssa);
    NIR_PASS_V(s, nir_lower_tex, tex_options);
+   NIR_PASS_V(s, lima_nir_lower_txp);
 
    do {
       progress = false;
@@ -283,7 +284,6 @@ lima_fs_compile_shader(struct lima_context *ctx,
    nir_shader *nir = nir_shader_clone(fs, ufs->base.ir.nir);
 
    struct nir_lower_tex_options tex_options = {
-      .lower_txp = ~0u,
       .swizzle_result = ~0u,
    };
 
diff --git a/src/gallium/drivers/lima/meson.build b/src/gallium/drivers/lima/meson.build
index 5bc6fbbf869..c7b9a8b099b 100644
--- a/src/gallium/drivers/lima/meson.build
+++ b/src/gallium/drivers/lima/meson.build
@@ -51,6 +51,7 @@ files_lima = files(
   'ir/lima_nir_lower_uniform_to_scalar.c',
   'ir/lima_nir_split_load_input.c',
   'ir/lima_nir_split_loads.c',
+  'ir/lima_nir_lower_txp.c',
 
   'ir/lima_ir.h',
 



More information about the mesa-commit mailing list