summaryrefslogtreecommitdiffstats
path: root/src/compiler/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/glsl')
-rw-r--r--src/compiler/glsl/ast_function.cpp3
-rw-r--r--src/compiler/glsl/ast_to_hir.cpp63
-rw-r--r--src/compiler/glsl/glsl_parser_extras.cpp1
-rw-r--r--src/compiler/glsl/ir.h8
-rw-r--r--src/compiler/glsl/link_varyings.cpp31
-rw-r--r--src/compiler/glsl/linker.cpp341
-rw-r--r--src/compiler/glsl/tests/varyings_test.cpp78
7 files changed, 254 insertions, 271 deletions
diff --git a/src/compiler/glsl/ast_function.cpp b/src/compiler/glsl/ast_function.cpp
index 0eb456a2b1f..c7fdcb24379 100644
--- a/src/compiler/glsl/ast_function.cpp
+++ b/src/compiler/glsl/ast_function.cpp
@@ -560,7 +560,8 @@ done:
state->symbols->add_global_function(f);
emit_function(state, f);
}
- f->add_signature(sig->clone_prototype(f, NULL));
+ sig = sig->clone_prototype(f, NULL);
+ f->add_signature(sig);
}
}
return sig;
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
index 7213ad8ebec..a4842400288 100644
--- a/src/compiler/glsl/ast_to_hir.cpp
+++ b/src/compiler/glsl/ast_to_hir.cpp
@@ -4211,33 +4211,46 @@ ast_declarator_list::hir(exec_list *instructions,
_mesa_glsl_error(&loc, state,
"invalid type `%s' in empty declaration",
type_name);
- } else if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) {
- /* Empty atomic counter declarations are allowed and useful
- * to set the default offset qualifier.
- */
- return NULL;
- } else if (this->type->qualifier.precision != ast_precision_none) {
- if (this->type->specifier->structure != NULL) {
- _mesa_glsl_error(&loc, state,
- "precision qualifiers can't be applied "
- "to structures");
- } else {
- static const char *const precision_names[] = {
- "highp",
- "highp",
- "mediump",
- "lowp"
- };
+ } else {
+ if (decl_type->base_type == GLSL_TYPE_ARRAY) {
+ /* From Section 4.12 (Empty Declarations) of the GLSL 4.5 spec:
+ *
+ * "The combinations of types and qualifiers that cause
+ * compile-time or link-time errors are the same whether or not
+ * the declaration is empty."
+ */
+ validate_array_dimensions(decl_type, state, &loc);
+ }
- _mesa_glsl_warning(&loc, state,
- "empty declaration with precision qualifier, "
- "to set the default precision, use "
- "`precision %s %s;'",
- precision_names[this->type->qualifier.precision],
- type_name);
+ if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) {
+ /* Empty atomic counter declarations are allowed and useful
+ * to set the default offset qualifier.
+ */
+ return NULL;
+ } else if (this->type->qualifier.precision != ast_precision_none) {
+ if (this->type->specifier->structure != NULL) {
+ _mesa_glsl_error(&loc, state,
+ "precision qualifiers can't be applied "
+ "to structures");
+ } else {
+ static const char *const precision_names[] = {
+ "highp",
+ "highp",
+ "mediump",
+ "lowp"
+ };
+
+ _mesa_glsl_warning(&loc, state,
+ "empty declaration with precision "
+ "qualifier, to set the default precision, "
+ "use `precision %s %s;'",
+ precision_names[this->type->
+ qualifier.precision],
+ type_name);
+ }
+ } else if (this->type->specifier->structure == NULL) {
+ _mesa_glsl_warning(&loc, state, "empty declaration");
}
- } else if (this->type->specifier->structure == NULL) {
- _mesa_glsl_warning(&loc, state, "empty declaration");
}
}
diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp
index d7a4b254aa2..73d378c4bc9 100644
--- a/src/compiler/glsl/glsl_parser_extras.cpp
+++ b/src/compiler/glsl/glsl_parser_extras.cpp
@@ -27,6 +27,7 @@
#include "main/core.h" /* for struct gl_context */
#include "main/context.h"
+#include "main/debug_output.h"
#include "main/shaderobj.h"
#include "util/u_atomic.h" /* for p_atomic_cmpxchg */
#include "util/ralloc.h"
diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h
index 09e21b22188..bf9b7caffae 100644
--- a/src/compiler/glsl/ir.h
+++ b/src/compiler/glsl/ir.h
@@ -864,6 +864,14 @@ public:
int location;
/**
+ * for glsl->tgsi/mesa IR we need to store the index into the
+ * parameters for uniforms, initially the code overloaded location
+ * but this causes problems with indirect samplers and AoA.
+ * This is assigned in _mesa_generate_parameters_list_for_uniforms.
+ */
+ int param_index;
+
+ /**
* Vertex stream output identifier.
*/
unsigned stream;
diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp
index a4c730ffdcf..590de174507 100644
--- a/src/compiler/glsl/link_varyings.cpp
+++ b/src/compiler/glsl/link_varyings.cpp
@@ -1352,7 +1352,7 @@ private:
namespace linker {
-bool
+void
populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
hash_table *consumer_inputs,
hash_table *consumer_interface_inputs,
@@ -1366,8 +1366,8 @@ populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
ir_variable *const input_var = node->as_variable();
if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) {
- if (input_var->type->is_interface())
- return false;
+ /* All interface blocks should have been lowered by this point */
+ assert(!input_var->type->is_interface());
if (input_var->data.explicit_location) {
/* assign_varying_locations only cares about finding the
@@ -1401,8 +1401,6 @@ populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
}
}
}
-
- return true;
}
/**
@@ -1626,18 +1624,11 @@ assign_varying_locations(struct gl_context *ctx,
if (producer)
canonicalize_shader_io(producer->ir, ir_var_shader_out);
- if (consumer
- && !linker::populate_consumer_input_sets(mem_ctx,
- consumer->ir,
- consumer_inputs,
- consumer_interface_inputs,
- consumer_inputs_with_locations)) {
- assert(!"populate_consumer_input_sets failed");
- hash_table_dtor(tfeedback_candidates);
- hash_table_dtor(consumer_inputs);
- hash_table_dtor(consumer_interface_inputs);
- return false;
- }
+ if (consumer)
+ linker::populate_consumer_input_sets(mem_ctx, consumer->ir,
+ consumer_inputs,
+ consumer_interface_inputs,
+ consumer_inputs_with_locations);
if (producer) {
foreach_in_list(ir_instruction, node, producer->ir) {
@@ -1652,8 +1643,10 @@ assign_varying_locations(struct gl_context *ctx,
(output_var->data.stream < MAX_VERTEX_STREAMS &&
producer->Stage == MESA_SHADER_GEOMETRY));
- tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
- g.process(output_var);
+ if (num_tfeedback_decls > 0) {
+ tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
+ g.process(output_var);
+ }
ir_variable *const input_var =
linker::get_matching_input(mem_ctx, output_var, consumer_inputs,
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index 4776ffa6acd..bad1c1742b7 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -82,8 +82,6 @@
#include "main/enums.h"
-void linker_error(gl_shader_program *, const char *, ...);
-
namespace {
/**
@@ -2125,6 +2123,7 @@ link_intrastage_shaders(void *mem_ctx,
if (ok) {
memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *));
+ _mesa_glsl_initialize_builtin_functions();
linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader();
ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1);
@@ -4105,15 +4104,34 @@ disable_varying_optimizations_for_sso(struct gl_shader_program *prog)
void
link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
{
+ prog->LinkStatus = true; /* All error paths will set this to false */
+ prog->Validated = false;
+ prog->_Used = false;
+
+ /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec says:
+ *
+ * "Linking can fail for a variety of reasons as specified in the
+ * OpenGL Shading Language Specification, as well as any of the
+ * following reasons:
+ *
+ * - No shader objects are attached to program."
+ *
+ * The Compatibility Profile specification does not list the error. In
+ * Compatibility Profile missing shader stages are replaced by
+ * fixed-function. This applies to the case where all stages are
+ * missing.
+ */
+ if (prog->NumShaders == 0) {
+ if (ctx->API != API_OPENGL_COMPAT)
+ linker_error(prog, "no shaders attached to the program\n");
+ return;
+ }
+
tfeedback_decl *tfeedback_decls = NULL;
unsigned num_tfeedback_decls = prog->TransformFeedback.NumVarying;
void *mem_ctx = ralloc_context(NULL); // temporary linker context
- prog->LinkStatus = true; /* All error paths will set this to false */
- prog->Validated = false;
- prog->_Used = false;
-
prog->ARB_fragment_coord_conventions_enable = false;
/* Separate the shaders into groups based on their type.
@@ -4129,13 +4147,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
unsigned min_version = UINT_MAX;
unsigned max_version = 0;
- const bool is_es_prog =
- (prog->NumShaders > 0 && prog->Shaders[0]->IsES) ? true : false;
for (unsigned i = 0; i < prog->NumShaders; i++) {
min_version = MIN2(min_version, prog->Shaders[i]->Version);
max_version = MAX2(max_version, prog->Shaders[i]->Version);
- if (prog->Shaders[i]->IsES != is_es_prog) {
+ if (prog->Shaders[i]->IsES != prog->Shaders[0]->IsES) {
linker_error(prog, "all shaders must use same shading "
"language version\n");
goto done;
@@ -4153,80 +4169,59 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
/* In desktop GLSL, different shader versions may be linked together. In
* GLSL ES, all shader versions must be the same.
*/
- if (is_es_prog && min_version != max_version) {
+ if (prog->Shaders[0]->IsES && min_version != max_version) {
linker_error(prog, "all shaders must use same shading "
"language version\n");
goto done;
}
prog->Version = max_version;
- prog->IsES = is_es_prog;
-
- /* From OpenGL 4.5 Core specification (7.3 Program Objects):
- * "Linking can fail for a variety of reasons as specified in the OpenGL
- * Shading Language Specification, as well as any of the following
- * reasons:
- *
- * * No shader objects are attached to program.
- *
- * ..."
- *
- * Same rule applies for OpenGL ES >= 3.1.
- */
-
- if (prog->NumShaders == 0 &&
- ((ctx->API == API_OPENGL_CORE && ctx->Version >= 45) ||
- (ctx->API == API_OPENGLES2 && ctx->Version >= 31))) {
- linker_error(prog, "No shader objects are attached to program.\n");
- goto done;
- }
+ prog->IsES = prog->Shaders[0]->IsES;
/* Some shaders have to be linked with some other shaders present.
*/
- if (num_shaders[MESA_SHADER_GEOMETRY] > 0 &&
- num_shaders[MESA_SHADER_VERTEX] == 0 &&
- !prog->SeparateShader) {
- linker_error(prog, "Geometry shader must be linked with "
- "vertex shader\n");
- goto done;
- }
- if (num_shaders[MESA_SHADER_TESS_EVAL] > 0 &&
- num_shaders[MESA_SHADER_VERTEX] == 0 &&
- !prog->SeparateShader) {
- linker_error(prog, "Tessellation evaluation shader must be linked with "
- "vertex shader\n");
- goto done;
- }
- if (num_shaders[MESA_SHADER_TESS_CTRL] > 0 &&
- num_shaders[MESA_SHADER_VERTEX] == 0 &&
- !prog->SeparateShader) {
- linker_error(prog, "Tessellation control shader must be linked with "
- "vertex shader\n");
- goto done;
- }
+ if (!prog->SeparateShader) {
+ if (num_shaders[MESA_SHADER_GEOMETRY] > 0 &&
+ num_shaders[MESA_SHADER_VERTEX] == 0) {
+ linker_error(prog, "Geometry shader must be linked with "
+ "vertex shader\n");
+ goto done;
+ }
+ if (num_shaders[MESA_SHADER_TESS_EVAL] > 0 &&
+ num_shaders[MESA_SHADER_VERTEX] == 0) {
+ linker_error(prog, "Tessellation evaluation shader must be linked "
+ "with vertex shader\n");
+ goto done;
+ }
+ if (num_shaders[MESA_SHADER_TESS_CTRL] > 0 &&
+ num_shaders[MESA_SHADER_VERTEX] == 0) {
+ linker_error(prog, "Tessellation control shader must be linked with "
+ "vertex shader\n");
+ goto done;
+ }
- /* The spec is self-contradictory here. It allows linking without a tess
- * eval shader, but that can only be used with transform feedback and
- * rasterization disabled. However, transform feedback isn't allowed
- * with GL_PATCHES, so it can't be used.
- *
- * More investigation showed that the idea of transform feedback after
- * a tess control shader was dropped, because some hw vendors couldn't
- * support tessellation without a tess eval shader, but the linker section
- * wasn't updated to reflect that.
- *
- * All specifications (ARB_tessellation_shader, GL 4.0-4.5) have this
- * spec bug.
- *
- * Do what's reasonable and always require a tess eval shader if a tess
- * control shader is present.
- */
- if (num_shaders[MESA_SHADER_TESS_CTRL] > 0 &&
- num_shaders[MESA_SHADER_TESS_EVAL] == 0 &&
- !prog->SeparateShader) {
- linker_error(prog, "Tessellation control shader must be linked with "
- "tessellation evaluation shader\n");
- goto done;
+ /* The spec is self-contradictory here. It allows linking without a tess
+ * eval shader, but that can only be used with transform feedback and
+ * rasterization disabled. However, transform feedback isn't allowed
+ * with GL_PATCHES, so it can't be used.
+ *
+ * More investigation showed that the idea of transform feedback after
+ * a tess control shader was dropped, because some hw vendors couldn't
+ * support tessellation without a tess eval shader, but the linker
+ * section wasn't updated to reflect that.
+ *
+ * All specifications (ARB_tessellation_shader, GL 4.0-4.5) have this
+ * spec bug.
+ *
+ * Do what's reasonable and always require a tess eval shader if a tess
+ * control shader is present.
+ */
+ if (num_shaders[MESA_SHADER_TESS_CTRL] > 0 &&
+ num_shaders[MESA_SHADER_TESS_EVAL] == 0) {
+ linker_error(prog, "Tessellation control shader must be linked with "
+ "tessellation evaluation shader\n");
+ goto done;
+ }
}
/* Compute shaders have additional restrictions. */
@@ -4362,7 +4357,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
*
* This rule also applies to GLSL ES 3.00.
*/
- if (max_version >= (is_es_prog ? 300 : 130)) {
+ if (max_version >= (prog->IsES ? 300 : 130)) {
struct gl_shader *sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
if (sh) {
lower_discard_flow(sh->ir);
@@ -4451,9 +4446,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
* non-zero, but the program object has no vertex or geometry
* shader;
*/
- if (first == MESA_SHADER_FRAGMENT) {
+ if (first >= MESA_SHADER_FRAGMENT) {
linker_error(prog, "Transform feedback varyings specified, but "
- "no vertex or geometry shader is present.\n");
+ "no vertex, tessellation, or geometry shader is "
+ "present.\n");
goto done;
}
@@ -4465,91 +4461,80 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done;
}
- /* Linking the stages in the opposite order (from fragment to vertex)
- * ensures that inter-shader outputs written to in an earlier stage are
- * eliminated if they are (transitively) not used in a later stage.
+ /* If there is no fragment shader we need to set transform feedback.
+ *
+ * For SSO we need also need to assign output locations, we assign them
+ * here because we need to do it for both single stage programs and multi
+ * stage programs.
*/
- int next;
-
- if (first < MESA_SHADER_FRAGMENT) {
- gl_shader *const sh = prog->_LinkedShaders[last];
-
- if (first != MESA_SHADER_VERTEX) {
- /* There was no vertex shader, but we still have to assign varying
- * locations for use by tessellation/geometry shader inputs in SSO.
- *
- * If the shader is not separable (i.e., prog->SeparateShader is
- * false), linking will have already failed when first is not
- * MESA_SHADER_VERTEX.
- */
- if (!assign_varying_locations(ctx, mem_ctx, prog,
- NULL, prog->_LinkedShaders[first],
- num_tfeedback_decls, tfeedback_decls))
- goto done;
- }
-
- if (last != MESA_SHADER_FRAGMENT &&
- (num_tfeedback_decls != 0 || prog->SeparateShader)) {
- /* There was no fragment shader, but we still have to assign varying
- * locations for use by transform feedback.
- */
- if (!assign_varying_locations(ctx, mem_ctx, prog,
- sh, NULL,
- num_tfeedback_decls, tfeedback_decls))
- goto done;
- }
-
- do_dead_builtin_varyings(ctx, sh, NULL,
- num_tfeedback_decls, tfeedback_decls);
+ if (last < MESA_SHADER_FRAGMENT &&
+ (num_tfeedback_decls != 0 || prog->SeparateShader)) {
+ if (!assign_varying_locations(ctx, mem_ctx, prog,
+ prog->_LinkedShaders[last], NULL,
+ num_tfeedback_decls, tfeedback_decls))
+ goto done;
+ }
- remove_unused_shader_inputs_and_outputs(prog->SeparateShader, sh,
+ if (last <= MESA_SHADER_FRAGMENT) {
+ /* Remove unused varyings from the first/last stage unless SSO */
+ remove_unused_shader_inputs_and_outputs(prog->SeparateShader,
+ prog->_LinkedShaders[first],
+ ir_var_shader_in);
+ remove_unused_shader_inputs_and_outputs(prog->SeparateShader,
+ prog->_LinkedShaders[last],
ir_var_shader_out);
- }
- else if (first == MESA_SHADER_FRAGMENT) {
- /* If the program only contains a fragment shader...
- */
- gl_shader *const sh = prog->_LinkedShaders[first];
- do_dead_builtin_varyings(ctx, NULL, sh,
- num_tfeedback_decls, tfeedback_decls);
+ /* If the program is made up of only a single stage */
+ if (first == last) {
- if (prog->SeparateShader) {
- if (!assign_varying_locations(ctx, mem_ctx, prog,
- NULL /* producer */,
- sh /* consumer */,
- 0 /* num_tfeedback_decls */,
- NULL /* tfeedback_decls */))
- goto done;
- } else {
- remove_unused_shader_inputs_and_outputs(false, sh,
- ir_var_shader_in);
- }
- }
+ gl_shader *const sh = prog->_LinkedShaders[last];
+ if (prog->SeparateShader) {
+ /* Assign input locations for SSO, output locations are already
+ * assigned.
+ */
+ if (!assign_varying_locations(ctx, mem_ctx, prog,
+ NULL /* producer */,
+ sh /* consumer */,
+ 0 /* num_tfeedback_decls */,
+ NULL /* tfeedback_decls */))
+ goto done;
+ }
- next = last;
- for (int i = next - 1; i >= 0; i--) {
- if (prog->_LinkedShaders[i] == NULL)
- continue;
+ do_dead_builtin_varyings(ctx, NULL, sh, 0, NULL);
+ do_dead_builtin_varyings(ctx, sh, NULL, num_tfeedback_decls,
+ tfeedback_decls);
+ } else {
+ /* Linking the stages in the opposite order (from fragment to vertex)
+ * ensures that inter-shader outputs written to in an earlier stage
+ * are eliminated if they are (transitively) not used in a later
+ * stage.
+ */
+ int next = last;
+ for (int i = next - 1; i >= 0; i--) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
- gl_shader *const sh_i = prog->_LinkedShaders[i];
- gl_shader *const sh_next = prog->_LinkedShaders[next];
+ gl_shader *const sh_i = prog->_LinkedShaders[i];
+ gl_shader *const sh_next = prog->_LinkedShaders[next];
- if (!assign_varying_locations(ctx, mem_ctx, prog, sh_i, sh_next,
- next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
- tfeedback_decls))
- goto done;
+ if (!assign_varying_locations(ctx, mem_ctx, prog, sh_i, sh_next,
+ next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
+ tfeedback_decls))
+ goto done;
- do_dead_builtin_varyings(ctx, sh_i, sh_next,
- next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
- tfeedback_decls);
+ do_dead_builtin_varyings(ctx, sh_i, sh_next,
+ next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
+ tfeedback_decls);
- /* This must be done after all dead varyings are eliminated. */
- if (!check_against_output_limit(ctx, prog, sh_i))
- goto done;
- if (!check_against_input_limit(ctx, prog, sh_next))
- goto done;
+ /* This must be done after all dead varyings are eliminated. */
+ if (!check_against_output_limit(ctx, prog, sh_i))
+ goto done;
+ if (!check_against_input_limit(ctx, prog, sh_next))
+ goto done;
- next = i;
+ next = i;
+ }
+ }
}
if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls))
@@ -4569,38 +4554,38 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
if (!prog->LinkStatus)
goto done;
- /* OpenGL ES requires that a vertex shader and a fragment shader both be
- * present in a linked program. GL_ARB_ES2_compatibility doesn't say
+ /* OpenGL ES < 3.1 requires that a vertex shader and a fragment shader both
+ * be present in a linked program. GL_ARB_ES2_compatibility doesn't say
* anything about shader linking when one of the shaders (vertex or
* fragment shader) is absent. So, the extension shouldn't change the
* behavior specified in GLSL specification.
+ *
+ * From OpenGL ES 3.1 specification (7.3 Program Objects):
+ * "Linking can fail for a variety of reasons as specified in the
+ * OpenGL ES Shading Language Specification, as well as any of the
+ * following reasons:
+ *
+ * ...
+ *
+ * * program contains objects to form either a vertex shader or
+ * fragment shader, and program is not separable, and does not
+ * contain objects to form both a vertex shader and fragment
+ * shader."
+ *
+ * However, the only scenario in 3.1+ where we don't require them both is
+ * when we have a compute shader. For example:
+ *
+ * - No shaders is a link error.
+ * - Geom or Tess without a Vertex shader is a link error which means we
+ * always require a Vertex shader and hence a Fragment shader.
+ * - Finally a Compute shader linked with any other stage is a link error.
*/
- if (!prog->SeparateShader && ctx->API == API_OPENGLES2) {
- /* With ES < 3.1 one needs to have always vertex + fragment shader. */
- if (ctx->Version < 31) {
- if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
- linker_error(prog, "program lacks a vertex shader\n");
- } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
- linker_error(prog, "program lacks a fragment shader\n");
- }
- } else {
- /* From OpenGL ES 3.1 specification (7.3 Program Objects):
- * "Linking can fail for a variety of reasons as specified in the
- * OpenGL ES Shading Language Specification, as well as any of the
- * following reasons:
- *
- * ...
- *
- * * program contains objects to form either a vertex shader or
- * fragment shader, and program is not separable, and does not
- * contain objects to form both a vertex shader and fragment
- * shader."
- */
- if (!!prog->_LinkedShaders[MESA_SHADER_VERTEX] ^
- !!prog->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
- linker_error(prog, "Program needs to contain both vertex and "
- "fragment shaders.\n");
- }
+ if (!prog->SeparateShader && ctx->API == API_OPENGLES2 &&
+ num_shaders[MESA_SHADER_COMPUTE] == 0) {
+ if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
+ linker_error(prog, "program lacks a vertex shader\n");
+ } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
+ linker_error(prog, "program lacks a fragment shader\n");
}
}
diff --git a/src/compiler/glsl/tests/varyings_test.cpp b/src/compiler/glsl/tests/varyings_test.cpp
index 0c4e0a471b8..9be5e8344b4 100644
--- a/src/compiler/glsl/tests/varyings_test.cpp
+++ b/src/compiler/glsl/tests/varyings_test.cpp
@@ -156,11 +156,11 @@ TEST_F(link_varyings, single_simple_input)
ir.push_tail(v);
- ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
- &ir,
- consumer_inputs,
- consumer_interface_inputs,
- junk));
+ linker::populate_consumer_input_sets(mem_ctx,
+ &ir,
+ consumer_inputs,
+ consumer_interface_inputs,
+ junk);
EXPECT_EQ((void *) v, hash_table_find(consumer_inputs, "a"));
EXPECT_EQ(1u, num_elements(consumer_inputs));
@@ -183,11 +183,11 @@ TEST_F(link_varyings, gl_ClipDistance)
ir.push_tail(clipdistance);
- ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
- &ir,
- consumer_inputs,
- consumer_interface_inputs,
- junk));
+ linker::populate_consumer_input_sets(mem_ctx,
+ &ir,
+ consumer_inputs,
+ consumer_interface_inputs,
+ junk);
EXPECT_EQ(clipdistance, junk[VARYING_SLOT_CLIP_DIST0]);
EXPECT_TRUE(is_empty(consumer_inputs));
@@ -205,11 +205,11 @@ TEST_F(link_varyings, single_interface_input)
ir.push_tail(v);
- ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
- &ir,
- consumer_inputs,
- consumer_interface_inputs,
- junk));
+ linker::populate_consumer_input_sets(mem_ctx,
+ &ir,
+ consumer_inputs,
+ consumer_interface_inputs,
+ junk);
char *const full_name = interface_field_name(simple_interface);
EXPECT_EQ((void *) v, hash_table_find(consumer_interface_inputs, full_name));
@@ -236,11 +236,11 @@ TEST_F(link_varyings, one_interface_and_one_simple_input)
ir.push_tail(iface);
- ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
- &ir,
- consumer_inputs,
- consumer_interface_inputs,
- junk));
+ linker::populate_consumer_input_sets(mem_ctx,
+ &ir,
+ consumer_inputs,
+ consumer_interface_inputs,
+ junk);
char *const iface_field_name = interface_field_name(simple_interface);
@@ -252,24 +252,6 @@ TEST_F(link_varyings, one_interface_and_one_simple_input)
EXPECT_EQ(1u, num_elements(consumer_inputs));
}
-TEST_F(link_varyings, invalid_interface_input)
-{
- ir_variable *const v =
- new(mem_ctx) ir_variable(simple_interface,
- "named_interface",
- ir_var_shader_in);
-
- ASSERT_EQ(simple_interface, v->get_interface_type());
-
- ir.push_tail(v);
-
- EXPECT_FALSE(linker::populate_consumer_input_sets(mem_ctx,
- &ir,
- consumer_inputs,
- consumer_interface_inputs,
- junk));
-}
-
TEST_F(link_varyings, interface_field_doesnt_match_noninterface)
{
char *const iface_field_name = interface_field_name(simple_interface);
@@ -283,11 +265,11 @@ TEST_F(link_varyings, interface_field_doesnt_match_noninterface)
ir.push_tail(in_v);
- ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
- &ir,
- consumer_inputs,
- consumer_interface_inputs,
- junk));
+ linker::populate_consumer_input_sets(mem_ctx,
+ &ir,
+ consumer_inputs,
+ consumer_interface_inputs,
+ junk);
/* Create an output variable, "v", that is part of an interface block named
* "a". They should not match.
@@ -325,11 +307,11 @@ TEST_F(link_varyings, interface_field_doesnt_match_noninterface_vice_versa)
ir.push_tail(in_v);
- ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
- &ir,
- consumer_inputs,
- consumer_interface_inputs,
- junk));
+ linker::populate_consumer_input_sets(mem_ctx,
+ &ir,
+ consumer_inputs,
+ consumer_interface_inputs,
+ junk);
/* Create an output variable "a.v". They should not match.
*/