[PATCH 4/6] wined3d: Implement SM4+ interpolation modifiers for GLSL < 4.40.
Józef Kucia
jkucia at codeweavers.com
Tue Oct 17 17:25:08 CDT 2017
Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
dlls/wined3d/arb_program_shader.c | 2 +-
dlls/wined3d/glsl_shader.c | 36 ++++++++++++----------
dlls/wined3d/shader.c | 64 +++++++++++++++++++++++++++------------
dlls/wined3d/wined3d_private.h | 26 ++++++++++++----
4 files changed, 86 insertions(+), 42 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 8f2f0e804eac..04c0d702ca62 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -4494,7 +4494,7 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
int i;
WORD int_skip;
- find_vs_compile_args(state, shader, context->stream_info.swizzle_map, &args->super, d3d_info);
+ find_vs_compile_args(state, shader, context->stream_info.swizzle_map, &args->super, context);
args->clip.boolclip_compare = 0;
if (use_ps(state))
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 911c9fed6cd4..e4aa6c501ae0 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -2154,12 +2154,8 @@ static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_i
shader_addline(buffer, "in shader_in_out {\n");
for (i = 0; i < element_count; ++i)
{
- const char *interpolation_qualifiers = "";
- if (shader_glsl_get_version(gl_info) >= 440)
- interpolation_qualifiers = shader_glsl_interpolation_qualifiers(interpolation_mode[i]);
- else if (interpolation_mode[i] && interpolation_mode[i] != WINED3DSIM_LINEAR)
- FIXME("Unhandled interpolation mode %#x.\n", interpolation_mode[i]);
- shader_addline(buffer, "%s vec4 reg%u;\n", interpolation_qualifiers, i);
+ shader_addline(buffer, "%s vec4 reg%u;\n",
+ shader_glsl_interpolation_qualifiers(interpolation_mode[i]), i);
}
shader_addline(buffer, "} shader_in;\n");
}
@@ -2175,7 +2171,8 @@ static void shader_glsl_declare_shader_inputs(const struct wined3d_gl_info *gl_i
}
static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_info,
- struct wined3d_string_buffer *buffer, unsigned int element_count, BOOL rasterizer_setup)
+ struct wined3d_string_buffer *buffer, unsigned int element_count, BOOL rasterizer_setup,
+ const enum wined3d_shader_interpolation_mode *interpolation_mode)
{
unsigned int i;
@@ -2185,7 +2182,12 @@ static void shader_glsl_declare_shader_outputs(const struct wined3d_gl_info *gl_
{
shader_addline(buffer, "out shader_in_out {\n");
for (i = 0; i < element_count; ++i)
- shader_addline(buffer, " vec4 reg%u;\n", i);
+ {
+ const char *interpolation_qualifiers = "";
+ if (needs_interpolation_qualifiers_for_shader_outputs(gl_info))
+ interpolation_qualifiers = shader_glsl_interpolation_qualifiers(interpolation_mode[i]);
+ shader_addline(buffer, "%s vec4 reg%u;\n", interpolation_qualifiers, i);
+ }
shader_addline(buffer, "} shader_out;\n");
}
else
@@ -7044,7 +7046,7 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl
{
unsigned int in_count = min(vec4_varyings(ps_major, gl_info), ps->limits->packed_input);
- shader_glsl_declare_shader_outputs(gl_info, buffer, in_count, FALSE);
+ shader_glsl_declare_shader_outputs(gl_info, buffer, in_count, FALSE, NULL);
shader_addline(buffer, "void setup_vs_output(in vec4 outputs[%u])\n{\n", vs->limits->packed_output);
shader_glsl_setup_sm3_rasterizer_input(priv, gl_info, ps->u.ps.input_reg_map, &ps->input_signature,
&ps->reg_maps, 0, &vs->output_signature, &vs->reg_maps, per_vertex_point_size);
@@ -7061,7 +7063,8 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl
static void shader_glsl_generate_sm4_output_setup(struct shader_glsl_priv *priv,
const struct wined3d_shader *shader, unsigned int input_count,
- const struct wined3d_gl_info *gl_info, BOOL rasterizer_setup)
+ const struct wined3d_gl_info *gl_info, BOOL rasterizer_setup,
+ const enum wined3d_shader_interpolation_mode *interpolation_mode)
{
const char *prefix = shader_glsl_get_prefix(shader->reg_maps.shader_version.type);
struct wined3d_string_buffer *buffer = &priv->shader_buffer;
@@ -7070,7 +7073,7 @@ static void shader_glsl_generate_sm4_output_setup(struct shader_glsl_priv *priv,
input_count = min(vec4_varyings(4, gl_info), input_count);
if (input_count)
- shader_glsl_declare_shader_outputs(gl_info, buffer, input_count, rasterizer_setup);
+ shader_glsl_declare_shader_outputs(gl_info, buffer, input_count, rasterizer_setup, interpolation_mode);
shader_addline(buffer, "void setup_%s_output(in vec4 outputs[%u])\n{\n",
prefix, shader->limits->packed_output);
@@ -7660,7 +7663,7 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
if (reg_maps->shader_version.major >= 4)
shader_glsl_generate_sm4_output_setup(priv, shader, args->next_shader_input_count,
- gl_info, args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL);
+ gl_info, args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL, args->interpolation_mode);
shader_addline(buffer, "void main()\n{\n");
@@ -7901,7 +7904,7 @@ static GLuint shader_glsl_generate_domain_shader(const struct wined3d_context *c
shader_addline(buffer, "uniform vec4 pos_fixup;\n");
shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, gl_info,
- args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL);
+ args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL, args->interpolation_mode);
shader_glsl_generate_patch_constant_setup(buffer, &shader->patch_constant_signature, TRUE);
shader_addline(buffer, "void main()\n{\n");
@@ -7950,7 +7953,8 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
if (!gl_info->supported[ARB_CLIP_CONTROL])
shader_addline(buffer, "uniform vec4 pos_fixup;\n");
- shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count, gl_info, TRUE);
+ shader_glsl_generate_sm4_output_setup(priv, shader, args->output_count,
+ gl_info, TRUE, args->interpolation_mode);
shader_addline(buffer, "void main()\n{\n");
if (FAILED(shader_generate_code(shader, buffer, reg_maps, &priv_ctx, NULL, NULL)))
return 0;
@@ -9818,7 +9822,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
vshader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
- find_vs_compile_args(state, vshader, context->stream_info.swizzle_map, &vs_compile_args, d3d_info);
+ find_vs_compile_args(state, vshader, context->stream_info.swizzle_map, &vs_compile_args, context);
vs_id = find_glsl_vshader(context, priv, vshader, &vs_compile_args);
vs_list = &vshader->linked_programs;
}
@@ -9861,7 +9865,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
{
struct gs_compile_args args;
- find_gs_compile_args(state, gshader, &args);
+ find_gs_compile_args(state, gshader, &args, context);
gs_id = find_glsl_geometry_shader(context, priv, gshader, &args);
}
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index de58ade1222b..2c741c808548 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -3400,25 +3400,41 @@ HRESULT CDECL wined3d_shader_set_local_constants_float(struct wined3d_shader *sh
return WINED3D_OK;
}
+static void init_interpolation_compile_args(enum wined3d_shader_interpolation_mode *interpolation_args,
+ const struct wined3d_shader *pixel_shader, const struct wined3d_gl_info *gl_info)
+{
+ if (!needs_interpolation_qualifiers_for_shader_outputs(gl_info)
+ || !pixel_shader || pixel_shader->reg_maps.shader_version.major < 4)
+ {
+ memset(interpolation_args, 0, MAX_REG_INPUT * sizeof(*interpolation_args));
+ return;
+ }
+
+ memcpy(interpolation_args, pixel_shader->u.ps.interpolation_mode,
+ sizeof(pixel_shader->u.ps.interpolation_mode));
+}
+
void find_vs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
- WORD swizzle_map, struct vs_compile_args *args, const struct wined3d_d3d_info *d3d_info)
+ WORD swizzle_map, struct vs_compile_args *args, const struct wined3d_context *context)
{
+ const struct wined3d_shader *geometry_shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
+ const struct wined3d_shader *pixel_shader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
+ const struct wined3d_shader *hull_shader = state->shader[WINED3D_SHADER_TYPE_HULL];
+ const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+
args->fog_src = state->render_states[WINED3D_RS_FOGTABLEMODE]
== WINED3D_FOG_NONE ? VS_FOG_COORD : VS_FOG_Z;
args->clip_enabled = state->render_states[WINED3D_RS_CLIPPING]
&& state->render_states[WINED3D_RS_CLIPPLANEENABLE];
args->point_size = state->gl_primitive_type == GL_POINTS;
args->per_vertex_point_size = shader->reg_maps.point_size;
- args->next_shader_type = state->shader[WINED3D_SHADER_TYPE_HULL] ? WINED3D_SHADER_TYPE_HULL
- : state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ? WINED3D_SHADER_TYPE_GEOMETRY
- : WINED3D_SHADER_TYPE_PIXEL;
+ args->next_shader_type = hull_shader? WINED3D_SHADER_TYPE_HULL
+ : geometry_shader ? WINED3D_SHADER_TYPE_GEOMETRY : WINED3D_SHADER_TYPE_PIXEL;
if (shader->reg_maps.shader_version.major >= 4)
- args->next_shader_input_count = state->shader[WINED3D_SHADER_TYPE_HULL]
- ? state->shader[WINED3D_SHADER_TYPE_HULL]->limits->packed_input
- : state->shader[WINED3D_SHADER_TYPE_GEOMETRY]
- ? state->shader[WINED3D_SHADER_TYPE_GEOMETRY]->limits->packed_input
- : state->shader[WINED3D_SHADER_TYPE_PIXEL]
- ? state->shader[WINED3D_SHADER_TYPE_PIXEL]->limits->packed_input : 0;
+ args->next_shader_input_count = hull_shader ? hull_shader->limits->packed_input
+ : geometry_shader ? geometry_shader->limits->packed_input
+ : pixel_shader ? pixel_shader->limits->packed_input : 0;
else
args->next_shader_input_count = 0;
args->swizzle_map = swizzle_map;
@@ -3426,6 +3442,9 @@ void find_vs_compile_args(const struct wined3d_state *state, const struct wined3
args->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
else
args->flatshading = 0;
+
+ init_interpolation_compile_args(args->interpolation_mode,
+ args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL ? pixel_shader : NULL, gl_info);
}
static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2)
@@ -3695,28 +3714,35 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3
void find_ds_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
struct ds_compile_args *args, const struct wined3d_context *context)
{
+ const struct wined3d_shader *geometry_shader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY];
+ const struct wined3d_shader *pixel_shader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
const struct wined3d_shader *hull_shader = state->shader[WINED3D_SHADER_TYPE_HULL];
+ const struct wined3d_gl_info *gl_info = context->gl_info;
args->tessellator_output_primitive = hull_shader->u.hs.tessellator_output_primitive;
args->tessellator_partitioning = hull_shader->u.hs.tessellator_partitioning;
- args->output_count = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ?
- state->shader[WINED3D_SHADER_TYPE_GEOMETRY]->limits->packed_input :
- state->shader[WINED3D_SHADER_TYPE_PIXEL] ? state->shader[WINED3D_SHADER_TYPE_PIXEL]->limits->packed_input
- : shader->limits->packed_output;
- args->next_shader_type = state->shader[WINED3D_SHADER_TYPE_GEOMETRY] ? WINED3D_SHADER_TYPE_GEOMETRY
- : WINED3D_SHADER_TYPE_PIXEL;
+ args->output_count = geometry_shader ? geometry_shader->limits->packed_input
+ : pixel_shader ? pixel_shader->limits->packed_input : shader->limits->packed_output;
+ args->next_shader_type = geometry_shader ? WINED3D_SHADER_TYPE_GEOMETRY : WINED3D_SHADER_TYPE_PIXEL;
args->render_offscreen = context->render_offscreen;
+ init_interpolation_compile_args(args->interpolation_mode,
+ args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL ? pixel_shader : NULL, gl_info);
+
args->padding = 0;
}
void find_gs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
- struct gs_compile_args *args)
+ struct gs_compile_args *args, const struct wined3d_context *context)
{
- args->output_count = state->shader[WINED3D_SHADER_TYPE_PIXEL]
- ? state->shader[WINED3D_SHADER_TYPE_PIXEL]->limits->packed_input : shader->limits->packed_output;
+ const struct wined3d_shader *pixel_shader = state->shader[WINED3D_SHADER_TYPE_PIXEL];
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+
+ args->output_count = pixel_shader ? pixel_shader->limits->packed_input : shader->limits->packed_output;
+
+ init_interpolation_compile_args(args->interpolation_mode, pixel_shader, gl_info);
}
void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 7ffa45b2460c..26bda6154648 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -61,6 +61,8 @@
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#endif
+#define MAKEDWORD_VERSION(maj, min) (((maj & 0xffffu) << 16) | (min & 0xffffu))
+
/* Driver quirks */
#define WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT 0x00000001
#define WINED3D_QUIRK_SET_TEXCOORD_W 0x00000002
@@ -1323,7 +1325,8 @@ enum wined3d_shader_tex_types
WINED3D_SHADER_TEX_CUBE = 2,
};
-struct ps_compile_args {
+struct ps_compile_args
+{
struct color_fixup_desc color_fixup[MAX_FRAGMENT_SAMPLERS];
enum vertexprocessing_mode vp_mode;
enum wined3d_ffp_ps_fog_mode fog;
@@ -1343,7 +1346,8 @@ struct ps_compile_args {
DWORD padding : 26;
};
-enum fog_src_type {
+enum fog_src_type
+{
VS_FOG_Z = 0,
VS_FOG_COORD = 1
};
@@ -1359,6 +1363,7 @@ struct vs_compile_args
BYTE padding : 1;
WORD swizzle_map; /* MAX_ATTRIBS, 16 */
unsigned int next_shader_input_count;
+ enum wined3d_shader_interpolation_mode interpolation_mode[MAX_REG_INPUT];
};
struct ds_compile_args
@@ -1369,11 +1374,13 @@ struct ds_compile_args
unsigned int next_shader_type : 3;
unsigned int render_offscreen : 1;
unsigned int padding : 12;
+ enum wined3d_shader_interpolation_mode interpolation_mode[MAX_REG_INPUT];
};
struct gs_compile_args
{
unsigned int output_count;
+ enum wined3d_shader_interpolation_mode interpolation_mode[MAX_REG_INPUT];
};
struct wined3d_context;
@@ -3970,13 +3977,13 @@ BOOL vshader_get_input(const struct wined3d_shader *shader,
BYTE usage_req, BYTE usage_idx_req, unsigned int *regnum) DECLSPEC_HIDDEN;
void find_vs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
WORD swizzle_map, struct vs_compile_args *args,
- const struct wined3d_d3d_info *d3d_info) DECLSPEC_HIDDEN;
+ const struct wined3d_context *context) DECLSPEC_HIDDEN;
void find_ds_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
struct ds_compile_args *args, const struct wined3d_context *context) DECLSPEC_HIDDEN;
void find_gs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
- struct gs_compile_args *args) DECLSPEC_HIDDEN;
+ struct gs_compile_args *args, const struct wined3d_context *context) DECLSPEC_HIDDEN;
void string_buffer_clear(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN;
BOOL string_buffer_init(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN;
@@ -4277,6 +4284,15 @@ static inline BOOL can_use_texture_swizzle(const struct wined3d_gl_info *gl_info
&& !is_scaling_fixup(format->color_fixup);
}
+static inline BOOL needs_interpolation_qualifiers_for_shader_outputs(const struct wined3d_gl_info *gl_info)
+{
+ /* In GLSL 4.40+ it is fine to specify interpolation qualifiers only in
+ * fragment shaders. In older GLSL versions interpolation qualifiers must
+ * match between shader stages.
+ */
+ return gl_info->glsl_version < MAKEDWORD_VERSION(4, 40);
+}
+
static inline struct wined3d_surface *context_get_rt_surface(const struct wined3d_context *context)
{
struct wined3d_texture *texture = context->current_rt.texture;
@@ -4300,6 +4316,4 @@ static inline void wined3d_not_from_cs(struct wined3d_cs *cs)
/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
-#define MAKEDWORD_VERSION(maj, min) (((maj & 0xffffu) << 16) | (min & 0xffffu))
-
#endif
--
2.13.6
More information about the wine-patches
mailing list