[PATCH 5/5] wined3d: Only store light type counts in struct wined3d_ffp_vs_settings.
Henri Verbeet
hverbeet at codeweavers.com
Thu Jan 26 06:25:21 CST 2017
The ordering doesn't matter, so this avoids creating some redundant shader
variants.
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/wined3d/glsl_shader.c | 308 ++++++++++++++++++++++++-----------------
dlls/wined3d/utils.c | 24 +++-
dlls/wined3d/wined3d_private.h | 12 +-
3 files changed, 207 insertions(+), 137 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 7196cc6..3cdc957 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -1278,15 +1278,12 @@ static void multiply_vector_matrix(struct wined3d_vec4 *dest, const struct wined
}
static void shader_glsl_ffp_vertex_light_uniform(const struct wined3d_context *context,
- const struct wined3d_state *state, unsigned int light, struct glsl_shader_prog_link *prog)
+ const struct wined3d_state *state, unsigned int light, const struct wined3d_light_info *light_info,
+ struct glsl_shader_prog_link *prog)
{
+ const struct wined3d_matrix *view = &state->transforms[WINED3D_TS_VIEW];
const struct wined3d_gl_info *gl_info = context->gl_info;
- const struct wined3d_light_info *light_info = state->lights[light];
struct wined3d_vec4 vec4;
- const struct wined3d_matrix *view = &state->transforms[WINED3D_TS_VIEW];
-
- if (!light_info)
- return;
GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].diffuse, 1, &light_info->OriginalParms.diffuse.r));
GL_EXTCALL(glUniform4fv(prog->vs.light_location[light].specular, 1, &light_info->OriginalParms.specular.r));
@@ -1510,9 +1507,70 @@ static void shader_glsl_load_constants(void *shader_priv, struct wined3d_context
if (update_mask & WINED3D_SHADER_CONST_FFP_LIGHTS)
{
+ unsigned int point_idx, spot_idx, directional_idx, parallel_point_idx;
+ DWORD point_count = 0;
+ DWORD spot_count = 0;
+ DWORD directional_count = 0;
+ DWORD parallel_point_count = 0;
+
+ for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
+ {
+ if (!state->lights[i])
+ continue;
+
+ switch (state->lights[i]->OriginalParms.type)
+ {
+ case WINED3D_LIGHT_POINT:
+ ++point_count;
+ break;
+ case WINED3D_LIGHT_SPOT:
+ ++spot_count;
+ break;
+ case WINED3D_LIGHT_DIRECTIONAL:
+ ++directional_count;
+ break;
+ case WINED3D_LIGHT_PARALLELPOINT:
+ ++parallel_point_count;
+ break;
+ default:
+ FIXME("Unhandled light type %#x.\n", state->lights[i]->OriginalParms.type);
+ break;
+ }
+ }
+ point_idx = 0;
+ spot_idx = point_idx + point_count;
+ directional_idx = spot_idx + spot_count;
+ parallel_point_idx = directional_idx + directional_count;
+
shader_glsl_ffp_vertex_lightambient_uniform(context, state, prog);
for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
- shader_glsl_ffp_vertex_light_uniform(context, state, i, prog);
+ {
+ const struct wined3d_light_info *light_info = state->lights[i];
+ unsigned int idx;
+
+ if (!light_info)
+ continue;
+
+ switch (light_info->OriginalParms.type)
+ {
+ case WINED3D_LIGHT_POINT:
+ idx = point_idx++;
+ break;
+ case WINED3D_LIGHT_SPOT:
+ idx = spot_idx++;
+ break;
+ case WINED3D_LIGHT_DIRECTIONAL:
+ idx = directional_idx++;
+ break;
+ case WINED3D_LIGHT_PARALLELPOINT:
+ idx = parallel_point_idx++;
+ break;
+ default:
+ FIXME("Unhandled light type %#x.\n", light_info->OriginalParms.type);
+ continue;
+ }
+ shader_glsl_ffp_vertex_light_uniform(context, state, idx, light_info, prog);
+ }
}
if (update_mask & WINED3D_SHADER_CONST_PS_F)
@@ -6599,8 +6657,7 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
const struct wined3d_ffp_vs_settings *settings, BOOL legacy_lighting)
{
const char *diffuse, *specular, *emissive, *ambient;
- enum wined3d_light_type light_type;
- unsigned int i;
+ unsigned int i, idx;
if (!settings->lighting)
{
@@ -6620,131 +6677,124 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
specular = shader_glsl_ffp_mcs(settings->specular_source, "ffp_material.specular");
emissive = shader_glsl_ffp_mcs(settings->emissive_source, "ffp_material.emissive");
- for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
+ idx = 0;
+ for (i = 0; i < settings->point_light_count; ++i, ++idx)
{
- light_type = (settings->light_type >> WINED3D_FFP_LIGHT_TYPE_SHIFT(i)) & WINED3D_FFP_LIGHT_TYPE_MASK;
- switch (light_type)
+ shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", idx);
+ shader_addline(buffer, "dst.z = dot(dir, dir);\n");
+ shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
+ shader_addline(buffer, "dst.x = 1.0;\n");
+ if (legacy_lighting)
{
- case WINED3D_LIGHT_POINT:
- shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", i);
- shader_addline(buffer, "dst.z = dot(dir, dir);\n");
- shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
- shader_addline(buffer, "dst.x = 1.0;\n");
- if (legacy_lighting)
- {
- shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", i, i);
- shader_addline(buffer, "dst.z = dst.y * dst.y;\n");
- }
- else
- {
- shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", i);
- }
- shader_addline(buffer, "att = dot(dst.xyz, vec3(ffp_light[%u].c_att,"
- " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", i, i, i);
- if (!legacy_lighting)
- shader_addline(buffer, "att = 1.0 / att;\n");
- shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", i);
- if (!settings->normal)
- {
- if (!legacy_lighting)
- shader_addline(buffer, "}\n");
- break;
- }
- shader_addline(buffer, "dir = normalize(dir);\n");
- shader_addline(buffer, "diffuse += (clamp(dot(dir, normal), 0.0, 1.0)"
- " * ffp_light[%u].diffuse.xyz) * att;\n", i);
- if (settings->localviewer)
- shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
- else
- shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
- shader_addline(buffer, "if (t > 0.0) specular += (pow(t, ffp_material.shininess)"
- " * ffp_light[%u].specular) * att;\n", i);
- if (!legacy_lighting)
- shader_addline(buffer, "}\n");
- break;
-
- case WINED3D_LIGHT_SPOT:
- shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", i);
- shader_addline(buffer, "dst.z = dot(dir, dir);\n");
- shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
- shader_addline(buffer, "dst.x = 1.0;\n");
- if (legacy_lighting)
- {
- shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", i, i);
- shader_addline(buffer, "dst.z = dst.y * dst.y;\n");
- }
- else
- {
- shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", i);
- }
- shader_addline(buffer, "dir = normalize(dir);\n");
- shader_addline(buffer, "t = dot(-dir, normalize(ffp_light[%u].direction));\n", i);
- shader_addline(buffer, "if (t > ffp_light[%u].cos_htheta) att = 1.0;\n", i);
- shader_addline(buffer, "else if (t <= ffp_light[%u].cos_hphi) att = 0.0;\n", i);
- shader_addline(buffer, "else att = pow((t - ffp_light[%u].cos_hphi)"
- " / (ffp_light[%u].cos_htheta - ffp_light[%u].cos_hphi), ffp_light[%u].falloff);\n",
- i, i, i, i);
- if (legacy_lighting)
- shader_addline(buffer, "att *= dot(dst.xyz, vec3(ffp_light[%u].c_att,"
- " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
- i, i, i);
- else
- shader_addline(buffer, "att /= dot(dst.xyz, vec3(ffp_light[%u].c_att,"
- " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
- i, i, i);
- shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", i);
- if (!settings->normal)
- {
- if (!legacy_lighting)
- shader_addline(buffer, "}\n");
- break;
- }
- shader_addline(buffer, "diffuse += (clamp(dot(dir, normal), 0.0, 1.0)"
- " * ffp_light[%u].diffuse.xyz) * att;\n", i);
- if (settings->localviewer)
- shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
- else
- shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
- shader_addline(buffer, "if (t > 0.0) specular += (pow(t, ffp_material.shininess)"
- " * ffp_light[%u].specular) * att;\n", i);
- if (!legacy_lighting)
- shader_addline(buffer, "}\n");
- break;
+ shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", idx, idx);
+ shader_addline(buffer, "dst.z = dst.y * dst.y;\n");
+ }
+ else
+ {
+ shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", idx);
+ }
+ shader_addline(buffer, "att = dot(dst.xyz, vec3(ffp_light[%u].c_att,"
+ " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", idx, idx, idx);
+ if (!legacy_lighting)
+ shader_addline(buffer, "att = 1.0 / att;\n");
+ shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", idx);
+ if (!settings->normal)
+ {
+ if (!legacy_lighting)
+ shader_addline(buffer, "}\n");
+ continue;
+ }
+ shader_addline(buffer, "dir = normalize(dir);\n");
+ shader_addline(buffer, "diffuse += (clamp(dot(dir, normal), 0.0, 1.0)"
+ " * ffp_light[%u].diffuse.xyz) * att;\n", idx);
+ if (settings->localviewer)
+ shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+ else
+ shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
+ shader_addline(buffer, "if (t > 0.0) specular += (pow(t, ffp_material.shininess)"
+ " * ffp_light[%u].specular) * att;\n", idx);
+ if (!legacy_lighting)
+ shader_addline(buffer, "}\n");
+ }
- case WINED3D_LIGHT_DIRECTIONAL:
- shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", i);
- if (!settings->normal)
- break;
- shader_addline(buffer, "dir = normalize(ffp_light[%u].direction.xyz);\n", i);
- shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)"
- " * ffp_light[%u].diffuse.xyz;\n", i);
- /* TODO: In the non-local viewer case the halfvector is constant
- * and could be precomputed and stored in a uniform. */
- if (settings->localviewer)
- shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
- else
- shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
- shader_addline(buffer, "if (t > 0.0) specular += pow(t, ffp_material.shininess)"
- " * ffp_light[%u].specular;\n", i);
- break;
+ for (i = 0; i < settings->spot_light_count; ++i, ++idx)
+ {
+ shader_addline(buffer, "dir = ffp_light[%u].position.xyz - ec_pos.xyz;\n", idx);
+ shader_addline(buffer, "dst.z = dot(dir, dir);\n");
+ shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
+ shader_addline(buffer, "dst.x = 1.0;\n");
+ if (legacy_lighting)
+ {
+ shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", idx, idx);
+ shader_addline(buffer, "dst.z = dst.y * dst.y;\n");
+ }
+ else
+ {
+ shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", idx);
+ }
+ shader_addline(buffer, "dir = normalize(dir);\n");
+ shader_addline(buffer, "t = dot(-dir, normalize(ffp_light[%u].direction));\n", idx);
+ shader_addline(buffer, "if (t > ffp_light[%u].cos_htheta) att = 1.0;\n", idx);
+ shader_addline(buffer, "else if (t <= ffp_light[%u].cos_hphi) att = 0.0;\n", idx);
+ shader_addline(buffer, "else att = pow((t - ffp_light[%u].cos_hphi)"
+ " / (ffp_light[%u].cos_htheta - ffp_light[%u].cos_hphi), ffp_light[%u].falloff);\n",
+ idx, idx, idx, idx);
+ if (legacy_lighting)
+ shader_addline(buffer, "att *= dot(dst.xyz, vec3(ffp_light[%u].c_att,"
+ " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
+ idx, idx, idx);
+ else
+ shader_addline(buffer, "att /= dot(dst.xyz, vec3(ffp_light[%u].c_att,"
+ " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
+ idx, idx, idx);
+ shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", idx);
+ if (!settings->normal)
+ {
+ if (!legacy_lighting)
+ shader_addline(buffer, "}\n");
+ continue;
+ }
+ shader_addline(buffer, "diffuse += (clamp(dot(dir, normal), 0.0, 1.0)"
+ " * ffp_light[%u].diffuse.xyz) * att;\n", idx);
+ if (settings->localviewer)
+ shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+ else
+ shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
+ shader_addline(buffer, "if (t > 0.0) specular += (pow(t, ffp_material.shininess)"
+ " * ffp_light[%u].specular) * att;\n", idx);
+ if (!legacy_lighting)
+ shader_addline(buffer, "}\n");
+ }
- case WINED3D_LIGHT_PARALLELPOINT:
- shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", i);
- if (!settings->normal)
- break;
- shader_addline(buffer, "dir = normalize(ffp_light[%u].position.xyz);\n", i);
- shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)"
- " * ffp_light[%u].diffuse.xyz;\n", i);
- shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
- shader_addline(buffer, "if (t > 0.0) specular += pow(t, ffp_material.shininess)"
- " * ffp_light[%u].specular;\n", i);
- break;
+ for (i = 0; i < settings->directional_light_count; ++i, ++idx)
+ {
+ shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx);
+ if (!settings->normal)
+ continue;
+ shader_addline(buffer, "dir = normalize(ffp_light[%u].direction.xyz);\n", idx);
+ shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)"
+ " * ffp_light[%u].diffuse.xyz;\n", idx);
+ /* TODO: In the non-local viewer case the halfvector is constant
+ * and could be precomputed and stored in a uniform. */
+ if (settings->localviewer)
+ shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+ else
+ shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
+ shader_addline(buffer, "if (t > 0.0) specular += pow(t, ffp_material.shininess)"
+ " * ffp_light[%u].specular;\n", idx);
+ }
- default:
- if (light_type)
- FIXME("Unhandled light type %#x.\n", light_type);
- continue;
- }
+ for (i = 0; i < settings->parallel_point_light_count; ++i, ++idx)
+ {
+ shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx);
+ if (!settings->normal)
+ continue;
+ shader_addline(buffer, "dir = normalize(ffp_light[%u].position.xyz);\n", idx);
+ shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)"
+ " * ffp_light[%u].diffuse.xyz;\n", idx);
+ shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+ shader_addline(buffer, "if (t > 0.0) specular += pow(t, ffp_material.shininess)"
+ " * ffp_light[%u].specular;\n", idx);
}
shader_addline(buffer, "ffp_varying_diffuse.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n",
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index f3001e5..d7f2182 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -5717,9 +5717,27 @@ void wined3d_ffp_get_vs_settings(const struct wined3d_context *context,
for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
{
- if (state->lights[i])
- settings->light_type |= (state->lights[i]->OriginalParms.type
- & WINED3D_FFP_LIGHT_TYPE_MASK) << WINED3D_FFP_LIGHT_TYPE_SHIFT(i);
+ if (!state->lights[i])
+ continue;
+
+ switch (state->lights[i]->OriginalParms.type)
+ {
+ case WINED3D_LIGHT_POINT:
+ ++settings->point_light_count;
+ break;
+ case WINED3D_LIGHT_SPOT:
+ ++settings->spot_light_count;
+ break;
+ case WINED3D_LIGHT_DIRECTIONAL:
+ ++settings->directional_light_count;
+ break;
+ case WINED3D_LIGHT_PARALLELPOINT:
+ ++settings->parallel_point_light_count;
+ break;
+ default:
+ FIXME("Unhandled light type %#x.\n", state->lights[i]->OriginalParms.type);
+ break;
+ }
}
if (!state->render_states[WINED3D_RS_FOGENABLE])
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9f061bf..4ee9d5c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2377,12 +2377,14 @@ enum wined3d_ffp_vs_fog_mode
struct wined3d_ffp_vs_settings
{
- DWORD light_type : 24; /* MAX_ACTIVE_LIGHTS, 8 * 3 */
+ DWORD point_light_count : 4;
+ DWORD spot_light_count : 4;
+ DWORD directional_light_count : 4;
+ DWORD parallel_point_light_count : 4;
DWORD diffuse_source : 2;
DWORD emissive_source : 2;
DWORD ambient_source : 2;
DWORD specular_source : 2;
-
DWORD transformed : 1;
DWORD vertexblends : 2;
DWORD clipping : 1;
@@ -2390,17 +2392,17 @@ struct wined3d_ffp_vs_settings
DWORD normalize : 1;
DWORD lighting : 1;
DWORD localviewer : 1;
+
DWORD point_size : 1;
DWORD per_vertex_point_size : 1;
DWORD fog_mode : 2;
DWORD texcoords : 8; /* MAX_TEXTURES */
DWORD ortho_fog : 1;
DWORD flatshading : 1;
- DWORD padding : 10;
+ DWORD swizzle_map : 16; /* MAX_ATTRIBS, 16 */
+ DWORD padding : 2;
DWORD texgen[MAX_TEXTURES];
-
- WORD swizzle_map; /* MAX_ATTRIBS, 16 */
};
struct wined3d_ffp_vs_desc
--
2.1.4
More information about the wine-patches
mailing list