[PATCH 3/8] wined3d: Simplify shader interface matching for SM4+ vertex shaders.

Matteo Bruni mbruni at codeweavers.com
Tue Apr 19 11:56:48 CDT 2016


After some testing it looks like, with SM4+ on Windows:
1. Output registers have to match with input registers from the
following shader stage (register index and mask). There is no "smart"
matching of semantics like in SM3.
2. Using uninitialized varyings in SM4+ shaders doesn't give consistent
results.
That means we can simplify the relevant code quite a bit. Applications
shouldn't be able to depend on particular values for uninitialized
varyings so we can avoid explicitly initializing them.

Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
Unfortunately it isn't really possible to write a test for the Wine test
suite to confirm this. I have used the geometry shader test (at the end
of this series), modifying the various shaders in multiple ways to
verify it...

 dlls/wined3d/glsl_shader.c | 42 ++++++++++++++++++++++++++++++++++++------
 dlls/wined3d/shader.c      |  3 ++-
 2 files changed, 38 insertions(+), 7 deletions(-)

diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 198e50d..0ab0936 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -5151,12 +5151,12 @@ static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const struc
     HeapFree(GetProcessHeap(), 0, entry);
 }
 
-static void shader_glsl_setup_shader_output(struct shader_glsl_priv *priv,
+static void shader_glsl_setup_vs3_output(struct shader_glsl_priv *priv,
         const struct wined3d_gl_info *gl_info, const DWORD *map,
         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, const char *out_array_name)
+        const struct wined3d_shader_reg_maps *reg_maps_out)
 {
     struct wined3d_string_buffer *destination = string_buffer_get(&priv->string_buffers);
     BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
@@ -5191,7 +5191,7 @@ static void shader_glsl_setup_shader_output(struct shader_glsl_priv *priv,
         else if (in_idx == in_count + 1)
             string_buffer_sprintf(destination, "gl_FrontSecondaryColor");
         else
-            string_buffer_sprintf(destination, "%s[%u]", out_array_name, in_idx);
+            string_buffer_sprintf(destination, "%s[%u]", "ps_link", in_idx);
 
         if (!set[in_idx])
             set[in_idx] = ~0u;
@@ -5243,7 +5243,7 @@ static void shader_glsl_setup_shader_output(struct shader_glsl_priv *priv,
         else if (i == in_count + 1)
             string_buffer_sprintf(destination, "gl_FrontSecondaryColor");
         else
-            string_buffer_sprintf(destination, "%s[%u]", out_array_name, i);
+            string_buffer_sprintf(destination, "%s[%u]", "ps_link", i);
 
         if (size == 1)
             shader_addline(buffer, "%s.%s = 0.0;\n", destination->buffer, reg_mask);
@@ -5255,6 +5255,33 @@ static void shader_glsl_setup_shader_output(struct shader_glsl_priv *priv,
     string_buffer_release(&priv->string_buffers, destination);
 }
 
+static void shader_glsl_setup_sm4_shader_output(struct shader_glsl_priv *priv,
+        const struct wined3d_shader_signature *output_signature,
+        const struct wined3d_shader_reg_maps *reg_maps_out, const char *out_array_name)
+{
+    struct wined3d_string_buffer *destination = string_buffer_get(&priv->string_buffers);
+    struct wined3d_string_buffer *buffer = &priv->shader_buffer;
+    char reg_mask[6];
+    unsigned int i;
+
+    for (i = 0; i < output_signature->element_count; ++i)
+    {
+        const struct wined3d_shader_signature_element *output = &output_signature->elements[i];
+
+        if (!(reg_maps_out->output_registers & (1u << output->register_idx)))
+            continue;
+
+        string_buffer_sprintf(destination, "%s[%u]", out_array_name, output->register_idx);
+
+        shader_glsl_write_mask_to_str(output->mask, reg_mask);
+
+        shader_addline(buffer, "%s%s = shader_out[%u]%s;\n",
+                destination->buffer, reg_mask, output->register_idx, reg_mask);
+    }
+
+    string_buffer_release(&priv->string_buffers, destination);
+}
+
 static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv,
         const struct wined3d_gl_info *gl_info, const DWORD *map,
         const struct wined3d_shader_signature *input_signature,
@@ -5293,8 +5320,11 @@ static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv
     }
 
     /* Then, setup the pixel shader input. */
-    shader_glsl_setup_shader_output(priv, gl_info, map, input_signature, reg_maps_in,
-            output_signature, reg_maps_out, "ps_link");
+    if (reg_maps_out->shader_version.major < 4)
+        shader_glsl_setup_vs3_output(priv, gl_info, map, input_signature, reg_maps_in,
+                output_signature, reg_maps_out);
+    else
+        shader_glsl_setup_sm4_shader_output(priv, output_signature, reg_maps_out, "ps_link");
 }
 
 /* Context activation is done by the caller. */
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 55c1d5b..6278239 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -3125,7 +3125,8 @@ static HRESULT pixel_shader_init(struct wined3d_shader *shader, struct wined3d_d
     /* Don't do any register mapping magic if it is not needed, or if we can't
      * achieve anything anyway */
     if (highest_reg_used < (gl_info->limits.glsl_varyings / 4)
-            || num_regs_used > (gl_info->limits.glsl_varyings / 4))
+            || num_regs_used > (gl_info->limits.glsl_varyings / 4)
+            || shader->reg_maps.shader_version.major >= 4)
     {
         if (num_regs_used > (gl_info->limits.glsl_varyings / 4))
         {
-- 
2.7.3




More information about the wine-patches mailing list