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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2020-02-12 14:48:44 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2020-02-15 22:33:16 +0300
commit007f1b74a67302fb4c164eb26969419434a98aee (patch)
treef56ba0eecbbc11fc22e6a47aa0d76582e553e3da /source/blender
parent6701db773e660e5306e305a1b10f8ea52955f06b (diff)
Cleanup: split off code from gpu_codegen.c into smaller files
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenlib/BLI_string.h1
-rw-r--r--source/blender/blenlib/intern/string.c18
-rw-r--r--source/blender/draw/intern/draw_manager_data.c2
-rw-r--r--source/blender/gpu/CMakeLists.txt3
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c940
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h163
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c3
-rw-r--r--source/blender/gpu/intern/gpu_material.c42
-rw-r--r--source/blender/gpu/intern/gpu_material_library.c882
-rw-r--r--source/blender/gpu/intern/gpu_material_library.h644
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c562
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h182
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c2
13 files changed, 1759 insertions, 1685 deletions
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index cab2e68ca2b..cc91c26a2ab 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -118,6 +118,7 @@ int BLI_str_index_in_array_n(const char *__restrict str,
int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array)
ATTR_NONNULL();
+bool BLI_str_startswith(const char *__restrict str, const char *__restrict start) ATTR_NONNULL();
bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL();
bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t length)
ATTR_NONNULL();
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 1eed59e568e..acc256226d2 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -900,6 +900,24 @@ int BLI_str_index_in_array(const char *__restrict str, const char **__restrict s
return -1;
}
+/**
+ * Find if a string starts with another string.
+ *
+ * \param str: The string to search within.
+ * \param start: The string we look for at the start.
+ * \return If str starts with start.
+ */
+bool BLI_str_startswith(const char *__restrict str, const char *__restrict start)
+{
+ for (; *str && *start; str++, start++) {
+ if (*str != *start) {
+ return false;
+ }
+ }
+
+ return (*start == '\0');
+}
+
bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t slength)
{
size_t elength = strlen(end);
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index f9a6b663900..1b2195b8e41 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -46,8 +46,10 @@
#endif
#include "GPU_buffers.h"
+#include "GPU_material.h"
#include "intern/gpu_codegen.h"
+#include "intern/gpu_node_graph.h"
/* -------------------------------------------------------------------- */
/** \name Uniform Buffer Object (DRW_uniformbuffer)
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index ea8bcfda92c..0ab3e775566 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -69,7 +69,9 @@ set(SRC
intern/gpu_immediate_util.c
intern/gpu_init_exit.c
intern/gpu_material.c
+ intern/gpu_material_library.c
intern/gpu_matrix.c
+ intern/gpu_node_graph.c
intern/gpu_platform.c
intern/gpu_primitive.c
intern/gpu_select.c
@@ -121,6 +123,7 @@ set(SRC
intern/gpu_context_private.h
intern/gpu_material_library.h
intern/gpu_matrix_private.h
+ intern/gpu_node_graph.h
intern/gpu_primitive_private.h
intern/gpu_private.h
intern/gpu_select_private.h
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 4787015e3d6..2f9af536b8c 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -27,8 +27,6 @@
#include "DNA_customdata_types.h"
#include "DNA_image_types.h"
-#include "DNA_material_types.h"
-#include "DNA_node_types.h"
#include "BLI_blenlib.h"
#include "BLI_hash_mm2a.h"
@@ -38,10 +36,10 @@
#include "BLI_ghash.h"
#include "BLI_threads.h"
-#include "BKE_material.h"
-
#include "PIL_time.h"
+#include "BKE_material.h"
+
#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_material.h"
@@ -53,13 +51,11 @@
#include "gpu_codegen.h"
#include "gpu_material_library.h"
+#include "gpu_node_graph.h"
#include <string.h>
#include <stdarg.h>
-extern char datatoc_gpu_shader_material_glsl[];
-extern char datatoc_gpu_shader_geometry_glsl[];
-
extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
@@ -132,281 +128,6 @@ static GPUPass *gpu_pass_cache_resolve_collision(GPUPass *pass,
return NULL;
}
-/* -------------------- GPU Codegen ------------------ */
-
-/* type definitions and constants */
-
-#define MAX_FUNCTION_NAME 64
-#define MAX_PARAMETER 32
-
-typedef enum {
- FUNCTION_QUAL_IN,
- FUNCTION_QUAL_OUT,
- FUNCTION_QUAL_INOUT,
-} GPUFunctionQual;
-
-typedef struct GPUFunction {
- char name[MAX_FUNCTION_NAME];
- eGPUType paramtype[MAX_PARAMETER];
- GPUFunctionQual paramqual[MAX_PARAMETER];
- int totparam;
- GPUMaterialLibrary *library;
-} GPUFunction;
-
-/* Indices match the eGPUType enum */
-static const char *GPU_DATATYPE_STR[17] = {
- "",
- "float",
- "vec2",
- "vec3",
- "vec4",
- NULL,
- NULL,
- NULL,
- NULL,
- "mat3",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "mat4",
-};
-
-/* GLSL code parsing for finding function definitions.
- * These are stored in a hash for lookup when creating a material. */
-
-static GHash *FUNCTION_HASH = NULL;
-#if 0
-static char *FUNCTION_PROTOTYPES = NULL;
-static GPUShader *FUNCTION_LIB = NULL;
-#endif
-
-static int gpu_str_prefix(const char *str, const char *prefix)
-{
- while (*str && *prefix) {
- if (*str != *prefix) {
- return 0;
- }
-
- str++;
- prefix++;
- }
-
- return (*prefix == '\0');
-}
-
-static char *gpu_str_skip_token(char *str, char *token, int max)
-{
- int len = 0;
-
- /* skip a variable/function name */
- while (*str) {
- if (ELEM(*str, ' ', '(', ')', ',', ';', '\t', '\n', '\r')) {
- break;
- }
- else {
- if (token && len < max - 1) {
- *token = *str;
- token++;
- len++;
- }
- str++;
- }
- }
-
- if (token) {
- *token = '\0';
- }
-
- /* skip the next special characters:
- * note the missing ')' */
- while (*str) {
- if (ELEM(*str, ' ', '(', ',', ';', '\t', '\n', '\r')) {
- str++;
- }
- else {
- break;
- }
- }
-
- return str;
-}
-
-static void gpu_parse_material_library(GHash *hash, GPUMaterialLibrary *library)
-{
- GPUFunction *function;
- eGPUType type;
- GPUFunctionQual qual;
- int i;
- char *code = library->code;
-
- while ((code = strstr(code, "void "))) {
- function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
- function->library = library;
-
- code = gpu_str_skip_token(code, NULL, 0);
- code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
-
- /* get parameters */
- while (*code && *code != ')') {
- /* test if it's an input or output */
- qual = FUNCTION_QUAL_IN;
- if (gpu_str_prefix(code, "out ")) {
- qual = FUNCTION_QUAL_OUT;
- }
- if (gpu_str_prefix(code, "inout ")) {
- qual = FUNCTION_QUAL_INOUT;
- }
- if ((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in ")) {
- code = gpu_str_skip_token(code, NULL, 0);
- }
-
- /* test for type */
- type = GPU_NONE;
- for (i = 1; i < ARRAY_SIZE(GPU_DATATYPE_STR); i++) {
- if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
- type = i;
- break;
- }
- }
-
- if (!type && gpu_str_prefix(code, "samplerCube")) {
- type = GPU_TEXCUBE;
- }
- if (!type && gpu_str_prefix(code, "sampler2DShadow")) {
- type = GPU_SHADOW2D;
- }
- if (!type && gpu_str_prefix(code, "sampler1DArray")) {
- type = GPU_TEX1D_ARRAY;
- }
- if (!type && gpu_str_prefix(code, "sampler2DArray")) {
- type = GPU_TEX2D_ARRAY;
- }
- if (!type && gpu_str_prefix(code, "sampler2D")) {
- type = GPU_TEX2D;
- }
- if (!type && gpu_str_prefix(code, "sampler3D")) {
- type = GPU_TEX3D;
- }
-
- if (!type && gpu_str_prefix(code, "Closure")) {
- type = GPU_CLOSURE;
- }
-
- if (type) {
- /* add parameter */
- code = gpu_str_skip_token(code, NULL, 0);
- code = gpu_str_skip_token(code, NULL, 0);
- function->paramqual[function->totparam] = qual;
- function->paramtype[function->totparam] = type;
- function->totparam++;
- }
- else {
- fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
- break;
- }
- }
-
- if (function->name[0] == '\0' || function->totparam == 0) {
- fprintf(stderr, "GPU functions parse error.\n");
- MEM_freeN(function);
- break;
- }
-
- BLI_ghash_insert(hash, function->name, function);
- }
-}
-
-#if 0
-static char *gpu_generate_function_prototyps(GHash *hash)
-{
- DynStr *ds = BLI_dynstr_new();
- GHashIterator *ghi;
- GPUFunction *function;
- char *name, *prototypes;
- int a;
-
- /* automatically generate function prototypes to add to the top of the
- * generated code, to avoid have to add the actual code & recompile all */
- ghi = BLI_ghashIterator_new(hash);
-
- for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) {
- name = BLI_ghashIterator_getValue(ghi);
- function = BLI_ghashIterator_getValue(ghi);
-
- BLI_dynstr_appendf(ds, "void %s(", name);
- for (a = 0; a < function->totparam; a++) {
- if (function->paramqual[a] == FUNCTION_QUAL_OUT) {
- BLI_dynstr_append(ds, "out ");
- }
- else if (function->paramqual[a] == FUNCTION_QUAL_INOUT) {
- BLI_dynstr_append(ds, "inout ");
- }
-
- if (function->paramtype[a] == GPU_TEX2D) {
- BLI_dynstr_append(ds, "sampler2D");
- }
- else if (function->paramtype[a] == GPU_SHADOW2D) {
- BLI_dynstr_append(ds, "sampler2DShadow");
- }
- else {
- BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
- }
-# if 0
- BLI_dynstr_appendf(ds, " param%d", a);
-# endif
-
- if (a != function->totparam - 1) {
- BLI_dynstr_append(ds, ", ");
- }
- }
- BLI_dynstr_append(ds, ");\n");
- }
-
- BLI_dynstr_append(ds, "\n");
-
- prototypes = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return prototypes;
-}
-#endif
-
-static GPUFunction *gpu_lookup_function(const char *name)
-{
- return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
-}
-
-void gpu_codegen_init(void)
-{
- GPU_code_generate_glsl_lib();
-}
-
-void gpu_codegen_exit(void)
-{
- BKE_material_defaults_free_gpu();
-
- if (FUNCTION_HASH) {
- BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
- FUNCTION_HASH = NULL;
- }
-
- GPU_shader_free_builtin_shaders();
-
-#if 0
- if (FUNCTION_PROTOTYPES) {
- MEM_freeN(FUNCTION_PROTOTYPES);
- FUNCTION_PROTOTYPES = NULL;
- }
- if (FUNCTION_LIB) {
- GPU_shader_free(FUNCTION_LIB);
- FUNCTION_LIB = NULL;
- }
-#endif
-}
-
/* GLSL code generation */
static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id)
@@ -485,7 +206,7 @@ static void codegen_print_datatype(DynStr *ds, const eGPUType type, float *data)
{
int i;
- BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
+ BLI_dynstr_appendf(ds, "%s(", gpu_data_type_to_string(type));
for (i = 0; i < type; i++) {
BLI_dynstr_appendf(ds, "%.12f", data[i]);
@@ -508,7 +229,7 @@ static int codegen_input_has_texture(GPUInput *input)
}
}
-const char *GPU_builtin_name(eGPUBuiltin builtin)
+static const char *gpu_builtin_name(eGPUBuiltin builtin)
{
if (builtin == GPU_VIEW_MATRIX) {
return "unfviewmat";
@@ -676,18 +397,18 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
/* only define each builtin uniform/varying once */
if (!(builtins & input->builtin)) {
builtins |= input->builtin;
- name = GPU_builtin_name(input->builtin);
+ name = gpu_builtin_name(input->builtin);
- if (gpu_str_prefix(name, "samp")) {
+ if (BLI_str_startswith(name, "samp")) {
if ((input->builtin == GPU_VOLUME_DENSITY) || (input->builtin == GPU_VOLUME_FLAME)) {
BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name);
}
}
- else if (gpu_str_prefix(name, "unf")) {
- BLI_dynstr_appendf(ds, "uniform %s %s;\n", GPU_DATATYPE_STR[input->type], name);
+ else if (BLI_str_startswith(name, "unf")) {
+ BLI_dynstr_appendf(ds, "uniform %s %s;\n", gpu_data_type_to_string(input->type), name);
}
else {
- BLI_dynstr_appendf(ds, "in %s %s;\n", GPU_DATATYPE_STR[input->type], name);
+ BLI_dynstr_appendf(ds, "in %s %s;\n", gpu_data_type_to_string(input->type), name);
}
}
}
@@ -702,12 +423,14 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
}
}
else if (input->source == GPU_SOURCE_CONSTANT) {
- BLI_dynstr_appendf(ds, "const %s cons%d = ", GPU_DATATYPE_STR[input->type], input->id);
+ BLI_dynstr_appendf(
+ ds, "const %s cons%d = ", gpu_data_type_to_string(input->type), input->id);
codegen_print_datatype(ds, input->type, input->vec);
BLI_dynstr_append(ds, ";\n");
}
else if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
- BLI_dynstr_appendf(ds, "in %s var%d;\n", GPU_DATATYPE_STR[input->type], input->attr_id);
+ BLI_dynstr_appendf(
+ ds, "in %s var%d;\n", gpu_data_type_to_string(input->type), input->attr_id);
}
}
}
@@ -721,7 +444,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
for (LinkData *link = ubo_inputs.first; link; link = link->next) {
input = link->data;
- BLI_dynstr_appendf(ds, "\t%s unf%d;\n", GPU_DATATYPE_STR[input->type], input->id);
+ BLI_dynstr_appendf(ds, "\t%s unf%d;\n", gpu_data_type_to_string(input->type), input->id);
}
BLI_dynstr_append(ds, "};\n");
BLI_freelistN(&ubo_inputs);
@@ -744,7 +467,7 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
BLI_dynstr_appendf(ds, "\tClosure tmp%d;\n", output->id);
}
else {
- BLI_dynstr_appendf(ds, "\t%s tmp%d;\n", GPU_DATATYPE_STR[output->type], output->id);
+ BLI_dynstr_appendf(ds, "\t%s tmp%d;\n", gpu_data_type_to_string(output->type), output->id);
}
}
}
@@ -814,7 +537,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, "facingwnormal");
}
else {
- BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
+ BLI_dynstr_append(ds, gpu_builtin_name(input->builtin));
}
}
else if (input->source == GPU_SOURCE_STRUCT) {
@@ -1021,7 +744,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
else if (input->attr_name[0] == '\0') {
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s);\n",
- GPU_DATATYPE_STR[input->type],
+ gpu_data_type_to_string(input->type),
attr_prefix_get(input->attr_type));
BLI_dynstr_appendf(
ds, "#define att%d %s\n", input->attr_id, attr_prefix_get(input->attr_type));
@@ -1032,7 +755,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
input->attr_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME);
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s%s);\n",
- GPU_DATATYPE_STR[input->type],
+ gpu_data_type_to_string(input->type),
attr_prefix_get(input->attr_type),
attr_safe_name);
BLI_dynstr_appendf(ds,
@@ -1043,7 +766,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
}
BLI_dynstr_appendf(ds,
"out %s var%d%s;\n",
- GPU_DATATYPE_STR[input->type],
+ gpu_data_type_to_string(input->type),
input->attr_id,
use_geom ? "g" : "");
}
@@ -1143,7 +866,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
"\tvar%d%s = hair_get_customdata_%s(att%d);\n",
input->attr_id,
use_geom ? "g" : "",
- GPU_DATATYPE_STR[input->type],
+ gpu_data_type_to_string(input->type),
input->attr_id);
}
}
@@ -1245,8 +968,10 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
builtins |= input->builtin;
}
if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
- BLI_dynstr_appendf(ds, "in %s var%dg[];\n", GPU_DATATYPE_STR[input->type], input->attr_id);
- BLI_dynstr_appendf(ds, "out %s var%d;\n", GPU_DATATYPE_STR[input->type], input->attr_id);
+ BLI_dynstr_appendf(
+ ds, "in %s var%dg[];\n", gpu_data_type_to_string(input->type), input->attr_id);
+ BLI_dynstr_appendf(
+ ds, "out %s var%d;\n", gpu_data_type_to_string(input->type), input->attr_id);
}
}
}
@@ -1369,320 +1094,12 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
return code;
}
-void GPU_code_generate_glsl_lib(void)
-{
- /* Only parse GLSL shader files once. */
- if (FUNCTION_HASH) {
- return;
- }
-
- FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
- for (int i = 0; gpu_material_libraries[i]; i++) {
- gpu_parse_material_library(FUNCTION_HASH, gpu_material_libraries[i]);
- }
-}
-
-/* GPU pass binding/unbinding */
-
GPUShader *GPU_pass_shader_get(GPUPass *pass)
{
return pass->shader;
}
-void GPU_nodes_extract_dynamic_inputs(GPUShader *shader, ListBase *inputs, ListBase *nodes)
-{
- GPUNode *node;
- GPUInput *next, *input;
-
- BLI_listbase_clear(inputs);
-
- if (!shader) {
- return;
- }
-
- for (node = nodes->first; node; node = node->next) {
- int z = 0;
- for (input = node->inputs.first; input; input = next, z++) {
- next = input->next;
-
- /* attributes don't need to be bound, they already have
- * an id that the drawing functions will use. Builtins have
- * constant names. */
- if (ELEM(input->source, GPU_SOURCE_ATTR, GPU_SOURCE_BUILTIN)) {
- continue;
- }
-
- if (input->source == GPU_SOURCE_TEX) {
- BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
- }
- else {
- BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
- }
-
- if (input->source == GPU_SOURCE_TEX) {
- if (input->bindtex) {
- input->shaderloc = GPU_shader_get_uniform_ensure(shader, input->shadername);
- /* extract nodes */
- BLI_remlink(&node->inputs, input);
- BLI_addtail(inputs, input);
- }
- }
- }
- }
-}
-
-/* Node Link Functions */
-
-static GPUNodeLink *GPU_node_link_create(void)
-{
- GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
- link->users++;
-
- return link;
-}
-
-static void gpu_node_link_free(GPUNodeLink *link)
-{
- link->users--;
-
- if (link->users < 0) {
- fprintf(stderr, "GPU_node_link_free: negative refcount\n");
- }
-
- if (link->users == 0) {
- if (link->output) {
- link->output->link = NULL;
- }
- MEM_freeN(link);
- }
-}
-
-/* Node Functions */
-
-static GPUNode *GPU_node_begin(const char *name)
-{
- GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
-
- node->name = name;
-
- return node;
-}
-
-static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType type)
-{
- GPUInput *input;
- GPUNode *outnode;
- const char *name;
-
- if (link->link_type == GPU_NODE_LINK_OUTPUT) {
- outnode = link->output->node;
- name = outnode->name;
- input = outnode->inputs.first;
-
- if ((STR_ELEM(name, "set_value", "set_rgb", "set_rgba")) && (input->type == type)) {
- input = MEM_dupallocN(outnode->inputs.first);
- if (input->link) {
- input->link->users++;
- }
- BLI_addtail(&node->inputs, input);
- return;
- }
- }
-
- input = MEM_callocN(sizeof(GPUInput), "GPUInput");
- input->node = node;
- input->type = type;
-
- switch (link->link_type) {
- case GPU_NODE_LINK_BUILTIN:
- input->source = GPU_SOURCE_BUILTIN;
- input->builtin = link->builtin;
- break;
- case GPU_NODE_LINK_OUTPUT:
- input->source = GPU_SOURCE_OUTPUT;
- input->link = link;
- link->users++;
- break;
- case GPU_NODE_LINK_COLORBAND:
- input->source = GPU_SOURCE_TEX;
- input->coba = link->coba;
- break;
- case GPU_NODE_LINK_IMAGE_BLENDER:
- case GPU_NODE_LINK_IMAGE_TILEMAP:
- input->source = GPU_SOURCE_TEX;
- input->ima = link->ima;
- input->iuser = link->iuser;
- break;
- case GPU_NODE_LINK_ATTR:
- input->source = GPU_SOURCE_ATTR;
- input->attr_type = link->attr_type;
- BLI_strncpy(input->attr_name, link->attr_name, sizeof(input->attr_name));
- break;
- case GPU_NODE_LINK_CONSTANT:
- input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT;
- break;
- case GPU_NODE_LINK_UNIFORM:
- input->source = GPU_SOURCE_UNIFORM;
- break;
- default:
- break;
- }
-
- if (ELEM(input->source, GPU_SOURCE_CONSTANT, GPU_SOURCE_UNIFORM)) {
- memcpy(input->vec, link->data, type * sizeof(float));
- }
-
- if (link->link_type != GPU_NODE_LINK_OUTPUT) {
- MEM_freeN(link);
- }
- BLI_addtail(&node->inputs, input);
-}
-
-static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type)
-{
- switch (type) {
- /* For now INT is supported as float. */
- case SOCK_INT:
- case SOCK_FLOAT:
- return "set_value";
- case SOCK_VECTOR:
- return "set_rgb";
- case SOCK_RGBA:
- return "set_rgba";
- default:
- BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype");
- return NULL;
- }
-}
-
-/**
- * Link stack uniform buffer.
- * This is called for the input/output sockets that are note connected.
- */
-static GPUNodeLink *gpu_uniformbuffer_link(GPUMaterial *mat,
- bNode *node,
- GPUNodeStack *stack,
- const int index,
- const eNodeSocketInOut in_out)
-{
- bNodeSocket *socket;
-
- if (in_out == SOCK_IN) {
- socket = BLI_findlink(&node->inputs, index);
- }
- else {
- socket = BLI_findlink(&node->outputs, index);
- }
-
- BLI_assert(socket != NULL);
- BLI_assert(socket->in_out == in_out);
-
- if ((socket->flag & SOCK_HIDE_VALUE) == 0) {
- GPUNodeLink *link;
- switch (socket->type) {
- case SOCK_FLOAT: {
- bNodeSocketValueFloat *socket_data = socket->default_value;
- link = GPU_uniform(&socket_data->value);
- break;
- }
- case SOCK_VECTOR: {
- bNodeSocketValueVector *socket_data = socket->default_value;
- link = GPU_uniform(socket_data->value);
- break;
- }
- case SOCK_RGBA: {
- bNodeSocketValueRGBA *socket_data = socket->default_value;
- link = GPU_uniform(socket_data->value);
- break;
- }
- default:
- return NULL;
- break;
- }
-
- if (in_out == SOCK_IN) {
- GPU_link(mat, gpu_uniform_set_function_from_type(socket->type), link, &stack->link);
- }
- return link;
- }
- return NULL;
-}
-
-static void gpu_node_input_socket(
- GPUMaterial *material, bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index)
-{
- if (sock->link) {
- gpu_node_input_link(node, sock->link, sock->type);
- }
- else if ((material != NULL) &&
- (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != NULL)) {
- gpu_node_input_link(node, sock->link, sock->type);
- }
- else {
- gpu_node_input_link(node, GPU_constant(sock->vec), sock->type);
- }
-}
-
-static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **link)
-{
- GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
-
- output->type = type;
- output->node = node;
-
- if (link) {
- *link = output->link = GPU_node_link_create();
- output->link->link_type = GPU_NODE_LINK_OUTPUT;
- output->link->output = output;
-
- /* note: the caller owns the reference to the link, GPUOutput
- * merely points to it, and if the node is destroyed it will
- * set that pointer to NULL */
- }
-
- BLI_addtail(&node->outputs, output);
-}
-
-void GPU_inputs_free(ListBase *inputs)
-{
- GPUInput *input;
-
- for (input = inputs->first; input; input = input->next) {
- if (input->link) {
- gpu_node_link_free(input->link);
- }
- }
-
- BLI_freelistN(inputs);
-}
-
-static void gpu_node_free(GPUNode *node)
-{
- GPUOutput *output;
-
- GPU_inputs_free(&node->inputs);
-
- for (output = node->outputs.first; output; output = output->next) {
- if (output->link) {
- output->link->output = NULL;
- gpu_node_link_free(output->link);
- }
- }
-
- BLI_freelistN(&node->outputs);
- MEM_freeN(node);
-}
-
-static void gpu_nodes_free(ListBase *nodes)
-{
- GPUNode *node;
-
- while ((node = BLI_pophead(nodes))) {
- gpu_node_free(node);
- }
-}
-
-/* vertex attributes */
+/* Vertex Attributes */
static void gpu_nodes_get_vertex_attrs(ListBase *nodes, GPUVertAttrLayers *attrs)
{
@@ -1723,284 +1140,16 @@ static void gpu_nodes_get_vertex_attrs(ListBase *nodes, GPUVertAttrLayers *attrs
}
}
-/* varargs linking */
-
-GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
-{
- GPUNodeLink *link = GPU_node_link_create();
- link->link_type = GPU_NODE_LINK_ATTR;
- link->attr_name = name;
- /* Fall back to the UV layer, which matches old behavior. */
- if (type == CD_AUTO_FROM_NAME && name[0] == '\0') {
- link->attr_type = CD_MTFACE;
- }
- else {
- link->attr_type = type;
- }
- return link;
-}
-
-GPUNodeLink *GPU_constant(float *num)
-{
- GPUNodeLink *link = GPU_node_link_create();
- link->link_type = GPU_NODE_LINK_CONSTANT;
- link->data = num;
- return link;
-}
-
-GPUNodeLink *GPU_uniform(float *num)
-{
- GPUNodeLink *link = GPU_node_link_create();
- link->link_type = GPU_NODE_LINK_UNIFORM;
- link->data = num;
- return link;
-}
-
-GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
-{
- GPUNodeLink *link = GPU_node_link_create();
- link->link_type = GPU_NODE_LINK_IMAGE_BLENDER;
- link->ima = ima;
- link->iuser = iuser;
- return link;
-}
-
-GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row)
-{
- GPUNodeLink *link = GPU_node_link_create();
- link->link_type = GPU_NODE_LINK_COLORBAND;
- link->coba = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
- MEM_freeN(pixels);
- return link;
-}
-
-GPUNodeLink *GPU_builtin(eGPUBuiltin builtin)
-{
- GPUNodeLink *link = GPU_node_link_create();
- link->link_type = GPU_NODE_LINK_BUILTIN;
- link->builtin = builtin;
- return link;
-}
-
-static void gpu_material_use_library_with_dependencies(GSet *used_libraries,
- GPUMaterialLibrary *library)
-{
- if (BLI_gset_add(used_libraries, library->code)) {
- for (int i = 0; library->dependencies[i]; i++) {
- gpu_material_use_library_with_dependencies(used_libraries, library->dependencies[i]);
- }
- }
-}
-
-static void gpu_material_use_library(GPUMaterial *material, GPUMaterialLibrary *library)
-{
- GSet *used_libraries = gpu_material_used_libraries(material);
- gpu_material_use_library_with_dependencies(used_libraries, library);
-}
-
-bool GPU_link(GPUMaterial *mat, const char *name, ...)
-{
- GPUNode *node;
- GPUFunction *function;
- GPUNodeLink *link, **linkptr;
- va_list params;
- int i;
-
- function = gpu_lookup_function(name);
- if (!function) {
- fprintf(stderr, "GPU failed to find function %s\n", name);
- return false;
- }
-
- gpu_material_use_library(mat, function->library);
-
- node = GPU_node_begin(name);
-
- va_start(params, name);
- for (i = 0; i < function->totparam; i++) {
- if (function->paramqual[i] != FUNCTION_QUAL_IN) {
- linkptr = va_arg(params, GPUNodeLink **);
- gpu_node_output(node, function->paramtype[i], linkptr);
- }
- else {
- link = va_arg(params, GPUNodeLink *);
- gpu_node_input_link(node, link, function->paramtype[i]);
- }
- }
- va_end(params);
-
- gpu_material_add_node(mat, node);
-
- return true;
-}
-
-bool GPU_stack_link(GPUMaterial *material,
- bNode *bnode,
- const char *name,
- GPUNodeStack *in,
- GPUNodeStack *out,
- ...)
-{
- GPUNode *node;
- GPUFunction *function;
- GPUNodeLink *link, **linkptr;
- va_list params;
- int i, totin, totout;
-
- function = gpu_lookup_function(name);
- if (!function) {
- fprintf(stderr, "GPU failed to find function %s\n", name);
- return false;
- }
-
- gpu_material_use_library(material, function->library);
-
- node = GPU_node_begin(name);
- totin = 0;
- totout = 0;
-
- if (in) {
- for (i = 0; !in[i].end; i++) {
- if (in[i].type != GPU_NONE) {
- gpu_node_input_socket(material, bnode, node, &in[i], i);
- totin++;
- }
- }
- }
-
- if (out) {
- for (i = 0; !out[i].end; i++) {
- if (out[i].type != GPU_NONE) {
- gpu_node_output(node, out[i].type, &out[i].link);
- totout++;
- }
- }
- }
-
- va_start(params, out);
- for (i = 0; i < function->totparam; i++) {
- if (function->paramqual[i] != FUNCTION_QUAL_IN) {
- if (totout == 0) {
- linkptr = va_arg(params, GPUNodeLink **);
- gpu_node_output(node, function->paramtype[i], linkptr);
- }
- else {
- totout--;
- }
- }
- else {
- if (totin == 0) {
- link = va_arg(params, GPUNodeLink *);
- if (link->socket) {
- gpu_node_input_socket(NULL, NULL, node, link->socket, -1);
- }
- else {
- gpu_node_input_link(node, link, function->paramtype[i]);
- }
- }
- else {
- totin--;
- }
- }
- }
- va_end(params);
-
- gpu_material_add_node(material, node);
-
- return true;
-}
-
-GPUNodeLink *GPU_uniformbuffer_link_out(GPUMaterial *mat,
- bNode *node,
- GPUNodeStack *stack,
- const int index)
-{
- return gpu_uniformbuffer_link(mat, node, stack, index, SOCK_OUT);
-}
-
/* Pass create/free */
-static void gpu_nodes_tag(GPUNodeLink *link)
-{
- GPUNode *node;
- GPUInput *input;
-
- if (!link->output) {
- return;
- }
-
- node = link->output->node;
- if (node->tag) {
- return;
- }
-
- node->tag = true;
- for (input = node->inputs.first; input; input = input->next) {
- if (input->link) {
- gpu_nodes_tag(input->link);
- }
- }
-}
-
-static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
-{
- GPUNode *node, *next;
-
- for (node = nodes->first; node; node = node->next) {
- node->tag = false;
- }
-
- gpu_nodes_tag(outlink);
-
- for (node = nodes->first; node; node = next) {
- next = node->next;
-
- if (!node->tag) {
- BLI_remlink(nodes, node);
- gpu_node_free(node);
- }
- }
-}
-
static bool gpu_pass_is_valid(GPUPass *pass)
{
/* Shader is not null if compilation is successful. */
return (pass->compiled == false || pass->shader != NULL);
}
-static char *code_generate_material_library(GPUMaterial *material, const char *frag_lib)
-{
- DynStr *ds = BLI_dynstr_new();
-
- if (frag_lib) {
- BLI_dynstr_append(ds, frag_lib);
- }
-
- GSet *used_libraries = gpu_material_used_libraries(material);
-
- /* Always include those because they may be needed by the execution function. */
- gpu_material_use_library_with_dependencies(used_libraries,
- &gpu_shader_material_world_normals_library);
-
- /* Add library code in order, for dependencies. */
- for (int i = 0; gpu_material_libraries[i]; i++) {
- GPUMaterialLibrary *library = gpu_material_libraries[i];
- if (BLI_gset_haskey(used_libraries, library->code)) {
- BLI_dynstr_append(ds, library->code);
- }
- }
-
- char *result = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return result;
-}
-
GPUPass *GPU_generate_pass(GPUMaterial *material,
- GPUNodeLink *frag_outlink,
- struct GPUVertAttrLayers *attrs,
- ListBase *nodes,
- int *builtins,
+ GPUNodeGraph *graph,
const char *vert_code,
const char *geom_code,
const char *frag_lib,
@@ -2011,14 +1160,15 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
/* Prune the unused nodes and extract attributes before compiling so the
* generated VBOs are ready to accept the future shader. */
- gpu_nodes_prune(nodes, frag_outlink);
- gpu_nodes_get_vertex_attrs(nodes, attrs);
+ gpu_node_graph_prune_unused(graph);
+ gpu_nodes_get_vertex_attrs(&graph->nodes, &graph->attrs);
/* generate code */
- char *fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, builtins);
+ char *fragmentgen = code_generate_fragment(
+ material, &graph->nodes, graph->outlink->output, &graph->builtins);
/* Cache lookup: Reuse shaders already compiled */
- uint32_t hash = gpu_pass_hash(fragmentgen, defines, attrs);
+ uint32_t hash = gpu_pass_hash(fragmentgen, defines, &graph->attrs);
pass_hash = gpu_pass_cache_lookup(hash);
if (pass_hash && (pass_hash->next == NULL || pass_hash->next->hash != hash)) {
@@ -2034,10 +1184,11 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
/* Either the shader is not compiled or there is a hash collision...
* continue generating the shader strings. */
- char *tmp = code_generate_material_library(material, frag_lib);
+ GSet *used_libraries = gpu_material_used_libraries(material);
+ char *tmp = gpu_material_library_generate_code(used_libraries, frag_lib);
- geometrycode = code_generate_geometry(nodes, geom_code, defines);
- vertexcode = code_generate_vertex(nodes, vert_code, (geometrycode != NULL));
+ geometrycode = code_generate_geometry(&graph->nodes, geom_code, defines);
+ vertexcode = code_generate_vertex(&graph->nodes, vert_code, (geometrycode != NULL));
fragmentcode = BLI_strdupcat(tmp, fragmentgen);
MEM_freeN(fragmentgen);
@@ -2111,7 +1262,7 @@ static int count_active_texture_sampler(GPUShader *shader, char *source)
code++;
}
/* Skip following spaces. */
- if (gpu_str_prefix(code, "sampler")) {
+ if (BLI_str_startswith(code, "sampler")) {
/* Move past "uniform". */
code += 7;
/* Skip sampler type suffix. */
@@ -2233,11 +1384,6 @@ static void gpu_pass_free(GPUPass *pass)
MEM_freeN(pass);
}
-void GPU_pass_free_nodes(ListBase *nodes)
-{
- gpu_nodes_free(nodes);
-}
-
void GPU_pass_cache_garbage_collect(void)
{
static int lasttime = 0;
@@ -2283,3 +1429,15 @@ void GPU_pass_cache_free(void)
BLI_spin_end(&pass_cache_spin);
}
+
+/* Module */
+
+void gpu_codegen_init(void)
+{
+}
+
+void gpu_codegen_exit(void)
+{
+ BKE_material_defaults_free_gpu();
+ GPU_shader_free_builtin_shaders();
+}
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index baa4debf862..ce20f495ba3 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -19,143 +19,21 @@
/** \file
* \ingroup gpu
+ *
+ * Generate shader code from the intermediate node graph.
*/
#ifndef __GPU_CODEGEN_H__
#define __GPU_CODEGEN_H__
-#include "DNA_customdata_types.h"
-#include "DNA_listBase.h"
-#include "GPU_material.h"
-#include "GPU_glew.h"
-
-struct GPUNode;
+struct GPUMaterial;
+struct GPUNodeGraph;
struct GPUOutput;
struct GPUShader;
-struct GPUVertAttrLayers;
struct GSet;
struct ListBase;
-/* Pass Generation
- * - Takes a list of nodes and a desired output, and makes a pass. This
- * will take ownership of the nodes and free them early if unused or
- * at the end if used.
- */
-
-typedef enum eGPUDataSource {
- GPU_SOURCE_OUTPUT,
- GPU_SOURCE_CONSTANT,
- GPU_SOURCE_UNIFORM,
- GPU_SOURCE_ATTR,
- GPU_SOURCE_BUILTIN,
- GPU_SOURCE_STRUCT,
- GPU_SOURCE_TEX,
-} eGPUDataSource;
-
-typedef enum {
- GPU_NODE_LINK_NONE = 0,
- GPU_NODE_LINK_ATTR,
- GPU_NODE_LINK_BUILTIN,
- GPU_NODE_LINK_COLORBAND,
- GPU_NODE_LINK_CONSTANT,
- GPU_NODE_LINK_IMAGE_BLENDER,
- GPU_NODE_LINK_IMAGE_TILEMAP,
- GPU_NODE_LINK_OUTPUT,
- GPU_NODE_LINK_UNIFORM,
-} GPUNodeLinkType;
-
-struct GPUNode {
- struct GPUNode *next, *prev;
-
- const char *name;
-
- /* Internal flag to mark nodes during pruning */
- bool tag;
-
- ListBase inputs;
- ListBase outputs;
-};
-
-struct GPUNodeLink {
- GPUNodeStack *socket;
-
- GPUNodeLinkType link_type;
- int users; /* Refcount */
-
- union {
- /* GPU_NODE_LINK_CONSTANT | GPU_NODE_LINK_UNIFORM */
- float *data;
- /* GPU_NODE_LINK_BUILTIN */
- eGPUBuiltin builtin;
- /* GPU_NODE_LINK_COLORBAND */
- struct GPUTexture **coba;
- /* GPU_NODE_LINK_OUTPUT */
- struct GPUOutput *output;
- /* GPU_NODE_LINK_ATTR */
- struct {
- const char *attr_name;
- CustomDataType attr_type;
- };
- /* GPU_NODE_LINK_IMAGE_BLENDER | GPU_NODE_LINK_IMAGE_TILEMAP */
- struct {
- struct Image *ima;
- struct ImageUser *iuser;
- };
- };
-};
-
-typedef struct GPUOutput {
- struct GPUOutput *next, *prev;
-
- GPUNode *node;
- eGPUType type; /* data type = length of vector/matrix */
- GPUNodeLink *link; /* output link */
- int id; /* unique id as created by code generator */
-} GPUOutput;
-
-typedef struct GPUInput {
- struct GPUInput *next, *prev;
-
- GPUNode *node;
- eGPUType type; /* datatype */
- GPUNodeLink *link;
- int id; /* unique id as created by code generator */
-
- eGPUDataSource source; /* data source */
-
- int shaderloc; /* id from opengl */
- char shadername[32]; /* name in shader */
-
- /* Content based on eGPUDataSource */
- union {
- /* GPU_SOURCE_CONSTANT | GPU_SOURCE_UNIFORM */
- float vec[16]; /* vector data */
- /* GPU_SOURCE_BUILTIN */
- eGPUBuiltin builtin; /* builtin uniform */
- /* GPU_SOURCE_TEX */
- struct {
- struct GPUTexture **coba; /* input texture, only set at runtime */
- struct Image *ima; /* image */
- struct ImageUser *iuser; /* image user */
- bool bindtex; /* input is responsible for binding the texture? */
- int texid; /* number for multitexture, starting from zero */
- eGPUType textype; /* texture type (2D, 1D Array ...) */
- };
- /* GPU_SOURCE_ATTR */
- struct {
- /** Attribute name. */
- char attr_name[MAX_CUSTOMDATA_LAYER_NAME];
- /** ID for vertex attributes. */
- int attr_id;
- /** This is the first one that is bound. */
- bool attr_first;
- /** Attribute type. */
- CustomDataType attr_type;
- };
- };
-} GPUInput;
-
-struct GPUPass {
+typedef struct GPUPass {
struct GPUPass *next;
struct GPUShader *shader;
@@ -171,42 +49,23 @@ struct GPUPass {
int len;
} binary;
bool compiled; /* Did we already tried to compile the attached GPUShader. */
-};
+} GPUPass;
-typedef struct GPUPass GPUPass;
+/* Pass */
-GPUPass *GPU_generate_pass(GPUMaterial *material,
- GPUNodeLink *frag_outlink,
- struct GPUVertAttrLayers *attrs,
- ListBase *nodes,
- int *builtins,
+GPUPass *GPU_generate_pass(struct GPUMaterial *material,
+ struct GPUNodeGraph *graph,
const char *vert_code,
const char *geom_code,
const char *frag_lib,
const char *defines);
-
struct GPUShader *GPU_pass_shader_get(GPUPass *pass);
-
-void GPU_nodes_extract_dynamic_inputs(struct GPUShader *shader, ListBase *inputs, ListBase *nodes);
-
bool GPU_pass_compile(GPUPass *pass, const char *shname);
void GPU_pass_release(GPUPass *pass);
-void GPU_pass_free_nodes(ListBase *nodes);
-void GPU_inputs_free(ListBase *inputs);
+/* Module */
void gpu_codegen_init(void);
void gpu_codegen_exit(void);
-/* Material calls */
-
-const char *GPU_builtin_name(eGPUBuiltin builtin);
-void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node);
-struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat,
- int size,
- float *pixels,
- float *row);
-
-struct GSet *gpu_material_used_libraries(struct GPUMaterial *material);
-
-#endif
+#endif /* __GPU_CODEGEN_H__ */
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 7b6016e11cb..c99b7fc8a67 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -29,6 +29,7 @@
#include "BKE_global.h"
#include "intern/gpu_codegen.h"
+#include "intern/gpu_material_library.h"
#include "intern/gpu_private.h"
/**
@@ -50,6 +51,7 @@ void GPU_init(void)
gpu_extensions_init(); /* must come first */
gpu_codegen_init();
+ gpu_material_library_init();
gpu_framebuffer_module_init();
if (G.debug & G_DEBUG_GPU) {
@@ -80,6 +82,7 @@ void GPU_exit(void)
}
gpu_framebuffer_module_exit();
+ gpu_material_library_exit();
gpu_codegen_exit();
gpu_extensions_exit();
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index d8d431e329a..9eed3e4619b 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -52,6 +52,7 @@
#include "DRW_engine.h"
#include "gpu_codegen.h"
+#include "gpu_node_graph.h"
/* Structs */
#define MAX_COLOR_BAND 128
@@ -70,15 +71,11 @@ struct GPUMaterial {
const void *engine_type; /* attached engine type */
int options; /* to identify shader variations (shadow, probe, world background...) */
- /* for creating the material */
- ListBase nodes;
- GPUNodeLink *outlink;
+ /* Nodes */
+ GPUNodeGraph graph;
/* for binding the material */
GPUPass *pass;
- ListBase inputs; /* GPUInput */
- GPUVertAttrLayers attrs;
- int builtins;
/* XXX: Should be in Material. But it depends on the output node
* used and since the output selection is different for GPUMaterial...
@@ -169,8 +166,7 @@ static void gpu_material_free_single(GPUMaterial *material)
/* Cancel / wait any pending lazy compilation. */
DRW_deferred_shader_remove(material);
- GPU_pass_free_nodes(&material->nodes);
- GPU_inputs_free(&material->inputs);
+ gpu_node_graph_free(&material->graph);
if (material->pass != NULL) {
GPU_pass_release(material->pass);
@@ -203,7 +199,7 @@ void GPU_material_free(ListBase *gpumaterial)
eGPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
{
- return material->builtins;
+ return material->graph.builtins;
}
Scene *GPU_material_scene(GPUMaterial *material)
@@ -218,7 +214,7 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material)
ListBase *GPU_material_get_inputs(GPUMaterial *material)
{
- return &material->inputs;
+ return &material->graph.inputs;
}
/* Return can be NULL if it's a world material. */
@@ -573,19 +569,19 @@ struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void)
void GPU_material_vertex_attrs(GPUMaterial *material, GPUVertAttrLayers *r_attrs)
{
- *r_attrs = material->attrs;
+ *r_attrs = material->graph.attrs;
}
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
{
- if (!material->outlink) {
- material->outlink = link;
+ if (!material->graph.outlink) {
+ material->graph.outlink = link;
}
}
void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
{
- BLI_addtail(&material->nodes, node);
+ BLI_addtail(&material->graph.nodes, node);
}
GSet *gpu_material_used_libraries(GPUMaterial *material)
@@ -682,7 +678,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
SET_FLAG_FROM_TEST(mat->domain, has_surface_output, GPU_DOMAIN_SURFACE);
SET_FLAG_FROM_TEST(mat->domain, has_volume_output, GPU_DOMAIN_VOLUME);
- if (mat->outlink) {
+ if (mat->graph.outlink) {
/* HACK: this is only for eevee. We add the define here after the nodetree evaluation. */
if (GPU_material_flag_get(mat, GPU_MATFLAG_SSS)) {
defines = BLI_string_joinN(defines,
@@ -691,15 +687,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
"#endif\n");
}
/* Create source code and search pass cache for an already compiled version. */
- mat->pass = GPU_generate_pass(mat,
- mat->outlink,
- &mat->attrs,
- &mat->nodes,
- &mat->builtins,
- vert_code,
- geom_code,
- frag_lib,
- defines);
+ mat->pass = GPU_generate_pass(mat, &mat->graph, vert_code, geom_code, frag_lib, defines);
if (GPU_material_flag_get(mat, GPU_MATFLAG_SSS)) {
MEM_freeN((char *)defines);
@@ -714,7 +702,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
if (sh != NULL) {
/* We had a cache hit and the shader is already compiled. */
mat->status = GPU_MAT_SUCCESS;
- GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes);
+ gpu_node_graph_extract_dynamic_inputs(sh, &mat->graph);
}
else {
mat->status = GPU_MAT_QUEUED;
@@ -760,12 +748,12 @@ void GPU_material_compile(GPUMaterial *mat)
GPUShader *sh = GPU_pass_shader_get(mat->pass);
if (sh != NULL) {
mat->status = GPU_MAT_SUCCESS;
- GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes);
+ gpu_node_graph_extract_dynamic_inputs(sh, &mat->graph);
}
}
else {
mat->status = GPU_MAT_FAILED;
- GPU_pass_free_nodes(&mat->nodes);
+ gpu_node_graph_free(&mat->graph);
GPU_pass_release(mat->pass);
mat->pass = NULL;
}
diff --git a/source/blender/gpu/intern/gpu_material_library.c b/source/blender/gpu/intern/gpu_material_library.c
new file mode 100644
index 00000000000..e7ec1bb12a2
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_material_library.c
@@ -0,0 +1,882 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * GPU material library parsing and code generation.
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_dynstr.h"
+#include "BLI_ghash.h"
+#include "BLI_string.h"
+
+#include "gpu_material_library.h"
+
+/* List of all gpu_shader_material_*.glsl files used by GLSL materials. These
+ * will be parsed to make all functions in them available to use for GPU_link().
+ *
+ * If a file uses functions from another file, it must be added to the list of
+ * dependencies, and be placed after that file in the list. */
+
+extern char datatoc_gpu_shader_material_add_shader_glsl[];
+extern char datatoc_gpu_shader_material_ambient_occlusion_glsl[];
+extern char datatoc_gpu_shader_material_anisotropic_glsl[];
+extern char datatoc_gpu_shader_material_attribute_glsl[];
+extern char datatoc_gpu_shader_material_background_glsl[];
+extern char datatoc_gpu_shader_material_bevel_glsl[];
+extern char datatoc_gpu_shader_material_blackbody_glsl[];
+extern char datatoc_gpu_shader_material_bright_contrast_glsl[];
+extern char datatoc_gpu_shader_material_bump_glsl[];
+extern char datatoc_gpu_shader_material_camera_glsl[];
+extern char datatoc_gpu_shader_material_clamp_glsl[];
+extern char datatoc_gpu_shader_material_color_ramp_glsl[];
+extern char datatoc_gpu_shader_material_color_util_glsl[];
+extern char datatoc_gpu_shader_material_combine_hsv_glsl[];
+extern char datatoc_gpu_shader_material_combine_rgb_glsl[];
+extern char datatoc_gpu_shader_material_combine_xyz_glsl[];
+extern char datatoc_gpu_shader_material_diffuse_glsl[];
+extern char datatoc_gpu_shader_material_displacement_glsl[];
+extern char datatoc_gpu_shader_material_eevee_specular_glsl[];
+extern char datatoc_gpu_shader_material_emission_glsl[];
+extern char datatoc_gpu_shader_material_fractal_noise_glsl[];
+extern char datatoc_gpu_shader_material_fresnel_glsl[];
+extern char datatoc_gpu_shader_material_gamma_glsl[];
+extern char datatoc_gpu_shader_material_geometry_glsl[];
+extern char datatoc_gpu_shader_material_glass_glsl[];
+extern char datatoc_gpu_shader_material_glossy_glsl[];
+extern char datatoc_gpu_shader_material_hair_info_glsl[];
+extern char datatoc_gpu_shader_material_hash_glsl[];
+extern char datatoc_gpu_shader_material_holdout_glsl[];
+extern char datatoc_gpu_shader_material_hue_sat_val_glsl[];
+extern char datatoc_gpu_shader_material_invert_glsl[];
+extern char datatoc_gpu_shader_material_layer_weight_glsl[];
+extern char datatoc_gpu_shader_material_light_falloff_glsl[];
+extern char datatoc_gpu_shader_material_light_path_glsl[];
+extern char datatoc_gpu_shader_material_mapping_glsl[];
+extern char datatoc_gpu_shader_material_map_range_glsl[];
+extern char datatoc_gpu_shader_material_math_glsl[];
+extern char datatoc_gpu_shader_material_math_util_glsl[];
+extern char datatoc_gpu_shader_material_mix_rgb_glsl[];
+extern char datatoc_gpu_shader_material_mix_shader_glsl[];
+extern char datatoc_gpu_shader_material_noise_glsl[];
+extern char datatoc_gpu_shader_material_normal_glsl[];
+extern char datatoc_gpu_shader_material_normal_map_glsl[];
+extern char datatoc_gpu_shader_material_object_info_glsl[];
+extern char datatoc_gpu_shader_material_output_material_glsl[];
+extern char datatoc_gpu_shader_material_output_world_glsl[];
+extern char datatoc_gpu_shader_material_particle_info_glsl[];
+extern char datatoc_gpu_shader_material_principled_glsl[];
+extern char datatoc_gpu_shader_material_refraction_glsl[];
+extern char datatoc_gpu_shader_material_rgb_curves_glsl[];
+extern char datatoc_gpu_shader_material_rgb_to_bw_glsl[];
+extern char datatoc_gpu_shader_material_separate_hsv_glsl[];
+extern char datatoc_gpu_shader_material_separate_rgb_glsl[];
+extern char datatoc_gpu_shader_material_separate_xyz_glsl[];
+extern char datatoc_gpu_shader_material_set_glsl[];
+extern char datatoc_gpu_shader_material_shader_to_rgba_glsl[];
+extern char datatoc_gpu_shader_material_squeeze_glsl[];
+extern char datatoc_gpu_shader_material_subsurface_scattering_glsl[];
+extern char datatoc_gpu_shader_material_tangent_glsl[];
+extern char datatoc_gpu_shader_material_tex_brick_glsl[];
+extern char datatoc_gpu_shader_material_tex_checker_glsl[];
+extern char datatoc_gpu_shader_material_tex_environment_glsl[];
+extern char datatoc_gpu_shader_material_tex_gradient_glsl[];
+extern char datatoc_gpu_shader_material_tex_image_glsl[];
+extern char datatoc_gpu_shader_material_tex_magic_glsl[];
+extern char datatoc_gpu_shader_material_tex_musgrave_glsl[];
+extern char datatoc_gpu_shader_material_tex_noise_glsl[];
+extern char datatoc_gpu_shader_material_tex_sky_glsl[];
+extern char datatoc_gpu_shader_material_texture_coordinates_glsl[];
+extern char datatoc_gpu_shader_material_tex_voronoi_glsl[];
+extern char datatoc_gpu_shader_material_tex_wave_glsl[];
+extern char datatoc_gpu_shader_material_tex_white_noise_glsl[];
+extern char datatoc_gpu_shader_material_toon_glsl[];
+extern char datatoc_gpu_shader_material_translucent_glsl[];
+extern char datatoc_gpu_shader_material_transparent_glsl[];
+extern char datatoc_gpu_shader_material_uv_map_glsl[];
+extern char datatoc_gpu_shader_material_vector_curves_glsl[];
+extern char datatoc_gpu_shader_material_vector_displacement_glsl[];
+extern char datatoc_gpu_shader_material_vector_math_glsl[];
+extern char datatoc_gpu_shader_material_velvet_glsl[];
+extern char datatoc_gpu_shader_material_vertex_color_glsl[];
+extern char datatoc_gpu_shader_material_volume_absorption_glsl[];
+extern char datatoc_gpu_shader_material_volume_info_glsl[];
+extern char datatoc_gpu_shader_material_volume_principled_glsl[];
+extern char datatoc_gpu_shader_material_volume_scatter_glsl[];
+extern char datatoc_gpu_shader_material_wireframe_glsl[];
+extern char datatoc_gpu_shader_material_world_normals_glsl[];
+
+static GPUMaterialLibrary gpu_shader_material_math_util_library = {
+ .code = datatoc_gpu_shader_material_math_util_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_color_util_library = {
+ .code = datatoc_gpu_shader_material_color_util_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_hash_library = {
+ .code = datatoc_gpu_shader_material_hash_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_noise_library = {
+ .code = datatoc_gpu_shader_material_noise_glsl,
+ .dependencies = {&gpu_shader_material_hash_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_fractal_noise_library = {
+ .code = datatoc_gpu_shader_material_fractal_noise_glsl,
+ .dependencies = {&gpu_shader_material_noise_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_add_shader_library = {
+ .code = datatoc_gpu_shader_material_add_shader_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_ambient_occlusion_library = {
+ .code = datatoc_gpu_shader_material_ambient_occlusion_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_glossy_library = {
+ .code = datatoc_gpu_shader_material_glossy_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_anisotropic_library = {
+ .code = datatoc_gpu_shader_material_anisotropic_glsl,
+ .dependencies = {&gpu_shader_material_glossy_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_attribute_library = {
+ .code = datatoc_gpu_shader_material_attribute_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_background_library = {
+ .code = datatoc_gpu_shader_material_background_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_bevel_library = {
+ .code = datatoc_gpu_shader_material_bevel_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_blackbody_library = {
+ .code = datatoc_gpu_shader_material_blackbody_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_bright_contrast_library = {
+ .code = datatoc_gpu_shader_material_bright_contrast_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_bump_library = {
+ .code = datatoc_gpu_shader_material_bump_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_camera_library = {
+ .code = datatoc_gpu_shader_material_camera_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_clamp_library = {
+ .code = datatoc_gpu_shader_material_clamp_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_color_ramp_library = {
+ .code = datatoc_gpu_shader_material_color_ramp_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_combine_hsv_library = {
+ .code = datatoc_gpu_shader_material_combine_hsv_glsl,
+ .dependencies = {&gpu_shader_material_color_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_combine_rgb_library = {
+ .code = datatoc_gpu_shader_material_combine_rgb_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_combine_xyz_library = {
+ .code = datatoc_gpu_shader_material_combine_xyz_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_diffuse_library = {
+ .code = datatoc_gpu_shader_material_diffuse_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_displacement_library = {
+ .code = datatoc_gpu_shader_material_displacement_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_eevee_specular_library = {
+ .code = datatoc_gpu_shader_material_eevee_specular_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_emission_library = {
+ .code = datatoc_gpu_shader_material_emission_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_fresnel_library = {
+ .code = datatoc_gpu_shader_material_fresnel_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_gamma_library = {
+ .code = datatoc_gpu_shader_material_gamma_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tangent_library = {
+ .code = datatoc_gpu_shader_material_tangent_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_geometry_library = {
+ .code = datatoc_gpu_shader_material_geometry_glsl,
+ .dependencies = {&gpu_shader_material_tangent_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_glass_library = {
+ .code = datatoc_gpu_shader_material_glass_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_hair_info_library = {
+ .code = datatoc_gpu_shader_material_hair_info_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_holdout_library = {
+ .code = datatoc_gpu_shader_material_holdout_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_hue_sat_val_library = {
+ .code = datatoc_gpu_shader_material_hue_sat_val_glsl,
+ .dependencies = {&gpu_shader_material_color_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_invert_library = {
+ .code = datatoc_gpu_shader_material_invert_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_layer_weight_library = {
+ .code = datatoc_gpu_shader_material_layer_weight_glsl,
+ .dependencies = {&gpu_shader_material_fresnel_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_light_falloff_library = {
+ .code = datatoc_gpu_shader_material_light_falloff_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_light_path_library = {
+ .code = datatoc_gpu_shader_material_light_path_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_mapping_library = {
+ .code = datatoc_gpu_shader_material_mapping_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_map_range_library = {
+ .code = datatoc_gpu_shader_material_map_range_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_math_library = {
+ .code = datatoc_gpu_shader_material_math_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_mix_rgb_library = {
+ .code = datatoc_gpu_shader_material_mix_rgb_glsl,
+ .dependencies = {&gpu_shader_material_color_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_mix_shader_library = {
+ .code = datatoc_gpu_shader_material_mix_shader_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_normal_library = {
+ .code = datatoc_gpu_shader_material_normal_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_normal_map_library = {
+ .code = datatoc_gpu_shader_material_normal_map_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_object_info_library = {
+ .code = datatoc_gpu_shader_material_object_info_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_output_material_library = {
+ .code = datatoc_gpu_shader_material_output_material_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_output_world_library = {
+ .code = datatoc_gpu_shader_material_output_world_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_particle_info_library = {
+ .code = datatoc_gpu_shader_material_particle_info_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_principled_library = {
+ .code = datatoc_gpu_shader_material_principled_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_refraction_library = {
+ .code = datatoc_gpu_shader_material_refraction_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_rgb_curves_library = {
+ .code = datatoc_gpu_shader_material_rgb_curves_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_rgb_to_bw_library = {
+ .code = datatoc_gpu_shader_material_rgb_to_bw_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_separate_hsv_library = {
+ .code = datatoc_gpu_shader_material_separate_hsv_glsl,
+ .dependencies = {&gpu_shader_material_color_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_separate_rgb_library = {
+ .code = datatoc_gpu_shader_material_separate_rgb_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_separate_xyz_library = {
+ .code = datatoc_gpu_shader_material_separate_xyz_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_set_library = {
+ .code = datatoc_gpu_shader_material_set_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_shader_to_rgba_library = {
+ .code = datatoc_gpu_shader_material_shader_to_rgba_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_squeeze_library = {
+ .code = datatoc_gpu_shader_material_squeeze_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_subsurface_scattering_library = {
+ .code = datatoc_gpu_shader_material_subsurface_scattering_glsl,
+ .dependencies = {&gpu_shader_material_diffuse_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_brick_library = {
+ .code = datatoc_gpu_shader_material_tex_brick_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library,
+ &gpu_shader_material_hash_library,
+ NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_checker_library = {
+ .code = datatoc_gpu_shader_material_tex_checker_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_environment_library = {
+ .code = datatoc_gpu_shader_material_tex_environment_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_gradient_library = {
+ .code = datatoc_gpu_shader_material_tex_gradient_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_image_library = {
+ .code = datatoc_gpu_shader_material_tex_image_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_magic_library = {
+ .code = datatoc_gpu_shader_material_tex_magic_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_musgrave_library = {
+ .code = datatoc_gpu_shader_material_tex_musgrave_glsl,
+ .dependencies = {&gpu_shader_material_noise_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_noise_library = {
+ .code = datatoc_gpu_shader_material_tex_noise_glsl,
+ .dependencies = {&gpu_shader_material_fractal_noise_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_sky_library = {
+ .code = datatoc_gpu_shader_material_tex_sky_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_texture_coordinates_library = {
+ .code = datatoc_gpu_shader_material_texture_coordinates_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_voronoi_library = {
+ .code = datatoc_gpu_shader_material_tex_voronoi_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library,
+ &gpu_shader_material_hash_library,
+ NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_wave_library = {
+ .code = datatoc_gpu_shader_material_tex_wave_glsl,
+ .dependencies = {&gpu_shader_material_fractal_noise_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_white_noise_library = {
+ .code = datatoc_gpu_shader_material_tex_white_noise_glsl,
+ .dependencies = {&gpu_shader_material_hash_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_toon_library = {
+ .code = datatoc_gpu_shader_material_toon_glsl,
+ .dependencies = {&gpu_shader_material_diffuse_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_translucent_library = {
+ .code = datatoc_gpu_shader_material_translucent_glsl,
+ .dependencies = {&gpu_shader_material_diffuse_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_transparent_library = {
+ .code = datatoc_gpu_shader_material_transparent_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_uv_map_library = {
+ .code = datatoc_gpu_shader_material_uv_map_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_vector_curves_library = {
+ .code = datatoc_gpu_shader_material_vector_curves_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_vector_displacement_library = {
+ .code = datatoc_gpu_shader_material_vector_displacement_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_vector_math_library = {
+ .code = datatoc_gpu_shader_material_vector_math_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_velvet_library = {
+ .code = datatoc_gpu_shader_material_velvet_glsl,
+ .dependencies = {&gpu_shader_material_diffuse_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_vertex_color_library = {
+ .code = datatoc_gpu_shader_material_vertex_color_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_volume_absorption_library = {
+ .code = datatoc_gpu_shader_material_volume_absorption_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_volume_info_library = {
+ .code = datatoc_gpu_shader_material_volume_info_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_volume_principled_library = {
+ .code = datatoc_gpu_shader_material_volume_principled_glsl,
+ .dependencies = {&gpu_shader_material_blackbody_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_volume_scatter_library = {
+ .code = datatoc_gpu_shader_material_volume_scatter_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_wireframe_library = {
+ .code = datatoc_gpu_shader_material_wireframe_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_world_normals_library = {
+ .code = datatoc_gpu_shader_material_world_normals_glsl,
+ .dependencies = {&gpu_shader_material_texture_coordinates_library, NULL},
+};
+
+static GPUMaterialLibrary *gpu_material_libraries[] = {
+ &gpu_shader_material_math_util_library,
+ &gpu_shader_material_color_util_library,
+ &gpu_shader_material_hash_library,
+ &gpu_shader_material_noise_library,
+ &gpu_shader_material_fractal_noise_library,
+ &gpu_shader_material_add_shader_library,
+ &gpu_shader_material_ambient_occlusion_library,
+ &gpu_shader_material_glossy_library,
+ &gpu_shader_material_anisotropic_library,
+ &gpu_shader_material_attribute_library,
+ &gpu_shader_material_background_library,
+ &gpu_shader_material_bevel_library,
+ &gpu_shader_material_blackbody_library,
+ &gpu_shader_material_bright_contrast_library,
+ &gpu_shader_material_bump_library,
+ &gpu_shader_material_camera_library,
+ &gpu_shader_material_clamp_library,
+ &gpu_shader_material_color_ramp_library,
+ &gpu_shader_material_combine_hsv_library,
+ &gpu_shader_material_combine_rgb_library,
+ &gpu_shader_material_combine_xyz_library,
+ &gpu_shader_material_diffuse_library,
+ &gpu_shader_material_displacement_library,
+ &gpu_shader_material_eevee_specular_library,
+ &gpu_shader_material_emission_library,
+ &gpu_shader_material_fresnel_library,
+ &gpu_shader_material_gamma_library,
+ &gpu_shader_material_tangent_library,
+ &gpu_shader_material_geometry_library,
+ &gpu_shader_material_glass_library,
+ &gpu_shader_material_hair_info_library,
+ &gpu_shader_material_holdout_library,
+ &gpu_shader_material_hue_sat_val_library,
+ &gpu_shader_material_invert_library,
+ &gpu_shader_material_layer_weight_library,
+ &gpu_shader_material_light_falloff_library,
+ &gpu_shader_material_light_path_library,
+ &gpu_shader_material_mapping_library,
+ &gpu_shader_material_map_range_library,
+ &gpu_shader_material_math_library,
+ &gpu_shader_material_mix_rgb_library,
+ &gpu_shader_material_mix_shader_library,
+ &gpu_shader_material_normal_library,
+ &gpu_shader_material_normal_map_library,
+ &gpu_shader_material_object_info_library,
+ &gpu_shader_material_output_material_library,
+ &gpu_shader_material_output_world_library,
+ &gpu_shader_material_particle_info_library,
+ &gpu_shader_material_principled_library,
+ &gpu_shader_material_refraction_library,
+ &gpu_shader_material_rgb_curves_library,
+ &gpu_shader_material_rgb_to_bw_library,
+ &gpu_shader_material_separate_hsv_library,
+ &gpu_shader_material_separate_rgb_library,
+ &gpu_shader_material_separate_xyz_library,
+ &gpu_shader_material_set_library,
+ &gpu_shader_material_shader_to_rgba_library,
+ &gpu_shader_material_squeeze_library,
+ &gpu_shader_material_subsurface_scattering_library,
+ &gpu_shader_material_tex_brick_library,
+ &gpu_shader_material_tex_checker_library,
+ &gpu_shader_material_tex_environment_library,
+ &gpu_shader_material_tex_gradient_library,
+ &gpu_shader_material_tex_image_library,
+ &gpu_shader_material_tex_magic_library,
+ &gpu_shader_material_tex_musgrave_library,
+ &gpu_shader_material_tex_noise_library,
+ &gpu_shader_material_tex_sky_library,
+ &gpu_shader_material_texture_coordinates_library,
+ &gpu_shader_material_tex_voronoi_library,
+ &gpu_shader_material_tex_wave_library,
+ &gpu_shader_material_tex_white_noise_library,
+ &gpu_shader_material_toon_library,
+ &gpu_shader_material_translucent_library,
+ &gpu_shader_material_transparent_library,
+ &gpu_shader_material_uv_map_library,
+ &gpu_shader_material_vector_curves_library,
+ &gpu_shader_material_vector_displacement_library,
+ &gpu_shader_material_vector_math_library,
+ &gpu_shader_material_velvet_library,
+ &gpu_shader_material_vertex_color_library,
+ &gpu_shader_material_volume_absorption_library,
+ &gpu_shader_material_volume_info_library,
+ &gpu_shader_material_volume_principled_library,
+ &gpu_shader_material_volume_scatter_library,
+ &gpu_shader_material_wireframe_library,
+ &gpu_shader_material_world_normals_library,
+ NULL};
+
+/* GLSL code parsing for finding function definitions.
+ * These are stored in a hash for lookup when creating a material. */
+
+static GHash *FUNCTION_HASH = NULL;
+
+char *gpu_str_skip_token(char *str, char *token, int max)
+{
+ int len = 0;
+
+ /* skip a variable/function name */
+ while (*str) {
+ if (ELEM(*str, ' ', '(', ')', ',', ';', '\t', '\n', '\r')) {
+ break;
+ }
+ else {
+ if (token && len < max - 1) {
+ *token = *str;
+ token++;
+ len++;
+ }
+ str++;
+ }
+ }
+
+ if (token) {
+ *token = '\0';
+ }
+
+ /* skip the next special characters:
+ * note the missing ')' */
+ while (*str) {
+ if (ELEM(*str, ' ', '(', ',', ';', '\t', '\n', '\r')) {
+ str++;
+ }
+ else {
+ break;
+ }
+ }
+
+ return str;
+}
+
+/* Indices match the eGPUType enum */
+static const char *GPU_DATATYPE_STR[17] = {
+ "",
+ "float",
+ "vec2",
+ "vec3",
+ "vec4",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "mat3",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "mat4",
+};
+
+const char *gpu_data_type_to_string(const eGPUType type)
+{
+ return GPU_DATATYPE_STR[type];
+}
+
+static void gpu_parse_material_library(GHash *hash, GPUMaterialLibrary *library)
+{
+ GPUFunction *function;
+ eGPUType type;
+ GPUFunctionQual qual;
+ int i;
+ char *code = library->code;
+
+ while ((code = strstr(code, "void "))) {
+ function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
+ function->library = library;
+
+ code = gpu_str_skip_token(code, NULL, 0);
+ code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
+
+ /* get parameters */
+ while (*code && *code != ')') {
+ /* test if it's an input or output */
+ qual = FUNCTION_QUAL_IN;
+ if (BLI_str_startswith(code, "out ")) {
+ qual = FUNCTION_QUAL_OUT;
+ }
+ if (BLI_str_startswith(code, "inout ")) {
+ qual = FUNCTION_QUAL_INOUT;
+ }
+ if ((qual != FUNCTION_QUAL_IN) || BLI_str_startswith(code, "in ")) {
+ code = gpu_str_skip_token(code, NULL, 0);
+ }
+
+ /* test for type */
+ type = GPU_NONE;
+ for (i = 1; i < ARRAY_SIZE(GPU_DATATYPE_STR); i++) {
+ if (GPU_DATATYPE_STR[i] && BLI_str_startswith(code, GPU_DATATYPE_STR[i])) {
+ type = i;
+ break;
+ }
+ }
+
+ if (!type && BLI_str_startswith(code, "samplerCube")) {
+ type = GPU_TEXCUBE;
+ }
+ if (!type && BLI_str_startswith(code, "sampler2DShadow")) {
+ type = GPU_SHADOW2D;
+ }
+ if (!type && BLI_str_startswith(code, "sampler1DArray")) {
+ type = GPU_TEX1D_ARRAY;
+ }
+ if (!type && BLI_str_startswith(code, "sampler2DArray")) {
+ type = GPU_TEX2D_ARRAY;
+ }
+ if (!type && BLI_str_startswith(code, "sampler2D")) {
+ type = GPU_TEX2D;
+ }
+ if (!type && BLI_str_startswith(code, "sampler3D")) {
+ type = GPU_TEX3D;
+ }
+
+ if (!type && BLI_str_startswith(code, "Closure")) {
+ type = GPU_CLOSURE;
+ }
+
+ if (type) {
+ /* add parameter */
+ code = gpu_str_skip_token(code, NULL, 0);
+ code = gpu_str_skip_token(code, NULL, 0);
+ function->paramqual[function->totparam] = qual;
+ function->paramtype[function->totparam] = type;
+ function->totparam++;
+ }
+ else {
+ fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name);
+ break;
+ }
+ }
+
+ if (function->name[0] == '\0' || function->totparam == 0) {
+ fprintf(stderr, "GPU functions parse error.\n");
+ MEM_freeN(function);
+ break;
+ }
+
+ BLI_ghash_insert(hash, function->name, function);
+ }
+}
+
+/* Module */
+
+void gpu_material_library_init(void)
+{
+ /* Only parse GLSL shader files once. */
+ if (FUNCTION_HASH) {
+ return;
+ }
+
+ FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
+ for (int i = 0; gpu_material_libraries[i]; i++) {
+ gpu_parse_material_library(FUNCTION_HASH, gpu_material_libraries[i]);
+ }
+}
+
+void gpu_material_library_exit(void)
+{
+ if (FUNCTION_HASH) {
+ BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
+ FUNCTION_HASH = NULL;
+ }
+}
+
+/* Code Generation */
+
+static void gpu_material_use_library_with_dependencies(GSet *used_libraries,
+ GPUMaterialLibrary *library)
+{
+ if (BLI_gset_add(used_libraries, library->code)) {
+ for (int i = 0; library->dependencies[i]; i++) {
+ gpu_material_use_library_with_dependencies(used_libraries, library->dependencies[i]);
+ }
+ }
+}
+
+GPUFunction *gpu_material_library_use_function(GSet *used_libraries, const char *name)
+{
+ GPUFunction *function = BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
+ if (function) {
+ gpu_material_use_library_with_dependencies(used_libraries, function->library);
+ }
+ return function;
+}
+
+char *gpu_material_library_generate_code(GSet *used_libraries, const char *frag_lib)
+{
+ DynStr *ds = BLI_dynstr_new();
+
+ if (frag_lib) {
+ BLI_dynstr_append(ds, frag_lib);
+ }
+
+ /* Always include those because they may be needed by the execution function. */
+ gpu_material_use_library_with_dependencies(used_libraries,
+ &gpu_shader_material_world_normals_library);
+
+ /* Add library code in order, for dependencies. */
+ for (int i = 0; gpu_material_libraries[i]; i++) {
+ GPUMaterialLibrary *library = gpu_material_libraries[i];
+ if (BLI_gset_haskey(used_libraries, library->code)) {
+ BLI_dynstr_append(ds, library->code);
+ }
+ }
+
+ char *result = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return result;
+}
+
diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h
index 0d697a31c35..f69c25b9490 100644
--- a/source/blender/gpu/intern/gpu_material_library.h
+++ b/source/blender/gpu/intern/gpu_material_library.h
@@ -20,634 +20,50 @@
/** \file
* \ingroup gpu
*
- * List of all gpu_shader_material_*.glsl files used by GLSL materials. These
- * will be parsed to make all functions in them available to use for GPU_link().
- *
- * If a file uses functions from another file, it must be added to the list of
- * dependencies, and be placed after that file in the list. */
+ * Parsing of and code generation using GLSL shaders in gpu/shaders/material. */
#ifndef __GPU_MATERIAL_LIBRARY_H__
#define __GPU_MATERIAL_LIBRARY_H__
+#include "GPU_material.h"
+
+#define MAX_FUNCTION_NAME 64
+#define MAX_PARAMETER 32
+
+struct GSet;
+
typedef struct GPUMaterialLibrary {
char *code;
struct GPUMaterialLibrary *dependencies[8];
} GPUMaterialLibrary;
-extern char datatoc_gpu_shader_material_add_shader_glsl[];
-extern char datatoc_gpu_shader_material_ambient_occlusion_glsl[];
-extern char datatoc_gpu_shader_material_anisotropic_glsl[];
-extern char datatoc_gpu_shader_material_attribute_glsl[];
-extern char datatoc_gpu_shader_material_background_glsl[];
-extern char datatoc_gpu_shader_material_bevel_glsl[];
-extern char datatoc_gpu_shader_material_blackbody_glsl[];
-extern char datatoc_gpu_shader_material_bright_contrast_glsl[];
-extern char datatoc_gpu_shader_material_bump_glsl[];
-extern char datatoc_gpu_shader_material_camera_glsl[];
-extern char datatoc_gpu_shader_material_clamp_glsl[];
-extern char datatoc_gpu_shader_material_color_ramp_glsl[];
-extern char datatoc_gpu_shader_material_color_util_glsl[];
-extern char datatoc_gpu_shader_material_combine_hsv_glsl[];
-extern char datatoc_gpu_shader_material_combine_rgb_glsl[];
-extern char datatoc_gpu_shader_material_combine_xyz_glsl[];
-extern char datatoc_gpu_shader_material_diffuse_glsl[];
-extern char datatoc_gpu_shader_material_displacement_glsl[];
-extern char datatoc_gpu_shader_material_eevee_specular_glsl[];
-extern char datatoc_gpu_shader_material_emission_glsl[];
-extern char datatoc_gpu_shader_material_fractal_noise_glsl[];
-extern char datatoc_gpu_shader_material_fresnel_glsl[];
-extern char datatoc_gpu_shader_material_gamma_glsl[];
-extern char datatoc_gpu_shader_material_geometry_glsl[];
-extern char datatoc_gpu_shader_material_glass_glsl[];
-extern char datatoc_gpu_shader_material_glossy_glsl[];
-extern char datatoc_gpu_shader_material_hair_info_glsl[];
-extern char datatoc_gpu_shader_material_hash_glsl[];
-extern char datatoc_gpu_shader_material_holdout_glsl[];
-extern char datatoc_gpu_shader_material_hue_sat_val_glsl[];
-extern char datatoc_gpu_shader_material_invert_glsl[];
-extern char datatoc_gpu_shader_material_layer_weight_glsl[];
-extern char datatoc_gpu_shader_material_light_falloff_glsl[];
-extern char datatoc_gpu_shader_material_light_path_glsl[];
-extern char datatoc_gpu_shader_material_mapping_glsl[];
-extern char datatoc_gpu_shader_material_map_range_glsl[];
-extern char datatoc_gpu_shader_material_math_glsl[];
-extern char datatoc_gpu_shader_material_math_util_glsl[];
-extern char datatoc_gpu_shader_material_mix_rgb_glsl[];
-extern char datatoc_gpu_shader_material_mix_shader_glsl[];
-extern char datatoc_gpu_shader_material_noise_glsl[];
-extern char datatoc_gpu_shader_material_normal_glsl[];
-extern char datatoc_gpu_shader_material_normal_map_glsl[];
-extern char datatoc_gpu_shader_material_object_info_glsl[];
-extern char datatoc_gpu_shader_material_output_material_glsl[];
-extern char datatoc_gpu_shader_material_output_world_glsl[];
-extern char datatoc_gpu_shader_material_particle_info_glsl[];
-extern char datatoc_gpu_shader_material_principled_glsl[];
-extern char datatoc_gpu_shader_material_refraction_glsl[];
-extern char datatoc_gpu_shader_material_rgb_curves_glsl[];
-extern char datatoc_gpu_shader_material_rgb_to_bw_glsl[];
-extern char datatoc_gpu_shader_material_separate_hsv_glsl[];
-extern char datatoc_gpu_shader_material_separate_rgb_glsl[];
-extern char datatoc_gpu_shader_material_separate_xyz_glsl[];
-extern char datatoc_gpu_shader_material_set_glsl[];
-extern char datatoc_gpu_shader_material_shader_to_rgba_glsl[];
-extern char datatoc_gpu_shader_material_squeeze_glsl[];
-extern char datatoc_gpu_shader_material_subsurface_scattering_glsl[];
-extern char datatoc_gpu_shader_material_tangent_glsl[];
-extern char datatoc_gpu_shader_material_tex_brick_glsl[];
-extern char datatoc_gpu_shader_material_tex_checker_glsl[];
-extern char datatoc_gpu_shader_material_tex_environment_glsl[];
-extern char datatoc_gpu_shader_material_tex_gradient_glsl[];
-extern char datatoc_gpu_shader_material_tex_image_glsl[];
-extern char datatoc_gpu_shader_material_tex_magic_glsl[];
-extern char datatoc_gpu_shader_material_tex_musgrave_glsl[];
-extern char datatoc_gpu_shader_material_tex_noise_glsl[];
-extern char datatoc_gpu_shader_material_tex_sky_glsl[];
-extern char datatoc_gpu_shader_material_texture_coordinates_glsl[];
-extern char datatoc_gpu_shader_material_tex_voronoi_glsl[];
-extern char datatoc_gpu_shader_material_tex_wave_glsl[];
-extern char datatoc_gpu_shader_material_tex_white_noise_glsl[];
-extern char datatoc_gpu_shader_material_toon_glsl[];
-extern char datatoc_gpu_shader_material_translucent_glsl[];
-extern char datatoc_gpu_shader_material_transparent_glsl[];
-extern char datatoc_gpu_shader_material_uv_map_glsl[];
-extern char datatoc_gpu_shader_material_vector_curves_glsl[];
-extern char datatoc_gpu_shader_material_vector_displacement_glsl[];
-extern char datatoc_gpu_shader_material_vector_math_glsl[];
-extern char datatoc_gpu_shader_material_velvet_glsl[];
-extern char datatoc_gpu_shader_material_vertex_color_glsl[];
-extern char datatoc_gpu_shader_material_volume_absorption_glsl[];
-extern char datatoc_gpu_shader_material_volume_info_glsl[];
-extern char datatoc_gpu_shader_material_volume_principled_glsl[];
-extern char datatoc_gpu_shader_material_volume_scatter_glsl[];
-extern char datatoc_gpu_shader_material_wireframe_glsl[];
-extern char datatoc_gpu_shader_material_world_normals_glsl[];
-
-static GPUMaterialLibrary gpu_shader_material_math_util_library = {
- .code = datatoc_gpu_shader_material_math_util_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_color_util_library = {
- .code = datatoc_gpu_shader_material_color_util_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_hash_library = {
- .code = datatoc_gpu_shader_material_hash_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_noise_library = {
- .code = datatoc_gpu_shader_material_noise_glsl,
- .dependencies = {&gpu_shader_material_hash_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_fractal_noise_library = {
- .code = datatoc_gpu_shader_material_fractal_noise_glsl,
- .dependencies = {&gpu_shader_material_noise_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_add_shader_library = {
- .code = datatoc_gpu_shader_material_add_shader_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_ambient_occlusion_library = {
- .code = datatoc_gpu_shader_material_ambient_occlusion_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_glossy_library = {
- .code = datatoc_gpu_shader_material_glossy_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_anisotropic_library = {
- .code = datatoc_gpu_shader_material_anisotropic_glsl,
- .dependencies = {&gpu_shader_material_glossy_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_attribute_library = {
- .code = datatoc_gpu_shader_material_attribute_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_background_library = {
- .code = datatoc_gpu_shader_material_background_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_bevel_library = {
- .code = datatoc_gpu_shader_material_bevel_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_blackbody_library = {
- .code = datatoc_gpu_shader_material_blackbody_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_bright_contrast_library = {
- .code = datatoc_gpu_shader_material_bright_contrast_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_bump_library = {
- .code = datatoc_gpu_shader_material_bump_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_camera_library = {
- .code = datatoc_gpu_shader_material_camera_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_clamp_library = {
- .code = datatoc_gpu_shader_material_clamp_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_color_ramp_library = {
- .code = datatoc_gpu_shader_material_color_ramp_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_combine_hsv_library = {
- .code = datatoc_gpu_shader_material_combine_hsv_glsl,
- .dependencies = {&gpu_shader_material_color_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_combine_rgb_library = {
- .code = datatoc_gpu_shader_material_combine_rgb_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_combine_xyz_library = {
- .code = datatoc_gpu_shader_material_combine_xyz_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_diffuse_library = {
- .code = datatoc_gpu_shader_material_diffuse_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_displacement_library = {
- .code = datatoc_gpu_shader_material_displacement_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_eevee_specular_library = {
- .code = datatoc_gpu_shader_material_eevee_specular_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_emission_library = {
- .code = datatoc_gpu_shader_material_emission_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_fresnel_library = {
- .code = datatoc_gpu_shader_material_fresnel_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_gamma_library = {
- .code = datatoc_gpu_shader_material_gamma_glsl,
- .dependencies = {&gpu_shader_material_math_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tangent_library = {
- .code = datatoc_gpu_shader_material_tangent_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_geometry_library = {
- .code = datatoc_gpu_shader_material_geometry_glsl,
- .dependencies = {&gpu_shader_material_tangent_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_glass_library = {
- .code = datatoc_gpu_shader_material_glass_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_hair_info_library = {
- .code = datatoc_gpu_shader_material_hair_info_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_holdout_library = {
- .code = datatoc_gpu_shader_material_holdout_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_hue_sat_val_library = {
- .code = datatoc_gpu_shader_material_hue_sat_val_glsl,
- .dependencies = {&gpu_shader_material_color_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_invert_library = {
- .code = datatoc_gpu_shader_material_invert_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_layer_weight_library = {
- .code = datatoc_gpu_shader_material_layer_weight_glsl,
- .dependencies = {&gpu_shader_material_fresnel_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_light_falloff_library = {
- .code = datatoc_gpu_shader_material_light_falloff_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_light_path_library = {
- .code = datatoc_gpu_shader_material_light_path_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_mapping_library = {
- .code = datatoc_gpu_shader_material_mapping_glsl,
- .dependencies = {&gpu_shader_material_math_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_map_range_library = {
- .code = datatoc_gpu_shader_material_map_range_glsl,
- .dependencies = {&gpu_shader_material_math_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_math_library = {
- .code = datatoc_gpu_shader_material_math_glsl,
- .dependencies = {&gpu_shader_material_math_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_mix_rgb_library = {
- .code = datatoc_gpu_shader_material_mix_rgb_glsl,
- .dependencies = {&gpu_shader_material_color_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_mix_shader_library = {
- .code = datatoc_gpu_shader_material_mix_shader_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_normal_library = {
- .code = datatoc_gpu_shader_material_normal_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_normal_map_library = {
- .code = datatoc_gpu_shader_material_normal_map_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_object_info_library = {
- .code = datatoc_gpu_shader_material_object_info_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_output_material_library = {
- .code = datatoc_gpu_shader_material_output_material_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_output_world_library = {
- .code = datatoc_gpu_shader_material_output_world_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_particle_info_library = {
- .code = datatoc_gpu_shader_material_particle_info_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_principled_library = {
- .code = datatoc_gpu_shader_material_principled_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_refraction_library = {
- .code = datatoc_gpu_shader_material_refraction_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_rgb_curves_library = {
- .code = datatoc_gpu_shader_material_rgb_curves_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_rgb_to_bw_library = {
- .code = datatoc_gpu_shader_material_rgb_to_bw_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_separate_hsv_library = {
- .code = datatoc_gpu_shader_material_separate_hsv_glsl,
- .dependencies = {&gpu_shader_material_color_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_separate_rgb_library = {
- .code = datatoc_gpu_shader_material_separate_rgb_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_separate_xyz_library = {
- .code = datatoc_gpu_shader_material_separate_xyz_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_set_library = {
- .code = datatoc_gpu_shader_material_set_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_shader_to_rgba_library = {
- .code = datatoc_gpu_shader_material_shader_to_rgba_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_squeeze_library = {
- .code = datatoc_gpu_shader_material_squeeze_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_subsurface_scattering_library = {
- .code = datatoc_gpu_shader_material_subsurface_scattering_glsl,
- .dependencies = {&gpu_shader_material_diffuse_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_brick_library = {
- .code = datatoc_gpu_shader_material_tex_brick_glsl,
- .dependencies = {&gpu_shader_material_math_util_library,
- &gpu_shader_material_hash_library,
- NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_checker_library = {
- .code = datatoc_gpu_shader_material_tex_checker_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_environment_library = {
- .code = datatoc_gpu_shader_material_tex_environment_glsl,
- .dependencies = {&gpu_shader_material_math_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_gradient_library = {
- .code = datatoc_gpu_shader_material_tex_gradient_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_image_library = {
- .code = datatoc_gpu_shader_material_tex_image_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_magic_library = {
- .code = datatoc_gpu_shader_material_tex_magic_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_musgrave_library = {
- .code = datatoc_gpu_shader_material_tex_musgrave_glsl,
- .dependencies = {&gpu_shader_material_noise_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_noise_library = {
- .code = datatoc_gpu_shader_material_tex_noise_glsl,
- .dependencies = {&gpu_shader_material_fractal_noise_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_sky_library = {
- .code = datatoc_gpu_shader_material_tex_sky_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_texture_coordinates_library = {
- .code = datatoc_gpu_shader_material_texture_coordinates_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_voronoi_library = {
- .code = datatoc_gpu_shader_material_tex_voronoi_glsl,
- .dependencies = {&gpu_shader_material_math_util_library,
- &gpu_shader_material_hash_library,
- NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_wave_library = {
- .code = datatoc_gpu_shader_material_tex_wave_glsl,
- .dependencies = {&gpu_shader_material_fractal_noise_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_tex_white_noise_library = {
- .code = datatoc_gpu_shader_material_tex_white_noise_glsl,
- .dependencies = {&gpu_shader_material_hash_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_toon_library = {
- .code = datatoc_gpu_shader_material_toon_glsl,
- .dependencies = {&gpu_shader_material_diffuse_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_translucent_library = {
- .code = datatoc_gpu_shader_material_translucent_glsl,
- .dependencies = {&gpu_shader_material_diffuse_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_transparent_library = {
- .code = datatoc_gpu_shader_material_transparent_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_uv_map_library = {
- .code = datatoc_gpu_shader_material_uv_map_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_vector_curves_library = {
- .code = datatoc_gpu_shader_material_vector_curves_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_vector_displacement_library = {
- .code = datatoc_gpu_shader_material_vector_displacement_glsl,
- .dependencies = {NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_vector_math_library = {
- .code = datatoc_gpu_shader_material_vector_math_glsl,
- .dependencies = {&gpu_shader_material_math_util_library, NULL},
-};
-
-static GPUMaterialLibrary gpu_shader_material_velvet_library = {
- .code = datatoc_gpu_shader_material_velvet_glsl,
- .dependencies = {&gpu_shader_material_diffuse_library, NULL},
-};
+typedef enum {
+ FUNCTION_QUAL_IN,
+ FUNCTION_QUAL_OUT,
+ FUNCTION_QUAL_INOUT,
+} GPUFunctionQual;
-static GPUMaterialLibrary gpu_shader_material_vertex_color_library = {
- .code = datatoc_gpu_shader_material_vertex_color_glsl,
- .dependencies = {NULL},
-};
+typedef struct GPUFunction {
+ char name[MAX_FUNCTION_NAME];
+ eGPUType paramtype[MAX_PARAMETER];
+ GPUFunctionQual paramqual[MAX_PARAMETER];
+ int totparam;
+ GPUMaterialLibrary *library;
+} GPUFunction;
-static GPUMaterialLibrary gpu_shader_material_volume_absorption_library = {
- .code = datatoc_gpu_shader_material_volume_absorption_glsl,
- .dependencies = {NULL},
-};
+/* Module */
-static GPUMaterialLibrary gpu_shader_material_volume_info_library = {
- .code = datatoc_gpu_shader_material_volume_info_glsl,
- .dependencies = {NULL},
-};
+void gpu_material_library_init(void);
+void gpu_material_library_exit(void);
-static GPUMaterialLibrary gpu_shader_material_volume_principled_library = {
- .code = datatoc_gpu_shader_material_volume_principled_glsl,
- .dependencies = {&gpu_shader_material_blackbody_library, NULL},
-};
+/* Code Generation */
-static GPUMaterialLibrary gpu_shader_material_volume_scatter_library = {
- .code = datatoc_gpu_shader_material_volume_scatter_glsl,
- .dependencies = {NULL},
-};
+GPUFunction *gpu_material_library_use_function(struct GSet *used_libraries, const char *name);
+char *gpu_material_library_generate_code(struct GSet *used_libraries, const char *frag_lib);
-static GPUMaterialLibrary gpu_shader_material_wireframe_library = {
- .code = datatoc_gpu_shader_material_wireframe_glsl,
- .dependencies = {NULL},
-};
+/* Code Parsing */
-static GPUMaterialLibrary gpu_shader_material_world_normals_library = {
- .code = datatoc_gpu_shader_material_world_normals_glsl,
- .dependencies = {&gpu_shader_material_texture_coordinates_library, NULL},
-};
+char *gpu_str_skip_token(char *str, char *token, int max);
+const char *gpu_data_type_to_string(const eGPUType type);
-static GPUMaterialLibrary *gpu_material_libraries[] = {
- &gpu_shader_material_math_util_library,
- &gpu_shader_material_color_util_library,
- &gpu_shader_material_hash_library,
- &gpu_shader_material_noise_library,
- &gpu_shader_material_fractal_noise_library,
- &gpu_shader_material_add_shader_library,
- &gpu_shader_material_ambient_occlusion_library,
- &gpu_shader_material_glossy_library,
- &gpu_shader_material_anisotropic_library,
- &gpu_shader_material_attribute_library,
- &gpu_shader_material_background_library,
- &gpu_shader_material_bevel_library,
- &gpu_shader_material_blackbody_library,
- &gpu_shader_material_bright_contrast_library,
- &gpu_shader_material_bump_library,
- &gpu_shader_material_camera_library,
- &gpu_shader_material_clamp_library,
- &gpu_shader_material_color_ramp_library,
- &gpu_shader_material_combine_hsv_library,
- &gpu_shader_material_combine_rgb_library,
- &gpu_shader_material_combine_xyz_library,
- &gpu_shader_material_diffuse_library,
- &gpu_shader_material_displacement_library,
- &gpu_shader_material_eevee_specular_library,
- &gpu_shader_material_emission_library,
- &gpu_shader_material_fresnel_library,
- &gpu_shader_material_gamma_library,
- &gpu_shader_material_tangent_library,
- &gpu_shader_material_geometry_library,
- &gpu_shader_material_glass_library,
- &gpu_shader_material_hair_info_library,
- &gpu_shader_material_holdout_library,
- &gpu_shader_material_hue_sat_val_library,
- &gpu_shader_material_invert_library,
- &gpu_shader_material_layer_weight_library,
- &gpu_shader_material_light_falloff_library,
- &gpu_shader_material_light_path_library,
- &gpu_shader_material_mapping_library,
- &gpu_shader_material_map_range_library,
- &gpu_shader_material_math_library,
- &gpu_shader_material_mix_rgb_library,
- &gpu_shader_material_mix_shader_library,
- &gpu_shader_material_normal_library,
- &gpu_shader_material_normal_map_library,
- &gpu_shader_material_object_info_library,
- &gpu_shader_material_output_material_library,
- &gpu_shader_material_output_world_library,
- &gpu_shader_material_particle_info_library,
- &gpu_shader_material_principled_library,
- &gpu_shader_material_refraction_library,
- &gpu_shader_material_rgb_curves_library,
- &gpu_shader_material_rgb_to_bw_library,
- &gpu_shader_material_separate_hsv_library,
- &gpu_shader_material_separate_rgb_library,
- &gpu_shader_material_separate_xyz_library,
- &gpu_shader_material_set_library,
- &gpu_shader_material_shader_to_rgba_library,
- &gpu_shader_material_squeeze_library,
- &gpu_shader_material_subsurface_scattering_library,
- &gpu_shader_material_tex_brick_library,
- &gpu_shader_material_tex_checker_library,
- &gpu_shader_material_tex_environment_library,
- &gpu_shader_material_tex_gradient_library,
- &gpu_shader_material_tex_image_library,
- &gpu_shader_material_tex_magic_library,
- &gpu_shader_material_tex_musgrave_library,
- &gpu_shader_material_tex_noise_library,
- &gpu_shader_material_tex_sky_library,
- &gpu_shader_material_texture_coordinates_library,
- &gpu_shader_material_tex_voronoi_library,
- &gpu_shader_material_tex_wave_library,
- &gpu_shader_material_tex_white_noise_library,
- &gpu_shader_material_toon_library,
- &gpu_shader_material_translucent_library,
- &gpu_shader_material_transparent_library,
- &gpu_shader_material_uv_map_library,
- &gpu_shader_material_vector_curves_library,
- &gpu_shader_material_vector_displacement_library,
- &gpu_shader_material_vector_math_library,
- &gpu_shader_material_velvet_library,
- &gpu_shader_material_vertex_color_library,
- &gpu_shader_material_volume_absorption_library,
- &gpu_shader_material_volume_info_library,
- &gpu_shader_material_volume_principled_library,
- &gpu_shader_material_volume_scatter_library,
- &gpu_shader_material_wireframe_library,
- &gpu_shader_material_world_normals_library,
- NULL};
-#endif
+#endif /* __ __GPU_MATERIAL_LIBRARY_H__ */
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
new file mode 100644
index 00000000000..432c2d773b5
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -0,0 +1,562 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * Intermediate node graph for generating GLSL shaders.
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_node_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "gpu_material_library.h"
+#include "gpu_node_graph.h"
+
+/* Node Link Functions */
+
+static GPUNodeLink *gpu_node_link_create(void)
+{
+ GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
+ link->users++;
+
+ return link;
+}
+
+static void gpu_node_link_free(GPUNodeLink *link)
+{
+ link->users--;
+
+ if (link->users < 0) {
+ fprintf(stderr, "gpu_node_link_free: negative refcount\n");
+ }
+
+ if (link->users == 0) {
+ if (link->output) {
+ link->output->link = NULL;
+ }
+ MEM_freeN(link);
+ }
+}
+
+/* Node Functions */
+
+static GPUNode *gpu_node_create(const char *name)
+{
+ GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
+
+ node->name = name;
+
+ return node;
+}
+
+static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType type)
+{
+ GPUInput *input;
+ GPUNode *outnode;
+ const char *name;
+
+ if (link->link_type == GPU_NODE_LINK_OUTPUT) {
+ outnode = link->output->node;
+ name = outnode->name;
+ input = outnode->inputs.first;
+
+ if ((STR_ELEM(name, "set_value", "set_rgb", "set_rgba")) && (input->type == type)) {
+ input = MEM_dupallocN(outnode->inputs.first);
+ if (input->link) {
+ input->link->users++;
+ }
+ BLI_addtail(&node->inputs, input);
+ return;
+ }
+ }
+
+ input = MEM_callocN(sizeof(GPUInput), "GPUInput");
+ input->node = node;
+ input->type = type;
+
+ switch (link->link_type) {
+ case GPU_NODE_LINK_BUILTIN:
+ input->source = GPU_SOURCE_BUILTIN;
+ input->builtin = link->builtin;
+ break;
+ case GPU_NODE_LINK_OUTPUT:
+ input->source = GPU_SOURCE_OUTPUT;
+ input->link = link;
+ link->users++;
+ break;
+ case GPU_NODE_LINK_COLORBAND:
+ input->source = GPU_SOURCE_TEX;
+ input->coba = link->coba;
+ break;
+ case GPU_NODE_LINK_IMAGE_BLENDER:
+ case GPU_NODE_LINK_IMAGE_TILEMAP:
+ input->source = GPU_SOURCE_TEX;
+ input->ima = link->ima;
+ input->iuser = link->iuser;
+ break;
+ case GPU_NODE_LINK_ATTR:
+ input->source = GPU_SOURCE_ATTR;
+ input->attr_type = link->attr_type;
+ BLI_strncpy(input->attr_name, link->attr_name, sizeof(input->attr_name));
+ break;
+ case GPU_NODE_LINK_CONSTANT:
+ input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT;
+ break;
+ case GPU_NODE_LINK_UNIFORM:
+ input->source = GPU_SOURCE_UNIFORM;
+ break;
+ default:
+ break;
+ }
+
+ if (ELEM(input->source, GPU_SOURCE_CONSTANT, GPU_SOURCE_UNIFORM)) {
+ memcpy(input->vec, link->data, type * sizeof(float));
+ }
+
+ if (link->link_type != GPU_NODE_LINK_OUTPUT) {
+ MEM_freeN(link);
+ }
+ BLI_addtail(&node->inputs, input);
+}
+
+static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type)
+{
+ switch (type) {
+ /* For now INT is supported as float. */
+ case SOCK_INT:
+ case SOCK_FLOAT:
+ return "set_value";
+ case SOCK_VECTOR:
+ return "set_rgb";
+ case SOCK_RGBA:
+ return "set_rgba";
+ default:
+ BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype");
+ return NULL;
+ }
+}
+
+/**
+ * Link stack uniform buffer.
+ * This is called for the input/output sockets that are note connected.
+ */
+static GPUNodeLink *gpu_uniformbuffer_link(GPUMaterial *mat,
+ bNode *node,
+ GPUNodeStack *stack,
+ const int index,
+ const eNodeSocketInOut in_out)
+{
+ bNodeSocket *socket;
+
+ if (in_out == SOCK_IN) {
+ socket = BLI_findlink(&node->inputs, index);
+ }
+ else {
+ socket = BLI_findlink(&node->outputs, index);
+ }
+
+ BLI_assert(socket != NULL);
+ BLI_assert(socket->in_out == in_out);
+
+ if ((socket->flag & SOCK_HIDE_VALUE) == 0) {
+ GPUNodeLink *link;
+ switch (socket->type) {
+ case SOCK_FLOAT: {
+ bNodeSocketValueFloat *socket_data = socket->default_value;
+ link = GPU_uniform(&socket_data->value);
+ break;
+ }
+ case SOCK_VECTOR: {
+ bNodeSocketValueVector *socket_data = socket->default_value;
+ link = GPU_uniform(socket_data->value);
+ break;
+ }
+ case SOCK_RGBA: {
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ link = GPU_uniform(socket_data->value);
+ break;
+ }
+ default:
+ return NULL;
+ break;
+ }
+
+ if (in_out == SOCK_IN) {
+ GPU_link(mat, gpu_uniform_set_function_from_type(socket->type), link, &stack->link);
+ }
+ return link;
+ }
+ return NULL;
+}
+
+static void gpu_node_input_socket(
+ GPUMaterial *material, bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index)
+{
+ if (sock->link) {
+ gpu_node_input_link(node, sock->link, sock->type);
+ }
+ else if ((material != NULL) &&
+ (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != NULL)) {
+ gpu_node_input_link(node, sock->link, sock->type);
+ }
+ else {
+ gpu_node_input_link(node, GPU_constant(sock->vec), sock->type);
+ }
+}
+
+static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **link)
+{
+ GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
+
+ output->type = type;
+ output->node = node;
+
+ if (link) {
+ *link = output->link = gpu_node_link_create();
+ output->link->link_type = GPU_NODE_LINK_OUTPUT;
+ output->link->output = output;
+
+ /* note: the caller owns the reference to the link, GPUOutput
+ * merely points to it, and if the node is destroyed it will
+ * set that pointer to NULL */
+ }
+
+ BLI_addtail(&node->outputs, output);
+}
+
+/* Creating Inputs */
+
+GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
+{
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_ATTR;
+ link->attr_name = name;
+ /* Fall back to the UV layer, which matches old behavior. */
+ if (type == CD_AUTO_FROM_NAME && name[0] == '\0') {
+ link->attr_type = CD_MTFACE;
+ }
+ else {
+ link->attr_type = type;
+ }
+ return link;
+}
+
+GPUNodeLink *GPU_constant(float *num)
+{
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_CONSTANT;
+ link->data = num;
+ return link;
+}
+
+GPUNodeLink *GPU_uniform(float *num)
+{
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_UNIFORM;
+ link->data = num;
+ return link;
+}
+
+GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
+{
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_IMAGE_BLENDER;
+ link->ima = ima;
+ link->iuser = iuser;
+ return link;
+}
+
+GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row)
+{
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_COLORBAND;
+ link->coba = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
+ MEM_freeN(pixels);
+ return link;
+}
+
+GPUNodeLink *GPU_builtin(eGPUBuiltin builtin)
+{
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_BUILTIN;
+ link->builtin = builtin;
+ return link;
+}
+
+/* Creating Nodes */
+
+bool GPU_link(GPUMaterial *mat, const char *name, ...)
+{
+ GSet *used_libraries = gpu_material_used_libraries(mat);
+ GPUNode *node;
+ GPUFunction *function;
+ GPUNodeLink *link, **linkptr;
+ va_list params;
+ int i;
+
+ function = gpu_material_library_use_function(used_libraries, name);
+ if (!function) {
+ fprintf(stderr, "GPU failed to find function %s\n", name);
+ return false;
+ }
+
+ node = gpu_node_create(name);
+
+ va_start(params, name);
+ for (i = 0; i < function->totparam; i++) {
+ if (function->paramqual[i] != FUNCTION_QUAL_IN) {
+ linkptr = va_arg(params, GPUNodeLink **);
+ gpu_node_output(node, function->paramtype[i], linkptr);
+ }
+ else {
+ link = va_arg(params, GPUNodeLink *);
+ gpu_node_input_link(node, link, function->paramtype[i]);
+ }
+ }
+ va_end(params);
+
+ gpu_material_add_node(mat, node);
+
+ return true;
+}
+
+bool GPU_stack_link(GPUMaterial *material,
+ bNode *bnode,
+ const char *name,
+ GPUNodeStack *in,
+ GPUNodeStack *out,
+ ...)
+{
+ GSet *used_libraries = gpu_material_used_libraries(material);
+ GPUNode *node;
+ GPUFunction *function;
+ GPUNodeLink *link, **linkptr;
+ va_list params;
+ int i, totin, totout;
+
+ function = gpu_material_library_use_function(used_libraries, name);
+ if (!function) {
+ fprintf(stderr, "GPU failed to find function %s\n", name);
+ return false;
+ }
+
+ node = gpu_node_create(name);
+ totin = 0;
+ totout = 0;
+
+ if (in) {
+ for (i = 0; !in[i].end; i++) {
+ if (in[i].type != GPU_NONE) {
+ gpu_node_input_socket(material, bnode, node, &in[i], i);
+ totin++;
+ }
+ }
+ }
+
+ if (out) {
+ for (i = 0; !out[i].end; i++) {
+ if (out[i].type != GPU_NONE) {
+ gpu_node_output(node, out[i].type, &out[i].link);
+ totout++;
+ }
+ }
+ }
+
+ va_start(params, out);
+ for (i = 0; i < function->totparam; i++) {
+ if (function->paramqual[i] != FUNCTION_QUAL_IN) {
+ if (totout == 0) {
+ linkptr = va_arg(params, GPUNodeLink **);
+ gpu_node_output(node, function->paramtype[i], linkptr);
+ }
+ else {
+ totout--;
+ }
+ }
+ else {
+ if (totin == 0) {
+ link = va_arg(params, GPUNodeLink *);
+ if (link->socket) {
+ gpu_node_input_socket(NULL, NULL, node, link->socket, -1);
+ }
+ else {
+ gpu_node_input_link(node, link, function->paramtype[i]);
+ }
+ }
+ else {
+ totin--;
+ }
+ }
+ }
+ va_end(params);
+
+ gpu_material_add_node(material, node);
+
+ return true;
+}
+
+GPUNodeLink *GPU_uniformbuffer_link_out(GPUMaterial *mat,
+ bNode *node,
+ GPUNodeStack *stack,
+ const int index)
+{
+ return gpu_uniformbuffer_link(mat, node, stack, index, SOCK_OUT);
+}
+
+/* Node Graph */
+
+static void gpu_inputs_free(ListBase *inputs)
+{
+ GPUInput *input;
+
+ for (input = inputs->first; input; input = input->next) {
+ if (input->link) {
+ gpu_node_link_free(input->link);
+ }
+ }
+
+ BLI_freelistN(inputs);
+}
+
+static void gpu_node_free(GPUNode *node)
+{
+ GPUOutput *output;
+
+ gpu_inputs_free(&node->inputs);
+
+ for (output = node->outputs.first; output; output = output->next) {
+ if (output->link) {
+ output->link->output = NULL;
+ gpu_node_link_free(output->link);
+ }
+ }
+
+ BLI_freelistN(&node->outputs);
+ MEM_freeN(node);
+}
+
+void gpu_node_graph_free(GPUNodeGraph *graph)
+{
+ GPUNode *node;
+
+ while ((node = BLI_pophead(&graph->nodes))) {
+ gpu_node_free(node);
+ }
+
+ gpu_inputs_free(&graph->inputs);
+ graph->outlink = NULL;
+ graph->builtins = 0;
+ memset(&graph->attrs, 0, sizeof(graph->attrs));
+}
+
+/* Extract Dynamic Inputs */
+
+void gpu_node_graph_extract_dynamic_inputs(GPUShader *shader, GPUNodeGraph *graph)
+{
+ GPUNode *node;
+ GPUInput *next, *input;
+
+ if (!shader) {
+ return;
+ }
+
+ while ((node = BLI_pophead(&graph->nodes))) {
+ for (input = node->inputs.first; input; input = next) {
+ next = input->next;
+
+ /* attributes don't need to be bound, they already have
+ * an id that the drawing functions will use. Builtins have
+ * constant names. */
+ if (ELEM(input->source, GPU_SOURCE_ATTR, GPU_SOURCE_BUILTIN)) {
+ continue;
+ }
+
+ if (input->source == GPU_SOURCE_TEX) {
+ BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
+ }
+ else {
+ BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
+ }
+
+ if (input->source == GPU_SOURCE_TEX) {
+ if (input->bindtex) {
+ input->shaderloc = GPU_shader_get_uniform_ensure(shader, input->shadername);
+ /* extract nodes */
+ BLI_remlink(&node->inputs, input);
+ BLI_addtail(&graph->inputs, input);
+ }
+ }
+ }
+
+ gpu_node_free(node);
+ }
+}
+
+/* Prune Unused Nodes */
+
+static void gpu_nodes_tag(GPUNodeLink *link)
+{
+ GPUNode *node;
+ GPUInput *input;
+
+ if (!link->output) {
+ return;
+ }
+
+ node = link->output->node;
+ if (node->tag) {
+ return;
+ }
+
+ node->tag = true;
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->link) {
+ gpu_nodes_tag(input->link);
+ }
+ }
+}
+
+void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
+{
+ GPUNode *node, *next;
+
+ for (node = graph->nodes.first; node; node = node->next) {
+ node->tag = false;
+ }
+
+ gpu_nodes_tag(graph->outlink);
+
+ for (node = graph->nodes.first; node; node = next) {
+ next = node->next;
+
+ if (!node->tag) {
+ BLI_remlink(&graph->nodes, node);
+ gpu_node_free(node);
+ }
+ }
+}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
new file mode 100644
index 00000000000..51e188e3f5e
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -0,0 +1,182 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_NODE_GRAPH_H__
+#define __GPU_NODE_GRAPH_H__
+
+#include "DNA_customdata_types.h"
+#include "DNA_listBase.h"
+
+#include "GPU_material.h"
+#include "GPU_glew.h"
+#include "GPU_shader.h"
+
+struct GPUNode;
+struct GPUOutput;
+struct GPUShader;
+struct GPUVertAttrLayers;
+struct ListBase;
+
+typedef enum eGPUDataSource {
+ GPU_SOURCE_OUTPUT,
+ GPU_SOURCE_CONSTANT,
+ GPU_SOURCE_UNIFORM,
+ GPU_SOURCE_ATTR,
+ GPU_SOURCE_BUILTIN,
+ GPU_SOURCE_STRUCT,
+ GPU_SOURCE_TEX,
+} eGPUDataSource;
+
+typedef enum {
+ GPU_NODE_LINK_NONE = 0,
+ GPU_NODE_LINK_ATTR,
+ GPU_NODE_LINK_BUILTIN,
+ GPU_NODE_LINK_COLORBAND,
+ GPU_NODE_LINK_CONSTANT,
+ GPU_NODE_LINK_IMAGE_BLENDER,
+ GPU_NODE_LINK_IMAGE_TILEMAP,
+ GPU_NODE_LINK_OUTPUT,
+ GPU_NODE_LINK_UNIFORM,
+} GPUNodeLinkType;
+
+struct GPUNode {
+ struct GPUNode *next, *prev;
+
+ const char *name;
+
+ /* Internal flag to mark nodes during pruning */
+ bool tag;
+
+ ListBase inputs;
+ ListBase outputs;
+};
+
+struct GPUNodeLink {
+ GPUNodeStack *socket;
+
+ GPUNodeLinkType link_type;
+ int users; /* Refcount */
+
+ union {
+ /* GPU_NODE_LINK_CONSTANT | GPU_NODE_LINK_UNIFORM */
+ float *data;
+ /* GPU_NODE_LINK_BUILTIN */
+ eGPUBuiltin builtin;
+ /* GPU_NODE_LINK_COLORBAND */
+ struct GPUTexture **coba;
+ /* GPU_NODE_LINK_OUTPUT */
+ struct GPUOutput *output;
+ /* GPU_NODE_LINK_ATTR */
+ struct {
+ const char *attr_name;
+ CustomDataType attr_type;
+ };
+ /* GPU_NODE_LINK_IMAGE_BLENDER | GPU_NODE_LINK_IMAGE_TILEMAP */
+ struct {
+ struct Image *ima;
+ struct ImageUser *iuser;
+ };
+ };
+};
+
+typedef struct GPUOutput {
+ struct GPUOutput *next, *prev;
+
+ GPUNode *node;
+ eGPUType type; /* data type = length of vector/matrix */
+ GPUNodeLink *link; /* output link */
+ int id; /* unique id as created by code generator */
+} GPUOutput;
+
+typedef struct GPUInput {
+ struct GPUInput *next, *prev;
+
+ GPUNode *node;
+ eGPUType type; /* datatype */
+ GPUNodeLink *link;
+ int id; /* unique id as created by code generator */
+
+ eGPUDataSource source; /* data source */
+
+ int shaderloc; /* id from opengl */
+ char shadername[32]; /* name in shader */
+
+ /* Content based on eGPUDataSource */
+ union {
+ /* GPU_SOURCE_CONSTANT | GPU_SOURCE_UNIFORM */
+ float vec[16]; /* vector data */
+ /* GPU_SOURCE_BUILTIN */
+ eGPUBuiltin builtin; /* builtin uniform */
+ /* GPU_SOURCE_TEX */
+ struct {
+ struct GPUTexture **coba; /* input texture, only set at runtime */
+ struct Image *ima; /* image */
+ struct ImageUser *iuser; /* image user */
+ bool bindtex; /* input is responsible for binding the texture? */
+ int texid; /* number for multitexture, starting from zero */
+ eGPUType textype; /* texture type (2D, 1D Array ...) */
+ };
+ /* GPU_SOURCE_ATTR */
+ struct {
+ /** Attribute name. */
+ char attr_name[MAX_CUSTOMDATA_LAYER_NAME];
+ /** ID for vertex attributes. */
+ int attr_id;
+ /** This is the first one that is bound. */
+ bool attr_first;
+ /** Attribute type. */
+ CustomDataType attr_type;
+ };
+ };
+} GPUInput;
+
+typedef struct GPUNodeGraph {
+ /* Nodes */
+ ListBase nodes;
+
+ /* Inputs and output. */
+ ListBase inputs;
+ GPUNodeLink *outlink;
+
+ /* Needed attributes. */
+ GPUVertAttrLayers attrs;
+ int builtins;
+} GPUNodeGraph;
+
+/* Node Graph */
+
+void gpu_node_graph_prune_unused(GPUNodeGraph *graph);
+void gpu_node_graph_extract_dynamic_inputs(struct GPUShader *shader, GPUNodeGraph *graph);
+void gpu_node_graph_free(GPUNodeGraph *graph);
+
+/* Material calls */
+
+void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node);
+struct GPUTexture **gpu_material_ramp_texture_row_set(struct GPUMaterial *mat,
+ int size,
+ float *pixels,
+ float *row);
+
+struct GSet *gpu_material_used_libraries(struct GPUMaterial *material);
+
+#endif /* __GPU_NODE_GRAPH_H__ */
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
index 46dcc6c6f78..734b4fa7b92 100644
--- a/source/blender/gpu/intern/gpu_uniformbuffer.c
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.c
@@ -26,8 +26,8 @@
#include "BLI_blenlib.h"
-#include "gpu_codegen.h"
#include "gpu_context_private.h"
+#include "gpu_node_graph.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"