Cycles: Split ShaderData object and shader flags

We started to run out of bits there, so now we separate flags
which came from __object_flags and which are either runtime or
coming from __shader_flags.

Rule now is: SD_OBJECT_* flags are to be tested against new
object_flags field of ShaderData, all the rest flags are to
be tested against flags field of ShaderData.

There should be no user-visible changes, and time difference
should be minimal. In fact, from tests here can only see hardly
measurable difference and sometimes the new code is somewhat
faster (all within a noise floor, so hard to tell for sure).

Reviewers: brecht, dingto, juicyfruit, lukasstockner97, maiself

Differential Revision: https://developer.blender.org/D2428
This commit is contained in:
Sergey Sharybin 2016-12-23 11:31:19 +01:00
parent b9311b5e5a
commit bc096e1eb8
15 changed files with 155 additions and 93 deletions

@ -236,9 +236,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* instance push */ /* instance push */
object = kernel_tex_fetch(__prim_object, -prim_addr-1); object = kernel_tex_fetch(__prim_object, -prim_addr-1);
int object_flag = kernel_tex_fetch(__object_flag, object); int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_HAS_VOLUME) { if(object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION) # if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm); bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
# else # else

@ -287,7 +287,6 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* instance push */ /* instance push */
object = kernel_tex_fetch(__prim_object, -prim_addr-1); object = kernel_tex_fetch(__prim_object, -prim_addr-1);
int object_flag = kernel_tex_fetch(__object_flag, object); int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_HAS_VOLUME) { if(object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION) # if BVH_FEATURE(BVH_MOTION)

@ -293,7 +293,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Instance push. */ /* Instance push. */
object = kernel_tex_fetch(__prim_object, -prim_addr-1); object = kernel_tex_fetch(__prim_object, -prim_addr-1);
int object_flag = kernel_tex_fetch(__object_flag, object); int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_HAS_VOLUME) { if(object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION) # if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm); bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);

@ -344,9 +344,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Instance push. */ /* Instance push. */
object = kernel_tex_fetch(__prim_object, -prim_addr-1); object = kernel_tex_fetch(__prim_object, -prim_addr-1);
int object_flag = kernel_tex_fetch(__object_flag, object); int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_HAS_VOLUME) { if(object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION) # if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm); bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm);
# else # else

@ -81,7 +81,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
} }
/* Compute face normal. */ /* Compute face normal. */
float3 Ng; float3 Ng;
if(ccl_fetch(sd, flag) & SD_OBJECT_NEGATIVE_SCALE_APPLIED) { if(ccl_fetch(sd, object_flag) & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0])); Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0]));
} }
else { else {

@ -113,7 +113,6 @@ ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int
ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg, int object, float time, Transform *itfm) ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg, int object, float time, Transform *itfm)
{ {
int object_flag = kernel_tex_fetch(__object_flag, object); int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_MOTION) { if(object_flag & SD_OBJECT_MOTION) {
/* if we do motion blur */ /* if we do motion blur */
Transform tfm = object_fetch_transform_motion(kg, object, time); Transform tfm = object_fetch_transform_motion(kg, object, time);

@ -157,8 +157,9 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *
if(is_curve_primitive) { if(is_curve_primitive) {
center = curve_motion_center_location(kg, sd); center = curve_motion_center_location(kg, sd);
if(!(ccl_fetch(sd, flag) & SD_OBJECT_TRANSFORM_APPLIED)) if(!(ccl_fetch(sd, object_flag) & SD_OBJECT_TRANSFORM_APPLIED)) {
object_position_transform(kg, sd, &center); object_position_transform(kg, sd, &center);
}
} }
else else
#endif #endif
@ -181,7 +182,7 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *
motion_post = primitive_attribute_float3(kg, sd, desc, NULL, NULL); motion_post = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
#ifdef __HAIR__ #ifdef __HAIR__
if(is_curve_primitive && (ccl_fetch(sd, flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) { if(is_curve_primitive && (ccl_fetch(sd, object_flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
object_position_transform(kg, sd, &motion_pre); object_position_transform(kg, sd, &motion_pre);
object_position_transform(kg, sd, &motion_post); object_position_transform(kg, sd, &motion_post);
} }

@ -32,10 +32,12 @@ ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
const float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2)); const float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2));
/* return normal */ /* return normal */
if(ccl_fetch(sd, flag) & SD_OBJECT_NEGATIVE_SCALE_APPLIED) if(ccl_fetch(sd, object_flag) & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
return normalize(cross(v2 - v0, v1 - v0)); return normalize(cross(v2 - v0, v1 - v0));
else }
else {
return normalize(cross(v1 - v0, v2 - v0)); return normalize(cross(v1 - v0, v2 - v0));
}
} }
/* point and normal on triangle */ /* point and normal on triangle */
@ -46,20 +48,18 @@ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int
float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+0)); float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+0));
float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+1)); float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+1));
float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2)); float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2));
/* compute point */ /* compute point */
float t = 1.0f - u - v; float t = 1.0f - u - v;
*P = (u*v0 + v*v1 + t*v2); *P = (u*v0 + v*v1 + t*v2);
/* get object flags */ /* get object flags */
int object_flag = kernel_tex_fetch(__object_flag, object); int object_flag = kernel_tex_fetch(__object_flag, object);
/* compute normal */ /* compute normal */
if(object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) if(object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
*Ng = normalize(cross(v2 - v0, v1 - v0)); *Ng = normalize(cross(v2 - v0, v1 - v0));
else }
else {
*Ng = normalize(cross(v1 - v0, v2 - v0)); *Ng = normalize(cross(v1 - v0, v2 - v0));
}
/* shader`*/ /* shader`*/
*shader = kernel_tex_fetch(__tri_shader, prim); *shader = kernel_tex_fetch(__tri_shader, prim);
} }

@ -452,7 +452,7 @@ bool kernel_path_subsurface_scatter(
# ifdef __VOLUME__ # ifdef __VOLUME__
ss_indirect->need_update_volume_stack = ss_indirect->need_update_volume_stack =
kernel_data.integrator.use_volumes && kernel_data.integrator.use_volumes &&
ccl_fetch(sd, flag) & SD_OBJECT_INTERSECTS_VOLUME; ccl_fetch(sd, object_flag) & SD_OBJECT_INTERSECTS_VOLUME;
# endif /* __VOLUME__ */ # endif /* __VOLUME__ */
/* compute lighting with the BSDF closure */ /* compute lighting with the BSDF closure */
@ -777,21 +777,25 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
/* holdout */ /* holdout */
#ifdef __HOLDOUT__ #ifdef __HOLDOUT__
if((sd.flag & (SD_HOLDOUT|SD_OBJECT_HOLDOUT_MASK)) && (state.flag & PATH_RAY_CAMERA)) { if(((sd.flag & SD_HOLDOUT) ||
(sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
(state.flag & PATH_RAY_CAMERA))
{
if(kernel_data.background.transparent) { if(kernel_data.background.transparent) {
float3 holdout_weight; float3 holdout_weight;
if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) {
if(sd.flag & SD_OBJECT_HOLDOUT_MASK)
holdout_weight = make_float3(1.0f, 1.0f, 1.0f); holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
else }
else {
holdout_weight = shader_holdout_eval(kg, &sd); holdout_weight = shader_holdout_eval(kg, &sd);
}
/* any throughput is ok, should all be identical here */ /* any throughput is ok, should all be identical here */
L_transparent += average(holdout_weight*throughput); L_transparent += average(holdout_weight*throughput);
} }
if(sd.flag & SD_OBJECT_HOLDOUT_MASK) if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) {
break; break;
}
} }
#endif /* __HOLDOUT__ */ #endif /* __HOLDOUT__ */

@ -167,8 +167,9 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
true); true);
#ifdef __VOLUME__ #ifdef __VOLUME__
Ray volume_ray = *ray; Ray volume_ray = *ray;
bool need_update_volume_stack = kernel_data.integrator.use_volumes && bool need_update_volume_stack =
ccl_fetch(sd, flag) & SD_OBJECT_INTERSECTS_VOLUME; kernel_data.integrator.use_volumes &&
ccl_fetch(sd, object_flag) & SD_OBJECT_INTERSECTS_VOLUME;
#endif /* __VOLUME__ */ #endif /* __VOLUME__ */
/* compute lighting with the BSDF closure */ /* compute lighting with the BSDF closure */
@ -473,21 +474,21 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
/* holdout */ /* holdout */
#ifdef __HOLDOUT__ #ifdef __HOLDOUT__
if(sd.flag & (SD_HOLDOUT|SD_OBJECT_HOLDOUT_MASK)) { if((sd.flag & SD_HOLDOUT) || (sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) {
if(kernel_data.background.transparent) { if(kernel_data.background.transparent) {
float3 holdout_weight; float3 holdout_weight;
if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) {
if(sd.flag & SD_OBJECT_HOLDOUT_MASK)
holdout_weight = make_float3(1.0f, 1.0f, 1.0f); holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
else }
else {
holdout_weight = shader_holdout_eval(kg, &sd); holdout_weight = shader_holdout_eval(kg, &sd);
}
/* any throughput is ok, should all be identical here */ /* any throughput is ok, should all be identical here */
L_transparent += average(holdout_weight*throughput); L_transparent += average(holdout_weight*throughput);
} }
if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) {
if(sd.flag & SD_OBJECT_HOLDOUT_MASK)
break; break;
}
} }
#endif /* __HOLDOUT__ */ #endif /* __HOLDOUT__ */

@ -38,7 +38,7 @@ CCL_NAMESPACE_BEGIN
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
ccl_device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time) ccl_device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time)
{ {
if(ccl_fetch(sd, flag) & SD_OBJECT_MOTION) { if(ccl_fetch(sd, object_flag) & SD_OBJECT_MOTION) {
ccl_fetch(sd, ob_tfm) = object_fetch_transform_motion(kg, ccl_fetch(sd, object), time); ccl_fetch(sd, ob_tfm) = object_fetch_transform_motion(kg, ccl_fetch(sd, object), time);
ccl_fetch(sd, ob_itfm) = transform_quick_inverse(ccl_fetch(sd, ob_tfm)); ccl_fetch(sd, ob_itfm) = transform_quick_inverse(ccl_fetch(sd, ob_tfm));
} }
@ -59,7 +59,9 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
#endif #endif
ccl_fetch(sd, type) = isect->type; ccl_fetch(sd, type) = isect->type;
ccl_fetch(sd, flag) = kernel_tex_fetch(__object_flag, ccl_fetch(sd, object)); ccl_fetch(sd, flag) = 0;
ccl_fetch(sd, object_flag) = kernel_tex_fetch(__object_flag,
ccl_fetch(sd, object));
/* matrices and time */ /* matrices and time */
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
@ -160,10 +162,11 @@ void shader_setup_from_subsurface(
const Intersection *isect, const Intersection *isect,
const Ray *ray) const Ray *ray)
{ {
bool backfacing = sd->flag & SD_BACKFACING; const bool backfacing = sd->flag & SD_BACKFACING;
/* object, matrices, time, ray_length stay the same */ /* object, matrices, time, ray_length stay the same */
sd->flag = kernel_tex_fetch(__object_flag, sd->object); sd->flag = 0;
sd->object_flag = kernel_tex_fetch(__object_flag, sd->object);
sd->prim = kernel_tex_fetch(__prim_index, isect->prim); sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
sd->type = isect->type; sd->type = isect->type;
@ -271,8 +274,10 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
ccl_fetch(sd, ray_length) = t; ccl_fetch(sd, ray_length) = t;
ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE); ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE);
ccl_fetch(sd, object_flag) = 0;
if(ccl_fetch(sd, object) != OBJECT_NONE) { if(ccl_fetch(sd, object) != OBJECT_NONE) {
ccl_fetch(sd, flag) |= kernel_tex_fetch(__object_flag, ccl_fetch(sd, object)); ccl_fetch(sd, object_flag) |= kernel_tex_fetch(__object_flag,
ccl_fetch(sd, object));
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, time); shader_setup_object_transforms(kg, sd, time);
@ -298,7 +303,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v)); ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v));
#ifdef __INSTANCING__ #ifdef __INSTANCING__
if(!(ccl_fetch(sd, flag) & SD_OBJECT_TRANSFORM_APPLIED)) { if(!(ccl_fetch(sd, object_flag) & SD_OBJECT_TRANSFORM_APPLIED)) {
object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N)); object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N));
} }
#endif #endif
@ -309,7 +314,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv)); triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv));
# ifdef __INSTANCING__ # ifdef __INSTANCING__
if(!(ccl_fetch(sd, flag) & SD_OBJECT_TRANSFORM_APPLIED)) { if(!(ccl_fetch(sd, object_flag) & SD_OBJECT_TRANSFORM_APPLIED)) {
object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu)); object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu));
object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv)); object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv));
} }
@ -379,6 +384,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
ccl_fetch(sd, I) = -ray->D; ccl_fetch(sd, I) = -ray->D;
ccl_fetch(sd, shader) = kernel_data.background.surface_shader; ccl_fetch(sd, shader) = kernel_data.background.surface_shader;
ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE); ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE);
ccl_fetch(sd, object_flag) = 0;
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
ccl_fetch(sd, time) = ray->time; ccl_fetch(sd, time) = ray->time;
#endif #endif
@ -420,6 +426,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
sd->I = -ray->D; sd->I = -ray->D;
sd->shader = SHADER_NONE; sd->shader = SHADER_NONE;
sd->flag = 0; sd->flag = 0;
sd->object_flag = 0;
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
sd->time = ray->time; sd->time = ray->time;
#endif #endif
@ -1027,6 +1034,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
sd->num_closure = 0; sd->num_closure = 0;
sd->num_closure_extra = 0; sd->num_closure_extra = 0;
sd->flag = 0; sd->flag = 0;
sd->object_flag = 0;
for(int i = 0; stack[i].shader != SHADER_NONE; i++) { for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
/* setup shaderdata from stack. it's mostly setup already in /* setup shaderdata from stack. it's mostly setup already in
@ -1034,11 +1042,12 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
sd->object = stack[i].object; sd->object = stack[i].object;
sd->shader = stack[i].shader; sd->shader = stack[i].shader;
sd->flag &= ~(SD_SHADER_FLAGS|SD_OBJECT_FLAGS); sd->flag &= ~SD_SHADER_FLAGS;
sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE); sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
sd->object_flag &= ~SD_OBJECT_FLAGS;
if(sd->object != OBJECT_NONE) { if(sd->object != OBJECT_NONE) {
sd->flag |= kernel_tex_fetch(__object_flag, sd->object); sd->object_flag |= kernel_tex_fetch(__object_flag, sd->object);
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
/* todo: this is inefficient for motion blur, we should be /* todo: this is inefficient for motion blur, we should be

@ -692,56 +692,108 @@ typedef enum ShaderContext {
/* Shader Data /* Shader Data
* *
* Main shader state at a point on the surface or in a volume. All coordinates * Main shader state at a point on the surface or in a volume. All coordinates
* are in world space. */ * are in world space.
*/
enum ShaderDataFlag { enum ShaderDataFlag {
/* runtime flags */ /* Runtime flags. */
SD_BACKFACING = (1 << 0), /* backside of surface? */
SD_EMISSION = (1 << 1), /* have emissive closure? */ /* Set when ray hits backside of surface. */
SD_BSDF = (1 << 2), /* have bsdf closure? */ SD_BACKFACING = (1 << 0),
SD_BSDF_HAS_EVAL = (1 << 3), /* have non-singular bsdf closure? */ /* Shader has emissive closure. */
SD_BSSRDF = (1 << 4), /* have bssrdf */ SD_EMISSION = (1 << 1),
SD_HOLDOUT = (1 << 5), /* have holdout closure? */ /* Shader has BSDF closure. */
SD_ABSORPTION = (1 << 6), /* have volume absorption closure? */ SD_BSDF = (1 << 2),
SD_SCATTER = (1 << 7), /* have volume phase closure? */ /* Shader has non-singular BSDF closure. */
SD_AO = (1 << 8), /* have ao closure? */ SD_BSDF_HAS_EVAL = (1 << 3),
SD_TRANSPARENT = (1 << 9), /* have transparent closure? */ /* Shader has BSSRDF closure. */
SD_BSSRDF = (1 << 4),
/* Shader has holdout closure. */
SD_HOLDOUT = (1 << 5),
/* Shader has volume absorption closure. */
SD_ABSORPTION = (1 << 6),
/* Shader has have volume phase (scatter) closure. */
SD_SCATTER = (1 << 7),
/* Shader has AO closure. */
SD_AO = (1 << 8),
/* Shader has transparent closure. */
SD_TRANSPARENT = (1 << 9),
/* BSDF requires LCG for evaluation. */
SD_BSDF_NEEDS_LCG = (1 << 10), SD_BSDF_NEEDS_LCG = (1 << 10),
SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF| SD_CLOSURE_FLAGS = (SD_EMISSION |
SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO| SD_BSDF |
SD_BSDF_HAS_EVAL |
SD_BSSRDF |
SD_HOLDOUT |
SD_ABSORPTION |
SD_SCATTER |
SD_AO |
SD_BSDF_NEEDS_LCG), SD_BSDF_NEEDS_LCG),
/* shader flags */ /* Shader flags. */
SD_USE_MIS = (1 << 12), /* direct light sample */
SD_HAS_TRANSPARENT_SHADOW = (1 << 13), /* has transparent shadow */
SD_HAS_VOLUME = (1 << 14), /* has volume shader */
SD_HAS_ONLY_VOLUME = (1 << 15), /* has only volume shader, no surface */
SD_HETEROGENEOUS_VOLUME = (1 << 16), /* has heterogeneous volume */
SD_HAS_BSSRDF_BUMP = (1 << 17), /* bssrdf normal uses bump */
SD_VOLUME_EQUIANGULAR = (1 << 18), /* use equiangular sampling */
SD_VOLUME_MIS = (1 << 19), /* use multiple importance sampling */
SD_VOLUME_CUBIC = (1 << 20), /* use cubic interpolation for voxels */
SD_HAS_BUMP = (1 << 21), /* has data connected to the displacement input */
SD_HAS_DISPLACEMENT = (1 << 22), /* has true displacement */
SD_HAS_CONSTANT_EMISSION = (1 << 23), /* has constant emission (value stored in __shader_flag) */
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME| /* direct light sample */
SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME| SD_USE_MIS = (1 << 16),
SD_HAS_BSSRDF_BUMP|SD_VOLUME_EQUIANGULAR|SD_VOLUME_MIS| /* Has transparent shadow. */
SD_VOLUME_CUBIC|SD_HAS_BUMP|SD_HAS_DISPLACEMENT|SD_HAS_CONSTANT_EMISSION), SD_HAS_TRANSPARENT_SHADOW = (1 << 17),
/* Has volume shader. */
SD_HAS_VOLUME = (1 << 18),
/* Has only volume shader, no surface. */
SD_HAS_ONLY_VOLUME = (1 << 19),
/* Has heterogeneous volume. */
SD_HETEROGENEOUS_VOLUME = (1 << 20),
/* BSSRDF normal uses bump. */
SD_HAS_BSSRDF_BUMP = (1 << 21),
/* Use equiangular volume sampling */
SD_VOLUME_EQUIANGULAR = (1 << 22),
/* Use multiple importance volume sampling. */
SD_VOLUME_MIS = (1 << 23),
/* Use cubic interpolation for voxels. */
SD_VOLUME_CUBIC = (1 << 24),
/* Has data connected to the displacement input. */
SD_HAS_BUMP = (1 << 25),
/* Has true displacement. */
SD_HAS_DISPLACEMENT = (1 << 26),
/* Has constant emission (value stored in __shader_flag) */
SD_HAS_CONSTANT_EMISSION = (1 << 27),
/* object flags */ SD_SHADER_FLAGS = (SD_USE_MIS |
SD_OBJECT_HOLDOUT_MASK = (1 << 24), /* holdout for camera rays */ SD_HAS_TRANSPARENT_SHADOW |
SD_OBJECT_MOTION = (1 << 25), /* has object motion blur */ SD_HAS_VOLUME |
SD_OBJECT_TRANSFORM_APPLIED = (1 << 26), /* vertices have transform applied */ SD_HAS_ONLY_VOLUME |
SD_OBJECT_NEGATIVE_SCALE_APPLIED = (1 << 27), /* vertices have negative scale applied */ SD_HETEROGENEOUS_VOLUME|
SD_OBJECT_HAS_VOLUME = (1 << 28), /* object has a volume shader */ SD_HAS_BSSRDF_BUMP |
SD_OBJECT_INTERSECTS_VOLUME = (1 << 29), /* object intersects AABB of an object with volume shader */ SD_VOLUME_EQUIANGULAR |
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 30), /* has position for motion vertices */ SD_VOLUME_MIS |
SD_VOLUME_CUBIC |
SD_HAS_BUMP |
SD_HAS_DISPLACEMENT |
SD_HAS_CONSTANT_EMISSION)
};
SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_OBJECT_TRANSFORM_APPLIED| /* Object flags. */
SD_OBJECT_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME| enum ShaderDataObjectFlag {
/* Holdout for camera rays. */
SD_OBJECT_HOLDOUT_MASK = (1 << 0),
/* Has object motion blur. */
SD_OBJECT_MOTION = (1 << 1),
/* Vertices have transform applied. */
SD_OBJECT_TRANSFORM_APPLIED = (1 << 2),
/* Vertices have negative scale applied. */
SD_OBJECT_NEGATIVE_SCALE_APPLIED = (1 << 3),
/* Object has a volume shader. */
SD_OBJECT_HAS_VOLUME = (1 << 4),
/* Object intersects AABB of an object with volume shader. */
SD_OBJECT_INTERSECTS_VOLUME = (1 << 5),
/* Has position for motion vertices. */
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 6),
SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK |
SD_OBJECT_MOTION |
SD_OBJECT_TRANSFORM_APPLIED |
SD_OBJECT_NEGATIVE_SCALE_APPLIED |
SD_OBJECT_HAS_VOLUME |
SD_OBJECT_INTERSECTS_VOLUME) SD_OBJECT_INTERSECTS_VOLUME)
}; };
@ -780,6 +832,8 @@ typedef ccl_addr_space struct ShaderData {
ccl_soa_member(int, shader); ccl_soa_member(int, shader);
/* booleans describing shader, see ShaderDataFlag */ /* booleans describing shader, see ShaderDataFlag */
ccl_soa_member(int, flag); ccl_soa_member(int, flag);
/* booleans describing object of the shader, see ShaderDataObjectFlag */
ccl_soa_member(int, object_flag);
/* primitive id if there is one, ~0 otherwise */ /* primitive id if there is one, ~0 otherwise */
ccl_soa_member(int, prim); ccl_soa_member(int, prim);

@ -712,7 +712,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
else else
motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, P); motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, P);
if(!(sd->flag & SD_OBJECT_TRANSFORM_APPLIED)) { if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
object_position_transform(kg, sd, &P[0]); object_position_transform(kg, sd, &P[0]);
object_position_transform(kg, sd, &P[1]); object_position_transform(kg, sd, &P[1]);
object_position_transform(kg, sd, &P[2]); object_position_transform(kg, sd, &P[2]);

@ -137,22 +137,22 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
/* holdout */ /* holdout */
#ifdef __HOLDOUT__ #ifdef __HOLDOUT__
if((ccl_fetch(sd, flag) & (SD_HOLDOUT|SD_OBJECT_HOLDOUT_MASK)) && if(((ccl_fetch(sd, flag) & SD_HOLDOUT) ||
(ccl_fetch(sd, object_flag) & SD_OBJECT_HOLDOUT_MASK)) &&
(state->flag & PATH_RAY_CAMERA)) (state->flag & PATH_RAY_CAMERA))
{ {
if(kernel_data.background.transparent) { if(kernel_data.background.transparent) {
float3 holdout_weight; float3 holdout_weight;
if(ccl_fetch(sd, object_flag) & SD_OBJECT_HOLDOUT_MASK) {
if(ccl_fetch(sd, flag) & SD_OBJECT_HOLDOUT_MASK)
holdout_weight = make_float3(1.0f, 1.0f, 1.0f); holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
else }
else {
holdout_weight = shader_holdout_eval(kg, sd); holdout_weight = shader_holdout_eval(kg, sd);
}
/* any throughput is ok, should all be identical here */ /* any throughput is ok, should all be identical here */
L_transparent_coop[ray_index] += average(holdout_weight*throughput); L_transparent_coop[ray_index] += average(holdout_weight*throughput);
} }
if(ccl_fetch(sd, object_flag) & SD_OBJECT_HOLDOUT_MASK) {
if(ccl_fetch(sd, flag) & SD_OBJECT_HOLDOUT_MASK) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
*enqueue_flag = 1; *enqueue_flag = 1;
} }

@ -57,7 +57,7 @@ ccl_device_inline float wireframe(KernelGlobals *kg,
else else
motion_triangle_vertices(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), Co); motion_triangle_vertices(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), Co);
if(!(ccl_fetch(sd, flag) & SD_OBJECT_TRANSFORM_APPLIED)) { if(!(ccl_fetch(sd, object_flag) & SD_OBJECT_TRANSFORM_APPLIED)) {
object_position_transform(kg, sd, &Co[0]); object_position_transform(kg, sd, &Co[0]);
object_position_transform(kg, sd, &Co[1]); object_position_transform(kg, sd, &Co[1]);
object_position_transform(kg, sd, &Co[2]); object_position_transform(kg, sd, &Co[2]);