Clutter Wiki

Views
From ClutterProject
Jump to: navigation, search

CoglProgram

I'd really like to hear ideas from people about this one, it's a fairly complex one to design but it should be one of the most important components of Cogl moving forward

  • I like the GL style of emulating standard compiler stages; i.e. take your source code; compile it into objects; link the objects into a program.
  • In the same way that macros can be defined on the commandline with gcc like -DFOO, I think it would be nice if we could do that when compiling shaders.
  • I wonder if we should also consider the potential for other compiler options: e.g. the semantic equivalent of -Wall or -Werror could be supported in future OpenGL drivers.
  • I currently like the idea of mapping shader variable names to application variables via some form of CoglSymbolTable object.
  • The OpenGL glUniform{1|2|3|4}{f|i}v API style seems really clunky.
  • I don't like that glShaderSource takes an array of strings. I can see cases where it can be handy, if you are splicing together a shader from many snippets, but it would have made more sense to me with an API that could have parsed the snippets in-place but as glShaderSource has to implicitly copy all the strings anyway it seems the application could just as well do the splicing.
  • The CoglProgram API should support multiple languages; not just glsl.
  • The API should support specifying source without null termination (considering mmaping a file)
  • Keep in mind that the ARB didn't rule out the idea of one day supporting variables global between multiple programs. ARBfp apparently supports this already.

Some different API styles I've been considering for compiling shaders:

API Style A
-----------
program = cogl_compile_glsl (source, "prog name", "DEFINE_A:VALUE_A", &log, &error);

API Style B
-----------
objects[0] = cogl_compile_glsl (source0, "obj0 name", "DEFINE_A:VALUE_A", &log, &error);
objects[1] = cogl_compile_glsl (source1, "obj1 name", NULL, &log, &error);

program = cogl_link (objects, "prog name", &error);

API Style C
-----------
objects[0] = cogl_glsl_shader_object_new ("obj0 name");
cogl_glsl_shader_object_set_source (objects[0], source0);
cogl_glsl_shader_object_compile (objects[0], "DEFINE_A:VALUE_A", &log, &error);
objects[1] = cogl_shader_object_new ("obj1 name");
cogl_glsl_shader_object_set_source (objects[1], source1);
cogl_glsl_shader_object_compile (objects[1], NULL, &error);

prog = cogl_program_new ("name");
cogl_program_add_objects (prog, objects);
cogl_program_link (prog, &error);

API Style D
-----------
object[0] = cogl_glsl_shader_object_new_with_source ("name0", source0);
<rest same as C/>

API Style E
-----------
compiler = cogl_glsl_compiler_new ();
cogl_glsl_compiler_define_macro (compiler, "FOO", "bar");
cogl_glsl_compiler_set_verbose (compiler);
cogl_glsl_compiler_enable_debug (compiler);

objects[0] = cogl_glsl_compiler_compile (compiler, source0, len, &log, &error);
objects[1] = cogl_glsl_compiler_compile (compiler, source1, -1, &log, &error);

linker = cogl_linker_new ();
//cogl_linker_add_object (linker, object0);
//cogl_linker_add_object (linker, object1);
cogl_linker_add_objects (linker, objects);
program = cogl_linker_link (linker, &log, &error);

I currently prefer the idea of having A as a convenience for 90% of users, and E for more advanced uses.

How the symbol table might work:

This *really* needs more thought put into it

  • The table maps between the string constant shader names, and application variables
  • The table is persistent so it gives us an opportunity to cache the linked location of the shader names for quick updates. (OpenGL separates finding the link location via GetUniformLocation from updating the value via glUniformXfv to avoid repeatedly mapping string constant names to locations)
  • Consider that GLSL only has 3 basic types; int, float and bool, and so there are only three basic types of application variables that need to be considered.
  • For Cogl we will want to support CoglMatrix as well as floats for defining glsl matrix types. We may also want to support CoglColor for vecs and CoglSamplers instead of ints for sampler uniforms.
CoglProgramValue float_uniform; /* or CoglUniform/CoglParameter */

symbols = cogl_program_get_symbols (program);
float_uniform = cogl_symbols_add_float (symbols, "var_name0", &float_var); //only for float types
cogl_symbols_add_int (symbols, "var_name1", &int_var); //only for int types
cogl_symbols_add_bool (symbols, "var_name2", &int_var); //only for bool types
cogl_symbols_add_color (symbols, "var_name3", &cogl_color_var); //for vec floats or vec ints
cogl_symbols_add_matrix (symbols, "var_name4", &cogl_matrix_var); //only matrix types
cogl_symbols_add_float_array (symbols, "var_name5", array); //for vec, array or matrix types
cogl_symbols_add_int_array (symbols, "var_name6", array); //for vec or array types
FIXME: Consider matrix types further, and handling transposed matrices.
...
cogl_symbols_update_all_values (symbols); /* use uniform buffers under the hood ? or track which value is dirty and update them ? */
cogl_symbols_update_value (symbols, float_uniform);
cogl_symbols_update_value_by_name (symbols, "var_name1"); /* do we want to add that ? */

Note: this design relies on the ability to query variable type data from OpenGL such as array lengths or for vec types to determine the number of components. This is possible for glsl, but I don't know about ARBfp.

symbol table Vs ARBfp

  • ARBfp has an array of vect4 local parameters that roughly maps the GLSL uniforms. The size of this array can be queried with MAX_PROGRAM_LOCAL_PARAMETERS_ARB
  • the way to access those variables inside the fragment program is trough program.local[a][.xyzw] or program.local[a..b][.xyzw]
// index: [0-9]+ -> is the index in the ARBfp array of local parameters
// swizzle1: x | y | z | w | r | g | b | a -> component
// index_range: [0-9]+..[0-9]+

cogl_symbols_add_int (symbols, "index.swizzle1" | "index", &int_var);
cogl_symbols_add_bool (symbols, "index.swizzle1" | "index", &int_var); 
cogl_symbols_add_color (symbols, "index", &cogl_color_var);
cogl_symbols_add_float_array (symbols, "index_range", array); //for vec, array or matrix types
Personal tools