GPUMaterial: Add a domain property.

This let us know efficiently if a material has a dedicated nodetree for each of it's output node input.

Only works for Eevee at this moment.
This commit is contained in:
Clément Foucault 2017-10-27 16:07:44 +02:00
parent 23f51a4e43
commit 18ba7e26ad
4 changed files with 62 additions and 0 deletions

View File

@ -816,6 +816,7 @@ extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *));
void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat, short compatibility);
void ntreeGPUMaterialDomain(struct bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output);
/** \} */

View File

@ -267,6 +267,8 @@ void GPU_material_vertex_attributes(GPUMaterial *material,
bool GPU_material_do_color_management(GPUMaterial *mat);
bool GPU_material_use_new_shading_nodes(GPUMaterial *mat);
bool GPU_material_use_world_space_shading(GPUMaterial *mat);
bool GPU_material_use_domain_surface(GPUMaterial *mat);
bool GPU_material_use_domain_volume(GPUMaterial *mat);
/* Exported shading */

View File

@ -135,9 +135,20 @@ struct GPUMaterial {
bool bound;
bool is_opensubdiv;
/* XXX: Should be in Material. But it depends on the output node
* used and since the output selection is difference for GPUMaterial...
*/
int domain;
GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
};
enum {
GPU_DOMAIN_SURFACE = (1 << 0),
GPU_DOMAIN_VOLUME = (1 << 1)
};
/* Forward declaration so shade_light_textures() can use this, while still keeping the code somewhat organized */
static void texture_rgb_blend(
GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg,
@ -509,6 +520,16 @@ bool GPU_material_use_world_space_shading(GPUMaterial *mat)
return BKE_scene_use_world_space_shading(mat->scene);
}
bool GPU_material_use_domain_surface(GPUMaterial *mat)
{
return (mat->domain & GPU_DOMAIN_SURFACE);
}
bool GPU_material_use_domain_volume(GPUMaterial *mat)
{
return (mat->domain & GPU_DOMAIN_VOLUME);
}
static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist)
{
GPUNodeLink *visifac;
@ -2145,6 +2166,7 @@ GPUMaterial *GPU_material_from_nodetree(
GPUMaterial *mat;
GPUNodeLink *outlink;
LinkData *link;
bool has_volume_output, has_surface_output;
/* Caller must re-use materials. */
BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
@ -2156,6 +2178,14 @@ GPUMaterial *GPU_material_from_nodetree(
mat->options = options;
ntreeGPUMaterialNodes(ntree, mat, NODE_NEW_SHADING | NODE_NEWER_SHADING);
ntreeGPUMaterialDomain(ntree, &has_surface_output, &has_volume_output);
if (has_surface_output) {
mat->domain |= GPU_DOMAIN_SURFACE;
}
if (has_volume_output) {
mat->domain |= GPU_DOMAIN_VOLUME;
}
/* Let Draw manager finish the construction. */
if (mat->outlink) {

View File

@ -527,6 +527,35 @@ static void ntree_shader_tag_ssr_node(bNodeTree *ntree, short compatibility)
nodeChainIter(ntree, output_node, ntree_tag_ssr_bsdf_cb, &lobe_count, true);
}
/* EEVEE: Find which material domain are used (volume, surface ...).
*/
void ntreeGPUMaterialDomain(bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output)
{
/* localize tree to create links for reroute and mute */
bNodeTree *localtree = ntreeLocalize(ntree);
struct bNode *output = ntree_shader_output_node(localtree);
*has_surface_output = false;
*has_volume_output = false;
if (output != NULL) {
bNodeSocket *surface_sock = ntree_shader_node_find_input(output, "Surface");
bNodeSocket *volume_sock = ntree_shader_node_find_input(output, "Volume");
if (surface_sock != NULL) {
*has_surface_output = (nodeCountSocketLinks(localtree, surface_sock) > 0);
}
if (volume_sock != NULL) {
*has_volume_output = (nodeCountSocketLinks(localtree, volume_sock) > 0);
}
}
ntreeFreeTree(localtree);
MEM_freeN(localtree);
}
void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibility)
{
/* localize tree to create links for reroute and mute */