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