From 6f25d45877a1e1a7ac6250a7d051d33485e0cba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Fri, 3 Jun 2022 14:00:11 +0200 Subject: [PATCH] spirv: handle phis decorated with RelaxedPrecision If the driver can do 16-bit ALU ops, then store RelaxedPrecision phi values into 16-bit NIR variables with downconverts/upconverts on the way in/out. This has no impact on shader-db on freedreno (not that we have a ton of GLES content there), but it does cause an ANGLE-translated CTS shader on vulkan to get consistent conversions between two copies of a value, and avoid a test bug. Reviewed-by: Emma Anholt Closes: #6585 Part-of: --- src/compiler/spirv/vtn_cfg.c | 39 +++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c index e0f88322f6a..9f1853befbe 100644 --- a/src/compiler/spirv/vtn_cfg.c +++ b/src/compiler/spirv/vtn_cfg.c @@ -921,13 +921,34 @@ vtn_handle_phis_first_pass(struct vtn_builder *b, SpvOp opcode, * algorithm all over again. It's easier if we just let * lower_vars_to_ssa do that for us instead of repeating it here. */ - struct vtn_type *type = vtn_get_type(b, w[1]); - nir_variable *phi_var = - nir_local_variable_create(b->nb.impl, type->type, "phi"); + bool relaxed_precision = false; + if (b->options->mediump_16bit_alu) { + struct vtn_value *phi_val = vtn_untyped_value(b, w[2]); + relaxed_precision = vtn_value_is_relaxed_precision(b, phi_val); + } + + const struct glsl_type *dest_type = vtn_get_type(b, w[1])->type; + const struct glsl_type *type = dest_type; + if (relaxed_precision) { + if (glsl_get_base_type(type) == GLSL_TYPE_FLOAT) + type = glsl_float16_type(type); + else if (glsl_get_base_type(type) == GLSL_TYPE_INT) + type = glsl_int16_type(type); + else if (glsl_get_base_type(type) == GLSL_TYPE_UINT) + type = glsl_uint16_type(type); + } + + nir_variable *phi_var = nir_local_variable_create(b->nb.impl, type, "phi"); _mesa_hash_table_insert(b->phi_table, w, phi_var); - vtn_push_ssa_value(b, w[2], - vtn_local_load(b, nir_build_deref_var(&b->nb, phi_var), 0)); + struct vtn_ssa_value *dest = + vtn_local_load(b, nir_build_deref_var(&b->nb, phi_var), 0); + + if (relaxed_precision) { + dest->type = dest_type; + vtn_mediump_upconvert_value(b, dest); + } + vtn_push_ssa_value(b, w[2], dest); return true; } @@ -948,6 +969,12 @@ vtn_handle_phi_second_pass(struct vtn_builder *b, SpvOp opcode, if (phi_entry == NULL) return true; + bool relaxed_precision = false; + if (b->options->mediump_16bit_alu) { + struct vtn_value *phi_val = vtn_untyped_value(b, w[2]); + relaxed_precision = vtn_value_is_relaxed_precision(b, phi_val); + } + nir_variable *phi_var = phi_entry->data; for (unsigned i = 3; i < count; i += 2) { @@ -961,6 +988,8 @@ vtn_handle_phi_second_pass(struct vtn_builder *b, SpvOp opcode, b->nb.cursor = nir_after_instr(&pred->end_nop->instr); struct vtn_ssa_value *src = vtn_ssa_value(b, w[i]); + if (relaxed_precision) + src = vtn_mediump_downconvert_value(b, src); vtn_local_store(b, src, nir_build_deref_var(&b->nb, phi_var), 0); }