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
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.
This *really* needs more thought put into it
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.
// 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