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
path: root/source
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-02-27 17:06:27 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-02-27 17:06:27 +0300
commit616545b5cfaae77058173f42ee45e3e84047054f (patch)
tree1eb9689333d64191fb1efc88020524dff78c3766 /source
parent4c4e798f3529b3972d96ad68635b3e31eccdee81 (diff)
DRW: Shader: Add shader library manager
This new object makes it easier to resolve shader code dependency.
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/intern/DRW_render.h19
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c129
2 files changed, 148 insertions, 0 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 4f7554006cb..1eb4a903d90 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -81,6 +81,7 @@ typedef struct DRWPass DRWPass;
typedef struct DRWShadingGroup DRWShadingGroup;
typedef struct DRWUniform DRWUniform;
typedef struct DRWView DRWView;
+typedef struct DRWShaderLibrary DRWShaderLibrary;
/* TODO Put it somewhere else? */
typedef struct BoundSphere {
@@ -244,6 +245,24 @@ void DRW_shader_free(struct GPUShader *shader);
} \
} while (0)
+DRWShaderLibrary *DRW_shader_library_create(void);
+
+/* Warning: Each library must be added after all its dependencies. */
+void DRW_shader_library_add_file(DRWShaderLibrary *lib, char *lib_code, const char *lib_name);
+#define DRW_SHADER_LIB_ADD(lib, lib_name) \
+ DRW_shader_library_add_file(lib, datatoc_##lib_name##_glsl, STRINGIFY(lib_name) ".glsl")
+
+char *DRW_shader_library_create_shader_string(DRWShaderLibrary *lib, char *shader_code);
+
+void DRW_shader_library_free(DRWShaderLibrary *lib);
+#define DRW_SHADER_LIB_FREE_SAFE(lib) \
+ do { \
+ if (lib != NULL) { \
+ DRW_shader_library_free(lib); \
+ lib = NULL; \
+ } \
+ } while (0)
+
/* Batches */
typedef enum {
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 9c34cdbac3b..9c72e6c4823 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -24,6 +24,7 @@
#include "DNA_world_types.h"
#include "DNA_material_types.h"
+#include "BLI_dynstr.h"
#include "BLI_listbase.h"
#include "BLI_string_utils.h"
#include "BLI_threads.h"
@@ -282,6 +283,8 @@ void DRW_deferred_shader_remove(GPUMaterial *mat)
/* -------------------------------------------------------------------- */
+/** \{ */
+
GPUShader *DRW_shader_create(const char *vert,
const char *geom,
const char *frag,
@@ -464,3 +467,129 @@ void DRW_shader_free(GPUShader *shader)
{
GPU_shader_free(shader);
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Shader Library
+ *
+ * Simple include system for glsl files.
+ *
+ * Usage: Create a DRWShaderLibrary and add the library in the right order.
+ * You can have nested dependencies but each new library needs to have all its dependencies already
+ * added to the DRWShaderLibrary.
+ * Finally you can use DRW_shader_library_create_shader_string to get a shader string that also
+ * contains the needed libraries for this shader.
+ * \{ */
+
+/* 32 because we use a 32bit bitmap. */
+#define MAX_LIB 32
+#define MAX_LIB_NAME 64
+#define MAX_LIB_DEPS 8
+
+struct DRWShaderLibrary {
+ char *libs[MAX_LIB];
+ char libs_name[MAX_LIB][MAX_LIB_NAME];
+ uint32_t libs_deps[MAX_LIB];
+};
+
+DRWShaderLibrary *DRW_shader_library_create(void)
+{
+ return MEM_callocN(sizeof(DRWShaderLibrary), "DRWShaderLibrary");
+}
+
+void DRW_shader_library_free(DRWShaderLibrary *lib)
+{
+ MEM_SAFE_FREE(lib);
+}
+
+static int drw_shader_library_search(DRWShaderLibrary *lib, const char *name)
+{
+ for (int i = 0; i < MAX_LIB; i++) {
+ if (lib->libs[i]) {
+ if (!strncmp(lib->libs_name[i], name, strlen(lib->libs_name[i]))) {
+ return i;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ return -1;
+}
+
+/* Return bitmap of dependencies. */
+static uint32_t drw_shader_dependencies_get(DRWShaderLibrary *lib, char *lib_code)
+{
+ /* Search dependencies. */
+ uint32_t deps = 0;
+ char *haystack = lib_code;
+ while ((haystack = strstr(haystack, "BLENDER_REQUIRE("))) {
+ haystack += 16;
+ int dep = drw_shader_library_search(lib, haystack);
+ if (dep == -1) {
+ printf(
+ "Error: Dependency not found.\n"
+ "This might be due to bad lib ordering.\n");
+ BLI_assert(0);
+ }
+ else {
+ deps |= 1u << (uint32_t)dep;
+ }
+ }
+ return deps;
+}
+
+void DRW_shader_library_add_file(DRWShaderLibrary *lib, char *lib_code, const char *lib_name)
+{
+ int index = -1;
+ for (int i = 0; i < MAX_LIB; i++) {
+ if (lib->libs[i] == NULL) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index > -1) {
+ lib->libs[index] = lib_code;
+ BLI_strncpy(lib->libs_name[index], lib_name, MAX_LIB_NAME);
+ }
+ else {
+ printf("Error: Too many libraries. Cannot add %s.\n", lib_name);
+ BLI_assert(0);
+ }
+
+ lib->libs_deps[index] = drw_shader_dependencies_get(lib, lib_code);
+}
+
+/* Return an allocN'ed string containing the shader code with its dependencies prepended.
+ * Caller must free the string with MEM_freeN after use. */
+char *DRW_shader_library_create_shader_string(DRWShaderLibrary *lib, char *shader_code)
+{
+ uint32_t deps = drw_shader_dependencies_get(lib, shader_code);
+
+ DynStr *ds = BLI_dynstr_new();
+ /* Add all dependencies recursively. */
+ for (int i = MAX_LIB - 1; i > -1; i--) {
+ if (lib->libs[i] && (deps & (1u << (uint32_t)i))) {
+ deps |= lib->libs_deps[i];
+ }
+ }
+ /* Concatenate all needed libs into one string. */
+ for (int i = 0; i < MAX_LIB; i++) {
+ if (deps & 1u) {
+ BLI_dynstr_append(ds, lib->libs[i]);
+ }
+ deps = deps >> 1;
+ }
+
+ BLI_dynstr_append(ds, shader_code);
+
+ char *str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
+/** \} */