diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-06-10 11:14:05 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-07-07 18:25:48 +0300 |
commit | 1eacbf47e3cdf009b27972e1c617fb1ff56c0aad (patch) | |
tree | 07330ae832445574bd084e71afe4fdfcfc47fddf /intern/cycles/kernel/geom | |
parent | a19da5c10d2edac01070760438ae9bb1d89f1439 (diff) |
Cycles: Support visibility check for inner nodes of QBVH
It was initially unsupported because initial idea of checking visibility
of all children was slowing scenes down a lot. Now the idea has changed
and we only perform visibility check of current node. This avoids huge
slowdown (from tests here it seems to be withing 1-2%, but more tests
would never hurt) and gives nice speedup of ray traversal for complex
scenes which utilized ray visibility.
Here's timing of koro.blend:
Without visibility check With visibility check
Original file 4min 20sec 4min 23sec
Camera rays only 1min 43 sec 55sec
Unfortunately, this doesn't come for free and requires extra data in
BVH node, which increases memory usage of BVH nodes by 15%. This we
can solve with some future trickery of avoiding __tri_storage created
for curve segments.
Diffstat (limited to 'intern/cycles/kernel/geom')
-rw-r--r-- | intern/cycles/kernel/geom/geom.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/geom/geom_qbvh.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/geom/geom_qbvh_shadow.h | 14 | ||||
-rw-r--r-- | intern/cycles/kernel/geom/geom_qbvh_subsurface.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/geom/geom_qbvh_traversal.h | 15 | ||||
-rw-r--r-- | intern/cycles/kernel/geom/geom_qbvh_volume.h | 13 | ||||
-rw-r--r-- | intern/cycles/kernel/geom/geom_qbvh_volume_all.h | 13 |
7 files changed, 54 insertions, 10 deletions
diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h index 2949f66c2ae..26e0af99bbc 100644 --- a/intern/cycles/kernel/geom/geom.h +++ b/intern/cycles/kernel/geom/geom.h @@ -23,7 +23,7 @@ #define BVH_QSTACK_SIZE 384 #define BVH_NODE_SIZE 4 #define BVH_NODE_LEAF_SIZE 1 -#define BVH_QNODE_SIZE 7 +#define BVH_QNODE_SIZE 8 #define BVH_QNODE_LEAF_SIZE 1 #define TRI_NODE_SIZE 3 diff --git a/intern/cycles/kernel/geom/geom_qbvh.h b/intern/cycles/kernel/geom/geom_qbvh.h index 2a2d7822eee..118bceb4bec 100644 --- a/intern/cycles/kernel/geom/geom_qbvh.h +++ b/intern/cycles/kernel/geom/geom_qbvh.h @@ -69,7 +69,7 @@ ccl_device_inline int qbvh_node_intersect(KernelGlobals *__restrict kg, const int nodeAddr, ssef *__restrict dist) { - const int offset = nodeAddr*BVH_QNODE_SIZE; + const int offset = nodeAddr*BVH_QNODE_SIZE + 1; #ifdef __KERNEL_AVX2__ const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x), idir.x, org_idir.x); const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y), idir.y, org_idir.y); @@ -120,7 +120,7 @@ ccl_device_inline int qbvh_node_intersect_robust(KernelGlobals *__restrict kg, const float difl, ssef *__restrict dist) { - const int offset = nodeAddr*BVH_QNODE_SIZE; + const int offset = nodeAddr*BVH_QNODE_SIZE + 1; #ifdef __KERNEL_AVX2__ const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x), idir.x, P_idir.x); const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y), idir.y, P_idir.y); diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h index edb5b5c78c3..01babba0215 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h @@ -97,6 +97,17 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, do { /* Traverse internal nodes. */ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { + float4 inodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+0); + +#ifdef __VISIBILITY_FLAG__ + if((__float_as_uint(inodes.x) & PATH_RAY_SHADOW) == 0) { + /* Pop. */ + nodeAddr = traversalStack[stackPtr].addr; + --stackPtr; + continue; + } +#endif + ssef dist; int traverseChild = qbvh_node_intersect(kg, tnear, @@ -113,7 +124,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &dist); if(traverseChild != 0) { - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, + nodeAddr*BVH_QNODE_SIZE+7); /* One child is hit, continue with that child. */ int r = __bscf(traverseChild); diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h index 84512a8783c..bc717a0747e 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h @@ -123,7 +123,8 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &dist); if(traverseChild != 0) { - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, + nodeAddr*BVH_QNODE_SIZE+7); /* One child is hit, continue with that child. */ int r = __bscf(traverseChild); diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h index 738d08ac6fc..098881a6d7e 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h @@ -106,7 +106,14 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, do { /* Traverse internal nodes. */ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { - if(UNLIKELY(nodeDist > isect->t)) { + float4 inodes = kernel_tex_fetch(__bvh_nodes, + nodeAddr*BVH_QNODE_SIZE+0); + + if(UNLIKELY(nodeDist > isect->t) +#ifdef __VISIBILITY_FLAG__ + || (__float_as_uint(inodes.x) & visibility) == 0) +#endif + { /* Pop. */ nodeAddr = traversalStack[stackPtr].addr; nodeDist = traversalStack[stackPtr].dist; @@ -160,7 +167,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, } if(traverseChild != 0) { - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, + nodeAddr*BVH_QNODE_SIZE+7); /* One child is hit, continue with that child. */ int r = __bscf(traverseChild); @@ -261,7 +269,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE); #ifdef __VISIBILITY_FLAG__ - if(UNLIKELY((nodeDist > isect->t) || ((__float_as_uint(leaf.z) & visibility) == 0))) + if(UNLIKELY((nodeDist > isect->t) || + ((__float_as_uint(leaf.z) & visibility) == 0))) #else if(UNLIKELY((nodeDist > isect->t))) #endif diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h index ab2e530dd20..2aae90380c1 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_volume.h +++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h @@ -93,6 +93,16 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, do { /* Traverse internal nodes. */ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { +#ifdef __VISIBILITY_FLAG__ + float4 inodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+0); + if((__float_as_uint(inodes.x) & visibility) == 0) { + /* Pop. */ + nodeAddr = traversalStack[stackPtr].addr; + --stackPtr; + continue; + } +#endif + ssef dist; int traverseChild = qbvh_node_intersect(kg, tnear, @@ -109,7 +119,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &dist); if(traverseChild != 0) { - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, + nodeAddr*BVH_QNODE_SIZE+7); /* One child is hit, continue with that child. */ int r = __bscf(traverseChild); diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume_all.h b/intern/cycles/kernel/geom/geom_qbvh_volume_all.h index 5546471b0e3..e6b668eb758 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_volume_all.h +++ b/intern/cycles/kernel/geom/geom_qbvh_volume_all.h @@ -97,6 +97,16 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, do { /* Traverse internal nodes. */ while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { +#ifdef __VISIBILITY_FLAG__ + float4 inodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+0); + if((__float_as_uint(inodes.x) & visibility) == 0) { + /* Pop. */ + nodeAddr = traversalStack[stackPtr].addr; + --stackPtr; + continue; + } +#endif + ssef dist; int traverseChild = qbvh_node_intersect(kg, tnear, @@ -113,7 +123,8 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, &dist); if(traverseChild != 0) { - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, + nodeAddr*BVH_QNODE_SIZE+7); /* One child is hit, continue with that child. */ int r = __bscf(traverseChild); |