[17/23] wined3d: Implement return instruction.
Andrew Wesie
awesie at gmail.com
Sun Nov 13 12:35:17 CST 2016
The return instruction can come at any point in the shader, and it
may be in a conditional or loop. Instead of ignoring the return,
add a return instruction in the output, as well as the necessary
prologue.
Signed-off-by: Andrew Wesie <awesie at gmail.com>
---
dlls/wined3d/glsl_shader.c | 94 +++++++++++++++++++++++++++++++---------------
1 file changed, 64 insertions(+), 30 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index b94ea33..df7bd3b 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -271,6 +271,9 @@ struct glsl_ffp_destroy_ctx
const struct wined3d_gl_info *gl_info;
};
+static void shader_glsl_prologue_ps(const struct wined3d_shader_context *ctx);
+static void shader_glsl_prologue_vs(const struct wined3d_shader_context *ctx);
+
static const char *debug_gl_shader_type(GLenum type)
{
switch (type)
@@ -4470,9 +4473,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_prologue_ps(ins->ctx);
+ break;
+ case WINED3D_SHADER_TYPE_VERTEX:
+ shader_glsl_prologue_vs(ins->ctx);
+ break;
+ default:
+ break;
+ }
+
+ shader_addline(ins->ctx->buffer, "return;\n");
}
/*********************************************
@@ -6011,25 +6026,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_prologue_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. */
@@ -6040,10 +6064,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));
@@ -6079,8 +6101,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_prologue_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),
@@ -6090,10 +6130,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");
}
@@ -6101,26 +6141,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)
--
2.7.4
More information about the wine-patches
mailing list