[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [43422] trunk/blender/intern/cycles: Cycles: add option to cache BVH's between subsequent renders, storing the BVH on

Brecht Van Lommel brechtvanlommel at pandora.be
Mon Jan 16 14:13:47 CET 2012


Revision: 43422
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=43422
Author:   blendix
Date:     2012-01-16 13:13:37 +0000 (Mon, 16 Jan 2012)
Log Message:
-----------
Cycles: add option to cache BVH's between subsequent renders, storing the BVH on
disk to be reused by the next render.

This is useful for rendering animations where only the camera or materials change.
Note that saving the BVH to disk only to be removed for the next frame is slower
if this is not the case and the meshes do actually change.

For a render, it will save bvh files to the cache user directory, and remove all
cache files from other renders. The files are named using a MD5 hash based on the
mesh, to verify if the meshes are still the same.

Modified Paths:
--------------
    trunk/blender/intern/cycles/blender/addon/properties.py
    trunk/blender/intern/cycles/blender/addon/ui.py
    trunk/blender/intern/cycles/blender/blender_sync.cpp
    trunk/blender/intern/cycles/bvh/bvh.cpp
    trunk/blender/intern/cycles/bvh/bvh.h
    trunk/blender/intern/cycles/bvh/bvh_params.h
    trunk/blender/intern/cycles/render/mesh.cpp
    trunk/blender/intern/cycles/util/util_cache.cpp
    trunk/blender/intern/cycles/util/util_cache.h

Modified: trunk/blender/intern/cycles/blender/addon/properties.py
===================================================================
--- trunk/blender/intern/cycles/blender/addon/properties.py	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/blender/addon/properties.py	2012-01-16 13:13:37 UTC (rev 43422)
@@ -103,6 +103,8 @@
             items=enums.bvh_types, default="DYNAMIC_BVH")
         cls.debug_use_spatial_splits = BoolProperty(name="Use Spatial Splits", description="Use BVH spatial splits: longer builder time, faster render",
             default=False)
+        cls.use_cache = BoolProperty(name="Cache BVH", description="Cache last built BVH to disk for faster re-render if no geometry changed",
+            default=False)
 
     @classmethod
     def unregister(cls):

Modified: trunk/blender/intern/cycles/blender/addon/ui.py
===================================================================
--- trunk/blender/intern/cycles/blender/addon/ui.py	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/blender/addon/ui.py	2012-01-16 13:13:37 UTC (rev 43422)
@@ -147,6 +147,7 @@
         sub.label(text="Acceleration structure:")
         sub.prop(cscene, "debug_bvh_type", text="")
         sub.prop(cscene, "debug_use_spatial_splits")
+        sub.prop(cscene, "use_cache")
 
 class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
     bl_label = "Layers"

Modified: trunk/blender/intern/cycles/blender/blender_sync.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_sync.cpp	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/blender/blender_sync.cpp	2012-01-16 13:13:37 UTC (rev 43422)
@@ -236,6 +236,7 @@
 		params.bvh_type = (SceneParams::BVHType)RNA_enum_get(&cscene, "debug_bvh_type");
 
 	params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
+	params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false;
 
 	return params;
 }

Modified: trunk/blender/intern/cycles/bvh/bvh.cpp
===================================================================
--- trunk/blender/intern/cycles/bvh/bvh.cpp	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/bvh/bvh.cpp	2012-01-16 13:13:37 UTC (rev 43422)
@@ -75,12 +75,18 @@
 	foreach(Object *ob, objects) {
 		key.add(ob->mesh->verts);
 		key.add(ob->mesh->triangles);
+		key.add(&ob->bounds, sizeof(ob->bounds));
+		key.add(&ob->visibility, sizeof(ob->visibility));
+		key.add(&ob->mesh->transform_applied, sizeof(bool));
 	}
 
 	CacheData value;
 
 	if(Cache::global.lookup(key, value)) {
+		cache_filename = key.get_filename();
+
 		value.read(pack.root_index);
+		value.read(pack.SAH);
 
 		value.read(pack.nodes);
 		value.read(pack.object_node);
@@ -101,6 +107,7 @@
 	CacheData value;
 
 	value.add(pack.root_index);
+	value.add(pack.SAH);
 
 	value.add(pack.nodes);
 	value.add(pack.object_node);
@@ -111,8 +118,28 @@
 	value.add(pack.is_leaf);
 
 	Cache::global.insert(key, value);
+
+	cache_filename = key.get_filename();
 }
 
+void BVH::clear_cache_except()
+{
+	set<string> except;
+
+	if(!cache_filename.empty())
+		except.insert(cache_filename);
+
+	foreach(Object *ob, objects) {
+		Mesh *mesh = ob->mesh;
+		BVH *bvh = mesh->bvh;
+
+		if(bvh && !bvh->cache_filename.empty())
+			except.insert(bvh->cache_filename);
+	}
+
+	Cache::global.clear_except("bvh", except);
+}
+
 /* Building */
 
 void BVH::build(Progress& progress)
@@ -177,6 +204,10 @@
 	if(params.use_cache) {
 		progress.set_substatus("Writing BVH cache");
 		cache_write(key);
+
+		/* clear other bvh files from cache */
+		if(params.top_level)
+			clear_cache_except();
 	}
 }
 

Modified: trunk/blender/intern/cycles/bvh/bvh.h
===================================================================
--- trunk/blender/intern/cycles/bvh/bvh.h	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/bvh/bvh.h	2012-01-16 13:13:37 UTC (rev 43422)
@@ -20,6 +20,7 @@
 
 #include "bvh_params.h"
 
+#include "util_string.h"
 #include "util_types.h"
 #include "util_vector.h"
 
@@ -83,6 +84,7 @@
 	PackedBVH pack;
 	BVHParams params;
 	vector<Object*> objects;
+	string cache_filename;
 
 	static BVH *create(const BVHParams& params, const vector<Object*>& objects);
 	virtual ~BVH() {}
@@ -90,6 +92,8 @@
 	void build(Progress& progress);
 	void refit(Progress& progress);
 
+	void clear_cache_except();
+
 protected:
 	BVH(const BVHParams& params, const vector<Object*>& objects);
 

Modified: trunk/blender/intern/cycles/bvh/bvh_params.h
===================================================================
--- trunk/blender/intern/cycles/bvh/bvh_params.h	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/bvh/bvh_params.h	2012-01-16 13:13:37 UTC (rev 43422)
@@ -26,7 +26,7 @@
 {
 public:
 	/* spatial split area threshold */
-	bool use_spatial_split;
+	int use_spatial_split;
 	float spatial_split_alpha;
 
 	/* SAH costs */
@@ -38,14 +38,16 @@
 	int max_leaf_size;
 
 	/* object or mesh level bvh */
-	bool top_level;
+	int top_level;
 
 	/* disk cache */
-	bool use_cache;
+	int use_cache;
 
 	/* QBVH */
-	bool use_qbvh;
+	int use_qbvh;
 
+	int pad;
+
 	/* fixed parameters */
 	enum {
 		MAX_DEPTH = 64,
@@ -67,6 +69,7 @@
 		top_level = false;
 		use_cache = false;
 		use_qbvh = false;
+		pad = false;
 	}
 
 	/* SAH costs */

Modified: trunk/blender/intern/cycles/render/mesh.cpp
===================================================================
--- trunk/blender/intern/cycles/render/mesh.cpp	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/render/mesh.cpp	2012-01-16 13:13:37 UTC (rev 43422)
@@ -586,6 +586,7 @@
 	bparams.top_level = true;
 	bparams.use_qbvh = scene->params.use_qbvh;
 	bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
+	bparams.use_cache = scene->params.use_bvh_cache;
 
 	delete bvh;
 	bvh = BVH::create(bparams, scene->objects);

Modified: trunk/blender/intern/cycles/util/util_cache.cpp
===================================================================
--- trunk/blender/intern/cycles/util/util_cache.cpp	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/util/util_cache.cpp	2012-01-16 13:13:37 UTC (rev 43422)
@@ -19,11 +19,18 @@
 #include <stdio.h>
 
 #include "util_cache.h"
+#include "util_debug.h"
 #include "util_foreach.h"
+#include "util_map.h"
 #include "util_md5.h"
 #include "util_path.h"
 #include "util_types.h"
 
+#define BOOST_FILESYSTEM_VERSION 2
+
+#include <boost/filesystem.hpp> 
+#include <boost/algorithm/string.hpp>
+
 CCL_NAMESPACE_BEGIN
 
 /* CacheData */
@@ -32,6 +39,7 @@
 {
 	name = name_;
 	f = NULL;
+	have_filename = false;
 }
 
 CacheData::~CacheData()
@@ -40,24 +48,35 @@
 		fclose(f);
 }
 
+const string& CacheData::get_filename()
+{
+	if(!have_filename) {
+		MD5Hash hash;
+
+		foreach(const CacheBuffer& buffer, buffers)
+			if(buffer.size)
+				hash.append((uint8_t*)buffer.data, buffer.size);
+		
+		filename = name + "_" + hash.get_hex();
+		have_filename = true;
+	}
+
+	return filename;
+}
+
 /* Cache */
 
 Cache Cache::global;
 
-string Cache::data_filename(const CacheData& key)
+string Cache::data_filename(CacheData& key)
 {
-	MD5Hash hash;
-
-	foreach(const CacheBuffer& buffer, key.buffers)
-		hash.append((uint8_t*)buffer.data, buffer.size);
-	
-	string fname = key.name + "_" + hash.get_hex();
-	return path_get("cache/" + fname);
+	return path_user_get(path_join("cache", key.get_filename()));
 }
 
-void Cache::insert(const CacheData& key, const CacheData& value)
+void Cache::insert(CacheData& key, CacheData& value)
 {
 	string filename = data_filename(key);
+	path_create_directories(filename);
 	FILE *f = fopen(filename.c_str(), "wb");
 
 	if(!f) {
@@ -65,17 +84,18 @@
 		return;
 	}
 
-	foreach(const CacheBuffer& buffer, value.buffers) {
+	foreach(CacheBuffer& buffer, value.buffers) {
 		if(!fwrite(&buffer.size, sizeof(buffer.size), 1, f))
 			fprintf(stderr, "Failed to write to file %s.\n", filename.c_str());
-		if(!fwrite(buffer.data, buffer.size, 1, f))
-			fprintf(stderr, "Failed to write to file %s.\n", filename.c_str());
+		if(buffer.size)
+			if(!fwrite(buffer.data, buffer.size, 1, f))
+				fprintf(stderr, "Failed to write to file %s.\n", filename.c_str());
 	}
 	
 	fclose(f);
 }
 
-bool Cache::lookup(const CacheData& key, CacheData& value)
+bool Cache::lookup(CacheData& key, CacheData& value)
 {
 	string filename = data_filename(key);
 	FILE *f = fopen(filename.c_str(), "rb");
@@ -89,5 +109,22 @@
 	return true;
 }
 
+void Cache::clear_except(const string& name, const set<string>& except)
+{
+	string dir = path_user_get("cache");
+
+	if(boost::filesystem::exists(dir)) {
+		boost::filesystem::directory_iterator it(dir), it_end;
+
+		for(; it != it_end; it++) {
+			string filename = it->path().filename();
+
+			if(boost::starts_with(filename, name))
+				if(except.find(filename) == except.end())
+					boost::filesystem::remove(it->path());
+		}
+	}
+}
+
 CCL_NAMESPACE_END
 

Modified: trunk/blender/intern/cycles/util/util_cache.h
===================================================================
--- trunk/blender/intern/cycles/util/util_cache.h	2012-01-16 11:50:17 UTC (rev 43421)
+++ trunk/blender/intern/cycles/util/util_cache.h	2012-01-16 13:13:37 UTC (rev 43422)
@@ -32,6 +32,7 @@
  * different scenes where it may be hard to detect duplicate work.
  */
 
+#include "util_set.h"
 #include "util_string.h"
 #include "util_vector.h"
 
@@ -50,25 +51,25 @@
 public:
 	vector<CacheBuffer> buffers;
 	string name;
+	string filename;
+	bool have_filename;
 	FILE *f;
 
 	CacheData(const string& name = "");
 	~CacheData();
 
+	const string& get_filename();
+
 	template<typename T> void add(const vector<T>& data)
 	{
-		if(data.size()) {
-			CacheBuffer buffer(&data[0], data.size()*sizeof(T));
-			buffers.push_back(buffer);
-		}
+		CacheBuffer buffer(data.size()? &data[0]: NULL, data.size()*sizeof(T));
+		buffers.push_back(buffer);
 	}
 
 	template<typename T> void add(const array<T>& data)
 	{
-		if(data.size()) {
-			CacheBuffer buffer(&data[0], data.size()*sizeof(T));
-			buffers.push_back(buffer);
-		}
+		CacheBuffer buffer(data.size()? &data[0]: NULL, data.size()*sizeof(T));
+		buffers.push_back(buffer);
 	}
 
 	void add(void *data, size_t size)
@@ -85,6 +86,12 @@
 		buffers.push_back(buffer);
 	}
 
+	void add(float& data)
+	{
+		CacheBuffer buffer(&data, sizeof(float));
+		buffers.push_back(buffer);
+	}
+
 	void add(size_t& data)
 	{
 		CacheBuffer buffer(&data, sizeof(size_t));
@@ -113,12 +120,30 @@
 
 	void read(int& data)
 	{
+		size_t size;
+

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-blender-cvs mailing list