Code refactor: rename subsurface to local traversal, for reuse.

This commit is contained in:
Brecht Van Lommel 2017-10-30 20:25:08 +01:00
parent d0af56fe3b
commit f79f386731
17 changed files with 231 additions and 187 deletions

View File

@ -139,6 +139,9 @@ public:
/* Denoising features. */
bool use_denoising;
/* Use raytracing in shaders. */
bool use_shader_raytrace;
DeviceRequestedFeatures()
{
/* TODO(sergey): Find more meaningful defaults. */
@ -158,6 +161,7 @@ public:
use_shadow_tricks = false;
use_principled = false;
use_denoising = false;
use_shader_raytrace = false;
}
bool modified(const DeviceRequestedFeatures& requested_features)
@ -177,7 +181,8 @@ public:
use_transparent == requested_features.use_transparent &&
use_shadow_tricks == requested_features.use_shadow_tricks &&
use_principled == requested_features.use_principled &&
use_denoising == requested_features.use_denoising);
use_denoising == requested_features.use_denoising &&
use_shader_raytrace == requested_features.use_shader_raytrace);
}
/* Convert the requested features structure to a build options,
@ -230,6 +235,9 @@ public:
if(!use_denoising) {
build_options += " -D__NO_DENOISING__";
}
if(!use_shader_raytrace) {
build_options += " -D__NO_SHADER_RAYTRACE__";
}
return build_options;
}
};

View File

@ -65,14 +65,14 @@ set(SRC_BVH_HEADERS
bvh/bvh.h
bvh/bvh_nodes.h
bvh/bvh_shadow_all.h
bvh/bvh_subsurface.h
bvh/bvh_local.h
bvh/bvh_traversal.h
bvh/bvh_types.h
bvh/bvh_volume.h
bvh/bvh_volume_all.h
bvh/qbvh_nodes.h
bvh/qbvh_shadow_all.h
bvh/qbvh_subsurface.h
bvh/qbvh_local.h
bvh/qbvh_traversal.h
bvh/qbvh_volume.h
bvh/qbvh_volume_all.h

View File

@ -68,17 +68,17 @@ CCL_NAMESPACE_BEGIN
/* Subsurface scattering BVH traversal */
#if defined(__SUBSURFACE__)
# define BVH_FUNCTION_NAME bvh_intersect_subsurface
#if defined(__BVH_LOCAL__)
# define BVH_FUNCTION_NAME bvh_intersect_local
# define BVH_FUNCTION_FEATURES BVH_HAIR
# include "kernel/bvh/bvh_subsurface.h"
# include "kernel/bvh/bvh_local.h"
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
# define BVH_FUNCTION_NAME bvh_intersect_local_motion
# define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
# include "kernel/bvh/bvh_subsurface.h"
# include "kernel/bvh/bvh_local.h"
# endif
#endif /* __SUBSURFACE__ */
#endif /* __BVH_LOCAL__ */
/* Volume BVH traversal */
@ -201,31 +201,31 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
#endif /* __KERNEL_CPU__ */
}
#ifdef __SUBSURFACE__
#ifdef __BVH_LOCAL__
/* Note: ray is passed by value to work around a possible CUDA compiler bug. */
ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
const Ray ray,
SubsurfaceIntersection *ss_isect,
int subsurface_object,
uint *lcg_state,
int max_hits)
ccl_device_intersect void scene_intersect_local(KernelGlobals *kg,
const Ray ray,
LocalIntersection *local_isect,
int local_object,
uint *lcg_state,
int max_hits)
{
#ifdef __OBJECT_MOTION__
if(kernel_data.bvh.have_motion) {
return bvh_intersect_subsurface_motion(kg,
&ray,
ss_isect,
subsurface_object,
lcg_state,
max_hits);
return bvh_intersect_local_motion(kg,
&ray,
local_isect,
local_object,
lcg_state,
max_hits);
}
#endif /* __OBJECT_MOTION__ */
return bvh_intersect_subsurface(kg,
&ray,
ss_isect,
subsurface_object,
lcg_state,
max_hits);
return bvh_intersect_local(kg,
&ray,
local_isect,
local_object,
lcg_state,
max_hits);
}
#endif

View File

@ -18,7 +18,7 @@
*/
#ifdef __QBVH__
# include "kernel/bvh/qbvh_subsurface.h"
# include "kernel/bvh/qbvh_local.h"
#endif
#if BVH_FEATURE(BVH_HAIR)
@ -27,9 +27,10 @@
# define NODE_INTERSECT bvh_aligned_node_intersect
#endif
/* This is a template BVH traversal function for subsurface scattering, where
* various features can be enabled/disabled. This way we can compile optimized
* versions for each case without new features slowing things down.
/* This is a template BVH traversal function for finding local intersections
* around the shading point, for subsurface scattering and bevel. We disable
* various features for performance, and for instanced objects avoid traversing
* other parts of the scene.
*
* BVH_MOTION: motion blur rendering
*
@ -42,8 +43,8 @@ ccl_device_inline
#endif
void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
const Ray *ray,
SubsurfaceIntersection *ss_isect,
int subsurface_object,
LocalIntersection *local_isect,
int local_object,
uint *lcg_state,
int max_hits)
{
@ -60,7 +61,7 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* traversal variables in registers */
int stack_ptr = 0;
int node_addr = kernel_tex_fetch(__object_node, subsurface_object);
int node_addr = kernel_tex_fetch(__object_node, local_object);
/* ray parameters in registers */
float3 P = ray->P;
@ -69,14 +70,14 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
int object = OBJECT_NONE;
float isect_t = ray->t;
ss_isect->num_hits = 0;
local_isect->num_hits = 0;
const int object_flag = kernel_tex_fetch(__object_flag, subsurface_object);
const int object_flag = kernel_tex_fetch(__object_flag, local_object);
if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
#if BVH_FEATURE(BVH_MOTION)
Transform ob_itfm;
isect_t = bvh_instance_motion_push(kg,
subsurface_object,
local_object,
ray,
&P,
&dir,
@ -84,9 +85,9 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
isect_t,
&ob_itfm);
#else
isect_t = bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, isect_t);
isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
#endif
object = subsurface_object;
object = local_object;
}
#if defined(__KERNEL_SSE2__)
@ -193,15 +194,16 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* intersect ray against primitive */
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
triangle_intersect_subsurface(kg,
ss_isect,
P,
dir,
object,
prim_addr,
isect_t,
lcg_state,
max_hits);
triangle_intersect_local(kg,
local_isect,
P,
dir,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits);
}
break;
}
@ -210,16 +212,17 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* intersect ray against primitive */
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
motion_triangle_intersect_subsurface(kg,
ss_isect,
P,
dir,
ray->time,
object,
prim_addr,
isect_t,
lcg_state,
max_hits);
motion_triangle_intersect_local(kg,
local_isect,
P,
dir,
ray->time,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits);
}
break;
}
@ -235,8 +238,8 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
const Ray *ray,
SubsurfaceIntersection *ss_isect,
int subsurface_object,
LocalIntersection *local_isect,
int local_object,
uint *lcg_state,
int max_hits)
{
@ -244,8 +247,8 @@ ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
if(kernel_data.bvh.use_qbvh) {
return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
ray,
ss_isect,
subsurface_object,
local_isect,
local_object,
lcg_state,
max_hits);
}
@ -255,8 +258,8 @@ ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
kernel_assert(kernel_data.bvh.use_qbvh == false);
return BVH_FUNCTION_FULL_NAME(BVH)(kg,
ray,
ss_isect,
subsurface_object,
local_isect,
local_object,
lcg_state,
max_hits);
}

View File

@ -14,9 +14,10 @@
* limitations under the License.
*/
/* This is a template BVH traversal function for subsurface scattering, where
* various features can be enabled/disabled. This way we can compile optimized
* versions for each case without new features slowing things down.
/* This is a template BVH traversal function for finding local intersections
* around the shading point, for subsurface scattering and bevel. We disable
* various features for performance, and for instanced objects avoid traversing
* other parts of the scene.
*
* BVH_MOTION: motion blur rendering
*
@ -30,8 +31,8 @@
ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
SubsurfaceIntersection *ss_isect,
int subsurface_object,
LocalIntersection *local_isect,
int local_object,
uint *lcg_state,
int max_hits)
{
@ -49,7 +50,7 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Traversal variables in registers. */
int stack_ptr = 0;
int node_addr = kernel_tex_fetch(__object_node, subsurface_object);
int node_addr = kernel_tex_fetch(__object_node, local_object);
/* Ray parameters in registers. */
float3 P = ray->P;
@ -58,14 +59,14 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
int object = OBJECT_NONE;
float isect_t = ray->t;
ss_isect->num_hits = 0;
local_isect->num_hits = 0;
const int object_flag = kernel_tex_fetch(__object_flag, subsurface_object);
const int object_flag = kernel_tex_fetch(__object_flag, local_object);
if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
#if BVH_FEATURE(BVH_MOTION)
Transform ob_itfm;
isect_t = bvh_instance_motion_push(kg,
subsurface_object,
local_object,
ray,
&P,
&dir,
@ -73,9 +74,9 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
isect_t,
&ob_itfm);
#else
isect_t = bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, isect_t);
isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
#endif
object = subsurface_object;
object = local_object;
}
#ifndef __KERNEL_SSE41__
@ -249,15 +250,16 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Intersect ray against primitive, */
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
triangle_intersect_subsurface(kg,
ss_isect,
P,
dir,
object,
prim_addr,
isect_t,
lcg_state,
max_hits);
triangle_intersect_local(kg,
local_isect,
P,
dir,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits);
}
break;
}
@ -266,16 +268,17 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Intersect ray against primitive. */
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
motion_triangle_intersect_subsurface(kg,
ss_isect,
P,
dir,
ray->time,
object,
prim_addr,
isect_t,
lcg_state,
max_hits);
motion_triangle_intersect_local(kg,
local_isect,
P,
dir,
ray->time,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits);
}
break;
}

View File

@ -97,17 +97,17 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg,
* for instancing.
*/
#ifdef __SUBSURFACE__
#ifdef __BVH_LOCAL__
# if defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))
ccl_device_noinline
# else
ccl_device_inline
# endif
float3 motion_triangle_refine_subsurface(KernelGlobals *kg,
ShaderData *sd,
const Intersection *isect,
const Ray *ray,
float3 verts[3])
float3 motion_triangle_refine_local(KernelGlobals *kg,
ShaderData *sd,
const Intersection *isect,
const Ray *ray,
float3 verts[3])
{
float3 P = ray->P;
float3 D = ray->D;
@ -159,7 +159,7 @@ float3 motion_triangle_refine_subsurface(KernelGlobals *kg,
return P + D*t;
# endif /* __INTERSECTION_REFINE__ */
}
#endif /* __SUBSURFACE__ */
#endif /* __BVH_LOCAL__ */
/* Ray intersection. We simply compute the vertex positions at the given ray
@ -215,31 +215,37 @@ ccl_device_inline bool motion_triangle_intersect(
return false;
}
/* Special ray intersection routines for subsurface scattering. In that case we
/* Special ray intersection routines for local intersections. In that case we
* only want to intersect with primitives in the same object, and if case of
* multiple hits we pick a single random primitive as the intersection point.
*/
#ifdef __SUBSURFACE__
ccl_device_inline void motion_triangle_intersect_subsurface(
#ifdef __BVH_LOCAL__
ccl_device_inline void motion_triangle_intersect_local(
KernelGlobals *kg,
SubsurfaceIntersection *ss_isect,
LocalIntersection *local_isect,
float3 P,
float3 dir,
float time,
int object,
int local_object,
int prim_addr,
float tmax,
uint *lcg_state,
int max_hits)
{
/* Only intersect with matching object, for instanced objects we
* already know we are only intersecting the right object. */
if(object == OBJECT_NONE) {
if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
return;
}
}
/* Primitive index for vertex location lookup. */
int prim = kernel_tex_fetch(__prim_index, prim_addr);
int fobject = (object == OBJECT_NONE)
? kernel_tex_fetch(__prim_object, prim_addr)
: object;
/* Get vertex locations for intersection. */
float3 verts[3];
motion_triangle_vertices(kg, fobject, prim, time, verts);
motion_triangle_vertices(kg, local_object, prim, time, verts);
/* Ray-triangle intersection, unoptimized. */
float t, u, v;
if(ray_triangle_intersect(P,
@ -252,27 +258,27 @@ ccl_device_inline void motion_triangle_intersect_subsurface(
#endif
&u, &v, &t))
{
for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
if(ss_isect->hits[i].t == t) {
for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
if(local_isect->hits[i].t == t) {
return;
}
}
ss_isect->num_hits++;
local_isect->num_hits++;
int hit;
if(ss_isect->num_hits <= max_hits) {
hit = ss_isect->num_hits - 1;
if(local_isect->num_hits <= max_hits) {
hit = local_isect->num_hits - 1;
}
else {
/* Reservoir sampling: if we are at the maximum number of
* hits, randomly replace element or skip it.
*/
hit = lcg_step_uint(lcg_state) % ss_isect->num_hits;
hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
if(hit >= max_hits)
return;
}
/* Record intersection. */
Intersection *isect = &ss_isect->hits[hit];
Intersection *isect = &local_isect->hits[hit];
isect->t = t;
isect->u = u;
isect->v = v;
@ -280,10 +286,10 @@ ccl_device_inline void motion_triangle_intersect_subsurface(
isect->object = object;
isect->type = PRIMITIVE_MOTION_TRIANGLE;
/* Record geometric normal. */
ss_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
local_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
verts[2] - verts[0]));
}
}
#endif /* __SUBSURFACE__ */
#endif /* __BVH_LOCAL__ */
CCL_NAMESPACE_END

View File

@ -36,7 +36,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
ShaderData *sd, const
Intersection *isect,
const Ray *ray,
bool subsurface)
bool is_local)
{
/* Get shader. */
sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
@ -66,16 +66,16 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
verts[1] = (1.0f - t)*verts[1] + t*next_verts[1];
verts[2] = (1.0f - t)*verts[2] + t*next_verts[2];
/* Compute refined position. */
#ifdef __SUBSURFACE__
if(subsurface) {
sd->P = motion_triangle_refine_subsurface(kg,
sd,
isect,
ray,
verts);
#ifdef __BVH_LOCAL__
if(is_local) {
sd->P = motion_triangle_refine_local(kg,
sd,
isect,
ray,
verts);
}
else
#endif /* __SUBSURFACE__*/
#endif /* __BVH_LOCAL__*/
{
sd->P = motion_triangle_refine(kg, sd, isect, ray, verts);
}

View File

@ -70,23 +70,32 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
return false;
}
/* Special ray intersection routines for subsurface scattering. In that case we
/* Special ray intersection routines for local intersection. In that case we
* only want to intersect with primitives in the same object, and if case of
* multiple hits we pick a single random primitive as the intersection point.
*/
#ifdef __SUBSURFACE__
ccl_device_inline void triangle_intersect_subsurface(
#ifdef __BVH_LOCAL__
ccl_device_inline void triangle_intersect_local(
KernelGlobals *kg,
SubsurfaceIntersection *ss_isect,
LocalIntersection *local_isect,
float3 P,
float3 dir,
int object,
int local_object,
int prim_addr,
float tmax,
uint *lcg_state,
int max_hits)
{
/* Only intersect with matching object, for instanced objects we
* already know we are only intersecting the right object. */
if(object == OBJECT_NONE) {
if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
return;
}
}
const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex];
@ -109,29 +118,29 @@ ccl_device_inline void triangle_intersect_subsurface(
return;
}
for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
if(ss_isect->hits[i].t == t) {
for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
if(local_isect->hits[i].t == t) {
return;
}
}
ss_isect->num_hits++;
local_isect->num_hits++;
int hit;
if(ss_isect->num_hits <= max_hits) {
hit = ss_isect->num_hits - 1;
if(local_isect->num_hits <= max_hits) {
hit = local_isect->num_hits - 1;
}
else {
/* reservoir sampling: if we are at the maximum number of
* hits, randomly replace element or skip it */
hit = lcg_step_uint(lcg_state) % ss_isect->num_hits;
hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
if(hit >= max_hits)
return;
}
/* record intersection */
Intersection *isect = &ss_isect->hits[hit];
Intersection *isect = &local_isect->hits[hit];
isect->prim = prim_addr;
isect->object = object;
isect->type = PRIMITIVE_TRIANGLE;
@ -145,9 +154,9 @@ ccl_device_inline void triangle_intersect_subsurface(
tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+1)),
tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2));
#endif
ss_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
local_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
}
#endif /* __SUBSURFACE__ */
#endif /* __BVH_LOCAL__ */
/* Refine triangle intersection to more precise hit point. For rays that travel
* far the precision is often not so good, this reintersects the primitive from
@ -226,10 +235,10 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
/* Same as above, except that isect->t is assumed to be in object space for
* instancing.
*/
ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
ShaderData *sd,
const Intersection *isect,
const Ray *ray)
ccl_device_inline float3 triangle_refine_local(KernelGlobals *kg,
ShaderData *sd,
const Intersection *isect,
const Ray *ray)
{
float3 P = ray->P;
float3 D = ray->D;

View File

@ -340,7 +340,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
/* do subsurface scatter step with copy of shader data, this will
* replace the BSSRDF with a diffuse BSDF closure */
for(int j = 0; j < num_samples; j++) {
SubsurfaceIntersection ss_isect;
LocalIntersection ss_isect;
float bssrdf_u, bssrdf_v;
path_branched_rng_2D(kg, bssrdf_rng_hash, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
int num_hits = subsurface_scatter_multi_intersect(kg,

View File

@ -47,7 +47,7 @@ bool kernel_path_subsurface_scatter(
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
SubsurfaceIntersection ss_isect;
LocalIntersection ss_isect;
int num_hits = subsurface_scatter_multi_intersect(kg,
&ss_isect,
sd,

View File

@ -181,7 +181,7 @@ void shader_setup_from_subsurface(
sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
/* static triangle */
sd->P = triangle_refine_subsurface(kg, sd, isect, ray);
sd->P = triangle_refine_local(kg, sd, isect, ray);
sd->Ng = Ng;
sd->N = Ng;

View File

@ -175,7 +175,7 @@ ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
*/
ccl_device_inline int subsurface_scatter_multi_intersect(
KernelGlobals *kg,
SubsurfaceIntersection *ss_isect,
LocalIntersection *ss_isect,
ShaderData *sd,
const ShaderClosure *sc,
uint *lcg_state,
@ -240,22 +240,22 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
/* intersect with the same object. if multiple intersections are found it
* will use at most BSSRDF_MAX_HITS hits, a random subset of all hits */
scene_intersect_subsurface(kg,
*ray,
ss_isect,
sd->object,
lcg_state,
BSSRDF_MAX_HITS);
scene_intersect_local(kg,
*ray,
ss_isect,
sd->object,
lcg_state,
BSSRDF_MAX_HITS);
int num_eval_hits = min(ss_isect->num_hits, BSSRDF_MAX_HITS);
for(int hit = 0; hit < num_eval_hits; hit++) {
/* Quickly retrieve P and Ng without setting up ShaderData. */
float3 hit_P;
if(sd->type & PRIMITIVE_TRIANGLE) {
hit_P = triangle_refine_subsurface(kg,
sd,
&ss_isect->hits[hit],
ray);
hit_P = triangle_refine_local(kg,
sd,
&ss_isect->hits[hit],
ray);
}
#ifdef __OBJECT_MOTION__
else if(sd->type & PRIMITIVE_MOTION_TRIANGLE) {
@ -266,11 +266,11 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
kernel_tex_fetch(__prim_index, ss_isect->hits[hit].prim),
sd->time,
verts);
hit_P = motion_triangle_refine_subsurface(kg,
sd,
&ss_isect->hits[hit],
ray,
verts);
hit_P = motion_triangle_refine_local(kg,
sd,
&ss_isect->hits[hit],
ray,
verts);
}
#endif /* __OBJECT_MOTION__ */
else {
@ -313,7 +313,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
ccl_device_noinline void subsurface_scatter_multi_setup(
KernelGlobals *kg,
SubsurfaceIntersection* ss_isect,
LocalIntersection* ss_isect,
int hit,
ShaderData *sd,
ccl_addr_space PathState *state,
@ -403,8 +403,8 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_a
/* intersect with the same object. if multiple intersections are
* found it will randomly pick one of them */
SubsurfaceIntersection ss_isect;
scene_intersect_subsurface(kg, ray, &ss_isect, sd->object, lcg_state, 1);
LocalIntersection ss_isect;
scene_intersect_local(kg, ray, &ss_isect, sd->object, lcg_state, 1);
/* evaluate bssrdf */
if(ss_isect.num_hits > 0) {

View File

@ -34,7 +34,7 @@
CCL_NAMESPACE_BEGIN
/* constants */
/* Constants */
#define OBJECT_SIZE 12
#define OBJECT_VECTOR_SIZE 6
#define LIGHT_SIZE 11
@ -46,6 +46,7 @@ CCL_NAMESPACE_BEGIN
#define BSSRDF_MIN_RADIUS 1e-8f
#define BSSRDF_MAX_HITS 4
#define LOCAL_MAX_HITS 4
#define BECKMANN_TABLE_SIZE 256
@ -56,6 +57,7 @@ CCL_NAMESPACE_BEGIN
#define VOLUME_STACK_SIZE 16
/* Split kernel constants */
#define WORK_POOL_SIZE_GPU 64
#define WORK_POOL_SIZE_CPU 1
#ifdef __KERNEL_GPU__
@ -76,7 +78,7 @@ CCL_NAMESPACE_BEGIN
#endif
/* device capabilities */
/* Device capabilities */
#ifdef __KERNEL_CPU__
# ifdef __KERNEL_SSE2__
# define __QBVH__
@ -161,7 +163,7 @@ CCL_NAMESPACE_BEGIN
#endif /* __KERNEL_OPENCL__ */
/* kernel features */
/* Kernel features */
#define __SOBOL__
#define __INSTANCING__
#define __DPDU__
@ -175,8 +177,8 @@ CCL_NAMESPACE_BEGIN
#define __CLAMP_SAMPLE__
#define __PATCH_EVAL__
#define __SHADOW_TRICKS__
#define __DENOISING_FEATURES__
#define __SHADER_RAYTRACE__
#ifdef __KERNEL_SHADING__
# define __SVM__
@ -199,10 +201,6 @@ CCL_NAMESPACE_BEGIN
# define __BAKING__
#endif
#ifdef WITH_CYCLES_DEBUG
# define __KERNEL_DEBUG__
#endif
/* Scene-based selective features compilation. */
#ifdef __NO_CAMERA_MOTION__
# undef __CAMERA_MOTION__
@ -241,6 +239,18 @@ CCL_NAMESPACE_BEGIN
#ifdef __NO_DENOISING__
# undef __DENOISING_FEATURES__
#endif
#ifdef __NO_SHADER_RAYTRACE__
# undef __SHADER_RAYTRACE__
#endif
/* Features that enable others */
#ifdef WITH_CYCLES_DEBUG
# define __KERNEL_DEBUG__
#endif
#if defined(__SUBSURFACE__) || defined(__SHADER_RAYTRACE__)
# define __BVH_LOCAL__
#endif
/* Shader Evaluation */
@ -1048,17 +1058,17 @@ typedef struct PathState {
#endif
} PathState;
/* Subsurface */
/* Struct to gather multiple SSS hits. */
typedef struct SubsurfaceIntersection {
/* Struct to gather multiple nearby intersections. */
typedef struct LocalIntersection {
Ray ray;
float3 weight[BSSRDF_MAX_HITS];
float3 weight[LOCAL_MAX_HITS];
int num_hits;
struct Intersection hits[BSSRDF_MAX_HITS];
float3 Ng[BSSRDF_MAX_HITS];
} SubsurfaceIntersection;
struct Intersection hits[LOCAL_MAX_HITS];
float3 Ng[LOCAL_MAX_HITS];
} LocalIntersection;
/* Subsurface */
/* Struct to gather SSS indirect rays and delay tracing them. */
typedef struct SubsurfaceIndirectRays {
@ -1070,6 +1080,7 @@ typedef struct SubsurfaceIndirectRays {
float3 throughputs[BSSRDF_MAX_HITS];
struct PathRadianceState L_state[BSSRDF_MAX_HITS];
} SubsurfaceIndirectRays;
static_assert(BSSRDF_MAX_HITS <= LOCAL_MAX_HITS, "BSSRDF hits too high.");
/* Constant Kernel Data
*

View File

@ -67,7 +67,7 @@ typedef ccl_global struct SplitBranchedState {
int num_hits;
uint lcg_state;
SubsurfaceIntersection ss_isect;
LocalIntersection ss_isect;
# ifdef __VOLUME__
VolumeStack volume_stack[VOLUME_STACK_SIZE];

View File

@ -61,7 +61,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
/* do subsurface scatter step with copy of shader data, this will
* replace the BSSRDF with a diffuse BSDF closure */
for(int j = branched_state->ss_next_sample; j < num_samples; j++) {
ccl_global SubsurfaceIntersection *ss_isect = &branched_state->ss_isect;
ccl_global LocalIntersection *ss_isect = &branched_state->ss_isect;
float bssrdf_u, bssrdf_v;
path_branched_rng_2D(kg,
bssrdf_rng_hash,
@ -75,7 +75,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
/* intersection is expensive so avoid doing multiple times for the same input */
if(branched_state->next_hit == 0 && branched_state->next_closure == 0 && branched_state->next_sample == 0) {
uint lcg_state = branched_state->lcg_state;
SubsurfaceIntersection ss_isect_private;
LocalIntersection ss_isect_private;
branched_state->num_hits = subsurface_scatter_multi_intersect(kg,
&ss_isect_private,
@ -102,7 +102,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
*bssrdf_sd = *sd; /* note: copy happens each iteration of inner loop, this is
* important as the indirect path will write into bssrdf_sd */
SubsurfaceIntersection ss_isect_private = *ss_isect;
LocalIntersection ss_isect_private = *ss_isect;
subsurface_scatter_multi_setup(kg,
&ss_isect_private,
hit,

View File

@ -157,6 +157,7 @@ public:
virtual bool has_object_dependency() { return false; }
virtual bool has_integrator_dependency() { return false; }
virtual bool has_volume_support() { return false; }
virtual bool has_raytrace() { return false; }
vector<ShaderInput*> inputs;
vector<ShaderOutput*> outputs;

View File

@ -592,6 +592,9 @@ void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
if(node->has_surface_transparent()) {
requested_features->use_transparent = true;
}
if(node->has_raytrace()) {
requested_features->use_shader_raytrace = true;
}
}
}