From 668ab9f19d86d34672c2e390ff6f412dae9c6191 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Sun, 21 Apr 2019 12:42:21 +0200 Subject: [PATCH] glsl: Add support for float16 types in the IR tree MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reviewed-by: Marek Olšák Reviewed-by: Alyssa Rosenzweig Reviewed-by: Ian Romanick Part-of: --- src/compiler/glsl/glsl_to_nir.cpp | 11 ++++ src/compiler/glsl/ir.cpp | 57 ++++++++++++++++++-- src/compiler/glsl/ir.h | 2 + src/compiler/glsl/ir_constant_expression.cpp | 1 + src/compiler/glsl/ir_print_visitor.cpp | 27 ++++++---- 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index fed456a36ea..8f15cd55fcb 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -316,6 +316,7 @@ nir_visitor::constant_copy(ir_constant *ir, void *mem_ctx) break; case GLSL_TYPE_FLOAT: + case GLSL_TYPE_FLOAT16: case GLSL_TYPE_DOUBLE: if (cols > 1) { ret->elements = ralloc_array(mem_ctx, nir_constant *, cols); @@ -329,6 +330,11 @@ nir_visitor::constant_copy(ir_constant *ir, void *mem_ctx) col_const->values[r].f32 = ir->value.f[c * rows + r]; break; + case GLSL_TYPE_FLOAT16: + for (unsigned r = 0; r < rows; r++) + col_const->values[r].u16 = ir->value.f16[c * rows + r]; + break; + case GLSL_TYPE_DOUBLE: for (unsigned r = 0; r < rows; r++) col_const->values[r].f64 = ir->value.d[c * rows + r]; @@ -346,6 +352,11 @@ nir_visitor::constant_copy(ir_constant *ir, void *mem_ctx) ret->values[r].f32 = ir->value.f[r]; break; + case GLSL_TYPE_FLOAT16: + for (unsigned r = 0; r < rows; r++) + ret->values[r].u16 = ir->value.f16[r]; + break; + case GLSL_TYPE_DOUBLE: for (unsigned r = 0; r < rows; r++) ret->values[r].f64 = ir->value.d[r]; diff --git a/src/compiler/glsl/ir.cpp b/src/compiler/glsl/ir.cpp index 57551850757..d9bc83501cd 100644 --- a/src/compiler/glsl/ir.cpp +++ b/src/compiler/glsl/ir.cpp @@ -22,6 +22,7 @@ */ #include #include "ir.h" +#include "util/half_float.h" #include "compiler/glsl_types.h" #include "glsl_parser_extras.h" @@ -796,6 +797,7 @@ ir_constant::ir_constant(const ir_constant *c, unsigned i) case GLSL_TYPE_UINT: this->value.u[0] = c->value.u[i]; break; case GLSL_TYPE_INT: this->value.i[0] = c->value.i[i]; break; case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break; + case GLSL_TYPE_FLOAT16: this->value.f16[0] = c->value.f16[i]; break; case GLSL_TYPE_BOOL: this->value.b[0] = c->value.b[i]; break; case GLSL_TYPE_DOUBLE: this->value.d[0] = c->value.d[i]; break; default: assert(!"Should not get here."); break; @@ -841,14 +843,23 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) if (value->type->is_scalar() && value->next->is_tail_sentinel()) { if (type->is_matrix()) { /* Matrix - fill diagonal (rest is already set to 0) */ - assert(type->is_float() || type->is_double()); for (unsigned i = 0; i < type->matrix_columns; i++) { - if (type->is_float()) + switch (type->base_type) { + case GLSL_TYPE_FLOAT: this->value.f[i * type->vector_elements + i] = value->value.f[0]; - else + break; + case GLSL_TYPE_DOUBLE: this->value.d[i * type->vector_elements + i] = value->value.d[0]; + break; + case GLSL_TYPE_FLOAT16: + this->value.f16[i * type->vector_elements + i] = + value->value.f16[0]; + break; + default: + assert(!"unexpected matrix base type"); + } } } else { /* Vector or scalar - fill all components */ @@ -862,6 +873,10 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) for (unsigned i = 0; i < type->components(); i++) this->value.f[i] = value->value.f[0]; break; + case GLSL_TYPE_FLOAT16: + for (unsigned i = 0; i < type->components(); i++) + this->value.f16[i] = value->value.f16[0]; + break; case GLSL_TYPE_DOUBLE: for (unsigned i = 0; i < type->components(); i++) this->value.d[i] = value->value.d[0]; @@ -931,6 +946,9 @@ ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) case GLSL_TYPE_FLOAT: this->value.f[i] = value->get_float_component(j); break; + case GLSL_TYPE_FLOAT16: + this->value.f16[i] = value->get_float16_component(j); + break; case GLSL_TYPE_BOOL: this->value.b[i] = value->get_bool_component(j); break; @@ -996,6 +1014,7 @@ ir_constant::get_bool_component(unsigned i) const case GLSL_TYPE_UINT: return this->value.u[i] != 0; case GLSL_TYPE_INT: return this->value.i[i] != 0; case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0; + case GLSL_TYPE_FLOAT16: return ((int)_mesa_half_to_float(this->value.f16[i])) != 0; case GLSL_TYPE_BOOL: return this->value.b[i]; case GLSL_TYPE_DOUBLE: return this->value.d[i] != 0.0; case GLSL_TYPE_SAMPLER: @@ -1018,6 +1037,7 @@ ir_constant::get_float_component(unsigned i) const case GLSL_TYPE_UINT: return (float) this->value.u[i]; case GLSL_TYPE_INT: return (float) this->value.i[i]; case GLSL_TYPE_FLOAT: return this->value.f[i]; + case GLSL_TYPE_FLOAT16: return _mesa_half_to_float(this->value.f16[i]); case GLSL_TYPE_BOOL: return this->value.b[i] ? 1.0f : 0.0f; case GLSL_TYPE_DOUBLE: return (float) this->value.d[i]; case GLSL_TYPE_SAMPLER: @@ -1033,6 +1053,15 @@ ir_constant::get_float_component(unsigned i) const return 0.0; } +uint16_t +ir_constant::get_float16_component(unsigned i) const +{ + if (this->type->base_type == GLSL_TYPE_FLOAT16) + return this->value.f16[i]; + else + return _mesa_float_to_half(get_float_component(i)); +} + double ir_constant::get_double_component(unsigned i) const { @@ -1040,6 +1069,7 @@ ir_constant::get_double_component(unsigned i) const case GLSL_TYPE_UINT: return (double) this->value.u[i]; case GLSL_TYPE_INT: return (double) this->value.i[i]; case GLSL_TYPE_FLOAT: return (double) this->value.f[i]; + case GLSL_TYPE_FLOAT16: return (double) _mesa_half_to_float(this->value.f16[i]); case GLSL_TYPE_BOOL: return this->value.b[i] ? 1.0 : 0.0; case GLSL_TYPE_DOUBLE: return this->value.d[i]; case GLSL_TYPE_SAMPLER: @@ -1062,6 +1092,7 @@ ir_constant::get_int_component(unsigned i) const case GLSL_TYPE_UINT: return this->value.u[i]; case GLSL_TYPE_INT: return this->value.i[i]; case GLSL_TYPE_FLOAT: return (int) this->value.f[i]; + case GLSL_TYPE_FLOAT16: return (int) _mesa_half_to_float(this->value.f16[i]); case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0; case GLSL_TYPE_DOUBLE: return (int) this->value.d[i]; case GLSL_TYPE_SAMPLER: @@ -1084,6 +1115,7 @@ ir_constant::get_uint_component(unsigned i) const case GLSL_TYPE_UINT: return this->value.u[i]; case GLSL_TYPE_INT: return this->value.i[i]; case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i]; + case GLSL_TYPE_FLOAT16: return (unsigned) _mesa_half_to_float(this->value.f16[i]); case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0; case GLSL_TYPE_DOUBLE: return (unsigned) this->value.d[i]; case GLSL_TYPE_SAMPLER: @@ -1106,6 +1138,7 @@ ir_constant::get_int64_component(unsigned i) const case GLSL_TYPE_UINT: return this->value.u[i]; case GLSL_TYPE_INT: return this->value.i[i]; case GLSL_TYPE_FLOAT: return (int64_t) this->value.f[i]; + case GLSL_TYPE_FLOAT16: return (int64_t) _mesa_half_to_float(this->value.f16[i]); case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0; case GLSL_TYPE_DOUBLE: return (int64_t) this->value.d[i]; case GLSL_TYPE_SAMPLER: @@ -1128,6 +1161,7 @@ ir_constant::get_uint64_component(unsigned i) const case GLSL_TYPE_UINT: return this->value.u[i]; case GLSL_TYPE_INT: return this->value.i[i]; case GLSL_TYPE_FLOAT: return (uint64_t) this->value.f[i]; + case GLSL_TYPE_FLOAT16: return (uint64_t) _mesa_half_to_float(this->value.f16[i]); case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0; case GLSL_TYPE_DOUBLE: return (uint64_t) this->value.d[i]; case GLSL_TYPE_SAMPLER: @@ -1182,6 +1216,7 @@ ir_constant::copy_offset(ir_constant *src, int offset) case GLSL_TYPE_UINT: case GLSL_TYPE_INT: case GLSL_TYPE_FLOAT: + case GLSL_TYPE_FLOAT16: case GLSL_TYPE_DOUBLE: case GLSL_TYPE_SAMPLER: case GLSL_TYPE_IMAGE: @@ -1201,6 +1236,9 @@ ir_constant::copy_offset(ir_constant *src, int offset) case GLSL_TYPE_FLOAT: value.f[i+offset] = src->get_float_component(i); break; + case GLSL_TYPE_FLOAT16: + value.f16[i+offset] = src->get_float16_component(i); + break; case GLSL_TYPE_BOOL: value.b[i+offset] = src->get_bool_component(i); break; @@ -1260,6 +1298,9 @@ ir_constant::copy_masked_offset(ir_constant *src, int offset, unsigned int mask) case GLSL_TYPE_FLOAT: value.f[i+offset] = src->get_float_component(id++); break; + case GLSL_TYPE_FLOAT16: + value.f16[i+offset] = src->get_float16_component(id++); + break; case GLSL_TYPE_BOOL: value.b[i+offset] = src->get_bool_component(id++); break; @@ -1310,6 +1351,12 @@ ir_constant::has_value(const ir_constant *c) const if (this->value.f[i] != c->value.f[i]) return false; break; + case GLSL_TYPE_FLOAT16: + /* Convert to float to make sure NaN and ±0.0 compares correctly */ + if (_mesa_half_to_float(this->value.f16[i]) != + _mesa_half_to_float(c->value.f16[i])) + return false; + break; case GLSL_TYPE_BOOL: if (this->value.b[i] != c->value.b[i]) return false; @@ -1353,6 +1400,10 @@ ir_constant::is_value(float f, int i) const if (this->value.f[c] != f) return false; break; + case GLSL_TYPE_FLOAT16: + if (_mesa_half_to_float(this->value.f16[c]) != f) + return false; + break; case GLSL_TYPE_INT: if (this->value.i[c] != i) return false; diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h index c43c03c89a7..2e20f4bee7a 100644 --- a/src/compiler/glsl/ir.h +++ b/src/compiler/glsl/ir.h @@ -2180,6 +2180,7 @@ union ir_constant_data { float f[16]; bool b[16]; double d[16]; + uint16_t f16[16]; uint64_t u64[16]; int64_t i64[16]; }; @@ -2244,6 +2245,7 @@ public: /*@{*/ bool get_bool_component(unsigned i) const; float get_float_component(unsigned i) const; + uint16_t get_float16_component(unsigned i) const; double get_double_component(unsigned i) const; int get_int_component(unsigned i) const; unsigned get_uint_component(unsigned i) const; diff --git a/src/compiler/glsl/ir_constant_expression.cpp b/src/compiler/glsl/ir_constant_expression.cpp index d7f0abe8304..4b80282c266 100644 --- a/src/compiler/glsl/ir_constant_expression.cpp +++ b/src/compiler/glsl/ir_constant_expression.cpp @@ -773,6 +773,7 @@ ir_swizzle::constant_expression_value(void *mem_ctx, case GLSL_TYPE_UINT: case GLSL_TYPE_INT: data.u[i] = v->value.u[swiz_idx[i]]; break; case GLSL_TYPE_FLOAT: data.f[i] = v->value.f[swiz_idx[i]]; break; + case GLSL_TYPE_FLOAT16: data.f16[i] = v->value.f16[swiz_idx[i]]; break; case GLSL_TYPE_BOOL: data.b[i] = v->value.b[swiz_idx[i]]; break; case GLSL_TYPE_DOUBLE:data.d[i] = v->value.d[swiz_idx[i]]; break; case GLSL_TYPE_UINT64:data.u64[i] = v->value.u64[swiz_idx[i]]; break; diff --git a/src/compiler/glsl/ir_print_visitor.cpp b/src/compiler/glsl/ir_print_visitor.cpp index 86120e19b19..7533a52ee81 100644 --- a/src/compiler/glsl/ir_print_visitor.cpp +++ b/src/compiler/glsl/ir_print_visitor.cpp @@ -28,6 +28,7 @@ #include "main/macros.h" #include "util/hash_table.h" #include "util/u_string.h" +#include "util/half_float.h" static void print_type(FILE *f, const glsl_type *t); @@ -460,6 +461,19 @@ void ir_print_visitor::visit(ir_assignment *ir) fprintf(f, ") "); } +static void +print_float_constant(FILE *f, float val) +{ + if (val == 0.0f) + /* 0.0 == -0.0, so print with %f to get the proper sign. */ + fprintf(f, "%f", val); + else if (fabs(val) < 0.000001f) + fprintf(f, "%a", val); + else if (fabs(val) > 1000000.0f) + fprintf(f, "%e", val); + else + fprintf(f, "%f", val); +} void ir_print_visitor::visit(ir_constant *ir) { @@ -484,15 +498,10 @@ void ir_print_visitor::visit(ir_constant *ir) case GLSL_TYPE_UINT: fprintf(f, "%u", ir->value.u[i]); break; case GLSL_TYPE_INT: fprintf(f, "%d", ir->value.i[i]); break; case GLSL_TYPE_FLOAT: - if (ir->value.f[i] == 0.0f) - /* 0.0 == -0.0, so print with %f to get the proper sign. */ - fprintf(f, "%f", ir->value.f[i]); - else if (fabs(ir->value.f[i]) < 0.000001f) - fprintf(f, "%a", ir->value.f[i]); - else if (fabs(ir->value.f[i]) > 1000000.0f) - fprintf(f, "%e", ir->value.f[i]); - else - fprintf(f, "%f", ir->value.f[i]); + print_float_constant(f, ir->value.f[i]); + break; + case GLSL_TYPE_FLOAT16: + print_float_constant(f, _mesa_half_to_float(ir->value.f16[i])); break; case GLSL_TYPE_SAMPLER: case GLSL_TYPE_IMAGE: -- 2.30.2