return visit_continue;
}
+static bool
+function_always_returns_mediump_or_lowp(const char *name)
+{
+ return !strcmp(name, "bitCount") ||
+ !strcmp(name, "findLSB") ||
+ !strcmp(name, "findMSB") ||
+ !strcmp(name, "unpackHalf2x16") ||
+ !strcmp(name, "unpackUnorm4x8") ||
+ !strcmp(name, "unpackSnorm4x8");
+}
+
static bool
is_lowerable_builtin(ir_call *ir,
const struct set *lowerable_rvalues)
* uses lower precision. The function parameters don't matter.
*/
if (var && var->type->without_array()->is_sampler()) {
+ /* textureSize always returns highp. */
+ if (!strcmp(ir->callee_name(), "textureSize"))
+ return false;
+
return var->data.precision == GLSL_PRECISION_MEDIUM ||
var->data.precision == GLSL_PRECISION_LOW;
}
}
- if (!ir->callee->is_builtin())
+ if (!ir->callee->is_builtin() ||
+ /* Parameters are always highp: */
+ !strcmp(ir->callee_name(), "floatBitsToInt") ||
+ !strcmp(ir->callee_name(), "floatBitsToUint") ||
+ !strcmp(ir->callee_name(), "intBitsToFloat") ||
+ !strcmp(ir->callee_name(), "uintBitsToFloat") ||
+ !strcmp(ir->callee_name(), "bitfieldReverse") ||
+ !strcmp(ir->callee_name(), "frexp") ||
+ !strcmp(ir->callee_name(), "ldexp") ||
+ /* Parameters and outputs are always highp: */
+ /* TODO: The operations are highp, but carry and borrow outputs are lowp. */
+ !strcmp(ir->callee_name(), "uaddCarry") ||
+ !strcmp(ir->callee_name(), "usubBorrow") ||
+ !strcmp(ir->callee_name(), "imulExtended") ||
+ !strcmp(ir->callee_name(), "umulExtended") ||
+ !strcmp(ir->callee_name(), "unpackUnorm2x16") ||
+ !strcmp(ir->callee_name(), "unpackSnorm2x16") ||
+ /* Outputs are highp: */
+ !strcmp(ir->callee_name(), "packUnorm2x16") ||
+ !strcmp(ir->callee_name(), "packSnorm2x16") ||
+ /* Parameters are mediump and outputs are highp. The parameters should
+ * be optimized in NIR, not here, e.g:
+ * - packHalf2x16 can just be a bitcast from f16vec2 to uint32
+ * - Other opcodes don't have to convert parameters to highp if the hw
+ * has f16 versions. Optimize in NIR accordingly.
+ */
+ !strcmp(ir->callee_name(), "packHalf2x16") ||
+ !strcmp(ir->callee_name(), "packUnorm4x8") ||
+ !strcmp(ir->callee_name(), "packSnorm4x8"))
return false;
assert(ir->callee->return_precision == GLSL_PRECISION_NONE);
+ /* Number of parameters to check if they are lowerable. */
+ unsigned check_parameters = ir->actual_parameters.length();
+
+ /* Interpolation functions only consider the precision of the interpolant. */
+ /* Bitfield functions ignore the precision of "offset" and "bits". */
+ if (!strcmp(ir->callee_name(), "interpolateAtOffset") ||
+ !strcmp(ir->callee_name(), "interpolateAtSample") ||
+ !strcmp(ir->callee_name(), "bitfieldExtract")) {
+ check_parameters = 1;
+ } else if (!strcmp(ir->callee_name(), "bitfieldInsert")) {
+ check_parameters = 2;
+ } if (function_always_returns_mediump_or_lowp(ir->callee_name())) {
+ /* These only lower the return value. Parameters keep their precision,
+ * which is preserved in map_builtin.
+ */
+ check_parameters = 0;
+ }
+
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;
+
+ --check_parameters;
}
return true;
ir_function_signature *lowered_sig =
sig->clone(lowered_builtin_mem_ctx, clone_ht);
- foreach_in_list(ir_variable, param, &lowered_sig->parameters) {
- param->data.precision = GLSL_PRECISION_MEDIUM;
+ /* Functions that always return mediump or lowp should keep their
+ * parameters intact, because they can be highp. NIR can lower
+ * the up-conversion for parameters if needed.
+ */
+ if (!function_always_returns_mediump_or_lowp(sig->function_name())) {
+ foreach_in_list(ir_variable, param, &lowered_sig->parameters) {
+ param->data.precision = GLSL_PRECISION_MEDIUM;
+ }
}
lower_precision(options, &lowered_sig->body);