[2/3] d3dx9: Add relative addressing support to the shader assembler.
Matteo Bruni
matteo.mystral at gmail.com
Wed May 5 14:00:37 CDT 2010
-------------- next part --------------
From 36d8aa46b1f7413f53053495214238c73d51e6a7 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Wed, 5 May 2010 19:55:26 +0200
Subject: d3dx9: Add relative addressing support to the shader assembler.
---
dlls/d3dx9_36/asmshader.l | 9 ++++
dlls/d3dx9_36/asmshader.y | 87 +++++++++++++++++++++++++++++++++++++++-
dlls/d3dx9_36/asmutils.c | 30 +++++++++++--
dlls/d3dx9_36/bytecodewriter.c | 42 +++++++++++++++++++
dlls/d3dx9_36/tests/asm.c | 12 +++---
5 files changed, 168 insertions(+), 12 deletions(-)
diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l
index b0a1e9e..1d0e4b6 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 3f65fb3..a6d2db6 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> 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;
diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c
index 87f948b..725931c 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 caf2c4b..0081576 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 7056ef5..14b1e9c 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",
--
1.6.4.4
More information about the wine-patches
mailing list