d3dx9: Add swizzle and writemask support to the shader assembler.
This commit is contained in:
parent
82fdc926a2
commit
9019267bfa
|
@ -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]; }
|
||||
|
|
|
@ -45,12 +45,18 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
|
|||
%union {
|
||||
unsigned int regnum;
|
||||
struct shader_reg reg;
|
||||
DWORD writemask;
|
||||
struct {
|
||||
DWORD writemask;
|
||||
DWORD idx;
|
||||
DWORD last;
|
||||
} wm_components;
|
||||
DWORD swizzle;
|
||||
struct {
|
||||
DWORD swizzle;
|
||||
DWORD writemask;
|
||||
} swizzle_wmask;
|
||||
DWORD writemask;
|
||||
DWORD swizzle;
|
||||
DWORD idx;
|
||||
} sw_components;
|
||||
DWORD component;
|
||||
struct {
|
||||
DWORD mod;
|
||||
DWORD shift;
|
||||
|
@ -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 */
|
||||
{
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]));
|
||||
|
|
Loading…
Reference in New Issue