summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler/glsl/ast_to_hir.cpp3
-rw-r--r--src/compiler/glsl/ir.h6
-rw-r--r--src/compiler/glsl/linker.cpp41
-rw-r--r--src/compiler/glsl/lower_named_interface_blocks.cpp2
4 files changed, 49 insertions, 3 deletions
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
index adedcbbdf3c..a9a1ba3c48c 100644
--- a/src/compiler/glsl/ast_to_hir.cpp
+++ b/src/compiler/glsl/ast_to_hir.cpp
@@ -4330,6 +4330,8 @@ handle_tess_ctrl_shader_output_decl(struct _mesa_glsl_parse_state *state,
if (var->data.patch)
return;
+ var->data.tess_varying_implicit_sized_array = var->type->is_unsized_array();
+
validate_layout_qualifier_vertex_count(state, loc, var, num_vertices,
&state->tcs_output_size,
"tessellation control shader output");
@@ -4366,6 +4368,7 @@ handle_tess_shader_input_decl(struct _mesa_glsl_parse_state *state,
if (var->type->is_unsized_array()) {
var->type = glsl_type::get_array_instance(var->type->fields.array,
state->Const.MaxPatchVertices);
+ var->data.tess_varying_implicit_sized_array = true;
} else if (var->type->length != state->Const.MaxPatchVertices) {
_mesa_glsl_error(&loc, state,
"per-vertex tessellation shader input arrays must be "
diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h
index 3d28dd5731f..f07e3b20910 100644
--- a/src/compiler/glsl/ir.h
+++ b/src/compiler/glsl/ir.h
@@ -833,6 +833,12 @@ public:
unsigned implicit_sized_array:1;
/**
+ * Is this a non-patch TCS output / TES input array that was implicitly
+ * sized to gl_MaxPatchVertices?
+ */
+ unsigned tess_varying_implicit_sized_array:1;
+
+ /**
* Whether this is a fragment shader output implicitly initialized with
* the previous contents of the specified render target at the
* framebuffer location corresponding to this shader invocation.
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index 116e17b5004..215fcc409f7 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -3584,6 +3584,7 @@ static gl_shader_variable *
create_shader_variable(struct gl_shader_program *shProg,
const ir_variable *in,
const char *name, const glsl_type *type,
+ const glsl_type *interface_type,
bool use_implicit_location, int location,
const glsl_type *outermost_struct_type)
{
@@ -3641,7 +3642,7 @@ create_shader_variable(struct gl_shader_program *shProg,
out->type = type;
out->outermost_struct_type = outermost_struct_type;
- out->interface_type = in->get_interface_type();
+ out->interface_type = interface_type;
out->component = in->data.location_frac;
out->index = in->data.index;
out->patch = in->data.patch;
@@ -3653,6 +3654,17 @@ create_shader_variable(struct gl_shader_program *shProg,
return out;
}
+static const glsl_type *
+resize_to_max_patch_vertices(const struct gl_context *ctx,
+ const glsl_type *type)
+{
+ if (!type)
+ return NULL;
+
+ return glsl_type::get_array_instance(type->fields.array,
+ ctx->Const.MaxPatchVertices);
+}
+
static bool
add_shader_variable(const struct gl_context *ctx,
struct gl_shader_program *shProg,
@@ -3699,6 +3711,29 @@ add_shader_variable(const struct gl_context *ctx,
}
default: {
+ const glsl_type *interface_type = var->get_interface_type();
+
+ /* Unsized (non-patch) TCS output/TES input arrays are implicitly
+ * sized to gl_MaxPatchVertices. Internally, we shrink them to a
+ * smaller size.
+ *
+ * This can cause trouble with SSO programs. Since the TCS declares
+ * the number of output vertices, we can always shrink TCS output
+ * arrays. However, the TES might not be linked with a TCS, in
+ * which case it won't know the size of the patch. In other words,
+ * the TCS and TES may disagree on the (smaller) array sizes. This
+ * can result in the resource names differing across stages, causing
+ * SSO validation failures and other cascading issues.
+ *
+ * Expanding the array size to the full gl_MaxPatchVertices fixes
+ * these issues. It's also what program interface queries expect,
+ * as that is the official size of the array.
+ */
+ if (var->data.tess_varying_implicit_sized_array) {
+ type = resize_to_max_patch_vertices(ctx, type);
+ interface_type = resize_to_max_patch_vertices(ctx, interface_type);
+ }
+
/* Issue #16 of the ARB_program_interface_query spec says:
*
* "* If a variable is a member of an interface block without an
@@ -3711,8 +3746,7 @@ add_shader_variable(const struct gl_context *ctx,
*/
const char *prefixed_name = (var->data.from_named_ifc_block &&
!is_gl_identifier(var->name))
- ? ralloc_asprintf(shProg, "%s.%s", var->get_interface_type()->name,
- name)
+ ? ralloc_asprintf(shProg, "%s.%s", interface_type->name, name)
: name;
/* The ARB_program_interface_query spec says:
@@ -3723,6 +3757,7 @@ add_shader_variable(const struct gl_context *ctx,
*/
gl_shader_variable *sha_v =
create_shader_variable(shProg, var, prefixed_name, type,
+ interface_type,
use_implicit_location, location,
outermost_struct_type);
if (!sha_v)
diff --git a/src/compiler/glsl/lower_named_interface_blocks.cpp b/src/compiler/glsl/lower_named_interface_blocks.cpp
index a00e60dd771..53ef638c9c4 100644
--- a/src/compiler/glsl/lower_named_interface_blocks.cpp
+++ b/src/compiler/glsl/lower_named_interface_blocks.cpp
@@ -193,6 +193,8 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
new_var->data.patch = iface_t->fields.structure[i].patch;
new_var->data.stream = var->data.stream;
new_var->data.how_declared = var->data.how_declared;
+ new_var->data.tess_varying_implicit_sized_array =
+ var->data.tess_varying_implicit_sized_array;
new_var->data.from_named_ifc_block = 1;
new_var->init_interface_type(var->type);