[9/18] d3dx9: Shader assembler VS 1.X support

Matteo Bruni matteo.mystral at gmail.com
Sun Aug 16 12:52:41 CDT 2009


-------------- next part --------------
From eed13bf147915f8b2917c5d778846182046e0515 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Sun, 16 Aug 2009 01:02:16 +0200
Subject: d3dx9: Shader assembler VS 1.X support

---
 dlls/d3dx9_36/asmparser.c      |  109 ++++++++++++++++++++++++++
 dlls/d3dx9_36/asmshader.y      |    4 +-
 dlls/d3dx9_36/bytecodewriter.c |  167 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 276 insertions(+), 4 deletions(-)

diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c
index c268a0a..2560c0b 100644
--- a/dlls/d3dx9_36/asmparser.c
+++ b/dlls/d3dx9_36/asmparser.c
@@ -311,6 +311,47 @@ static BOOL check_reg_type(const struct shader_reg *reg,
     return FALSE;
 }
 
+/* Native compiler doesn't make separate checks for src and dst registers */
+struct allowed_reg_type vs_1_reg_allowed[] = {
+    { BWRITERSPR_TEMP,     12 },
+    { BWRITERSPR_INPUT,    16 },
+    { BWRITERSPR_CONST,   ~0U },
+    { BWRITERSPR_ADDR,      1 },
+    { BWRITERSPR_RASTOUT,   3 }, /* oPos, oFog and oPts */
+    { BWRITERSPR_ATTROUT,   2 },
+    { BWRITERSPR_TEXCRDOUT, 8 },
+    { ~0U, 0 } /* End tag */
+};
+
+/* struct instruction *asmparser_srcreg
+ *
+ * Records a source register in the instruction and does shader version
+ * specific checks and modifications on it
+ *
+ * Parameters:
+ *  This: Shader parser instance
+ *  instr: instruction to store the register in
+ *  num: Number of source register
+ *  src: Pointer to source the register structure. The caller can free
+ *  it afterwards
+ */
+static void asmparser_srcreg_vs_1(struct asm_parser *This,
+                                  struct instruction *instr, int num,
+                                  const struct shader_reg *src) {
+    struct shader_reg reg;
+
+    if(!check_reg_type(src, vs_1_reg_allowed)) {
+        asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
+                          This->line_no,
+                          debug_print_srcreg(src, ST_VERTEX));
+        set_parse_status(This, PARSE_ERR);
+    }
+    check_legacy_srcmod(This, src->srcmod);
+    check_abs_srcmod(This, src->srcmod);
+    reg = map_oldvs_register(src);
+    memcpy(&instr->src[num], &reg, sizeof(reg));
+}
+
 struct allowed_reg_type vs_2_reg_allowed[] = {
     { BWRITERSPR_TEMP,      12 },
     { BWRITERSPR_INPUT,     16 },
@@ -466,6 +507,22 @@ static void asmparser_srcreg_ps_3(struct asm_parser *This,
     memcpy(&instr->src[num], src, sizeof(*src));
 }
 
+static void asmparser_dstreg_vs_1(struct asm_parser *This,
+                                  struct instruction *instr,
+                                  const struct shader_reg *dst) {
+    struct shader_reg reg;
+
+    if(!check_reg_type(dst, vs_1_reg_allowed)) {
+        asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\n",
+                          This->line_no,
+                          debug_print_dstreg(dst, ST_VERTEX));
+        set_parse_status(This, PARSE_ERR);
+    }
+    reg = map_oldvs_register(dst);
+    memcpy(&instr->dst, &reg, sizeof(reg));
+    instr->has_dst = TRUE;
+}
+
 static void asmparser_dstreg_vs_2(struct asm_parser *This,
                                   struct instruction *instr,
                                   const struct shader_reg *dst) {
@@ -564,6 +621,26 @@ static void asmparser_coissue_unsupported(struct asm_parser *This) {
     set_parse_status(This, PARSE_ERR);
 }
 
+static struct asmparser_backend parser_vs_1 = {
+    asmparser_constF,
+    asmparser_constI,
+    asmparser_constB,
+
+    asmparser_dstreg_vs_1,
+    asmparser_srcreg_vs_1,
+
+    asmparser_predicate_unsupported,
+    asmparser_coissue_unsupported,
+
+    asmparser_dcl_output,
+    asmparser_dcl_input,
+    asmparser_dcl_sampler,
+
+    asmparser_end,
+
+    asmparser_instr,
+};
+
 static struct asmparser_backend parser_vs_2 = {
     asmparser_constF,
     asmparser_constI,
@@ -695,6 +772,38 @@ static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
     record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL);
 }
 
+void create_vs10_parser(struct asm_parser *ret) {
+    TRACE_(parsed_shader)("vs_1_0\n");
+
+    ret->shader = asm_alloc(sizeof(*ret->shader));
+    if(!ret->shader) {
+        ERR("Failed to allocate memory for the shader\n");
+        set_parse_status(ret, PARSE_ERR);
+        return;
+    }
+
+    ret->shader->type = ST_VERTEX;
+    ret->shader->version = BWRITERVS_VERSION(1, 0);
+    ret->funcs = &parser_vs_1;
+    gen_oldvs_output(ret->shader);
+}
+
+void create_vs11_parser(struct asm_parser *ret) {
+    TRACE_(parsed_shader)("vs_1_1\n");
+
+    ret->shader = asm_alloc(sizeof(*ret->shader));
+    if(!ret->shader) {
+        ERR("Failed to allocate memory for the shader\n");
+        set_parse_status(ret, PARSE_ERR);
+        return;
+    }
+
+    ret->shader->type = ST_VERTEX;
+    ret->shader->version = BWRITERVS_VERSION(1, 1);
+    ret->funcs = &parser_vs_1;
+    gen_oldvs_output(ret->shader);
+}
+
 void create_vs20_parser(struct asm_parser *ret) {
     TRACE_(parsed_shader)("vs_2_0\n");
 
diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y
index 7e142ad..653d4e9 100644
--- a/dlls/d3dx9_36/asmshader.y
+++ b/dlls/d3dx9_36/asmshader.y
@@ -300,12 +300,12 @@ shader:               version_marker instructions
 version_marker:       VER_VS10
                         {
                             TRACE("Vertex shader 1.0\n");
-                            /* TODO: create the appropriate parser context */
+                            create_vs10_parser(ctx);
                         }
                     | VER_VS11
                         {
                             TRACE("Vertex shader 1.1\n");
-                            /* TODO: create the appropriate parser context */
+                            create_vs11_parser(ctx);
                         }
                     | VER_VS20
                         {
diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c
index a7d2322..1090bce 100644
--- a/dlls/d3dx9_36/bytecodewriter.c
+++ b/dlls/d3dx9_36/bytecodewriter.c
@@ -496,6 +496,31 @@ static HRESULT find_builtin_varyings(struct bc_writer *This, const struct bwrite
     return S_OK;
 }
 
+static void vs_1_x_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
+    HRESULT hr;
+
+    /* First check the constants and varyings, and complain if unsupported things are used */
+    if(shader->num_ci || shader->num_cb) {
+        WARN("Int and bool constants are not supported in shader model 1 shaders\n");
+        WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
+        This->state = E_INVALIDARG;
+        return;
+    }
+
+    hr = find_builtin_varyings(This, shader);
+    if(FAILED(hr)) {
+        This->state = hr;
+        return;
+    }
+
+    /* Declare the shader type and version */
+    put_dword(buffer, This->version);
+
+    write_declarations(buffer, FALSE, shader->inputs, shader->num_inputs, D3DSPR_INPUT);
+    write_constF(shader, buffer, FALSE);
+    return;
+}
+
 static void ps_legacy_header(struct bc_writer *This, const struct bwriter_shader *shader,
                              struct bytecode_buffer *buffer, DWORD texcoords,
                              BOOL has_instr_len) {
@@ -706,6 +731,83 @@ static void vs_12_dstreg(struct bc_writer *This, const struct shader_reg *reg,
     put_dword(buffer, token);
 }
 
+static void vs_1_x_srcreg(struct bc_writer *This, const struct shader_reg *reg,
+                          struct bytecode_buffer *buffer) {
+    DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
+    DWORD has_swizzle;
+    DWORD component ;
+
+    switch(reg->type) {
+        case BWRITERSPR_OUTPUT:
+            /* The output register component is stored as a writemask, since that is the form most
+             * commonly used. If we're reading from it, we've got a swizzle. If this swizzle selects
+             * a single component, map it to a writemask selecting this component, otherwise
+             * 0 does the job. If a component is needed to identify the register, an unconvertible
+             * swizzle is an error anyway
+             */
+            if(reg->swizzle == BWRITERVS_SWIZZLE_X) {
+                component = BWRITERSP_WRITEMASK_0;
+            } else if(reg->swizzle == BWRITERVS_SWIZZLE_Y) {
+                component = BWRITERSP_WRITEMASK_1;
+            } else if(reg->swizzle == BWRITERVS_SWIZZLE_Z) {
+                component = BWRITERSP_WRITEMASK_2;
+            } else if(reg->swizzle == BWRITERVS_SWIZZLE_W) {
+                component = BWRITERSP_WRITEMASK_3;
+            } else {
+                component = 0;
+            }
+            token |= vs_output(This, reg->regnum, component, &has_swizzle);
+            break;
+
+        case BWRITERSPR_RASTOUT:
+        case BWRITERSPR_ATTROUT:
+            /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
+             * but are unexpected. If we hit this path it might be due to an error.
+             */
+            FIXME("Unexpected register type %u\n", reg->type);
+            /* drop through */
+        case BWRITERSPR_INPUT:
+        case BWRITERSPR_TEMP:
+        case BWRITERSPR_CONST:
+            token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
+            token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
+            if(reg->rel_reg) {
+                if(reg->rel_reg->type != BWRITERSPR_ADDR ||
+                   reg->rel_reg->regnum != 0 ||
+                   reg->rel_reg->swizzle != BWRITERVS_SWIZZLE_X) {
+                    WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
+                    This->state = E_INVALIDARG;
+                    return;
+                }
+                token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
+            }
+            break;
+
+        case BWRITERSPR_ADDR:
+            /* This is only supported for relative addressing or as a mov dest reg */
+            WARN("D3DSPR_ADDR is not valid as an src reg\n");
+            This->state = E_INVALIDARG;
+            return;
+
+        default:
+            WARN("Invalid register type for 1.x vshader\n");
+            This->state = E_INVALIDARG;
+            return;
+    }
+
+    token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
+
+    if(reg->srcmod == BWRITERSPSM_DZ || reg->srcmod == BWRITERSPSM_DW ||
+       reg->srcmod == BWRITERSPSM_ABS || reg->srcmod == BWRITERSPSM_ABSNEG ||
+       reg->srcmod == BWRITERSPSM_NOT) {
+        WARN("Invalid source modifier %u for vs_1_x\n", reg->srcmod);
+        This->state = E_INVALIDARG;
+        return;
+    }
+    token |= d3d9_srcmod(reg->srcmod);
+    put_dword(buffer, token);
+}
+
 static void write_srcregs(struct bc_writer *This, const struct instruction *instr,
                           struct bytecode_buffer *buffer){
     unsigned int i;
@@ -778,6 +880,16 @@ static DWORD instrlen(const struct instruction *instr, unsigned int srcs, unsign
     return ret;
 }
 
+static void sm_1_x_opcode(struct bc_writer *This,
+                          const struct instruction *instr,
+                          DWORD token, struct bytecode_buffer *buffer) {
+    /* In sm_1_x instruction length isn't encoded */
+    if(instr->coissue){
+        token |= D3DSI_COISSUE;
+    }
+    put_dword(buffer,token);
+}
+
 static void instr_handler(struct bc_writer *This,
                           const struct instruction *instr,
                           struct bytecode_buffer *buffer) {
@@ -789,6 +901,47 @@ static void instr_handler(struct bc_writer *This,
     write_srcregs(This, instr, buffer);
 }
 
+struct instr_handler_table vs_1_x_handlers[] = {
+    {BWRITERSIO_ADD,            instr_handler},
+    {BWRITERSIO_NOP,            instr_handler},
+    {BWRITERSIO_MOV,            instr_handler},
+    {BWRITERSIO_SUB,            instr_handler},
+    {BWRITERSIO_MAD,            instr_handler},
+    {BWRITERSIO_MUL,            instr_handler},
+    {BWRITERSIO_RCP,            instr_handler},
+    {BWRITERSIO_RSQ,            instr_handler},
+    {BWRITERSIO_DP3,            instr_handler},
+    {BWRITERSIO_DP4,            instr_handler},
+    {BWRITERSIO_MIN,            instr_handler},
+    {BWRITERSIO_MAX,            instr_handler},
+    {BWRITERSIO_SLT,            instr_handler},
+    {BWRITERSIO_SGE,            instr_handler},
+    {BWRITERSIO_EXP,            instr_handler},
+    {BWRITERSIO_LOG,            instr_handler},
+    {BWRITERSIO_EXPP,           instr_handler},
+    {BWRITERSIO_LOGP,           instr_handler},
+    {BWRITERSIO_DST,            instr_handler},
+    {BWRITERSIO_FRC,            instr_handler},
+    {BWRITERSIO_M4x4,           instr_handler},
+    {BWRITERSIO_M4x3,           instr_handler},
+    {BWRITERSIO_M3x4,           instr_handler},
+    {BWRITERSIO_M3x3,           instr_handler},
+    {BWRITERSIO_M3x2,           instr_handler},
+    {BWRITERSIO_LIT,            instr_handler},
+
+    {BWRITERSIO_END,            NULL}, /* Sentinel value, it signals
+                                          the end of the list */
+};
+
+static struct bytecode_backend vs_1_x_backend = {
+    vs_1_x_header,
+    end,
+    vs_1_x_srcreg,
+    vs_12_dstreg,
+    sm_1_x_opcode,
+    vs_1_x_handlers
+};
+
 static void write_constB(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
     DWORD i;
     DWORD instr_def = D3DSIO_DEFB;
@@ -1635,6 +1788,16 @@ static struct bytecode_backend ps_3_backend = {
     ps_3_handlers
 };
 
+static void init_vs10_dx9_writer(struct bc_writer *writer) {
+    TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
+    writer->funcs = &vs_1_x_backend;
+}
+
+static void init_vs11_dx9_writer(struct bc_writer *writer) {
+    TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
+    writer->funcs = &vs_1_x_backend;
+}
+
 static void init_vs20_dx9_writer(struct bc_writer *writer) {
     TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
     writer->funcs = &vs_2_0_backend;
@@ -1679,14 +1842,14 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
                 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion);
                 goto fail;
             }
-            /* TODO: Set the appropriate writer backend */
+            init_vs10_dx9_writer(ret);
             break;
         case BWRITERVS_VERSION(1, 1):
             if(dxversion != 9) {
                 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion);
                 goto fail;
             }
-            /* TODO: Set the appropriate writer backend */
+            init_vs11_dx9_writer(ret);
             break;
         case BWRITERVS_VERSION(2, 0):
             if(dxversion != 9) {
-- 
1.6.3.3


More information about the wine-patches mailing list