From d8c0e0805b3693f279d31b190173518231965fbc Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Thu, 21 Jan 2016 12:41:45 -0800 Subject: [PATCH] nir/spirv: Properly assign locations to split structures --- src/glsl/nir/spirv/spirv_to_nir.c | 1 + src/glsl/nir/spirv/vtn_private.h | 3 ++ src/glsl/nir/spirv/vtn_variables.c | 60 +++++++++++++++++++++--------- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/glsl/nir/spirv/spirv_to_nir.c b/src/glsl/nir/spirv/spirv_to_nir.c index 7d9d0981269..32188e5f364 100644 --- a/src/glsl/nir/spirv/spirv_to_nir.c +++ b/src/glsl/nir/spirv/spirv_to_nir.c @@ -585,6 +585,7 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode, val->type = rzalloc(b, struct vtn_type); val->type->is_builtin = false; + val->type->val = val; switch (opcode) { case SpvOpTypeVoid: diff --git a/src/glsl/nir/spirv/vtn_private.h b/src/glsl/nir/spirv/vtn_private.h index e0f4b220c4c..3840d8c4b65 100644 --- a/src/glsl/nir/spirv/vtn_private.h +++ b/src/glsl/nir/spirv/vtn_private.h @@ -196,6 +196,9 @@ struct vtn_ssa_value { struct vtn_type { const struct glsl_type *type; + /* The value that declares this type. Used for finding decorations */ + struct vtn_value *val; + /* for matrices, whether the matrix is stored row-major */ bool row_major; diff --git a/src/glsl/nir/spirv/vtn_variables.c b/src/glsl/nir/spirv/vtn_variables.c index 8171a5fc156..5c372774126 100644 --- a/src/glsl/nir/spirv/vtn_variables.c +++ b/src/glsl/nir/spirv/vtn_variables.c @@ -887,6 +887,43 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member, case SpvDecorationDescriptorSet: vtn_var->descriptor_set = dec->literals[0]; return; + + case SpvDecorationLocation: { + unsigned location = dec->literals[0]; + bool is_vertex_input; + if (b->shader->stage == MESA_SHADER_FRAGMENT && + vtn_var->mode == vtn_variable_mode_output) { + is_vertex_input = false; + location += FRAG_RESULT_DATA0; + } else if (b->shader->stage == MESA_SHADER_VERTEX && + vtn_var->mode == vtn_variable_mode_input) { + is_vertex_input = true; + location += VERT_ATTRIB_GENERIC0; + } else if (vtn_var->mode == vtn_variable_mode_input || + vtn_var->mode == vtn_variable_mode_output) { + is_vertex_input = false; + location += VARYING_SLOT_VAR0; + } else { + assert(!"Location must be on input or output variable"); + } + + if (vtn_var->var) { + vtn_var->var->data.location = location; + vtn_var->var->data.explicit_location = true; + } else { + assert(vtn_var->members); + unsigned length = glsl_get_length(vtn_var->type->type); + for (unsigned i = 0; i < length; i++) { + vtn_var->members[i]->data.location = location; + vtn_var->members[i]->data.explicit_location = true; + location += + glsl_count_attribute_slots(vtn_var->members[i]->interface_type, + is_vertex_input); + } + } + return; + } + default: break; } @@ -899,7 +936,6 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member, assert(member == -1); } else { assert(val->value_type == vtn_value_type_type); - assert(vtn_var->type == val->type); if (member != -1) nir_var = vtn_var->members[member]; } @@ -932,22 +968,6 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member, case SpvDecorationNonWritable: nir_var->data.read_only = true; break; - case SpvDecorationLocation: - nir_var->data.location = dec->literals[0]; - if (b->shader->stage == MESA_SHADER_FRAGMENT && - nir_var->data.mode == nir_var_shader_out) { - nir_var->data.location += FRAG_RESULT_DATA0; - } else if (b->shader->stage == MESA_SHADER_VERTEX && - nir_var->data.mode == nir_var_shader_in) { - nir_var->data.location += VERT_ATTRIB_GENERIC0; - } else if (nir_var->data.mode == nir_var_shader_in || - nir_var->data.mode == nir_var_shader_out) { - nir_var->data.location += VARYING_SLOT_VAR0; - } else { - assert(!"Location must be on input or output variable"); - } - nir_var->data.explicit_location = true; - break; case SpvDecorationComponent: nir_var->data.location_frac = dec->literals[0]; break; @@ -1201,7 +1221,13 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, var->var->interface_type = interface_type->type; var->var->data.mode = nir_mode; } + + /* For inputs and outputs, we need to grab locations and builtin + * information from the interface type. + */ + vtn_foreach_decoration(b, interface_type->val, var_decoration_cb, var); break; + case vtn_variable_mode_param: unreachable("Not created through OpVariable"); } -- 2.30.2