From 027ed1b505a1bf6e3f5ad4412734d7edf337c08b Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 24 Apr 2009 09:43:44 -0600 Subject: mesa: signal _NEW_PROGRAM_CONSTANTS instead of _NEW_PROGRAM Use _NEW_PROGRAM_CONSTANTS when changing constant/uniform buffer values. Binding a new program/shader sets both _NEW_PROGRAM and _NEW_PROGRAM_CONSTANTS. --- src/mesa/shader/arbprogram.c | 13 +++++++------ src/mesa/shader/nvprogram.c | 2 +- src/mesa/shader/shader_api.c | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src/mesa/shader') diff --git a/src/mesa/shader/arbprogram.c b/src/mesa/shader/arbprogram.c index 981565ab8f..317d623a22 100644 --- a/src/mesa/shader/arbprogram.c +++ b/src/mesa/shader/arbprogram.c @@ -74,8 +74,6 @@ _mesa_BindProgram(GLenum target, GLuint id) GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - /* Error-check target and get curProg */ if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */ (ctx->Extensions.NV_vertex_program || @@ -132,6 +130,9 @@ _mesa_BindProgram(GLenum target, GLuint id) return; } + /* signal new program (and its new constants) */ + FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + /* bind newProg */ if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */ _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, @@ -489,7 +490,7 @@ _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); if (target == GL_FRAGMENT_PROGRAM_ARB && ctx->Extensions.ARB_fragment_program) { @@ -537,7 +538,7 @@ _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, GLfloat * dest; ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); if (count <= 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)"); @@ -631,7 +632,7 @@ _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index, struct gl_program *prog; ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); if ((target == GL_FRAGMENT_PROGRAM_NV && ctx->Extensions.NV_fragment_program) || @@ -685,7 +686,7 @@ _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); if (count <= 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)"); diff --git a/src/mesa/shader/nvprogram.c b/src/mesa/shader/nvprogram.c index 5142c2a4a5..8ba521182b 100644 --- a/src/mesa/shader/nvprogram.c +++ b/src/mesa/shader/nvprogram.c @@ -706,7 +706,7 @@ _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); prog = _mesa_lookup_program(ctx, id); if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 644cd39185..8f414a0889 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -1487,7 +1487,7 @@ _mesa_use_program(GLcontext *ctx, GLuint program) return; } - FLUSH_VERTICES(ctx, _NEW_PROGRAM); + FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); if (program) { shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); @@ -1789,7 +1789,7 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, return; } - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); uniform = &shProg->Uniforms->Uniforms[location]; @@ -1929,7 +1929,7 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, return; } - FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); + FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); uniform = &shProg->Uniforms->Uniforms[location]; -- cgit v1.2.3 From 7da3f9403b235394a5c7e9456e34a0c9dad7dd15 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 24 Apr 2009 16:28:36 -0600 Subject: mesa: refactor code and make _mesa_find_temp_intervals() public --- src/mesa/shader/prog_optimize.c | 154 ++++++++++++++++++++++++++++++++++------ src/mesa/shader/prog_optimize.h | 12 ++++ 2 files changed, 144 insertions(+), 22 deletions(-) (limited to 'src/mesa/shader') diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index 6ba2e76ff9..a02f5efa41 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -547,15 +547,13 @@ update_interval(GLint intBegin[], GLint intEnd[], GLuint index, GLuint ic) /** - * Find the live intervals for each temporary register in the program. - * For register R, the interval [A,B] indicates that R is referenced - * from instruction A through instruction B. - * Special consideration is needed for loops and subroutines. - * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason + * Find first/last instruction that references each temporary register. */ -static GLboolean -find_live_intervals(struct gl_program *prog, - struct interval_list *liveIntervals) +GLboolean +_mesa_find_temp_intervals(const struct prog_instruction *instructions, + GLuint numInstructions, + GLint intBegin[MAX_PROGRAM_TEMPS], + GLint intEnd[MAX_PROGRAM_TEMPS]) { struct loop_info { @@ -563,26 +561,15 @@ find_live_intervals(struct gl_program *prog, }; struct loop_info loopStack[MAX_LOOP_NESTING]; GLuint loopStackDepth = 0; - GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS]; GLuint i; - /* - * Note: we'll return GL_FALSE below if we find relative indexing - * into the TEMP register file. We can't handle that yet. - * We also give up on subroutines for now. - */ - - if (dbg) { - _mesa_printf("Optimize: Begin find intervals\n"); - } - for (i = 0; i < MAX_PROGRAM_TEMPS; i++){ intBegin[i] = intEnd[i] = -1; } /* Scan instructions looking for temporary registers */ - for (i = 0; i < prog->NumInstructions; i++) { - const struct prog_instruction *inst = prog->Instructions + i; + for (i = 0; i < numInstructions; i++) { + const struct prog_instruction *inst = instructions + i; if (inst->Opcode == OPCODE_BGNLOOP) { loopStack[loopStackDepth].Start = i; loopStack[loopStackDepth].End = inst->BranchTarget; @@ -595,7 +582,7 @@ find_live_intervals(struct gl_program *prog, return GL_FALSE; } else { - const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); + const GLuint numSrc = 3;/*_mesa_num_inst_src_regs(inst->Opcode);*/ GLuint j; for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) { @@ -624,6 +611,39 @@ find_live_intervals(struct gl_program *prog, } } + return GL_TRUE; +} + + +/** + * Find the live intervals for each temporary register in the program. + * For register R, the interval [A,B] indicates that R is referenced + * from instruction A through instruction B. + * Special consideration is needed for loops and subroutines. + * \return GL_TRUE if success, GL_FALSE if we cannot proceed for some reason + */ +static GLboolean +find_live_intervals(struct gl_program *prog, + struct interval_list *liveIntervals) +{ + GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS]; + GLuint i; + + /* + * Note: we'll return GL_FALSE below if we find relative indexing + * into the TEMP register file. We can't handle that yet. + * We also give up on subroutines for now. + */ + + if (dbg) { + _mesa_printf("Optimize: Begin find intervals\n"); + } + + /* build intermediate arrays */ + if (!_mesa_find_temp_intervals(prog->Instructions, prog->NumInstructions, + intBegin, intEnd)) + return GL_FALSE; + /* Build live intervals list from intermediate arrays */ liveIntervals->Num = 0; for (i = 0; i < MAX_PROGRAM_TEMPS; i++) { @@ -794,6 +814,96 @@ _mesa_reallocate_registers(struct gl_program *prog) + + + + +#if 0 +static void +_mesa_find_temporary_live_intervals(struct gl_program *prog, + GLint firstInst[MAX_PROGRAM_TEMPS], + GLint lastInst[MAX_PROGRAM_TEMPS]) +{ + GLuint i; + + for (i = 0; i < MAX_PROGRAM_TEMPS; i++) { + firstInst[i] = lastInst[i] = -1; + } + + struct loop_info loopStack[MAX_LOOP_NESTING]; + GLuint loopStackDepth = 0; + GLint intBegin[MAX_PROGRAM_TEMPS], intEnd[MAX_PROGRAM_TEMPS]; + GLuint i; + + /* + * Note: we'll return GL_FALSE below if we find relative indexing + * into the TEMP register file. We can't handle that yet. + * We also give up on subroutines for now. + */ + + if (dbg) { + _mesa_printf("Optimize: Begin find intervals\n"); + } + + for (i = 0; i < MAX_PROGRAM_TEMPS; i++){ + intBegin[i] = intEnd[i] = -1; + } + + /* Scan instructions looking for temporary registers */ + for (i = 0; i < prog->NumInstructions; i++) { + const struct prog_instruction *inst = prog->Instructions + i; + if (inst->Opcode == OPCODE_BGNLOOP) { + loopStack[loopStackDepth].Start = i; + loopStack[loopStackDepth].End = inst->BranchTarget; + loopStackDepth++; + } + else if (inst->Opcode == OPCODE_ENDLOOP) { + loopStackDepth--; + } + else if (inst->Opcode == OPCODE_CAL) { + return GL_FALSE; + } + else { + const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); + GLuint j; + for (j = 0; j < numSrc; j++) { + if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) { + const GLuint index = inst->SrcReg[j].Index; + if (inst->SrcReg[j].RelAddr) + return GL_FALSE; + update_interval(intBegin, intEnd, index, i); + if (loopStackDepth > 0) { + /* extend temp register's interval to end of loop */ + GLuint loopEnd = loopStack[loopStackDepth - 1].End; + update_interval(intBegin, intEnd, index, loopEnd); + } + } + } + if (inst->DstReg.File == PROGRAM_TEMPORARY) { + const GLuint index = inst->DstReg.Index; + if (inst->DstReg.RelAddr) + return GL_FALSE; + update_interval(intBegin, intEnd, index, i); + if (loopStackDepth > 0) { + /* extend temp register's interval to end of loop */ + GLuint loopEnd = loopStack[loopStackDepth - 1].End; + update_interval(intBegin, intEnd, index, loopEnd); + } + } + } + } + + + + +#endif + + + + + + + /** * Apply optimizations to the given program to eliminate unnecessary * instructions, temp regs, etc. diff --git a/src/mesa/shader/prog_optimize.h b/src/mesa/shader/prog_optimize.h index d102cfd9fc..43894a2723 100644 --- a/src/mesa/shader/prog_optimize.h +++ b/src/mesa/shader/prog_optimize.h @@ -25,7 +25,19 @@ #ifndef PROG_OPT_H #define PROG_OPT_H + +#include "main/config.h" + + struct gl_program; +struct prog_instruction; + + +extern GLboolean +_mesa_find_temp_intervals(const struct prog_instruction *instructions, + GLuint numInstructions, + GLint intBegin[MAX_PROGRAM_TEMPS], + GLint intEnd[MAX_PROGRAM_TEMPS]); extern void _mesa_optimize_program(GLcontext *ctx, struct gl_program *program); -- cgit v1.2.3 From dca190e9432d4ed122bdd534922d0c3d85791c6a Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 29 Apr 2009 11:52:06 -0600 Subject: mesa: added _mesa_check_soa_dependencies() function This function will check an instruction to see if there's data dependencies between the dst and src registers if executed in an SOA manner. --- src/mesa/shader/prog_instruction.c | 50 ++++++++++++++++++++++++++++++++++++++ src/mesa/shader/prog_instruction.h | 3 +++ 2 files changed, 53 insertions(+) (limited to 'src/mesa/shader') diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c index ca7565c091..ae3a003fee 100644 --- a/src/mesa/shader/prog_instruction.c +++ b/src/mesa/shader/prog_instruction.c @@ -285,6 +285,56 @@ _mesa_is_tex_instruction(gl_inst_opcode opcode) } +/** + * Check if there's a potential src/dst register data dependency when + * using SOA execution. + * Example: + * MOV T, T.yxwz; + * This would expand into: + * MOV t0, t1; + * MOV t1, t0; + * MOV t2, t3; + * MOV t3, t2; + * The second instruction will have the wrong value for t0 if executed as-is. + */ +GLboolean +_mesa_check_soa_dependencies(const struct prog_instruction *inst) +{ + GLuint i, chan; + + if (inst->DstReg.WriteMask == WRITEMASK_X || + inst->DstReg.WriteMask == WRITEMASK_Y || + inst->DstReg.WriteMask == WRITEMASK_Z || + inst->DstReg.WriteMask == WRITEMASK_W || + inst->DstReg.WriteMask == 0x0) { + /* no chance of data dependency */ + return GL_FALSE; + } + + /* loop over src regs */ + for (i = 0; i < 3; i++) { + if (inst->SrcReg[i].File == inst->DstReg.File && + inst->SrcReg[i].Index == inst->DstReg.Index) { + /* loop over dest channels */ + GLuint channelsWritten = 0x0; + for (chan = 0; chan < 4; chan++) { + if (inst->DstReg.WriteMask & (1 << chan)) { + /* check if we're reading a channel that's been written */ + GLuint swizzle = GET_SWZ(inst->SrcReg[i].Swizzle, chan); + if (swizzle <= SWIZZLE_W && + (channelsWritten & (1 << swizzle))) { + return GL_TRUE; + } + + channelsWritten |= (1 << chan); + } + } + } + } + return GL_FALSE; +} + + /** * Return string name for given program opcode. */ diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h index 3109f6cbae..40ad998f79 100644 --- a/src/mesa/shader/prog_instruction.h +++ b/src/mesa/shader/prog_instruction.h @@ -428,6 +428,9 @@ _mesa_num_inst_dst_regs(gl_inst_opcode opcode); extern GLboolean _mesa_is_tex_instruction(gl_inst_opcode opcode); +extern GLboolean +_mesa_check_soa_dependencies(const struct prog_instruction *inst); + extern const char * _mesa_opcode_string(gl_inst_opcode opcode); -- cgit v1.2.3