On Friday, 2017-11-24 14:27:11 +0200, Topi Pohjolainen wrote: > At least the following need more thought: > > 1) Converting right-hand-side of assignments from 16-bits to 32-bits > - More correct thing to do is to treat rhs as 32-bits latest in the > expression producing the value > > 2) Texture arguments except coordinates are not handled at all > - Moreover, coordinates are always converted into 32-bits due to > logic missing in the Intel compiler backend. > > Signed-off-by: Topi Pohjolainen <topi.pohjolai...@intel.com> > --- > src/compiler/Makefile.sources | 1 + > src/compiler/glsl/ir_optimization.h | 1 + > src/compiler/glsl/lower_mediump.cpp | 273 > ++++++++++++++++++++++++++++++++++++ > 3 files changed, 275 insertions(+) > create mode 100644 src/compiler/glsl/lower_mediump.cpp > > diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources > index 2ab8e163a2..47bde4fb78 100644 > --- a/src/compiler/Makefile.sources > +++ b/src/compiler/Makefile.sources > @@ -94,6 +94,7 @@ LIBGLSL_FILES = \ > glsl/lower_int64.cpp \ > glsl/lower_jumps.cpp \ > glsl/lower_mat_op_to_vec.cpp \ > + glsl/lower_mediump.cpp \ > glsl/lower_noise.cpp \ > glsl/lower_offset_array.cpp \ > glsl/lower_packed_varyings.cpp \
----8<---- diff --git a/src/compiler/glsl/meson.build b/src/compiler/glsl/meson.build index 5b505c007a03d8d2e19b..1bfc2106738caf3a266f 100644 --- a/src/compiler/glsl/meson.build +++ b/src/compiler/glsl/meson.build @@ -133,6 +133,7 @@ files_libglsl = files( 'lower_int64.cpp', 'lower_jumps.cpp', 'lower_mat_op_to_vec.cpp', + 'lower_mediump.cpp', 'lower_noise.cpp', 'lower_offset_array.cpp', 'lower_packed_varyings.cpp', ---->8---- > diff --git a/src/compiler/glsl/ir_optimization.h > b/src/compiler/glsl/ir_optimization.h > index 2b8c195151..09c4d664e0 100644 > --- a/src/compiler/glsl/ir_optimization.h > +++ b/src/compiler/glsl/ir_optimization.h > @@ -132,6 +132,7 @@ bool do_vec_index_to_swizzle(exec_list *instructions); > bool lower_discard(exec_list *instructions); > void lower_discard_flow(exec_list *instructions); > bool lower_instructions(exec_list *instructions, unsigned what_to_lower); > +bool lower_mediump(struct gl_linked_shader *shader); > bool lower_noise(exec_list *instructions); > bool lower_variable_index_to_cond_assign(gl_shader_stage stage, > exec_list *instructions, bool lower_input, bool lower_output, > diff --git a/src/compiler/glsl/lower_mediump.cpp > b/src/compiler/glsl/lower_mediump.cpp > new file mode 100644 > index 0000000000..89eed8b294 > --- /dev/null > +++ b/src/compiler/glsl/lower_mediump.cpp > @@ -0,0 +1,273 @@ > +/* > + * Copyright 2017 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > + * DEALINGS IN THE SOFTWARE. > + */ > + > +/** > + * \file lower_mediump.cpp > + * > + */ > + > +#include "compiler/glsl_types.h" > +#include "ir.h" > +#include "ir_rvalue_visitor.h" > +#include "ast.h" > + > +static const glsl_type * > +get_mediump(const glsl_type *highp) > +{ > + if (highp->is_float()) > + return glsl_type::get_instance(GLSL_TYPE_FLOAT16, > + highp->vector_elements, > + highp->matrix_columns); > + > + if (highp->is_array() && highp->fields.array->is_float()) > + return glsl_type::get_array_instance( > + glsl_type::get_instance(GLSL_TYPE_FLOAT16, > + > highp->fields.array->vector_elements, > + highp->fields.array->matrix_columns), > + highp->length); > + > + return highp; > +} > + > +static bool > +is_16_bit(const ir_rvalue *ir) > +{ > + return ir->type->get_scalar_type()->base_type == GLSL_TYPE_FLOAT16; > +} > + > +static bool > +refers_16_bit_float(const ir_rvalue *ir) > +{ > + ir_variable *var = ir->variable_referenced(); > + > + /* Only variables have the mediump property, constants need conversion. */ > + if (!var) > + return false; > + > + return var->type->get_scalar_type()->base_type == GLSL_TYPE_FLOAT16; > +} > + > +static ir_rvalue * > +convert(ir_rvalue *ir, enum ir_expression_operation op) > +{ > + if (ir->ir_type == ir_type_constant) { > + assert(op == ir_unop_f2h); > + ir->type = get_mediump(ir->type); > + return ir; > + } > + > + void *ctx = ralloc_parent(ir); > + return new(ctx) ir_expression(op, ir); > +} > + > +class lower_mediump_visitor : public ir_rvalue_visitor { > +public: > + lower_mediump_visitor() : progress(false) {} > + > + virtual ir_visitor_status visit(ir_variable *ir); > + virtual ir_visitor_status visit(ir_dereference_variable *ir); > + > + virtual ir_visitor_status visit_leave(ir_assignment *ir); > + virtual ir_visitor_status visit_leave(ir_expression *ir); > + virtual ir_visitor_status visit_leave(ir_swizzle *ir); > + > + virtual void handle_rvalue(ir_rvalue **rvalue); > + > + bool progress; > + > +private: > + bool can_be_lowered(const ir_variable *var) const; > + > + void retype_to_float16(const glsl_type **t); > +}; > + > +bool > +lower_mediump_visitor::can_be_lowered(const ir_variable *var) const > +{ > + if (!var->type->get_scalar_type()->is_float()) > + return false; > + > + return var->data.precision == ast_precision_low || > + var->data.precision == ast_precision_medium; > +} > + > +void > +lower_mediump_visitor::retype_to_float16(const glsl_type **t) > +{ > + const glsl_type * const mediump = get_mediump(*t); > + progress = mediump != *t; > + *t = mediump; > +} > + > +ir_visitor_status > +lower_mediump_visitor::visit(ir_variable *ir) > +{ > + if (!can_be_lowered(ir)) > + return visit_continue; > + > + const glsl_type * const mediump = get_mediump(ir->type); > + progress = mediump != ir->type; > + ir->type = mediump; > + > + return visit_continue; > +} > + > +ir_visitor_status > +lower_mediump_visitor::visit(ir_dereference_variable *ir) > +{ > + if (!refers_16_bit_float(ir)) > + return visit_continue; > + > + const glsl_type * const mediump = get_mediump(ir->type); > + progress = mediump != ir->type; > + ir->type = mediump; > + > + return visit_continue; > +} > + > +ir_visitor_status > +lower_mediump_visitor::visit_leave(ir_assignment *ir) > +{ > + ir_rvalue_visitor::visit_leave(ir); > + > + if (!ir->lhs || !ir->rhs) > + return visit_continue; > + > + ir_variable *lhs = ir->lhs->variable_referenced(); > + if (lhs == NULL) > + return visit_continue; > + > + /* Consider if the dereference targets 16-bit variable. In such case lower > + * the dereference type and emit conversion for the source if needed. > + */ > + if (refers_16_bit_float(ir->lhs)) { > + retype_to_float16(&ir->lhs->type); > + > + /* Consider if source needs conversion to float16. */ > + if (!is_16_bit(ir->rhs)) > + ir->rhs = convert(ir->rhs, ir_unop_f2h); > + > + return visit_continue; > + } > + > + /* If in turn target is 32-bit but source is 16-bit, emit conversion. */ > + if (is_16_bit(ir->rhs)) > + ir->rhs = convert(ir->rhs, ir_unop_h2f); > + > + return visit_continue; > +} > + > +ir_visitor_status > +lower_mediump_visitor::visit_leave(ir_swizzle *ir) > +{ > + ir_rvalue_visitor::visit_leave(ir); > + > + if (is_16_bit(ir->val)) > + retype_to_float16(&ir->type); > + > + return visit_continue; > +} > + > +/* Consider expressions in depth-first order according to the rules found in > + * GLES 3.2 Specification, 4.7.3 Precision Qualifiers: > + * > + * In cases where operands do not have a precision qualifier, the precision > + * qualification will come from the other operands. If no operands have a > + * precision qualifier, then the precision qualifications of the operands of > + * the next consuming operation in the expression will be used. This rule > can > + * be applied recursively until a precision qualified operand is found. If > + * necessary, it will also include the precision qualification of l-values > for > + * assignments, of the declared variable for initializers, of formal > + * parameters for function call arguments, or of function return types for > + * function return values. If the precision cannot be determined by this > + * method e.g. if an entire expression is composed only of operands with no > + * precision qualifier, and the result is not assigned or passed as an > + * argument, then it is evaluated at the default precision of the type or > + * greater. When this occurs in the fragment shader, the default precision > + * must be defined. > + * > + * For example, consider the statements: > + * > + * uniform highp float h1; > + * highp float h2 = 2.3 * 4.7; // operation and result are highp precision > + * mediump float m; > + * m = 3.7 * h1 * h2; // all operations are highp precision > + * h2 = m * h1; // operation is highp precision > + * m = h2 - h1; // operation is highp precision > + * h2 = m + m; // addition and result at mediump precision > + * void f(highp float p); > + * f(3.3); // 3.3 will be passed in at highp precisi > + */ > +ir_visitor_status > +lower_mediump_visitor::visit_leave(ir_expression *ir) > +{ > + ir_rvalue_visitor::visit_leave(ir); > + > + bool has_32_bit_src = false; > + bool has_16_bit_src = false; > + for (unsigned i = 0; i < ir->num_operands; i++) { > + if (is_16_bit(ir->operands[i])) > + has_16_bit_src = true; > + else > + has_32_bit_src = true; > + } > + > + if (!has_16_bit_src) > + return visit_continue; > + > + /* If there are no 32-bit source operands the expression can be evaluated > + * in lower precision. > + */ > + if (!has_32_bit_src && > + ir->operation != ir_triop_lrp) { > + retype_to_float16(&ir->type); > + return visit_continue; > + } > + > + /* All other 16-bit operands need to be converted to 32-bits in order to > + * perform the operation in 32-bits. > + */ > + for (unsigned i = 0; i < ir->num_operands; i++) { > + if (is_16_bit(ir->operands[i])) > + ir->operands[i] = convert(ir->operands[i], ir_unop_h2f); > + } > + > + return visit_continue; > +} > + > +void > +lower_mediump_visitor::handle_rvalue(ir_rvalue **rvalue) > +{ > + if (*rvalue == NULL || !refers_16_bit_float(*rvalue)) > + return; > + > + retype_to_float16(&(*rvalue)->type); > +} > + > +bool > +lower_mediump(struct gl_linked_shader *shader) > +{ > + lower_mediump_visitor v; > + visit_list_elements(&v, shader->ir); > + return v.progress; > +} > -- > 2.11.0 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev