From 0fdd5690c6b760334bf0307e5c1d3c82f3937239 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 25 Nov 2011 13:41:13 +0000 Subject: [PATCH] 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 --- cogl/cogl-pipeline-fragend-glsl.c | 89 ++++++++++++++++--------------- cogl/cogl-pipeline-vertend-glsl.c | 87 +++++++++++++++--------------- tests/conform/test-snippets.c | 10 ++-- 3 files changed, 96 insertions(+), 90 deletions(-) diff --git a/cogl/cogl-pipeline-fragend-glsl.c b/cogl/cogl-pipeline-fragend-glsl.c index d44519039..aa8a8d916 100644 --- a/cogl/cogl-pipeline-fragend-glsl.c +++ b/cogl/cogl-pipeline-fragend-glsl.c @@ -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) ); diff --git a/cogl/cogl-pipeline-vertend-glsl.c b/cogl/cogl-pipeline-vertend-glsl.c index a6cadee2d..680375856 100644 --- a/cogl/cogl-pipeline-vertend-glsl.c +++ b/cogl/cogl-pipeline-vertend-glsl.c @@ -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) ); diff --git a/tests/conform/test-snippets.c b/tests/conform/test-snippets.c index 1246fdf00..6a5bf60b4 100644 --- a/tests/conform/test-snippets.c +++ b/tests/conform/test-snippets.c @@ -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);