[1/3] d3dx9: Add swizzle and writemask support to the shader assembler. [try 2]
Matteo Bruni
matteo.mystral at gmail.com
Wed Apr 21 11:08:42 CDT 2010
Hi,
I've modified the swizzle/writemask parsing to better split the two. I
couldn't write the writemask rule as a list of accepted strings, as
they are too many (native accepts mixed [xyzw] and [rgba] in the same
writemask, test included), so I had to recur to the COMPONENT token
here too.
-------------- next part --------------
From bdcf52d8552b5d0250f4f33f3dca42fd5ad62fc7 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Wed, 21 Apr 2010 16:15:46 +0200
Subject: d3dx9: Add swizzle and writemask support to the shader assembler.
---
dlls/d3dx9_36/asmshader.l | 30 +++++++++++
dlls/d3dx9_36/asmshader.y | 100 ++++++++++++++++++++++++++++++++++++-
dlls/d3dx9_36/asmutils.c | 56 ++++++++++++++++++++-
dlls/d3dx9_36/d3dx9_36_private.h | 10 ++++
dlls/d3dx9_36/tests/asm.c | 11 ++++
5 files changed, 202 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l
index 99af380..ad1efab 100644
--- a/dlls/d3dx9_36/asmshader.l
+++ b/dlls/d3dx9_36/asmshader.l
@@ -34,6 +34,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
%option prefix="asmshader_"
%option noinput nounput
+/* Swizzles and writemasks consist of a dot and up to 4 x, y, z or w characters,
+ * or up to 4 a, r, g, b characters. There are different rules for swizzles and
+ * writemasks wrt repetition, those are handled in the grammar.
+ */
+DOT \.
+COMPONENT [xyzw]|[rgba]
+
/* Registers */
REG_TEMP r[0-9]+
/* for relative addressing in the form o[x], v[x] and c[x] */
@@ -89,6 +96,29 @@ ps_2_0 {return VER_PS20; }
ps_2_x {return VER_PS2X; }
ps_3_0 {return VER_PS30; }
+{DOT} {return yytext[0]; }
+{COMPONENT} {
+ switch(yytext[0]) {
+ case 'x':
+ case 'r':
+ asmshader_lval.component = 0;
+ break;
+ case 'y':
+ case 'g':
+ asmshader_lval.component = 1;
+ break;
+ case 'z':
+ case 'b':
+ asmshader_lval.component = 2;
+ break;
+ case 'w':
+ case 'a':
+ asmshader_lval.component = 3;
+ break;
+ }
+ return COMPONENT;
+ }
+
{COMMA} {return yytext[0]; }
- {return yytext[0]; }
\( {return yytext[0]; }
diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y
index 93741b6..e0117c6 100644
--- a/dlls/d3dx9_36/asmshader.y
+++ b/dlls/d3dx9_36/asmshader.y
@@ -45,13 +45,19 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%union {
unsigned int regnum;
struct shader_reg reg;
+ DWORD writemask;
struct {
- DWORD swizzle;
DWORD writemask;
- } swizzle_wmask;
- DWORD writemask;
+ DWORD idx;
+ DWORD last;
+ } wm_components;
DWORD swizzle;
struct {
+ DWORD swizzle;
+ DWORD idx;
+ } sw_components;
+ DWORD component;
+ struct {
DWORD mod;
DWORD shift;
} modshift;
@@ -82,12 +88,17 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%token VER_PS2X
%token VER_PS30
+/* Misc stuff */
+%token <component> COMPONENT
%type <reg> dreg_name
%type <reg> dreg
%type <reg> sreg_name
%type <reg> sreg
+%type <writemask> writemask
+%type <wm_components> wm_components
%type <swizzle> swizzle
+%type <sw_components> sw_components
%type <modshift> omods
%type <rel_reg> rel_reg
%type <sregs> sregs
@@ -202,17 +213,100 @@ dreg: dreg_name rel_reg
$$.srcmod = BWRITERSPSM_NONE;
set_rel_reg(&$$, &$2);
}
+ | dreg_name writemask
+ {
+ $$.regnum = $1.regnum;
+ $$.type = $1.type;
+ $$.writemask = $2;
+ $$.srcmod = BWRITERSPSM_NONE;
+ $$.rel_reg = NULL;
+ }
dreg_name: REG_TEMP
{
$$.regnum = $1; $$.type = BWRITERSPR_TEMP;
}
+writemask: '.' wm_components
+ {
+ if($2.writemask == SWIZZLE_ERR) {
+ asmparser_message(&asm_ctx, "Line %u: Invalid writemask specified\n",
+ asm_ctx.line_no);
+ set_parse_status(&asm_ctx, PARSE_ERR);
+ /* Provide a correct writemask to prevent following complaints */
+ $$ = BWRITERSP_WRITEMASK_ALL;
+ }
+ else {
+ $$ = $2.writemask;
+ TRACE("Writemask: %x\n", $$);
+ }
+ }
+
+wm_components: COMPONENT
+ {
+ $$.writemask = 1 << $1;
+ $$.last = $1;
+ $$.idx = 1;
+ }
+ | wm_components COMPONENT
+ {
+ if($1.writemask == SWIZZLE_ERR || $1.idx == 4)
+ /* Wrong writemask */
+ $$.writemask = SWIZZLE_ERR;
+ else {
+ if($2 <= $1.last)
+ $$.writemask = SWIZZLE_ERR;
+ else {
+ $$.writemask = $1.writemask | (1 << $2);
+ $$.idx = $1.idx + 1;
+ }
+ }
+ }
+
swizzle: /* empty */
{
$$ = BWRITERVS_NOSWIZZLE;
TRACE("Default swizzle: %08x\n", $$);
}
+ | '.' sw_components
+ {
+ if($2.swizzle == SWIZZLE_ERR) {
+ asmparser_message(&asm_ctx, "Line %u: Invalid swizzle\n",
+ asm_ctx.line_no);
+ set_parse_status(&asm_ctx, PARSE_ERR);
+ /* Provide a correct swizzle to prevent following complaints */
+ $$ = BWRITERVS_NOSWIZZLE;
+ }
+ else {
+ DWORD last, i;
+
+ $$ = $2.swizzle << BWRITERVS_SWIZZLE_SHIFT;
+ /* Fill the swizzle by extending the last component */
+ last = ($2.swizzle >> 2 * ($2.idx - 1)) & 0x03;
+ for(i = $2.idx; i < 4; i++){
+ $$ |= last << (BWRITERVS_SWIZZLE_SHIFT + 2 * i);
+ }
+ TRACE("Got a swizzle: %08x\n", $$);
+ }
+ }
+
+sw_components: COMPONENT
+ {
+ $$.swizzle = $1;
+ $$.idx = 1;
+ }
+ | sw_components COMPONENT
+ {
+ if($1.idx == 4) {
+ /* Too many sw_components */
+ $$.swizzle = SWIZZLE_ERR;
+ $$.idx = 4;
+ }
+ else {
+ $$.swizzle = $1.swizzle | ($2 << 2 * $1.idx);
+ $$.idx = $1.idx + 1;
+ }
+ }
omods: /* Empty */
{
diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c
index facb2af..6fd186a 100644
--- a/dlls/d3dx9_36/asmutils.c
+++ b/dlls/d3dx9_36/asmutils.c
@@ -99,14 +99,66 @@ static const char *get_regname(const struct shader_reg *reg, shader_type st) {
}
}
+const char *debug_print_writemask(DWORD mask) {
+ char ret[6];
+ unsigned char pos = 1;
+
+ if(mask == BWRITERSP_WRITEMASK_ALL) return "";
+ ret[0] = '.';
+ if(mask & BWRITERSP_WRITEMASK_0) ret[pos++] = 'x';
+ if(mask & BWRITERSP_WRITEMASK_1) ret[pos++] = 'y';
+ if(mask & BWRITERSP_WRITEMASK_2) ret[pos++] = 'z';
+ if(mask & BWRITERSP_WRITEMASK_3) ret[pos++] = 'w';
+ ret[pos] = 0;
+ return wine_dbg_sprintf("%s", ret);
+}
+
const char *debug_print_dstreg(const struct shader_reg *reg, shader_type st) {
- return get_regname(reg, st);
+ return wine_dbg_sprintf("%s%s", get_regname(reg, st),
+ debug_print_writemask(reg->writemask));
+}
+
+const char *debug_print_swizzle(DWORD arg) {
+ char ret[6];
+ unsigned int i;
+ DWORD swizzle[4];
+
+ switch(arg) {
+ case BWRITERVS_NOSWIZZLE:
+ return "";
+ case BWRITERVS_SWIZZLE_X:
+ return ".x";
+ case BWRITERVS_SWIZZLE_Y:
+ return ".y";
+ case BWRITERVS_SWIZZLE_Z:
+ return ".z";
+ case BWRITERVS_SWIZZLE_W:
+ return ".w";
+ }
+
+ swizzle[0] = (arg >> (BWRITERVS_SWIZZLE_SHIFT + 0)) & 0x03;
+ swizzle[1] = (arg >> (BWRITERVS_SWIZZLE_SHIFT + 2)) & 0x03;
+ swizzle[2] = (arg >> (BWRITERVS_SWIZZLE_SHIFT + 4)) & 0x03;
+ swizzle[3] = (arg >> (BWRITERVS_SWIZZLE_SHIFT + 6)) & 0x03;
+
+ ret[0] = '.';
+ for(i = 0; i < 4; i++) {
+ switch(swizzle[i]) {
+ case 0: ret[1 + i] = 'x'; break;
+ case 1: ret[1 + i] = 'y'; break;
+ case 2: ret[1 + i] = 'z'; break;
+ case 3: ret[1 + i] = 'w'; break;
+ }
+ }
+ ret[5] = '\0';
+ return wine_dbg_sprintf("%s", ret);
}
const char *debug_print_srcreg(const struct shader_reg *reg, shader_type st) {
switch(reg->srcmod) {
case BWRITERSPSM_NONE:
- return get_regname(reg, st);
+ return wine_dbg_sprintf("%s%s", get_regname(reg, st),
+ debug_print_swizzle(reg->swizzle));
}
return "Unknown modifier";
}
diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index 275b153..7146f99 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -342,6 +342,8 @@ struct bc_writer {
/* Debug utility routines */
const char *debug_print_dstreg(const struct shader_reg *reg, shader_type st);
const char *debug_print_srcreg(const struct shader_reg *reg, shader_type st);
+const char *debug_print_swizzle(DWORD swizzle);
+const char *debug_print_writemask(DWORD mask);
const char *debug_print_opcode(DWORD opcode);
/* Utilities for internal->d3d constant mapping */
@@ -350,6 +352,9 @@ DWORD d3d9_writemask(DWORD bwriter_writemask);
DWORD d3d9_register(DWORD bwriter_register);
DWORD d3d9_opcode(DWORD bwriter_opcode);
+/* Used to signal an incorrect swizzle/writemask */
+#define SWIZZLE_ERR ~0U
+
/*
Enumerations and defines used in the bytecode writer
intermediate representation
@@ -407,6 +412,11 @@ typedef enum _BWRITERSHADER_PARAM_SRCMOD_TYPE {
#define BWRITERVS_NOSWIZZLE (BWRITERVS_X_X | BWRITERVS_Y_Y | BWRITERVS_Z_Z | BWRITERVS_W_W)
+#define BWRITERVS_SWIZZLE_X (BWRITERVS_X_X | BWRITERVS_Y_X | BWRITERVS_Z_X | BWRITERVS_W_X)
+#define BWRITERVS_SWIZZLE_Y (BWRITERVS_X_Y | BWRITERVS_Y_Y | BWRITERVS_Z_Y | BWRITERVS_W_Y)
+#define BWRITERVS_SWIZZLE_Z (BWRITERVS_X_Z | BWRITERVS_Y_Z | BWRITERVS_Z_Z | BWRITERVS_W_Z)
+#define BWRITERVS_SWIZZLE_W (BWRITERVS_X_W | BWRITERVS_Y_W | BWRITERVS_Z_W | BWRITERVS_W_W)
+
struct bwriter_shader *SlAssembleShader(const char *text, char **messages);
DWORD SlWriteBytecode(const struct bwriter_shader *shader, int dxversion, DWORD **result);
void SlDeleteShader(struct bwriter_shader *shader);
diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c
index de29e45..6cf8e08 100644
--- a/dlls/d3dx9_36/tests/asm.c
+++ b/dlls/d3dx9_36/tests/asm.c
@@ -1058,6 +1058,17 @@ static void vs_3_0_test(void) {
"mov r2, r1_abs\n",
{0xfffe0300, 0x02000001, 0x800f0002, 0x8be40001, 0x0000ffff}
},*/
+ { /* shader 9 */
+ "vs_3_0\n"
+ "mov r2, r1.xygb\n",
+ {0xfffe0300, 0x02000001, 0x800f0002, 0x80940001, 0x0000ffff}
+ },
+ { /* shader 10 */
+ "vs_3_0\n"
+ "mov r2.xyb, r1\n",
+ {0xfffe0300, 0x02000001, 0x80070002, 0x80e40001, 0x0000ffff}
+ },
+
};
exec_tests("vs_3_0", tests, sizeof(tests) / sizeof(tests[0]));
--
1.6.4.4
More information about the wine-patches
mailing list