[v2 1/3] wined3d: Implement return instruction.

Andrew Wesie awesie at gmail.com
Thu Nov 17 23:46:00 CST 2016


A return instruction may occur inside of a conditional or loop, and we need
to output a GLSL return instruction, and possibly an epilogue. Some shaders
may not end with a return instruction, in which case we pretend there was
one.

Signed-off-by: Andrew Wesie <awesie at gmail.com>
---
 dlls/wined3d/glsl_shader.c | 94 +++++++++++++++++++++++++++++++---------------
 dlls/wined3d/shader.c      | 11 ++++++
 2 files changed, 75 insertions(+), 30 deletions(-)

diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 9e9c83b..9af8fc5 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -270,6 +270,9 @@ struct glsl_ffp_destroy_ctx
     const struct wined3d_gl_info *gl_info;
 };
 
+static void shader_glsl_epilogue_ps(const struct wined3d_shader_context *ctx);
+static void shader_glsl_epilogue_vs(const struct wined3d_shader_context *ctx);
+
 static const char *debug_gl_shader_type(GLenum type)
 {
     switch (type)
@@ -4461,9 +4464,21 @@ static void shader_glsl_callnz(const struct wined3d_shader_instruction *ins)
 
 static void shader_glsl_ret(const struct wined3d_shader_instruction *ins)
 {
-    /* No-op. The closing } is written when a new function is started, and at the end of the shader. This
-     * function only suppresses the unhandled instruction warning
-     */
+    const struct wined3d_shader_version *version = &ins->ctx->shader->reg_maps.shader_version;
+
+    switch(version->type)
+    {
+    case WINED3D_SHADER_TYPE_PIXEL:
+        shader_glsl_epilogue_ps(ins->ctx);
+        break;
+    case WINED3D_SHADER_TYPE_VERTEX:
+        shader_glsl_epilogue_vs(ins->ctx);
+        break;
+    default:
+        break;
+    }
+
+    shader_addline(ins->ctx->buffer, "return;\n");
 }
 
 /*********************************************
@@ -5995,25 +6010,34 @@ static GLuint shader_glsl_generate_pshader(const struct wined3d_context *context
     /* Base Shader Body */
     shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
 
+    shader_addline(buffer, "}\n");
+
+    TRACE("Compiling shader object %u.\n", shader_id);
+    shader_glsl_compile(gl_info, shader_id, buffer->buffer);
+
+    return shader_id;
+}
+
+static void shader_glsl_epilogue_ps(const struct wined3d_shader_context *ctx)
+{
+    const struct wined3d_shader *shader = ctx->shader;
+    const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+    const struct shader_glsl_ctx_priv *priv = ctx->backend_data;
+    const struct ps_compile_args *args = priv->cur_ps_args;
+
     /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
     if (reg_maps->shader_version.major < 2)
-        shader_addline(buffer, "%s[0] = R0;\n", get_fragment_output(gl_info));
+        shader_addline(ctx->buffer, "%s[0] = R0;\n", get_fragment_output(gl_info));
 
     if (args->srgb_correction)
-        shader_glsl_generate_srgb_write_correction(buffer, gl_info);
+        shader_glsl_generate_srgb_write_correction(ctx->buffer, gl_info);
 
     /* SM < 3 does not replace the fog stage. */
     if (reg_maps->shader_version.major < 3)
-        shader_glsl_generate_fog_code(buffer, gl_info, args->fog);
-
-    shader_glsl_generate_alpha_test(buffer, gl_info, args->alpha_test_func + 1);
-
-    shader_addline(buffer, "}\n");
-
-    TRACE("Compiling shader object %u.\n", shader_id);
-    shader_glsl_compile(gl_info, shader_id, buffer->buffer);
+        shader_glsl_generate_fog_code(ctx->buffer, gl_info, args->fog);
 
-    return shader_id;
+    shader_glsl_generate_alpha_test(ctx->buffer, gl_info, args->alpha_test_func + 1);
 }
 
 /* Context activation is done by the caller. */
@@ -6024,10 +6048,8 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
     const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
     struct wined3d_string_buffer *buffer = &priv->shader_buffer;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
     const DWORD *function = shader->function;
     struct shader_glsl_ctx_priv priv_ctx;
-    unsigned int i;
 
     /* Create the hw GLSL shader program and assign it as the shader->prgId */
     GLuint shader_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
@@ -6063,8 +6085,26 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
     /* Base Shader Body */
     shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
 
+    shader_addline(buffer, "}\n");
+
+    TRACE("Compiling shader object %u.\n", shader_id);
+    shader_glsl_compile(gl_info, shader_id, buffer->buffer);
+
+    return shader_id;
+}
+
+static void shader_glsl_epilogue_vs(const struct wined3d_shader_context *ctx)
+{
+    const struct wined3d_shader *shader = ctx->shader;
+    const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+    const struct shader_glsl_ctx_priv *priv = ctx->backend_data;
+    const struct vs_compile_args *args = priv->cur_vs_args;
+    BOOL legacy_context = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT];
+    unsigned int i;
+
     /* Unpack outputs */
-    shader_addline(buffer, "setup_vs_output(vs_out);\n");
+    shader_addline(ctx->buffer, "setup_vs_output(vs_out);\n");
 
     /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
      * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
@@ -6074,10 +6114,10 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
     if (reg_maps->shader_version.major < 3)
     {
         if (args->fog_src == VS_FOG_Z)
-            shader_addline(buffer, "%s = gl_Position.z;\n",
+            shader_addline(ctx->buffer, "%s = gl_Position.z;\n",
                     legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord");
         else if (!reg_maps->fog)
-            shader_addline(buffer, "%s = 0.0;\n",
+            shader_addline(ctx->buffer, "%s = 0.0;\n",
                     legacy_context ? "gl_FogFragCoord" : "ffp_varying_fogcoord");
     }
 
@@ -6085,26 +6125,20 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
     if (args->clip_enabled)
     {
         if (legacy_context)
-            shader_addline(buffer, "gl_ClipVertex = gl_Position;\n");
+            shader_addline(ctx->buffer, "gl_ClipVertex = gl_Position;\n");
         else
             for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
-                shader_addline(buffer, "gl_ClipDistance[%u] = dot(gl_Position, clip_planes[%u]);\n", i, i);
+                shader_addline(ctx->buffer, "gl_ClipDistance[%u] = dot(gl_Position, clip_planes[%u]);\n", i, i);
     }
 
     if (args->point_size && !args->per_vertex_point_size)
-        shader_addline(buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n");
+        shader_addline(ctx->buffer, "gl_PointSize = clamp(ffp_point.size, ffp_point.size_min, ffp_point.size_max);\n");
 
     if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL && !gl_info->supported[ARB_CLIP_CONTROL])
-        shader_glsl_fixup_position(buffer);
-
-    shader_addline(buffer, "}\n");
-
-    TRACE("Compiling shader object %u.\n", shader_id);
-    shader_glsl_compile(gl_info, shader_id, buffer->buffer);
-
-    return shader_id;
+        shader_glsl_fixup_position(ctx->buffer);
 }
 
+
 /* Context activation is done by the caller. */
 static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context *context,
         struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct gs_compile_args *args)
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 61509d9..592e53b 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -2028,6 +2028,7 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_st
     struct wined3d_shader_tex_mx tex_mx;
     struct wined3d_shader_context ctx;
     const DWORD *ptr = byte_code;
+    enum WINED3D_SHADER_INSTRUCTION_HANDLER last_opcode = WINED3DSIH_TABLE_SIZE;
 
     /* Initialize current parsing state. */
     tex_mx.current_row = 0;
@@ -2062,6 +2063,16 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_st
 
         /* Call appropriate function for output target */
         device->shader_backend->shader_handle_instruction(&ins);
+        last_opcode = ins.handler_idx;
+    }
+
+    if (last_opcode != WINED3DSIH_RET)
+    {
+        /* Force a return instruction at the end of function body. */
+        memset(&ins, 0, sizeof(ins));
+        ins.ctx = &ctx;
+        ins.handler_idx = WINED3DSIH_RET;
+        device->shader_backend->shader_handle_instruction(&ins);
     }
 }
 
-- 
2.7.4




More information about the wine-patches mailing list