diff options
Diffstat (limited to 'src/mesa/program')
-rw-r--r-- | src/mesa/program/arbprogparse.h | 6 | ||||
-rw-r--r-- | src/mesa/program/ir_to_mesa.cpp | 159 | ||||
-rw-r--r-- | src/mesa/program/ir_to_mesa.h | 7 | ||||
-rw-r--r-- | src/mesa/program/nvfragparse.h | 5 | ||||
-rw-r--r-- | src/mesa/program/nvvertparse.h | 5 | ||||
-rw-r--r-- | src/mesa/program/prog_cache.h | 3 | ||||
-rw-r--r-- | src/mesa/program/prog_execute.c | 12 | ||||
-rw-r--r-- | src/mesa/program/prog_instruction.h | 2 | ||||
-rw-r--r-- | src/mesa/program/prog_optimize.h | 3 | ||||
-rw-r--r-- | src/mesa/program/prog_statevars.c | 30 | ||||
-rw-r--r-- | src/mesa/program/prog_statevars.h | 5 | ||||
-rw-r--r-- | src/mesa/program/program.c | 1 | ||||
-rw-r--r-- | src/mesa/program/symbol_table.c | 85 | ||||
-rw-r--r-- | src/mesa/program/symbol_table.h | 4 |
14 files changed, 302 insertions, 25 deletions
diff --git a/src/mesa/program/arbprogparse.h b/src/mesa/program/arbprogparse.h index 08e25a1c16..4c0c300720 100644 --- a/src/mesa/program/arbprogparse.h +++ b/src/mesa/program/arbprogparse.h @@ -26,7 +26,11 @@ #ifndef ARBPROGPARSE_H #define ARBPROGPARSE_H -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_fragment_program; +struct gl_vertex_program; extern void _mesa_parse_arb_vertex_program(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index a5b17bb328..786fdfbd23 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -295,6 +295,8 @@ public: bool process_move_condition(ir_rvalue *ir); + void copy_propagate(void); + void *mem_ctx; }; @@ -1574,7 +1576,13 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) break; offset += type_size(struct_type->fields.structure[i].type); } - this->result.swizzle = swizzle_for_size(ir->type->vector_elements); + + /* If the type is smaller than a vec4, replicate the last channel out. */ + if (ir->type->is_scalar() || ir->type->is_vector()) + this->result.swizzle = swizzle_for_size(ir->type->vector_elements); + else + this->result.swizzle = SWIZZLE_NOOP; + this->result.index += offset; } @@ -2171,9 +2179,14 @@ ir_to_mesa_visitor::visit(ir_discard *ir) { struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog; - assert(ir->condition == NULL); /* FINISHME */ + if (ir->condition) { + ir->condition->accept(this); + this->result.negate = ~this->result.negate; + ir_to_mesa_emit_op1(ir, OPCODE_KIL, ir_to_mesa_undef_dst, this->result); + } else { + ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV); + } - ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV); fp->UsesKill = GL_TRUE; } @@ -2610,6 +2623,133 @@ set_uniform_initializers(struct gl_context *ctx, talloc_free(mem_ctx); } +/* + * On a basic block basis, tracks available PROGRAM_TEMPORARY register + * channels for copy propagation and updates following instructions to + * use the original versions. + * + * The ir_to_mesa_visitor lazily produces code assuming that this pass + * will occur. As an example, a TXP production before this pass: + * + * 0: MOV TEMP[1], INPUT[4].xyyy; + * 1: MOV TEMP[1].w, INPUT[4].wwww; + * 2: TXP TEMP[2], TEMP[1], texture[0], 2D; + * + * and after: + * + * 0: MOV TEMP[1], INPUT[4].xyyy; + * 1: MOV TEMP[1].w, INPUT[4].wwww; + * 2: TXP TEMP[2], INPUT[4].xyyw, texture[0], 2D; + * + * which allows for dead code elimination on TEMP[1]'s writes. + */ +void +ir_to_mesa_visitor::copy_propagate(void) +{ + ir_to_mesa_instruction **acp = talloc_zero_array(mem_ctx, + ir_to_mesa_instruction *, + this->next_temp * 4); + + foreach_iter(exec_list_iterator, iter, this->instructions) { + ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get(); + + /* First, do any copy propagation possible into the src regs. */ + for (int r = 0; r < 3; r++) { + ir_to_mesa_instruction *first = NULL; + bool good = true; + int acp_base = inst->src_reg[r].index * 4; + + if (inst->src_reg[r].file != PROGRAM_TEMPORARY || + inst->src_reg[r].reladdr) + continue; + + /* See if we can find entries in the ACP consisting of MOVs + * from the same src register for all the swizzled channels + * of this src register reference. + */ + for (int i = 0; i < 4; i++) { + int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i); + ir_to_mesa_instruction *copy_chan = acp[acp_base + src_chan]; + + if (!copy_chan) { + good = false; + break; + } + + if (!first) { + first = copy_chan; + } else { + if (first->src_reg[0].file != copy_chan->src_reg[0].file || + first->src_reg[0].index != copy_chan->src_reg[0].index) { + good = false; + break; + } + } + } + + if (good) { + /* We've now validated that we can copy-propagate to + * replace this src register reference. Do it. + */ + inst->src_reg[r].file = first->src_reg[0].file; + inst->src_reg[r].index = first->src_reg[0].index; + + int swizzle = 0; + for (int i = 0; i < 4; i++) { + int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i); + ir_to_mesa_instruction *copy_inst = acp[acp_base + src_chan]; + swizzle |= (GET_SWZ(copy_inst->src_reg[0].swizzle, src_chan) << + (3 * i)); + } + inst->src_reg[r].swizzle = swizzle; + } + } + + switch (inst->op) { + case OPCODE_BGNLOOP: + case OPCODE_ENDLOOP: + case OPCODE_ELSE: + case OPCODE_ENDIF: + /* End of a basic block, clear the ACP entirely. */ + memset(acp, 0, sizeof(*acp) * this->next_temp * 4); + break; + + default: + /* Continuing the block, clear any written channels from + * the ACP. + */ + if (inst->dst_reg.file == PROGRAM_TEMPORARY) { + if (inst->dst_reg.reladdr) { + memset(acp, 0, sizeof(*acp) * this->next_temp * 4); + } else { + for (int i = 0; i < 4; i++) { + if (inst->dst_reg.writemask & (1 << i)) { + acp[4 * inst->dst_reg.index + i] = NULL; + } + } + } + } + break; + } + + /* If this is a copy, add it to the ACP. */ + if (inst->op == OPCODE_MOV && + inst->dst_reg.file == PROGRAM_TEMPORARY && + !inst->dst_reg.reladdr && + !inst->saturate && + !inst->src_reg[0].reladdr && + !inst->src_reg[0].negate) { + for (int i = 0; i < 4; i++) { + if (inst->dst_reg.writemask & (1 << i)) { + acp[4 * inst->dst_reg.index + i] = inst; + } + } + } + } + + talloc_free(acp); +} + /** * Convert a shader's GLSL IR into a Mesa gl_program. @@ -2709,6 +2849,8 @@ get_mesa_program(struct gl_context *ctx, mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *, num_instructions); + v.copy_propagate(); + /* Convert ir_mesa_instructions into prog_instructions. */ mesa_inst = mesa_instructions; @@ -2849,8 +2991,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) /* Lowering */ do_mat_op_to_vec(ir); - lower_instructions(ir, MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2 - | LOG_TO_LOG2); + lower_instructions(ir, (MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2 + | LOG_TO_LOG2 + | ((options->EmitNoPow) ? POW_TO_EXP2 : 0))); progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; @@ -2858,8 +3001,10 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) progress = lower_quadop_vector(ir, true) || progress; - if (options->EmitNoIfs) - progress = do_if_to_cond_assign(ir) || progress; + if (options->EmitNoIfs) { + progress = lower_discard(ir) || progress; + progress = lower_if_to_cond_assign(ir) || progress; + } if (options->EmitNoNoise) progress = lower_noise(ir) || progress; diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h index 7197615f94..7410e14973 100644 --- a/src/mesa/program/ir_to_mesa.h +++ b/src/mesa/program/ir_to_mesa.h @@ -25,8 +25,11 @@ extern "C" { #endif -#include "main/config.h" -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_shader; +struct gl_shader_program; void _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *sh); void _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); diff --git a/src/mesa/program/nvfragparse.h b/src/mesa/program/nvfragparse.h index 3e85dd2c30..088e7527d5 100644 --- a/src/mesa/program/nvfragparse.h +++ b/src/mesa/program/nvfragparse.h @@ -30,7 +30,10 @@ #ifndef NVFRAGPARSE_H #define NVFRAGPARSE_H -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_fragment_program; extern void _mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/program/nvvertparse.h b/src/mesa/program/nvvertparse.h index e98e867320..7318e14941 100644 --- a/src/mesa/program/nvvertparse.h +++ b/src/mesa/program/nvvertparse.h @@ -29,7 +29,10 @@ #ifndef NVVERTPARSE_H #define NVVERTPARSE_H -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_vertex_program; extern void _mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/program/prog_cache.h b/src/mesa/program/prog_cache.h index 4907ae3030..0167334827 100644 --- a/src/mesa/program/prog_cache.h +++ b/src/mesa/program/prog_cache.h @@ -30,8 +30,9 @@ #define PROG_CACHE_H -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; /** Opaque type */ struct gl_program_cache; diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c index c20347fe67..e7553c69db 100644 --- a/src/mesa/program/prog_execute.c +++ b/src/mesa/program/prog_execute.c @@ -1674,6 +1674,18 @@ _mesa_execute_program(struct gl_context * ctx, fetch_texel(ctx, machine, inst, texcoord, lodBias, color); + if (DEBUG_PROG) { + printf("TXB (%g, %g, %g, %g) = texture[%d][%g %g %g %g]" + " bias %g\n", + color[0], color[1], color[2], color[3], + inst->TexSrcUnit, + texcoord[0], + texcoord[1], + texcoord[2], + texcoord[3], + lodBias); + } + store_vector4(inst, machine, color); } break; diff --git a/src/mesa/program/prog_instruction.h b/src/mesa/program/prog_instruction.h index ca90de7ce1..a383828e34 100644 --- a/src/mesa/program/prog_instruction.h +++ b/src/mesa/program/prog_instruction.h @@ -247,7 +247,7 @@ typedef enum prog_opcode { * Number of bits for the src/dst register Index field. * This limits the size of temp/uniform register files. */ -#define INST_INDEX_BITS 10 +#define INST_INDEX_BITS 11 /** diff --git a/src/mesa/program/prog_optimize.h b/src/mesa/program/prog_optimize.h index 00f1080449..463f5fc51c 100644 --- a/src/mesa/program/prog_optimize.h +++ b/src/mesa/program/prog_optimize.h @@ -27,9 +27,10 @@ #include "main/config.h" -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; struct gl_program; struct prog_instruction; diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c index baac29ff0d..c310acb01d 100644 --- a/src/mesa/program/prog_statevars.c +++ b/src/mesa/program/prog_statevars.c @@ -572,6 +572,24 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], value[3] = 0.0F; return; + case STATE_FB_WPOS_Y_TRANSFORM: + /* A driver may negate this conditional by using ZW swizzle + * instead of XY (based on e.g. some other state). */ + if (ctx->DrawBuffer->Name != 0) { + /* Identity (XY) followed by flipping Y upside down (ZW). */ + value[0] = 1.0F; + value[1] = 0.0F; + value[2] = -1.0F; + value[3] = (GLfloat) (ctx->DrawBuffer->Height - 1); + } else { + /* Flipping Y upside down (XY) followed by identity (ZW). */ + value[0] = -1.0F; + value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); + value[2] = 1.0F; + value[3] = 0.0F; + } + return; + case STATE_ROT_MATRIX_0: { const int unit = (int) state[2]; @@ -695,6 +713,7 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) return _NEW_PIXEL; case STATE_FB_SIZE: + case STATE_FB_WPOS_Y_TRANSFORM: return _NEW_BUFFERS; default: @@ -900,6 +919,9 @@ append_token(char *dst, gl_state_index k) case STATE_FB_SIZE: append(dst, "FbSize"); break; + case STATE_FB_WPOS_Y_TRANSFORM: + append(dst, "FbWposYTransform"); + break; case STATE_ROT_MATRIX_0: append(dst, "rotMatrixRow0"); break; @@ -1046,7 +1068,9 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) * Loop over all the parameters in a parameter list. If the parameter * is a GL state reference, look up the current value of that state * variable and put it into the parameter's Value[4] array. - * This would be called at glBegin time when using a fragment program. + * Other parameter types never change or are explicitly set by the user + * with glUniform() or glProgramParameter(), etc. + * This would be called at glBegin time. */ void _mesa_load_state_parameters(struct gl_context *ctx, @@ -1057,12 +1081,10 @@ _mesa_load_state_parameters(struct gl_context *ctx, if (!paramList) return; - /*assert(ctx->Driver.NeedFlush == 0);*/ - for (i = 0; i < paramList->NumParameters; i++) { if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { _mesa_fetch_state(ctx, - (gl_state_index *) paramList->Parameters[i].StateIndexes, + paramList->Parameters[i].StateIndexes, paramList->ParameterValues[i]); } } diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h index 6e5be53630..f2407af9c8 100644 --- a/src/mesa/program/prog_statevars.h +++ b/src/mesa/program/prog_statevars.h @@ -25,8 +25,10 @@ #ifndef PROG_STATEVARS_H #define PROG_STATEVARS_H -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; +struct gl_program_parameter_list; /** * Number of STATE_* values we need to address any GL state. @@ -117,6 +119,7 @@ typedef enum gl_state_index_ { STATE_PT_BIAS, /**< Pixel transfer RGBA bias */ STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */ STATE_FB_SIZE, /**< (width-1, height-1, 0, 0) */ + STATE_FB_WPOS_Y_TRANSFORM, /**< (1, 0, -1, height-1) if a FBO is bound, (-1, height-1, 1, 0) otherwise */ STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */ STATE_ROT_MATRIX_1, /**< ATI_envmap_bumpmap, rot matrix row 1 */ STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */ diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c index 9ffa49bb01..52254e9365 100644 --- a/src/mesa/program/program.c +++ b/src/mesa/program/program.c @@ -32,6 +32,7 @@ #include "main/glheader.h" #include "main/context.h" #include "main/hash.h" +#include "main/mfeatures.h" #include "program.h" #include "prog_cache.h" #include "prog_parameter.h" diff --git a/src/mesa/program/symbol_table.c b/src/mesa/program/symbol_table.c index 09e7cb44ef..004f1f8fa7 100644 --- a/src/mesa/program/symbol_table.c +++ b/src/mesa/program/symbol_table.c @@ -336,12 +336,12 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table, check_symbol_table(table); if (hdr == NULL) { - hdr = calloc(1, sizeof(*hdr)); - hdr->name = strdup(name); + hdr = calloc(1, sizeof(*hdr)); + hdr->name = strdup(name); - hash_table_insert(table->ht, hdr, hdr->name); - hdr->next = table->hdr; - table->hdr = hdr; + hash_table_insert(table->ht, hdr, hdr->name); + hdr->next = table->hdr; + table->hdr = hdr; } check_symbol_table(table); @@ -376,6 +376,81 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table, } +int +_mesa_symbol_table_add_global_symbol(struct _mesa_symbol_table *table, + int name_space, const char *name, + void *declaration) +{ + struct symbol_header *hdr; + struct symbol *sym; + struct symbol *curr; + struct scope_level *top_scope; + + check_symbol_table(table); + + hdr = find_symbol(table, name); + + check_symbol_table(table); + + if (hdr == NULL) { + hdr = calloc(1, sizeof(*hdr)); + hdr->name = strdup(name); + + hash_table_insert(table->ht, hdr, hdr->name); + hdr->next = table->hdr; + table->hdr = hdr; + } + + check_symbol_table(table); + + /* If the symbol already exists in this namespace at this scope, it cannot + * be added to the table. + */ + for (sym = hdr->symbols + ; (sym != NULL) && (sym->name_space != name_space) + ; sym = sym->next_with_same_name) { + /* empty */ + } + + if (sym && sym->depth == 0) + return -1; + + /* Find the top-level scope */ + for (top_scope = table->current_scope + ; top_scope->next != NULL + ; top_scope = top_scope->next) { + /* empty */ + } + + sym = calloc(1, sizeof(*sym)); + sym->next_with_same_scope = top_scope->symbols; + sym->hdr = hdr; + sym->name_space = name_space; + sym->data = declaration; + + assert(sym->hdr == hdr); + + /* Since next_with_same_name is ordered by scope, we need to append the + * new symbol to the _end_ of the list. + */ + if (hdr->symbols == NULL) { + hdr->symbols = sym; + } else { + for (curr = hdr->symbols + ; curr->next_with_same_name != NULL + ; curr = curr->next_with_same_name) { + /* empty */ + } + curr->next_with_same_name = sym; + } + top_scope->symbols = sym; + + check_symbol_table(table); + return 0; +} + + + struct _mesa_symbol_table * _mesa_symbol_table_ctor(void) { diff --git a/src/mesa/program/symbol_table.h b/src/mesa/program/symbol_table.h index 1d570fc1a0..f9d91649bb 100644 --- a/src/mesa/program/symbol_table.h +++ b/src/mesa/program/symbol_table.h @@ -33,6 +33,10 @@ extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table); extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab, int name_space, const char *name, void *declaration); +extern int _mesa_symbol_table_add_global_symbol( + struct _mesa_symbol_table *symtab, int name_space, const char *name, + void *declaration); + extern int _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table, int name_space, const char *name); |