From: Emma Anholt Date: Wed, 1 Mar 2023 23:31:21 +0000 (-0800) Subject: glsl: Set the precisions of builtin function arguments and returns. X-Git-Tag: upstream/23.3.3~11363 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=be2731f445ce1ff11d052fd8ca10742193d77d1e;p=platform%2Fupstream%2Fmesa.git glsl: Set the precisions of builtin function arguments and returns. These have precision qualifiers defined in the spec, in which case we should emit them them while generating builtin signatures and code. We've been special-casing them in GLSL lower_precision, but now we can just rely on the precision qualifier of the builtin if non-NONE. Reviewed-by: Marek Olšák Part-of: --- diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp index e07ac61..4d1f67f 100644 --- a/src/compiler/glsl/builtin_functions.cpp +++ b/src/compiler/glsl/builtin_functions.cpp @@ -1017,7 +1017,11 @@ private: * member available. */ ir_variable *in_var(const glsl_type *type, const char *name); + ir_variable *in_mediump_var(const glsl_type *type, const char *name); + ir_variable *in_highp_var(const glsl_type *type, const char *name); ir_variable *out_var(const glsl_type *type, const char *name); + ir_variable *out_lowp_var(const glsl_type *type, const char *name); + ir_variable *out_highp_var(const glsl_type *type, const char *name); ir_constant *imm(float f, unsigned vector_elements=1); ir_constant *imm(bool b, unsigned vector_elements=1); ir_constant *imm(int i, unsigned vector_elements=1); @@ -1079,6 +1083,10 @@ private: ir_expression_operation opcode, const glsl_type *return_type, const glsl_type *param_type); + ir_function_signature *unop_precision(builtin_available_predicate avail, + ir_expression_operation opcode, + const glsl_type *return_type, + const glsl_type *param_type, uint32_t precision); ir_function_signature *binop(builtin_available_predicate avail, ir_expression_operation opcode, const glsl_type *return_type, @@ -5651,11 +5659,43 @@ builtin_builder::in_var(const glsl_type *type, const char *name) } ir_variable * +builtin_builder::in_highp_var(const glsl_type *type, const char *name) +{ + ir_variable *var = in_var(type, name); + var->data.precision = GLSL_PRECISION_HIGH; + return var; +} + +ir_variable * +builtin_builder::in_mediump_var(const glsl_type *type, const char *name) +{ + ir_variable *var = in_var(type, name); + var->data.precision = GLSL_PRECISION_MEDIUM; + return var; +} + +ir_variable * builtin_builder::out_var(const glsl_type *type, const char *name) { return new(mem_ctx) ir_variable(type, name, ir_var_function_out); } +ir_variable * +builtin_builder::out_lowp_var(const glsl_type *type, const char *name) +{ + ir_variable *var = out_var(type, name); + var->data.precision = GLSL_PRECISION_LOW; + return var; +} + +ir_variable * +builtin_builder::out_highp_var(const glsl_type *type, const char *name) +{ + ir_variable *var = out_var(type, name); + var->data.precision = GLSL_PRECISION_HIGH; + return var; +} + ir_constant * builtin_builder::imm(bool b, unsigned vector_elements) { @@ -6290,8 +6330,9 @@ builtin_builder::_uint64BitsToDouble(builtin_available_predicate avail, const gl ir_function_signature * builtin_builder::_packUnorm2x16(builtin_available_predicate avail) { - ir_variable *v = in_var(glsl_type::vec2_type, "v"); + ir_variable *v = in_highp_var(glsl_type::vec2_type, "v"); MAKE_SIG(glsl_type::uint_type, avail, 1, v); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(ret(expr(ir_unop_pack_unorm_2x16, v))); return sig; } @@ -6301,6 +6342,7 @@ builtin_builder::_packSnorm2x16(builtin_available_predicate avail) { ir_variable *v = in_var(glsl_type::vec2_type, "v"); MAKE_SIG(glsl_type::uint_type, avail, 1, v); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(ret(expr(ir_unop_pack_snorm_2x16, v))); return sig; } @@ -6308,8 +6350,9 @@ builtin_builder::_packSnorm2x16(builtin_available_predicate avail) ir_function_signature * builtin_builder::_packUnorm4x8(builtin_available_predicate avail) { - ir_variable *v = in_var(glsl_type::vec4_type, "v"); + ir_variable *v = in_mediump_var(glsl_type::vec4_type, "v"); MAKE_SIG(glsl_type::uint_type, avail, 1, v); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(ret(expr(ir_unop_pack_unorm_4x8, v))); return sig; } @@ -6317,8 +6360,9 @@ builtin_builder::_packUnorm4x8(builtin_available_predicate avail) ir_function_signature * builtin_builder::_packSnorm4x8(builtin_available_predicate avail) { - ir_variable *v = in_var(glsl_type::vec4_type, "v"); + ir_variable *v = in_mediump_var(glsl_type::vec4_type, "v"); MAKE_SIG(glsl_type::uint_type, avail, 1, v); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(ret(expr(ir_unop_pack_snorm_4x8, v))); return sig; } @@ -6326,8 +6370,9 @@ builtin_builder::_packSnorm4x8(builtin_available_predicate avail) ir_function_signature * builtin_builder::_unpackUnorm2x16(builtin_available_predicate avail) { - ir_variable *p = in_var(glsl_type::uint_type, "p"); + ir_variable *p = in_highp_var(glsl_type::uint_type, "p"); MAKE_SIG(glsl_type::vec2_type, avail, 1, p); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(ret(expr(ir_unop_unpack_unorm_2x16, p))); return sig; } @@ -6335,8 +6380,9 @@ builtin_builder::_unpackUnorm2x16(builtin_available_predicate avail) ir_function_signature * builtin_builder::_unpackSnorm2x16(builtin_available_predicate avail) { - ir_variable *p = in_var(glsl_type::uint_type, "p"); + ir_variable *p = in_highp_var(glsl_type::uint_type, "p"); MAKE_SIG(glsl_type::vec2_type, avail, 1, p); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(ret(expr(ir_unop_unpack_snorm_2x16, p))); return sig; } @@ -6345,8 +6391,9 @@ builtin_builder::_unpackSnorm2x16(builtin_available_predicate avail) ir_function_signature * builtin_builder::_unpackUnorm4x8(builtin_available_predicate avail) { - ir_variable *p = in_var(glsl_type::uint_type, "p"); + ir_variable *p = in_highp_var(glsl_type::uint_type, "p"); MAKE_SIG(glsl_type::vec4_type, avail, 1, p); + sig->return_precision = GLSL_PRECISION_MEDIUM; body.emit(ret(expr(ir_unop_unpack_unorm_4x8, p))); return sig; } @@ -6354,8 +6401,9 @@ builtin_builder::_unpackUnorm4x8(builtin_available_predicate avail) ir_function_signature * builtin_builder::_unpackSnorm4x8(builtin_available_predicate avail) { - ir_variable *p = in_var(glsl_type::uint_type, "p"); + ir_variable *p = in_highp_var(glsl_type::uint_type, "p"); MAKE_SIG(glsl_type::vec4_type, avail, 1, p); + sig->return_precision = GLSL_PRECISION_MEDIUM; body.emit(ret(expr(ir_unop_unpack_snorm_4x8, p))); return sig; } @@ -6363,8 +6411,9 @@ builtin_builder::_unpackSnorm4x8(builtin_available_predicate avail) ir_function_signature * builtin_builder::_packHalf2x16(builtin_available_predicate avail) { - ir_variable *v = in_var(glsl_type::vec2_type, "v"); + ir_variable *v = in_mediump_var(glsl_type::vec2_type, "v"); MAKE_SIG(glsl_type::uint_type, avail, 1, v); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(ret(expr(ir_unop_pack_half_2x16, v))); return sig; } @@ -6372,8 +6421,9 @@ builtin_builder::_packHalf2x16(builtin_available_predicate avail) ir_function_signature * builtin_builder::_unpackHalf2x16(builtin_available_predicate avail) { - ir_variable *p = in_var(glsl_type::uint_type, "p"); + ir_variable *p = in_highp_var(glsl_type::uint_type, "p"); MAKE_SIG(glsl_type::vec2_type, avail, 1, p); + sig->return_precision = GLSL_PRECISION_MEDIUM; body.emit(ret(expr(ir_unop_unpack_half_2x16, p))); return sig; } @@ -7072,6 +7122,7 @@ builtin_builder::_textureSize(builtin_available_predicate avail, ir_variable *s = in_var(sampler_type, "sampler"); /* The sampler always exists; add optional lod later. */ MAKE_SIG(return_type, avail, 1, s); + sig->return_precision = GLSL_PRECISION_HIGH; ir_texture *tex = new(mem_ctx) ir_texture(ir_txs); tex->set_sampler(new(mem_ctx) ir_dereference_variable(s), return_type); @@ -7621,27 +7672,44 @@ builtin_builder::_bitfieldInsert(const glsl_type *type) return sig; } -UNOP(bitfieldReverse, ir_unop_bitfield_reverse, gpu_shader5_or_es31_or_integer_functions) +ir_function_signature * +builtin_builder::_bitfieldReverse(const glsl_type *type) +{ + ir_variable *x = in_highp_var(type, "x"); + MAKE_SIG(type, gpu_shader5_or_es31_or_integer_functions, 1, x); + sig->return_precision = GLSL_PRECISION_HIGH; + body.emit(ret(expr(ir_unop_bitfield_reverse, x))); + return sig; +} ir_function_signature * builtin_builder::_bitCount(const glsl_type *type) { - return unop(gpu_shader5_or_es31_or_integer_functions, ir_unop_bit_count, - glsl_type::ivec(type->vector_elements), type); + ir_variable *x = in_var(type, "x"); + MAKE_SIG(glsl_type::ivec(type->vector_elements), gpu_shader5_or_es31_or_integer_functions, 1, x); + sig->return_precision = GLSL_PRECISION_LOW; + body.emit(ret(expr(ir_unop_bit_count, x))); + return sig; } ir_function_signature * builtin_builder::_findLSB(const glsl_type *type) { - return unop(gpu_shader5_or_es31_or_integer_functions, ir_unop_find_lsb, - glsl_type::ivec(type->vector_elements), type); + ir_variable *x = in_highp_var(type, "x"); + MAKE_SIG(glsl_type::ivec(type->vector_elements), gpu_shader5_or_es31_or_integer_functions, 1, x); + sig->return_precision = GLSL_PRECISION_LOW; + body.emit(ret(expr(ir_unop_find_lsb, x))); + return sig; } ir_function_signature * builtin_builder::_findMSB(const glsl_type *type) { - return unop(gpu_shader5_or_es31_or_integer_functions, ir_unop_find_msb, - glsl_type::ivec(type->vector_elements), type); + ir_variable *x = in_highp_var(type, "x"); + MAKE_SIG(glsl_type::ivec(type->vector_elements), gpu_shader5_or_es31_or_integer_functions, 1, x); + sig->return_precision = GLSL_PRECISION_LOW; + body.emit(ret(expr(ir_unop_find_msb, x))); + return sig; } ir_function_signature * @@ -7682,14 +7750,18 @@ builtin_builder::_fma(builtin_available_predicate avail, const glsl_type *type) ir_function_signature * builtin_builder::_ldexp(const glsl_type *x_type, const glsl_type *exp_type) { - return binop(x_type->is_double() ? fp64 : gpu_shader5_or_es31_or_integer_functions, - ir_binop_ldexp, x_type, x_type, exp_type); + ir_variable *x = in_highp_var(x_type, "x"); + ir_variable *y = in_highp_var(exp_type, "y"); + MAKE_SIG(x_type, x_type->is_double() ? fp64 : gpu_shader5_or_es31_or_integer_functions, 2, x, y); + sig->return_precision = GLSL_PRECISION_HIGH; + body.emit(ret(expr(ir_binop_ldexp, x, y))); + return sig; } ir_function_signature * builtin_builder::_dfrexp(const glsl_type *x_type, const glsl_type *exp_type) { - ir_variable *x = in_var(x_type, "x"); + ir_variable *x = in_highp_var(x_type, "x"); ir_variable *exponent = out_var(exp_type, "exp"); MAKE_SIG(x_type, fp64, 2, x, exponent); @@ -7702,9 +7774,10 @@ builtin_builder::_dfrexp(const glsl_type *x_type, const glsl_type *exp_type) ir_function_signature * builtin_builder::_frexp(const glsl_type *x_type, const glsl_type *exp_type) { - ir_variable *x = in_var(x_type, "x"); - ir_variable *exponent = out_var(exp_type, "exp"); + ir_variable *x = in_highp_var(x_type, "x"); + ir_variable *exponent = out_highp_var(exp_type, "exp"); MAKE_SIG(x_type, gpu_shader5_or_es31_or_integer_functions, 2, x, exponent); + sig->return_precision = GLSL_PRECISION_HIGH; const unsigned vec_elem = x_type->vector_elements; const glsl_type *bvec = glsl_type::get_instance(GLSL_TYPE_BOOL, vec_elem, 1); @@ -7750,10 +7823,11 @@ builtin_builder::_frexp(const glsl_type *x_type, const glsl_type *exp_type) ir_function_signature * builtin_builder::_uaddCarry(const glsl_type *type) { - ir_variable *x = in_var(type, "x"); - ir_variable *y = in_var(type, "y"); - ir_variable *carry = out_var(type, "carry"); + ir_variable *x = in_highp_var(type, "x"); + ir_variable *y = in_highp_var(type, "y"); + ir_variable *carry = out_lowp_var(type, "carry"); MAKE_SIG(type, gpu_shader5_or_es31_or_integer_functions, 3, x, y, carry); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(assign(carry, ir_builder::carry(x, y))); body.emit(ret(add(x, y))); @@ -7771,10 +7845,11 @@ builtin_builder::_addSaturate(builtin_available_predicate avail, ir_function_signature * builtin_builder::_usubBorrow(const glsl_type *type) { - ir_variable *x = in_var(type, "x"); - ir_variable *y = in_var(type, "y"); - ir_variable *borrow = out_var(type, "borrow"); + ir_variable *x = in_highp_var(type, "x"); + ir_variable *y = in_highp_var(type, "y"); + ir_variable *borrow = out_lowp_var(type, "borrow"); MAKE_SIG(type, gpu_shader5_or_es31_or_integer_functions, 3, x, y, borrow); + sig->return_precision = GLSL_PRECISION_HIGH; body.emit(assign(borrow, ir_builder::borrow(x, y))); body.emit(ret(sub(x, y))); @@ -7835,10 +7910,10 @@ builtin_builder::_mulExtended(const glsl_type *type) unpack_type = glsl_type::uvec2_type; } - ir_variable *x = in_var(type, "x"); - ir_variable *y = in_var(type, "y"); - ir_variable *msb = out_var(type, "msb"); - ir_variable *lsb = out_var(type, "lsb"); + ir_variable *x = in_highp_var(type, "x"); + ir_variable *y = in_highp_var(type, "y"); + ir_variable *msb = out_highp_var(type, "msb"); + ir_variable *lsb = out_highp_var(type, "lsb"); MAKE_SIG(glsl_type::void_type, gpu_shader5_or_es31_or_integer_functions, 4, x, y, msb, lsb); ir_variable *unpack_val = body.make_temp(unpack_type, "_unpack_val"); @@ -8303,6 +8378,10 @@ builtin_builder::_image(image_prototype_ctr prototype, } else { ir_variable *ret_val = body.make_temp(sig->return_type, "_ret_val"); + /* all non-void image functions return highp, so make our temporary and return + * value in the signature highp. + */ + ret_val->data.precision = GLSL_PRECISION_HIGH; body.emit(call(f, ret_val, sig->parameters)); body.emit(ret(ret_val)); } @@ -8312,6 +8391,7 @@ builtin_builder::_image(image_prototype_ctr prototype, } else { sig->intrinsic_id = id; } + sig->return_precision = GLSL_PRECISION_HIGH; return sig; } diff --git a/src/compiler/glsl/lower_precision.cpp b/src/compiler/glsl/lower_precision.cpp index 2b01b9a..1912270 100644 --- a/src/compiler/glsl/lower_precision.cpp +++ b/src/compiler/glsl/lower_precision.cpp @@ -431,7 +431,7 @@ handle_call(ir_call *ir, const struct set *lowerable_rvalues) ir_rvalue *param = (ir_rvalue*)ir->actual_parameters.get_head(); ir_variable *resource = param->variable_referenced(); - assert(ir->callee->return_precision == GLSL_PRECISION_NONE); + assert(ir->callee->return_precision == GLSL_PRECISION_HIGH); assert(resource->type->without_array()->is_image()); /* GLSL ES 3.20 requires that images have a precision modifier, but if @@ -460,7 +460,7 @@ handle_call(ir_call *ir, const struct set *lowerable_rvalues) } /* Return the declared precision for user-defined functions. */ - if (!ir->callee->is_builtin()) + if (!ir->callee->is_builtin() || ir->callee->return_precision != GLSL_PRECISION_NONE) return ir->callee->return_precision; /* Handle special calls. */ @@ -476,10 +476,6 @@ handle_call(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 GLSL_PRECISION_HIGH; - /* textureGatherOffsets always takes a highp array of constants. As * per the discussion https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16547#note_1393704 * trying to lower the precision results in segfault later on @@ -493,40 +489,18 @@ handle_call(ir_call *ir, const struct set *lowerable_rvalues) } } - if (/* Parameters are always highp: */ + if (ir->callee->return_precision != GLSL_PRECISION_NONE) + return ir->callee->return_precision; + + if (/* Parameters are always implicitly promoted to 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") || /* Atomic functions are not lowered. */ strstr(ir->callee_name(), "atomic") == ir->callee_name()) return GLSL_PRECISION_HIGH; - assert(ir->callee->return_precision == GLSL_PRECISION_NONE); - /* Number of parameters to check if they are lowerable. */ unsigned check_parameters = ir->actual_parameters.length(); @@ -538,11 +512,6 @@ handle_call(ir_call *ir, const struct set *lowerable_rvalues) 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; } /* If the call is to a builtin, then the function won’t have a return @@ -587,10 +556,12 @@ find_lowerable_rvalues_visitor::visit_leave(ir_call *ir) handle_precision(var->type, return_precision); if (lower_state == SHOULD_LOWER) { - /* There probably shouldn’t be any situations where multiple ir_call - * instructions write to the same temporary? + /* Function calls always write to a temporary return value in the caller, + * which has no other users. That temp may start with the precision of + * the function's signature, but if we're inferring the precision of an + * unqualified builtin operation (particularly the imageLoad overrides!) + * then we need to update it. */ - assert(var->data.precision == GLSL_PRECISION_NONE); var->data.precision = GLSL_PRECISION_MEDIUM; } else { var->data.precision = GLSL_PRECISION_HIGH;