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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
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
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')
-rw-r--r--source/blender/draw/intern/draw_manager_data.c38
-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
-rw-r--r--source/blender/nodes/shader/node_shader_util.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_attribute.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tangent.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c32
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_sky.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_uvmap.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_displacement.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vertex_color.c2
18 files changed, 377 insertions, 401 deletions
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index fbdabb44b15..43e8e2a4733 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -1203,6 +1203,19 @@ static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass
return grp;
}
+static void drw_shgroup_material_texture(DRWShadingGroup *grp,
+ GPUMaterialTexture *tex,
+ const char *name,
+ int textarget)
+{
+ GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget);
+ DRW_shgroup_uniform_texture(grp, name, gputex);
+
+ GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images);
+ *gputex_ref = gputex;
+ GPU_texture_ref(gputex);
+}
+
static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
struct GPUMaterial *material)
{
@@ -1210,35 +1223,20 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
/* Bind all textures needed by the material. */
for (GPUMaterialTexture *tex = textures.first; tex; tex = tex->next) {
- GPUTexture *gputex;
-
if (tex->ima) {
/* Image */
- GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images);
-
- int textarget;
- if (tex->type == GPU_TEX2D_ARRAY) {
- textarget = GL_TEXTURE_2D_ARRAY;
- }
- else if (tex->type == GPU_TEX1D_ARRAY) {
- textarget = GL_TEXTURE_1D_ARRAY;
+ if (tex->tiled_mapping_name[0]) {
+ drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D_ARRAY);
+ drw_shgroup_material_texture(grp, tex, tex->tiled_mapping_name, GL_TEXTURE_1D_ARRAY);
}
else {
- textarget = GL_TEXTURE_2D;
+ drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D);
}
- *gputex_ref = gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget);
-
- GPU_texture_ref(gputex);
}
else if (tex->colorband) {
/* Color Ramp */
- gputex = *tex->colorband;
+ DRW_shgroup_uniform_texture(grp, tex->sampler_name, *tex->colorband);
}
- else {
- continue;
- }
-
- DRW_shgroup_uniform_texture(grp, tex->shadername, gputex);
}
GPUUniformBuffer *ubo = GPU_material_uniform_buffer_get(material);
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,
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 9615c6f01e0..93d03720058 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -276,7 +276,7 @@ void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink *
void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
{
if (!*link) {
- *link = GPU_attribute(CD_ORCO, "");
+ *link = GPU_attribute(mat, CD_ORCO, "");
GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), *link, link);
node_shader_gpu_bump_tex_coord(mat, node, link);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c
index ecb8c53c312..757db5fe8b3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_attribute.c
+++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c
@@ -66,7 +66,7 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
GPU_builtin(GPU_VOLUME_TEMPERATURE));
}
else {
- GPUNodeLink *cd_attr = GPU_attribute(CD_AUTO_FROM_NAME, attr->name);
+ GPUNodeLink *cd_attr = GPU_attribute(mat, CD_AUTO_FROM_NAME, attr->name);
GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr);
/* for each output. */
diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c
index 6b23fec5f18..b1ee3c4806a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geometry.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c
@@ -46,7 +46,8 @@ static int node_shader_gpu_geometry(GPUMaterial *mat,
GPUNodeLink *bary_link = (!out[5].hasoutput) ? GPU_constant(val) :
GPU_builtin(GPU_BARYCENTRIC_TEXCO);
/* Opti: don't request orco if not needed. */
- GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) : GPU_attribute(CD_ORCO, "");
+ GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) :
+ GPU_attribute(mat, CD_ORCO, "");
const bool success = GPU_stack_link(mat,
node,
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index 006f15f40a1..0f3ffe51706 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -92,7 +92,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
GPU_link(mat,
"node_normal_map",
GPU_builtin(GPU_OBJECT_INFO),
- GPU_attribute(CD_TANGENT, nm->uv_map),
+ GPU_attribute(mat, CD_TANGENT, nm->uv_map),
GPU_builtin(GPU_WORLD_NORMAL),
newnormal,
&newnormal);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c
index 478b9524737..474db465d87 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tangent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c
@@ -43,10 +43,10 @@ static int node_shader_gpu_tangent(GPUMaterial *mat,
if (attr->direction_type == SHD_TANGENT_UVMAP) {
return GPU_stack_link(
- mat, node, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, attr->uv_map));
+ mat, node, "node_tangentmap", in, out, GPU_attribute(mat, CD_TANGENT, attr->uv_map));
}
else {
- GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
+ GPUNodeLink *orco = GPU_attribute(mat, CD_ORCO, "");
if (attr->axis == SHD_TANGENT_AXIS_X) {
GPU_link(mat, "tangent_orco_x", orco, &orco);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
index 3c1a2280aae..81a5ee31f7d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -47,8 +47,8 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat,
/* Opti: don't request orco if not needed. */
GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant((float[4]){0.0f, 0.0f, 0.0f, 0.0f}) :
- GPU_attribute(CD_ORCO, "");
- GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
+ GPU_attribute(mat, CD_ORCO, "");
+ GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, "");
GPUNodeLink *viewpos = GPU_builtin(GPU_VIEW_POSITION);
GPUNodeLink *worldnor = GPU_builtin(GPU_WORLD_NORMAL);
GPUNodeLink *texcofacs = GPU_builtin(GPU_CAMERA_TEXCO_FACTORS);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index 6c380efe0b2..d2615d76345 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -88,7 +88,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
"node_tex_environment_equirectangular",
in[0].link,
GPU_constant(&clamp_size),
- GPU_image(ima, iuser),
+ GPU_image(mat, ima, iuser),
&in[0].link);
}
else {
@@ -103,7 +103,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
GPU_link(mat,
"node_tex_image_linear_no_mip",
in[0].link,
- GPU_image(ima, iuser),
+ GPU_image(mat, ima, iuser),
&out[0].link,
&outalpha);
break;
@@ -111,13 +111,17 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
GPU_link(mat,
"node_tex_image_nearest",
in[0].link,
- GPU_image(ima, iuser),
+ GPU_image(mat, ima, iuser),
&out[0].link,
&outalpha);
break;
default:
- GPU_link(
- mat, "node_tex_image_cubic", in[0].link, GPU_image(ima, iuser), &out[0].link, &outalpha);
+ GPU_link(mat,
+ "node_tex_image_cubic",
+ in[0].link,
+ GPU_image(mat, ima, iuser),
+ &out[0].link,
+ &outalpha);
break;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 781fd1eb579..ebc852486dc 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -123,26 +123,21 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
}
if (!*texco) {
- *texco = GPU_attribute(CD_MTFACE, "");
+ *texco = GPU_attribute(mat, CD_MTFACE, "");
node_shader_gpu_bump_tex_coord(mat, node, texco);
}
node_shader_gpu_tex_mapping(mat, node, in, out);
if (ima->source == IMA_SRC_TILED) {
- /* The tiled shader needs both the tile array itself as well as the mapping from tile to array
- * position. Which of these to allocate is automatically decided based on the shader argument
- * type, so here the first GPU_image(ima, iuser) will resolve to the array and the second to
- * the mapping since the third argument in the shader has type sampler2DArray while
- * the fourth is sampler1DArray.
- */
+ /* UDIM tiles needs a samper2DArray and sampler1DArray for tile mapping. */
GPU_stack_link(mat,
node,
names_tiled[tex->interpolation],
in,
out,
- GPU_image(ima, iuser),
- GPU_image(ima, iuser));
+ GPU_image_tiled(mat, ima, iuser),
+ GPU_image_tiled_mapping(mat, ima, iuser));
}
else {
switch (tex->projection) {
@@ -157,20 +152,21 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
+ GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
}
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
break;
case SHD_PROJ_BOX:
vnor = GPU_builtin(GPU_WORLD_NORMAL);
ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
blend = GPU_uniform(&tex->projection_blend);
- gpu_image = GPU_image(ima, iuser);
+ gpu_image = GPU_image(mat, ima, iuser);
/* equivalent to normal_world_to_object */
GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm);
- GPU_link(mat, gpu_node_name, *texco, norm, GPU_image(ima, iuser), &col1, &col2, &col3);
+ GPU_link(
+ mat, gpu_node_name, *texco, norm, GPU_image(mat, ima, iuser), &col1, &col2, &col3);
GPU_stack_link(
mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend);
break;
@@ -184,9 +180,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
+ GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
}
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
break;
case SHD_PROJ_TUBE:
@@ -198,9 +194,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
+ GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
}
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
break;
}
@@ -208,7 +204,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
if (do_texco_clip) {
gpu_node_name = names_clip[tex->interpolation];
in[0].link = input_coords;
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser), out[0].link);
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser), out[0].link);
}
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
index b1fb0cad4b2..0a576e465fa 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c
@@ -63,7 +63,7 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat,
GPUNodeStack *out)
{
if (!in[0].link) {
- in[0].link = GPU_attribute(CD_ORCO, "");
+ in[0].link = GPU_attribute(mat, CD_ORCO, "");
}
node_shader_gpu_tex_mapping(mat, node, in, out);
diff --git a/source/blender/nodes/shader/nodes/node_shader_uvmap.c b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
index a2e47735490..f01542be44a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_uvmap.c
+++ b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
@@ -41,7 +41,7 @@ static int node_shader_gpu_uvmap(GPUMaterial *mat,
GPUNodeStack *out)
{
NodeShaderUVMap *attr = node->storage;
- GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, attr->uv_map);
+ GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, attr->uv_map);
GPU_stack_link(mat, node, "node_uvmap", in, out, mtface);
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c
index ac8b49c4572..df303b2d3f1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c
@@ -60,7 +60,7 @@ static int gpu_shader_vector_displacement(GPUMaterial *mat,
"node_vector_displacement_tangent",
in,
out,
- GPU_attribute(CD_TANGENT, ""),
+ GPU_attribute(mat, CD_TANGENT, ""),
GPU_builtin(GPU_WORLD_NORMAL),
GPU_builtin(GPU_OBJECT_MATRIX),
GPU_builtin(GPU_VIEW_MATRIX));
diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c
index 8848fc37c66..98d575cece2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vertex_color.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.c
@@ -39,7 +39,7 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat,
GPUNodeStack *out)
{
NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage;
- GPUNodeLink *vertexColorLink = GPU_attribute(CD_MCOL, vertexColor->layer_name);
+ GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_MCOL, vertexColor->layer_name);
return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink);
}