summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/spirv/spirv_to_nir.c126
1 files 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
@@ -4085,6 +4085,70 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode,
}
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: