From 5189a4f13585f9e90e492ee10d0d110b654ccb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Wed, 18 Oct 2017 00:25:08 +0200 Subject: [PATCH] wined3d: Implement SM4+ interpolation modifiers for GLSL < 4.40. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/arb_program_shader.c | 2 +- dlls/wined3d/glsl_shader.c | 36 +++++++++-------- dlls/wined3d/shader.c | 66 +++++++++++++++++++++---------- dlls/wined3d/wined3d_private.h | 26 +++++++++--- 4 files changed, 87 insertions(+), 43 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 8f2f0e804ea..04c0d702ca6 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 911c9fed6cd..e4aa6c501ae 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 de58ade1222..2c741c80854 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; } -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) +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_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 7ffa45b2460..26bda615464 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