[4/4] d3dx9: Add sampler dcl instruction support to the shader assembler.

Matteo Bruni matteo.mystral at gmail.com
Thu May 13 10:25:30 CDT 2010


-------------- next part --------------
From 1fda7e7e2d49cb565e695276c9d7c37673824d6c Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Thu, 13 May 2010 17:21:59 +0200
Subject: d3dx9: Add sampler dcl instruction support to the shader assembler.

---
 dlls/d3dx9_36/asmparser.c        |    9 ++++++
 dlls/d3dx9_36/asmshader.l        |   10 ++++++
 dlls/d3dx9_36/asmshader.y        |   44 ++++++++++++++++++++++++++++
 dlls/d3dx9_36/asmutils.c         |   11 +++++++
 dlls/d3dx9_36/bytecodewriter.c   |   59 ++++++++++++++++++++++++++++++++++++++
 dlls/d3dx9_36/d3dx9_36_private.h |   13 ++++++++-
 dlls/d3dx9_36/tests/asm.c        |   10 ++----
 7 files changed, 148 insertions(+), 8 deletions(-)

diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c
index bee92f6..6d0d31f 100644
--- a/dlls/d3dx9_36/asmparser.c
+++ b/dlls/d3dx9_36/asmparser.c
@@ -60,6 +60,14 @@ static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num,
     }
 }
 
+static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype, DWORD regnum, unsigned int line_no) {
+    if(!This->shader) return;
+    if(!record_sampler(This->shader, samptype, regnum)) {
+        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,
@@ -159,6 +167,7 @@ static const struct asmparser_backend parser_vs_3 = {
 
     asmparser_dcl_output,
     asmparser_dcl_input,
+    asmparser_dcl_sampler,
 
     asmparser_end,
 
diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l
index b7835a8..9486b53 100644
--- a/dlls/d3dx9_36/asmshader.l
+++ b/dlls/d3dx9_36/asmshader.l
@@ -81,6 +81,11 @@ DCL_FOG                 _fog[0-9]*
 DCL_DEPTH               _depth[0-9]*
 DCL_SAMPLE              _sample[0-9]*
 
+DCL_SAMPLER1D           _1d
+DCL_SAMPLER2D           _2d
+DCL_SAMPLERCUBE         _cube
+DCL_SAMPLERVOLUME       _volume
+
 PREPROCESSORDIRECTIVE   #[^\n]*\n
 
 /* Comments */
@@ -400,6 +405,11 @@ ps_3_0                  {return VER_PS30;       }
                             return USAGE_SAMPLE;
                         }
 
+{DCL_SAMPLER1D}         { return SAMPTYPE_1D;       }
+{DCL_SAMPLER2D}         { return SAMPTYPE_2D;       }
+{DCL_SAMPLERCUBE}       { return SAMPTYPE_CUBE;     }
+{DCL_SAMPLERVOLUME}     { return SAMPTYPE_VOLUME;   }
+
 {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 ca4d24c..a6ab57e 100644
--- a/dlls/d3dx9_36/asmshader.y
+++ b/dlls/d3dx9_36/asmshader.y
@@ -84,6 +84,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
         DWORD           dclusage;
         unsigned int    regnum;
     } declaration;
+    BWRITERSAMPLER_TEXTURE_TYPE samplertype;
     struct rel_reg      rel_reg;
     struct src_regs     sregs;
 }
@@ -198,6 +199,12 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
 %token SMOD_ABS
 %token SMOD_NOT
 
+/* Sampler types */
+%token SAMPTYPE_1D
+%token SAMPTYPE_2D
+%token SAMPTYPE_CUBE
+%token SAMPTYPE_VOLUME
+
 /* Usage declaration tokens */
 %token <regnum> USAGE_POSITION
 %token <regnum> USAGE_BLENDWEIGHT
@@ -232,6 +239,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
 %type <modshift> omodifier
 %type <comptype> comp
 %type <declaration> dclusage
+%type <samplertype> sampdcl
 %type <rel_reg> rel_reg
 %type <reg> predicate
 %type <immval> immsum
@@ -546,6 +554,25 @@ instruction:          INSTR_ADD omods dreg ',' sregs
                                 reg.writemask = $4;
                                 asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, &reg);
                             }
+                    | INSTR_DCL sampdcl REG_SAMPLER
+                            {
+                                TRACE("Sampler declared\n");
+                                asm_ctx.funcs->dcl_sampler(&asm_ctx, $2, $3, asm_ctx.line_no);
+                            }
+                    | INSTR_DCL sampdcl REG_INPUT
+                            {
+                                TRACE("Error rule: sampler decl of input reg\n");
+                                asmparser_message(&asm_ctx, "Line %u: Sampler declarations of input regs is not valid\n",
+                                                  asm_ctx.line_no);
+                                set_parse_status(&asm_ctx, PARSE_WARN);
+                            }
+                    | INSTR_DCL sampdcl REG_OUTPUT
+                            {
+                                TRACE("Error rule: sampler decl of output reg\n");
+                                asmparser_message(&asm_ctx, "Line %u: Sampler declarations of output regs is not valid\n",
+                                                  asm_ctx.line_no);
+                                set_parse_status(&asm_ctx, PARSE_WARN);
+                            }
                     | INSTR_REP sregs
                             {
                                 TRACE("REP\n");
@@ -1196,6 +1223,23 @@ dclusage:             USAGE_POSITION
                             $$.dclusage = BWRITERDECLUSAGE_SAMPLE;
                         }
 
+sampdcl:              SAMPTYPE_1D
+                        {
+                            $$ = BWRITERSTT_1D;
+                        }
+                    | SAMPTYPE_2D
+                        {
+                            $$ = BWRITERSTT_2D;
+                        }
+                    | SAMPTYPE_CUBE
+                        {
+                            $$ = BWRITERSTT_CUBE;
+                        }
+                    | SAMPTYPE_VOLUME
+                        {
+                            $$ = BWRITERSTT_VOLUME;
+                        }
+
 predicate:            '(' REG_PREDICATE swizzle ')'
                         {
                             $$.type = BWRITERSPR_PREDICATE;
diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c
index c5098ca..c34f5f5 100644
--- a/dlls/d3dx9_36/asmutils.c
+++ b/dlls/d3dx9_36/asmutils.c
@@ -105,6 +105,17 @@ DWORD d3d9_comparetype(DWORD asmshader_comparetype) {
     }
 }
 
+DWORD d3d9_sampler(DWORD bwriter_sampler) {
+    if(bwriter_sampler == BWRITERSTT_UNKNOWN)   return D3DSTT_UNKNOWN;
+    if(bwriter_sampler == BWRITERSTT_1D)        return D3DSTT_1D;
+    if(bwriter_sampler == BWRITERSTT_2D)        return D3DSTT_2D;
+    if(bwriter_sampler == BWRITERSTT_CUBE)      return D3DSTT_CUBE;
+    if(bwriter_sampler == BWRITERSTT_VOLUME)    return D3DSTT_VOLUME;
+    FIXME("Unexpected BWRITERSAMPLER_TEXTURE_TYPE type %u\n", bwriter_sampler);
+
+    return 0;
+}
+
 DWORD d3d9_register(DWORD bwriter_register) {
     if(bwriter_register == BWRITERSPR_TEMP)         return D3DSPR_TEMP;
     if(bwriter_register == BWRITERSPR_INPUT)        return D3DSPR_INPUT;
diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c
index 4d62465..82a3655 100644
--- a/dlls/d3dx9_36/bytecodewriter.c
+++ b/dlls/d3dx9_36/bytecodewriter.c
@@ -151,6 +151,44 @@ BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_
     return TRUE;
 }
 
+BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD regnum) {
+    unsigned int i;
+
+    if(!shader) return FALSE;
+
+    if(shader->num_samplers == 0) {
+        shader->samplers = asm_alloc(sizeof(*shader->samplers));
+        if(!shader->samplers) {
+            ERR("Error allocating samplers array\n");
+            return FALSE;
+        }
+    } else {
+        struct samplerdecl *newarray;
+
+        for(i = 0; i < shader->num_samplers; i++) {
+            if(shader->samplers[i].regnum == regnum) {
+                WARN("Sampler %u already declared\n", regnum);
+                /* This is not an error as far as the assembler is concerned.
+                 * Direct3D might refuse to load the compiled shader though
+                 */
+            }
+        }
+
+        newarray = asm_realloc(shader->samplers,
+                               sizeof(*shader->samplers) * (shader->num_samplers + 1));
+        if(!newarray) {
+            ERR("Error reallocating samplers array\n");
+            return FALSE;
+        }
+        shader->samplers = newarray;
+    }
+
+    shader->samplers[shader->num_samplers].type = samptype;
+    shader->samplers[shader->num_samplers].regnum = regnum;
+    shader->num_samplers++;
+    return TRUE;
+}
+
 
 /* shader bytecode buffer manipulation functions.
  * allocate_buffer creates a new buffer structure, put_dword adds a new
@@ -280,12 +318,33 @@ static void sm_2_opcode(struct bc_writer *This,
     put_dword(buffer,token);
 }
 
+static void write_samplers(const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
+    DWORD i;
+    DWORD instr_dcl = D3DSIO_DCL | (2 << D3DSI_INSTLENGTH_SHIFT);
+    DWORD token;
+    const DWORD reg = (1<<31) |
+                      ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
+                      ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
+                      D3DSP_WRITEMASK_ALL;
+
+    for(i = 0; i < shader->num_samplers; i++) {
+        /* Write the DCL instruction */
+        put_dword(buffer, instr_dcl);
+        token = (1<<31);
+        /* Already shifted */
+        token |= (d3d9_sampler(shader->samplers[i].type)) & D3DSP_TEXTURETYPE_MASK;
+        put_dword(buffer, token);
+        put_dword(buffer, reg | (shader->samplers[i].regnum & D3DSP_REGNUM_MASK));
+    }
+}
+
 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->inputs, shader->num_inputs, D3DSPR_INPUT);
     write_declarations(buffer, TRUE, shader->outputs, shader->num_outputs, D3DSPR_OUTPUT);
+    write_samplers(shader, buffer);
     return;
 }
 
diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index 344bdbf..a102e65 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -179,7 +179,6 @@ struct declaration {
 struct samplerdecl {
     DWORD                   type;
     DWORD                   regnum;
-    unsigned int            line_no; /* for error messages */
 };
 
 #define INSTRARRAY_INITIAL_SIZE 8
@@ -257,6 +256,8 @@ struct asmparser_backend {
                        const struct shader_reg *reg);
     void (*dcl_input)(struct asm_parser *This, DWORD usage, DWORD num,
                       const struct shader_reg *reg);
+    void (*dcl_sampler)(struct asm_parser *This, DWORD samptype, DWORD regnum,
+                        unsigned int line_no);
 
     void (*end)(struct asm_parser *This);
 
@@ -268,6 +269,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);
+BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD regnum);
 
 #define MESSAGEBUFFER_INITIAL_SIZE 256
 
@@ -366,6 +368,7 @@ DWORD d3d9_writemask(DWORD bwriter_writemask);
 DWORD d3d9_srcmod(DWORD bwriter_srcmod);
 DWORD d3d9_dstmod(DWORD bwriter_mod);
 DWORD d3d9_comparetype(DWORD bwriter_comparetype);
+DWORD d3d9_sampler(DWORD bwriter_sampler);
 DWORD d3d9_register(DWORD bwriter_register);
 DWORD d3d9_opcode(DWORD bwriter_opcode);
 
@@ -476,6 +479,14 @@ typedef enum _BWRITERSHADER_PARAM_DSTMOD_TYPE {
     BWRITERSPDM_MSAMPCENTROID = 4,
 } BWRITERSHADER_PARAM_DSTMOD_TYPE;
 
+typedef enum _BWRITERSAMPLER_TEXTURE_TYPE {
+    BWRITERSTT_UNKNOWN = 0,
+    BWRITERSTT_1D = 1,
+    BWRITERSTT_2D = 2,
+    BWRITERSTT_CUBE = 3,
+    BWRITERSTT_VOLUME = 4,
+} BWRITERSAMPLER_TEXTURE_TYPE;
+
 typedef enum _BWRITERSHADER_PARAM_SRCMOD_TYPE {
     BWRITERSPSM_NONE = 0,
     BWRITERSPSM_NEG,
diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c
index dd51a95..21adb81 100644
--- a/dlls/d3dx9_36/tests/asm.c
+++ b/dlls/d3dx9_36/tests/asm.c
@@ -1008,21 +1008,17 @@ static void ps_2_x_test(void) {
 }
 
 static void vs_3_0_test(void) {
-    /* FIXME: Some tests are temporarily commented out, because the
-       current implementation doesn't support the entire vs_3_0 syntax
-       and it is not trivial to remove todo_wine only from
-       a subset of the tests here */
     struct shader_test tests[] = {
         {   /* shader 0 */
             "vs_3_0\n"
             "mov r0, c0\n",
             {0xfffe0300, 0x02000001, 0x800f0000, 0xa0e40000, 0x0000ffff}
         },
-/*      {*/ /* shader 1 */
-/*          "vs_3_0\n"
+        {   /* shader 1 */
+            "vs_3_0\n"
             "dcl_2d s0\n",
             {0xfffe0300, 0x0200001f, 0x90000000, 0xa00f0800, 0x0000ffff}
-        },*/
+        },
         {   /* shader 2 */
             "vs_3_0\n"
             "dcl_position o0\n",
-- 
1.6.4.4


More information about the wine-patches mailing list