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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c411
-rw-r--r--source/blender/gpu/intern/gpu_draw.c3
-rw-r--r--source/blender/gpu/intern/gpu_material.c9
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c178
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h52
5 files changed, 313 insertions, 340 deletions
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 6c14d918816..553ecb65529 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -216,16 +216,6 @@ static void codegen_print_datatype(DynStr *ds, const eGPUType type, float *data)
}
}
-static int codegen_input_has_texture(GPUInput *input)
-{
- if (input->link) {
- return 0;
- }
- else {
- return (input->source == GPU_SOURCE_TEX);
- }
-}
-
static const char *gpu_builtin_name(eGPUBuiltin builtin)
{
if (builtin == GPU_VIEW_MATRIX) {
@@ -299,14 +289,14 @@ static const char *gpu_builtin_name(eGPUBuiltin builtin)
}
}
-static void codegen_set_unique_ids(ListBase *nodes)
+static void codegen_set_unique_ids(GPUNodeGraph *graph)
{
GPUNode *node;
GPUInput *input;
GPUOutput *output;
int id = 1;
- for (node = nodes->first; node; node = node->next) {
+ for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
/* set id for unique names of uniform variables */
input->id = id++;
@@ -322,7 +312,9 @@ static void codegen_set_unique_ids(ListBase *nodes)
/**
* It will create an UBO for GPUMaterial if there is any GPU_DYNAMIC_UBO.
*/
-static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, ListBase *nodes)
+static int codegen_process_uniforms_functions(GPUMaterial *material,
+ DynStr *ds,
+ GPUNodeGraph *graph)
{
GPUNode *node;
GPUInput *input;
@@ -330,27 +322,29 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
int builtins = 0;
ListBase ubo_inputs = {NULL, NULL};
- /* print uniforms */
- for (node = nodes->first; node; node = node->next) {
+ /* Attributes */
+ for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ BLI_dynstr_appendf(ds, "in %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
+ }
+
+ /* Textures */
+ for (GPUMaterialTexture *tex = graph->textures.first; tex; tex = tex->next) {
+ if (tex->colorband) {
+ BLI_dynstr_appendf(ds, "uniform sampler1DArray %s;\n", tex->sampler_name);
+ }
+ else if (tex->tiled_mapping_name[0]) {
+ BLI_dynstr_appendf(ds, "uniform sampler2DArray %s;\n", tex->sampler_name);
+ BLI_dynstr_appendf(ds, "uniform sampler1DArray %s;\n", tex->tiled_mapping_name);
+ }
+ else {
+ BLI_dynstr_appendf(ds, "uniform sampler2D %s;\n", tex->sampler_name);
+ }
+ }
+
+ /* Print other uniforms */
+ for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
- if (input->source == GPU_SOURCE_TEX) {
- /* create exactly one sampler for each texture */
- if (codegen_input_has_texture(input) && input->bindtex) {
- const char *type;
- if (input->colorband || input->type == GPU_TEX1D_ARRAY) {
- type = "sampler1DArray";
- }
- else if (input->type == GPU_TEX2D_ARRAY) {
- type = "sampler2DArray";
- }
- else {
- BLI_assert(input->type == GPU_TEX2D);
- type = "sampler2D";
- }
- BLI_dynstr_appendf(ds, "uniform %s samp%d;\n", type, input->texid);
- }
- }
- else if (input->source == GPU_SOURCE_BUILTIN) {
+ if (input->source == GPU_SOURCE_BUILTIN) {
/* only define each builtin uniform/varying once */
if (!(builtins & input->builtin)) {
builtins |= input->builtin;
@@ -385,10 +379,6 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
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_data_type_to_string(input->type), input->attr_id);
- }
}
}
@@ -412,12 +402,12 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
return builtins;
}
-static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
+static void codegen_declare_tmps(DynStr *ds, GPUNodeGraph *graph)
{
GPUNode *node;
GPUOutput *output;
- for (node = nodes->first; node; node = node->next) {
+ for (node = graph->nodes.first; node; node = node->next) {
/* declare temporary variables for node output storage */
for (output = node->outputs.first; output; output = output->next) {
if (output->type == GPU_CLOSURE) {
@@ -432,18 +422,21 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
BLI_dynstr_append(ds, "\n");
}
-static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
+static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *finaloutput)
{
GPUNode *node;
GPUInput *input;
GPUOutput *output;
- for (node = nodes->first; node; node = node->next) {
+ for (node = graph->nodes.first; node; node = node->next) {
BLI_dynstr_appendf(ds, "\t%s(", node->name);
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_TEX) {
- BLI_dynstr_appendf(ds, "samp%d", input->texid);
+ BLI_dynstr_append(ds, input->texture->sampler_name);
+ }
+ else if (input->source == GPU_SOURCE_TEX_TILED_MAPPING) {
+ BLI_dynstr_append(ds, input->texture->tiled_mapping_name);
}
else if (input->source == GPU_SOURCE_OUTPUT) {
codegen_convert_datatype(
@@ -507,7 +500,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_appendf(ds, "cons%d", input->id);
}
else if (input->source == GPU_SOURCE_ATTR) {
- BLI_dynstr_appendf(ds, "var%d", input->attr_id);
+ BLI_dynstr_appendf(ds, "var%d", input->attr->id);
}
BLI_dynstr_append(ds, ", ");
@@ -527,7 +520,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ";\n");
}
-static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUOutput *output)
+static char *code_generate_fragment(GPUMaterial *material, GPUNodeGraph *graph)
{
DynStr *ds = BLI_dynstr_new();
char *code;
@@ -537,8 +530,8 @@ static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUO
BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
#endif
- codegen_set_unique_ids(nodes);
- builtins = codegen_process_uniforms_functions(material, ds, nodes);
+ codegen_set_unique_ids(graph);
+ builtins = codegen_process_uniforms_functions(material, ds, graph);
if (builtins & (GPU_OBJECT_INFO | GPU_OBJECT_COLOR)) {
BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
@@ -614,8 +607,8 @@ static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUO
BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n");
}
- codegen_declare_tmps(ds, nodes);
- codegen_call_functions(ds, nodes, output);
+ codegen_declare_tmps(ds, graph);
+ codegen_call_functions(ds, graph, graph->outlink->output);
BLI_dynstr_append(ds, "}\n");
@@ -666,7 +659,7 @@ static const char *attr_prefix_get(CustomDataType type)
}
}
-static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool use_geom)
+static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bool use_geom)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
@@ -682,48 +675,44 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
"#define DEFINE_ATTR(type, attr) in type attr\n"
"#endif\n");
- for (node = nodes->first; node; node = node->next) {
+ for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ /* XXX FIXME : see notes in mesh_render_data_create() */
+ /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
+ if (attr->type == CD_ORCO) {
+ /* OPTI : orco is computed from local positions, but only if no modifier is present. */
+ BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
+ BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n");
+ }
+ else if (attr->name[0] == '\0') {
+ BLI_dynstr_appendf(ds,
+ "DEFINE_ATTR(%s, %s);\n",
+ gpu_data_type_to_string(attr->gputype),
+ attr_prefix_get(attr->type));
+ BLI_dynstr_appendf(ds, "#define att%d %s\n", attr->id, attr_prefix_get(attr->type));
+ }
+ else {
+ char attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME];
+ GPU_vertformat_safe_attrib_name(attr->name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME);
+ BLI_dynstr_appendf(ds,
+ "DEFINE_ATTR(%s, %s%s);\n",
+ gpu_data_type_to_string(attr->gputype),
+ attr_prefix_get(attr->type),
+ attr_safe_name);
+ BLI_dynstr_appendf(
+ ds, "#define att%d %s%s\n", attr->id, attr_prefix_get(attr->type), attr_safe_name);
+ }
+ BLI_dynstr_appendf(ds,
+ "out %s var%d%s;\n",
+ gpu_data_type_to_string(attr->gputype),
+ attr->id,
+ use_geom ? "g" : "");
+ }
+
+ for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_BUILTIN) {
builtins |= input->builtin;
}
- if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
- /* XXX FIXME : see notes in mesh_render_data_create() */
- /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
- if (input->attr_type == CD_ORCO) {
- /* OPTI : orco is computed from local positions, but only if no modifier is present. */
- BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
- BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n");
- }
- else if (input->attr_name[0] == '\0') {
- BLI_dynstr_appendf(ds,
- "DEFINE_ATTR(%s, %s);\n",
- 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));
- }
- else {
- char attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME];
- GPU_vertformat_safe_attrib_name(
- input->attr_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME);
- BLI_dynstr_appendf(ds,
- "DEFINE_ATTR(%s, %s%s);\n",
- gpu_data_type_to_string(input->type),
- attr_prefix_get(input->attr_type),
- attr_safe_name);
- BLI_dynstr_appendf(ds,
- "#define att%d %s%s\n",
- input->attr_id,
- attr_prefix_get(input->attr_type),
- attr_safe_name);
- }
- BLI_dynstr_appendf(ds,
- "out %s var%d%s;\n",
- gpu_data_type_to_string(input->type),
- input->attr_id,
- use_geom ? "g" : "");
- }
}
}
@@ -800,30 +789,26 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_append(ds, "\tbarycentricPosg = position;\n");
}
- for (node = nodes->first; node; node = node->next) {
- for (input = node->inputs.first; input; input = input->next) {
- if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
- if (input->attr_type == CD_TANGENT) {
- /* Not supported by hairs */
- BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", input->attr_id, use_geom ? "g" : "");
- }
- else if (input->attr_type == CD_ORCO) {
- BLI_dynstr_appendf(ds,
- "\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * "
- "vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n",
- input->attr_id,
- use_geom ? "g" : "");
- /* TODO: fix ORCO with modifiers. */
- }
- else {
- BLI_dynstr_appendf(ds,
- "\tvar%d%s = hair_get_customdata_%s(att%d);\n",
- input->attr_id,
- use_geom ? "g" : "",
- gpu_data_type_to_string(input->type),
- input->attr_id);
- }
- }
+ for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ if (attr->type == CD_TANGENT) {
+ /* Not supported by hairs */
+ BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", attr->id, use_geom ? "g" : "");
+ }
+ else if (attr->type == CD_ORCO) {
+ BLI_dynstr_appendf(ds,
+ "\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * "
+ "vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n",
+ attr->id,
+ use_geom ? "g" : "");
+ /* TODO: fix ORCO with modifiers. */
+ }
+ else {
+ BLI_dynstr_appendf(ds,
+ "\tvar%d%s = hair_get_customdata_%s(att%d);\n",
+ attr->id,
+ use_geom ? "g" : "",
+ gpu_data_type_to_string(attr->gputype),
+ attr->id);
}
}
@@ -837,49 +822,43 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_append(ds, "\tbarycentricPosg = (ModelMatrix * vec4(position, 1.0)).xyz;\n");
}
- for (node = nodes->first; node; node = node->next) {
- for (input = node->inputs.first; input; input = input->next) {
- if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
- if (input->attr_type == CD_TANGENT) { /* silly exception */
- BLI_dynstr_appendf(ds,
- "\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n",
- input->attr_id,
- use_geom ? "g" : "",
- input->attr_id);
- BLI_dynstr_appendf(
- ds, "\tvar%d%s.w = att%d.w;\n", input->attr_id, use_geom ? "g" : "", input->attr_id);
- /* Normalize only if vector is not null. */
- BLI_dynstr_appendf(ds,
- "\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n",
- input->attr_id,
- input->attr_id,
- use_geom ? "g" : "",
- input->attr_id,
- use_geom ? "g" : "");
- BLI_dynstr_appendf(ds,
- "\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n",
- input->attr_id,
- use_geom ? "g" : "",
- input->attr_id,
- input->attr_id);
- }
- else if (input->attr_type == CD_ORCO) {
- BLI_dynstr_appendf(ds,
- "\tvar%d%s = OrcoTexCoFactors[0].xyz + position *"
- " OrcoTexCoFactors[1].xyz;\n",
- input->attr_id,
- use_geom ? "g" : "");
- /* See mesh_create_loop_orco() for explanation. */
- BLI_dynstr_appendf(ds,
- "\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n",
- input->attr_id,
- use_geom ? "g" : "");
- }
- else {
- BLI_dynstr_appendf(
- ds, "\tvar%d%s = att%d;\n", input->attr_id, use_geom ? "g" : "", input->attr_id);
- }
- }
+ for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ if (attr->type == CD_TANGENT) { /* silly exception */
+ BLI_dynstr_appendf(ds,
+ "\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n",
+ attr->id,
+ use_geom ? "g" : "",
+ attr->id);
+ BLI_dynstr_appendf(ds, "\tvar%d%s.w = att%d.w;\n", attr->id, use_geom ? "g" : "", attr->id);
+ /* Normalize only if vector is not null. */
+ BLI_dynstr_appendf(ds,
+ "\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n",
+ attr->id,
+ attr->id,
+ use_geom ? "g" : "",
+ attr->id,
+ use_geom ? "g" : "");
+ BLI_dynstr_appendf(ds,
+ "\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n",
+ attr->id,
+ use_geom ? "g" : "",
+ attr->id,
+ attr->id);
+ }
+ else if (attr->type == CD_ORCO) {
+ BLI_dynstr_appendf(ds,
+ "\tvar%d%s = OrcoTexCoFactors[0].xyz + position *"
+ " OrcoTexCoFactors[1].xyz;\n",
+ attr->id,
+ use_geom ? "g" : "");
+ /* See mesh_create_loop_orco() for explanation. */
+ BLI_dynstr_appendf(ds,
+ "\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n",
+ attr->id,
+ use_geom ? "g" : "");
+ }
+ else {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = att%d;\n", attr->id, use_geom ? "g" : "", attr->id);
}
}
BLI_dynstr_append(ds, "#endif /* HAIR_SHADER */\n");
@@ -899,7 +878,9 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
return code;
}
-static char *code_generate_geometry(ListBase *nodes, const char *geom_code, const char *defines)
+static char *code_generate_geometry(GPUNodeGraph *graph,
+ const char *geom_code,
+ const char *defines)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
@@ -916,20 +897,19 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
BLI_dynstr_append(ds, "#define USE_ATTR\n");
/* Generate varying declarations. */
- for (node = nodes->first; node; node = node->next) {
+ for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_BUILTIN) {
builtins |= input->builtin;
}
- if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
- 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);
- }
}
}
+ for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ BLI_dynstr_appendf(ds, "in %s var%dg[];\n", gpu_data_type_to_string(attr->gputype), attr->id);
+ BLI_dynstr_appendf(ds, "out %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
+ }
+
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
BLI_dynstr_append(ds, "in vec2 barycentricTexCog[];\n");
@@ -1032,13 +1012,9 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
BLI_dynstr_append(ds, "#endif\n");
}
- for (node = nodes->first; node; node = node->next) {
- for (input = node->inputs.first; input; input = input->next) {
- if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
- /* TODO let shader choose what to do depending on what the attribute is. */
- BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", input->attr_id, input->attr_id);
- }
- }
+ for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
+ /* TODO let shader choose what to do depending on what the attribute is. */
+ BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", attr->id, attr->id);
}
BLI_dynstr_append(ds, "}\n");
@@ -1053,94 +1029,6 @@ GPUShader *GPU_pass_shader_get(GPUPass *pass)
return pass->shader;
}
-/* Requested Attributes */
-
-static ListBase gpu_nodes_requested_attributes(ListBase *nodes)
-{
- ListBase attributes = {NULL};
- int num_attributes = 0;
-
- /* Convert attributes requested by node inputs to list, checking for
- * checking for duplicates and assigning id's starting from zero. */
- for (GPUNode *node = nodes->first; node; node = node->next) {
- for (GPUInput *input = node->inputs.first; input; input = input->next) {
- if (input->source != GPU_SOURCE_ATTR) {
- continue;
- }
-
- GPUMaterialAttribute *attr = attributes.first;
- for (; attr; attr = attr->next) {
- if (attr->type == input->attr_type && STREQ(attr->name, input->attr_name)) {
- break;
- }
- }
-
- /* Add new requested attribute if it's within GPU limits. */
- if (attr == NULL && num_attributes < GPU_MAX_ATTR) {
- attr = MEM_callocN(sizeof(*attr), __func__);
- attr->type = input->attr_type;
- STRNCPY(attr->name, input->attr_name);
- attr->id = num_attributes++;
- BLI_addtail(&attributes, attr);
-
- input->attr_id = attr->id;
- input->attr_first = true;
- }
- else if (attr != NULL) {
- input->attr_id = attr->id;
- }
- }
- }
-
- return attributes;
-}
-
-/* Requested Textures */
-
-static ListBase gpu_nodes_requested_textures(ListBase *nodes)
-{
- ListBase textures = {NULL};
- int num_textures = 0;
-
- /* Convert textures requested by node inputs to list, checking for
- * checking for duplicates and assigning id's starting from zero. */
- for (GPUNode *node = nodes->first; node; node = node->next) {
- for (GPUInput *input = node->inputs.first; input; input = input->next) {
- if (!codegen_input_has_texture(input)) {
- continue;
- }
-
- GPUMaterialTexture *tex = textures.first;
- for (; tex; tex = tex->next) {
- if (tex->ima == input->ima && tex->colorband == input->colorband &&
- tex->type == input->type) {
- break;
- }
- }
-
- if (tex == NULL) {
- tex = MEM_callocN(sizeof(*tex), __func__);
- tex->ima = input->ima;
- tex->iuser = input->iuser;
- tex->colorband = input->colorband;
- tex->id = num_textures++;
- tex->type = input->type;
- BLI_snprintf(tex->shadername, sizeof(tex->shadername), "samp%d", tex->id);
- BLI_addtail(&textures, tex);
-
- input->texid = tex->id;
- input->bindtex = true;
- }
- else {
- input->texid = tex->id;
- input->bindtex = false;
- }
- }
- }
-
- return textures;
-}
-
/* Pass create/free */
static bool gpu_pass_is_valid(GPUPass *pass)
@@ -1160,11 +1048,8 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
* generated VBOs are ready to accept the future shader. */
gpu_node_graph_prune_unused(graph);
- graph->attributes = gpu_nodes_requested_attributes(&graph->nodes);
- graph->textures = gpu_nodes_requested_textures(&graph->nodes);
-
/* generate code */
- char *fragmentgen = code_generate_fragment(material, &graph->nodes, graph->outlink->output);
+ char *fragmentgen = code_generate_fragment(material, graph);
/* Cache lookup: Reuse shaders already compiled */
uint32_t hash = gpu_pass_hash(fragmentgen, defines, &graph->attributes);
@@ -1186,8 +1071,8 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
GSet *used_libraries = gpu_material_used_libraries(material);
char *tmp = gpu_material_library_generate_code(used_libraries, frag_lib);
- char *geometrycode = code_generate_geometry(&graph->nodes, geom_code, defines);
- char *vertexcode = code_generate_vertex(&graph->nodes, vert_code, (geometrycode != NULL));
+ char *geometrycode = code_generate_geometry(graph, geom_code, defines);
+ char *vertexcode = code_generate_vertex(graph, vert_code, (geometrycode != NULL));
char *fragmentcode = BLI_strdupcat(tmp, fragmentgen);
MEM_freeN(fragmentgen);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 62a5de7ebe6..d674f8600c2 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -1077,7 +1077,8 @@ void GPU_create_gl_tex(uint *bind,
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
- GLenum float_format = (!half_float && ima->flag & IMA_HIGH_BITDEPTH) ? GL_RGBA32F : GL_RGBA16F;
+ GLenum float_format = (!half_float && (ima && (ima->flag & IMA_HIGH_BITDEPTH))) ? GL_RGBA32F :
+ GL_RGBA16F;
GLenum internal_format = (frect) ? float_format : (use_srgb) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
if (textarget == GL_TEXTURE_2D) {
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index d8d3e5a2ff2..b2658839d67 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -207,11 +207,6 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material)
return material->pass;
}
-ListBase *GPU_material_get_inputs(GPUMaterial *material)
-{
- return &material->graph.inputs;
-}
-
/* Return can be NULL if it's a world material. */
Material *GPU_material_get_material(GPUMaterial *material)
{
@@ -579,9 +574,9 @@ void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
}
}
-void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
+GPUNodeGraph *gpu_material_node_graph(GPUMaterial *material)
{
- BLI_addtail(&material->graph.nodes, node);
+ return &material->graph;
}
GSet *gpu_material_used_libraries(GPUMaterial *material)
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index b271ac48f75..de35b43109f 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -109,20 +109,20 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->link = link;
link->users++;
break;
+ case GPU_NODE_LINK_IMAGE:
+ case GPU_NODE_LINK_IMAGE_TILED:
case GPU_NODE_LINK_COLORBAND:
input->source = GPU_SOURCE_TEX;
- input->colorband = link->colorband;
+ input->texture = link->texture;
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;
+ case GPU_NODE_LINK_IMAGE_TILED_MAPPING:
+ input->source = GPU_SOURCE_TEX_TILED_MAPPING;
+ input->texture = link->texture;
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));
+ input->attr = link->attr;
+ input->attr->gputype = type;
break;
case GPU_NODE_LINK_CONSTANT:
input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT;
@@ -249,24 +249,97 @@ static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **li
BLI_addtail(&node->outputs, output);
}
-/* Creating Inputs */
+/* Attributes and Textures */
-GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
+static GPUMaterialAttribute *gpu_node_graph_add_attribute(GPUNodeGraph *graph,
+ 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;
+ type = CD_MTFACE;
}
- else {
- link->attr_type = type;
+
+ /* Find existing attribute. */
+ int num_attributes = 0;
+ GPUMaterialAttribute *attr = graph->attributes.first;
+ for (; attr; attr = attr->next) {
+ if (attr->type == type && STREQ(attr->name, name)) {
+ break;
+ }
+ num_attributes++;
+ }
+
+ /* Add new requested attribute if it's within GPU limits. */
+ if (attr == NULL && num_attributes < GPU_MAX_ATTR) {
+ attr = MEM_callocN(sizeof(*attr), __func__);
+ attr->type = type;
+ STRNCPY(attr->name, name);
+ attr->id = num_attributes;
+ BLI_addtail(&graph->attributes, attr);
+ }
+
+ if (attr != NULL) {
+ attr->users++;
+ }
+
+ return attr;
+}
+
+static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
+ Image *ima,
+ ImageUser *iuser,
+ struct GPUTexture **colorband,
+ GPUNodeLinkType link_type)
+{
+ /* Find existing texture. */
+ int num_textures = 0;
+ GPUMaterialTexture *tex = graph->textures.first;
+ for (; tex; tex = tex->next) {
+ if (tex->ima == ima && tex->colorband == colorband) {
+ break;
+ }
+ num_textures++;
}
+
+ /* Add new requested texture. */
+ if (tex == NULL) {
+ tex = MEM_callocN(sizeof(*tex), __func__);
+ tex->ima = ima;
+ tex->iuser = iuser;
+ tex->colorband = colorband;
+ BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures);
+ if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) {
+ BLI_snprintf(
+ tex->tiled_mapping_name, sizeof(tex->tiled_mapping_name), "tsamp%d", num_textures);
+ }
+ BLI_addtail(&graph->textures, tex);
+ }
+
+ tex->users++;
+
+ return tex;
+}
+
+/* Creating Inputs */
+
+GPUNodeLink *GPU_attribute(GPUMaterial *mat, const CustomDataType type, const char *name)
+{
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
+ GPUMaterialAttribute *attr = gpu_node_graph_add_attribute(graph, type, name);
+
+ if (attr == NULL) {
+ static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
+ return GPU_constant(zero_data);
+ }
+
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_ATTR;
+ link->attr = attr;
return link;
}
-GPUNodeLink *GPU_constant(float *num)
+GPUNodeLink *GPU_constant(const float *num)
{
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_CONSTANT;
@@ -274,7 +347,7 @@ GPUNodeLink *GPU_constant(float *num)
return link;
}
-GPUNodeLink *GPU_uniform(float *num)
+GPUNodeLink *GPU_uniform(const float *num)
{
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_UNIFORM;
@@ -282,21 +355,42 @@ GPUNodeLink *GPU_uniform(float *num)
return link;
}
-GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
+GPUNodeLink *GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser)
{
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
- link->link_type = GPU_NODE_LINK_IMAGE_BLENDER;
- link->ima = ima;
- link->iuser = iuser;
+ link->link_type = GPU_NODE_LINK_IMAGE;
+ link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ return link;
+}
+
+GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser)
+{
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_IMAGE_TILED;
+ link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ return link;
+}
+
+GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iuser)
+{
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
+ GPUNodeLink *link = gpu_node_link_create();
+ link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING;
+ link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
return link;
}
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row)
{
+ struct GPUTexture **colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
+ MEM_freeN(pixels);
+
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_COLORBAND;
- link->colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
- MEM_freeN(pixels);
+ link->texture = gpu_node_graph_add_texture(graph, NULL, NULL, colorband, link->link_type);
return link;
}
@@ -340,7 +434,8 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
}
va_end(params);
- gpu_material_add_node(mat, node);
+ GPUNodeGraph *graph = gpu_material_node_graph(mat);
+ BLI_addtail(&graph->nodes, node);
return true;
}
@@ -415,7 +510,8 @@ bool GPU_stack_link(GPUMaterial *material,
}
va_end(params);
- gpu_material_add_node(material, node);
+ GPUNodeGraph *graph = gpu_material_node_graph(material);
+ BLI_addtail(&graph->nodes, node);
return true;
}
@@ -435,6 +531,13 @@ static void gpu_inputs_free(ListBase *inputs)
GPUInput *input;
for (input = inputs->first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTR) {
+ input->attr->users--;
+ }
+ else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) {
+ input->texture->users--;
+ }
+
if (input->link) {
gpu_node_link_free(input->link);
}
@@ -469,7 +572,6 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
gpu_node_free(node);
}
- gpu_inputs_free(&graph->inputs);
graph->outlink = NULL;
}
@@ -477,8 +579,8 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
void gpu_node_graph_free(GPUNodeGraph *graph)
{
gpu_node_graph_free_nodes(graph);
- BLI_freelistN(&graph->attributes);
BLI_freelistN(&graph->textures);
+ BLI_freelistN(&graph->attributes);
}
/* Prune Unused Nodes */
@@ -507,15 +609,13 @@ static void gpu_nodes_tag(GPUNodeLink *link)
void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
{
- GPUNode *node, *next;
-
- for (node = graph->nodes.first; node; node = node->next) {
+ for (GPUNode *node = graph->nodes.first; node; node = node->next) {
node->tag = false;
}
gpu_nodes_tag(graph->outlink);
- for (node = graph->nodes.first; node; node = next) {
+ for (GPUNode *node = graph->nodes.first, *next = NULL; node; node = next) {
next = node->next;
if (!node->tag) {
@@ -523,4 +623,18 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
gpu_node_free(node);
}
}
+
+ for (GPUMaterialAttribute *attr = graph->attributes.first, *next = NULL; attr; attr = next) {
+ next = attr->next;
+ if (attr->users == 0) {
+ BLI_freelinkN(&graph->attributes, attr);
+ }
+ }
+
+ for (GPUMaterialTexture *tex = graph->textures.first, *next = NULL; tex; tex = next) {
+ next = tex->next;
+ if (tex->users == 0) {
+ BLI_freelinkN(&graph->textures, tex);
+ }
+ }
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index 2ffde8dba39..9214bd7f1ba 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -19,6 +19,8 @@
/** \file
* \ingroup gpu
+ *
+ * Intermediate node graph for generating GLSL shaders.
*/
#ifndef __GPU_NODE_GRAPH_H__
@@ -45,6 +47,7 @@ typedef enum eGPUDataSource {
GPU_SOURCE_BUILTIN,
GPU_SOURCE_STRUCT,
GPU_SOURCE_TEX,
+ GPU_SOURCE_TEX_TILED_MAPPING,
} eGPUDataSource;
typedef enum {
@@ -53,8 +56,9 @@ typedef enum {
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_IMAGE,
+ GPU_NODE_LINK_IMAGE_TILED,
+ GPU_NODE_LINK_IMAGE_TILED_MAPPING,
GPU_NODE_LINK_OUTPUT,
GPU_NODE_LINK_UNIFORM,
} GPUNodeLinkType;
@@ -79,7 +83,7 @@ struct GPUNodeLink {
union {
/* GPU_NODE_LINK_CONSTANT | GPU_NODE_LINK_UNIFORM */
- float *data;
+ const float *data;
/* GPU_NODE_LINK_BUILTIN */
eGPUBuiltin builtin;
/* GPU_NODE_LINK_COLORBAND */
@@ -87,15 +91,9 @@ struct GPUNodeLink {
/* 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;
- };
+ struct GPUMaterialAttribute *attr;
+ /* GPU_NODE_LINK_IMAGE_BLENDER */
+ struct GPUMaterialTexture *texture;
};
};
@@ -118,35 +116,16 @@ typedef struct GPUInput {
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 **colorband; /* 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_TEX | GPU_SOURCE_TEX_TILED_MAPPING */
+ struct GPUMaterialTexture *texture;
/* 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;
- };
+ struct GPUMaterialAttribute *attr;
};
} GPUInput;
@@ -154,8 +133,7 @@ typedef struct GPUNodeGraph {
/* Nodes */
ListBase nodes;
- /* Inputs and output. */
- ListBase inputs;
+ /* Output. */
GPUNodeLink *outlink;
/* Requested attributes and textures. */
@@ -171,7 +149,7 @@ void gpu_node_graph_free(GPUNodeGraph *graph);
/* Material calls */
-void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node);
+struct GPUNodeGraph *gpu_material_node_graph(struct GPUMaterial *material);
struct GPUTexture **gpu_material_ramp_texture_row_set(struct GPUMaterial *mat,
int size,
float *pixels,