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 <cstdio>
#include <cstdarg>
extern "C" {
#include <talloc.h>
}
#include "main/mtypes.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
invalidate_variable_locations(glsl_shader *sh, enum ir_variable_mode mode,
int generic_base)
@@ -167,20 +184,22 @@ count_attribute_slots(const glsl_type *t)
* \param shader Vertex shader executable to be verified
*/
bool
validate_vertex_shader_executable(struct glsl_shader *shader)
validate_vertex_shader_executable(struct glsl_program *prog,
struct glsl_shader *shader)
{
if (shader == NULL)
return true;
if (!shader->symbols->get_function("main")) {
printf("error: vertex shader lacks `main'\n");
linker_error_printf(prog, "vertex shader lacks `main'\n");
return false;
}
find_assignment_visitor find("gl_Position");
find.run(&shader->ir);
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;
}
@@ -194,13 +213,14 @@ validate_vertex_shader_executable(struct glsl_shader *shader)
* \param shader Fragment shader executable to be verified
*/
bool
validate_fragment_shader_executable(struct glsl_shader *shader)
validate_fragment_shader_executable(struct glsl_program *prog,
struct glsl_shader *shader)
{
if (shader == NULL)
return true;
if (!shader->symbols->get_function("main")) {
printf("error: fragment shader lacks `main'\n");
linker_error_printf(prog, "fragment shader lacks `main'\n");
return false;
}
@@ -211,14 +231,14 @@ validate_fragment_shader_executable(struct glsl_shader *shader)
frag_data.run(&shader->ir);
if (!frag_color.variable_found() && !frag_data.variable_found()) {
printf("error: fragment shader does not write to `gl_FragColor' or "
"`gl_FragData'\n");
linker_error_printf(prog, "fragment shader does not write to "
"`gl_FragColor' or `gl_FragData'\n");
return false;
}
if (frag_color.variable_found() && frag_data.variable_found()) {
printf("error: fragment shader write to both `gl_FragColor' and "
"`gl_FragData'\n");
linker_error_printf(prog, "fragment shader writes to both "
"`gl_FragColor' and `gl_FragData'\n");
return false;
}
@@ -230,7 +250,8 @@ validate_fragment_shader_executable(struct glsl_shader *shader)
* Perform validation of uniforms used across multiple shader stages
*/
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
* them.
@@ -250,18 +271,19 @@ cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders)
ir_variable *const existing = uniforms.get_variable(var->name);
if (existing != NULL) {
if (var->type != existing->type) {
printf("error: uniform `%s' declared as type `%s' and "
"type `%s'\n",
var->name, var->type->name, existing->type->name);
linker_error_printf(prog, "uniform `%s' declared as type "
"`%s' and type `%s'\n",
var->name, var->type->name,
existing->type->name);
return false;
}
if (var->constant_value != NULL) {
if (existing->constant_value != NULL) {
if (!var->constant_value->has_value(existing->constant_value)) {
printf("error: initializers for uniform `%s' have "
"differing values\n",
var->name);
linker_error_printf(prog, "initializers for uniform "
"`%s' have differing values\n",
var->name);
return false;
}
} 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
*/
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;
/* 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.
*/
if (input->type != output->type) {
printf("error: %s shader output `%s' delcared as type `%s', but "
"%s shader input declared as type `%s'\n",
producer_stage, output->name, output->type->name,
consumer_stage, input->type->name);
linker_error_printf(prog,
"%s shader output `%s' delcared as "
"type `%s', but %s shader input declared "
"as type `%s'\n",
producer_stage, output->name,
output->type->name,
consumer_stage, input->type->name);
return false;
}
/* Check that all of the qualifiers match between stages.
*/
if (input->centroid != output->centroid) {
printf("error: %s shader output `%s' %s centroid qualifier, but "
"%s shader input %s centroid qualifier\n",
producer_stage,
output->name,
(output->centroid) ? "has" : "lacks",
consumer_stage,
(input->centroid) ? "has" : "lacks");
linker_error_printf(prog,
"%s shader output `%s' %s centroid qualifier, "
"but %s shader input %s centroid qualifier\n",
producer_stage,
output->name,
(output->centroid) ? "has" : "lacks",
consumer_stage,
(input->centroid) ? "has" : "lacks");
return false;
}
if (input->invariant != output->invariant) {
printf("error: %s shader output `%s' %s invariant qualifier, but "
"%s shader input %s invariant qualifier\n",
producer_stage,
output->name,
(output->invariant) ? "has" : "lacks",
consumer_stage,
(input->invariant) ? "has" : "lacks");
linker_error_printf(prog,
"%s shader output `%s' %s invariant qualifier, "
"but %s shader input %s invariant qualifier\n",
producer_stage,
output->name,
(output->invariant) ? "has" : "lacks",
consumer_stage,
(input->invariant) ? "has" : "lacks");
return false;
}
if (input->interpolation != output->interpolation) {
printf("error: %s shader output `%s' specifies %s interpolation "
"qualifier, "
"but %s shader input specifies %s interpolation "
"qualifier\n",
producer_stage,
output->name,
output->interpolation_string(),
consumer_stage,
input->interpolation_string());
linker_error_printf(prog,
"%s shader output `%s' specifies %s "
"interpolation qualifier, "
"but %s shader input specifies %s "
"interpolation qualifier\n",
producer_stage,
output->name,
output->interpolation_string(),
consumer_stage,
input->interpolation_string());
return false;
}
}
@@ -741,6 +770,11 @@ link_shaders(struct glsl_program *prog)
prog->Validated = 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.
*/
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.
*/
if (!validate_vertex_shader_executable(vert_shader_list[0])
|| !validate_fragment_shader_executable(frag_shader_list[0]))
if (!validate_vertex_shader_executable(prog, vert_shader_list[0])
|| !validate_fragment_shader_executable(prog, frag_shader_list[0]))
goto done;
@@ -795,12 +829,14 @@ link_shaders(struct glsl_program *prog)
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
* stage.
*/
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]))
goto done;
}