diff options
Diffstat (limited to 'src/mesa/program')
-rw-r--r-- | src/mesa/program/ir_to_mesa.cpp | 177 | ||||
-rw-r--r-- | src/mesa/program/prog_statevars.c | 2 | ||||
-rw-r--r-- | src/mesa/program/program.c | 8 | ||||
-rw-r--r-- | src/mesa/program/program.h | 33 | ||||
-rw-r--r-- | src/mesa/program/program_parse.tab.c | 2 | ||||
-rw-r--r-- | src/mesa/program/program_parse.y | 2 |
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); } |