From 3781697c23f5e75ab7a18cdec7140c779bb56ce7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 30 Jun 2020 20:24:44 -0400 Subject: [PATCH] glsl: don't lower builtins to mediump that don't allow it Reviewed-by: Alyssa Rosenzweig Part-of: --- src/compiler/glsl/ir_validate.cpp | 28 +- src/compiler/glsl/lower_precision.cpp | 30 +- .../glsl/tests/lower_precision_test.py | 283 ++++++++++++++++++ src/compiler/glsl_types.h | 8 + 4 files changed, 334 insertions(+), 15 deletions(-) diff --git a/src/compiler/glsl/ir_validate.cpp b/src/compiler/glsl/ir_validate.cpp index 4f96ef0031b..426862c039c 100644 --- a/src/compiler/glsl/ir_validate.cpp +++ b/src/compiler/glsl/ir_validate.cpp @@ -388,20 +388,20 @@ ir_validate::visit_leave(ir_expression *ir) assert(ir->type->is_int_16_32()); break; case ir_unop_bitcast_i2f: - assert(ir->operands[0]->type->is_int_16_32()); - assert(ir->type->is_float_16_32()); + assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT); + assert(ir->type->base_type == GLSL_TYPE_FLOAT); break; case ir_unop_bitcast_f2i: - assert(ir->operands[0]->type->is_float_16_32()); - assert(ir->type->is_int_16_32()); + assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); + assert(ir->type->base_type == GLSL_TYPE_INT); break; case ir_unop_bitcast_u2f: - assert(ir->operands[0]->type->is_uint_16_32()); - assert(ir->type->is_float_16_32()); + assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT); + assert(ir->type->base_type == GLSL_TYPE_FLOAT); break; case ir_unop_bitcast_f2u: - assert(ir->operands[0]->type->is_float_16_32()); - assert(ir->type->is_uint_16_32()); + assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT); + assert(ir->type->base_type == GLSL_TYPE_UINT); break; case ir_unop_bitcast_u642d: @@ -598,7 +598,7 @@ ir_validate::visit_leave(ir_expression *ir) case ir_unop_bitfield_reverse: assert(ir->operands[0]->type == ir->type); - assert(ir->type->is_integer_16_32()); + assert(ir->type->is_integer_32()); break; case ir_unop_bit_count: @@ -687,12 +687,12 @@ ir_validate::visit_leave(ir_expression *ir) break; case ir_unop_frexp_sig: - assert(ir->operands[0]->type->is_float_16_32_64()); + assert(ir->operands[0]->type->is_float_32_64()); assert(ir->type->is_double()); break; case ir_unop_frexp_exp: - assert(ir->operands[0]->type->is_float_16_32_64()); - assert(ir->type->is_int_16_32()); + assert(ir->operands[0]->type->is_float_32_64()); + assert(ir->type->base_type == GLSL_TYPE_INT); break; case ir_unop_subroutine_to_int: assert(ir->operands[0]->type->base_type == GLSL_TYPE_SUBROUTINE); @@ -847,8 +847,8 @@ ir_validate::visit_leave(ir_expression *ir) case ir_binop_ldexp: assert(ir->operands[0]->type == ir->type); - assert(ir->operands[0]->type->is_float_16_32_64()); - assert(ir->operands[1]->type->is_int_16_32()); + assert(ir->operands[0]->type->is_float_32_64()); + assert(ir->operands[1]->type->base_type == GLSL_TYPE_INT); assert(ir->operands[0]->type->components() == ir->operands[1]->type->components()); break; diff --git a/src/compiler/glsl/lower_precision.cpp b/src/compiler/glsl/lower_precision.cpp index 2529a35b4dd..e9975322e84 100644 --- a/src/compiler/glsl/lower_precision.cpp +++ b/src/compiler/glsl/lower_precision.cpp @@ -466,7 +466,35 @@ is_lowerable_builtin(ir_call *ir, } } - 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); diff --git a/src/compiler/glsl/tests/lower_precision_test.py b/src/compiler/glsl/tests/lower_precision_test.py index 9651a066ed6..3fa74050ed8 100644 --- a/src/compiler/glsl/tests/lower_precision_test.py +++ b/src/compiler/glsl/tests/lower_precision_test.py @@ -1176,6 +1176,289 @@ TESTS = [ } """, r'expression ivec2 \* \(txs ivec2 \(var_ref tex'), + Test("floatBitsToInt", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform float val; + out int color; + + void main() + { + color = floatBitsToInt(val + 1.0) + 1; + } + """, + r'expression int bitcast_f2i \(expression float'), + Test("floatBitsToUint", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform float val; + out uint color; + + void main() + { + color = floatBitsToUint(val + 1.0) + 1u; + } + """, + r'expression uint bitcast_f2u \(expression float'), + Test("intBitsToFloat", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform int val; + out float color; + + void main() + { + color = intBitsToFloat(val + 1) + 1.0; + } + """, + r'expression float bitcast_i2f \(expression int'), + Test("uintBitsToFloat", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform uint val; + out float color; + + void main() + { + color = uintBitsToFloat(val + 1u) + 1.0; + } + """, + r'expression float bitcast_u2f \(expression uint'), + Test("bitfieldReverse", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform int val; + out int color; + + void main() + { + color = bitfieldReverse(val + 1) + 1; + } + """, + r'expression int bitfield_reverse \(expression int'), + Test("frexp", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform float val; + out float color; + out int color2; + + void main() + { + int y; + float x = frexp(val + 1.0, y); + color = x + 1.0; + color2 = y + 1; + } + """, + r'assign \(x\) \(var_ref x\) \(expression float f162f'), + Test("ldexp", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform float val; + uniform int exp; + out float color; + + void main() + { + color = ldexp(val + 1.0, exp + 1) + 1.0; + } + """, + r'expression float ldexp \(expression float'), + Test("uaddCarry", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform uint x, y; + out uint color; + + void main() + { + lowp uint carry; + color = uaddCarry(x * 2u, y * 2u, carry) * 2u; + color *= carry; + } + """, + r'expression uint \+ \(var_ref x\) \(var_ref y'), + Test("usubBorrow", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform uint x, y; + out uint color; + + void main() + { + lowp uint borrow; + color = usubBorrow(x * 2u, y * 2u, borrow) * 2u; + color *= borrow; + } + """, + r'expression uint \+ \(var_ref x\) \(expression uint neg'), + Test("imulExtended", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform int x, y; + out int color; + + void main() + { + int msb, lsb; + imulExtended(x + 2, y + 2, msb, lsb); + color = msb + lsb; + } + """, + r'expression int64_t \* \(expression int'), + Test("umulExtended", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform uint x, y; + out uint color; + + void main() + { + uint msb, lsb; + umulExtended(x + 2u, y + 2u, msb, lsb); + color = msb + lsb; + } + """, + r'expression uint64_t \* \(expression uint'), + Test("unpackUnorm2x16", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform uint val; + out vec2 color; + + void main() + { + color = unpackUnorm2x16(val + 1u) + vec2(1.0); + } + """, + r'expression vec2 unpackUnorm2x16 \(expression uint'), + Test("unpackSnorm2x16", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform uint val; + out vec2 color; + + void main() + { + color = unpackSnorm2x16(val + 1u) + vec2(1.0); + } + """, + r'expression vec2 unpackSnorm2x16 \(expression uint'), + Test("packUnorm2x16", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform vec2 val; + out uint color; + + void main() + { + color = packUnorm2x16(val + vec2(1.0)) + 1u; + } + """, + r'expression uint packUnorm2x16 \(expression vec2'), + Test("packSnorm2x16", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform vec2 val; + out uint color; + + void main() + { + color = packSnorm2x16(val + vec2(1.0)) + 1u; + } + """, + r'expression uint packSnorm2x16 \(expression vec2'), + Test("packHalf2x16", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform vec2 val; + out uint color; + + void main() + { + color = packHalf2x16(val + vec2(1.0)) + 1u; + } + """, + r'expression uint packHalf2x16 \(expression vec2'), + Test("packUnorm4x8", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform vec4 val; + out uint color; + + void main() + { + color = packUnorm4x8(val + vec4(1.0)) + 1u; + } + """, + r'expression uint packUnorm4x8 \(expression vec4'), + Test("packSnorm4x8", + """ + #version 310 es + precision mediump float; + precision mediump int; + + uniform vec4 val; + out uint color; + + void main() + { + color = packSnorm4x8(val + vec4(1.0)) + 1u; + } + """, + r'expression uint packSnorm4x8 \(expression vec4'), ] diff --git a/src/compiler/glsl_types.h b/src/compiler/glsl_types.h index 4654ad7cf57..df5ca4629e5 100644 --- a/src/compiler/glsl_types.h +++ b/src/compiler/glsl_types.h @@ -811,6 +811,14 @@ public: return base_type == GLSL_TYPE_FLOAT16 || is_float() || is_double(); } + /** + * Query whether or not a type is a float or double + */ + bool is_float_32_64() const + { + return is_float() || is_double(); + } + bool is_int_16_32_64() const { return base_type == GLSL_TYPE_INT16 || -- 2.30.2