Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-01-22 02:29:46 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-01-22 02:38:28 +0300
commit7c0f925c593808c00042d65f2a3f6a6c2dbe4fce (patch)
tree9ca141cf19a6db6207950241679a12a83a4a4efe /source/blender/draw
parent8beab3e33922a86f1e15d6b9c7598e2ada03531f (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')
-rw-r--r--source/blender/draw/intern/DRW_render.h5
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c66
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)
{