glsl: improve precision determination for calls
authorMarek Olšák <marek.olsak@amd.com>
Sat, 25 Jul 2020 02:06:21 +0000 (22:06 -0400)
committerMarge Bot <eric+marge@anholt.net>
Wed, 5 Aug 2020 22:04:47 +0000 (22:04 +0000)
Don't leave the precision as NONE for non-lowerable calls. Set it to HIGH
if a function really returns highp.

Reviewed-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6073>

src/compiler/glsl/lower_precision.cpp

index f602c78878fa666441f52b3e47735a9beae6a2dd..df05a15deb2b9c7d69c96bba3a234b24e45d573b 100644 (file)
@@ -419,9 +419,8 @@ function_always_returns_mediump_or_lowp(const char *name)
           !strcmp(name, "unpackSnorm4x8");
 }
 
-static bool
-is_lowerable_builtin(ir_call *ir,
-                     const struct set *lowerable_rvalues)
+static unsigned
+handle_call(ir_call *ir, const struct set *lowerable_rvalues)
 {
    /* The intrinsic call is inside the wrapper imageLoad function that will
     * be inlined. We have to handle both of them.
@@ -447,15 +446,23 @@ is_lowerable_builtin(ir_call *ir,
          util_format_description(resource->data.image_format);
       int i =
          util_format_get_first_non_void_channel(resource->data.image_format);
+      bool mediump;
+
       assert(i >= 0);
 
       if (desc->channel[i].pure_integer ||
           desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT)
-         return desc->channel[i].size <= 16;
+         mediump = desc->channel[i].size <= 16;
       else
-         return desc->channel[i].size <= 10; /* unorm/snorm */
+         mediump = desc->channel[i].size <= 10; /* unorm/snorm */
+
+      return mediump ? GLSL_PRECISION_MEDIUM : GLSL_PRECISION_HIGH;
    }
 
+   /* Return the declared precision for user-defined functions. */
+   if (!ir->callee->is_builtin())
+      return ir->callee->return_precision;
+
    /* Handle special calls. */
    if (ir->callee->is_builtin() && ir->actual_parameters.length()) {
       ir_rvalue *param = (ir_rvalue*)ir->actual_parameters.get_head();
@@ -471,15 +478,13 @@ is_lowerable_builtin(ir_call *ir,
       if (var && var->type->without_array()->is_sampler()) {
          /* textureSize always returns highp. */
          if (!strcmp(ir->callee_name(), "textureSize"))
-            return false;
+            return GLSL_PRECISION_HIGH;
 
-         return var->data.precision == GLSL_PRECISION_MEDIUM ||
-                var->data.precision == GLSL_PRECISION_LOW;
+         return var->data.precision;
       }
    }
 
-   if (!ir->callee->is_builtin() ||
-       /* Parameters are always highp: */
+   if (/* Parameters are always highp: */
        !strcmp(ir->callee_name(), "floatBitsToInt") ||
        !strcmp(ir->callee_name(), "floatBitsToUint") ||
        !strcmp(ir->callee_name(), "intBitsToFloat") ||
@@ -509,7 +514,7 @@ is_lowerable_builtin(ir_call *ir,
        !strcmp(ir->callee_name(), "packSnorm4x8") ||
        /* Atomic functions are not lowered. */
        strstr(ir->callee_name(), "atomic") == ir->callee_name())
-      return false;
+      return GLSL_PRECISION_HIGH;
 
    assert(ir->callee->return_precision == GLSL_PRECISION_NONE);
 
@@ -531,18 +536,21 @@ is_lowerable_builtin(ir_call *ir,
       check_parameters = 0;
    }
 
+   /* If the call is to a builtin, then the function won’t have a return
+    * precision and we should determine it from the precision of the arguments.
+    */
    foreach_in_list(ir_rvalue, param, &ir->actual_parameters) {
       if (!check_parameters)
          break;
 
       if (!param->as_constant() &&
           _mesa_set_search(lowerable_rvalues, param) == NULL)
-         return false;
+         return GLSL_PRECISION_HIGH;
 
       --check_parameters;
    }
 
-   return true;
+   return GLSL_PRECISION_MEDIUM;
 }
 
 ir_visitor_status
@@ -564,13 +572,7 @@ find_lowerable_rvalues_visitor::visit_leave(ir_call *ir)
 
    assert(var->data.mode == ir_var_temporary);
 
-   unsigned return_precision = ir->callee->return_precision;
-
-   /* If the call is to a builtin, then the function won’t have a return
-    * precision and we should determine it from the precision of the arguments.
-    */
-   if (is_lowerable_builtin(ir, lowerable_rvalues))
-      return_precision = GLSL_PRECISION_MEDIUM;
+   unsigned return_precision = handle_call(ir, lowerable_rvalues);
 
    can_lower_state lower_state =
       handle_precision(var->type, return_precision);