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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2020-02-14 12:47:20 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2020-02-15 23:09:29 +0300
commit322dc723165a705c34df1e3246e500da1a9927de (patch)
treed82e780e36c89b327d58aa2b8ee215ee8a9fd514 /source/blender/gpu
parent007f1b74a67302fb4c164eb26969419434a98aee (diff)
Cleanup: refactor GPU material attribute and texture requests
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_material.h26
-rw-r--r--source/blender/gpu/GPU_shader.h10
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c188
-rw-r--r--source/blender/gpu/intern/gpu_material.c22
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c54
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h22
6 files changed, 147 insertions, 175 deletions
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 8c166ed6b64..075829065df 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -39,7 +39,6 @@ struct GPUNodeLink;
struct GPUNodeStack;
struct GPUTexture;
struct GPUUniformBuffer;
-struct GPUVertAttrLayers;
struct Image;
struct ImageUser;
struct ListBase;
@@ -161,7 +160,6 @@ GPUNodeLink *GPU_uniformbuffer_link_out(struct GPUMaterial *mat,
const int index);
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link);
-eGPUBuiltin GPU_get_material_builtins(GPUMaterial *material);
void GPU_material_sss_profile_create(GPUMaterial *material,
float radii[3],
@@ -201,8 +199,6 @@ struct GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material);
void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs);
struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void);
-void GPU_material_vertex_attrs(GPUMaterial *material, struct GPUVertAttrLayers *attrs);
-
bool GPU_material_use_domain_surface(GPUMaterial *mat);
bool GPU_material_use_domain_volume(GPUMaterial *mat);
@@ -213,6 +209,28 @@ void GPU_pass_cache_init(void);
void GPU_pass_cache_garbage_collect(void);
void GPU_pass_cache_free(void);
+/* Requested Material Attributes and Textures */
+
+typedef struct GPUMaterialAttribute {
+ struct GPUMaterialAttribute *next, *prev;
+ int type; /* CustomDataType */
+ char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ int id;
+} 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;
+} GPUMaterialTexture;
+
+ListBase GPU_material_attributes(GPUMaterial *material);
+ListBase GPU_material_textures(GPUMaterial *material);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 1339873ec67..d5716cd1b31 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -382,16 +382,6 @@ void GPU_shader_free_builtin_shaders(void);
* This makes sure the GPUVertexFormat name buffer does not overflow. */
#define GPU_MAX_ATTR 15
-typedef struct GPUVertAttrLayers {
- struct {
- int type; /* CustomDataType */
- int attr_id;
- char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
- } layer[GPU_MAX_ATTR];
-
- int totlayer;
-} GPUVertAttrLayers;
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 2f9af536b8c..ed6bf20cff4 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -70,16 +70,13 @@ extern char datatoc_common_view_lib_glsl[];
static GPUPass *pass_cache = NULL;
static SpinLock pass_cache_spin;
-static uint32_t gpu_pass_hash(const char *frag_gen, const char *defs, GPUVertAttrLayers *attrs)
+static uint32_t gpu_pass_hash(const char *frag_gen, const char *defs, ListBase *attributes)
{
BLI_HashMurmur2A hm2a;
BLI_hash_mm2a_init(&hm2a, 0);
BLI_hash_mm2a_add(&hm2a, (uchar *)frag_gen, strlen(frag_gen));
- if (attrs) {
- for (int att_idx = 0; att_idx < attrs->totlayer; att_idx++) {
- char *name = attrs->layer[att_idx].name;
- BLI_hash_mm2a_add(&hm2a, (uchar *)name, strlen(name));
- }
+ for (GPUMaterialAttribute *attr = attributes->first; attr; attr = attr->next) {
+ BLI_hash_mm2a_add(&hm2a, (uchar *)attr->name, strlen(attr->name));
}
if (defs) {
BLI_hash_mm2a_add(&hm2a, (uchar *)defs, strlen(defs));
@@ -302,55 +299,17 @@ static const char *gpu_builtin_name(eGPUBuiltin builtin)
}
}
-/* assign only one texid per buffer to avoid sampling the same texture twice */
-static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key1, int key2)
-{
- GHashPair pair = {key1, POINTER_FROM_INT(key2)};
- if (BLI_ghash_haskey(bindhash, &pair)) {
- /* Reuse existing texid */
- input->texid = POINTER_AS_INT(BLI_ghash_lookup(bindhash, &pair));
- }
- else {
- /* Allocate new texid */
- input->texid = *texid;
- (*texid)++;
- input->bindtex = true;
- void *key = BLI_ghashutil_pairalloc(key1, POINTER_FROM_INT(key2));
- BLI_ghash_insert(bindhash, key, POINTER_FROM_INT(input->texid));
- }
-}
-
static void codegen_set_unique_ids(ListBase *nodes)
{
- GHash *bindhash;
GPUNode *node;
GPUInput *input;
GPUOutput *output;
- int id = 1, texid = 0;
-
- bindhash = BLI_ghash_pair_new("codegen_set_unique_ids1 gh");
+ int id = 1;
for (node = 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++;
-
- /* set texid used for settings texture slot */
- if (codegen_input_has_texture(input)) {
- input->bindtex = false;
- if (input->ima) {
- /* input is texture from image */
- codegen_set_texid(bindhash, input, &texid, input->ima, input->type);
- }
- else if (input->coba) {
- /* input is color band texture, check coba pointer */
- codegen_set_texid(bindhash, input, &texid, input->coba, 0);
- }
- else {
- /* Either input->ima or input->coba should be non-NULL. */
- BLI_assert(0);
- }
- }
}
for (output = node->outputs.first; output; output = output->next) {
@@ -358,8 +317,6 @@ static void codegen_set_unique_ids(ListBase *nodes)
output->id = id++;
}
}
-
- BLI_ghash_free(bindhash, BLI_ghashutil_pairfree, NULL);
}
/**
@@ -380,7 +337,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
/* create exactly one sampler for each texture */
if (codegen_input_has_texture(input) && input->bindtex) {
const char *type;
- if (input->coba || input->type == GPU_TEX1D_ARRAY) {
+ if (input->colorband || input->type == GPU_TEX1D_ARRAY) {
type = "sampler1DArray";
}
else if (input->type == GPU_TEX2D_ARRAY) {
@@ -570,10 +527,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,
- int *rbuiltins)
+static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUOutput *output)
{
DynStr *ds = BLI_dynstr_new();
char *code;
@@ -584,7 +538,7 @@ static char *code_generate_fragment(GPUMaterial *material,
#endif
codegen_set_unique_ids(nodes);
- *rbuiltins = builtins = codegen_process_uniforms_functions(material, ds, nodes);
+ builtins = codegen_process_uniforms_functions(material, ds, nodes);
if (builtins & (GPU_OBJECT_INFO | GPU_OBJECT_COLOR)) {
BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
@@ -1099,45 +1053,90 @@ GPUShader *GPU_pass_shader_get(GPUPass *pass)
return pass->shader;
}
-/* Vertex Attributes */
+/* Requested Attributes */
-static void gpu_nodes_get_vertex_attrs(ListBase *nodes, GPUVertAttrLayers *attrs)
+static ListBase gpu_nodes_requested_attributes(ListBase *nodes)
{
- GPUNode *node;
- GPUInput *input;
- int a;
+ ListBase attributes = {NULL};
+ int num_attributes = 0;
- /* convert attributes requested by node inputs to an array of layers,
+ /* 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;
+ }
- memset(attrs, 0, sizeof(*attrs));
-
- for (node = nodes->first; node; node = node->next) {
- for (input = node->inputs.first; input; input = input->next) {
- if (input->source == GPU_SOURCE_ATTR) {
- for (a = 0; a < attrs->totlayer; a++) {
- if (attrs->layer[a].type == input->attr_type &&
- STREQ(attrs->layer[a].name, input->attr_name)) {
- break;
- }
+ GPUMaterialAttribute *attr = attributes.first;
+ for (; attr; attr = attr->next) {
+ if (attr->type == input->attr_type && STREQ(attr->name, input->attr_name)) {
+ break;
}
+ }
- if (a < GPU_MAX_ATTR) {
- if (a == attrs->totlayer) {
- input->attr_id = attrs->totlayer++;
- input->attr_first = true;
+ /* 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);
- attrs->layer[a].type = input->attr_type;
- attrs->layer[a].attr_id = input->attr_id;
- BLI_strncpy(attrs->layer[a].name, input->attr_name, sizeof(attrs->layer[a].name));
- }
- else {
- input->attr_id = attrs->layer[a].attr_id;
- }
+ 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) {
+ 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++;
+ 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 */
@@ -1155,21 +1154,19 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
const char *frag_lib,
const char *defines)
{
- char *vertexcode, *geometrycode, *fragmentcode;
- GPUPass *pass = NULL, *pass_hash = NULL;
-
/* Prune the unused nodes and extract attributes before compiling so the
* generated VBOs are ready to accept the future shader. */
gpu_node_graph_prune_unused(graph);
- gpu_nodes_get_vertex_attrs(&graph->nodes, &graph->attrs);
+
+ 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, &graph->builtins);
+ char *fragmentgen = code_generate_fragment(material, &graph->nodes, graph->outlink->output);
/* Cache lookup: Reuse shaders already compiled */
- uint32_t hash = gpu_pass_hash(fragmentgen, defines, &graph->attrs);
- pass_hash = gpu_pass_cache_lookup(hash);
+ uint32_t hash = gpu_pass_hash(fragmentgen, defines, &graph->attributes);
+ GPUPass *pass_hash = gpu_pass_cache_lookup(hash);
if (pass_hash && (pass_hash->next == NULL || pass_hash->next->hash != hash)) {
/* No collision, just return the pass. */
@@ -1187,13 +1184,14 @@ 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);
- geometrycode = code_generate_geometry(&graph->nodes, geom_code, defines);
- vertexcode = code_generate_vertex(&graph->nodes, vert_code, (geometrycode != NULL));
- fragmentcode = BLI_strdupcat(tmp, fragmentgen);
+ char *geometrycode = code_generate_geometry(&graph->nodes, geom_code, defines);
+ char *vertexcode = code_generate_vertex(&graph->nodes, vert_code, (geometrycode != NULL));
+ char *fragmentcode = BLI_strdupcat(tmp, fragmentgen);
MEM_freeN(fragmentgen);
MEM_freeN(tmp);
+ GPUPass *pass = NULL;
if (pass_hash) {
/* Cache lookup: Reuse shaders already compiled */
pass = gpu_pass_cache_resolve_collision(
@@ -1201,16 +1199,16 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
}
if (pass) {
+ MEM_SAFE_FREE(vertexcode);
+ MEM_SAFE_FREE(fragmentcode);
+ MEM_SAFE_FREE(geometrycode);
+
/* Cache hit. Reuse the same GPUPass and GPUShader. */
if (!gpu_pass_is_valid(pass)) {
/* Shader has already been created but failed to compile. */
return NULL;
}
- MEM_SAFE_FREE(vertexcode);
- MEM_SAFE_FREE(fragmentcode);
- MEM_SAFE_FREE(geometrycode);
-
pass->refcount += 1;
}
else {
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 9eed3e4619b..d8d3e5a2ff2 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -197,11 +197,6 @@ void GPU_material_free(ListBase *gpumaterial)
BLI_freelistN(gpumaterial);
}
-eGPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
-{
- return material->graph.builtins;
-}
-
Scene *GPU_material_scene(GPUMaterial *material)
{
return material->scene;
@@ -567,9 +562,14 @@ struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void)
#undef SSS_EXPONENT
#undef SSS_SAMPLES
-void GPU_material_vertex_attrs(GPUMaterial *material, GPUVertAttrLayers *r_attrs)
+ListBase GPU_material_attributes(GPUMaterial *material)
{
- *r_attrs = material->graph.attrs;
+ return material->graph.attributes;
+}
+
+ListBase GPU_material_textures(GPUMaterial *material)
+{
+ return material->graph.textures;
}
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
@@ -696,13 +696,14 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
if (mat->pass == NULL) {
/* We had a cache hit and the shader has already failed to compile. */
mat->status = GPU_MAT_FAILED;
+ gpu_node_graph_free(&mat->graph);
}
else {
GPUShader *sh = GPU_pass_shader_get(mat->pass);
if (sh != NULL) {
/* We had a cache hit and the shader is already compiled. */
mat->status = GPU_MAT_SUCCESS;
- gpu_node_graph_extract_dynamic_inputs(sh, &mat->graph);
+ gpu_node_graph_free_nodes(&mat->graph);
}
else {
mat->status = GPU_MAT_QUEUED;
@@ -711,6 +712,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
}
else {
mat->status = GPU_MAT_FAILED;
+ gpu_node_graph_free(&mat->graph);
}
/* Only free after GPU_pass_shader_get where GPUUniformBuffer
@@ -748,14 +750,14 @@ void GPU_material_compile(GPUMaterial *mat)
GPUShader *sh = GPU_pass_shader_get(mat->pass);
if (sh != NULL) {
mat->status = GPU_MAT_SUCCESS;
- gpu_node_graph_extract_dynamic_inputs(sh, &mat->graph);
+ gpu_node_graph_free_nodes(&mat->graph);
}
}
else {
mat->status = GPU_MAT_FAILED;
- gpu_node_graph_free(&mat->graph);
GPU_pass_release(mat->pass);
mat->pass = NULL;
+ gpu_node_graph_free(&mat->graph);
}
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 432c2d773b5..b271ac48f75 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -111,7 +111,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
break;
case GPU_NODE_LINK_COLORBAND:
input->source = GPU_SOURCE_TEX;
- input->coba = link->coba;
+ input->colorband = link->colorband;
break;
case GPU_NODE_LINK_IMAGE_BLENDER:
case GPU_NODE_LINK_IMAGE_TILEMAP:
@@ -295,7 +295,7 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
{
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_COLORBAND;
- link->coba = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
+ link->colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
MEM_freeN(pixels);
return link;
}
@@ -460,7 +460,8 @@ static void gpu_node_free(GPUNode *node)
MEM_freeN(node);
}
-void gpu_node_graph_free(GPUNodeGraph *graph)
+/* Free intermediate node graph. */
+void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
{
GPUNode *node;
@@ -470,51 +471,14 @@ void gpu_node_graph_free(GPUNodeGraph *graph)
gpu_inputs_free(&graph->inputs);
graph->outlink = NULL;
- graph->builtins = 0;
- memset(&graph->attrs, 0, sizeof(graph->attrs));
}
-/* Extract Dynamic Inputs */
-
-void gpu_node_graph_extract_dynamic_inputs(GPUShader *shader, GPUNodeGraph *graph)
+/* Free both node graph and requested attributes and textures. */
+void gpu_node_graph_free(GPUNodeGraph *graph)
{
- GPUNode *node;
- GPUInput *next, *input;
-
- if (!shader) {
- return;
- }
-
- while ((node = BLI_pophead(&graph->nodes))) {
- for (input = node->inputs.first; input; input = next) {
- next = input->next;
-
- /* attributes don't need to be bound, they already have
- * an id that the drawing functions will use. Builtins have
- * constant names. */
- if (ELEM(input->source, GPU_SOURCE_ATTR, GPU_SOURCE_BUILTIN)) {
- continue;
- }
-
- if (input->source == GPU_SOURCE_TEX) {
- BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
- }
- else {
- BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
- }
-
- if (input->source == GPU_SOURCE_TEX) {
- if (input->bindtex) {
- input->shaderloc = GPU_shader_get_uniform_ensure(shader, input->shadername);
- /* extract nodes */
- BLI_remlink(&node->inputs, input);
- BLI_addtail(&graph->inputs, input);
- }
- }
- }
-
- gpu_node_free(node);
- }
+ gpu_node_graph_free_nodes(graph);
+ BLI_freelistN(&graph->attributes);
+ BLI_freelistN(&graph->textures);
}
/* Prune Unused Nodes */
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index 51e188e3f5e..2ffde8dba39 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -83,7 +83,7 @@ struct GPUNodeLink {
/* GPU_NODE_LINK_BUILTIN */
eGPUBuiltin builtin;
/* GPU_NODE_LINK_COLORBAND */
- struct GPUTexture **coba;
+ struct GPUTexture **colorband;
/* GPU_NODE_LINK_OUTPUT */
struct GPUOutput *output;
/* GPU_NODE_LINK_ATTR */
@@ -129,12 +129,12 @@ typedef struct GPUInput {
eGPUBuiltin builtin; /* builtin uniform */
/* GPU_SOURCE_TEX */
struct {
- struct GPUTexture **coba; /* input texture, only set at runtime */
- struct Image *ima; /* image */
- struct ImageUser *iuser; /* image user */
- bool bindtex; /* input is responsible for binding the texture? */
- int texid; /* number for multitexture, starting from zero */
- eGPUType textype; /* texture type (2D, 1D Array ...) */
+ 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_ATTR */
struct {
@@ -158,15 +158,15 @@ typedef struct GPUNodeGraph {
ListBase inputs;
GPUNodeLink *outlink;
- /* Needed attributes. */
- GPUVertAttrLayers attrs;
- int builtins;
+ /* Requested attributes and textures. */
+ ListBase attributes;
+ ListBase textures;
} GPUNodeGraph;
/* Node Graph */
void gpu_node_graph_prune_unused(GPUNodeGraph *graph);
-void gpu_node_graph_extract_dynamic_inputs(struct GPUShader *shader, GPUNodeGraph *graph);
+void gpu_node_graph_free_nodes(GPUNodeGraph *graph);
void gpu_node_graph_free(GPUNodeGraph *graph);
/* Material calls */