From 007f1b74a67302fb4c164eb26969419434a98aee Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 12 Feb 2020 12:48:44 +0100 Subject: Cleanup: split off code from gpu_codegen.c into smaller files --- source/blender/blenlib/BLI_string.h | 1 + source/blender/blenlib/intern/string.c | 18 + source/blender/draw/intern/draw_manager_data.c | 2 + source/blender/gpu/CMakeLists.txt | 3 + source/blender/gpu/intern/gpu_codegen.c | 940 ++--------------------- source/blender/gpu/intern/gpu_codegen.h | 163 +--- source/blender/gpu/intern/gpu_init_exit.c | 3 + source/blender/gpu/intern/gpu_material.c | 42 +- source/blender/gpu/intern/gpu_material_library.c | 882 +++++++++++++++++++++ source/blender/gpu/intern/gpu_material_library.h | 644 +--------------- source/blender/gpu/intern/gpu_node_graph.c | 562 ++++++++++++++ source/blender/gpu/intern/gpu_node_graph.h | 182 +++++ source/blender/gpu/intern/gpu_uniformbuffer.c | 2 +- 13 files changed, 1759 insertions(+), 1685 deletions(-) create mode 100644 source/blender/gpu/intern/gpu_material_library.c create mode 100644 source/blender/gpu/intern/gpu_node_graph.c create mode 100644 source/blender/gpu/intern/gpu_node_graph.h 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 #include -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 + +#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 + +#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" -- cgit v1.2.3