pipeline: Wrap each snippet in its own function

Each snippet is now given its own function which contains the pre and
post strings. Between these strings the function will chain on to
another function. The generated cogl source is now stored in a
function called cogl_generated_source() which the last snippet will
chain on to. This should make it so that each snippet has its own
namespace for local variables and it can share variables declared in
the pre string in the post string. Hopefully the GLSL compiler will
just inline all of the functions so it shouldn't make much difference
to the compiled output.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2011-11-25 13:41:13 +00:00 committed by Robert Bragg
parent 2f66cd7036
commit 0fdd5690c6
3 changed files with 96 additions and 90 deletions

View File

@ -200,7 +200,6 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
CoglPipelineShaderState *shader_state;
CoglPipeline *authority;
CoglPipeline *template_pipeline = NULL;
CoglPipelineSnippet *snippet;
CoglProgram *user_program;
int i;
@ -327,40 +326,9 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
g_string_append (shader_state->source,
"void\n"
"main ()\n"
"cogl_generated_source ()\n"
"{\n");
COGL_LIST_FOREACH (snippet, get_fragment_snippets (pipeline), list_node)
{
const char *declarations =
cogl_snippet_get_declarations (snippet->snippet);
/* Add all of the declarations for fragment snippets */
if (declarations)
{
g_string_append (shader_state->header, declarations);
g_string_append_c (shader_state->header, '\n');
}
/* Add all of the pre-hooks for fragment processing */
if (snippet->hook == COGL_PIPELINE_SNIPPET_HOOK_FRAGMENT)
{
const char *pre =
cogl_snippet_get_pre (snippet->snippet);
if (pre)
{
g_string_append (shader_state->source, " {\n");
g_string_append (shader_state->source, pre);
g_string_append (shader_state->source, " }\n");
}
}
}
/* Enclose the generated fragment processing in a block so that any
variables declared in it won't be in the scope of the snippets */
g_string_append (shader_state->source, " {\n");
for (i = 0; i < n_layers; i++)
{
shader_state->unit_state[i].sampled = FALSE;
@ -928,6 +896,7 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
GLint compile_status;
GLuint shader;
CoglPipelineSnippet *snippet;
int snippet_num;
COGL_STATIC_COUNTER (fragend_glsl_compile_counter,
"glsl fragment compile counter",
@ -965,24 +934,58 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
add_alpha_test_snippet (pipeline, shader_state);
#endif
/* Close the block surrounding the generated fragment processing */
g_string_append (shader_state->source, " }\n");
/* Close the function surrounding the generated fragment processing */
g_string_append (shader_state->source, "}\n");
/* Add all of the post-hooks for fragment processing */
snippet_num = 0;
COGL_LIST_FOREACH (snippet, get_fragment_snippets (pipeline), list_node)
if (snippet->hook == COGL_PIPELINE_SNIPPET_HOOK_FRAGMENT)
{
const char *post =
cogl_snippet_get_post (snippet->snippet);
const char *source;
if (post)
{
g_string_append (shader_state->source, " {\n");
g_string_append (shader_state->source, post);
g_string_append (shader_state->source, " }\n");
}
if ((source = cogl_snippet_get_declarations (snippet->snippet)))
g_string_append (shader_state->source, source);
g_string_append_printf (shader_state->source,
"\n"
"void\n"
"cogl_snippet%i ()\n"
"{\n",
snippet_num);
if ((source = cogl_snippet_get_pre (snippet->snippet)))
g_string_append (shader_state->source, source);
/* Chain on to the next function */
if (snippet_num > 0)
g_string_append_printf (shader_state->source,
" cogl_snippet%i ();\n",
snippet_num - 1);
else
g_string_append (shader_state->source,
" cogl_generated_source ();\n");
if ((source = cogl_snippet_get_post (snippet->snippet)))
g_string_append (shader_state->source, source);
g_string_append (shader_state->source, "}\n");
snippet_num++;
}
g_string_append (shader_state->source,
"\n"
"void\n"
"main ()\n"
"{\n");
if (snippet_num > 0)
g_string_append_printf (shader_state->source,
" cogl_snippet%i ();\n",
snippet_num - 1);
else
g_string_append (shader_state->source,
" cogl_generated_source ();\n");
g_string_append (shader_state->source, "}\n");
GE_RET( shader, ctx, glCreateShader (GL_FRAGMENT_SHADER) );

View File

@ -146,7 +146,6 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
{
CoglPipelineShaderState *shader_state;
CoglPipeline *template_pipeline = NULL;
CoglPipelineSnippet *snippet;
CoglProgram *user_program;
_COGL_GET_CONTEXT (ctx, FALSE);
@ -262,40 +261,9 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
g_string_append (shader_state->source,
"void\n"
"main ()\n"
"cogl_generated_source ()\n"
"{\n");
COGL_LIST_FOREACH (snippet, get_vertex_snippets (pipeline), list_node)
{
const char *declarations =
cogl_snippet_get_declarations (snippet->snippet);
/* Add all of the declarations for vertex snippets */
if (declarations)
{
g_string_append (shader_state->header, declarations);
g_string_append_c (shader_state->header, '\n');
}
/* Add all of the pre-hooks for vertex processing */
if (snippet->hook == COGL_PIPELINE_SNIPPET_HOOK_VERTEX)
{
const char *pre =
cogl_snippet_get_pre (snippet->snippet);
if (pre)
{
g_string_append (shader_state->source, " {\n");
g_string_append (shader_state->source, pre);
g_string_append (shader_state->source, " }\n");
}
}
}
/* Enclose the generated vertex processing in a block so that any
variables declared in it won't be in the scope of the snippets */
g_string_append (shader_state->source, " {\n");
if (ctx->driver == COGL_DRIVER_GLES2)
/* There is no builtin uniform for the pointsize on GLES2 so we need
to copy it from the custom uniform in the vertex shader */
@ -393,6 +361,7 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
GLint compile_status;
GLuint shader;
CoglPipelineSnippet *snippet;
int snippet_num;
COGL_STATIC_COUNTER (vertend_glsl_compile_counter,
"glsl vertex compile counter",
@ -406,23 +375,57 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
"cogl_modelview_projection_matrix * "
"cogl_position_in;\n"
" cogl_color_out = cogl_color_in;\n"
" }\n");
"}\n");
/* Add all of the post-hooks for vertex processing */
snippet_num = 0;
COGL_LIST_FOREACH (snippet, get_vertex_snippets (pipeline), list_node)
if (snippet->hook == COGL_PIPELINE_SNIPPET_HOOK_VERTEX)
{
const char *post =
cogl_snippet_get_post (snippet->snippet);
const char *source;
if (post)
{
g_string_append (shader_state->source, " {\n");
g_string_append (shader_state->source, post);
g_string_append (shader_state->source, " }\n");
}
if ((source = cogl_snippet_get_declarations (snippet->snippet)))
g_string_append (shader_state->source, source);
g_string_append_printf (shader_state->source,
"\n"
"void\n"
"cogl_snippet%i ()\n"
"{\n",
snippet_num);
if ((source = cogl_snippet_get_pre (snippet->snippet)))
g_string_append (shader_state->source, source);
/* Chain on to the next function */
if (snippet_num > 0)
g_string_append_printf (shader_state->source,
" cogl_snippet%i ();\n",
snippet_num - 1);
else
g_string_append (shader_state->source,
" cogl_generated_source ();\n");
if ((source = cogl_snippet_get_post (snippet->snippet)))
g_string_append (shader_state->source, source);
g_string_append (shader_state->source, "}\n");
snippet_num++;
}
g_string_append (shader_state->source,
"\n"
"void\n"
"main ()\n"
"{\n");
if (snippet_num > 0)
g_string_append_printf (shader_state->source,
" cogl_snippet%i ();\n",
snippet_num - 1);
else
g_string_append (shader_state->source,
" cogl_generated_source ();\n");
g_string_append (shader_state->source, "}\n");
GE_RET( shader, ctx, glCreateShader (GL_VERTEX_SHADER) );

View File

@ -105,14 +105,14 @@ paint (TestState *state)
cogl_object_unref (pipeline);
/* The pre string can't really do anything with the current hooks,
but let's just test that it compiles */
/* Test that the pre string can declare variables used by the post
string */
pipeline = cogl_pipeline_new ();
cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255);
cogl_pipeline_set_color4ub (pipeline, 255, 255, 255, 255);
snippet = cogl_snippet_new (NULL, NULL);
cogl_snippet_set_pre (snippet, "cogl_color_out = vec4 (1.0, 0.5, 0.8, 1.0);");
snippet = cogl_snippet_new (NULL, "cogl_color_out = redvec;");
cogl_snippet_set_pre (snippet, "vec4 redvec = vec4 (1.0, 0.0, 0.0, 1.0);");
cogl_pipeline_add_vertex_hook (pipeline, snippet);
cogl_pipeline_add_fragment_hook (pipeline, snippet);
cogl_object_unref (snippet);