[PATCH v2 05/12] wined3d: Handle GS inputs and outputs.
Matteo Bruni
mbruni at codeweavers.com
Fri May 20 12:55:56 CDT 2016
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
v2: Don't use "reorder shaders".
dlls/wined3d/glsl_shader.c | 107 +++++++++++++++++++++++++++++++++--------
dlls/wined3d/shader.c | 10 ++++
dlls/wined3d/wined3d_private.h | 11 ++++-
3 files changed, 106 insertions(+), 22 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index b814639..7d24ece 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -231,6 +231,7 @@ struct glsl_vs_compiled_shader
struct glsl_gs_compiled_shader
{
+ struct gs_compile_args args;
GLuint id;
};
@@ -4117,6 +4118,7 @@ static void shader_glsl_else(const struct wined3d_shader_instruction *ins)
static void shader_glsl_emit(const struct wined3d_shader_instruction *ins)
{
+ shader_addline(ins->ctx->buffer, "setup_gs_output(gs_out);\n");
shader_addline(ins->ctx->buffer, "EmitVertex();\n");
}
@@ -5268,6 +5270,21 @@ static void shader_glsl_setup_sm4_shader_output(struct shader_glsl_priv *priv,
string_buffer_release(&priv->string_buffers, destination);
}
+/* Context activation is done by the caller. */
+static void shader_glsl_generate_vs_gs_setup(struct shader_glsl_priv *priv,
+ const struct wined3d_shader *vs, unsigned int input_count,
+ const struct wined3d_gl_info *gl_info)
+{
+ struct wined3d_string_buffer *buffer = &priv->shader_buffer;
+
+ shader_addline(buffer, "varying out vec4 gs_in[%u];\n", input_count);
+ shader_addline(buffer, "void setup_vs_output(in vec4 shader_out[%u])\n{\n", vs->limits->packed_output);
+
+ shader_glsl_setup_sm4_shader_output(priv, input_count, &vs->output_signature, &vs->reg_maps, "gs_in");
+
+ shader_addline(buffer, "}\n");
+}
+
static void shader_glsl_setup_sm3_rasterizer_input(struct shader_glsl_priv *priv,
const struct wined3d_gl_info *gl_info, const DWORD *map,
const struct wined3d_shader_signature *input_signature,
@@ -5457,8 +5474,8 @@ static GLuint shader_glsl_generate_vs3_rasterizer_input_setup(struct shader_glsl
return ret;
}
-static void shader_glsl_generate_vs4_rasterizer_input_setup(struct shader_glsl_priv *priv,
- const struct wined3d_shader *vs, unsigned int input_count,
+static void shader_glsl_generate_sm4_rasterizer_input_setup(struct shader_glsl_priv *priv,
+ const struct wined3d_shader *shader, unsigned int input_count,
const struct wined3d_gl_info *gl_info)
{
struct wined3d_string_buffer *buffer = &priv->shader_buffer;
@@ -5466,10 +5483,11 @@ static void shader_glsl_generate_vs4_rasterizer_input_setup(struct shader_glsl_p
if (input_count)
declare_out_varying(gl_info, buffer, FALSE, "vec4 ps_link[%u];\n", min(vec4_varyings(4, gl_info), input_count));
- shader_addline(buffer, "void setup_vs_output(in vec4 shader_out[%u])\n{\n", vs->limits->packed_output);
+ shader_addline(buffer, "void setup_%s_output(in vec4 shader_out[%u])\n{\n",
+ shader_glsl_get_prefix(shader->reg_maps.shader_version.type), shader->limits->packed_output);
shader_glsl_setup_sm3_rasterizer_input(priv, gl_info, NULL, NULL,
- NULL, input_count, &vs->output_signature, &vs->reg_maps, FALSE);
+ NULL, input_count, &shader->output_signature, &shader->reg_maps, FALSE);
shader_addline(buffer, "}\n");
}
@@ -5713,7 +5731,12 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
if (reg_maps->shader_version.major >= 4)
- shader_glsl_generate_vs4_rasterizer_input_setup(priv, shader, args->next_shader_input_count, gl_info);
+ {
+ if (args->next_shader_type == WINED3D_SHADER_TYPE_PIXEL)
+ shader_glsl_generate_sm4_rasterizer_input_setup(priv, shader, args->next_shader_input_count, gl_info);
+ else if (args->next_shader_type == WINED3D_SHADER_TYPE_GEOMETRY)
+ shader_glsl_generate_vs_gs_setup(priv, shader, args->next_shader_input_count, gl_info);
+ }
shader_addline(buffer, "void main()\n{\n");
@@ -5773,10 +5796,11 @@ static GLuint shader_glsl_generate_vshader(const struct wined3d_context *context
/* Context activation is done by the caller. */
static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context *context,
- struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers,
- const struct wined3d_shader *shader)
+ struct shader_glsl_priv *priv, const struct wined3d_shader *shader, const struct gs_compile_args *args)
{
+ struct wined3d_string_buffer_list *string_buffers = &priv->string_buffers;
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;
const DWORD *function = shader->function;
struct shader_glsl_ctx_priv priv_ctx;
@@ -5802,6 +5826,7 @@ static GLuint shader_glsl_generate_geometry_shader(const struct wined3d_context
memset(&priv_ctx, 0, sizeof(priv_ctx));
priv_ctx.string_buffers = string_buffers;
shader_generate_glsl_declarations(context, buffer, shader, reg_maps, &priv_ctx);
+ shader_glsl_generate_sm4_rasterizer_input_setup(priv, shader, args->ps_input_count, gl_info);
shader_addline(buffer, "void main()\n{\n");
shader_generate_main(shader, buffer, reg_maps, function, &priv_ctx);
shader_addline(buffer, "}\n");
@@ -5899,6 +5924,8 @@ static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const str
return FALSE;
if (stored->flatshading != new->flatshading)
return FALSE;
+ if (stored->next_shader_type != new->next_shader_type)
+ return FALSE;
if (stored->next_shader_input_count != new->next_shader_input_count)
return FALSE;
return stored->fog_src == new->fog_src;
@@ -5970,11 +5997,11 @@ static GLuint find_glsl_vshader(const struct wined3d_context *context, struct sh
}
static GLuint find_glsl_geometry_shader(const struct wined3d_context *context,
- struct wined3d_string_buffer *buffer, struct wined3d_string_buffer_list *string_buffers,
- struct wined3d_shader *shader)
+ struct shader_glsl_priv *priv, struct wined3d_shader *shader, const struct gs_compile_args *args)
{
- struct glsl_gs_compiled_shader *gl_shaders;
+ struct glsl_gs_compiled_shader *gl_shaders, *new_array;
struct glsl_shader_private *shader_data;
+ unsigned int i, new_size;
GLuint ret;
if (!shader->backend_data)
@@ -5988,21 +6015,38 @@ static GLuint find_glsl_geometry_shader(const struct wined3d_context *context,
shader_data = shader->backend_data;
gl_shaders = shader_data->gl_shaders.gs;
- if (shader_data->num_gl_shaders)
- return gl_shaders[0].id;
+ for (i = 0; i < shader_data->num_gl_shaders; ++i)
+ {
+ if (!memcmp(&gl_shaders[i].args, args, sizeof(*args)))
+ return gl_shaders[i].id;
+ }
TRACE("No matching GL shader found for shader %p, compiling a new shader.\n", shader);
- if (!(shader_data->gl_shaders.gs = HeapAlloc(GetProcessHeap(), 0, sizeof(*gl_shaders))))
+ if (shader_data->num_gl_shaders)
{
- ERR("Failed to allocate GL shader array.\n");
+ new_size = shader_data->shader_array_size + 1;
+ new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders.gs,
+ new_size * sizeof(*new_array));
+ }
+ else
+ {
+ new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_array));
+ new_size = 1;
+ }
+
+ if (!new_array)
+ {
+ ERR("Failed to allocate GL shaders array.\n");
return 0;
}
- shader_data->shader_array_size = 1;
- gl_shaders = shader_data->gl_shaders.gs;
+ shader_data->gl_shaders.gs = new_array;
+ shader_data->shader_array_size = new_size;
+ gl_shaders = new_array;
- string_buffer_clear(buffer);
- ret = shader_glsl_generate_geometry_shader(context, buffer, string_buffers, shader);
+ string_buffer_clear(&priv->shader_buffer);
+ ret = shader_glsl_generate_geometry_shader(context, priv, shader, args);
+ gl_shaders[shader_data->num_gl_shaders].args = *args;
gl_shaders[shader_data->num_gl_shaders++].id = ret;
return ret;
@@ -7340,7 +7384,12 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
&& ctx_data->glsl_program->gs.id)
gs_id = ctx_data->glsl_program->gs.id;
else if (gshader)
- gs_id = find_glsl_geometry_shader(context, &priv->shader_buffer, &priv->string_buffers, gshader);
+ {
+ struct gs_compile_args args;
+
+ find_gs_compile_args(state, gshader, &args);
+ gs_id = find_glsl_geometry_shader(context, priv, gshader, &args);
+ }
}
}
else if (use_vs(state))
@@ -7354,7 +7403,12 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
vs_list = &vshader->linked_programs;
if ((gshader = state->shader[WINED3D_SHADER_TYPE_GEOMETRY]))
- gs_id = find_glsl_geometry_shader(context, &priv->shader_buffer, &priv->string_buffers, gshader);
+ {
+ struct gs_compile_args gs_compile_args;
+
+ find_gs_compile_args(state, gshader, &gs_compile_args);
+ gs_id = find_glsl_geometry_shader(context, priv, gshader, &gs_compile_args);
+ }
}
else if (priv->vertex_pipe == &glsl_vertex_pipe)
{
@@ -8636,7 +8690,7 @@ static void glsl_vertex_pipe_vs(struct wined3d_context *context,
context_apply_state(context, state, STATE_VDECL);
}
-static void glsl_vertex_pipe_pixel_shader(struct wined3d_context *context,
+static void glsl_vertex_pipe_geometry_shader(struct wined3d_context *context,
const struct wined3d_state *state, DWORD state_id)
{
if (state->shader[WINED3D_SHADER_TYPE_VERTEX]
@@ -8644,6 +8698,16 @@ static void glsl_vertex_pipe_pixel_shader(struct wined3d_context *context,
context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
}
+static void glsl_vertex_pipe_pixel_shader(struct wined3d_context *context,
+ const struct wined3d_state *state, DWORD state_id)
+{
+ if (state->shader[WINED3D_SHADER_TYPE_GEOMETRY])
+ context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_GEOMETRY;
+ else if (state->shader[WINED3D_SHADER_TYPE_VERTEX]
+ && state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.shader_version.major >= 4)
+ context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
+}
+
static void glsl_vertex_pipe_world(struct wined3d_context *context,
const struct wined3d_state *state, DWORD state_id)
{
@@ -8768,6 +8832,7 @@ static const struct StateEntryTemplate glsl_vertex_pipe_vp_states[] =
{
{STATE_VDECL, {STATE_VDECL, glsl_vertex_pipe_vdecl }, WINED3D_GL_EXT_NONE },
{STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), {STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX), glsl_vertex_pipe_vs }, WINED3D_GL_EXT_NONE },
+ {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY), glsl_vertex_pipe_geometry_shader}, WINED3D_GL_EXT_NONE },
{STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL), glsl_vertex_pipe_pixel_shader}, WINED3D_GL_EXT_NONE },
{STATE_MATERIAL, {STATE_RENDER(WINED3D_RS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE },
{STATE_RENDER(WINED3D_RS_SPECULARENABLE), {STATE_RENDER(WINED3D_RS_SPECULARENABLE), glsl_vertex_pipe_material}, WINED3D_GL_EXT_NONE },
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index bda0b6d..0a6c1b9 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -2678,6 +2678,9 @@ void find_vs_compile_args(const struct wined3d_state *state, const struct wined3
&& 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;
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
@@ -2901,6 +2904,13 @@ static HRESULT geometry_shader_init(struct wined3d_shader *shader, struct wined3
return WINED3D_OK;
}
+void find_gs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
+ struct gs_compile_args *args)
+{
+ args->ps_input_count = state->shader[WINED3D_SHADER_TYPE_PIXEL]
+ ? state->shader[WINED3D_SHADER_TYPE_PIXEL]->limits->packed_input : 0;
+}
+
void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
BOOL position_transformed, struct ps_compile_args *args, const struct wined3d_context *context)
{
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 1910dff..74a15e7 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1044,11 +1044,17 @@ struct vs_compile_args
BYTE point_size : 1;
BYTE per_vertex_point_size : 1;
BYTE flatshading : 1;
- BYTE padding : 4;
+ BYTE next_shader_type : 3;
+ BYTE padding : 1;
WORD swizzle_map; /* MAX_ATTRIBS, 16 */
unsigned int next_shader_input_count;
};
+struct gs_compile_args
+{
+ unsigned int ps_input_count;
+};
+
struct wined3d_context;
struct wined3d_state;
struct fragment_pipeline;
@@ -3280,6 +3286,9 @@ void find_vs_compile_args(const struct wined3d_state *state, const struct wined3
WORD swizzle_map, struct vs_compile_args *args,
const struct wined3d_d3d_info *d3d_info) DECLSPEC_HIDDEN;
+void find_gs_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader,
+ struct gs_compile_args *args) DECLSPEC_HIDDEN;
+
void string_buffer_clear(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN;
BOOL string_buffer_init(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN;
void string_buffer_free(struct wined3d_string_buffer *buffer) DECLSPEC_HIDDEN;
--
2.7.3
More information about the wine-patches
mailing list