linker: Write errors to info log instead of stdout

This commit is contained in:
Ian Romanick
2010-06-23 12:07:22 -07:00
parent 0e59b2698a
commit f36460e1a7

View File

@@ -65,6 +65,11 @@
*/ */
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#include <cstdarg>
extern "C" {
#include <talloc.h>
}
#include "main/mtypes.h" #include "main/mtypes.h"
#include "glsl_symbol_table.h" #include "glsl_symbol_table.h"
@@ -108,6 +113,18 @@ private:
}; };
void
linker_error_printf(glsl_program *prog, const char *fmt, ...)
{
va_list ap;
prog->InfoLog = talloc_strdup_append(prog->InfoLog, "error: ");
va_start(ap, fmt);
prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, ap);
va_end(ap);
}
void void
invalidate_variable_locations(glsl_shader *sh, enum ir_variable_mode mode, invalidate_variable_locations(glsl_shader *sh, enum ir_variable_mode mode,
int generic_base) int generic_base)
@@ -167,20 +184,22 @@ count_attribute_slots(const glsl_type *t)
* \param shader Vertex shader executable to be verified * \param shader Vertex shader executable to be verified
*/ */
bool bool
validate_vertex_shader_executable(struct glsl_shader *shader) validate_vertex_shader_executable(struct glsl_program *prog,
struct glsl_shader *shader)
{ {
if (shader == NULL) if (shader == NULL)
return true; return true;
if (!shader->symbols->get_function("main")) { if (!shader->symbols->get_function("main")) {
printf("error: vertex shader lacks `main'\n"); linker_error_printf(prog, "vertex shader lacks `main'\n");
return false; return false;
} }
find_assignment_visitor find("gl_Position"); find_assignment_visitor find("gl_Position");
find.run(&shader->ir); find.run(&shader->ir);
if (!find.variable_found()) { if (!find.variable_found()) {
printf("error: vertex shader does not write to `gl_Position'\n"); linker_error_printf(prog,
"vertex shader does not write to `gl_Position'\n");
return false; return false;
} }
@@ -194,13 +213,14 @@ validate_vertex_shader_executable(struct glsl_shader *shader)
* \param shader Fragment shader executable to be verified * \param shader Fragment shader executable to be verified
*/ */
bool bool
validate_fragment_shader_executable(struct glsl_shader *shader) validate_fragment_shader_executable(struct glsl_program *prog,
struct glsl_shader *shader)
{ {
if (shader == NULL) if (shader == NULL)
return true; return true;
if (!shader->symbols->get_function("main")) { if (!shader->symbols->get_function("main")) {
printf("error: fragment shader lacks `main'\n"); linker_error_printf(prog, "fragment shader lacks `main'\n");
return false; return false;
} }
@@ -211,14 +231,14 @@ validate_fragment_shader_executable(struct glsl_shader *shader)
frag_data.run(&shader->ir); frag_data.run(&shader->ir);
if (!frag_color.variable_found() && !frag_data.variable_found()) { if (!frag_color.variable_found() && !frag_data.variable_found()) {
printf("error: fragment shader does not write to `gl_FragColor' or " linker_error_printf(prog, "fragment shader does not write to "
"`gl_FragData'\n"); "`gl_FragColor' or `gl_FragData'\n");
return false; return false;
} }
if (frag_color.variable_found() && frag_data.variable_found()) { if (frag_color.variable_found() && frag_data.variable_found()) {
printf("error: fragment shader write to both `gl_FragColor' and " linker_error_printf(prog, "fragment shader writes to both "
"`gl_FragData'\n"); "`gl_FragColor' and `gl_FragData'\n");
return false; return false;
} }
@@ -230,7 +250,8 @@ validate_fragment_shader_executable(struct glsl_shader *shader)
* Perform validation of uniforms used across multiple shader stages * Perform validation of uniforms used across multiple shader stages
*/ */
bool bool
cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders) cross_validate_uniforms(struct glsl_program *prog,
struct glsl_shader **shaders, unsigned num_shaders)
{ {
/* Examine all of the uniforms in all of the shaders and cross validate /* Examine all of the uniforms in all of the shaders and cross validate
* them. * them.
@@ -250,18 +271,19 @@ cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders)
ir_variable *const existing = uniforms.get_variable(var->name); ir_variable *const existing = uniforms.get_variable(var->name);
if (existing != NULL) { if (existing != NULL) {
if (var->type != existing->type) { if (var->type != existing->type) {
printf("error: uniform `%s' declared as type `%s' and " linker_error_printf(prog, "uniform `%s' declared as type "
"type `%s'\n", "`%s' and type `%s'\n",
var->name, var->type->name, existing->type->name); var->name, var->type->name,
existing->type->name);
return false; return false;
} }
if (var->constant_value != NULL) { if (var->constant_value != NULL) {
if (existing->constant_value != NULL) { if (existing->constant_value != NULL) {
if (!var->constant_value->has_value(existing->constant_value)) { if (!var->constant_value->has_value(existing->constant_value)) {
printf("error: initializers for uniform `%s' have " linker_error_printf(prog, "initializers for uniform "
"differing values\n", "`%s' have differing values\n",
var->name); var->name);
return false; return false;
} }
} else } else
@@ -284,7 +306,8 @@ cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders)
* Validate that outputs from one stage match inputs of another * Validate that outputs from one stage match inputs of another
*/ */
bool bool
cross_validate_outputs_to_inputs(glsl_shader *producer, glsl_shader *consumer) cross_validate_outputs_to_inputs(struct glsl_program *prog,
glsl_shader *producer, glsl_shader *consumer)
{ {
glsl_symbol_table parameters; glsl_symbol_table parameters;
/* FINISHME: Figure these out dynamically. */ /* FINISHME: Figure these out dynamically. */
@@ -324,47 +347,53 @@ cross_validate_outputs_to_inputs(glsl_shader *producer, glsl_shader *consumer)
/* Check that the types match between stages. /* Check that the types match between stages.
*/ */
if (input->type != output->type) { if (input->type != output->type) {
printf("error: %s shader output `%s' delcared as type `%s', but " linker_error_printf(prog,
"%s shader input declared as type `%s'\n", "%s shader output `%s' delcared as "
producer_stage, output->name, output->type->name, "type `%s', but %s shader input declared "
consumer_stage, input->type->name); "as type `%s'\n",
producer_stage, output->name,
output->type->name,
consumer_stage, input->type->name);
return false; return false;
} }
/* Check that all of the qualifiers match between stages. /* Check that all of the qualifiers match between stages.
*/ */
if (input->centroid != output->centroid) { if (input->centroid != output->centroid) {
printf("error: %s shader output `%s' %s centroid qualifier, but " linker_error_printf(prog,
"%s shader input %s centroid qualifier\n", "%s shader output `%s' %s centroid qualifier, "
producer_stage, "but %s shader input %s centroid qualifier\n",
output->name, producer_stage,
(output->centroid) ? "has" : "lacks", output->name,
consumer_stage, (output->centroid) ? "has" : "lacks",
(input->centroid) ? "has" : "lacks"); consumer_stage,
(input->centroid) ? "has" : "lacks");
return false; return false;
} }
if (input->invariant != output->invariant) { if (input->invariant != output->invariant) {
printf("error: %s shader output `%s' %s invariant qualifier, but " linker_error_printf(prog,
"%s shader input %s invariant qualifier\n", "%s shader output `%s' %s invariant qualifier, "
producer_stage, "but %s shader input %s invariant qualifier\n",
output->name, producer_stage,
(output->invariant) ? "has" : "lacks", output->name,
consumer_stage, (output->invariant) ? "has" : "lacks",
(input->invariant) ? "has" : "lacks"); consumer_stage,
(input->invariant) ? "has" : "lacks");
return false; return false;
} }
if (input->interpolation != output->interpolation) { if (input->interpolation != output->interpolation) {
printf("error: %s shader output `%s' specifies %s interpolation " linker_error_printf(prog,
"qualifier, " "%s shader output `%s' specifies %s "
"but %s shader input specifies %s interpolation " "interpolation qualifier, "
"qualifier\n", "but %s shader input specifies %s "
producer_stage, "interpolation qualifier\n",
output->name, producer_stage,
output->interpolation_string(), output->name,
consumer_stage, output->interpolation_string(),
input->interpolation_string()); consumer_stage,
input->interpolation_string());
return false; return false;
} }
} }
@@ -741,6 +770,11 @@ link_shaders(struct glsl_program *prog)
prog->Validated = false; prog->Validated = false;
prog->_Used = false; prog->_Used = false;
if (prog->InfoLog != NULL)
talloc_free(prog->InfoLog);
prog->InfoLog = talloc_strdup(NULL, "");
/* Separate the shaders into groups based on their type. /* Separate the shaders into groups based on their type.
*/ */
struct glsl_shader **vert_shader_list; struct glsl_shader **vert_shader_list;
@@ -775,8 +809,8 @@ link_shaders(struct glsl_program *prog)
/* Verify that each of the per-target executables is valid. /* Verify that each of the per-target executables is valid.
*/ */
if (!validate_vertex_shader_executable(vert_shader_list[0]) if (!validate_vertex_shader_executable(prog, vert_shader_list[0])
|| !validate_fragment_shader_executable(frag_shader_list[0])) || !validate_fragment_shader_executable(prog, frag_shader_list[0]))
goto done; goto done;
@@ -795,12 +829,14 @@ link_shaders(struct glsl_program *prog)
prog->_NumLinkedShaders++; prog->_NumLinkedShaders++;
} }
if (cross_validate_uniforms(prog->_LinkedShaders, prog->_NumLinkedShaders)) { if (cross_validate_uniforms(prog, prog->_LinkedShaders,
prog->_NumLinkedShaders)) {
/* Validate the inputs of each stage with the output of the preceeding /* Validate the inputs of each stage with the output of the preceeding
* stage. * stage.
*/ */
for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) { for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
if (!cross_validate_outputs_to_inputs(prog->_LinkedShaders[i - 1], if (!cross_validate_outputs_to_inputs(prog,
prog->_LinkedShaders[i - 1],
prog->_LinkedShaders[i])) prog->_LinkedShaders[i]))
goto done; goto done;
} }