[Bf-blender-cvs] [3c5d1076f4f] cycles_embree: Cycles: Some more cleanup/commenting for Embree integration.

Stefan Werner noreply at git.blender.org
Mon Sep 10 13:52:35 CEST 2018


Commit: 3c5d1076f4f60eebd4d1d53e7019fc2b69a83d1d
Author: Stefan Werner
Date:   Mon Sep 10 13:52:33 2018 +0200
Branches: cycles_embree
https://developer.blender.org/rB3c5d1076f4f60eebd4d1d53e7019fc2b69a83d1d

Cycles: Some more cleanup/commenting for Embree integration.

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

M	intern/cycles/bvh/bvh_embree.cpp

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

diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp
index d0dac07c7e2..2122d09ec7e 100644
--- a/intern/cycles/bvh/bvh_embree.cpp
+++ b/intern/cycles/bvh/bvh_embree.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017, Blender Foundation.
+ * Copyright 2018, Blender Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,6 +14,24 @@
  * limitations under the License.
  */
 
+/* This class implemens a ray accelerator for Cycles using Intel's Embree library.
+ * It supports triangles, curves, object and deformation blur and instancing.
+ * Not supported are thick line segments, those have no native equivalent in Embree.
+ * They could be implemented using Embree's thick curves, at the expense of wasted memory.
+ * User defined intersections for Embree could also be an option, but since Embree only uses aligned BVHs
+ * for user geometry, this would come with reduced performance and/or higher memory usage.
+ *
+ * Since Embree allows object to be either curves or triangles but not both, Cycles object IDs are maapped
+ * to Embree IDs by multiplying by two and adding one for curves.
+ *
+ * This implementation shares RTCDevices between Cycles instances. Eventually each instance should get
+ * a separate RTCDevice to correctly keep track of memory usage.
+ *
+ * Vertex and index buffers are duplicated between Cycles device arrays and Embree. These could be merged,
+ * which would requrie changes to intersection refinement, shader setup, mesh light sampling and a few
+ * other places in Cycles where direct access to vertex data is required.
+ */
+
 #ifdef WITH_EMBREE
 
 #include <pmmintrin.h>
@@ -46,6 +64,7 @@ CCL_NAMESPACE_BEGIN
 void rtc_filter_func(const RTCFilterFunctionNArguments *args);
 void rtc_filter_func(const RTCFilterFunctionNArguments *args)
 {
+	/* Current implementation in Cycles assumes only single-ray intersection queries. */
 	assert(args->N == 1);
 
 	const RTCRay *ray = (RTCRay*)args->ray;
@@ -83,120 +102,122 @@ void rtc_filter_occluded_func(const RTCFilterFunctionNArguments* args)
 		}
 	}
 
-	if(ctx->type == CCLIntersectContext::RAY_SHADOW_ALL) {
-		/* Append the intersection to the end of the array. */
-		if(ctx->num_hits < ctx->max_hits) {
-			Intersection current_isect;
-			kernel_embree_convert_hit(kg, ray, hit, &current_isect);
-			for(size_t i = 0; i < ctx->max_hits; ++i) {
-				if(current_isect.object == ctx->isect_s[i].object &&
-				   current_isect.prim == ctx->isect_s[i].prim &&
-				   current_isect.t == ctx->isect_s[i].t) {
-					/* This intersection was already recorded, skip it. */
+	switch(ctx->type) {
+		case CCLIntersectContext::RAY_SHADOW_ALL: {
+			/* Append the intersection to the end of the array. */
+			if(ctx->num_hits < ctx->max_hits) {
+				Intersection current_isect;
+				kernel_embree_convert_hit(kg, ray, hit, &current_isect);
+				for(size_t i = 0; i < ctx->max_hits; ++i) {
+					if(current_isect.object == ctx->isect_s[i].object &&
+					   current_isect.prim == ctx->isect_s[i].prim &&
+					   current_isect.t == ctx->isect_s[i].t) {
+						/* This intersection was already recorded, skip it. */
+						*args->valid = 0;
+						break;
+					}
+				}
+				Intersection *isect = &ctx->isect_s[ctx->num_hits];
+				ctx->num_hits++;
+				*isect = current_isect;
+				int prim = kernel_tex_fetch(__prim_index, isect->prim);
+				int shader = 0;
+				if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
+					shader = kernel_tex_fetch(__tri_shader, prim);
+				}
+				else {
+					float4 str = kernel_tex_fetch(__curves, prim);
+					shader = __float_as_int(str.z);
+				}
+				int flag = kernel_tex_fetch(__shaders, shader & SHADER_MASK).flags;
+				/* If no transparent shadows, all light is blocked. */
+				if(flag & (SD_HAS_TRANSPARENT_SHADOW)) {
+					/* This tells Embree to continue tracing. */
 					*args->valid = 0;
-					return;
 				}
 			}
-			Intersection *isect = &ctx->isect_s[ctx->num_hits];
-			ctx->num_hits++;
-			*isect = current_isect;
-			int prim = kernel_tex_fetch(__prim_index, isect->prim);
-			int shader = 0;
-			if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
-				shader = kernel_tex_fetch(__tri_shader, prim);
-			}
 			else {
-				float4 str = kernel_tex_fetch(__curves, prim);
-				shader = __float_as_int(str.z);
+				/* Increase the number of hits beyond ray.max_hits
+				 * so that the caller can detect this as opaque. */
+				ctx->num_hits++;
 			}
-			int flag = kernel_tex_fetch(__shaders, shader & SHADER_MASK).flags;
-			/* If no transparent shadows, all light is blocked. */
-			if(flag & (SD_HAS_TRANSPARENT_SHADOW)) {
-				/* This tells Embree to continue tracing. */
-				*args->valid = 0;
-			}
-		}
-		else {
-			/* Increase the number of hits beyond ray.max_hits
-			 * so that the caller can detect this as opaque. */
-			ctx->num_hits++;
-		}
-		return;
-	}
-	else if(ctx->type == CCLIntersectContext::RAY_SSS) {
-		/* No intersection information requested, just return a hit. */
-		if(ctx->max_hits == 0) {
-			return;
+			break;
 		}
-
-		/* See triangle_intersect_subsurface() for the native equivalent. */
-		for(int i = min(ctx->max_hits, ctx->ss_isect->num_hits) - 1; i >= 0; --i) {
-			if(ctx->ss_isect->hits[i].t == ray->tfar) {
-				/* This tells Embree to continue tracing. */
-				*args->valid = 0;
-				return;
+		case CCLIntersectContext::RAY_SSS: {
+			/* No intersection information requested, just return a hit. */
+			if(ctx->max_hits == 0) {
+				break;
 			}
-		}
 
-		ctx->ss_isect->num_hits++;
-		int hit_idx;
+			/* See triangle_intersect_subsurface() for the native equivalent. */
+			for(int i = min(ctx->max_hits, ctx->ss_isect->num_hits) - 1; i >= 0; --i) {
+				if(ctx->ss_isect->hits[i].t == ray->tfar) {
+					/* This tells Embree to continue tracing. */
+					*args->valid = 0;
+					break;
+				}
+			}
 
-		if(ctx->ss_isect->num_hits <= ctx->max_hits) {
-			hit_idx = ctx->ss_isect->num_hits - 1;
-		}
-		else {
-			/* reservoir sampling: if we are at the maximum number of
-			 * hits, randomly replace element or skip it */
-			hit_idx = lcg_step_uint(ctx->lcg_state) % ctx->ss_isect->num_hits;
+			ctx->ss_isect->num_hits++;
+			int hit_idx;
 
-			if(hit_idx >= ctx->max_hits) {
-				/* This tells Embree to continue tracing. */
-				*args->valid = 0;
-				return;
+			if(ctx->ss_isect->num_hits <= ctx->max_hits) {
+				hit_idx = ctx->ss_isect->num_hits - 1;
 			}
-		}
-		/* record intersection */
-		kernel_embree_convert_local_hit(kg, ray, hit, &ctx->ss_isect->hits[hit_idx], ctx->sss_object_id);
-		ctx->ss_isect->Ng[hit_idx].x = hit->Ng_x;
-		ctx->ss_isect->Ng[hit_idx].y = hit->Ng_y;
-		ctx->ss_isect->Ng[hit_idx].z = hit->Ng_z;
-		ctx->ss_isect->Ng[hit_idx] = normalize(ctx->ss_isect->Ng[hit_idx]);
-		/* this tells Embree to continue tracing */
-		*args->valid = 0;
-		return;
-	}
-	else if(ctx->type == CCLIntersectContext::RAY_VOLUME_ALL) {
-		/* Append the intersection to the end of the array. */
-		if(ctx->num_hits < ctx->max_hits) {
-			Intersection current_isect;
-			kernel_embree_convert_hit(kg, ray, hit, &current_isect);
-			for(size_t i = 0; i < ctx->max_hits; ++i) {
-				if(current_isect.object == ctx->isect_s[i].object &&
-				   current_isect.prim == ctx->isect_s[i].prim &&
-				   current_isect.t == ctx->isect_s[i].t) {
-					/* This intersection was already recorded, skip it. */
+			else {
+				/* reservoir sampling: if we are at the maximum number of
+				 * hits, randomly replace element or skip it */
+				hit_idx = lcg_step_uint(ctx->lcg_state) % ctx->ss_isect->num_hits;
+
+				if(hit_idx >= ctx->max_hits) {
+					/* This tells Embree to continue tracing. */
 					*args->valid = 0;
-					return;
+					break;
 				}
 			}
-			Intersection *isect = &ctx->isect_s[ctx->num_hits];
-			ctx->num_hits++;
-			*isect = current_isect;
-			/* Only primitives from volume object. */
-			uint tri_object = (isect->object == OBJECT_NONE) ?
-			                   kernel_tex_fetch(__prim_object, isect->prim) : isect->object;
-			int object_flag = kernel_tex_fetch(__object_flag, tri_object);
-			if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
-				ctx->num_hits--;
-			}
-			/* This tells Embree to continue tracing. */
+			/* record intersection */
+			kernel_embree_convert_local_hit(kg, ray, hit, &ctx->ss_isect->hits[hit_idx], ctx->sss_object_id);
+			ctx->ss_isect->Ng[hit_idx].x = hit->Ng_x;
+			ctx->ss_isect->Ng[hit_idx].y = hit->Ng_y;
+			ctx->ss_isect->Ng[hit_idx].z = hit->Ng_z;
+			ctx->ss_isect->Ng[hit_idx] = normalize(ctx->ss_isect->Ng[hit_idx]);
+			/* this tells Embree to continue tracing */
 			*args->valid = 0;
-			return;
+			break;
+		}
+		case CCLIntersectContext::RAY_VOLUME_ALL: {
+			/* Append the intersection to the end of the array. */
+			if(ctx->num_hits < ctx->max_hits) {
+				Intersection current_isect;
+				kernel_embree_convert_hit(kg, ray, hit, &current_isect);
+				for(size_t i = 0; i < ctx->max_hits; ++i) {
+					if(current_isect.object == ctx->isect_s[i].object &&
+					   current_isect.prim == ctx->isect_s[i].prim &&
+					   current_isect.t == ctx->isect_s[i].t) {
+						/* This intersection was already recorded, skip it. */
+						*args->valid = 0;
+						break;
+					}
+				}
+				Intersection *isect = &ctx->isect_s[ctx->num_hits];
+				ctx->num_hits++;
+				*isect = current_isect;
+				/* Only primitives from volume object. */
+				uint tri_object = (isect->object == OBJECT_NONE) ?
+								   kernel_tex_fetch(__prim_object, isect->prim) : isect->object;
+				int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+				if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+					ctx->num_hits--;
+				}
+				/* This tells Embree to continue tracing. */
+				*args->valid = 0;
+				break;
+			}
 		}
-		return;
+		case CCLIntersectContext::RAY_REGULAR:
+			/* nothing to do here. */
+			break;
 	}
-
-	return;
 }
 
 static size_t unaccounted_mem = 0;
@@ -605,11 +626,11 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh
 		if(use_curves) {
 			rtc_tangents = (float4*)rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_TANGENT, t,
 																RTC_FORMAT_FLOAT4

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list