summaryrefslogtreecommitdiff
path: root/src/mesa/program
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/program')
-rw-r--r--src/mesa/program/ir_to_mesa.cpp177
-rw-r--r--src/mesa/program/prog_statevars.c2
-rw-r--r--src/mesa/program/program.c8
-rw-r--r--src/mesa/program/program.h33
-rw-r--r--src/mesa/program/program_parse.tab.c2
-rw-r--r--src/mesa/program/program_parse.y2
6 files changed, 189 insertions, 35 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index f0e14b8ece..2edf01bb8f 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -186,6 +186,7 @@ public:
GLcontext *ctx;
struct gl_program *prog;
struct gl_shader_program *shader_program;
+ struct gl_shader_compiler_options *options;
int next_temp;
@@ -703,6 +704,10 @@ static struct statevar_element gl_Fog_elements[] = {
{"scale", {STATE_FOG_PARAMS}, SWIZZLE_WWWW},
};
+static struct statevar_element gl_NormalScale_elements[] = {
+ {NULL, {STATE_NORMAL_SCALE}, SWIZZLE_XXXX},
+};
+
#define MATRIX(name, statevar, modifier) \
static struct statevar_element name ## _elements[] = { \
{ NULL, { statevar, 0, 0, 0, modifier}, SWIZZLE_XYZW }, \
@@ -760,10 +765,10 @@ static struct statevar_element gl_NormalMatrix_elements[] = {
#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
-static struct {
+static const struct statevar {
const char *name;
struct statevar_element *elements;
- int num_elements;
+ unsigned int num_elements;
} statevars[] = {
STATEVAR(gl_DepthRange),
STATEVAR(gl_ClipPlane),
@@ -808,6 +813,7 @@ static struct {
STATEVAR(gl_TextureMatrixInverseTranspose),
STATEVAR(gl_NormalMatrix),
+ STATEVAR(gl_NormalScale),
};
void
@@ -823,12 +829,6 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
unsigned int i;
- struct variable_storage *entry;
- entry = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
- this->next_temp);
- this->variables.push_tail(entry);
- this->next_temp += type_size(ir->type);
-
for (i = 0; i < Elements(statevars); i++) {
if (strcmp(ir->name, statevars[i].name) == 0)
break;
@@ -840,9 +840,7 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
return;
}
- ir_to_mesa_dst_reg dst =
- ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY,
- entry->index, NULL));
+ const struct statevar *statevar = &statevars[i];
int array_count;
if (ir->type->is_array()) {
@@ -851,9 +849,41 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
array_count = 1;
}
+ /* Check if this statevar's setup in the STATE file exactly
+ * matches how we'll want to reference it as a
+ * struct/array/whatever. If not, then we need to move it into
+ * temporary storage and hope that it'll get copy-propagated
+ * out.
+ */
+ for (i = 0; i < statevar->num_elements; i++) {
+ if (statevar->elements[i].swizzle != SWIZZLE_XYZW) {
+ break;
+ }
+ }
+
+ struct variable_storage *storage;
+ ir_to_mesa_dst_reg dst;
+ if (i == statevar->num_elements) {
+ /* We'll set the index later. */
+ storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
+ this->variables.push_tail(storage);
+
+ dst = ir_to_mesa_undef_dst;
+ } else {
+ storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
+ this->next_temp);
+ this->variables.push_tail(storage);
+ this->next_temp += type_size(ir->type);
+
+ dst = ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg(PROGRAM_TEMPORARY,
+ storage->index,
+ NULL));
+ }
+
+
for (int a = 0; a < array_count; a++) {
- for (int j = 0; j < statevars[i].num_elements; j++) {
- struct statevar_element *element = &statevars[i].elements[j];
+ for (unsigned int i = 0; i < statevar->num_elements; i++) {
+ struct statevar_element *element = &statevar->elements[i];
int tokens[STATE_LENGTH];
memcpy(tokens, element->tokens, sizeof(element->tokens));
@@ -863,17 +893,28 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
int index = _mesa_add_state_reference(this->prog->Parameters,
(gl_state_index *)tokens);
- ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
- src.swizzle = element->swizzle;
- ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
- /* even a float takes up a whole vec4 reg in a struct/array. */
- dst.index++;
+
+ if (storage->file == PROGRAM_STATE_VAR) {
+ if (storage->index == -1) {
+ storage->index = index;
+ } else {
+ assert(index == ((int)storage->index +
+ a * statevar->num_elements + i));
+ }
+ } else {
+ ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
+ src.swizzle = element->swizzle;
+ ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
+ /* even a float takes up a whole vec4 reg in a struct/array. */
+ dst.index++;
+ }
}
}
- if (dst.index != entry->index + type_size(ir->type)) {
+ if (storage->file == PROGRAM_TEMPORARY &&
+ dst.index != storage->index + type_size(ir->type)) {
fail_link(this->shader_program,
"failed to load builtin uniform `%s' (%d/%d regs loaded)\n",
- ir->name, dst.index - entry->index,
+ ir->name, dst.index - storage->index,
type_size(ir->type));
}
}
@@ -882,13 +923,53 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
void
ir_to_mesa_visitor::visit(ir_loop *ir)
{
- assert(!ir->from);
- assert(!ir->to);
- assert(!ir->increment);
- assert(!ir->counter);
+ ir_dereference_variable *counter = NULL;
+
+ if (ir->counter != NULL)
+ counter = new(ir) ir_dereference_variable(ir->counter);
+
+ if (ir->from != NULL) {
+ assert(ir->counter != NULL);
+
+ ir_assignment *a = new(ir) ir_assignment(counter, ir->from, NULL);
+
+ a->accept(this);
+ delete a;
+ }
ir_to_mesa_emit_op0(NULL, OPCODE_BGNLOOP);
+
+ if (ir->to) {
+ ir_expression *e =
+ new(ir) ir_expression(ir->cmp, glsl_type::bool_type,
+ counter, ir->to);
+ ir_if *if_stmt = new(ir) ir_if(e);
+
+ ir_loop_jump *brk = new(ir) ir_loop_jump(ir_loop_jump::jump_break);
+
+ if_stmt->then_instructions.push_tail(brk);
+
+ if_stmt->accept(this);
+
+ delete if_stmt;
+ delete e;
+ delete brk;
+ }
+
visit_exec_list(&ir->body_instructions, this);
+
+ if (ir->increment) {
+ ir_expression *e =
+ new(ir) ir_expression(ir_binop_add, counter->type,
+ counter, ir->increment);
+
+ ir_assignment *a = new(ir) ir_assignment(counter, e, NULL);
+
+ a->accept(this);
+ delete a;
+ delete e;
+ }
+
ir_to_mesa_emit_op0(NULL, OPCODE_ENDLOOP);
}
@@ -1073,6 +1154,16 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
ir_to_mesa_emit_op1(ir, OPCODE_DDY, result_dst, op[0]);
break;
+ case ir_unop_noise: {
+ const enum prog_opcode opcode =
+ prog_opcode(OPCODE_NOISE1
+ + (ir->operands[0]->type->vector_elements) - 1);
+ assert((opcode >= OPCODE_NOISE1) && (opcode <= OPCODE_NOISE4));
+
+ ir_to_mesa_emit_op1(ir, opcode, result_dst, op[0]);
+ break;
+ }
+
case ir_binop_add:
ir_to_mesa_emit_op2(ir, OPCODE_ADD, result_dst, op[0], op[1]);
break;
@@ -1102,6 +1193,12 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
ir_to_mesa_emit_op2(ir, OPCODE_SGE, result_dst, op[0], op[1]);
break;
case ir_binop_equal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_nequal:
+ ir_to_mesa_emit_op2(ir, OPCODE_SNE, result_dst, op[0], op[1]);
+ break;
+ case ir_binop_all_equal:
/* "==" operator producing a scalar boolean. */
if (ir->operands[0]->type->is_vector() ||
ir->operands[1]->type->is_vector()) {
@@ -1115,7 +1212,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
ir_to_mesa_emit_op2(ir, OPCODE_SEQ, result_dst, op[0], op[1]);
}
break;
- case ir_binop_nequal:
+ case ir_binop_any_nequal:
/* "!=" operator producing a scalar boolean. */
if (ir->operands[0]->type->is_vector() ||
ir->operands[1]->type->is_vector()) {
@@ -2016,7 +2113,7 @@ ir_to_mesa_visitor::visit(ir_if *ir)
ir->condition->accept(this);
assert(this->result.file != PROGRAM_UNDEFINED);
- if (ctx->Shader.EmitCondCodes) {
+ if (this->options->EmitCondCodes) {
cond_inst = (ir_to_mesa_instruction *)this->instructions.get_tail();
/* See if we actually generated any instruction for generating
@@ -2446,6 +2543,8 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
GLenum target;
const char *target_string;
GLboolean progress;
+ struct gl_shader_compiler_options *options =
+ &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(shader->Type)];
switch (shader->Type) {
case GL_VERTEX_SHADER:
@@ -2472,6 +2571,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
v.ctx = ctx;
v.prog = prog;
v.shader_program = shader_program;
+ v.options = options;
add_uniforms_to_parameters_list(shader_program, shader, prog);
@@ -2549,7 +2649,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
if (mesa_inst->SrcReg[src].RelAddr)
prog->IndirectRegisterFiles |= 1 << mesa_inst->SrcReg[src].File;
- if (ctx->Shader.EmitNoIfs && mesa_inst->Opcode == OPCODE_IF) {
+ if (options->EmitNoIfs && mesa_inst->Opcode == OPCODE_IF) {
fail_link(shader_program, "Couldn't flatten if statement\n");
}
@@ -2623,6 +2723,8 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
bool progress;
exec_list *ir = prog->_LinkedShaders[i]->ir;
+ struct gl_shader_compiler_options *options =
+ &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(prog->_LinkedShaders[i]->Type)];
do {
progress = false;
@@ -2633,11 +2735,16 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
do_div_to_mul_rcp(ir);
do_explog_to_explog2(ir);
- progress = do_common_optimization(ir, true) || progress;
+ progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
- if (ctx->Shader.EmitNoIfs)
+ progress = do_common_optimization(ir, true, options->MaxUnrollIterations) || progress;
+
+ if (options->EmitNoIfs)
progress = do_if_to_cond_assign(ir) || progress;
+ if (options->EmitNoNoise)
+ progress = lower_noise(ir) || progress;
+
progress = do_vec_index_to_cond_assign(ir) || progress;
} while (progress);
@@ -2680,8 +2787,16 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
const char *source = shader->Source;
+ /* Check if the user called glCompileShader without first calling
+ * glShaderSource. This should fail to compile, but not raise a GL_ERROR.
+ */
+ if (source == NULL) {
+ shader->CompileStatus = GL_FALSE;
+ return;
+ }
+
state->error = preprocess(state, &source, &state->info_log,
- &ctx->Extensions);
+ &ctx->Extensions, ctx->API);
if (ctx->Shader.Flags & GLSL_DUMP) {
printf("GLSL source for shader %d:\n", shader->Name);
@@ -2705,7 +2820,7 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
/* Do some optimization at compile time to reduce shader IR size
* and reduce later work if the same shader is linked multiple times
*/
- while (do_common_optimization(shader->ir, false))
+ while (do_common_optimization(shader->ir, false, 32))
;
validate_ir_tree(shader->ir);
diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
index ead3ece95d..2687f8ae2c 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -1052,6 +1052,8 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
append_token(str, state[1]);
append_index(str, state[2]);
break;
+ case STATE_NORMAL_SCALE:
+ break;
case STATE_INTERNAL:
append_token(str, state[1]);
if (state[1] == STATE_CURRENT_ATTRIB)
diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
index 3b6d682744..06b9539bda 100644
--- a/src/mesa/program/program.c
+++ b/src/mesa/program/program.c
@@ -876,12 +876,16 @@ _mesa_find_used_registers(const struct gl_program *prog,
const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
if (inst->DstReg.File == file) {
- used[inst->DstReg.Index] = GL_TRUE;
+ ASSERT(inst->DstReg.Index < usedSize);
+ if(inst->DstReg.Index < usedSize)
+ used[inst->DstReg.Index] = GL_TRUE;
}
for (j = 0; j < n; j++) {
if (inst->SrcReg[j].File == file) {
- used[inst->SrcReg[j].Index] = GL_TRUE;
+ ASSERT(inst->SrcReg[j].Index < usedSize);
+ if(inst->SrcReg[j].Index < usedSize)
+ used[inst->SrcReg[j].Index] = GL_TRUE;
}
}
}
diff --git a/src/mesa/program/program.h b/src/mesa/program/program.h
index 286573de1f..03b1066f32 100644
--- a/src/mesa/program/program.h
+++ b/src/mesa/program/program.h
@@ -40,6 +40,7 @@
#ifndef PROGRAM_H
#define PROGRAM_H
+#include "main/compiler.h"
#include "main/mtypes.h"
@@ -167,5 +168,37 @@ _mesa_find_free_register(const GLboolean used[],
extern void
_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog);
+/* keep these in the same order as TGSI_PROCESSOR_* */
+
+static INLINE GLuint
+_mesa_program_target_to_index(GLenum v)
+{
+ switch(v)
+ {
+ case GL_VERTEX_PROGRAM_ARB:
+ return MESA_SHADER_VERTEX;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ return MESA_SHADER_FRAGMENT;
+ case GL_GEOMETRY_PROGRAM_NV:
+ return MESA_SHADER_GEOMETRY;
+ default:
+ ASSERT(0);
+ return ~0;
+ }
+}
+
+static INLINE GLenum
+_mesa_program_index_to_target(GLuint i)
+{
+ GLenum enums[MESA_SHADER_TYPES] = {
+ GL_VERTEX_PROGRAM_ARB,
+ GL_FRAGMENT_PROGRAM_ARB,
+ GL_GEOMETRY_PROGRAM_NV,
+ };
+ if(i >= MESA_SHADER_TYPES)
+ return 0;
+ else
+ return enums[i];
+}
#endif /* PROGRAM_H */
diff --git a/src/mesa/program/program_parse.tab.c b/src/mesa/program/program_parse.tab.c
index 31a609600b..08ead30def 100644
--- a/src/mesa/program/program_parse.tab.c
+++ b/src/mesa/program/program_parse.tab.c
@@ -5589,7 +5589,7 @@ yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
err_str = make_error_string("glProgramStringARB(%s)\n", s);
if (err_str) {
- _mesa_error(state->ctx, GL_INVALID_OPERATION, err_str);
+ _mesa_error(state->ctx, GL_INVALID_OPERATION, "%s", err_str);
free(err_str);
}
diff --git a/src/mesa/program/program_parse.y b/src/mesa/program/program_parse.y
index fb6ef85a9f..cf621ae424 100644
--- a/src/mesa/program/program_parse.y
+++ b/src/mesa/program/program_parse.y
@@ -2628,7 +2628,7 @@ yyerror(YYLTYPE *locp, struct asm_parser_state *state, const char *s)
err_str = make_error_string("glProgramStringARB(%s)\n", s);
if (err_str) {
- _mesa_error(state->ctx, GL_INVALID_OPERATION, err_str);
+ _mesa_error(state->ctx, GL_INVALID_OPERATION, "%s", err_str);
free(err_str);
}