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

Author: Emma Anholt <[email protected]>
Date:   Tue Sep  6 17:09:06 2022 -0700

nir/lower_mediump_vars: Don't lower mediump shared vars with atomic access.

I don't know of any GPUs doing 16-bit atomic accesses, nor do I know of
anybody wanting that in shaders.  But deqp has GLES CTS cases that set
mediump on shared variables, so just skip lowering for those vars.

Reviewed-by: Matt Turner <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18452>

---

 src/compiler/nir/nir_lower_mediump.c | 50 +++++++++++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/src/compiler/nir/nir_lower_mediump.c 
b/src/compiler/nir/nir_lower_mediump.c
index 2e8572c345b..7f870a6b3b1 100644
--- a/src/compiler/nir/nir_lower_mediump.c
+++ b/src/compiler/nir/nir_lower_mediump.c
@@ -387,11 +387,14 @@ is_mediump_or_lowp(unsigned precision)
 }
 
 static bool
-try_lower_mediump_var(nir_variable *var, nir_variable_mode modes)
+try_lower_mediump_var(nir_variable *var, nir_variable_mode modes, struct set 
*set)
 {
    if (!(var->data.mode & modes) || !is_mediump_or_lowp(var->data.precision))
       return false;
 
+   if (set && _mesa_set_search(set, var))
+      return false;
+
    const struct glsl_type *new_type = glsl_type_to_16bit(var->type);
    if (var->type == new_type)
       return false;
@@ -408,7 +411,7 @@ nir_lower_mediump_vars_impl(nir_function_impl *impl, 
nir_variable_mode modes,
 
    if (modes & nir_var_function_temp) {
       nir_foreach_function_temp_variable(var, impl) {
-         any_lowered = try_lower_mediump_var(var, modes) || any_lowered;
+         any_lowered = try_lower_mediump_var(var, modes, NULL) || any_lowered;
       }
    }
    if (!any_lowered)
@@ -550,9 +553,50 @@ nir_lower_mediump_vars(nir_shader *shader, 
nir_variable_mode modes)
    bool progress = false;
 
    if (modes & ~nir_var_function_temp) {
+      /* Don't lower GLES mediump atomic ops to 16-bit -- no hardware is 
expecting that. */
+      struct set *no_lower_set = _mesa_pointer_set_create(NULL);
+      nir_foreach_block(block, nir_shader_get_entrypoint(shader)) {
+         nir_foreach_instr(instr, block) {
+            if (instr->type != nir_instr_type_intrinsic)
+               continue;
+            nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+            switch (intr->intrinsic) {
+            case nir_intrinsic_deref_atomic_add:
+            case nir_intrinsic_deref_atomic_imin:
+            case nir_intrinsic_deref_atomic_umin:
+            case nir_intrinsic_deref_atomic_imax:
+            case nir_intrinsic_deref_atomic_umax:
+            case nir_intrinsic_deref_atomic_and:
+            case nir_intrinsic_deref_atomic_or:
+            case nir_intrinsic_deref_atomic_xor:
+            case nir_intrinsic_deref_atomic_exchange:
+            case nir_intrinsic_deref_atomic_fadd:
+            case nir_intrinsic_deref_atomic_fmin:
+            case nir_intrinsic_deref_atomic_fmax:
+            case nir_intrinsic_deref_atomic_comp_swap:
+            case nir_intrinsic_deref_atomic_fcomp_swap: {
+               nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
+               nir_variable *var = nir_deref_instr_get_variable(deref);
+
+               /* If we have atomic derefs that we can't track, then don't 
lower any mediump.  */
+               if (!var)
+                  return false;
+
+               _mesa_set_add(no_lower_set, var);
+               break;
+            }
+
+            default:
+               break;
+            }
+         }
+      }
+
       nir_foreach_variable_in_shader(var, shader) {
-         progress = try_lower_mediump_var(var, modes) || progress;
+         progress = try_lower_mediump_var(var, modes, no_lower_set) || 
progress;
       }
+
+      ralloc_free(no_lower_set);
    }
 
    nir_foreach_function(function, shader) {

Reply via email to