#include <errno.h>
#include "glcpp.h"
#include "main/mtypes.h"
+#include "main/shaderobj.h"
extern int yydebug;
+void
+_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
+ struct gl_shader *sh)
+{
+ *ptr = sh;
+}
+
/* Read from fd until EOF and return a string of everything read.
*/
static char *
#include "linker.h"
#include "ir_optimization.h"
+extern "C" {
+#include "main/shaderobj.h"
+}
+
/**
* Visitor that determines whether or not a variable is ever written.
*/
*/
glsl_symbol_table variables;
for (unsigned i = 0; i < num_shaders; i++) {
+ if (shader_list[i] == NULL)
+ continue;
+
foreach_list(node, shader_list[i]->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
cross_validate_uniforms(struct gl_shader_program *prog)
{
return cross_validate_globals(prog, prog->_LinkedShaders,
- prog->_NumLinkedShaders, true);
+ MESA_SHADER_TYPES, true);
}
static void
update_array_sizes(struct gl_shader_program *prog)
{
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
foreach_list(node, prog->_LinkedShaders[i]->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
continue;
unsigned int size = var->max_array_access;
- for (unsigned j = 0; j < prog->_NumLinkedShaders; j++) {
+ for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) {
+ if (prog->_LinkedShaders[j] == NULL)
+ continue;
+
foreach_list(node2, prog->_LinkedShaders[j]->ir) {
ir_variable *other_var = ((ir_instruction *) node2)->as_variable();
if (!other_var)
hash_table_string_compare);
void *mem_ctx = talloc_new(NULL);
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
unsigned next_position = 0;
foreach_list(node, prog->_LinkedShaders[i]->ir) {
prog->Version = max_version;
- for (unsigned int i = 0; i < prog->_NumLinkedShaders; i++) {
- ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+ for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] != NULL)
+ ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+
+ prog->_LinkedShaders[i] = NULL;
}
/* Link all shaders for a particular stage and validate the result.
*/
- prog->_NumLinkedShaders = 0;
if (num_vert_shaders > 0) {
gl_shader *const sh =
link_intrastage_shaders(ctx, prog, vert_shader_list, num_vert_shaders);
if (!validate_vertex_shader_executable(prog, sh))
goto done;
- prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
- prog->_NumLinkedShaders++;
+ _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_VERTEX],
+ sh);
}
if (num_frag_shaders > 0) {
if (!validate_fragment_shader_executable(prog, sh))
goto done;
- prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
- prog->_NumLinkedShaders++;
+ _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
+ sh);
}
/* Here begins the inter-stage linking phase. Some initial validation is
* varyings.
*/
if (cross_validate_uniforms(prog)) {
+ unsigned prev;
+
+ for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
+ if (prog->_LinkedShaders[prev] != NULL)
+ break;
+ }
+
/* Validate the inputs of each stage with the output of the preceeding
* stage.
*/
- for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
+ for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
if (!cross_validate_outputs_to_inputs(prog,
- prog->_LinkedShaders[i - 1],
+ prog->_LinkedShaders[prev],
prog->_LinkedShaders[i]))
goto done;
+
+ prev = i;
}
prog->LinkStatus = true;
* uniforms, and varyings. Later optimization could possibly make
* some of that unused.
*/
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, 32))
;
}
assign_uniform_locations(prog);
- if (prog->_NumLinkedShaders && prog->_LinkedShaders[0]->Type == GL_VERTEX_SHADER) {
+ if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
/* FINISHME: The value of the max_attribute_index parameter is
* FINISHME: implementation dependent based on the value of
* FINISHME: GL_MAX_VERTEX_ATTRIBS. GL_MAX_VERTEX_ATTRIBS must be
goto done;
}
- if (prog->_NumLinkedShaders == 1)
- demote_unread_shader_outputs(prog->_LinkedShaders[0]);
+ if ((prog->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)
+ && (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL))
+ demote_unread_shader_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX]);
}
- for (unsigned i = 1; i < prog->_NumLinkedShaders; i++)
+ unsigned prev;
+ for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
+ if (prog->_LinkedShaders[prev] != NULL)
+ break;
+ }
+
+ for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
assign_varying_locations(prog,
- prog->_LinkedShaders[i - 1],
+ prog->_LinkedShaders[prev],
prog->_LinkedShaders[i]);
+ prev = i;
+ }
/* FINISHME: Assign fragment shader output locations. */
extern "C" struct gl_shader *
_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
+extern "C" void
+_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
+ struct gl_shader *sh);
+
/* Copied from shader_api.c for the stand-alone compiler.
*/
+void
+_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
+ struct gl_shader *sh)
+{
+ *ptr = sh;
+}
+
struct gl_shader *
_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
{
printf("Info log for linking:\n%s\n", whole_program->InfoLog);
}
- for (unsigned i = 0; i < whole_program->_NumLinkedShaders; i++)
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
talloc_free(whole_program->_LinkedShaders[i]);
talloc_free(whole_program);
{
struct intel_context *intel = intel_context(ctx);
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
- struct brw_shader *shader = (struct brw_shader *)prog->_LinkedShaders[i];
-
- if (shader->base.Type == GL_FRAGMENT_SHADER) {
+ struct brw_shader *shader =
+ (struct brw_shader *)prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+ if (shader != NULL) {
void *mem_ctx = talloc_new(NULL);
bool progress;
reparent_ir(shader->ir, shader->ir);
talloc_free(mem_ctx);
- }
}
if (!_mesa_ir_link_shader(ctx, prog))
struct brw_compile *p = &c->func;
struct intel_context *intel = &brw->intel;
struct gl_context *ctx = &intel->ctx;
- struct brw_shader *shader = NULL;
struct gl_shader_program *prog = ctx->Shader.CurrentProgram;
if (!prog)
return GL_FALSE;
- for (unsigned int i = 0; i < prog->_NumLinkedShaders; i++) {
- if (prog->_LinkedShaders[i]->Type == GL_FRAGMENT_SHADER) {
- shader = (struct brw_shader *)prog->_LinkedShaders[i];
- break;
- }
- }
+ struct brw_shader *shader =
+ (brw_shader *) prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
if (!shader)
return GL_FALSE;
* using the new FS backend.
*/
shader_program = _mesa_lookup_shader_program(ctx, prog->Id);
- if (shader_program) {
- for (i = 0; i < shader_program->_NumLinkedShaders; i++) {
- struct brw_shader *shader;
-
- shader = (struct brw_shader *)shader_program->_LinkedShaders[i];
- if (shader->base.Type == GL_FRAGMENT_SHADER && shader->ir) {
- return GL_TRUE;
- }
- }
+ if (shader_program
+ && shader_program->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
+ return GL_TRUE;
}
}
else if (target == GL_VERTEX_PROGRAM_ARB) {
* 8-wide.
*/
if (ctx->Shader.CurrentProgram) {
- int i;
+ struct brw_shader *shader = (struct brw_shader *)
+ ctx->Shader.CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT];
- for (i = 0; i < ctx->Shader.CurrentProgram->_NumLinkedShaders; i++) {
- struct brw_shader *shader =
- (struct brw_shader *)ctx->Shader.CurrentProgram->_LinkedShaders[i];;
-
- if (shader->base.Type == GL_FRAGMENT_SHADER &&
- shader->ir != NULL) {
- key->is_glsl = GL_TRUE;
- }
+ if (shader != NULL && shader->ir != NULL) {
+ key->is_glsl = GL_TRUE;
}
}
_mesa_update_state(ctx);
if (ctx->Shader.CurrentProgram) {
- unsigned i;
+ struct gl_shader_program *const prog = ctx->Shader.CurrentProgram;
/* using shaders */
- if (!ctx->Shader.CurrentProgram->LinkStatus) {
+ if (!prog->LinkStatus) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(shader not linked)", where);
return GL_FALSE;
#if 0 /* not normally enabled */
{
char errMsg[100];
- if (!_mesa_validate_shader_program(ctx, ctx->Shader.CurrentProgram,
- errMsg)) {
+ if (!_mesa_validate_shader_program(ctx, prog, errMsg)) {
_mesa_warning(ctx, "Shader program %u is invalid: %s",
- ctx->Shader.CurrentProgram->Name, errMsg);
+ prog->Name, errMsg);
}
}
#endif
* any stages that are not provided, the corresponding assembly shader
* target will be validated below.
*/
- for (i = 0; i < ctx->Shader.CurrentProgram->_NumLinkedShaders; i++) {
- switch (ctx->Shader.CurrentProgram->_LinkedShaders[i]->Type) {
- case GL_VERTEX_SHADER: vert_from_glsl_shader = true; break;
- case GL_GEOMETRY_SHADER_ARB: geom_from_glsl_shader = true; break;
- case GL_FRAGMENT_SHADER: frag_from_glsl_shader = true; break;
- }
- }
+ vert_from_glsl_shader =
+ prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL;
+ geom_from_glsl_shader =
+ prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL;
+ frag_from_glsl_shader =
+ prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL;
}
/**
* Per-stage shaders resulting from the first stage of linking.
+ *
+ * Set of linked shaders for this program. The array is accessed using the
+ * \c MESA_SHADER_* defines. Entries for non-existent stages will be
+ * \c NULL.
*/
- /*@{*/
- GLuint _NumLinkedShaders;
- struct gl_shader *_LinkedShaders[2];
- /*@}*/
+ struct gl_shader *_LinkedShaders[MESA_SHADER_TYPES];
};
shProg->TransformFeedback.NumVarying = 0;
- for (i = 0; i < shProg->_NumLinkedShaders; i++) {
- ctx->Driver.DeleteShader(ctx, shProg->_LinkedShaders[i]);
+ for (i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (shProg->_LinkedShaders[i] != NULL) {
+ ctx->Driver.DeleteShader(ctx, shProg->_LinkedShaders[i]);
+ shProg->_LinkedShaders[i] = NULL;
+ }
}
- shProg->_NumLinkedShaders = 0;
}
{
void *mem_ctx = NULL;
- for (unsigned int i = 0; i < shader_program->_NumLinkedShaders; i++) {
+ for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
struct gl_shader *shader = shader_program->_LinkedShaders[i];
+
+ if (shader == NULL)
+ continue;
+
foreach_iter(exec_list_iterator, iter, *shader->ir) {
ir_instruction *ir = (ir_instruction *)iter.get();
ir_variable *var = ir->as_variable();
{
assert(prog->LinkStatus);
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
bool progress;
exec_list *ir = prog->_LinkedShaders[i]->ir;
const struct gl_shader_compiler_options *options =
validate_ir_tree(ir);
}
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+ for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
struct gl_program *linked_prog;
bool ok = true;
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
+
linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
switch (prog->_LinkedShaders[i]->Type) {