[PATCH 2/5] wined3d: Store shader input signatures as a wined3d_shader_signature structure.

Henri Verbeet hverbeet at codeweavers.com
Mon Mar 23 03:17:13 CDT 2015


---
 dlls/wined3d/arb_program_shader.c |  182 +++++++++++++++++++++----------------
 dlls/wined3d/glsl_shader.c        |   62 ++++++-------
 dlls/wined3d/shader.c             |  144 ++++++++++++++++++-----------
 dlls/wined3d/wined3d_private.h    |    2 +-
 4 files changed, 226 insertions(+), 164 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 212ccba..aa9dc76 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -288,7 +288,7 @@ struct shader_arb_ctx_priv
 
 struct ps_signature
 {
-    struct wined3d_shader_signature_element *sig;
+    struct wined3d_shader_signature sig;
     DWORD                               idx;
     struct wine_rb_entry                entry;
 };
@@ -3489,7 +3489,7 @@ static void init_ps_input(const struct wined3d_shader *shader,
         "fragment.texcoord[4]", "fragment.texcoord[5]", "fragment.texcoord[6]", "fragment.texcoord[7]"
     };
     unsigned int i;
-    const struct wined3d_shader_signature_element *sig = shader->input_signature;
+    const struct wined3d_shader_signature_element *input;
     const char *semantic_name;
     DWORD semantic_idx;
 
@@ -3505,38 +3505,47 @@ static void init_ps_input(const struct wined3d_shader *shader,
              * we'd either need a replacement shader that can load other attribs like BINORMAL, or
              * load the texcoord attrib pointers to match the pixel shader signature
              */
-            for(i = 0; i < MAX_REG_INPUT; i++)
+            for (i = 0; i < shader->input_signature.element_count; ++i)
             {
-                semantic_name = sig[i].semantic_name;
-                semantic_idx = sig[i].semantic_idx;
-                if (!semantic_name) continue;
+                input = &shader->input_signature.elements[i];
+                if (!(semantic_name = input->semantic_name))
+                    continue;
+                semantic_idx = input->semantic_idx;
 
                 if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
                 {
-                    if (!semantic_idx) priv->ps_input[i] = "fragment.color.primary";
-                    else if(semantic_idx == 1) priv->ps_input[i] = "fragment.color.secondary";
-                    else priv->ps_input[i] = "0.0";
+                    if (!semantic_idx)
+                        priv->ps_input[input->register_idx] = "fragment.color.primary";
+                    else if (semantic_idx == 1)
+                        priv->ps_input[input->register_idx] = "fragment.color.secondary";
+                    else
+                        priv->ps_input[input->register_idx] = "0.0";
                 }
-                else if(args->super.vp_mode == fixedfunction)
+                else if (args->super.vp_mode == fixedfunction)
                 {
-                    priv->ps_input[i] = "0.0";
+                    priv->ps_input[input->register_idx] = "0.0";
                 }
-                else if(shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
+                else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
                 {
-                    if(semantic_idx < 8) priv->ps_input[i] = texcoords[semantic_idx];
-                    else priv->ps_input[i] = "0.0";
+                    if (semantic_idx < 8)
+                        priv->ps_input[input->register_idx] = texcoords[semantic_idx];
+                    else
+                        priv->ps_input[input->register_idx] = "0.0";
                 }
-                else if(shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
+                else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
                 {
-                    if (!semantic_idx) priv->ps_input[i] = "fragment.fogcoord";
-                    else priv->ps_input[i] = "0.0";
+                    if (!semantic_idx)
+                        priv->ps_input[input->register_idx] = "fragment.fogcoord";
+                    else
+                        priv->ps_input[input->register_idx] = "0.0";
                 }
                 else
                 {
-                    priv->ps_input[i] = "0.0";
+                    priv->ps_input[input->register_idx] = "0.0";
                 }
 
-                TRACE("v%u, semantic %s%u is %s\n", i, semantic_name, semantic_idx, priv->ps_input[i]);
+                TRACE("v%u, semantic %s%u is %s\n", input->register_idx,
+                        semantic_name, semantic_idx, priv->ps_input[input->register_idx]);
             }
             break;
 
@@ -3910,51 +3919,68 @@ static GLuint shader_arb_generate_pshader(const struct wined3d_shader *shader,
     return retval;
 }
 
-static int compare_sig(const struct wined3d_shader_signature_element *sig1, const struct wined3d_shader_signature_element *sig2)
+static int compare_sig(const struct wined3d_shader_signature *sig1, const struct wined3d_shader_signature *sig2)
 {
     unsigned int i;
     int ret;
 
-    for(i = 0; i < MAX_REG_INPUT; i++)
+    if (sig1->element_count != sig2->element_count)
+        return sig1->element_count < sig2->element_count ? -1 : 1;
+
+    for (i = 0; i < sig1->element_count; ++i)
     {
-        if (!sig1[i].semantic_name || !sig2[i].semantic_name)
+        const struct wined3d_shader_signature_element *e1, *e2;
+
+        e1 = &sig1->elements[i];
+        e2 = &sig2->elements[i];
+
+        if (!e1->semantic_name || !e2->semantic_name)
         {
-            /* Compare pointers, not contents. One string is NULL(element does not exist), the other one is not NULL */
-            if(sig1[i].semantic_name != sig2[i].semantic_name) return sig1[i].semantic_name < sig2[i].semantic_name ? -1 : 1;
+            /* Compare pointers, not contents. One string is NULL (element
+             * does not exist), the other one is not NULL. */
+            if (e1->semantic_name != e2->semantic_name)
+                return e1->semantic_name < e2->semantic_name ? -1 : 1;
             continue;
         }
 
-        if ((ret = strcmp(sig1[i].semantic_name, sig2[i].semantic_name))) return ret;
-        if(sig1[i].semantic_idx    != sig2[i].semantic_idx)    return sig1[i].semantic_idx    < sig2[i].semantic_idx    ? -1 : 1;
-        if(sig1[i].sysval_semantic != sig2[i].sysval_semantic) return sig1[i].sysval_semantic < sig2[i].sysval_semantic ? -1 : 1;
-        if(sig1[i].component_type  != sig2[i].component_type)  return sig1[i].component_type  < sig2[i].component_type  ? -1 : 1;
-        if(sig1[i].register_idx    != sig2[i].register_idx)    return sig1[i].register_idx    < sig2[i].register_idx    ? -1 : 1;
-        if(sig1[i].mask            != sig2[i].mask)            return sig1[i].mask            < sig2[i].mask            ? -1 : 1;
+        if ((ret = strcmp(e1->semantic_name, e2->semantic_name)))
+            return ret;
+        if (e1->semantic_idx != e2->semantic_idx)
+            return e1->semantic_idx < e2->semantic_idx ? -1 : 1;
+        if (e1->sysval_semantic != e2->sysval_semantic)
+            return e1->sysval_semantic < e2->sysval_semantic ? -1 : 1;
+        if (e1->component_type != e2->component_type)
+            return e1->component_type < e2->component_type ? -1 : 1;
+        if (e1->register_idx != e2->register_idx)
+            return e1->register_idx < e2->register_idx ? -1 : 1;
+        if (e1->mask != e2->mask)
+            return e1->mask < e2->mask ? -1 : 1;
     }
     return 0;
 }
 
-static struct wined3d_shader_signature_element *clone_sig(const struct wined3d_shader_signature_element *sig)
+static void clone_sig(struct wined3d_shader_signature *new, const struct wined3d_shader_signature *sig)
 {
-    struct wined3d_shader_signature_element *new;
-    int i;
+    unsigned int i;
     char *name;
 
-    new = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*new) * MAX_REG_INPUT);
-    for(i = 0; i < MAX_REG_INPUT; i++)
+    new->element_count = sig->element_count;
+    new->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*new->elements) * new->element_count);
+    for (i = 0; i < sig->element_count; ++i)
     {
-        if (!sig[i].semantic_name) continue;
+        new->elements[i] = sig->elements[i];
+
+        if (!new->elements[i].semantic_name)
+            continue;
 
-        new[i] = sig[i];
         /* Clone the semantic string */
-        name = HeapAlloc(GetProcessHeap(), 0, strlen(sig[i].semantic_name) + 1);
-        strcpy(name, sig[i].semantic_name);
-        new[i].semantic_name = name;
+        name = HeapAlloc(GetProcessHeap(), 0, strlen(sig->elements[i].semantic_name) + 1);
+        strcpy(name, sig->elements[i].semantic_name);
+        new->elements[i].semantic_name = name;
     }
-    return new;
 }
 
-static DWORD find_input_signature(struct shader_arb_priv *priv, const struct wined3d_shader_signature_element *sig)
+static DWORD find_input_signature(struct shader_arb_priv *priv, const struct wined3d_shader_signature *sig)
 {
     struct wine_rb_entry *entry = wine_rb_get(&priv->signature_tree, sig);
     struct ps_signature *found_sig;
@@ -3966,7 +3992,7 @@ static DWORD find_input_signature(struct shader_arb_priv *priv, const struct win
         return found_sig->idx;
     }
     found_sig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*found_sig));
-    found_sig->sig = clone_sig(sig);
+    clone_sig(&found_sig->sig, sig);
     found_sig->idx = priv->ps_sig_number++;
     TRACE("New signature stored and assigned number %u\n", found_sig->idx);
     if(wine_rb_put(&priv->signature_tree, sig, &found_sig->entry) == -1)
@@ -3977,7 +4003,7 @@ static DWORD find_input_signature(struct shader_arb_priv *priv, const struct win
 }
 
 static void init_output_registers(const struct wined3d_shader *shader,
-        const struct wined3d_shader_signature_element *ps_input_sig,
+        const struct wined3d_shader_signature *ps_input_sig,
         struct shader_arb_ctx_priv *priv_ctx, struct arb_vs_compiled_shader *compiled)
 {
     unsigned int i, j;
@@ -3986,8 +4012,6 @@ static void init_output_registers(const struct wined3d_shader *shader,
         "result.texcoord[0]", "result.texcoord[1]", "result.texcoord[2]", "result.texcoord[3]",
         "result.texcoord[4]", "result.texcoord[5]", "result.texcoord[6]", "result.texcoord[7]"
     };
-    DWORD semantic_idx, reg_idx;
-
     /* Write generic input varyings 0 to 7 to result.texcoord[], varying 8 to result.color.primary
      * and varying 9 to result.color.secondary
      */
@@ -4078,14 +4102,12 @@ static void init_output_registers(const struct wined3d_shader *shader,
     priv_ctx->color_output[1] = "TA";
     priv_ctx->fog_output = "TA";
 
-    for(i = 0; i < MAX_REG_INPUT; i++)
+    for (i = 0; i < ps_input_sig->element_count; ++i)
     {
-        const char *semantic_name;
+        const struct wined3d_shader_signature_element *input = &ps_input_sig->elements[i];
 
-        semantic_name = ps_input_sig[i].semantic_name;
-        semantic_idx = ps_input_sig[i].semantic_idx;
-        reg_idx = ps_input_sig[i].register_idx;
-        if (!semantic_name) continue;
+        if (!input->semantic_name)
+            continue;
 
         /* If a declared input register is not written by builtin arguments, don't write to it.
          * GL_NV_vertex_program makes sure the input defaults to 0.0, which is correct with D3D
@@ -4093,28 +4115,28 @@ static void init_output_registers(const struct wined3d_shader *shader,
          * Don't care about POSITION and PSIZE here - this is a builtin vertex shader, position goes
          * to TMP_OUT in any case
          */
-        if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
+        if (shader_match_semantic(input->semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
         {
-            if (semantic_idx < 8)
-                priv_ctx->texcrd_output[semantic_idx] = decl_idx_to_string[reg_idx];
+            if (input->semantic_idx < 8)
+                priv_ctx->texcrd_output[input->semantic_idx] = decl_idx_to_string[input->register_idx];
         }
-        else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
+        else if (shader_match_semantic(input->semantic_name, WINED3D_DECL_USAGE_COLOR))
         {
-            if (semantic_idx < 2)
-                priv_ctx->color_output[semantic_idx] = decl_idx_to_string[reg_idx];
+            if (input->semantic_idx < 2)
+                priv_ctx->color_output[input->semantic_idx] = decl_idx_to_string[input->register_idx];
         }
-        else if(shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_FOG))
+        else if (shader_match_semantic(input->semantic_name, WINED3D_DECL_USAGE_FOG))
         {
-            if (!semantic_idx)
-                priv_ctx->fog_output = decl_idx_to_string[reg_idx];
+            if (!input->semantic_idx)
+                priv_ctx->fog_output = decl_idx_to_string[input->register_idx];
         }
         else
         {
             continue;
         }
 
-        if (!strcmp(decl_idx_to_string[reg_idx], "result.color.primary")
-                || !strcmp(decl_idx_to_string[reg_idx], "result.color.secondary"))
+        if (!strcmp(decl_idx_to_string[input->register_idx], "result.color.primary")
+                || !strcmp(decl_idx_to_string[input->register_idx], "result.color.secondary"))
         {
             compiled->need_color_unclamp = TRUE;
         }
@@ -4142,14 +4164,17 @@ static void init_output_registers(const struct wined3d_shader *shader,
             continue;
         }
 
-        for(j = 0; j < MAX_REG_INPUT; j++)
+        for (j = 0; j < ps_input_sig->element_count; ++j)
         {
-            if (!ps_input_sig[j].semantic_name) continue;
+            const struct wined3d_shader_signature_element *input = &ps_input_sig->elements[i];
+
+            if (!input->semantic_name)
+                continue;
 
-            if (!strcmp(ps_input_sig[j].semantic_name, output->semantic_name)
-                    && ps_input_sig[j].semantic_idx == output->semantic_idx)
+            if (!strcmp(input->semantic_name, output->semantic_name)
+                    && input->semantic_idx == output->semantic_idx)
             {
-                priv_ctx->vs_output[output->register_idx] = decl_idx_to_string[ps_input_sig[j].register_idx];
+                priv_ctx->vs_output[output->register_idx] = decl_idx_to_string[input->register_idx];
 
                 if (!strcmp(priv_ctx->vs_output[output->register_idx], "result.color.primary")
                         || !strcmp(priv_ctx->vs_output[output->register_idx], "result.color.secondary"))
@@ -4165,7 +4190,7 @@ static void init_output_registers(const struct wined3d_shader *shader,
 static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
         const struct wined3d_gl_info *gl_info, struct wined3d_shader_buffer *buffer,
         const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled,
-        const struct wined3d_shader_signature_element *ps_input_sig)
+        const struct wined3d_shader_signature *ps_input_sig)
 {
     const struct arb_vshader_private *shader_data = shader->backend_data;
     const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
@@ -4345,7 +4370,7 @@ static struct arb_ps_compiled_shader *find_arb_pshader(struct wined3d_shader *sh
         if (shader->reg_maps.shader_version.major < 3)
             shader_data->input_signature_idx = ~0U;
         else
-            shader_data->input_signature_idx = find_input_signature(priv, shader->input_signature);
+            shader_data->input_signature_idx = find_input_signature(priv, &shader->input_signature);
 
         TRACE("Shader got assigned input signature index %u\n", shader_data->input_signature_idx);
 
@@ -4420,7 +4445,7 @@ static inline BOOL vs_args_equal(const struct arb_vs_compile_args *stored, const
 
 static struct arb_vs_compiled_shader *find_arb_vshader(struct wined3d_shader *shader,
         const struct wined3d_gl_info *gl_info, DWORD use_map, const struct arb_vs_compile_args *args,
-        const struct wined3d_shader_signature_element *ps_input_sig)
+        const struct wined3d_shader_signature *ps_input_sig)
 {
     UINT i;
     DWORD new_size;
@@ -4717,7 +4742,7 @@ static void shader_arb_select(void *shader_priv, struct wined3d_context *context
         struct wined3d_shader *vs = state->shader[WINED3D_SHADER_TYPE_VERTEX];
         struct arb_vs_compile_args compile_args;
         struct arb_vs_compiled_shader *compiled;
-        const struct wined3d_shader_signature_element *ps_input_sig;
+        const struct wined3d_shader_signature *ps_input_sig;
 
         TRACE("Using vertex shader %p\n", vs);
         find_arb_vs_compile_args(state, context, vs, &compile_args);
@@ -4728,7 +4753,7 @@ static void shader_arb_select(void *shader_priv, struct wined3d_context *context
         if (compile_args.ps_signature == ~0U)
             ps_input_sig = NULL;
         else
-            ps_input_sig = state->shader[WINED3D_SHADER_TYPE_PIXEL]->input_signature;
+            ps_input_sig = &state->shader[WINED3D_SHADER_TYPE_PIXEL]->input_signature;
 
         compiled = find_arb_vshader(vs, context->gl_info, context->stream_info.use_map,
                 &compile_args, ps_input_sig);
@@ -4917,7 +4942,7 @@ static void shader_arb_destroy(struct wined3d_shader *shader)
 static int sig_tree_compare(const void *key, const struct wine_rb_entry *entry)
 {
     struct ps_signature *e = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry);
-    return compare_sig(key, e->sig);
+    return compare_sig(key, &e->sig);
 }
 
 static const struct wine_rb_functions sig_tree_functions =
@@ -4994,12 +5019,13 @@ fail:
 static void release_signature(struct wine_rb_entry *entry, void *context)
 {
     struct ps_signature *sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry);
-    int i;
-    for(i = 0; i < MAX_REG_INPUT; i++)
+    unsigned int i;
+
+    for (i = 0; i < sig->sig.element_count; ++i)
     {
-        HeapFree(GetProcessHeap(), 0, (char *) sig->sig[i].semantic_name);
+        HeapFree(GetProcessHeap(), 0, (char *)sig->sig.elements[i].semantic_name);
     }
-    HeapFree(GetProcessHeap(), 0, sig->sig);
+    HeapFree(GetProcessHeap(), 0, sig->sig.elements);
     HeapFree(GetProcessHeap(), 0, sig);
 }
 
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index c784af0..4240b08 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -4144,60 +4144,62 @@ static void shader_glsl_dp2add(const struct wined3d_shader_instruction *ins)
 }
 
 static void shader_glsl_input_pack(const struct wined3d_shader *shader, struct wined3d_shader_buffer *buffer,
-        const struct wined3d_shader_signature_element *input_signature,
+        const struct wined3d_shader_signature *input_signature,
         const struct wined3d_shader_reg_maps *reg_maps,
         enum vertexprocessing_mode vertexprocessing)
 {
-    WORD map = reg_maps->input_registers;
     unsigned int i;
 
-    for (i = 0; map; map >>= 1, ++i)
+    for (i = 0; i < input_signature->element_count; ++i)
     {
+        const struct wined3d_shader_signature_element *input = &input_signature->elements[i];
         const char *semantic_name;
         UINT semantic_idx;
         char reg_mask[6];
 
         /* Unused */
-        if (!(map & 1)) continue;
+        if (!(reg_maps->input_registers & (1 << input->register_idx)))
+            continue;
 
-        semantic_name = input_signature[i].semantic_name;
-        semantic_idx = input_signature[i].semantic_idx;
-        shader_glsl_write_mask_to_str(input_signature[i].mask, reg_mask);
+        semantic_name = input->semantic_name;
+        semantic_idx = input->semantic_idx;
+        shader_glsl_write_mask_to_str(input->mask, reg_mask);
 
         if (vertexprocessing == vertexshader)
         {
             if (!strcmp(semantic_name, "SV_POSITION") && !semantic_idx)
                 shader_addline(buffer, "ps_in[%u]%s = vpos%s;\n",
-                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
             else
                 shader_addline(buffer, "ps_in[%u]%s = ps_link[%u]%s;\n",
-                        shader->u.ps.input_reg_map[i], reg_mask, shader->u.ps.input_reg_map[i], reg_mask);
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask,
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask);
         }
         else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_TEXCOORD))
         {
             if (semantic_idx < 8 && vertexprocessing == pretransformed)
                 shader_addline(buffer, "ps_in[%u]%s = gl_TexCoord[%u]%s;\n",
-                        shader->u.ps.input_reg_map[i], reg_mask, semantic_idx, reg_mask);
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask, semantic_idx, reg_mask);
             else
                 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
-                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
         }
         else if (shader_match_semantic(semantic_name, WINED3D_DECL_USAGE_COLOR))
         {
             if (!semantic_idx)
                 shader_addline(buffer, "ps_in[%u]%s = vec4(gl_Color)%s;\n",
-                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
             else if (semantic_idx == 1)
                 shader_addline(buffer, "ps_in[%u]%s = vec4(gl_SecondaryColor)%s;\n",
-                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
             else
                 shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
-                        shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+                        shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
         }
         else
         {
             shader_addline(buffer, "ps_in[%u]%s = vec4(0.0, 0.0, 0.0, 0.0)%s;\n",
-                    shader->u.ps.input_reg_map[i], reg_mask, reg_mask);
+                    shader->u.ps.input_reg_map[input->register_idx], reg_mask, reg_mask);
         }
     }
 }
@@ -4259,31 +4261,31 @@ static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struc
 
 static void handle_ps3_input(struct wined3d_shader_buffer *buffer,
         const struct wined3d_gl_info *gl_info, const DWORD *map,
-        const struct wined3d_shader_signature_element *input_signature,
+        const struct wined3d_shader_signature *input_signature,
         const struct wined3d_shader_reg_maps *reg_maps_in,
         const struct wined3d_shader_signature *output_signature,
         const struct wined3d_shader_reg_maps *reg_maps_out)
 {
     unsigned int i, j;
-    const char *semantic_name_in;
-    UINT semantic_idx_in;
     DWORD *set;
     DWORD in_idx;
     unsigned int in_count = vec4_varyings(3, gl_info);
     char reg_mask[6];
     char destination[50];
-    WORD input_map;
 
     set = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*set) * (in_count + 2));
 
-    input_map = reg_maps_in->input_registers;
-    for (i = 0; input_map; input_map >>= 1, ++i)
+    for (i = 0; i < input_signature->element_count; ++i)
     {
-        if (!(input_map & 1)) continue;
+        const struct wined3d_shader_signature_element *input = &input_signature->elements[i];
+
+        if (!(reg_maps_in->input_registers & (1 << input->register_idx)))
+            continue;
 
-        in_idx = map[i];
+        in_idx = map[input->register_idx];
         /* Declared, but not read register */
-        if (in_idx == ~0U) continue;
+        if (in_idx == ~0u)
+            continue;
         if (in_idx >= (in_count + 2))
         {
             FIXME("More input varyings declared than supported, expect issues.\n");
@@ -4297,8 +4299,6 @@ static void handle_ps3_input(struct wined3d_shader_buffer *buffer,
         else
             sprintf(destination, "ps_link[%u]", in_idx);
 
-        semantic_name_in = input_signature[i].semantic_name;
-        semantic_idx_in = input_signature[i].semantic_idx;
         if (!set[in_idx])
             set[in_idx] = ~0u;
 
@@ -4308,9 +4308,9 @@ static void handle_ps3_input(struct wined3d_shader_buffer *buffer,
             DWORD mask;
 
             if (!(reg_maps_out->output_registers & (1 << output->register_idx))
-                    || semantic_idx_in != output->semantic_idx
-                    || strcmp(semantic_name_in, output->semantic_name)
-                    || !(mask = input_signature[i].mask & output->mask))
+                    || input->semantic_idx != output->semantic_idx
+                    || strcmp(input->semantic_name, output->semantic_name)
+                    || !(mask = input->mask & output->mask))
                 continue;
 
             if (set[in_idx] == ~0u)
@@ -4457,7 +4457,7 @@ static GLuint generate_param_reorder_function(struct wined3d_shader_buffer *buff
         }
 
         /* Then, fix the pixel shader input */
-        handle_ps3_input(buffer, gl_info, ps->u.ps.input_reg_map, ps->input_signature,
+        handle_ps3_input(buffer, gl_info, ps->u.ps.input_reg_map, &ps->input_signature,
                 &ps->reg_maps, &vs->output_signature, &vs->reg_maps);
 
         shader_addline(buffer, "}\n");
@@ -4546,7 +4546,7 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
 
     /* Pack 3.0 inputs */
     if (reg_maps->shader_version.major >= 3)
-        shader_glsl_input_pack(shader, buffer, shader->input_signature, reg_maps, args->vp_mode);
+        shader_glsl_input_pack(shader, buffer, &shader->input_signature, reg_maps, args->vp_mode);
 
     /* Base Shader Body */
     shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index f912ed1..9425ac4 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -639,9 +639,10 @@ static unsigned int get_instr_extra_regcount(enum WINED3D_SHADER_INSTRUCTION_HAN
 
 /* Note that this does not count the loop register as an address register. */
 static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const struct wined3d_shader_frontend *fe,
-        struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_signature_element *input_signature,
+        struct wined3d_shader_reg_maps *reg_maps, struct wined3d_shader_signature *input_signature,
         struct wined3d_shader_signature *output_signature, const DWORD *byte_code, DWORD constf_size)
 {
+    struct wined3d_shader_signature_element input_signature_elements[max(MAX_ATTRIBS, MAX_REG_INPUT)];
     struct wined3d_shader_signature_element output_signature_elements[MAX_REG_OUTPUT];
     unsigned int cur_loop_depth = 0, max_loop_depth = 0;
     void *fe_data = shader->frontend_data;
@@ -650,6 +651,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
     unsigned int i;
 
     memset(reg_maps, 0, sizeof(*reg_maps));
+    memset(input_signature_elements, 0, sizeof(input_signature_elements));
     memset(output_signature_elements, 0, sizeof(output_signature_elements));
     reg_maps->min_rel_offset = ~0U;
 
@@ -699,7 +701,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
                             && semantic->usage == WINED3D_DECL_USAGE_POSITION && !semantic->usage_idx)
                         return WINED3DERR_INVALIDCALL;
                     reg_maps->input_registers |= 1 << reg_idx;
-                    shader_signature_from_semantic(&input_signature[reg_idx], semantic);
+                    shader_signature_from_semantic(&input_signature_elements[reg_idx], semantic);
                     break;
 
                 /* Vertex shader: mark 3.0 output registers used, save token. */
@@ -1048,6 +1050,36 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
 
     shader->functionLength = ((const char *)ptr - (const char *)byte_code);
 
+    if (input_signature->elements)
+    {
+        for (i = 0; i < input_signature->element_count; ++i)
+        {
+            reg_maps->input_registers |= 1 << input_signature->elements[i].register_idx;
+            if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL
+                    && !strcmp(input_signature->elements[i].semantic_name, "SV_POSITION"))
+                reg_maps->vpos = 1;
+        }
+    }
+    else if (!input_signature->elements && reg_maps->input_registers)
+    {
+        unsigned int count = count_bits(reg_maps->input_registers);
+        struct wined3d_shader_signature_element *e;
+        unsigned int i;
+
+        if (!(input_signature->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*input_signature->elements) * count)))
+            return E_OUTOFMEMORY;
+        input_signature->element_count = count;
+
+        e = input_signature->elements;
+        for (i = 0; i < ARRAY_SIZE(input_signature_elements); ++i)
+        {
+            if (!(reg_maps->input_registers & (1 << i)))
+                continue;
+            input_signature_elements[i].register_idx = i;
+            *e++ = input_signature_elements[i];
+        }
+    }
+
     if (output_signature->elements)
     {
         for (i = 0; i < output_signature->element_count; ++i)
@@ -1059,7 +1091,6 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
     {
         unsigned int count = count_bits(reg_maps->output_registers);
         struct wined3d_shader_signature_element *e;
-        unsigned int i;
 
         if (!(output_signature->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*output_signature->elements) * count)))
             return E_OUTOFMEMORY;
@@ -1986,7 +2017,7 @@ static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *b
     shader->lconst_inf_or_nan = FALSE;
 
     /* Second pass: figure out which registers are used, what the semantics are, etc. */
-    if (FAILED(hr = shader_get_registers_used(shader, fe, reg_maps, shader->input_signature,
+    if (FAILED(hr = shader_get_registers_used(shader, fe, reg_maps, &shader->input_signature,
             &shader->output_signature, byte_code, float_const_count)))
         return hr;
 
@@ -2174,7 +2205,6 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d
     struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     unsigned int i;
     HRESULT hr;
-    WORD map;
     const DWORD vs_uniform_count = device->adapter->d3d_info.limits.vs_uniform_count;
 
     if (!desc->byte_code)
@@ -2237,15 +2267,16 @@ static HRESULT vertexshader_init(struct wined3d_shader *shader, struct wined3d_d
         return hr;
     }
 
-    map = reg_maps->input_registers;
-    for (i = 0; map; map >>= 1, ++i)
+    for (i = 0; i < shader->input_signature.element_count; ++i)
     {
-        if (!(map & 1) || !shader->input_signature[i].semantic_name)
+        const struct wined3d_shader_signature_element *input = &shader->input_signature.elements[i];
+
+        if (!(reg_maps->input_registers & (1 << input->register_idx)) || !input->semantic_name)
             continue;
 
-        shader->u.vs.attributes[i].usage =
-                shader_usage_from_semantic_name(shader->input_signature[i].semantic_name);
-        shader->u.vs.attributes[i].usage_idx = shader->input_signature[i].semantic_idx;
+        shader->u.vs.attributes[input->register_idx].usage =
+                shader_usage_from_semantic_name(input->semantic_name);
+        shader->u.vs.attributes[i].usage_idx = input->semantic_idx;
     }
 
     shader->load_local_constsF = (reg_maps->usesrelconstF && !list_empty(&shader->constantsF)) ||
@@ -2461,6 +2492,54 @@ static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_de
         return WINED3DERR_INVALIDCALL;
 
     shader_init(shader, device, parent, parent_ops);
+
+    if (desc->input_signature)
+    {
+        struct wined3d_shader_signature_element *e;
+        SIZE_T total, len;
+        char *ptr;
+
+        total = 0;
+        for (i = 0; i < desc->input_signature->element_count; ++i)
+        {
+            e = &desc->input_signature->elements[i];
+            len = strlen(e->semantic_name);
+            if (len >= ~(SIZE_T)0 - total)
+            {
+                shader_cleanup(shader);
+                return E_OUTOFMEMORY;
+            }
+
+            total += len + 1;
+        }
+
+        if (!(shader->signature_strings = HeapAlloc(GetProcessHeap(), 0, total)))
+        {
+            shader_cleanup(shader);
+            return E_OUTOFMEMORY;
+        }
+        ptr = shader->signature_strings;
+
+        shader->input_signature.element_count = desc->input_signature->element_count;
+        if (!(shader->input_signature.elements = HeapAlloc(GetProcessHeap(), 0,
+                sizeof(*shader->input_signature.elements) * shader->input_signature.element_count)))
+        {
+            shader_cleanup(shader);
+            return E_OUTOFMEMORY;
+        }
+
+        for (i = 0; i < desc->input_signature->element_count; ++i)
+        {
+            e = &desc->input_signature->elements[i];
+            shader->input_signature.elements[i] = *e;
+
+            len = strlen(e->semantic_name);
+            memcpy(ptr, e->semantic_name, len + 1);
+            shader->input_signature.elements[i].semantic_name = ptr;
+            ptr += len + 1;
+        }
+    }
+
     if (FAILED(hr = shader_set_function(shader, desc->byte_code, desc->output_signature,
             ps_uniform_count, WINED3D_SHADER_TYPE_PIXEL, desc->max_version)))
     {
@@ -2511,49 +2590,6 @@ static HRESULT pixelshader_init(struct wined3d_shader *shader, struct wined3d_de
 
     shader->load_local_constsF = shader->lconst_inf_or_nan;
 
-    if (desc->input_signature)
-    {
-        struct wined3d_shader_signature_element *e;
-        SIZE_T total, len;
-        char *ptr;
-
-        total = 0;
-        for (i = 0; i < desc->input_signature->element_count; ++i)
-        {
-            e = &desc->input_signature->elements[i];
-            len = strlen(e->semantic_name);
-            if (len >= ~(SIZE_T)0 - total)
-            {
-                shader_cleanup(shader);
-                return E_OUTOFMEMORY;
-            }
-
-            total += len + 1;
-        }
-
-        if (!(shader->signature_strings = HeapAlloc(GetProcessHeap(), 0, total)))
-        {
-            shader_cleanup(shader);
-            return E_OUTOFMEMORY;
-        }
-        ptr = shader->signature_strings;
-
-        for (i = 0; i < desc->input_signature->element_count; ++i)
-        {
-            e = &desc->input_signature->elements[i];
-            shader->reg_maps.input_registers |= 1 << e->register_idx;
-            shader->input_signature[e->register_idx] = *e;
-
-            len = strlen(e->semantic_name);
-            memcpy(ptr, e->semantic_name, len + 1);
-            shader->input_signature[e->register_idx].semantic_name = ptr;
-            ptr += len + 1;
-
-            if (!strcmp(e->semantic_name, "SV_POSITION"))
-                shader->reg_maps.vpos = 1;
-        }
-    }
-
     return WINED3D_OK;
 }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 519ef98..70f07a1 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2931,7 +2931,7 @@ struct wined3d_shader
     struct wined3d_shader_reg_maps reg_maps;
     BOOL lconst_inf_or_nan;
 
-    struct wined3d_shader_signature_element input_signature[max(MAX_ATTRIBS, MAX_REG_INPUT)];
+    struct wined3d_shader_signature input_signature;
     struct wined3d_shader_signature output_signature;
     char *signature_strings;
 
-- 
1.7.10.4




More information about the wine-patches mailing list