linker: Write errors to info log instead of stdout
This commit is contained in:
132
linker.cpp
132
linker.cpp
@@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user