From 17630291e516efcc8940a8e4de45586ca9a578b5 Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Mon, 3 Jun 2019 15:30:33 -0700 Subject: [PATCH] spirv: Move OpSelect handling to a function This will make a later change easier to review. Reviewed-by: Jason Ekstrand --- src/compiler/spirv/spirv_to_nir.c | 126 ++++++++++++++++-------------- 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 42fbc680230..8032a7b79c6 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -4084,6 +4084,70 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode, return true; } +static void +vtn_handle_select(struct vtn_builder *b, SpvOp opcode, + const uint32_t *w, unsigned count) +{ + /* Handle OpSelect up-front here because it needs to be able to handle + * pointers and not just regular vectors and scalars. + */ + struct vtn_value *res_val = vtn_untyped_value(b, w[2]); + struct vtn_value *sel_val = vtn_untyped_value(b, w[3]); + struct vtn_value *obj1_val = vtn_untyped_value(b, w[4]); + struct vtn_value *obj2_val = vtn_untyped_value(b, w[5]); + + const struct glsl_type *sel_type; + switch (res_val->type->base_type) { + case vtn_base_type_scalar: + sel_type = glsl_bool_type(); + break; + case vtn_base_type_vector: + sel_type = glsl_vector_type(GLSL_TYPE_BOOL, res_val->type->length); + break; + case vtn_base_type_pointer: + /* We need to have actual storage for pointer types */ + vtn_fail_if(res_val->type->type == NULL, + "Invalid pointer result type for OpSelect"); + sel_type = glsl_bool_type(); + break; + default: + vtn_fail("Result type of OpSelect must be a scalar, vector, or pointer"); + } + + if (unlikely(sel_val->type->type != sel_type)) { + if (sel_val->type->type == glsl_bool_type()) { + /* This case is illegal but some older versions of GLSLang produce + * it. The GLSLang issue was fixed on March 30, 2017: + * + * https://github.com/KhronosGroup/glslang/issues/809 + * + * Unfortunately, there are applications in the wild which are + * shipping with this bug so it isn't nice to fail on them so we + * throw a warning instead. It's not actually a problem for us as + * nir_builder will just splat the condition out which is most + * likely what the client wanted anyway. + */ + vtn_warn("Condition type of OpSelect must have the same number " + "of components as Result Type"); + } else { + vtn_fail("Condition type of OpSelect must be a scalar or vector " + "of Boolean type. It must have the same number of " + "components as Result Type"); + } + } + + vtn_fail_if(obj1_val->type != res_val->type || + obj2_val->type != res_val->type, + "Object types must match the result type in OpSelect"); + + struct vtn_type *res_type = vtn_value(b, w[1], vtn_value_type_type)->type; + struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, res_type->type); + ssa->def = nir_bcsel(&b->nb, vtn_ssa_value(b, w[3])->def, + vtn_ssa_value(b, w[4])->def, + vtn_ssa_value(b, w[5])->def); + vtn_push_ssa(b, w[2], res_type, ssa); +} + static void vtn_handle_ptr(struct vtn_builder *b, SpvOp opcode, const uint32_t *w, unsigned count) @@ -4258,67 +4322,9 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode, break; } - case SpvOpSelect: { - /* Handle OpSelect up-front here because it needs to be able to handle - * pointers and not just regular vectors and scalars. - */ - struct vtn_value *res_val = vtn_untyped_value(b, w[2]); - struct vtn_value *sel_val = vtn_untyped_value(b, w[3]); - struct vtn_value *obj1_val = vtn_untyped_value(b, w[4]); - struct vtn_value *obj2_val = vtn_untyped_value(b, w[5]); - - const struct glsl_type *sel_type; - switch (res_val->type->base_type) { - case vtn_base_type_scalar: - sel_type = glsl_bool_type(); - break; - case vtn_base_type_vector: - sel_type = glsl_vector_type(GLSL_TYPE_BOOL, res_val->type->length); - break; - case vtn_base_type_pointer: - /* We need to have actual storage for pointer types */ - vtn_fail_if(res_val->type->type == NULL, - "Invalid pointer result type for OpSelect"); - sel_type = glsl_bool_type(); - break; - default: - vtn_fail("Result type of OpSelect must be a scalar, vector, or pointer"); - } - - if (unlikely(sel_val->type->type != sel_type)) { - if (sel_val->type->type == glsl_bool_type()) { - /* This case is illegal but some older versions of GLSLang produce - * it. The GLSLang issue was fixed on March 30, 2017: - * - * https://github.com/KhronosGroup/glslang/issues/809 - * - * Unfortunately, there are applications in the wild which are - * shipping with this bug so it isn't nice to fail on them so we - * throw a warning instead. It's not actually a problem for us as - * nir_builder will just splat the condition out which is most - * likely what the client wanted anyway. - */ - vtn_warn("Condition type of OpSelect must have the same number " - "of components as Result Type"); - } else { - vtn_fail("Condition type of OpSelect must be a scalar or vector " - "of Boolean type. It must have the same number of " - "components as Result Type"); - } - } - - vtn_fail_if(obj1_val->type != res_val->type || - obj2_val->type != res_val->type, - "Object types must match the result type in OpSelect"); - - struct vtn_type *res_type = vtn_value(b, w[1], vtn_value_type_type)->type; - struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, res_type->type); - ssa->def = nir_bcsel(&b->nb, vtn_ssa_value(b, w[3])->def, - vtn_ssa_value(b, w[4])->def, - vtn_ssa_value(b, w[5])->def); - vtn_push_ssa(b, w[2], res_type, ssa); + case SpvOpSelect: + vtn_handle_select(b, opcode, w, count); break; - } case SpvOpSNegate: case SpvOpFNegate: -- 2.30.2