diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l index b0a1e9e5678..1d0e4b6efda 100644 --- a/dlls/d3dx9_36/asmshader.l +++ b/dlls/d3dx9_36/asmshader.l @@ -194,11 +194,20 @@ ps_3_0 {return VER_PS30; } \_pp {return MOD_PP; } \_centroid {return MOD_CENTROID; } +{IMMVAL} { + asmshader_lval.immval.val = atof(yytext); + asmshader_lval.immval.integer = ((strstr(yytext, ".") == NULL) && (strstr(yytext, "f") == NULL)); + return IMMVAL; + } + {COMMA} {return yytext[0]; } - {return yytext[0]; } \( {return yytext[0]; } \) {return yytext[0]; } + /* for relative addressing */ +\[|\]|\+ {return yytext[0]; } + \_abs {return SMOD_ABS; } {PREPROCESSORDIRECTIVE} { diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y index 3f65fb358cd..a6d2db6611a 100644 --- a/dlls/d3dx9_36/asmshader.y +++ b/dlls/d3dx9_36/asmshader.y @@ -37,12 +37,29 @@ void asmshader_error(const char *s); int asmshader_lex(void); void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) { - reg->rel_reg = NULL; + /* We can have an additional offset without true relative addressing + * ex. c2[ 4 ] */ + reg->regnum += rel->additional_offset; + if(!rel->has_rel_reg) { + reg->rel_reg = NULL; + } else { + reg->rel_reg = asm_alloc(sizeof(*reg->rel_reg)); + if(!reg->rel_reg) { + return; + } + reg->rel_reg->type = rel->type; + reg->rel_reg->swizzle = rel->swizzle; + reg->rel_reg->regnum = rel->rel_regnum; + } } %} %union { + struct { + float val; + BOOL integer; + } immval; unsigned int regnum; struct shader_reg reg; DWORD srcmod; @@ -118,10 +135,12 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) { /* Misc stuff */ %token COMPONENT +%token IMMVAL %type dreg_name %type dreg %type sreg_name +%type relreg_name %type sreg %type smod %type writemask @@ -131,6 +150,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) { %type omods %type omodifier %type rel_reg +%type immsum %type sregs %% @@ -523,12 +543,77 @@ rel_reg: /* empty */ $$.has_rel_reg = FALSE; $$.additional_offset = 0; } + | '[' immsum ']' + { + $$.has_rel_reg = FALSE; + $$.additional_offset = $2.val; + } + | '[' relreg_name swizzle ']' + { + $$.has_rel_reg = TRUE; + $$.type = $2.type; + $$.additional_offset = 0; + $$.rel_regnum = $2.regnum; + $$.swizzle = $3; + } + | '[' immsum '+' relreg_name swizzle ']' + { + $$.has_rel_reg = TRUE; + $$.type = $4.type; + $$.additional_offset = $2.val; + $$.rel_regnum = $4.regnum; + $$.swizzle = $5; + } + | '[' relreg_name swizzle '+' immsum ']' + { + $$.has_rel_reg = TRUE; + $$.type = $2.type; + $$.additional_offset = $5.val; + $$.rel_regnum = $2.regnum; + $$.swizzle = $3; + } + | '[' immsum '+' relreg_name swizzle '+' immsum ']' + { + $$.has_rel_reg = TRUE; + $$.type = $4.type; + $$.additional_offset = $2.val + $7.val; + $$.rel_regnum = $4.regnum; + $$.swizzle = $5; + } + +immsum: IMMVAL + { + if(!$1.integer) { + asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n", + asm_ctx.line_no, $1.val); + set_parse_status(&asm_ctx, PARSE_ERR); + } + $$.val = $1.val; + } + | immsum '+' IMMVAL + { + if(!$3.integer) { + asmparser_message(&asm_ctx, "Line %u: Unexpected float %f\n", + asm_ctx.line_no, $3.val); + set_parse_status(&asm_ctx, PARSE_ERR); + } + $$.val = $1.val + $3.val; + } smod: SMOD_ABS { $$ = BWRITERSPSM_ABS; } +relreg_name: REG_ADDRESS + { + $$.regnum = 0; $$.type = BWRITERSPR_ADDR; + } + | REG_LOOP + { + $$.regnum = 0; $$.type = BWRITERSPR_LOOP; + } + sreg_name: REG_TEMP { $$.regnum = $1; $$.type = BWRITERSPR_TEMP; diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c index 87f948b8e9e..725931cc8bb 100644 --- a/dlls/d3dx9_36/asmutils.c +++ b/dlls/d3dx9_36/asmutils.c @@ -231,8 +231,24 @@ const char *debug_print_writemask(DWORD mask) { return wine_dbg_sprintf("%s", ret); } +const char *debug_print_relarg(const struct shader_reg *reg) { + const char *short_swizzle; + if(!reg->rel_reg) return ""; + + short_swizzle = debug_print_swizzle(reg->rel_reg->swizzle); + + if(reg->rel_reg->type == BWRITERSPR_ADDR) { + return wine_dbg_sprintf("[a%u%s]", reg->rel_reg->regnum, short_swizzle); + } else if(reg->rel_reg->type == BWRITERSPR_LOOP && reg->rel_reg->regnum == 0) { + return wine_dbg_sprintf("[aL%s]", short_swizzle); + } else { + return "Unexpected relative addressing argument"; + } +} + const char *debug_print_dstreg(const struct shader_reg *reg, shader_type st) { - return wine_dbg_sprintf("%s%s", get_regname(reg, st), + return wine_dbg_sprintf("%s%s%s", get_regname(reg, st), + debug_print_relarg(reg), debug_print_writemask(reg->writemask)); } @@ -275,16 +291,20 @@ const char *debug_print_swizzle(DWORD arg) { const char *debug_print_srcreg(const struct shader_reg *reg, shader_type st) { switch(reg->srcmod) { case BWRITERSPSM_NONE: - return wine_dbg_sprintf("%s%s", get_regname(reg, st), + return wine_dbg_sprintf("%s%s%s", get_regname(reg, st), + debug_print_relarg(reg), debug_print_swizzle(reg->swizzle)); case BWRITERSPSM_NEG: - return wine_dbg_sprintf("-%s%s", get_regname(reg, st), + return wine_dbg_sprintf("-%s%s%s", get_regname(reg, st), + debug_print_relarg(reg), debug_print_swizzle(reg->swizzle)); case BWRITERSPSM_ABS: - return wine_dbg_sprintf("%s_abs%s", get_regname(reg, st), + return wine_dbg_sprintf("%s%s_abs%s", get_regname(reg, st), + debug_print_relarg(reg), debug_print_swizzle(reg->swizzle)); case BWRITERSPSM_ABSNEG: - return wine_dbg_sprintf("-%s_abs%s", get_regname(reg, st), + return wine_dbg_sprintf("-%s%s_abs%s", get_regname(reg, st), + debug_print_relarg(reg), debug_print_swizzle(reg->swizzle)); } return "Unknown modifier"; diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c index caf2c4b0d34..00815767772 100644 --- a/dlls/d3dx9_36/bytecodewriter.c +++ b/dlls/d3dx9_36/bytecodewriter.c @@ -219,7 +219,31 @@ static void sm_3_srcreg(struct bc_writer *This, token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK; token |= d3d9_srcmod(reg->srcmod); + if(reg->rel_reg) { + if(reg->type == BWRITERSPR_CONST && This->version == BWRITERPS_VERSION(3, 0)) { + WARN("c%u[...] is unsupported in ps_3_0\n", reg->regnum); + This->state = E_INVALIDARG; + return; + } + if(((reg->rel_reg->type == BWRITERSPR_ADDR && This->version == BWRITERVS_VERSION(3, 0)) || + reg->rel_reg->type == BWRITERSPR_LOOP) && + reg->rel_reg->regnum == 0) { + token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK; + } else { + WARN("Unsupported relative addressing register\n"); + This->state = E_INVALIDARG; + return; + } + } + put_dword(buffer, token); + + /* vs_2_0 and newer write the register containing the index explicitly in the + * binary code + */ + if(token & D3DVS_ADDRMODE_RELATIVE) { + sm_3_srcreg(This, reg->rel_reg, buffer); + } } static void sm_3_dstreg(struct bc_writer *This, @@ -229,6 +253,17 @@ static void sm_3_dstreg(struct bc_writer *This, DWORD token = (1 << 31); /* Bit 31 of registers is 1 */ DWORD d3d9reg; + if(reg->rel_reg) { + if(This->version == BWRITERVS_VERSION(3, 0) && + reg->type == BWRITERSPR_OUTPUT) { + token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK; + } else { + WARN("Relative addressing not supported for this shader type or register type\n"); + This->state = E_INVALIDARG; + return; + } + } + d3d9reg = d3d9_register(reg->type); token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK; token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2; @@ -238,6 +273,13 @@ static void sm_3_dstreg(struct bc_writer *This, token |= d3d9_writemask(reg->writemask); put_dword(buffer, token); + + /* vs_2_0 and newer write the register containing the index explicitly in the + * binary code + */ + if(token & D3DVS_ADDRMODE_RELATIVE) { + sm_3_srcreg(This, reg->rel_reg, buffer); + } } static const struct instr_handler_table vs_3_handlers[] = { diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c index 7056ef5c1cd..14b1e9c9ea6 100644 --- a/dlls/d3dx9_36/tests/asm.c +++ b/dlls/d3dx9_36/tests/asm.c @@ -1038,16 +1038,16 @@ static void vs_3_0_test(void) { "texldl r0, v0, s0\n", {0xfffe0300, 0x0300005f, 0x800f0000, 0x90e40000, 0xa0e40800, 0x0000ffff} },*/ -/* {*/ /* shader 5 */ -/* "vs_3_0\n" + { /* shader 5 */ + "vs_3_0\n" "mov r0, c0[aL]\n", {0xfffe0300, 0x03000001, 0x800f0000, 0xa0e42000, 0xf0e40800, 0x0000ffff} - },*/ -/* {*/ /* shader 6 */ -/* "vs_3_0\n" + }, + { /* shader 6 */ + "vs_3_0\n" "mov o[ a0.x + 12 ], r0\n", {0xfffe0300, 0x03000001, 0xe00f200c, 0xb0000000, 0x80e40000, 0x0000ffff} - },*/ + }, /* {*/ /* shader 7 */ /* "vs_3_0\n" "add_sat r0, r0, r1\n",