[1/3] d3dx9: Add swizzle and writemask support to the shader assembler.
Matteo Bruni
matteo.mystral at gmail.com
Thu Apr 8 07:20:48 CDT 2010
-------------- next part --------------
From 8fca6d279251ea247daaaa478a7c5244e7bc41ba Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Sun, 4 Apr 2010 22:49:58 +0200
Subject: d3dx9: Add swizzle and writemask support to the shader assembler.
---
dlls/d3dx9_36/asmshader.l | 72 ++++++++++++++++++++++++++++
dlls/d3dx9_36/asmshader.y | 39 +++++++++++++++
dlls/d3dx9_36/asmutils.c | 95 +++++++++++++++++++++++++++++++++++++-
dlls/d3dx9_36/d3dx9_36_private.h | 12 +++++
4 files changed, 216 insertions(+), 2 deletions(-)
diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l
index 99af380..c5402f2 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. color(argb) and
+ * coordinate(xyzw) components cannot be mixed.
+ */
+SWIZZLE \.(([w-z]+)|((a|r|g|b)+))
+
/* Registers */
REG_TEMP r[0-9]+
/* for relative addressing in the form o[x], v[x] and c[x] */
@@ -89,6 +96,71 @@ ps_2_0 {return VER_PS20; }
ps_2_x {return VER_PS2X; }
ps_3_0 {return VER_PS30; }
+{SWIZZLE} {
+ unsigned char i;
+ char last = 0;
+ DWORD ret = 0;
+ BOOL wmask_valid = TRUE;
+
+ /* Ignore the '.', hence the +1 */
+ asmshader_lval.swizzle_wmask.swizzle = text2swizzle(yytext + 1);
+ if(asmshader_lval.swizzle_wmask.swizzle == SWIZZLE_ERR) {
+ TRACE("Invalid swizzle/writemask %s\n", yytext);
+ asmshader_lval.swizzle_wmask.writemask = 0;
+ return SWIZZLE;
+ }
+ ret = 0;
+ last = 0;
+ for(i = 0; i < strlen(yytext + 1); i++) {
+ switch(yytext[i + 1]) {
+ case 'x':
+ case 'r':
+ if(last == 'x' || last == 'y' || last == 'z' || last == 'w') {
+ wmask_valid = FALSE;
+ break;
+ }
+ ret |= BWRITERSP_WRITEMASK_0;
+ last = 'x';
+ break;
+ case 'y':
+ case 'g':
+ if(last == 'y' || last == 'z' || last == 'w') {
+ wmask_valid = FALSE;
+ break;
+ }
+ ret |= BWRITERSP_WRITEMASK_1;
+ last = 'y';
+ break;
+ case 'z':
+ case 'b':
+ if(last == 'z' || last == 'w') {
+ wmask_valid = FALSE;
+ break;
+ }
+ ret |= BWRITERSP_WRITEMASK_2;
+ last = 'z';
+ break;
+ case 'w':
+ case 'a':
+ if(last == 'w') {
+ wmask_valid = FALSE;
+ break;
+ }
+ ret |= BWRITERSP_WRITEMASK_3;
+ last = 'w';
+ break;
+ }
+ }
+ if(wmask_valid) {
+ TRACE("Swizzle/Writemask string is a valid writemask\n");
+ asmshader_lval.swizzle_wmask.writemask = ret;
+ } else {
+ TRACE("Swizzle/Writemask string is not a valid writemask\n");
+ asmshader_lval.swizzle_wmask.writemask = 0;
+ }
+ return SWIZZLE;
+ }
+
{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..b379d74 100644
--- a/dlls/d3dx9_36/asmshader.y
+++ b/dlls/d3dx9_36/asmshader.y
@@ -82,12 +82,15 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%token VER_PS2X
%token VER_PS30
+/* Misc stuff */
+%token <swizzle_wmask> SWIZZLE
%type <reg> dreg_name
%type <reg> dreg
%type <reg> sreg_name
%type <reg> sreg
%type <swizzle> swizzle
+%type <writemask> writemask
%type <modshift> omods
%type <rel_reg> rel_reg
%type <sregs> sregs
@@ -202,17 +205,53 @@ 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: SWIZZLE
+ {
+ TRACE("Got a writemask\n");
+ if($1.writemask == 0) {
+ 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 {
+ $$ = $1.writemask;
+ }
+ }
+
swizzle: /* empty */
{
$$ = BWRITERVS_NOSWIZZLE;
TRACE("Default swizzle: %08x\n", $$);
}
+ | SWIZZLE
+ {
+ if($1.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 {
+ TRACE("Got a swizzle: %08x\n", $1.swizzle);
+ $$ = $1.swizzle;
+ }
+ }
omods: /* Empty */
{
diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c
index facb2af..7ed2408 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";
}
@@ -118,3 +170,42 @@ const char *debug_print_opcode(DWORD opcode) {
default: return "unknown";
}
}
+
+DWORD text2swizzle(const char *text) {
+ DWORD ret = 0;
+ char last = 0;
+ unsigned int i, len = strlen(text);
+
+ if(len > 4){
+ TRACE("Invalid swizzle %s\n", text);
+ return SWIZZLE_ERR;
+ }
+
+ for(i = 0; i < 4; i++) {
+ if(i < len) {
+ last = text[i];
+ }
+ switch(last) {
+ case 'x':
+ case 'r':
+ ret |= (BWRITERVS_X_X << (2 * i));
+ break;
+ case 'y':
+ case 'g':
+ ret |= (BWRITERVS_X_Y << (2 * i));
+ break;
+ case 'z':
+ case 'b':
+ ret |= (BWRITERVS_X_Z << (2 * i));
+ break;
+ case 'w':
+ case 'a':
+ ret |= (BWRITERVS_X_W << (2 * i));
+ break;
+ default:
+ TRACE("Unexpected swizzle character %c\n", last);
+ return SWIZZLE_ERR;
+ }
+ }
+ return ret;
+}
diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index 275b153..9d50b80 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,11 @@ DWORD d3d9_writemask(DWORD bwriter_writemask);
DWORD d3d9_register(DWORD bwriter_register);
DWORD d3d9_opcode(DWORD bwriter_opcode);
+/* Misc utility functions */
+#define SWIZZLE_ERR ~0U
+DWORD text2swizzle(const char *text);
+
+
/*
Enumerations and defines used in the bytecode writer
intermediate representation
@@ -407,6 +414,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);
--
1.6.4.4
More information about the wine-patches
mailing list