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 <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21666>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user