From 4189d297760166951641baf6172a1ef708863855 Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Thu, 11 Jun 2015 23:13:42 +0200 Subject: [PATCH] wined3d: Avoid the builtin GLSL vertex attributes. --- dlls/wined3d/directx.c | 1 + dlls/wined3d/drawprim.c | 6 +- dlls/wined3d/glsl_shader.c | 114 +++++++++++++++++++++++---------- dlls/wined3d/state.c | 11 +++- dlls/wined3d/utils.c | 6 +- dlls/wined3d/wined3d_private.h | 5 +- 6 files changed, 100 insertions(+), 43 deletions(-) diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index af3251c55de..f238fc0ccff 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -3562,6 +3562,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) adapter->vertex_pipe->vp_get_caps(gl_info, &vertex_caps); adapter->d3d_info.xyzrhw = vertex_caps.xyzrhw; + adapter->d3d_info.ffp_generic_attributes = vertex_caps.ffp_generic_attributes; adapter->fragment_pipe->get_caps(gl_info, &fragment_caps); adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages; diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index c0654a615d2..7a6a6e95b7a 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -761,8 +761,12 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co } else { - drawStridedSlow(device, context, stream_info, index_count, + if (context->d3d_info->ffp_generic_attributes) + drawStridedSlowVs(context, state, stream_info, index_count, state->gl_primitive_type, idx_data, idx_size, start_idx); + else + drawStridedSlow(device, context, stream_info, index_count, + state->gl_primitive_type, idx_data, idx_size, start_idx); } } else if (!gl_info->supported[ARB_INSTANCED_ARRAYS] && instance_count) diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 5ba246ed793..f69a2ce59eb 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -5505,9 +5505,9 @@ static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, c case WINED3D_MCS_MATERIAL: return material; case WINED3D_MCS_COLOR1: - return "gl_Color"; + return "ffp_attrib_diffuse"; case WINED3D_MCS_COLOR2: - return "gl_SecondaryColor"; + return "ffp_attrib_specular"; default: ERR("Invalid material color source %#x.\n", mcs); return ""; @@ -5524,8 +5524,8 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer if (!settings->lighting) { - shader_addline(buffer, "gl_FrontColor = gl_Color;\n"); - shader_addline(buffer, "gl_FrontSecondaryColor = gl_SecondaryColor;\n"); + shader_addline(buffer, "gl_FrontColor = ffp_attrib_diffuse;\n"); + shader_addline(buffer, "gl_FrontSecondaryColor = ffp_attrib_specular;\n"); return; } @@ -5678,6 +5678,22 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info, BOOL legacy_lighting) { + static const struct attrib_info + { + const char type[6]; + const char name[20]; + } + attrib_info[] = + { + {"vec4", "ffp_attrib_position"}, /* WINED3D_FFP_POSITION */ + /* TODO: Vertex blending */ + {"vec4", ""}, /* WINED3D_FFP_BLENDWEIGHT */ + {"float", ""}, /* WINED3D_FFP_BLENDINDICES */ + {"vec3", "ffp_attrib_normal"}, /* WINED3D_FFP_NORMAL */ + {"float", "ffp_attrib_psize"}, /* WINED3D_FFP_PSIZE */ + {"vec4", "ffp_attrib_diffuse"}, /* WINED3D_FFP_DIFFUSE */ + {"vec4", "ffp_attrib_specular"}, /* WINED3D_FFP_SPECULAR */ + }; GLuint shader_obj; unsigned int i; @@ -5686,6 +5702,14 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe shader_addline(buffer, "#version 120\n"); shader_addline(buffer, "\n"); + for (i = 0; i < WINED3D_FFP_ATTRIBS_COUNT; ++i) + { + const char *type = i < ARRAY_SIZE(attrib_info) ? attrib_info[i].type : "vec4"; + + shader_addline(buffer, "attribute %s vs_in%u;\n", type, i); + } + shader_addline(buffer, "\n"); + shader_addline(buffer, "uniform mat4 ffp_modelview_matrix;\n"); shader_addline(buffer, "uniform mat4 ffp_projection_matrix;\n"); shader_addline(buffer, "uniform mat3 ffp_normal_matrix;\n"); @@ -5731,15 +5755,30 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe shader_addline(buffer, "float m;\n"); shader_addline(buffer, "vec3 r;\n"); + for (i = 0; i < ARRAY_SIZE(attrib_info); ++i) + { + if (attrib_info[i].name[0]) + shader_addline(buffer, "%s %s = vs_in%u;\n", + attrib_info[i].type, attrib_info[i].name, i); + } + for (i = 0; i < MAX_TEXTURES; ++i) + { + unsigned int coord_idx = settings->texgen[i] & 0x0000ffff; + if ((settings->texgen[i] & 0xffff0000) == WINED3DTSS_TCI_PASSTHRU) + { + shader_addline(buffer, "vec4 ffp_attrib_texcoord%u = vs_in%u;\n", i, coord_idx + WINED3D_FFP_TEXCOORD0); + } + } + if (settings->transformed) { - shader_addline(buffer, "vec4 ec_pos = vec4(gl_Vertex.xyz, 1.0);\n"); + shader_addline(buffer, "vec4 ec_pos = vec4(ffp_attrib_position.xyz, 1.0);\n"); shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); - shader_addline(buffer, "if (gl_Vertex.w != 0.0) gl_Position /= gl_Vertex.w;\n"); + shader_addline(buffer, "if (ffp_attrib_position.w != 0.0) gl_Position /= ffp_attrib_position.w;\n"); } else { - shader_addline(buffer, "vec4 ec_pos = ffp_modelview_matrix * gl_Vertex;\n"); + shader_addline(buffer, "vec4 ec_pos = ffp_modelview_matrix * ffp_attrib_position;\n"); shader_addline(buffer, "gl_Position = ffp_projection_matrix * ec_pos;\n"); if (settings->clipping) shader_addline(buffer, "gl_ClipVertex = ec_pos;\n"); @@ -5749,19 +5788,19 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe if (!settings->normal) shader_addline(buffer, "vec3 normal = vec3(0.0);\n"); else if (settings->normalize) - shader_addline(buffer, "vec3 normal = normalize(ffp_normal_matrix * gl_Normal);\n"); + shader_addline(buffer, "vec3 normal = normalize(ffp_normal_matrix * ffp_attrib_normal);\n"); else - shader_addline(buffer, "vec3 normal = ffp_normal_matrix * gl_Normal;\n"); + shader_addline(buffer, "vec3 normal = ffp_normal_matrix * ffp_attrib_normal;\n"); shader_glsl_ffp_vertex_lighting(buffer, settings, gl_info, legacy_lighting); for (i = 0; i < MAX_TEXTURES; ++i) { - switch (settings->texgen[i] << WINED3D_FFP_TCI_SHIFT) + switch (settings->texgen[i] & 0xffff0000) { case WINED3DTSS_TCI_PASSTHRU: if (settings->texcoords & (1 << i)) - shader_addline(buffer, "gl_TexCoord[%u] = ffp_texture_matrix[%u] * gl_MultiTexCoord%d;\n", + shader_addline(buffer, "gl_TexCoord[%u] = ffp_texture_matrix[%u] * ffp_attrib_texcoord%u;\n", i, i, i); break; @@ -5797,7 +5836,7 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe break; case WINED3D_FFP_VS_FOG_FOGCOORD: - shader_addline(buffer, "gl_FogFragCoord = gl_SecondaryColor.w * 255.0;\n"); + shader_addline(buffer, "gl_FogFragCoord = ffp_attrib_specular.w * 255.0;\n"); break; case WINED3D_FFP_VS_FOG_RANGE: @@ -6668,6 +6707,8 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const GLuint gs_id = 0; GLuint ps_id = 0; struct list *ps_list, *vs_list; + WORD attribs_map; + struct wined3d_string_buffer *tmp_name; if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_VERTEX))) { @@ -6773,9 +6814,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const if (vshader) { - WORD map = vshader->reg_maps.input_registers; - struct wined3d_string_buffer *tmp_name = string_buffer_get(&priv->string_buffers); - + attribs_map = vshader->reg_maps.input_registers; reorder_shader_id = generate_param_reorder_function(priv, vshader, pshader, state->gl_primitive_type == GL_POINTS && vshader->reg_maps.point_size, gl_info); TRACE("Attaching GLSL shader object %u to program %u.\n", reorder_shader_id, program_id); @@ -6785,26 +6824,32 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const * is destroyed */ GL_EXTCALL(glDeleteShader(reorder_shader_id)); - - /* Bind vertex attributes to a corresponding index number to match - * the same index numbers as ARB_vertex_programs (makes loading - * vertex attributes simpler). With this method, we can use the - * exact same code to load the attributes later for both ARB and - * GLSL shaders. - * - * We have to do this here because we need to know the Program ID - * in order to make the bindings work, and it has to be done prior - * to linking the GLSL program. */ - for (i = 0; map; map >>= 1, ++i) - { - if (!(map & 1)) continue; - - string_buffer_sprintf(tmp_name, "vs_in%u", i); - GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer)); - } - checkGLcall("glBindAttribLocation"); - string_buffer_release(&priv->string_buffers, tmp_name); } + else + { + attribs_map = (1 << WINED3D_FFP_ATTRIBS_COUNT) - 1; + } + + /* Bind vertex attributes to a corresponding index number to match + * the same index numbers as ARB_vertex_programs (makes loading + * vertex attributes simpler). With this method, we can use the + * exact same code to load the attributes later for both ARB and + * GLSL shaders. + * + * We have to do this here because we need to know the Program ID + * in order to make the bindings work, and it has to be done prior + * to linking the GLSL program. */ + tmp_name = string_buffer_get(&priv->string_buffers); + for (i = 0; attribs_map; attribs_map >>= 1, ++i) + { + if (!(attribs_map & 1)) + continue; + + string_buffer_sprintf(tmp_name, "vs_in%u", i); + GL_EXTCALL(glBindAttribLocation(program_id, i, tmp_name->buffer)); + } + checkGLcall("glBindAttribLocation"); + string_buffer_release(&priv->string_buffers, tmp_name); if (gshader) { @@ -7753,6 +7798,7 @@ static void glsl_vertex_pipe_vp_enable(const struct wined3d_gl_info *gl_info, BO static void glsl_vertex_pipe_vp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps) { caps->xyzrhw = TRUE; + caps->ffp_generic_attributes = TRUE; caps->max_active_lights = MAX_ACTIVE_LIGHTS; caps->max_vertex_blend_matrices = 1; caps->max_vertex_blend_matrix_index = 0; diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index b7d7f92189f..67558fd67d5 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -3963,7 +3963,9 @@ static void load_numbered_arrays(struct wined3d_context *context, { if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i); - if (state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.input_registers & (1 << i)) + if (!use_vs(state) && i == WINED3D_FFP_DIFFUSE) + GL_EXTCALL(glVertexAttrib4f(i, 1.0f, 1.0f, 1.0f, 1.0f)); + else GL_EXTCALL(glVertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 0.0f)); continue; } @@ -4370,8 +4372,10 @@ static void load_vertex_data(struct wined3d_context *context, static void streamsrc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - BOOL load_numbered = use_vs(state) && !context->use_immediate_mode_draw; - BOOL load_named = !use_vs(state) && !context->use_immediate_mode_draw; + BOOL load_numbered = context->d3d_info->ffp_generic_attributes + || (use_vs(state) && !context->use_immediate_mode_draw); + BOOL load_named = !context->d3d_info->ffp_generic_attributes + && !use_vs(state) && !context->use_immediate_mode_draw; if (isStateDirty(context, STATE_VDECL)) return; if (context->numberedArraysLoaded && !load_numbered) @@ -5572,6 +5576,7 @@ static void ffp_free(struct wined3d_device *device) {} static void vp_ffp_get_caps(const struct wined3d_gl_info *gl_info, struct wined3d_vertex_caps *caps) { caps->xyzrhw = FALSE; + caps->ffp_generic_attributes = FALSE; caps->max_active_lights = gl_info->limits.lights; caps->max_vertex_blend_matrices = gl_info->limits.blends; caps->max_vertex_blend_matrix_index = 0; diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 44ba7ad8f7b..42df5e6286d 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -4526,8 +4526,7 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX]; if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx)))) settings->texcoords |= 1 << i; - settings->texgen[i] = (state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT) - & WINED3D_FFP_TCI_MASK; + settings->texgen[i] = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX]; } return; } @@ -4562,8 +4561,7 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_state *state, const struct coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX]; if (coord_idx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coord_idx)))) settings->texcoords |= 1 << i; - settings->texgen[i] = (state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT) - & WINED3D_FFP_TCI_MASK; + settings->texgen[i] = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX]; } settings->light_type = 0; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9bdd9da691d..9dd944366f8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -948,6 +948,7 @@ enum wined3d_ffp_idx WINED3D_FFP_TEXCOORD5 = 12, WINED3D_FFP_TEXCOORD6 = 13, WINED3D_FFP_TEXCOORD7 = 14, + WINED3D_FFP_ATTRIBS_COUNT = 15, }; enum wined3d_ffp_emit_idx @@ -1301,6 +1302,7 @@ struct fragment_pipeline struct wined3d_vertex_caps { BOOL xyzrhw; + BOOL ffp_generic_attributes; DWORD max_active_lights; DWORD max_vertex_blend_matrices; DWORD max_vertex_blend_matrix_index; @@ -1761,6 +1763,7 @@ struct wined3d_d3d_info struct wined3d_d3d_limits limits; struct wined3d_ffp_attrib_ops ffp_attrib_ops; BOOL xyzrhw; + BOOL ffp_generic_attributes; BOOL vs_clipping; BOOL shader_color_key; DWORD valid_rt_mask; @@ -1896,7 +1899,7 @@ struct wined3d_ffp_vs_settings DWORD ortho_fog : 1; DWORD padding : 14; - BYTE texgen[MAX_TEXTURES]; + DWORD texgen[MAX_TEXTURES]; }; struct wined3d_ffp_vs_desc