[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [39879] branches/cycles/intern/cycles: Cycles: optimizations for instances in scene updates before render starts,

Brecht Van Lommel brechtvanlommel at pandora.be
Fri Sep 2 18:15:18 CEST 2011


Revision: 39879
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=39879
Author:   blendix
Date:     2011-09-02 16:15:18 +0000 (Fri, 02 Sep 2011)
Log Message:
-----------
Cycles: optimizations for instances in scene updates before render starts,
should load a non-trivial mesh instanced many times quite a bit faster now.

Modified Paths:
--------------
    branches/cycles/intern/cycles/device/device_opencl.cpp
    branches/cycles/intern/cycles/render/light.cpp
    branches/cycles/intern/cycles/render/object.cpp
    branches/cycles/intern/cycles/util/util_transform.h

Modified: branches/cycles/intern/cycles/device/device_opencl.cpp
===================================================================
--- branches/cycles/intern/cycles/device/device_opencl.cpp	2011-09-02 15:19:30 UTC (rev 39878)
+++ branches/cycles/intern/cycles/device/device_opencl.cpp	2011-09-02 16:15:18 UTC (rev 39879)
@@ -217,8 +217,13 @@
 		if(!opencl_version_check())
 			return false;
 
+		/* nvidia opencl cache doesn't not work correct with includes, so force recompile */
+		static double recompile_trick = 0.0;
+		if(recompile_trick == 0.0)
+			recompile_trick = time_dt();
+
 		/* compile source */
-		string source = string_printf("#include \"kernel.cl\" // %lf\n", time_dt());
+		string source = string_printf("#include \"kernel.cl\" // %lf\n", recompile_trick);
 		size_t source_len = source.size();
 		const char *source_str = source.c_str();
 

Modified: branches/cycles/intern/cycles/render/light.cpp
===================================================================
--- branches/cycles/intern/cycles/render/light.cpp	2011-09-02 15:19:30 UTC (rev 39878)
+++ branches/cycles/intern/cycles/render/light.cpp	2011-09-02 16:15:18 UTC (rev 39879)
@@ -61,12 +61,24 @@
 
 	foreach(Object *object, scene->objects) {
 		Mesh *mesh = object->mesh;
+		bool have_emission = false;
 
-		for(size_t i = 0; i < mesh->triangles.size(); i++) {
-			Shader *shader = scene->shaders[mesh->shader[i]];
+		/* skip if we have no emission shaders */
+		foreach(uint sindex, mesh->used_shaders) {
+			if(scene->shaders[sindex]->has_surface_emission) {
+				have_emission = true;
+				break;
+			}
+		}
 
-			if(shader->has_surface_emission)
-				num_triangles++;
+		/* count triangles */
+		if(have_emission) {
+			for(size_t i = 0; i < mesh->triangles.size(); i++) {
+				Shader *shader = scene->shaders[mesh->shader[i]];
+
+				if(shader->has_surface_emission)
+					num_triangles++;
+			}
 		}
 	}
 
@@ -82,25 +94,38 @@
 
 	foreach(Object *object, scene->objects) {
 		Mesh *mesh = object->mesh;
-		Transform tfm = object->tfm;
-		int object_id = (mesh->transform_applied)? -j-1: j;
+		bool have_emission = false;
 
-		for(size_t i = 0; i < mesh->triangles.size(); i++) {
-			Shader *shader = scene->shaders[mesh->shader[i]];
+		/* skip if we have no emission shaders */
+		foreach(uint sindex, mesh->used_shaders) {
+			if(scene->shaders[sindex]->has_surface_emission) {
+				have_emission = true;
+				break;
+			}
+		}
 
-			if(shader->has_surface_emission) {
-				distribution[offset].x = totarea;
-				distribution[offset].y = __int_as_float(i + mesh->tri_offset);
-				distribution[offset].z = 1.0f;
-				distribution[offset].w = __int_as_float(object_id);
-				offset++;
+		/* sum area */
+		if(have_emission) {
+			Transform tfm = object->tfm;
+			int object_id = (mesh->transform_applied)? -j-1: j;
 
-				Mesh::Triangle t = mesh->triangles[i];
-				float3 p1 = transform(&tfm, mesh->verts[t.v[0]]);
-				float3 p2 = transform(&tfm, mesh->verts[t.v[1]]);
-				float3 p3 = transform(&tfm, mesh->verts[t.v[2]]);
+			for(size_t i = 0; i < mesh->triangles.size(); i++) {
+				Shader *shader = scene->shaders[mesh->shader[i]];
 
-				totarea += triangle_area(p1, p2, p3);
+				if(shader->has_surface_emission) {
+					distribution[offset].x = totarea;
+					distribution[offset].y = __int_as_float(i + mesh->tri_offset);
+					distribution[offset].z = 1.0f;
+					distribution[offset].w = __int_as_float(object_id);
+					offset++;
+
+					Mesh::Triangle t = mesh->triangles[i];
+					float3 p1 = transform(&tfm, mesh->verts[t.v[0]]);
+					float3 p2 = transform(&tfm, mesh->verts[t.v[1]]);
+					float3 p3 = transform(&tfm, mesh->verts[t.v[2]]);
+
+					totarea += triangle_area(p1, p2, p3);
+				}
 			}
 		}
 

Modified: branches/cycles/intern/cycles/render/object.cpp
===================================================================
--- branches/cycles/intern/cycles/render/object.cpp	2011-09-02 15:19:30 UTC (rev 39878)
+++ branches/cycles/intern/cycles/render/object.cpp	2011-09-02 16:15:18 UTC (rev 39879)
@@ -22,6 +22,7 @@
 #include "scene.h"
 
 #include "util_foreach.h"
+#include "util_map.h"
 #include "util_progress.h"
 
 CCL_NAMESPACE_BEGIN
@@ -103,6 +104,7 @@
 {
 	float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
 	int i = 0;
+	map<Mesh*, float> surface_area_map;
 
 	foreach(Object *ob, scene->objects) {
 		Mesh *mesh = ob->mesh;
@@ -112,25 +114,48 @@
 		Transform itfm = transform_inverse(tfm);
 		Transform ntfm = transform_transpose(itfm);
 
-		/* compute surface area */
+		/* compute surface area. for uniform scale we can do avoid the many
+		   transform calls and share computation for instances */
 		/* todo: correct for displacement, and move to a better place */
-		float surfacearea = 0.0f;
+		float uniform_scale;
+		float surface_area = 0.0f;
+		
+		if(transform_uniform_scale(tfm, uniform_scale)) {
+			map<Mesh*, float>::iterator it = surface_area_map.find(mesh);
 
-		foreach(Mesh::Triangle& t, mesh->triangles) {
-			float3 p1 = transform(&tfm, mesh->verts[t.v[0]]);
-			float3 p2 = transform(&tfm, mesh->verts[t.v[1]]);
-			float3 p3 = transform(&tfm, mesh->verts[t.v[2]]);
+			if(it == surface_area_map.end()) {
+				foreach(Mesh::Triangle& t, mesh->triangles) {
+					float3 p1 = mesh->verts[t.v[0]];
+					float3 p2 = mesh->verts[t.v[1]];
+					float3 p3 = mesh->verts[t.v[2]];
 
-			surfacearea += triangle_area(p1, p2, p3);
+					surface_area += triangle_area(p1, p2, p3);
+				}
+
+				surface_area_map[mesh] = surface_area;
+			}
+			else
+				surface_area = it->second;
+
+			surface_area *= uniform_scale;
 		}
+		else {
+			foreach(Mesh::Triangle& t, mesh->triangles) {
+				float3 p1 = transform(&tfm, mesh->verts[t.v[0]]);
+				float3 p2 = transform(&tfm, mesh->verts[t.v[1]]);
+				float3 p3 = transform(&tfm, mesh->verts[t.v[2]]);
 
+				surface_area += triangle_area(p1, p2, p3);
+			}
+		}
+
 		/* pack in texture */
 		int offset = i*OBJECT_SIZE;
 
 		memcpy(&objects[offset], &tfm, sizeof(float4)*4);
 		memcpy(&objects[offset+4], &itfm, sizeof(float4)*4);
 		memcpy(&objects[offset+8], &ntfm, sizeof(float4)*4);
-		objects[offset+12] = make_float4(surfacearea, 0.0f, 0.0f, 0.0f);
+		objects[offset+12] = make_float4(surface_area, 0.0f, 0.0f, 0.0f);
 
 		i++;
 

Modified: branches/cycles/intern/cycles/util/util_transform.h
===================================================================
--- branches/cycles/intern/cycles/util/util_transform.h	2011-09-02 15:19:30 UTC (rev 39878)
+++ branches/cycles/intern/cycles/util/util_transform.h	2011-09-02 16:15:18 UTC (rev 39879)
@@ -205,6 +205,30 @@
 
 Transform transform_inverse(const Transform& a);
 
+__device_inline bool transform_uniform_scale(const Transform& tfm, float& scale)
+{
+	/* the epsilon here is quite arbitrary, but this function is only used for
+	   surface area and bump, where we except it to not be so sensitive */
+	Transform ttfm = transform_transpose(tfm);
+	float eps = 1e-7f; 
+	
+	float sx = len(float4_to_float3(tfm.x));
+	float sy = len(float4_to_float3(tfm.y));
+	float sz = len(float4_to_float3(tfm.z));
+	float stx = len(float4_to_float3(ttfm.x));
+	float sty = len(float4_to_float3(ttfm.y));
+	float stz = len(float4_to_float3(ttfm.z));
+	
+	if(fabsf(sx - sy) < eps && fabsf(sx - sz) < eps &&
+	   fabsf(sx - stx) < eps && fabsf(sx - sty) < eps &&
+	   fabsf(sx - stz) < eps) {
+		scale = sx;
+		return true;
+	}
+   
+   return false;
+}
+
 #endif
 
 CCL_NAMESPACE_END




More information about the Bf-blender-cvs mailing list