[Bf-blender-cvs] [1eeb846e781] master: Fix Cycles viewport render not updating when tweaking displacement shader.

Brecht Van Lommel noreply at git.blender.org
Mon Jan 29 17:12:43 CET 2018


Commit: 1eeb846e781dac3f55d6c108d0fc4c3cfe88f4cc
Author: Brecht Van Lommel
Date:   Wed Jan 24 20:19:48 2018 +0100
Branches: master
https://developer.blender.org/rB1eeb846e781dac3f55d6c108d0fc4c3cfe88f4cc

Fix Cycles viewport render not updating when tweaking displacement shader.

This was disabled to avoid updating the geometry every time when the
material includes displacement, because there was no way to distinguish
between surface shader and displacement updates.

As a solution, we now compute an MD5 hash of the nodes linked to the
displacement socket, and only update the mesh if that changes.

Differential Revision: https://developer.blender.org/D3018

===================================================================

M	intern/cycles/blender/blender_mesh.cpp
M	intern/cycles/graph/node.cpp
M	intern/cycles/graph/node.h
M	intern/cycles/render/film.cpp
M	intern/cycles/render/graph.cpp
M	intern/cycles/render/graph.h
M	intern/cycles/render/mesh.cpp
M	intern/cycles/render/shader.cpp
M	intern/cycles/render/shader.h
M	intern/cycles/util/util_md5.cpp
M	intern/cycles/util/util_md5.h

===================================================================

diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 3b07464cd96..cda9fb59e49 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -1123,7 +1123,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
 			bool attribute_recalc = false;
 
 			foreach(Shader *shader, mesh->used_shaders)
-				if(shader->need_update_attributes)
+				if(shader->need_update_mesh)
 					attribute_recalc = true;
 
 			if(!attribute_recalc)
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index 10d91a1e4ef..c71221746ad 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -18,6 +18,7 @@
 #include "graph/node_type.h"
 
 #include "util/util_foreach.h"
+#include "util/util_md5.h"
 #include "util/util_param.h"
 #include "util/util_transform.h"
 
@@ -403,5 +404,24 @@ bool Node::equals(const Node& other) const
 	return true;
 }
 
+/* Hash */
+
+void Node::hash(MD5Hash& md5)
+{
+	md5.append(type->name.string());
+
+	foreach(const SocketType& socket, type->inputs) {
+		md5.append(socket.name.string());
+
+		if(socket.is_array()) {
+			const array<bool>* a = (const array<bool>*)(((char*)this) + socket.struct_offset);
+			md5.append((uint8_t*)a->data(), socket.size() * a->size());
+		}
+		else {
+			md5.append(((uint8_t*)this) + socket.struct_offset, socket.size());
+		}
+	}
+}
+
 CCL_NAMESPACE_END
 
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index 53425f5faf1..d198c38be32 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -24,6 +24,7 @@
 
 CCL_NAMESPACE_BEGIN
 
+class MD5Hash;
 struct Node;
 struct NodeType;
 struct Transform;
@@ -88,6 +89,9 @@ struct Node
 	/* equals */
 	bool equals(const Node& other) const;
 
+	/* compute hash of node and its socket values */
+	void hash(MD5Hash& md5);
+
 	ustring name;
 	const NodeType *type;
 };
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index b305f01095f..69828cc78da 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -496,7 +496,7 @@ void Film::tag_passes_update(Scene *scene, const array<Pass>& passes_)
 		scene->mesh_manager->tag_update(scene);
 
 		foreach(Shader *shader, scene->shaders)
-			shader->need_update_attributes = true;
+			shader->need_update_mesh = true;
 	}
 	else if(Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION))
 		scene->mesh_manager->tag_update(scene);
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index fb2e34c2fc7..096de878e51 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -23,8 +23,9 @@
 
 #include "util/util_algorithm.h"
 #include "util/util_foreach.h"
-#include "util/util_queue.h"
 #include "util/util_logging.h"
+#include "util/util_md5.h"
+#include "util/util_queue.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -683,6 +684,32 @@ void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<b
 	on_stack[node->id] = false;
 }
 
+void ShaderGraph::compute_displacement_hash()
+{
+	/* Compute hash of all nodes linked to displacement, to detect if we need
+	 * to recompute displacement when shader nodes change. */
+	ShaderInput *displacement_in = output()->input("Displacement");
+
+	if(!displacement_in->link) {
+		displacement_hash = "";
+		return;
+	}
+
+	ShaderNodeSet nodes_displace;
+	find_dependencies(nodes_displace, displacement_in);
+
+	MD5Hash md5;
+	foreach(ShaderNode *node, nodes_displace) {
+		node->hash(md5);
+		foreach(ShaderInput *input, node->inputs) {
+			int link_id = (input->link) ? input->link->parent->id : 0;
+			md5.append((uint8_t*)&link_id, sizeof(link_id));
+		}
+	}
+
+	displacement_hash = md5.get_hex();
+}
+
 void ShaderGraph::clean(Scene *scene)
 {
 	/* Graph simplification */
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 1d1701b30a2..7ed292b5b96 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -42,6 +42,7 @@ class SVMCompiler;
 class OSLCompiler;
 class OutputNode;
 class ConstantFolder;
+class MD5Hash;
 
 /* Bump
  *
@@ -243,6 +244,7 @@ public:
 	size_t num_node_ids;
 	bool finalized;
 	bool simplified;
+	string displacement_hash;
 
 	ShaderGraph();
 	~ShaderGraph();
@@ -256,6 +258,7 @@ public:
 	void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
 
 	void remove_proxy_nodes();
+	void compute_displacement_hash();
 	void simplify(Scene *scene);
 	void finalize(Scene *scene,
 	              bool do_bump = false,
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 4bf5b60a737..5bcb47deb65 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -1964,7 +1964,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
 	/* Update normals. */
 	foreach(Mesh *mesh, scene->meshes) {
 		foreach(Shader *shader, mesh->used_shaders) {
-			if(shader->need_update_attributes)
+			if(shader->need_update_mesh)
 				mesh->need_update = true;
 		}
 
@@ -2104,7 +2104,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
 	        << summary.full_report();
 
 	foreach(Shader *shader, scene->shaders) {
-		shader->need_update_attributes = false;
+		shader->need_update_mesh = false;
 	}
 
 	Scene::MotionType need_motion = scene->need_motion();
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index abb9e19a074..51b7f76b9d5 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -200,7 +200,7 @@ Shader::Shader()
 	used = false;
 
 	need_update = true;
-	need_update_attributes = true;
+	need_update_mesh = true;
 }
 
 Shader::~Shader()
@@ -235,9 +235,24 @@ void Shader::set_graph(ShaderGraph *graph_)
 	/* do this here already so that we can detect if mesh or object attributes
 	 * are needed, since the node attribute callbacks check if their sockets
 	 * are connected but proxy nodes should not count */
-	if(graph_)
+	if(graph_) {
 		graph_->remove_proxy_nodes();
 
+		if(displacement_method != DISPLACE_BUMP) {
+			graph_->compute_displacement_hash();
+		}
+	}
+
+	/* update geometry if displacement changed */
+	if(displacement_method != DISPLACE_BUMP) {
+		const char *old_hash = (graph)? graph->displacement_hash.c_str() : "";
+		const char *new_hash = (graph_)? graph_->displacement_hash.c_str() : "";
+
+		if(strcmp(old_hash, new_hash) != 0) {
+			need_update_mesh = true;
+		}
+	}
+
 	/* assign graph */
 	delete graph;
 	graph = graph_;
@@ -294,9 +309,9 @@ void Shader::tag_update(Scene *scene)
 	}
 	
 	/* compare if the attributes changed, mesh manager will check
-	 * need_update_attributes, update the relevant meshes and clear it. */
+	 * need_update_mesh, update the relevant meshes and clear it. */
 	if(attributes.modified(prev_attributes)) {
-		need_update_attributes = true;
+		need_update_mesh = true;
 		scene->mesh_manager->need_update = true;
 	}
 
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 3fdcd3c0c5b..4a48c1347da 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -98,7 +98,7 @@ public:
 
 	/* synchronization */
 	bool need_update;
-	bool need_update_attributes;
+	bool need_update_mesh;
 
 	/* If the shader has only volume components, the surface is assumed to
 	 * be transparent.
diff --git a/intern/cycles/util/util_md5.cpp b/intern/cycles/util/util_md5.cpp
index 19168135f01..749760d84f0 100644
--- a/intern/cycles/util/util_md5.cpp
+++ b/intern/cycles/util/util_md5.cpp
@@ -310,6 +310,13 @@ void MD5Hash::append(const uint8_t *data, int nbytes)
 		memcpy(buf, p, left);
 }
 
+void MD5Hash::append(const string& str)
+{
+	if(str.size()) {
+		append((const uint8_t*)str.c_str(), str.size());
+	}
+}
+
 bool MD5Hash::append_file(const string& filepath)
 {
 	FILE *f = path_fopen(filepath, "rb");
diff --git a/intern/cycles/util/util_md5.h b/intern/cycles/util/util_md5.h
index e4cd66c85b0..b043b591e67 100644
--- a/intern/cycles/util/util_md5.h
+++ b/intern/cycles/util/util_md5.h
@@ -41,6 +41,7 @@ public:
 	~MD5Hash();
 
 	void append(const uint8_t *data, int size);
+	void append(const string& str);
 	bool append_file(const string& filepath);
 	string get_hex();



More information about the Bf-blender-cvs mailing list