From a811981f66275043d3b3d9a6550c6d3d8417874c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fonseca?= Date: Thu, 14 Apr 2011 18:11:36 +0100 Subject: [PATCH] mesa: Tolerate NV_fragment_program2's IF/ELSE/ENDIF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without actually advertising it. Enough to allow the SPECviewperf11 catia viewset to compile. The same approach appears to be taken by AMD's fglrx drivers. Squashed commit of the following: commit a15aed81c2fa4540f15f5093140646f867a5614c Author: José Fonseca Date: Wed Apr 13 12:24:44 2011 +0100 mesa: Defer the condition code register initialization to first use. Prevents unused immediates from being declared. commit 1c3fc63dc707cd45544394083b6102cf8484b576 Author: José Fonseca Date: Tue Apr 12 20:34:01 2011 +0100 mesa: Translate `IF cc` to TGSI. commit 8e716ab17e5e9bf438ad18293e6787d6dcff20ef Author: Brian Paul Date: Tue Apr 12 18:00:21 2011 +0100 mesa: Implement IF/ELSE/ENDIF in NV_fragment_program2 (WIP). Seems enough to > allow the viewperf/catia shader program to compile (but not run properly). --- src/mesa/program/program_lexer.l | 4 + src/mesa/program/program_parse.y | 33 ++++++++ src/mesa/program/program_parse_extra.c | 9 ++- src/mesa/program/program_parser.h | 1 + src/mesa/state_tracker/st_mesa_to_tgsi.c | 118 +++++++++++++++++++++++++++--- 5 files changed, 154 insertions(+), 11 deletions(-) diff --git a/src/mesa/program/program_lexer.l b/src/mesa/program/program_lexer.l index 0a50dab..e8a60ac 100644 --- a/src/mesa/program/program_lexer.l +++ b/src/mesa/program/program_lexer.l @@ -32,6 +32,7 @@ #define require_ARB_vp (yyextra->mode == ARB_vertex) #define require_ARB_fp (yyextra->mode == ARB_fragment) #define require_NV_fp (yyextra->option.NV_fragment) +#define require_NV_fp2 (yyextra->option.NV_fragment_program2) #define require_shadow (yyextra->option.Shadow) #define require_rect (yyextra->option.TexRect) #define require_texarray (yyextra->option.TexArray) @@ -202,6 +203,9 @@ EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); } FLR{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, FLR, 3); } FRC{sz}{cc}{sat} { return_opcode( 1, VECTOR_OP, FRC, 3); } +IF { return_opcode(require_NV_fp2, IF, IF, 2); } +ELSE { return_opcode(require_NV_fp2, ELSE, ELSE, 4); } +ENDIF { return_opcode(require_NV_fp2, ENDIF, ENDIF, 5); } KIL { return_opcode(require_ARB_fp, KIL, KIL, 3); } LIT{szf}{cc}{sat} { return_opcode( 1, VECTOR_OP, LIT, 3); } diff --git a/src/mesa/program/program_parse.y b/src/mesa/program/program_parse.y index b35bc5a..9c3eda7 100644 --- a/src/mesa/program/program_parse.y +++ b/src/mesa/program/program_parse.y @@ -162,6 +162,7 @@ static struct asm_instruction *asm_instruction_copy_ctor( /* Tokens for instructions */ %token BIN_OP BINSC_OP SAMPLE_OP SCALAR_OP TRI_OP VECTOR_OP %token ARL KIL SWZ TXD_OP +%token IF ELSE ENDIF %token INTEGER %token REAL @@ -199,6 +200,8 @@ static struct asm_instruction *asm_instruction_copy_ctor( %type SCALARop_instruction BINSCop_instruction BINop_instruction %type TRIop_instruction TXD_instruction SWZ_instruction SAMPLE_instruction %type KIL_instruction +%type FLOW_instruction +%type IF_instruction ELSE_instruction ENDIF_instruction %type dstReg maskedDstReg maskedAddrReg %type srcReg scalarUse scalarSrcReg swizzleSrcReg @@ -358,6 +361,10 @@ instruction: ALU_instruction $$ = $1; state->prog->NumTexInstructions++; } + | FLOW_instruction + { + $$ = $1; + } ; ALU_instruction: ARL_instruction @@ -369,6 +376,11 @@ ALU_instruction: ARL_instruction | SWZ_instruction ; +FLOW_instruction: IF_instruction + | ELSE_instruction + | ENDIF_instruction + ; + TexInstruction: SAMPLE_instruction | KIL_instruction | TXD_instruction @@ -471,6 +483,27 @@ KIL_instruction: KIL swizzleSrcReg } ; +IF_instruction: IF ccTest + { + $$ = asm_instruction_ctor(OPCODE_IF, NULL, NULL, NULL, NULL); + $$->Base.DstReg.CondMask = $2.CondMask; + $$->Base.DstReg.CondSwizzle = $2.CondSwizzle; + $$->Base.DstReg.CondSrc = $2.CondSrc; + } + ; + +ELSE_instruction: ELSE + { + $$ = asm_instruction_ctor(OPCODE_ELSE, NULL, NULL, NULL, NULL); + } + ; + +ENDIF_instruction: ENDIF + { + $$ = asm_instruction_ctor(OPCODE_ENDIF, NULL, NULL, NULL, NULL); + } + ; + TXD_instruction: TXD_OP maskedDstReg ',' swizzleSrcReg ',' swizzleSrcReg ',' swizzleSrcReg ',' texImageUnit ',' texTarget { $$ = asm_instruction_copy_ctor(& $1, & $2, & $4, & $6, & $8); diff --git a/src/mesa/program/program_parse_extra.c b/src/mesa/program/program_parse_extra.c index 4d92848..d026259 100644 --- a/src/mesa/program/program_parse_extra.c +++ b/src/mesa/program/program_parse_extra.c @@ -245,11 +245,18 @@ _mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option) /* Other NV_fragment_program strings may be supported later. */ if (option[0] == '\0') { - if (state->ctx->Extensions.NV_fragment_program_option) { + if (1 /* state->ctx->Extensions.NV_fragment_program_option */) { state->option.NV_fragment = 1; return 1; } } + else if (option[0] == '2') { + if (1 /* state->ctx->Extensions.NV_fragment_program2 */) { + state->option.NV_fragment = 1; + state->option.NV_fragment_program2 = 1; + return 1; + } + } } else if (strncmp(option, "MESA_", 5) == 0) { option += 5; diff --git a/src/mesa/program/program_parser.h b/src/mesa/program/program_parser.h index 8e5aaee..63524dc 100644 --- a/src/mesa/program/program_parser.h +++ b/src/mesa/program/program_parser.h @@ -207,6 +207,7 @@ struct asm_parser_state { unsigned TexRect:1; unsigned TexArray:1; unsigned NV_fragment:1; + unsigned NV_fragment_program2:1; unsigned OriginUpperLeft:1; unsigned PixelCenterInteger:1; } option; diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index c07739f..a1fe05e 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -74,6 +74,11 @@ struct st_translate { struct ureg_src samplers[PIPE_MAX_SAMPLERS]; struct ureg_src systemValues[SYSTEM_VALUE_MAX]; + /* Condition code register. Not actual the condition code, but the value of + * the register such that comparing to zero will give the desired results. + */ + struct ureg_src cond; + /* Extra info for handling point size clamping in vertex shader */ struct ureg_dst pointSizeResult; /**< Actual point size output register */ struct ureg_src pointSizeConst; /**< Point size range constant register */ @@ -321,6 +326,22 @@ translate_dst( struct st_translate *t, /** + * Swizzle a TGSI ureg_src register according to the + * specified 12 bit swizzle mask. + */ +static struct ureg_src +swizzle_uint( struct ureg_src src, + GLuint swizzle ) +{ + return ureg_swizzle( src, + GET_SWZ( swizzle, 0 ) & 0x3, + GET_SWZ( swizzle, 1 ) & 0x3, + GET_SWZ( swizzle, 2 ) & 0x3, + GET_SWZ( swizzle, 3 ) & 0x3); +} + + +/** * Create a TGSI ureg_src register from a Mesa src register. */ static struct ureg_src @@ -329,6 +350,10 @@ translate_src( struct st_translate *t, { struct ureg_src src = src_register( t, SrcReg->File, SrcReg->Index ); + if (SrcReg->File == PROGRAM_UNDEFINED) { + return src; + } + if (t->procType == TGSI_PROCESSOR_GEOMETRY && SrcReg->HasIndex2) { src = src_register( t, SrcReg->File, SrcReg->Index2 ); if (SrcReg->RelAddr2) @@ -338,11 +363,7 @@ translate_src( struct st_translate *t, src = ureg_src_dimension( src, SrcReg->Index); } - src = ureg_swizzle( src, - GET_SWZ( SrcReg->Swizzle, 0 ) & 0x3, - GET_SWZ( SrcReg->Swizzle, 1 ) & 0x3, - GET_SWZ( SrcReg->Swizzle, 2 ) & 0x3, - GET_SWZ( SrcReg->Swizzle, 3 ) & 0x3); + src = swizzle_uint( src, SrcReg->Swizzle ); if (SrcReg->Negate == NEGATE_XYZW) src = ureg_negate(src); @@ -654,6 +675,58 @@ translate_opcode( unsigned op ) } +/** + * Emulate the condition mask with an opcode. + * + * Returns a ureg source register with the boolean result. + */ +static struct ureg_src +emit_setcmp( struct st_translate *t, + GLuint condcode, + struct ureg_dst tmp, + struct ureg_src src0 ) +{ + struct ureg_program *ureg = t->ureg; + struct ureg_src src[2]; + uint opcode; + + switch (condcode) { + case COND_GT: + opcode = TGSI_OPCODE_SGT; + break; + case COND_EQ: + opcode = TGSI_OPCODE_SEQ; + break; + case COND_GE: + opcode = TGSI_OPCODE_SGE; + break; + case COND_LT: + opcode = TGSI_OPCODE_SLT; + break; + case COND_NE: + opcode = TGSI_OPCODE_SNE; + break; + case COND_LE: + opcode = TGSI_OPCODE_SLE; + break; + case COND_TR: + return ureg_imm1f( ureg, 1.0f ); + case COND_FL: + return ureg_imm1f( ureg, 0.0f ); + default: + assert(0); + return ureg_imm1f( ureg, 0.0f ); + } + + src[0] = src0; + src[1] = ureg_imm1f( ureg, 0.0f ); + + ureg_insn( ureg, opcode, &tmp, 1, src, 2 ); + + return ureg_scalar( ureg_src(tmp), 0 ); +} + + static void compile_instruction( struct st_translate *t, @@ -665,6 +738,7 @@ compile_instruction( struct ureg_src src[4]; unsigned num_dst; unsigned num_src; + struct ureg_dst tmp = ureg_dst_undef(); num_dst = _mesa_num_inst_dst_regs( inst->Opcode ); num_src = _mesa_num_inst_src_regs( inst->Opcode ); @@ -680,19 +754,33 @@ compile_instruction( switch( inst->Opcode ) { case OPCODE_SWZ: emit_swz( t, dst[0], &inst->SrcReg[0] ); - return; + break; + + case OPCODE_IF: + debug_assert(num_dst == 0); + + if (inst->SrcReg[0].File == PROGRAM_UNDEFINED) { + tmp = ureg_DECL_temporary( ureg ); + + if (ureg_src_is_undef( t->cond )) { + t->cond = ureg_imm1f( ureg, 0.0f ); + } + src[0] = swizzle_uint( t->cond, inst->DstReg.CondSwizzle ) ; + + src[0] = emit_setcmp( t, inst->DstReg.CondMask, tmp, src[0] ); + } + + /* fall-through */ case OPCODE_BGNLOOP: case OPCODE_CAL: case OPCODE_ELSE: case OPCODE_ENDLOOP: - case OPCODE_IF: - debug_assert(num_dst == 0); ureg_label_insn( ureg, translate_opcode( inst->Opcode ), src, num_src, get_label( t, inst->BranchTarget )); - return; + break; case OPCODE_TEX: case OPCODE_TXB: @@ -706,7 +794,7 @@ compile_instruction( translate_texture_target( inst->TexSrcTarget, inst->TexShadow ), src, num_src ); - return; + break; case OPCODE_SCS: dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XY ); @@ -748,6 +836,13 @@ compile_instruction( src, num_src ); break; } + + /* Update the condition code register */ + if (inst->CondUpdate) { + t->cond = ureg_src( dst[0] ); + } + + ureg_release_temporary( ureg, tmp ); } @@ -1191,6 +1286,9 @@ st_translate_mesa_program( } } + /* condition code register -- initialized on first use */ + t->cond = ureg_src_undef(); + /* Emit each instruction in turn: */ for (i = 0; i < program->NumInstructions; i++) { -- 1.7.4.4