From 4a470f63c9c3f5aeef1e10ae42eee24c772f74fc Mon Sep 17 00:00:00 2001 From: michal Date: Tue, 7 Aug 2007 15:34:11 +0100 Subject: [PATCH] Naive implementation of IF/ELSE/ENDIF. Handle TGSI labels correctly. Enhance MESA opcode info queries. --- src/mesa/pipe/tgsi/core/tgsi_dump.c | 2 +- src/mesa/pipe/tgsi/core/tgsi_exec.c | 174 +++++++++++++++++++---- src/mesa/pipe/tgsi/core/tgsi_exec.h | 25 ++++ src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c | 2 +- src/mesa/shader/prog_instruction.c | 183 +++++++++++++------------ src/mesa/shader/prog_instruction.h | 3 + src/mesa/shader/shader_api.c | 2 +- 7 files changed, 277 insertions(+), 114 deletions(-) diff --git a/src/mesa/pipe/tgsi/core/tgsi_dump.c b/src/mesa/pipe/tgsi/core/tgsi_dump.c index 641339c8960..f1773ac9080 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_dump.c +++ b/src/mesa/pipe/tgsi/core/tgsi_dump.c @@ -788,7 +788,7 @@ dump_instruction_short( switch( inst->Instruction.Opcode ) { case TGSI_OPCODE_IF: case TGSI_OPCODE_ELSE: - TXT( " : " ); + TXT( " :" ); UID( inst->InstructionExtLabel.Label ); break; } diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.c b/src/mesa/pipe/tgsi/core/tgsi_exec.c index 2bd2e7ce051..71dfbc10f31 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_exec.c +++ b/src/mesa/pipe/tgsi/core/tgsi_exec.c @@ -111,6 +111,7 @@ tgsi_exec_prepare( { struct tgsi_parse_context parse; GLuint k; + GLuint instno = 0; mach->ImmLimit = 0; labels->count = 0; @@ -124,26 +125,30 @@ tgsi_exec_prepare( while( !tgsi_parse_end_of_tokens( &parse ) ) { GLuint pointer = parse.Position; GLuint i; + tgsi_parse_token( &parse ); switch( parse.FullToken.Token.Type ) { case TGSI_TOKEN_TYPE_DECLARATION: break; + case TGSI_TOKEN_TYPE_IMMEDIATE: assert( (parse.FullToken.FullImmediate.Immediate.Size - 1) % 4 == 0 ); assert( mach->ImmLimit + (parse.FullToken.FullImmediate.Immediate.Size - 1) / 4 <= 256 ); + for( i = 0; i < parse.FullToken.FullImmediate.Immediate.Size - 1; i++ ) { mach->Imms[mach->ImmLimit + i / 4][i % 4] = parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float; } mach->ImmLimit += (parse.FullToken.FullImmediate.Immediate.Size - 1) / 4; break; + case TGSI_TOKEN_TYPE_INSTRUCTION: - if( parse.FullToken.FullInstruction.InstructionExtLabel.Label ) { - assert( labels->count < 128 ); - labels->labels[labels->count][0] = parse.FullToken.FullInstruction.InstructionExtLabel.Label; - labels->labels[labels->count][1] = pointer; - labels->count++; - } + assert( labels->count < 128 ); + + labels->labels[labels->count][0] = instno; + labels->labels[labels->count][1] = pointer; + labels->count++; break; + default: assert( 0 ); } @@ -1233,22 +1238,6 @@ fetch_texel_3d( GLcontext *ctx, } #endif -static GLuint -map_label( - GLuint label, - struct tgsi_exec_labels *labels ) -{ - GLuint i; - - for( i = 0; i < labels->count; i++ ) { - if( labels->labels[i][0] == label ) { - return labels->labels[i][1]; - } - } - assert( 0 ); - return 0; -} - static void exec_instruction( struct tgsi_exec_machine *mach, @@ -1988,7 +1977,43 @@ exec_instruction( break; case TGSI_OPCODE_IF: - assert (0); + { + GLuint cond = 0; + struct tgsi_exec_cond_state *state; + + /* Allocate condition state. */ + assert( mach->CondStack.Index > 0 ); + mach->CondStack.Index--; + + /* Evaluate the condition mask. */ + FETCH( &r[0], 0, CHAN_X ); + if( r[0].u[0] ) { + cond |= 1; + } + if( r[0].u[1] ) { + cond |= 2; + } + if( r[0].u[2] ) { + cond |= 4; + } + if( r[0].u[3] ) { + cond |= 8; + } + + state = &mach->CondStack.States[mach->CondStack.Index]; + + /* Initialize the If portion of condition state. */ + memcpy( + state->IfPortion.TempsAddrs, + mach->Temps, + sizeof( state->IfPortion.TempsAddrs ) ); + memcpy( + state->IfPortion.Outputs, + mach->Outputs, + sizeof( state->IfPortion.Outputs ) ); + state->Condition = cond; + state->WasElse = GL_FALSE; + } break; case TGSI_OPCODE_LOOP: @@ -2000,12 +2025,107 @@ exec_instruction( break; case TGSI_OPCODE_ELSE: - assert (0); + { + struct tgsi_exec_cond_state *state; + struct tgsi_exec_cond_regs temp; + + state = &mach->CondStack.States[mach->CondStack.Index]; + + /* Copy the results of the If portion to temporary storage. */ + memcpy( + temp.TempsAddrs, + mach->Temps, + sizeof( temp.TempsAddrs ) ); + memcpy( + temp.Outputs, + mach->Outputs, + sizeof( temp.Outputs ) ); + + /* Restore the state of registers from before the If statement. */ + memcpy( + mach->Temps, + state->IfPortion.TempsAddrs, + sizeof( state->IfPortion.TempsAddrs ) ); + memcpy( + mach->Outputs, + state->IfPortion.Outputs, + sizeof( state->IfPortion.Outputs ) ); + + /* Save the results of If portion. */ + memcpy( + &state->IfPortion, + &temp, + sizeof( state->IfPortion ) ); + state->WasElse = GL_TRUE; + } break; case TGSI_OPCODE_ENDIF: - assert (0); - break; + { + struct tgsi_exec_cond_state *state; + GLuint i; + + state = &mach->CondStack.States[mach->CondStack.Index]; + + if( state->WasElse ) { + /* Save the results of Else portion. */ + memcpy( + state->ElsePortion.TempsAddrs, + mach->Temps, + sizeof( state->ElsePortion.TempsAddrs ) ); + memcpy( + state->ElsePortion.Outputs, + mach->Outputs, + sizeof( state->ElsePortion.Outputs ) ); + } + else { + /* Copy the state of registers from before the If statement to Else portion. */ + memcpy( + &state->ElsePortion, + &state->IfPortion, + sizeof( state->ElsePortion ) ); + + /* Save the results of the If portion. */ + memcpy( + state->IfPortion.TempsAddrs, + mach->Temps, + sizeof( state->IfPortion.TempsAddrs ) ); + memcpy( + state->IfPortion.Outputs, + mach->Outputs, + sizeof( state->IfPortion.Outputs ) ); + } + + /* Mix the If and Else portions based on condition mask. */ + for( i = 0; i < 4; i++ ) { + struct tgsi_exec_cond_regs *regs; + GLuint j; + + if( state->Condition & (1 << i) ) { + regs = &state->IfPortion; + } + else { + regs = &state->ElsePortion; + } + + for( j = 0; j < TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_ADDRS; j++ ) { + mach->Temps[j].xyzw[0].u[i] = regs->TempsAddrs[j].xyzw[0].u[i]; + mach->Temps[j].xyzw[1].u[i] = regs->TempsAddrs[j].xyzw[1].u[i]; + mach->Temps[j].xyzw[2].u[i] = regs->TempsAddrs[j].xyzw[2].u[i]; + mach->Temps[j].xyzw[3].u[i] = regs->TempsAddrs[j].xyzw[3].u[i]; + } + for( j = 0; j < 2; j++ ) { + mach->Outputs[j].xyzw[0].u[i] = regs->Outputs[j].xyzw[0].u[i]; + mach->Outputs[j].xyzw[1].u[i] = regs->Outputs[j].xyzw[1].u[i]; + mach->Outputs[j].xyzw[2].u[i] = regs->Outputs[j].xyzw[2].u[i]; + mach->Outputs[j].xyzw[3].u[i] = regs->Outputs[j].xyzw[3].u[i]; + } + } + + /* Release condition state. */ + mach->CondStack.Index++; + } + break; case TGSI_OPCODE_ENDLOOP: assert (0); @@ -2214,6 +2334,8 @@ tgsi_exec_machine_run2( mach->Primitives[0] = 0; } + mach->CondStack.Index = 8; + k = tgsi_parse_init( &parse, mach->Tokens ); if (k != TGSI_PARSE_OK) { printf("Problem parsing!\n"); diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.h b/src/mesa/pipe/tgsi/core/tgsi_exec.h index d2ff40cabbc..b92d1b59189 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_exec.h +++ b/src/mesa/pipe/tgsi/core/tgsi_exec.h @@ -85,6 +85,29 @@ struct tgsi_exec_labels #define TGSI_EXEC_NUM_TEMPS (32 + 4) #define TGSI_EXEC_NUM_ADDRS 1 +/* XXX: This is temporary */ +struct tgsi_exec_cond_regs +{ + struct tgsi_exec_vector TempsAddrs[TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_ADDRS]; + struct tgsi_exec_vector Outputs[2]; /* XXX: That's just enough for fragment shader only! */ +}; + +/* XXX: This is temporary */ +struct tgsi_exec_cond_state +{ + struct tgsi_exec_cond_regs IfPortion; + struct tgsi_exec_cond_regs ElsePortion; + GLuint Condition; + GLboolean WasElse; +}; + +/* XXX: This is temporary */ +struct tgsi_exec_cond_stack +{ + struct tgsi_exec_cond_state States[8]; + GLuint Index; /* into States[] */ +}; + struct tgsi_exec_machine { /* @@ -112,6 +135,8 @@ struct tgsi_exec_machine GLuint Processor; GLuint *Primitives; + + struct tgsi_exec_cond_stack CondStack; #if XXX_SSE struct x86_function Function; #endif diff --git a/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c index 654ec9ac68a..107b6bd2a36 100644 --- a/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c +++ b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c @@ -168,7 +168,7 @@ compile_instruction( *fullinst = tgsi_default_full_instruction(); fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode ); - fullinst->Instruction.NumDstRegs = 1; + fullinst->Instruction.NumDstRegs = _mesa_num_inst_dst_regs( inst->Opcode ); fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode ); fulldst = &fullinst->FullDstRegisters[0]; diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c index d6b5652a276..c84c76fd5bd 100644 --- a/src/mesa/shader/prog_instruction.c +++ b/src/mesa/shader/prog_instruction.c @@ -126,6 +126,7 @@ struct instruction_info gl_inst_opcode Opcode; const char *Name; GLuint NumSrcRegs; + GLuint NumDstRegs; }; /** @@ -133,91 +134,91 @@ struct instruction_info * \note Opcode should equal array index! */ static const struct instruction_info InstInfo[MAX_OPCODE] = { - { OPCODE_NOP, "NOP", 0 }, - { OPCODE_ABS, "ABS", 1 }, - { OPCODE_ADD, "ADD", 2 }, - { OPCODE_ARA, "ARA", 1 }, - { OPCODE_ARL, "ARL", 1 }, - { OPCODE_ARL_NV, "ARL", 1 }, - { OPCODE_ARR, "ARL", 1 }, - { OPCODE_BGNLOOP,"BGNLOOP", 0 }, - { OPCODE_BGNSUB, "BGNSUB", 0 }, - { OPCODE_BRA, "BRA", 0 }, - { OPCODE_BRK, "BRK", 0 }, - { OPCODE_CAL, "CAL", 0 }, - { OPCODE_CMP, "CMP", 3 }, - { OPCODE_CONT, "CONT", 0 }, - { OPCODE_COS, "COS", 1 }, - { OPCODE_DDX, "DDX", 1 }, - { OPCODE_DDY, "DDY", 1 }, - { OPCODE_DP3, "DP3", 2 }, - { OPCODE_DP4, "DP4", 2 }, - { OPCODE_DPH, "DPH", 2 }, - { OPCODE_DST, "DST", 2 }, - { OPCODE_ELSE, "ELSE", 0 }, - { OPCODE_END, "END", 0 }, - { OPCODE_ENDIF, "ENDIF", 0 }, - { OPCODE_ENDLOOP,"ENDLOOP", 0 }, - { OPCODE_ENDSUB, "ENDSUB", 0 }, - { OPCODE_EX2, "EX2", 1 }, - { OPCODE_EXP, "EXP", 1 }, - { OPCODE_FLR, "FLR", 1 }, - { OPCODE_FRC, "FRC", 1 }, - { OPCODE_IF, "IF", 0 }, - { OPCODE_INT, "INT", 1 }, - { OPCODE_KIL, "KIL", 1 }, - { OPCODE_KIL_NV, "KIL", 0 }, - { OPCODE_LG2, "LG2", 1 }, - { OPCODE_LIT, "LIT", 1 }, - { OPCODE_LOG, "LOG", 1 }, - { OPCODE_LRP, "LRP", 3 }, - { OPCODE_MAD, "MAD", 3 }, - { OPCODE_MAX, "MAX", 2 }, - { OPCODE_MIN, "MIN", 2 }, - { OPCODE_MOV, "MOV", 1 }, - { OPCODE_MUL, "MUL", 2 }, - { OPCODE_NOISE1, "NOISE1", 1 }, - { OPCODE_NOISE2, "NOISE2", 1 }, - { OPCODE_NOISE3, "NOISE3", 1 }, - { OPCODE_NOISE4, "NOISE4", 1 }, - { OPCODE_PK2H, "PK2H", 1 }, - { OPCODE_PK2US, "PK2US", 1 }, - { OPCODE_PK4B, "PK4B", 1 }, - { OPCODE_PK4UB, "PK4UB", 1 }, - { OPCODE_POW, "POW", 2 }, - { OPCODE_POPA, "POPA", 0 }, - { OPCODE_PRINT, "PRINT", 1 }, - { OPCODE_PUSHA, "PUSHA", 0 }, - { OPCODE_RCC, "RCC", 1 }, - { OPCODE_RCP, "RCP", 1 }, - { OPCODE_RET, "RET", 0 }, - { OPCODE_RFL, "RFL", 1 }, - { OPCODE_RSQ, "RSQ", 1 }, - { OPCODE_SCS, "SCS", 1 }, - { OPCODE_SEQ, "SEQ", 2 }, - { OPCODE_SFL, "SFL", 0 }, - { OPCODE_SGE, "SGE", 2 }, - { OPCODE_SGT, "SGT", 2 }, - { OPCODE_SIN, "SIN", 1 }, - { OPCODE_SLE, "SLE", 2 }, - { OPCODE_SLT, "SLT", 2 }, - { OPCODE_SNE, "SNE", 2 }, - { OPCODE_SSG, "SSG", 1 }, - { OPCODE_STR, "STR", 0 }, - { OPCODE_SUB, "SUB", 2 }, - { OPCODE_SWZ, "SWZ", 1 }, - { OPCODE_TEX, "TEX", 1 }, - { OPCODE_TXB, "TXB", 1 }, - { OPCODE_TXD, "TXD", 3 }, - { OPCODE_TXL, "TXL", 1 }, - { OPCODE_TXP, "TXP", 1 }, - { OPCODE_TXP_NV, "TXP", 1 }, - { OPCODE_UP2H, "UP2H", 1 }, - { OPCODE_UP2US, "UP2US", 1 }, - { OPCODE_UP4B, "UP4B", 1 }, - { OPCODE_UP4UB, "UP4UB", 1 }, - { OPCODE_X2D, "X2D", 3 }, - { OPCODE_XPD, "XPD", 2 } + { OPCODE_NOP, "NOP", 0, 0 }, + { OPCODE_ABS, "ABS", 1, 1 }, + { OPCODE_ADD, "ADD", 2, 1 }, + { OPCODE_ARA, "ARA", 1, 1 }, + { OPCODE_ARL, "ARL", 1, 1 }, + { OPCODE_ARL_NV, "ARL", 1, 1 }, + { OPCODE_ARR, "ARL", 1, 1 }, + { OPCODE_BGNLOOP,"BGNLOOP", 0, 0 }, + { OPCODE_BGNSUB, "BGNSUB", 0, 0 }, + { OPCODE_BRA, "BRA", 0, 0 }, + { OPCODE_BRK, "BRK", 0, 0 }, + { OPCODE_CAL, "CAL", 0, 0 }, + { OPCODE_CMP, "CMP", 3, 1 }, + { OPCODE_CONT, "CONT", 0, 0 }, + { OPCODE_COS, "COS", 1, 1 }, + { OPCODE_DDX, "DDX", 1, 1 }, + { OPCODE_DDY, "DDY", 1, 1 }, + { OPCODE_DP3, "DP3", 2, 1 }, + { OPCODE_DP4, "DP4", 2, 1 }, + { OPCODE_DPH, "DPH", 2, 1 }, + { OPCODE_DST, "DST", 2, 1 }, + { OPCODE_ELSE, "ELSE", 0, 0 }, + { OPCODE_END, "END", 0, 0 }, + { OPCODE_ENDIF, "ENDIF", 0, 0 }, + { OPCODE_ENDLOOP,"ENDLOOP", 0, 0 }, + { OPCODE_ENDSUB, "ENDSUB", 0, 0 }, + { OPCODE_EX2, "EX2", 1, 1 }, + { OPCODE_EXP, "EXP", 1, 1 }, + { OPCODE_FLR, "FLR", 1, 1 }, + { OPCODE_FRC, "FRC", 1, 1 }, + { OPCODE_IF, "IF", 1, 0 }, + { OPCODE_INT, "INT", 1, 1 }, + { OPCODE_KIL, "KIL", 1, 0 }, + { OPCODE_KIL_NV, "KIL", 0, 0 }, + { OPCODE_LG2, "LG2", 1, 1 }, + { OPCODE_LIT, "LIT", 1, 1 }, + { OPCODE_LOG, "LOG", 1, 1 }, + { OPCODE_LRP, "LRP", 3, 1 }, + { OPCODE_MAD, "MAD", 3, 1 }, + { OPCODE_MAX, "MAX", 2, 1 }, + { OPCODE_MIN, "MIN", 2, 1 }, + { OPCODE_MOV, "MOV", 1, 1 }, + { OPCODE_MUL, "MUL", 2, 1 }, + { OPCODE_NOISE1, "NOISE1", 1, 1 }, + { OPCODE_NOISE2, "NOISE2", 1, 1 }, + { OPCODE_NOISE3, "NOISE3", 1, 1 }, + { OPCODE_NOISE4, "NOISE4", 1, 1 }, + { OPCODE_PK2H, "PK2H", 1, 1 }, + { OPCODE_PK2US, "PK2US", 1, 1 }, + { OPCODE_PK4B, "PK4B", 1, 1 }, + { OPCODE_PK4UB, "PK4UB", 1, 1 }, + { OPCODE_POW, "POW", 2, 1 }, + { OPCODE_POPA, "POPA", 0, 0 }, + { OPCODE_PRINT, "PRINT", 1, 0 }, + { OPCODE_PUSHA, "PUSHA", 0, 0 }, + { OPCODE_RCC, "RCC", 1, 1 }, + { OPCODE_RCP, "RCP", 1, 1 }, + { OPCODE_RET, "RET", 0, 0 }, + { OPCODE_RFL, "RFL", 1, 1 }, + { OPCODE_RSQ, "RSQ", 1, 1 }, + { OPCODE_SCS, "SCS", 1, 1 }, + { OPCODE_SEQ, "SEQ", 2, 1 }, + { OPCODE_SFL, "SFL", 0, 1 }, + { OPCODE_SGE, "SGE", 2, 1 }, + { OPCODE_SGT, "SGT", 2, 1 }, + { OPCODE_SIN, "SIN", 1, 1 }, + { OPCODE_SLE, "SLE", 2, 1 }, + { OPCODE_SLT, "SLT", 2, 1 }, + { OPCODE_SNE, "SNE", 2, 1 }, + { OPCODE_SSG, "SSG", 1, 1 }, + { OPCODE_STR, "STR", 0, 1 }, + { OPCODE_SUB, "SUB", 2, 1 }, + { OPCODE_SWZ, "SWZ", 1, 1 }, + { OPCODE_TEX, "TEX", 1, 1 }, + { OPCODE_TXB, "TXB", 1, 1 }, + { OPCODE_TXD, "TXD", 3, 1 }, + { OPCODE_TXL, "TXL", 1, 1 }, + { OPCODE_TXP, "TXP", 1, 1 }, + { OPCODE_TXP_NV, "TXP", 1, 1 }, + { OPCODE_UP2H, "UP2H", 1, 1 }, + { OPCODE_UP2US, "UP2US", 1, 1 }, + { OPCODE_UP4B, "UP4B", 1, 1 }, + { OPCODE_UP4UB, "UP4UB", 1, 1 }, + { OPCODE_X2D, "X2D", 3, 1 }, + { OPCODE_XPD, "XPD", 2, 1 } }; @@ -233,6 +234,18 @@ _mesa_num_inst_src_regs(gl_inst_opcode opcode) } +/** + * Return the number of dst registers for the given instruction/opcode. + */ +GLuint +_mesa_num_inst_dst_regs(gl_inst_opcode opcode) +{ + ASSERT(opcode == InstInfo[opcode].Opcode); + ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode); + return InstInfo[opcode].NumDstRegs; +} + + /** * Return string name for given program opcode. */ diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h index c800757aa0f..643969b367e 100644 --- a/src/mesa/shader/prog_instruction.h +++ b/src/mesa/shader/prog_instruction.h @@ -440,6 +440,9 @@ _mesa_copy_instructions(struct prog_instruction *dest, extern GLuint _mesa_num_inst_src_regs(gl_inst_opcode opcode); +extern GLuint +_mesa_num_inst_dst_regs(gl_inst_opcode opcode); + extern const char * _mesa_opcode_string(gl_inst_opcode opcode); diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 1a931326afa..9f6c54dd4c5 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -332,7 +332,7 @@ _mesa_init_shader_state(GLcontext * ctx) * are generated by the GLSL compiler. */ ctx->Shader.EmitHighLevelInstructions = GL_TRUE; - ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */ + ctx->Shader.EmitCondCodes = GL_FALSE;/*GL_TRUE;*/ /* XXX probably want GL_FALSE... */ ctx->Shader.EmitComments = GL_FALSE; } -- 2.30.2