|
|
@@ -57,6 +57,10 @@ |
|
|
|
#include "program/hash_table.h" |
|
|
|
#include "ir.h" |
|
|
|
|
|
|
|
static void |
|
|
|
detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, |
|
|
|
exec_list *instructions); |
|
|
|
|
|
|
|
void |
|
|
|
_mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) |
|
|
|
{ |
|
|
@@ -87,6 +91,7 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) |
|
|
|
ast->hir(instructions, state); |
|
|
|
|
|
|
|
detect_recursion_unlinked(state, instructions); |
|
|
|
detect_conflicting_assignments(state, instructions); |
|
|
|
|
|
|
|
state->toplevel_ir = NULL; |
|
|
|
} |
|
|
@@ -4017,3 +4022,64 @@ ast_struct_specifier::hir(exec_list *instructions, |
|
|
|
*/ |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, |
|
|
|
exec_list *instructions) |
|
|
|
{ |
|
|
|
bool gl_FragColor_assigned = false; |
|
|
|
bool gl_FragData_assigned = false; |
|
|
|
bool user_defined_fs_output_assigned = false; |
|
|
|
ir_variable *user_defined_fs_output = NULL; |
|
|
|
|
|
|
|
/* It would be nice to have proper location information. */ |
|
|
|
YYLTYPE loc; |
|
|
|
memset(&loc, 0, sizeof(loc)); |
|
|
|
|
|
|
|
foreach_list(node, instructions) { |
|
|
|
ir_variable *var = ((ir_instruction *)node)->as_variable(); |
|
|
|
|
|
|
|
if (!var) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (strcmp(var->name, "gl_FragColor") == 0) |
|
|
|
gl_FragColor_assigned = var->assigned; |
|
|
|
else if (strcmp(var->name, "gl_FragData") == 0) |
|
|
|
gl_FragData_assigned = var->assigned; |
|
|
|
else if (strncmp(var->name, "gl_", 3) != 0) { |
|
|
|
if (state->target == fragment_shader && |
|
|
|
(var->mode == ir_var_out || var->mode == ir_var_inout)) { |
|
|
|
user_defined_fs_output_assigned = true; |
|
|
|
user_defined_fs_output = var; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* From the GLSL 1.30 spec: |
|
|
|
* |
|
|
|
* "If a shader statically assigns a value to gl_FragColor, it |
|
|
|
* may not assign a value to any element of gl_FragData. If a |
|
|
|
* shader statically writes a value to any element of |
|
|
|
* gl_FragData, it may not assign a value to |
|
|
|
* gl_FragColor. That is, a shader may assign values to either |
|
|
|
* gl_FragColor or gl_FragData, but not both. Multiple shaders |
|
|
|
* linked together must also consistently write just one of |
|
|
|
* these variables. Similarly, if user declared output |
|
|
|
* variables are in use (statically assigned to), then the |
|
|
|
* built-in variables gl_FragColor and gl_FragData may not be |
|
|
|
* assigned to. These incorrect usages all generate compile |
|
|
|
* time errors." |
|
|
|
*/ |
|
|
|
if (gl_FragColor_assigned && gl_FragData_assigned) { |
|
|
|
_mesa_glsl_error(&loc, state, "fragment shader writes to both " |
|
|
|
"`gl_FragColor' and `gl_FragData'\n"); |
|
|
|
} else if (gl_FragColor_assigned && user_defined_fs_output_assigned) { |
|
|
|
_mesa_glsl_error(&loc, state, "fragment shader writes to both " |
|
|
|
"`gl_FragColor' and `%s'\n", |
|
|
|
user_defined_fs_output->name); |
|
|
|
} else if (gl_FragData_assigned && user_defined_fs_output_assigned) { |
|
|
|
_mesa_glsl_error(&loc, state, "fragment shader writes to both " |
|
|
|
"`gl_FragData' and `%s'\n", |
|
|
|
user_defined_fs_output->name); |
|
|
|
} |
|
|
|
} |