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:
authorClément Foucault <foucault.clem@gmail.com>2017-04-27 23:27:09 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-05-01 19:11:21 +0300
commite868b459bb8efc35012b2364762f3d25d96b8b0d (patch)
treeeb2c0e9909a3a4ea5225f6b537f8b7fbdf51d832 /source/blender/gpu/intern
parent2f100c13ee14cc6876423d1ac39ef9c565fb8987 (diff)
Eevee: World nodetree gpumaterial compatibility.
- Unify GPUMaterial creation (world/mesh). - Support for multiple shader variations (not used for now). - Convert GPUInputs to DRWUniforms to be used with the draw manager. - Nodetree Update is not supported. The only way to refresh the shaders is to change render engine. - Cleanup in GPUPass. - Add new temporary Node Compatibility type. Compatibility types should be removed in the future.
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c123
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h6
-rw-r--r--source/blender/gpu/intern/gpu_material.c56
3 files changed, 179 insertions, 6 deletions
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index de2b94482f4..89c58eb8495 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -928,6 +928,67 @@ GPUShader *GPU_pass_shader(GPUPass *pass)
return pass->shader;
}
+static void gpu_nodes_extract_dynamic_inputs_new(GPUPass *pass, ListBase *nodes)
+{
+ GPUShader *shader = pass->shader;
+ GPUNode *node;
+ GPUInput *next, *input;
+ ListBase *inputs = &pass->inputs;
+ int extract, z;
+
+ memset(inputs, 0, sizeof(*inputs));
+
+ if (!shader)
+ return;
+
+ GPU_shader_bind(shader);
+
+ for (node = nodes->first; node; node = node->next) {
+ z = 0;
+ for (input = node->inputs.first; input; input = next, z++) {
+ next = input->next;
+
+ /* attributes don't need to be bound, they already have
+ * an id that the drawing functions will use */
+ if (input->source == GPU_SOURCE_ATTRIB) {
+ continue;
+ }
+
+ if (input->source == GPU_SOURCE_BUILTIN ||
+ input->source == GPU_SOURCE_OPENGL_BUILTIN)
+ {
+ continue;
+ }
+
+ if (input->ima || input->tex || input->prv)
+ BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
+ else
+ BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
+
+ /* pass non-dynamic uniforms to opengl */
+ extract = 0;
+
+ if (input->ima || input->tex || input->prv) {
+ if (input->bindtex)
+ extract = 1;
+ }
+ else if (input->dynamicvec)
+ extract = 1;
+
+ if (extract)
+ input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
+
+ /* extract nodes */
+ if (extract) {
+ BLI_remlink(&node->inputs, input);
+ BLI_addtail(inputs, input);
+ }
+ }
+ }
+
+ GPU_shader_unbind();
+}
+
static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
{
GPUShader *shader = pass->shader;
@@ -1647,6 +1708,67 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
}
}
+GPUPass *GPU_generate_pass_new(ListBase *nodes, struct GPUNodeLink *frag_outlink,
+ const char *vert_code, const char *geom_code,
+ const char *frag_lib, const char *defines)
+{
+ GPUShader *shader;
+ GPUPass *pass;
+ char *vertexgen, *geometrygen, *fragmentgen, *tmp;
+ char *vertexcode, *geometrycode, *fragmentcode;
+
+ /* prune unused nodes */
+ gpu_nodes_prune(nodes, frag_outlink);
+
+ /* generate code and compile with opengl */
+ fragmentgen = code_generate_fragment(nodes, frag_outlink->output);
+ // vertexgen = code_generate_vertex(nodes, GPU_MATERIAL_TYPE_MESH);
+ // geometrygen = code_generate_geometry(nodes, false);
+ UNUSED_VARS(vertexgen, geometrygen);
+
+ tmp = BLI_strdupcat(frag_lib, glsl_material_library);
+ fragmentcode = BLI_strdupcat(tmp, fragmentgen);
+ vertexcode = BLI_strdup(vert_code);
+ geometrycode = BLI_strdup(geom_code);
+
+ shader = GPU_shader_create(vertexcode,
+ fragmentcode,
+ geometrycode,
+ NULL,
+ defines);
+
+ MEM_freeN(tmp);
+
+ /* failed? */
+ if (!shader) {
+ if (fragmentcode)
+ MEM_freeN(fragmentcode);
+ if (vertexcode)
+ MEM_freeN(vertexcode);
+ if (geometrycode)
+ MEM_freeN(geometrycode);
+ MEM_freeN(fragmentgen);
+ gpu_nodes_free(nodes);
+ return NULL;
+ }
+
+ /* create pass */
+ pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
+ pass->shader = shader;
+ pass->fragmentcode = fragmentcode;
+ pass->geometrycode = geometrycode;
+ pass->vertexcode = vertexcode;
+ pass->libcode = glsl_material_library;
+
+ /* extract dynamic inputs and throw away nodes */
+ gpu_nodes_extract_dynamic_inputs_new(pass, nodes);
+ gpu_nodes_free(nodes);
+
+ MEM_freeN(fragmentgen);
+
+ return pass;
+}
+
GPUPass *GPU_generate_pass(
ListBase *nodes, GPUNodeLink *outlink,
GPUVertexAttribs *attribs, int *builtins,
@@ -1705,7 +1827,6 @@ GPUPass *GPU_generate_pass(
/* create pass */
pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
- pass->output = outlink->output;
pass->shader = shader;
pass->fragmentcode = fragmentcode;
pass->geometrycode = geometrycode;
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 7af17f9122d..9263fe3bc3f 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -156,10 +156,7 @@ typedef struct GPUInput {
} GPUInput;
struct GPUPass {
- struct GPUPass *next, *prev;
-
ListBase inputs;
- struct GPUOutput *output;
struct GPUShader *shader;
char *fragmentcode;
char *geometrycode;
@@ -170,6 +167,9 @@ struct GPUPass {
typedef struct GPUPass GPUPass;
+GPUPass *GPU_generate_pass_new(ListBase *nodes, struct GPUNodeLink *frag_outlink,
+ const char *vert_code, const char *geom_code,
+ const char *frag_lib, const char *defines);
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
struct GPUVertexAttribs *attribs, int *builtin,
const GPUMatType type, const char *name,
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index aa7a104ff86..083b0596b1c 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -94,12 +94,15 @@ static struct GPUWorld {
} GPUWorld;
struct GPUMaterial {
- Scene *scene;
+ Scene *scene; /* DEPRECATED was only usefull for lamps */
Material *ma;
/* material for mesh surface, worlds or something else.
* some code generation is done differently depending on the use case */
- int type;
+ int type; /* DEPRECATED */
+
+ void *engine; /* attached engine type */
+ int options; /* to identify shader variations (shadow, probe, world background...) */
/* for creating the material */
ListBase nodes;
@@ -436,6 +439,10 @@ GPUMatType GPU_Material_get_type(GPUMaterial *material)
return material->type;
}
+GPUPass *GPU_material_get_pass(GPUMaterial *material)
+{
+ return material->pass;
+}
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
@@ -470,6 +477,10 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
bool GPU_material_do_color_management(GPUMaterial *mat)
{
+ /* XXX mat->scene == NULL in that case */
+ if (mat->engine)
+ return true;
+
if (!BKE_scene_check_color_management_enabled(mat->scene))
return false;
@@ -2096,6 +2107,47 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
return mat;
}
+/* TODO : This is supposed to replace GPU_material_from_blender/_world in the future */
+GPUMaterial *GPU_material_from_nodetree(
+ struct bNodeTree *ntree, ListBase *gpumaterials, void *engine_type, int options,
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+{
+ GPUMaterial *mat;
+ GPUNodeLink *outlink;
+ LinkData *link;
+
+ for (link = gpumaterials->first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial *)link->data;
+ if (current_material->engine == engine_type &&
+ current_material->options == options)
+ {
+ return current_material;
+ }
+ }
+
+ /* allocate material */
+ mat = GPU_material_construct_begin(NULL); /* TODO remove GPU_material_construct_begin */
+ mat->engine = engine_type;
+ mat->options = options;
+
+ ntreeGPUMaterialNodes(ntree, mat, NODE_NEWER_SHADING);
+
+ /* Let Draw manager finish the construction. */
+ if (mat->outlink) {
+ outlink = mat->outlink;
+ mat->pass = GPU_generate_pass_new(&mat->nodes, outlink, vert_code, geom_code, frag_lib, defines);
+ }
+
+ /* note that even if building the shader fails in some way, we still keep
+ * it to avoid trying to compile again and again, and simple do not use
+ * the actual shader on drawing */
+
+ link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
+ link->data = mat;
+ BLI_addtail(gpumaterials, link);
+
+ return mat;
+}
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
{