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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2020-02-27 15:55:29 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-02-27 18:14:21 +0300
commite88a715364981af39353073c6d96b9056fafca6b (patch)
tree5deb475604760b1e5a59fc3ef4409f38d8ecfd11 /source/blender/gpu
parent1ec11363bd93cf6bd43e5da33322b3f88a9be210 (diff)
Cleanup: more refactoring of GPU material attributes and textures
This further separates requested attributes and textures from the actual node graph, that can be retained after the graph has been compiled and freed. It makes it easier to add volume grids as a native concept, which sits somewhere between an attribute and a texture. It also adds explicit link types for UDIM tile mapping, rather than relying on fairly hidden logic.
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_material.h19
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c411
-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, 323 insertions, 346 deletions
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 800843dd851..37fe30bc96b 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -64,6 +64,7 @@ typedef enum eGPUType {
GPU_VEC4 = 4,
GPU_MAT3 = 9,
GPU_MAT4 = 16,
+ GPU_MAX_CONSTANT_DATA = GPU_MAT4,
/* Values not in GPU_DATATYPE_STR */
GPU_TEX1D_ARRAY = 1001,
@@ -137,10 +138,12 @@ typedef enum eGPUMaterialStatus {
GPU_MAT_SUCCESS,
} eGPUMaterialStatus;
-GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
-GPUNodeLink *GPU_constant(float *num);
-GPUNodeLink *GPU_uniform(float *num);
-GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_constant(const float *num);
+GPUNodeLink *GPU_uniform(const float *num);
+GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name);
+GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
@@ -212,17 +215,19 @@ typedef struct GPUMaterialAttribute {
struct GPUMaterialAttribute *next, *prev;
int type; /* CustomDataType */
char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ eGPUType gputype;
int id;
+ int users;
} GPUMaterialAttribute;
typedef struct GPUMaterialTexture {
struct GPUMaterialTexture *next, *prev;
- eGPUType type;
struct Image *ima;
struct ImageUser *iuser;
struct GPUTexture **colorband;
- char shadername[32]; /* Name of sampler in GLSL. */
- int id;
+ char sampler_name[32]; /* Name of sampler in GLSL. */
+ char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */
+ int users;
} GPUMaterialTexture;
ListBase GPU_material_attributes(GPUMaterial *material);
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_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,