[Bf-blender-cvs] [7c0f925c593] master: DRW: Add DRW_shader_create_from_arrays utility

Campbell Barton noreply at git.blender.org
Tue Jan 22 01:10:12 CET 2019


Commit: 7c0f925c593808c00042d65f2a3f6a6c2dbe4fce
Author: Campbell Barton
Date:   Tue Jan 22 10:29:46 2019 +1100
Branches: master
https://developer.blender.org/rB7c0f925c593808c00042d65f2a3f6a6c2dbe4fce

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.

===================================================================

M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_manager_shader.c

===================================================================

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)
 {



More information about the Bf-blender-cvs mailing list