d3dx9: Add relative addressing support to the shader assembler.
This commit is contained in:
parent
5f934aca62
commit
399bde576e
|
@ -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} {
|
||||
|
|
|
@ -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> COMPONENT
|
||||
%token <immval> IMMVAL
|
||||
|
||||
%type <reg> dreg_name
|
||||
%type <reg> dreg
|
||||
%type <reg> sreg_name
|
||||
%type <reg> relreg_name
|
||||
%type <reg> sreg
|
||||
%type <srcmod> smod
|
||||
%type <writemask> writemask
|
||||
|
@ -131,6 +150,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
|
|||
%type <modshift> omods
|
||||
%type <modshift> omodifier
|
||||
%type <rel_reg> rel_reg
|
||||
%type <immval> immsum
|
||||
%type <sregs> 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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue