[1/4] d3dx9: Add output dcl instruction partial support to the shader assembler.
Matteo Bruni
matteo.mystral at gmail.com
Thu May 13 10:23:28 CDT 2010
-------------- next part --------------
From d37957c10098100432ae5cd6b326d99b5d64f2d1 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Thu, 13 May 2010 17:21:58 +0200
Subject: d3dx9: Add output dcl instruction partial support to the shader assembler.
---
dlls/d3dx9_36/asmparser.c | 15 +++++++
dlls/d3dx9_36/asmshader.l | 12 ++++++
dlls/d3dx9_36/asmshader.y | 40 +++++++++++++++++++
dlls/d3dx9_36/asmutils.c | 2 +
dlls/d3dx9_36/bytecodewriter.c | 79 ++++++++++++++++++++++++++++++++++++++
dlls/d3dx9_36/d3dx9_36_private.h | 9 ++++
dlls/d3dx9_36/tests/asm.c | 6 +-
7 files changed, 160 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c
index e08c421..f1360cb 100644
--- a/dlls/d3dx9_36/asmparser.c
+++ b/dlls/d3dx9_36/asmparser.c
@@ -38,6 +38,19 @@ static void asmparser_end(struct asm_parser *This) {
TRACE("Finalizing shader\n");
}
+static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num,
+ const struct shader_reg *reg) {
+ if(!This->shader) return;
+ if(This->shader->type == ST_PIXEL) {
+ asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no);
+ set_parse_status(This, PARSE_ERR);
+ }
+ if(!record_declaration(This->shader, usage, num, TRUE, reg->regnum, reg->writemask)) {
+ ERR("Out of memory\n");
+ set_parse_status(This, PARSE_ERR);
+ }
+}
+
static void asmparser_instr(struct asm_parser *This, DWORD opcode,
DWORD mod, DWORD shift,
BWRITER_COMPARISON_TYPE comp,
@@ -135,6 +148,8 @@ static const struct asmparser_backend parser_vs_3 = {
asmparser_predicate_supported,
asmparser_coissue_unsupported,
+ asmparser_dcl_output,
+
asmparser_end,
asmparser_instr,
diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l
index 0fe0932..e76da62 100644
--- a/dlls/d3dx9_36/asmshader.l
+++ b/dlls/d3dx9_36/asmshader.l
@@ -66,6 +66,8 @@ REG_PREDICATE p0
/* Not really a register, but it is considered as such */
REG_LABEL l[0-9]+
+DCL_POSITION _position[0-9]*
+
PREPROCESSORDIRECTIVE #[^\n]*\n
/* Comments */
@@ -117,6 +119,7 @@ m4x3 {return INSTR_M4x3; }
m3x4 {return INSTR_M3x4; }
m3x3 {return INSTR_M3x3; }
m3x2 {return INSTR_M3x2; }
+dcl {return INSTR_DCL; }
rep {return INSTR_REP; }
endrep {return INSTR_ENDREP; }
if {return INSTR_IF; }
@@ -271,6 +274,15 @@ ps_3_0 {return VER_PS30; }
! {return SMOD_NOT; }
+{DCL_POSITION} {
+ if(yytext[strlen("_position")] == '\0') {
+ asmshader_lval.regnum = 0;
+ } else {
+ asmshader_lval.regnum = atoi(yytext + strlen("_position"));
+ }
+ return USAGE_POSITION;
+ }
+
{PREPROCESSORDIRECTIVE} {
/* TODO: update current line information */
TRACE("line info update: %s", yytext);
diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y
index 0c114e5..2a31ebe 100644
--- a/dlls/d3dx9_36/asmshader.y
+++ b/dlls/d3dx9_36/asmshader.y
@@ -80,6 +80,10 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
DWORD shift;
} modshift;
BWRITER_COMPARISON_TYPE comptype;
+ struct {
+ DWORD dclusage;
+ unsigned int regnum;
+ } declaration;
struct rel_reg rel_reg;
struct src_regs sregs;
}
@@ -117,6 +121,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%token INSTR_M3x4
%token INSTR_M3x3
%token INSTR_M3x2
+%token INSTR_DCL
%token INSTR_REP
%token INSTR_ENDREP
%token INSTR_IF
@@ -193,6 +198,9 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%token SMOD_ABS
%token SMOD_NOT
+/* Usage declaration tokens */
+%token <regnum> USAGE_POSITION
+
/* Misc stuff */
%token <component> COMPONENT
%token <immval> IMMVAL
@@ -210,6 +218,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%type <modshift> omods
%type <modshift> omodifier
%type <comptype> comp
+%type <declaration> dclusage
%type <rel_reg> rel_reg
%type <reg> predicate
%type <immval> immsum
@@ -476,6 +485,30 @@ instruction: INSTR_ADD omods dreg ',' sregs
TRACE("M3x2\n");
asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2);
}
+ | INSTR_DCL dclusage REG_OUTPUT
+ {
+ struct shader_reg reg;
+ TRACE("Output reg declaration\n");
+ ZeroMemory(®, sizeof(reg));
+ reg.type = BWRITERSPR_OUTPUT;
+ reg.regnum = $3;
+ reg.rel_reg = NULL;
+ reg.srcmod = 0;
+ reg.writemask = BWRITERSP_WRITEMASK_ALL;
+ asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, ®);
+ }
+ | INSTR_DCL dclusage REG_OUTPUT writemask
+ {
+ struct shader_reg reg;
+ TRACE("Output reg declaration\n");
+ ZeroMemory(®, sizeof(reg));
+ reg.type = BWRITERSPR_OUTPUT;
+ reg.regnum = $3;
+ reg.rel_reg = NULL;
+ reg.srcmod = 0;
+ reg.writemask = $4;
+ asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, ®);
+ }
| INSTR_REP sregs
{
TRACE("REP\n");
@@ -1041,6 +1074,13 @@ comp: COMP_GT { $$ = BWRITER_COMPARISON_GT; }
| COMP_EQ { $$ = BWRITER_COMPARISON_EQ; }
| COMP_NE { $$ = BWRITER_COMPARISON_NE; }
+dclusage: USAGE_POSITION
+ {
+ TRACE("dcl_position%u\n", $1);
+ $$.regnum = $1;
+ $$.dclusage = BWRITERDECLUSAGE_POSITION;
+ }
+
predicate: '(' REG_PREDICATE swizzle ')'
{
$$.type = BWRITERSPR_PREDICATE;
diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c
index 9adb108..c5098ca 100644
--- a/dlls/d3dx9_36/asmutils.c
+++ b/dlls/d3dx9_36/asmutils.c
@@ -162,6 +162,7 @@ DWORD d3d9_opcode(DWORD bwriter_opcode) {
case BWRITERSIO_RET: return D3DSIO_RET;
case BWRITERSIO_ENDLOOP: return D3DSIO_ENDLOOP;
case BWRITERSIO_LABEL: return D3DSIO_LABEL;
+ case BWRITERSIO_DCL: return D3DSIO_DCL;
case BWRITERSIO_POW: return D3DSIO_POW;
case BWRITERSIO_CRS: return D3DSIO_CRS;
case BWRITERSIO_SGN: return D3DSIO_SGN;
@@ -426,6 +427,7 @@ const char *debug_print_opcode(DWORD opcode) {
case BWRITERSIO_RET: return "ret";
case BWRITERSIO_ENDLOOP: return "endloop";
case BWRITERSIO_LABEL: return "label";
+ case BWRITERSIO_DCL: return "dcl";
case BWRITERSIO_POW: return "pow";
case BWRITERSIO_CRS: return "crs";
case BWRITERSIO_SGN: return "sgn";
diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c
index 64a7035..ff6393f 100644
--- a/dlls/d3dx9_36/bytecodewriter.c
+++ b/dlls/d3dx9_36/bytecodewriter.c
@@ -104,6 +104,54 @@ BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr) {
return TRUE;
}
+BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_idx, BOOL output, DWORD regnum, DWORD writemask) {
+ unsigned int *num;
+ struct declaration **decl;
+ unsigned int i;
+
+ if(!shader) return FALSE;
+
+ if(output) {
+ num = &shader->num_outputs;
+ decl = &shader->outputs;
+ } else {
+ num = &shader->num_inputs;
+ decl = &shader->inputs;
+ }
+
+ if(*num == 0) {
+ *decl = asm_alloc(sizeof(**decl));
+ if(!*decl) {
+ ERR("Error allocating declarations array\n");
+ return FALSE;
+ }
+ } else {
+ struct declaration *newdecl;
+ for(i = 0; i < *num; i++) {
+ if((*decl)[i].regnum == regnum && ((*decl)[i].writemask & writemask)) {
+ WARN("Declaration of register %u already exists, writemask match 0x%x\n",
+ regnum, (*decl)[i].writemask & writemask);
+ }
+ }
+
+ newdecl = asm_realloc(*decl,
+ sizeof(**decl) * ((*num) + 1));
+ if(!newdecl) {
+ ERR("Error reallocating declarations array\n");
+ return FALSE;
+ }
+ *decl = newdecl;
+ }
+ (*decl)[*num].usage = usage;
+ (*decl)[*num].usage_idx = usage_idx;
+ (*decl)[*num].regnum = regnum;
+ (*decl)[*num].writemask = writemask;
+ (*num)++;
+
+ return TRUE;
+}
+
+
/* shader bytecode buffer manipulation functions.
* allocate_buffer creates a new buffer structure, put_dword adds a new
* DWORD to the buffer. In the rare case of a memory allocation failure
@@ -147,6 +195,35 @@ static void put_dword(struct bytecode_buffer *buffer, DWORD value) {
/******************************************************
* Implementation of the writer functions starts here *
******************************************************/
+static void write_declarations(struct bytecode_buffer *buffer, BOOL len,
+ const struct declaration *decls, unsigned int num, DWORD type) {
+ DWORD i;
+ DWORD instr_dcl = D3DSIO_DCL;
+ DWORD token;
+
+ if(len) {
+ instr_dcl |= 2 << D3DSI_INSTLENGTH_SHIFT;
+ }
+
+ for(i = 0; i < num; i++) {
+ /* Write the DCL instruction */
+ put_dword(buffer, instr_dcl);
+
+ /* Write the usage and index */
+ token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
+ token |= (decls[i].usage << D3DSP_DCL_USAGE_SHIFT) & D3DSP_DCL_USAGE_MASK;
+ token |= (decls[i].usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT) & D3DSP_DCL_USAGEINDEX_MASK;
+ put_dword(buffer, token);
+
+ /* Write the dest register */
+ token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
+ token |= (type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
+ token |= (d3d9_writemask(decls[i].writemask)) & D3DSP_WRITEMASK_ALL;
+ token |= decls[i].regnum & D3DSP_REGNUM_MASK;
+ put_dword(buffer, token);
+ }
+}
+
static void end(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
put_dword(buffer, D3DSIO_END);
}
@@ -206,6 +283,8 @@ static void sm_2_opcode(struct bc_writer *This,
static void sm_3_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
/* Declare the shader type and version */
put_dword(buffer, This->version);
+
+ write_declarations(buffer, TRUE, shader->outputs, shader->num_outputs, D3DSPR_OUTPUT);
return;
}
diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index 6222d66..0e839dd 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -253,6 +253,9 @@ struct asmparser_backend {
const struct shader_reg *predicate);
void (*coissue)(struct asm_parser *This);
+ void (*dcl_output)(struct asm_parser *This, DWORD usage, DWORD num,
+ const struct shader_reg *reg);
+
void (*end)(struct asm_parser *This);
void (*instr)(struct asm_parser *This, DWORD opcode, DWORD mod, DWORD shift,
@@ -262,6 +265,7 @@ struct asmparser_backend {
struct instruction *alloc_instr(unsigned int srcs);
BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr);
+BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_idx, BOOL output, DWORD regnum, DWORD writemask);
#define MESSAGEBUFFER_INITIAL_SIZE 256
@@ -402,6 +406,7 @@ typedef enum _BWRITERSHADER_INSTRUCTION_OPCODE_TYPE {
BWRITERSIO_RET,
BWRITERSIO_ENDLOOP,
BWRITERSIO_LABEL,
+ BWRITERSIO_DCL,
BWRITERSIO_POW,
BWRITERSIO_CRS,
BWRITERSIO_SGN,
@@ -513,6 +518,10 @@ typedef enum _BWRITERSHADER_PARAM_SRCMOD_TYPE {
#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)
+typedef enum _BWRITERDECLUSAGE {
+ BWRITERDECLUSAGE_POSITION,
+} BWRITERDECLUSAGE;
+
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 d5473bc..968766a 100644
--- a/dlls/d3dx9_36/tests/asm.c
+++ b/dlls/d3dx9_36/tests/asm.c
@@ -1023,11 +1023,11 @@ static void vs_3_0_test(void) {
"dcl_2d s0\n",
{0xfffe0300, 0x0200001f, 0x90000000, 0xa00f0800, 0x0000ffff}
},*/
-/* {*/ /* shader 2 */
-/* "vs_3_0\n"
+ { /* shader 2 */
+ "vs_3_0\n"
"dcl_position o0\n",
{0xfffe0300, 0x0200001f, 0x80000000, 0xe00f0000, 0x0000ffff}
- },*/
+ },
/* {*/ /* shader 3 */
/* "vs_3_0\n"
"dcl_texcoord12 o11\n",
--
1.6.4.4
More information about the wine-patches
mailing list