[PATCH 1/3] wined3d: Read complete shader instructions at a time.

Henri Verbeet hverbeet at codeweavers.com
Tue Sep 4 13:15:08 CDT 2012


---
 dlls/wined3d/shader.c          |  235 ++++++++++++----------------------------
 dlls/wined3d/shader_sm1.c      |  126 +++++++++++++++------
 dlls/wined3d/shader_sm4.c      |   99 ++++++++++--------
 dlls/wined3d/wined3d_private.h |   26 ++---
 4 files changed, 224 insertions(+), 262 deletions(-)

diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 8b9b81c..d19b575 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -483,69 +483,57 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
         struct wined3d_shader_instruction ins;
         const char *comment;
         UINT comment_size;
-        UINT param_size;
 
         /* Skip comments. */
         fe->shader_read_comment(&ptr, &comment, &comment_size);
         if (comment) continue;
 
         /* Fetch opcode. */
-        fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
+        fe->shader_read_instruction(fe_data, &ptr, &ins);
 
         /* Unhandled opcode, and its parameters. */
         if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
         {
             TRACE("Skipping unrecognized instruction.\n");
-            ptr += param_size;
             continue;
         }
 
         /* Handle declarations. */
         if (ins.handler_idx == WINED3DSIH_DCL)
         {
-            struct wined3d_shader_semantic semantic;
-
-            fe->shader_read_semantic(&ptr, &semantic);
-
-            switch (semantic.reg.reg.type)
+            switch (ins.semantic.reg.reg.type)
             {
                 /* Mark input registers used. */
                 case WINED3DSPR_INPUT:
-                    reg_maps->input_registers |= 1 << semantic.reg.reg.idx;
-                    shader_signature_from_semantic(&input_signature[semantic.reg.reg.idx], &semantic);
+                    reg_maps->input_registers |= 1 << ins.semantic.reg.reg.idx;
+                    shader_signature_from_semantic(&input_signature[ins.semantic.reg.reg.idx], &ins.semantic);
                     break;
 
                 /* Vertex shader: mark 3.0 output registers used, save token. */
                 case WINED3DSPR_OUTPUT:
-                    reg_maps->output_registers |= 1 << semantic.reg.reg.idx;
-                    shader_signature_from_semantic(&output_signature[semantic.reg.reg.idx], &semantic);
-                    if (semantic.usage == WINED3D_DECL_USAGE_FOG)
+                    reg_maps->output_registers |= 1 << ins.semantic.reg.reg.idx;
+                    shader_signature_from_semantic(&output_signature[ins.semantic.reg.reg.idx], &ins.semantic);
+                    if (ins.semantic.usage == WINED3D_DECL_USAGE_FOG)
                         reg_maps->fog = 1;
                     break;
 
                 /* Save sampler usage token. */
                 case WINED3DSPR_SAMPLER:
-                    reg_maps->sampler_type[semantic.reg.reg.idx] = semantic.sampler_type;
+                    reg_maps->sampler_type[ins.semantic.reg.reg.idx] = ins.semantic.sampler_type;
                     break;
 
                 default:
-                    TRACE("Not recording DCL register type %#x.\n", semantic.reg.reg.type);
+                    TRACE("Not recording DCL register type %#x.\n", ins.semantic.reg.reg.type);
                     break;
             }
         }
         else if (ins.handler_idx == WINED3DSIH_DEF)
         {
-            struct wined3d_shader_src_param rel_addr;
-            struct wined3d_shader_dst_param dst;
-
             struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
             if (!lconst) return E_OUTOFMEMORY;
 
-            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-            lconst->idx = dst.reg.idx;
-
-            memcpy(lconst->value, ptr, 4 * sizeof(DWORD));
-            ptr += 4;
+            lconst->idx = ins.dst[0].reg.idx;
+            memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD));
 
             /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
             if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
@@ -565,51 +553,36 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
         }
         else if (ins.handler_idx == WINED3DSIH_DEFI)
         {
-            struct wined3d_shader_src_param rel_addr;
-            struct wined3d_shader_dst_param dst;
-
             struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
             if (!lconst) return E_OUTOFMEMORY;
 
-            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-            lconst->idx = dst.reg.idx;
-
-            memcpy(lconst->value, ptr, 4 * sizeof(DWORD));
-            ptr += 4;
+            lconst->idx = ins.dst[0].reg.idx;
+            memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD));
 
             list_add_head(&shader->constantsI, &lconst->entry);
-            reg_maps->local_int_consts |= (1 << dst.reg.idx);
+            reg_maps->local_int_consts |= (1 << lconst->idx);
         }
         else if (ins.handler_idx == WINED3DSIH_DEFB)
         {
-            struct wined3d_shader_src_param rel_addr;
-            struct wined3d_shader_dst_param dst;
-
             struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
             if (!lconst) return E_OUTOFMEMORY;
 
-            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-            lconst->idx = dst.reg.idx;
-
-            memcpy(lconst->value, ptr, sizeof(DWORD));
-            ++ptr;
+            lconst->idx = ins.dst[0].reg.idx;
+            memcpy(lconst->value, ins.src[0].reg.immconst_data, sizeof(DWORD));
 
             list_add_head(&shader->constantsB, &lconst->entry);
-            reg_maps->local_bool_consts |= (1 << dst.reg.idx);
+            reg_maps->local_bool_consts |= (1 << lconst->idx);
         }
         /* For subroutine prototypes. */
         else if (ins.handler_idx == WINED3DSIH_LABEL)
         {
-            struct wined3d_shader_src_param src, rel_addr;
-
-            fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr);
-            reg_maps->labels |= 1 << src.reg.idx;
+            reg_maps->labels |= 1 << ins.src[0].reg.idx;
         }
         /* Set texture, address, temporary registers. */
         else
         {
             BOOL color0_mov = FALSE;
-            unsigned int i, limit;
+            unsigned int i;
 
             /* This will loop over all the registers and try to
              * make a bitmask of the ones we're interested in.
@@ -619,21 +592,16 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
              * they are initialized (required by spec). */
             for (i = 0; i < ins.dst_count; ++i)
             {
-                struct wined3d_shader_src_param dst_rel_addr;
-                struct wined3d_shader_dst_param dst_param;
-
-                fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr);
-
-                shader_record_register_usage(shader, reg_maps, &dst_param.reg, shader_version.type);
+                shader_record_register_usage(shader, reg_maps, &ins.dst[i].reg, shader_version.type);
 
                 /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
                  * is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
                  * shaders because TECRDOUT isn't used in them, but future register types might cause issues */
                 if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX && shader_version.major < 3)
                 {
-                    UINT idx = dst_param.reg.idx;
+                    UINT idx = ins.dst[i].reg.idx;
 
-                    switch (dst_param.reg.type)
+                    switch (ins.dst[i].reg.type)
                     {
                         case WINED3DSPR_RASTOUT:
                             switch (idx)
@@ -664,29 +632,29 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                                 idx += 8;
                                 if (reg_maps->output_registers & (1 << idx))
                                 {
-                                    output_signature[idx].mask |= dst_param.write_mask;
+                                    output_signature[idx].mask |= ins.dst[i].write_mask;
                                 }
                                 else
                                 {
                                     reg_maps->output_registers |= 1 << idx;
                                     shader_signature_from_usage(&output_signature[idx],
-                                            WINED3D_DECL_USAGE_COLOR, idx - 8, idx, dst_param.write_mask);
+                                            WINED3D_DECL_USAGE_COLOR, idx - 8, idx, ins.dst[i].write_mask);
                                 }
                             }
                             break;
 
                         case WINED3DSPR_TEXCRDOUT:
 
-                            reg_maps->texcoord_mask[idx] |= dst_param.write_mask;
+                            reg_maps->texcoord_mask[idx] |= ins.dst[i].write_mask;
                             if (reg_maps->output_registers & (1 << idx))
                             {
-                                output_signature[idx].mask |= dst_param.write_mask;
+                                output_signature[idx].mask |= ins.dst[i].write_mask;
                             }
                             else
                             {
                                 reg_maps->output_registers |= 1 << idx;
                                 shader_signature_from_usage(&output_signature[idx],
-                                        WINED3D_DECL_USAGE_TEXCOORD, idx, idx, dst_param.write_mask);
+                                        WINED3D_DECL_USAGE_TEXCOORD, idx, idx, ins.dst[i].write_mask);
                             }
                             break;
 
@@ -697,7 +665,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
 
                 if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
                 {
-                    if (dst_param.reg.type == WINED3DSPR_COLOROUT && !dst_param.reg.idx)
+                    if (ins.dst[i].reg.type == WINED3DSPR_COLOROUT && !ins.dst[i].reg.idx)
                     {
                         /* Many 2.0 and 3.0 pixel shaders end with a MOV from a temp register to
                          * COLOROUT 0. If we know this in advance, the ARB shader backend can skip
@@ -708,7 +676,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                          * COLOROUT 0 is overwritten partially later, the marker is dropped again. */
                         shader->u.ps.color0_mov = FALSE;
                         if (ins.handler_idx == WINED3DSIH_MOV
-                                && dst_param.write_mask == WINED3DSP_WRITEMASK_ALL)
+                                && ins.dst[i].write_mask == WINED3DSP_WRITEMASK_ALL)
                         {
                             /* Used later when the source register is read. */
                             color0_mov = TRUE;
@@ -717,8 +685,8 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                     /* Also drop the MOV marker if the source register is overwritten prior to the shader
                      * end
                      */
-                    else if (dst_param.reg.type == WINED3DSPR_TEMP
-                            && dst_param.reg.idx == shader->u.ps.color0_reg)
+                    else if (ins.dst[i].reg.type == WINED3DSPR_TEMP
+                            && ins.dst[i].reg.idx == shader->u.ps.color0_reg)
                     {
                         shader->u.ps.color0_mov = FALSE;
                     }
@@ -739,7 +707,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                             || ins.handler_idx == WINED3DSIH_TEXREG2RGB))
                 {
                     /* Fake sampler usage, only set reserved bit and type. */
-                    DWORD sampler_code = dst_param.reg.idx;
+                    DWORD sampler_code = ins.dst[i].reg.idx;
 
                     TRACE("Setting fake 2D sampler for 1.x pixelshader.\n");
                     reg_maps->sampler_type[sampler_code] = WINED3DSTT_2D;
@@ -748,16 +716,16 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                     if (ins.handler_idx == WINED3DSIH_TEXBEM
                             || ins.handler_idx == WINED3DSIH_TEXBEML)
                     {
-                        reg_maps->bumpmat |= 1 << dst_param.reg.idx;
+                        reg_maps->bumpmat |= 1 << ins.dst[i].reg.idx;
                         if (ins.handler_idx == WINED3DSIH_TEXBEML)
                         {
-                            reg_maps->luminanceparams |= 1 << dst_param.reg.idx;
+                            reg_maps->luminanceparams |= 1 << ins.dst[i].reg.idx;
                         }
                     }
                 }
                 else if (ins.handler_idx == WINED3DSIH_BEM)
                 {
-                    reg_maps->bumpmat |= 1 << dst_param.reg.idx;
+                    reg_maps->bumpmat |= 1 << ins.dst[i].reg.idx;
                 }
             }
 
@@ -781,30 +749,29 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                     || ins.handler_idx == WINED3DSIH_ENDREP)
                 --cur_loop_depth;
 
-            limit = ins.src_count + (ins.predicate ? 1 : 0);
-            for (i = 0; i < limit; ++i)
-            {
-                struct wined3d_shader_src_param src_param, src_rel_addr;
-                unsigned int count;
+            if (ins.predicate)
+                shader_record_register_usage(shader, reg_maps, &ins.predicate->reg, shader_version.type);
 
-                fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
-                count = get_instr_extra_regcount(ins.handler_idx, i);
+            for (i = 0; i < ins.src_count; ++i)
+            {
+                unsigned int count = get_instr_extra_regcount(ins.handler_idx, i);
+                struct wined3d_shader_register reg = ins.src[i].reg;
 
-                shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type);
+                shader_record_register_usage(shader, reg_maps, &ins.src[i].reg, shader_version.type);
                 while (count)
                 {
-                    ++src_param.reg.idx;
-                    shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type);
+                    ++reg.idx;
+                    shader_record_register_usage(shader, reg_maps, &reg, shader_version.type);
                     --count;
                 }
 
                 if (color0_mov)
                 {
-                    if (src_param.reg.type == WINED3DSPR_TEMP
-                            && src_param.swizzle == WINED3DSP_NOSWIZZLE)
+                    if (ins.src[i].reg.type == WINED3DSPR_TEMP
+                            && ins.src[i].swizzle == WINED3DSP_NOSWIZZLE)
                     {
                         shader->u.ps.color0_mov = TRUE;
-                        shader->u.ps.color0_reg = src_param.reg.idx;
+                        shader->u.ps.color0_reg = ins.src[i].reg.idx;
                     }
                 }
             }
@@ -1161,17 +1128,12 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_sh
     struct wined3d_device *device = shader->device;
     const struct wined3d_shader_frontend *fe = shader->frontend;
     void *fe_data = shader->frontend_data;
-    struct wined3d_shader_src_param dst_rel_addr[2];
-    struct wined3d_shader_src_param src_rel_addr[4];
-    struct wined3d_shader_dst_param dst_param[2];
-    struct wined3d_shader_src_param src_param[4];
     struct wined3d_shader_version shader_version;
     struct wined3d_shader_loop_state loop_state;
     struct wined3d_shader_instruction ins;
     struct wined3d_shader_tex_mx tex_mx;
     struct wined3d_shader_context ctx;
     const DWORD *ptr = byte_code;
-    DWORD i;
 
     /* Initialize current parsing state. */
     tex_mx.current_row = 0;
@@ -1185,10 +1147,7 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_sh
     ctx.tex_mx = &tex_mx;
     ctx.loop_state = &loop_state;
     ctx.backend_data = backend_ctx;
-
     ins.ctx = &ctx;
-    ins.dst = dst_param;
-    ins.src = src_param;
 
     fe->shader_read_header(fe_data, &ptr, &shader_version);
 
@@ -1196,20 +1155,18 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_sh
     {
         const char *comment;
         UINT comment_size;
-        UINT param_size;
 
         /* Skip comment tokens. */
         fe->shader_read_comment(&ptr, &comment, &comment_size);
         if (comment) continue;
 
         /* Read opcode. */
-        fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
+        fe->shader_read_instruction(fe_data, &ptr, &ins);
 
         /* Unknown opcode and its parameters. */
         if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
         {
             TRACE("Skipping unrecognized instruction.\n");
-            ptr += param_size;
             continue;
         }
 
@@ -1220,29 +1177,10 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_sh
                 || ins.handler_idx == WINED3DSIH_DEFI
                 || ins.handler_idx == WINED3DSIH_DEFB
                 || ins.handler_idx == WINED3DSIH_PHASE)
-        {
-            ptr += param_size;
             continue;
-        }
 
-        /* Destination tokens */
-        for (i = 0; i < ins.dst_count; ++i)
-        {
-            fe->shader_read_dst_param(fe_data, &ptr, &dst_param[i], &dst_rel_addr[i]);
-        }
-
-        /* Predication token */
         if (ins.predicate)
-        {
             FIXME("Predicates not implemented.\n");
-            ins.predicate = *ptr++;
-        }
-
-        /* Other source tokens */
-        for (i = 0; i < ins.src_count; ++i)
-        {
-            fe->shader_read_src_param(fe_data, &ptr, &src_param[i], &src_rel_addr[i]);
-        }
 
         /* Call appropriate function for output target */
         device->shader_backend->shader_handle_instruction(&ins);
@@ -1311,7 +1249,6 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe
         struct wined3d_shader_instruction ins;
         const char *comment;
         UINT comment_size;
-        UINT param_size;
 
         /* comment */
         fe->shader_read_comment(&ptr, &comment, &comment_size);
@@ -1341,82 +1278,46 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe
             continue;
         }
 
-        fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
+        fe->shader_read_instruction(fe_data, &ptr, &ins);
         if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
         {
             TRACE("Skipping unrecognized instruction.\n");
-            ptr += param_size;
             continue;
         }
 
         if (ins.handler_idx == WINED3DSIH_DCL)
         {
-            struct wined3d_shader_semantic semantic;
-
-            fe->shader_read_semantic(&ptr, &semantic);
-
-            shader_dump_decl_usage(&semantic, &shader_version);
-            shader_dump_ins_modifiers(&semantic.reg);
+            shader_dump_decl_usage(&ins.semantic, &shader_version);
+            shader_dump_ins_modifiers(&ins.semantic.reg);
             TRACE(" ");
-            shader_dump_dst_param(&semantic.reg, &shader_version);
+            shader_dump_dst_param(&ins.semantic.reg, &shader_version);
         }
         else if (ins.handler_idx == WINED3DSIH_DEF)
         {
-            struct wined3d_shader_src_param rel_addr;
-            struct wined3d_shader_dst_param dst;
-
-            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-
-            TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(dst.reg.type, dst.reg.idx),
-                    *(const float *)(ptr),
-                    *(const float *)(ptr + 1),
-                    *(const float *)(ptr + 2),
-                    *(const float *)(ptr + 3));
-            ptr += 4;
+            TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(ins.dst[0].reg.type, ins.dst[0].reg.idx),
+                    *(const float *)&ins.src[0].reg.immconst_data[0],
+                    *(const float *)&ins.src[0].reg.immconst_data[1],
+                    *(const float *)&ins.src[0].reg.immconst_data[2],
+                    *(const float *)&ins.src[0].reg.immconst_data[3]);
         }
         else if (ins.handler_idx == WINED3DSIH_DEFI)
         {
-            struct wined3d_shader_src_param rel_addr;
-            struct wined3d_shader_dst_param dst;
-
-            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-
-            TRACE("defi i%u = %d, %d, %d, %d", dst.reg.idx,
-                    *(ptr),
-                    *(ptr + 1),
-                    *(ptr + 2),
-                    *(ptr + 3));
-            ptr += 4;
+            TRACE("defi i%u = %d, %d, %d, %d", ins.dst[0].reg.idx,
+                    ins.src[0].reg.immconst_data[0],
+                    ins.src[0].reg.immconst_data[1],
+                    ins.src[0].reg.immconst_data[2],
+                    ins.src[0].reg.immconst_data[3]);
         }
         else if (ins.handler_idx == WINED3DSIH_DEFB)
         {
-            struct wined3d_shader_src_param rel_addr;
-            struct wined3d_shader_dst_param dst;
-
-            fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-
-            TRACE("defb b%u = %s", dst.reg.idx, *ptr ? "true" : "false");
-            ++ptr;
+            TRACE("defb b%u = %s", ins.dst[0].reg.idx, ins.src[0].reg.immconst_data[0] ? "true" : "false");
         }
         else
         {
-            struct wined3d_shader_src_param dst_rel_addr[2];
-            struct wined3d_shader_src_param src_rel_addr;
-            struct wined3d_shader_dst_param dst_param[2];
-            struct wined3d_shader_src_param src_param;
-
-            for (i = 0; i < ins.dst_count; ++i)
-            {
-                fe->shader_read_dst_param(fe_data, &ptr, &dst_param[i], &dst_rel_addr[i]);
-            }
-
-            /* Print out predication source token first - it follows
-             * the destination token. */
             if (ins.predicate)
             {
-                fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
                 TRACE("(");
-                shader_dump_src_param(&src_param, &shader_version);
+                shader_dump_src_param(ins.predicate, &shader_version);
                 TRACE(") ");
             }
 
@@ -1446,20 +1347,18 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe
                 TRACE("p");
             }
 
-            /* We already read the destination tokens, print them. */
             for (i = 0; i < ins.dst_count; ++i)
             {
-                shader_dump_ins_modifiers(&dst_param[i]);
+                shader_dump_ins_modifiers(&ins.dst[i]);
                 TRACE(!i ? " " : ", ");
-                shader_dump_dst_param(&dst_param[i], &shader_version);
+                shader_dump_dst_param(&ins.dst[i], &shader_version);
             }
 
             /* Other source tokens */
             for (i = ins.dst_count; i < (ins.dst_count + ins.src_count); ++i)
             {
-                fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
                 TRACE(!i ? " " : ", ");
-                shader_dump_src_param(&src_param, &shader_version);
+                shader_dump_src_param(&ins.src[i - ins.dst_count], &shader_version);
             }
         }
         TRACE("\n");
diff --git a/dlls/wined3d/shader_sm1.c b/dlls/wined3d/shader_sm1.c
index aa1da56..bba65dd 100644
--- a/dlls/wined3d/shader_sm1.c
+++ b/dlls/wined3d/shader_sm1.c
@@ -204,6 +204,13 @@ struct wined3d_sm1_data
 {
     struct wined3d_shader_version shader_version;
     const struct wined3d_sm1_opcode_info *opcode_table;
+
+    struct wined3d_shader_src_param src_rel_addr[4];
+    struct wined3d_shader_src_param pred_rel_addr;
+    struct wined3d_shader_src_param dst_rel_addr;
+    struct wined3d_shader_src_param src_param[4];
+    struct wined3d_shader_src_param pred_param;
+    struct wined3d_shader_dst_param dst_param;
 };
 
 /* This table is not order or position dependent. */
@@ -568,36 +575,9 @@ static void shader_sm1_read_header(void *data, const DWORD **ptr, struct wined3d
     *shader_version = priv->shader_version;
 }
 
-static void shader_sm1_read_opcode(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins,
-        UINT *param_size)
+static void shader_sm1_read_src_param(struct wined3d_sm1_data *priv, const DWORD **ptr,
+        struct wined3d_shader_src_param *src_param, struct wined3d_shader_src_param *src_rel_addr)
 {
-    struct wined3d_sm1_data *priv = data;
-    const struct wined3d_sm1_opcode_info *opcode_info;
-    DWORD opcode_token;
-
-    opcode_token = *(*ptr)++;
-    opcode_info = shader_get_opcode(priv, opcode_token);
-    if (!opcode_info)
-    {
-        FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
-        ins->handler_idx = WINED3DSIH_TABLE_SIZE;
-        *param_size = shader_skip_unrecognized(priv, *ptr);
-        return;
-    }
-
-    ins->handler_idx = opcode_info->handler_idx;
-    ins->flags = (opcode_token & WINED3D_OPCODESPECIFICCONTROL_MASK) >> WINED3D_OPCODESPECIFICCONTROL_SHIFT;
-    ins->coissue = opcode_token & WINED3DSI_COISSUE;
-    ins->predicate = opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED;
-    ins->dst_count = opcode_info->dst_count ? 1 : 0;
-    ins->src_count = opcode_info->param_count - opcode_info->dst_count;
-    *param_size = shader_skip_opcode(priv, opcode_info, opcode_token);
-}
-
-static void shader_sm1_read_src_param(void *data, const DWORD **ptr, struct wined3d_shader_src_param *src_param,
-        struct wined3d_shader_src_param *src_rel_addr)
-{
-    struct wined3d_sm1_data *priv = data;
     DWORD token, addr_token;
 
     *ptr += shader_get_param(priv, *ptr, &token, &addr_token);
@@ -612,10 +592,9 @@ static void shader_sm1_read_src_param(void *data, const DWORD **ptr, struct wine
     }
 }
 
-static void shader_sm1_read_dst_param(void *data, const DWORD **ptr, struct wined3d_shader_dst_param *dst_param,
-        struct wined3d_shader_src_param *dst_rel_addr)
+static void shader_sm1_read_dst_param(struct wined3d_sm1_data *priv, const DWORD **ptr,
+        struct wined3d_shader_dst_param *dst_param, struct wined3d_shader_src_param *dst_rel_addr)
 {
-    struct wined3d_sm1_data *priv = data;
     DWORD token, addr_token;
 
     *ptr += shader_get_param(priv, *ptr, &token, &addr_token);
@@ -641,6 +620,84 @@ static void shader_sm1_read_semantic(const DWORD **ptr, struct wined3d_shader_se
     shader_parse_dst_param(dst_token, NULL, &semantic->reg);
 }
 
+static void shader_sm1_read_immconst(const DWORD **ptr, struct wined3d_shader_src_param *src_param,
+        enum wined3d_immconst_type type)
+{
+    UINT count = type == WINED3D_IMMCONST_VEC4 ? 4 : 1;
+    src_param->reg.type = WINED3DSPR_IMMCONST;
+    src_param->reg.idx = ~0U;
+    src_param->reg.array_idx = ~0U;
+    src_param->reg.rel_addr = NULL;
+    src_param->reg.immconst_type = type;
+    memcpy(src_param->reg.immconst_data, *ptr, count * sizeof(DWORD));
+    src_param->swizzle = WINED3DSP_NOSWIZZLE;
+    src_param->modifiers = 0;
+
+    *ptr += count;
+}
+
+static void shader_sm1_read_instruction(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins)
+{
+    const struct wined3d_sm1_opcode_info *opcode_info;
+    struct wined3d_sm1_data *priv = data;
+    DWORD opcode_token;
+    unsigned int i;
+    const DWORD *p;
+
+    opcode_token = *(*ptr)++;
+    if (!(opcode_info = shader_get_opcode(priv, opcode_token)))
+    {
+        FIXME("Unrecognized opcode: token=0x%08x.\n", opcode_token);
+        ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+        *ptr += shader_skip_unrecognized(priv, *ptr);
+        return;
+    }
+
+    ins->handler_idx = opcode_info->handler_idx;
+    ins->flags = (opcode_token & WINED3D_OPCODESPECIFICCONTROL_MASK) >> WINED3D_OPCODESPECIFICCONTROL_SHIFT;
+    ins->coissue = opcode_token & WINED3DSI_COISSUE;
+    ins->predicate = opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED ? &priv->pred_param : NULL;
+    ins->dst_count = opcode_info->dst_count ? 1 : 0;
+    ins->dst = &priv->dst_param;
+    ins->src_count = opcode_info->param_count - opcode_info->dst_count;
+    ins->src = priv->src_param;
+
+    p = *ptr;
+    *ptr += shader_skip_opcode(priv, opcode_info, opcode_token);
+
+    if (ins->handler_idx == WINED3DSIH_DCL)
+    {
+        shader_sm1_read_semantic(&p, &ins->semantic);
+    }
+    else if (ins->handler_idx == WINED3DSIH_DEF
+            || ins->handler_idx == WINED3DSIH_DEFI)
+    {
+        shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+        shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_VEC4);
+    }
+    else if (ins->handler_idx == WINED3DSIH_DEFB)
+    {
+        shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+        shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_SCALAR);
+    }
+    else
+    {
+        /* Destination token */
+        if (ins->dst_count)
+            shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+
+        /* Predication token */
+        if (ins->predicate)
+            shader_sm1_read_src_param(priv, &p, &priv->pred_param, &priv->pred_rel_addr);
+
+        /* Other source tokens */
+        for (i = 0; i < ins->src_count; ++i)
+        {
+            shader_sm1_read_src_param(priv, &p, &priv->src_param[i], &priv->src_rel_addr[i]);
+        }
+    }
+}
+
 static void shader_sm1_read_comment(const DWORD **ptr, const char **comment, UINT *comment_size)
 {
     DWORD token = **ptr;
@@ -674,10 +731,7 @@ const struct wined3d_shader_frontend sm1_shader_frontend =
     shader_sm1_init,
     shader_sm1_free,
     shader_sm1_read_header,
-    shader_sm1_read_opcode,
-    shader_sm1_read_src_param,
-    shader_sm1_read_dst_param,
-    shader_sm1_read_semantic,
+    shader_sm1_read_instruction,
     shader_sm1_read_comment,
     shader_sm1_is_end,
 };
diff --git a/dlls/wined3d/shader_sm4.c b/dlls/wined3d/shader_sm4.c
index 25bb72a..778c924 100644
--- a/dlls/wined3d/shader_sm4.c
+++ b/dlls/wined3d/shader_sm4.c
@@ -122,6 +122,11 @@ struct wined3d_sm4_data
     struct wined3d_shader_version shader_version;
     const DWORD *end;
     const struct wined3d_shader_signature *output_signature;
+
+    struct wined3d_shader_src_param src_rel_addr[5];
+    struct wined3d_shader_src_param dst_rel_addr[2];
+    struct wined3d_shader_src_param src_param[5];
+    struct wined3d_shader_dst_param dst_param[2];
 };
 
 struct wined3d_sm4_opcode_info
@@ -333,41 +338,9 @@ static void shader_sm4_read_header(void *data, const DWORD **ptr, struct wined3d
     *shader_version = priv->shader_version;
 }
 
-static void shader_sm4_read_opcode(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins,
-        UINT *param_size)
+static void shader_sm4_read_src_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
+        struct wined3d_shader_src_param *src_param, struct wined3d_shader_src_param *src_rel_addr)
 {
-    const struct wined3d_sm4_opcode_info *opcode_info;
-    DWORD token = *(*ptr)++;
-    DWORD opcode = token & WINED3D_SM4_OPCODE_MASK;
-
-    *param_size = ((token & WINED3D_SM4_INSTRUCTION_LENGTH_MASK) >> WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT) - 1;
-
-    opcode_info = get_opcode_info(opcode);
-    if (!opcode_info)
-    {
-        FIXME("Unrecognized opcode %#x, token 0x%08x\n", opcode, token);
-        ins->handler_idx = WINED3DSIH_TABLE_SIZE;
-        return;
-    }
-
-    ins->handler_idx = opcode_info->handler_idx;
-    ins->flags = 0;
-    ins->coissue = 0;
-    ins->predicate = 0;
-    ins->dst_count = opcode_info->dst_count;
-    ins->src_count = opcode_info->src_count;
-
-    if (token & WINED3D_SM4_INSTRUCTION_MODIFIER)
-    {
-        DWORD modifier = *(*ptr)++;
-        FIXME("Skipping modifier 0x%08x.\n", modifier);
-    }
-}
-
-static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wined3d_shader_src_param *src_param,
-        struct wined3d_shader_src_param *src_rel_addr)
-{
-    struct wined3d_sm4_data *priv = data;
     DWORD token = *(*ptr)++;
     enum wined3d_sm4_register_type register_type;
     DWORD order;
@@ -456,10 +429,9 @@ static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wine
     map_register(priv, &src_param->reg);
 }
 
-static void shader_sm4_read_dst_param(void *data, const DWORD **ptr, struct wined3d_shader_dst_param *dst_param,
-        struct wined3d_shader_src_param *dst_rel_addr)
+static void shader_sm4_read_dst_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
+        struct wined3d_shader_dst_param *dst_param, struct wined3d_shader_src_param *dst_rel_addr)
 {
-    struct wined3d_sm4_data *priv = data;
     DWORD token = *(*ptr)++;
     enum wined3d_sm4_register_type register_type;
     DWORD order;
@@ -493,9 +465,53 @@ static void shader_sm4_read_dst_param(void *data, const DWORD **ptr, struct wine
     map_register(priv, &dst_param->reg);
 }
 
-static void shader_sm4_read_semantic(const DWORD **ptr, struct wined3d_shader_semantic *semantic)
+static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins)
 {
-    FIXME("ptr %p, semantic %p stub!\n", ptr, semantic);
+    const struct wined3d_sm4_opcode_info *opcode_info;
+    struct wined3d_sm4_data *priv = data;
+    DWORD opcode_token, opcode;
+    const DWORD *p;
+    UINT i, len;
+
+    opcode_token = *(*ptr)++;
+    opcode = opcode_token & WINED3D_SM4_OPCODE_MASK;
+    len = ((opcode_token & WINED3D_SM4_INSTRUCTION_LENGTH_MASK) >> WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT) - 1;
+
+    if (!(opcode_info = get_opcode_info(opcode)))
+    {
+        FIXME("Unrecognized opcode %#x, opcode_token 0x%08x.\n", opcode, opcode_token);
+        ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+        *ptr += len;
+        return;
+    }
+
+    ins->handler_idx = opcode_info->handler_idx;
+    ins->flags = 0;
+    ins->coissue = 0;
+    ins->predicate = NULL;
+    ins->dst_count = opcode_info->dst_count;
+    ins->dst = priv->dst_param;
+    ins->src_count = opcode_info->src_count;
+    ins->src = priv->src_param;
+
+    p = *ptr;
+    *ptr += len;
+
+    if (opcode_token & WINED3D_SM4_INSTRUCTION_MODIFIER)
+    {
+        DWORD modifier = *p++;
+        FIXME("Skipping modifier 0x%08x.\n", modifier);
+    }
+
+    for (i = 0; i < ins->dst_count; ++i)
+    {
+        shader_sm4_read_dst_param(priv, &p, &priv->dst_param[i], &priv->dst_rel_addr[i]);
+    }
+
+    for (i = 0; i < ins->src_count; ++i)
+    {
+        shader_sm4_read_src_param(priv, &p, &priv->src_param[i], &priv->src_rel_addr[i]);
+    }
 }
 
 static void shader_sm4_read_comment(const DWORD **ptr, const char **comment, UINT *comment_size)
@@ -515,10 +531,7 @@ const struct wined3d_shader_frontend sm4_shader_frontend =
     shader_sm4_init,
     shader_sm4_free,
     shader_sm4_read_header,
-    shader_sm4_read_opcode,
-    shader_sm4_read_src_param,
-    shader_sm4_read_dst_param,
-    shader_sm4_read_semantic,
+    shader_sm4_read_instruction,
     shader_sm4_read_comment,
     shader_sm4_is_end,
 };
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 1bc28c6..e0e8c0d 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -634,25 +634,26 @@ struct wined3d_shader_src_param
     enum wined3d_shader_src_modifier modifiers;
 };
 
+struct wined3d_shader_semantic
+{
+    enum wined3d_decl_usage usage;
+    UINT usage_idx;
+    enum wined3d_sampler_texture_type sampler_type;
+    struct wined3d_shader_dst_param reg;
+};
+
 struct wined3d_shader_instruction
 {
     const struct wined3d_shader_context *ctx;
     enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
     DWORD flags;
     BOOL coissue;
-    DWORD predicate;
+    const struct wined3d_shader_src_param *predicate;
     UINT dst_count;
     const struct wined3d_shader_dst_param *dst;
     UINT src_count;
     const struct wined3d_shader_src_param *src;
-};
-
-struct wined3d_shader_semantic
-{
-    enum wined3d_decl_usage usage;
-    UINT usage_idx;
-    enum wined3d_sampler_texture_type sampler_type;
-    struct wined3d_shader_dst_param reg;
+    struct wined3d_shader_semantic semantic;
 };
 
 struct wined3d_shader_attribute
@@ -673,12 +674,7 @@ struct wined3d_shader_frontend
     void *(*shader_init)(const DWORD *ptr, const struct wined3d_shader_signature *output_signature);
     void (*shader_free)(void *data);
     void (*shader_read_header)(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version);
-    void (*shader_read_opcode)(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins, UINT *param_size);
-    void (*shader_read_src_param)(void *data, const DWORD **ptr, struct wined3d_shader_src_param *src_param,
-            struct wined3d_shader_src_param *src_rel_addr);
-    void (*shader_read_dst_param)(void *data, const DWORD **ptr, struct wined3d_shader_dst_param *dst_param,
-            struct wined3d_shader_src_param *dst_rel_addr);
-    void (*shader_read_semantic)(const DWORD **ptr, struct wined3d_shader_semantic *semantic);
+    void (*shader_read_instruction)(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins);
     void (*shader_read_comment)(const DWORD **ptr, const char **comment, UINT *comment_size);
     BOOL (*shader_is_end)(void *data, const DWORD **ptr);
 };
-- 
1.7.8.6




More information about the wine-patches mailing list