d3dx9: Add relative addressing support to the shader assembler.

This commit is contained in:
Matteo Bruni 2010-05-05 19:55:26 +02:00 committed by Alexandre Julliard
parent 5f934aca62
commit 399bde576e
5 changed files with 168 additions and 12 deletions

View File

@ -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} {

View File

@ -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;

View File

@ -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";

View File

@ -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[] = {

View File

@ -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",