[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(&reg, 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, &reg);
+                            }
+                    | INSTR_DCL dclusage REG_OUTPUT writemask
+                            {
+                                struct shader_reg reg;
+                                TRACE("Output reg declaration\n");
+                                ZeroMemory(&reg, 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, &reg);
+                            }
                     | 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