diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-01-22 02:29:46 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-01-22 02:38:28 +0300 |
commit | 7c0f925c593808c00042d65f2a3f6a6c2dbe4fce (patch) | |
tree | 9ca141cf19a6db6207950241679a12a83a4a4efe /source/blender/draw/intern | |
parent | 8beab3e33922a86f1e15d6b9c7598e2ada03531f (diff) |
DRW: Add DRW_shader_create_from_arrays utility
While verbose, this is a more flexible way to construct shaders.
Libs & defines can be optionally included for each shader type
which was previously done with inline string creation.
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 5 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_shader.c | 66 |
2 files changed, 71 insertions, 0 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index cb5b8074f4b..af679b5e534 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -243,6 +243,11 @@ void DRW_multisamples_resolve( /* Shaders */ struct GPUShader *DRW_shader_create( const char *vert, const char *geom, const char *frag, const char *defines); +struct DRW_ShaderCreateFromArray_Params { const char **vert, **geom, **frag, **defs; }; +struct GPUShader *DRW_shader_create_from_arrays_impl( + const struct DRW_ShaderCreateFromArray_Params *params); +#define DRW_shader_create_from_arrays(...) \ + DRW_shader_create_from_arrays_impl(&(const struct DRW_ShaderCreateFromArray_Params)__VA_ARGS__) struct GPUShader *DRW_shader_create_with_lib( const char *vert, const char *geom, const char *frag, const char *lib, const char *defines); struct GPUShader *DRW_shader_create_with_transform_feedback( diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index e8d693aa7c0..cd8102ef492 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -267,6 +267,72 @@ GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *fra return GPU_shader_create(vert, frag, geom, NULL, defines, __func__); } +static const char *string_join_array_maybe_alloc(const char **str_arr, bool *r_is_alloc) +{ + bool is_alloc = false; + if (str_arr == NULL) { + *r_is_alloc = false; + return NULL; + } + /* Skip empty strings (avoid alloc if we can). */ + while (str_arr[0] && str_arr[0][0] == '\0') { + str_arr++; + } + int i; + for (i = 0; str_arr[i]; i++) { + if (i != 0 && str_arr[i][0] != '\0') { + is_alloc = true; + } + } + *r_is_alloc = is_alloc; + if (is_alloc) { + return BLI_string_join_arrayN(str_arr, i); + } + else { + return str_arr[0]; + } +} + +/** + * Use via #DRW_shader_create_from_arrays macro (avoids passing in param). + * + * Similar to #DRW_shader_create_with_lib with the ability to include libs for each type of shader. + * + * It has the advantage that each item can be conditionally included + * without having to build the string inline, then free it. + * + * \param params: NULL terminated arrays of strings. + * + * Example: + * \code{.c} + * sh = DRW_shader_create_from_arrays({ + * .vert = (const char *[]){shader_lib_glsl, shader_vert_glsl, NULL}, + * .geom = (const char *[]){shader_geom_glsl, NULL}, + * .frag = (const char *[]){shader_frag_glsl, NULL}, + * .defs = (const char *[]){"#define DEFINE\n", test ? "#define OTHER_DEFINE\n" : "", NULL}}); + * \endcode + * + */ +struct GPUShader *DRW_shader_create_from_arrays_impl( + const struct DRW_ShaderCreateFromArray_Params *params) +{ + struct { const char *str; bool is_alloc;} str_dst[4] = {0}; + const char **str_src[4] = {params->vert, params->geom, params->frag, params->defs}; + + for (int i = 0; i < ARRAY_SIZE(str_src); i++) { + str_dst[i].str = string_join_array_maybe_alloc(str_src[i], &str_dst[i].is_alloc); + } + + GPUShader *sh = DRW_shader_create(str_dst[0].str, str_dst[1].str, str_dst[2].str, str_dst[3].str); + + for (int i = 0; i < ARRAY_SIZE(str_dst); i++) { + if (str_dst[i].is_alloc) { + MEM_freeN((void *)str_dst[i].str); + } + } + return sh; +} + GPUShader *DRW_shader_create_with_lib( const char *vert, const char *geom, const char *frag, const char *lib, const char *defines) { |