diff options
Diffstat (limited to 'intern/cycles/kernel/kernel_shader.h')
-rw-r--r-- | intern/cycles/kernel/kernel_shader.h | 1043 |
1 files changed, 268 insertions, 775 deletions
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 7f02e6fc7b3..3052bb53040 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -14,14 +14,9 @@ * limitations under the License. */ -/* - * ShaderData, used in four steps: - * - * Setup from incoming ray, sampled position and background. - * Execute for surface, volume or displacement. - * Evaluate one or more closures. - * Release. - */ +/* Functions to evaluate shaders and use the resulting shader closures. */ + +#pragma once // clang-format off #include "kernel/closure/alloc.h" @@ -30,479 +25,39 @@ #include "kernel/closure/emissive.h" // clang-format on +#include "kernel/kernel_accumulate.h" #include "kernel/svm/svm.h" -CCL_NAMESPACE_BEGIN - -/* ShaderData setup from incoming ray */ - -#ifdef __OBJECT_MOTION__ -ccl_device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time) -{ - if (sd->object_flag & SD_OBJECT_MOTION) { - sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time); - sd->ob_itfm = transform_quick_inverse(sd->ob_tfm); - } - else { - sd->ob_tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); - sd->ob_itfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); - } -} -#endif - -#ifdef __KERNEL_OPTIX__ -ccl_device_inline -#else -ccl_device_noinline -#endif - void - shader_setup_from_ray(KernelGlobals *kg, - ShaderData *sd, - const Intersection *isect, - const Ray *ray) -{ - PROFILING_INIT(kg, PROFILING_SHADER_SETUP); - - sd->object = (isect->object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, isect->prim) : - isect->object; - sd->lamp = LAMP_NONE; - - sd->type = isect->type; - sd->flag = 0; - sd->object_flag = kernel_tex_fetch(__object_flag, sd->object); - - /* matrices and time */ -#ifdef __OBJECT_MOTION__ - shader_setup_object_transforms(kg, sd, ray->time); -#endif - sd->time = ray->time; - - sd->prim = kernel_tex_fetch(__prim_index, isect->prim); - sd->ray_length = isect->t; - - sd->u = isect->u; - sd->v = isect->v; - -#ifdef __HAIR__ - if (sd->type & PRIMITIVE_ALL_CURVE) { - /* curve */ - curve_shader_setup(kg, sd, isect, ray); - } - else -#endif - if (sd->type & PRIMITIVE_TRIANGLE) { - /* static triangle */ - float3 Ng = triangle_normal(kg, sd); - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); - - /* vectors */ - sd->P = triangle_refine(kg, sd, isect, ray); - sd->Ng = Ng; - sd->N = Ng; - - /* smooth normal */ - if (sd->shader & SHADER_SMOOTH_NORMAL) - sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v); - -#ifdef __DPDU__ - /* dPdu/dPdv */ - triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv); -#endif - } - else { - /* motion triangle */ - motion_triangle_shader_setup(kg, sd, isect, ray, false); - } - - sd->I = -ray->D; - - sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; - - if (isect->object != OBJECT_NONE) { - /* instance transform */ - object_normal_transform_auto(kg, sd, &sd->N); - object_normal_transform_auto(kg, sd, &sd->Ng); -#ifdef __DPDU__ - object_dir_transform_auto(kg, sd, &sd->dPdu); - object_dir_transform_auto(kg, sd, &sd->dPdv); -#endif - } - - /* backfacing test */ - bool backfacing = (dot(sd->Ng, sd->I) < 0.0f); - - if (backfacing) { - sd->flag |= SD_BACKFACING; - sd->Ng = -sd->Ng; - sd->N = -sd->N; -#ifdef __DPDU__ - sd->dPdu = -sd->dPdu; - sd->dPdv = -sd->dPdv; -#endif - } - -#ifdef __RAY_DIFFERENTIALS__ - /* differentials */ - differential_transfer(&sd->dP, ray->dP, ray->D, ray->dD, sd->Ng, isect->t); - differential_incoming(&sd->dI, ray->dD); - differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng); -#endif - - PROFILING_SHADER(sd->shader); - PROFILING_OBJECT(sd->object); -} - -/* ShaderData setup from BSSRDF scatter */ - -#ifdef __SUBSURFACE__ -# ifndef __KERNEL_CUDA__ -ccl_device -# else -ccl_device_inline -# endif - void - shader_setup_from_subsurface(KernelGlobals *kg, - ShaderData *sd, - const Intersection *isect, - const Ray *ray) -{ - PROFILING_INIT(kg, PROFILING_SHADER_SETUP); - - const bool backfacing = sd->flag & SD_BACKFACING; - - /* object, matrices, time, ray_length stay the same */ - sd->flag = 0; - sd->object_flag = kernel_tex_fetch(__object_flag, sd->object); - sd->prim = kernel_tex_fetch(__prim_index, isect->prim); - sd->type = isect->type; - - sd->u = isect->u; - sd->v = isect->v; - - /* fetch triangle data */ - if (sd->type == PRIMITIVE_TRIANGLE) { - float3 Ng = triangle_normal(kg, sd); - sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); - - /* static triangle */ - sd->P = triangle_refine_local(kg, sd, isect, ray); - sd->Ng = Ng; - sd->N = Ng; - - if (sd->shader & SHADER_SMOOTH_NORMAL) - sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v); - -# ifdef __DPDU__ - /* dPdu/dPdv */ - triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv); -# endif - } - else { - /* motion triangle */ - motion_triangle_shader_setup(kg, sd, isect, ray, true); - } - - sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; - - if (isect->object != OBJECT_NONE) { - /* instance transform */ - object_normal_transform_auto(kg, sd, &sd->N); - object_normal_transform_auto(kg, sd, &sd->Ng); -# ifdef __DPDU__ - object_dir_transform_auto(kg, sd, &sd->dPdu); - object_dir_transform_auto(kg, sd, &sd->dPdv); -# endif - } - - /* backfacing test */ - if (backfacing) { - sd->flag |= SD_BACKFACING; - sd->Ng = -sd->Ng; - sd->N = -sd->N; -# ifdef __DPDU__ - sd->dPdu = -sd->dPdu; - sd->dPdv = -sd->dPdv; -# endif - } - - /* should not get used in principle as the shading will only use a diffuse - * BSDF, but the shader might still access it */ - sd->I = sd->N; - -# ifdef __RAY_DIFFERENTIALS__ - /* differentials */ - differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng); - /* don't modify dP and dI */ -# endif - - PROFILING_SHADER(sd->shader); -} -#endif - -/* ShaderData setup from position sampled on mesh */ - -ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg, - ShaderData *sd, - const float3 P, - const float3 Ng, - const float3 I, - int shader, - int object, - int prim, - float u, - float v, - float t, - float time, - bool object_space, - int lamp) -{ - PROFILING_INIT(kg, PROFILING_SHADER_SETUP); - - /* vectors */ - sd->P = P; - sd->N = Ng; - sd->Ng = Ng; - sd->I = I; - sd->shader = shader; - if (prim != PRIM_NONE) - sd->type = PRIMITIVE_TRIANGLE; - else if (lamp != LAMP_NONE) - sd->type = PRIMITIVE_LAMP; - else - sd->type = PRIMITIVE_NONE; - - /* primitive */ - sd->object = object; - sd->lamp = LAMP_NONE; - /* Currently no access to bvh prim index for strand sd->prim. */ - sd->prim = prim; - sd->u = u; - sd->v = v; - sd->time = time; - sd->ray_length = t; - - sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; - sd->object_flag = 0; - if (sd->object != OBJECT_NONE) { - sd->object_flag |= kernel_tex_fetch(__object_flag, sd->object); - -#ifdef __OBJECT_MOTION__ - shader_setup_object_transforms(kg, sd, time); - } - else if (lamp != LAMP_NONE) { - sd->ob_tfm = lamp_fetch_transform(kg, lamp, false); - sd->ob_itfm = lamp_fetch_transform(kg, lamp, true); - sd->lamp = lamp; -#else - } - else if (lamp != LAMP_NONE) { - sd->lamp = lamp; -#endif - } - - /* transform into world space */ - if (object_space) { - object_position_transform_auto(kg, sd, &sd->P); - object_normal_transform_auto(kg, sd, &sd->Ng); - sd->N = sd->Ng; - object_dir_transform_auto(kg, sd, &sd->I); - } - - if (sd->type & PRIMITIVE_TRIANGLE) { - /* smooth normal */ - if (sd->shader & SHADER_SMOOTH_NORMAL) { - sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v); - - if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { - object_normal_transform_auto(kg, sd, &sd->N); - } - } - - /* dPdu/dPdv */ -#ifdef __DPDU__ - triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv); - - if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { - object_dir_transform_auto(kg, sd, &sd->dPdu); - object_dir_transform_auto(kg, sd, &sd->dPdv); - } -#endif - } - else { -#ifdef __DPDU__ - sd->dPdu = zero_float3(); - sd->dPdv = zero_float3(); -#endif - } - - /* backfacing test */ - if (sd->prim != PRIM_NONE) { - bool backfacing = (dot(sd->Ng, sd->I) < 0.0f); - - if (backfacing) { - sd->flag |= SD_BACKFACING; - sd->Ng = -sd->Ng; - sd->N = -sd->N; -#ifdef __DPDU__ - sd->dPdu = -sd->dPdu; - sd->dPdv = -sd->dPdv; -#endif - } - } - -#ifdef __RAY_DIFFERENTIALS__ - /* no ray differentials here yet */ - sd->dP = differential3_zero(); - sd->dI = differential3_zero(); - sd->du = differential_zero(); - sd->dv = differential_zero(); -#endif - - PROFILING_SHADER(sd->shader); - PROFILING_OBJECT(sd->object); -} - -/* ShaderData setup for displacement */ - -ccl_device void shader_setup_from_displace( - KernelGlobals *kg, ShaderData *sd, int object, int prim, float u, float v) -{ - float3 P, Ng, I = zero_float3(); - int shader; - - triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader); - - /* force smooth shading for displacement */ - shader |= SHADER_SMOOTH_NORMAL; - - shader_setup_from_sample( - kg, - sd, - P, - Ng, - I, - shader, - object, - prim, - u, - v, - 0.0f, - 0.5f, - !(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED), - LAMP_NONE); -} - -/* ShaderData setup from ray into background */ - -ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, - ShaderData *sd, - const Ray *ray) -{ - PROFILING_INIT(kg, PROFILING_SHADER_SETUP); - - /* vectors */ - sd->P = ray->D; - sd->N = -ray->D; - sd->Ng = -ray->D; - sd->I = -ray->D; - sd->shader = kernel_data.background.surface_shader; - sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; - sd->object_flag = 0; - sd->time = ray->time; - sd->ray_length = 0.0f; - - sd->object = OBJECT_NONE; - sd->lamp = LAMP_NONE; - sd->prim = PRIM_NONE; - sd->u = 0.0f; - sd->v = 0.0f; - -#ifdef __DPDU__ - /* dPdu/dPdv */ - sd->dPdu = zero_float3(); - sd->dPdv = zero_float3(); -#endif - -#ifdef __RAY_DIFFERENTIALS__ - /* differentials */ - sd->dP = ray->dD; - differential_incoming(&sd->dI, sd->dP); - sd->du = differential_zero(); - sd->dv = differential_zero(); +#ifdef __OSL__ +# include "kernel/osl/osl_shader.h" #endif - /* for NDC coordinates */ - sd->ray_P = ray->P; - - PROFILING_SHADER(sd->shader); - PROFILING_OBJECT(sd->object); -} - -/* ShaderData setup from point inside volume */ - -#ifdef __VOLUME__ -ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *sd, const Ray *ray) -{ - PROFILING_INIT(kg, PROFILING_SHADER_SETUP); - - /* vectors */ - sd->P = ray->P; - sd->N = -ray->D; - sd->Ng = -ray->D; - sd->I = -ray->D; - sd->shader = SHADER_NONE; - sd->flag = 0; - sd->object_flag = 0; - sd->time = ray->time; - sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */ - - sd->object = OBJECT_NONE; /* todo: fill this for texture coordinates */ - sd->lamp = LAMP_NONE; - sd->prim = PRIM_NONE; - sd->type = PRIMITIVE_NONE; - - sd->u = 0.0f; - sd->v = 0.0f; - -# ifdef __DPDU__ - /* dPdu/dPdv */ - sd->dPdu = zero_float3(); - sd->dPdv = zero_float3(); -# endif - -# ifdef __RAY_DIFFERENTIALS__ - /* differentials */ - sd->dP = ray->dD; - differential_incoming(&sd->dI, sd->dP); - sd->du = differential_zero(); - sd->dv = differential_zero(); -# endif - - /* for NDC coordinates */ - sd->ray_P = ray->P; - sd->ray_dP = ray->dP; - - PROFILING_SHADER(sd->shader); - PROFILING_OBJECT(sd->object); -} -#endif /* __VOLUME__ */ +CCL_NAMESPACE_BEGIN /* Merging */ -#if defined(__BRANCHED_PATH__) || defined(__VOLUME__) -ccl_device_inline void shader_merge_closures(ShaderData *sd) +#if defined(__VOLUME__) +ccl_device_inline void shader_merge_volume_closures(ShaderData *sd) { - /* merge identical closures, better when we sample a single closure at a time */ + /* Merge identical closures to save closure space with stacked volumes. */ for (int i = 0; i < sd->num_closure; i++) { ShaderClosure *sci = &sd->closure[i]; + if (sci->type != CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) { + continue; + } + for (int j = i + 1; j < sd->num_closure; j++) { ShaderClosure *scj = &sd->closure[j]; - - if (sci->type != scj->type) + if (sci->type != scj->type) { continue; - if (!bsdf_merge(sci, scj)) + } + + const HenyeyGreensteinVolume *hgi = (const HenyeyGreensteinVolume *)sci; + const HenyeyGreensteinVolume *hgj = (const HenyeyGreensteinVolume *)scj; + if (!(hgi->g == hgj->g)) { continue; + } sci->weight += scj->weight; sci->sample_weight += scj->sample_weight; @@ -520,16 +75,40 @@ ccl_device_inline void shader_merge_closures(ShaderData *sd) } } } -#endif /* __BRANCHED_PATH__ || __VOLUME__ */ -/* Defensive sampling. */ +ccl_device_inline void shader_copy_volume_phases(ShaderVolumePhases *ccl_restrict phases, + const ShaderData *ccl_restrict sd) +{ + phases->num_closure = 0; + + for (int i = 0; i < sd->num_closure; i++) { + const ShaderClosure *from_sc = &sd->closure[i]; + const HenyeyGreensteinVolume *from_hg = (const HenyeyGreensteinVolume *)from_sc; + + if (from_sc->type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) { + ShaderVolumeClosure *to_sc = &phases->closure[phases->num_closure]; + + to_sc->weight = from_sc->weight; + to_sc->sample_weight = from_sc->sample_weight; + to_sc->g = from_hg->g; + phases->num_closure++; + if (phases->num_closure >= MAX_VOLUME_CLOSURE) { + break; + } + } + } +} +#endif /* __VOLUME__ */ -ccl_device_inline void shader_prepare_closures(ShaderData *sd, ccl_addr_space PathState *state) +ccl_device_inline void shader_prepare_surface_closures(INTEGRATOR_STATE_CONST_ARGS, ShaderData *sd) { - /* We can likely also do defensive sampling at deeper bounces, particularly + /* Defensive sampling. + * + * We can likely also do defensive sampling at deeper bounces, particularly * for cases like a perfect mirror but possibly also others. This will need * a good heuristic. */ - if (state->bounce + state->transparent_bounce == 0 && sd->num_closure > 1) { + if (INTEGRATOR_STATE(path, bounce) + INTEGRATOR_STATE(path, transparent_bounce) == 0 && + sd->num_closure > 1) { float sum = 0.0f; for (int i = 0; i < sd->num_closure; i++) { @@ -546,98 +125,119 @@ ccl_device_inline void shader_prepare_closures(ShaderData *sd, ccl_addr_space Pa } } } + + /* Filter glossy. + * + * Blurring of bsdf after bounces, for rays that have a small likelihood + * of following this particular path (diffuse, rough glossy) */ + if (kernel_data.integrator.filter_glossy != FLT_MAX) { + float blur_pdf = kernel_data.integrator.filter_glossy * INTEGRATOR_STATE(path, min_ray_pdf); + + if (blur_pdf < 1.0f) { + float blur_roughness = sqrtf(1.0f - blur_pdf) * 0.5f; + + for (int i = 0; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + if (CLOSURE_IS_BSDF(sc->type)) { + bsdf_blur(kg, sc, blur_roughness); + } + } + } + } } /* BSDF */ -ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, - ShaderData *sd, - const float3 omega_in, - float *pdf, - const ShaderClosure *skip_sc, - BsdfEval *result_eval, - float sum_pdf, - float sum_sample_weight) +ccl_device_inline bool shader_bsdf_is_transmission(const ShaderData *sd, const float3 omega_in) +{ + return dot(sd->N, omega_in) < 0.0f; +} + +ccl_device_forceinline bool _shader_bsdf_exclude(ClosureType type, uint light_shader_flags) +{ + if (!(light_shader_flags & SHADER_EXCLUDE_ANY)) { + return false; + } + if (light_shader_flags & SHADER_EXCLUDE_DIFFUSE) { + if (CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_BSDF_BSSRDF(type)) { + return true; + } + } + if (light_shader_flags & SHADER_EXCLUDE_GLOSSY) { + if (CLOSURE_IS_BSDF_GLOSSY(type)) { + return true; + } + } + if (light_shader_flags & SHADER_EXCLUDE_TRANSMIT) { + if (CLOSURE_IS_BSDF_TRANSMISSION(type)) { + return true; + } + } + return false; +} + +ccl_device_inline float _shader_bsdf_multi_eval(const KernelGlobals *kg, + ShaderData *sd, + const float3 omega_in, + const bool is_transmission, + const ShaderClosure *skip_sc, + BsdfEval *result_eval, + float sum_pdf, + float sum_sample_weight, + const uint light_shader_flags) { /* this is the veach one-sample model with balance heuristic, some pdf * factors drop out when using balance heuristic weighting */ for (int i = 0; i < sd->num_closure; i++) { const ShaderClosure *sc = &sd->closure[i]; - if (sc != skip_sc && CLOSURE_IS_BSDF(sc->type)) { - float bsdf_pdf = 0.0f; - float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf); + if (sc == skip_sc) { + continue; + } + + if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { + if (CLOSURE_IS_BSDF(sc->type) && !_shader_bsdf_exclude(sc->type, light_shader_flags)) { + float bsdf_pdf = 0.0f; + float3 eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf); - if (bsdf_pdf != 0.0f) { - bsdf_eval_accum(result_eval, sc->type, eval * sc->weight, 1.0f); - sum_pdf += bsdf_pdf * sc->sample_weight; + if (bsdf_pdf != 0.0f) { + const bool is_diffuse = (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || + CLOSURE_IS_BSDF_BSSRDF(sc->type)); + bsdf_eval_accum(result_eval, is_diffuse, eval * sc->weight, 1.0f); + sum_pdf += bsdf_pdf * sc->sample_weight; + } } sum_sample_weight += sc->sample_weight; } } - *pdf = (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f; -} - -#ifdef __BRANCHED_PATH__ -ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg, - ShaderData *sd, - const float3 omega_in, - BsdfEval *result_eval, - float light_pdf, - bool use_mis) -{ - for (int i = 0; i < sd->num_closure; i++) { - const ShaderClosure *sc = &sd->closure[i]; - if (CLOSURE_IS_BSDF(sc->type)) { - float bsdf_pdf = 0.0f; - float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf); - if (bsdf_pdf != 0.0f) { - float mis_weight = use_mis ? power_heuristic(light_pdf, bsdf_pdf) : 1.0f; - bsdf_eval_accum(result_eval, sc->type, eval * sc->weight, mis_weight); - } - } - } + return (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f; } -#endif /* __BRANCHED_PATH__ */ #ifndef __KERNEL_CUDA__ ccl_device #else ccl_device_inline #endif - void - shader_bsdf_eval(KernelGlobals *kg, + float + shader_bsdf_eval(const KernelGlobals *kg, ShaderData *sd, const float3 omega_in, - BsdfEval *eval, - float light_pdf, - bool use_mis) + const bool is_transmission, + BsdfEval *bsdf_eval, + const uint light_shader_flags) { - PROFILING_INIT(kg, PROFILING_CLOSURE_EVAL); - - bsdf_eval_init(eval, NBUILTIN_CLOSURES, zero_float3(), kernel_data.film.use_light_pass); + bsdf_eval_init(bsdf_eval, false, zero_float3()); -#ifdef __BRANCHED_PATH__ - if (kernel_data.integrator.branched) - _shader_bsdf_multi_eval_branched(kg, sd, omega_in, eval, light_pdf, use_mis); - else -#endif - { - float pdf; - _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, NULL, eval, 0.0f, 0.0f); - if (use_mis) { - float weight = power_heuristic(light_pdf, pdf); - bsdf_eval_mis(eval, weight); - } - } + return _shader_bsdf_multi_eval( + kg, sd, omega_in, is_transmission, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags); } -ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd, float *randu) +/* Randomly sample a BSSRDF or BSDF proportional to ShaderClosure.sample_weight. */ +ccl_device_inline const ShaderClosure *shader_bsdf_bssrdf_pick(const ShaderData *ccl_restrict sd, + float *randu) { - /* Note the sampling here must match shader_bssrdf_pick, - * since we reuse the same random number. */ int sampled = 0; if (sd->num_closure > 1) { @@ -674,106 +274,33 @@ ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd, float *r } } - const ShaderClosure *sc = &sd->closure[sampled]; - return CLOSURE_IS_BSDF(sc->type) ? sc : NULL; + return &sd->closure[sampled]; } -ccl_device_inline const ShaderClosure *shader_bssrdf_pick(ShaderData *sd, - ccl_addr_space float3 *throughput, - float *randu) +/* Return weight for picked BSSRDF. */ +ccl_device_inline float3 shader_bssrdf_sample_weight(const ShaderData *ccl_restrict sd, + const ShaderClosure *ccl_restrict bssrdf_sc) { - /* Note the sampling here must match shader_bsdf_pick, - * since we reuse the same random number. */ - int sampled = 0; + float3 weight = bssrdf_sc->weight; if (sd->num_closure > 1) { - /* Pick a BSDF or BSSRDF or based on sample weights. */ - float sum_bsdf = 0.0f; - float sum_bssrdf = 0.0f; - - for (int i = 0; i < sd->num_closure; i++) { - const ShaderClosure *sc = &sd->closure[i]; - - if (CLOSURE_IS_BSDF(sc->type)) { - sum_bsdf += sc->sample_weight; - } - else if (CLOSURE_IS_BSSRDF(sc->type)) { - sum_bssrdf += sc->sample_weight; - } - } - - float r = (*randu) * (sum_bsdf + sum_bssrdf); - float partial_sum = 0.0f; - + float sum = 0.0f; for (int i = 0; i < sd->num_closure; i++) { const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { - float next_sum = partial_sum + sc->sample_weight; - - if (r < next_sum) { - if (CLOSURE_IS_BSDF(sc->type)) { - *throughput *= (sum_bsdf + sum_bssrdf) / sum_bsdf; - return NULL; - } - else { - *throughput *= (sum_bsdf + sum_bssrdf) / sum_bssrdf; - sampled = i; - - /* Rescale to reuse for direction sample, to better preserve stratification. */ - *randu = (r - partial_sum) / sc->sample_weight; - break; - } - } - - partial_sum = next_sum; + sum += sc->sample_weight; } } + weight *= sum / bssrdf_sc->sample_weight; } - const ShaderClosure *sc = &sd->closure[sampled]; - return CLOSURE_IS_BSSRDF(sc->type) ? sc : NULL; -} - -ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg, - ShaderData *sd, - float randu, - float randv, - BsdfEval *bsdf_eval, - float3 *omega_in, - differential3 *domega_in, - float *pdf) -{ - PROFILING_INIT(kg, PROFILING_CLOSURE_SAMPLE); - - const ShaderClosure *sc = shader_bsdf_pick(sd, &randu); - if (sc == NULL) { - *pdf = 0.0f; - return LABEL_NONE; - } - - /* BSSRDF should already have been handled elsewhere. */ - kernel_assert(CLOSURE_IS_BSDF(sc->type)); - - int label; - float3 eval = zero_float3(); - - *pdf = 0.0f; - label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); - - if (*pdf != 0.0f) { - bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight, kernel_data.film.use_light_pass); - - if (sd->num_closure > 1) { - float sweight = sc->sample_weight; - _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sc, bsdf_eval, *pdf * sweight, sweight); - } - } - - return label; + return weight; } -ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, +/* Sample direction for picked BSDF, and return evaluation and pdf for all + * BSDFs combined using MIS. */ +ccl_device int shader_bsdf_sample_closure(const KernelGlobals *kg, ShaderData *sd, const ShaderClosure *sc, float randu, @@ -783,7 +310,8 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, differential3 *domega_in, float *pdf) { - PROFILING_INIT(kg, PROFILING_CLOSURE_SAMPLE); + /* BSSRDF should already have been handled elsewhere. */ + kernel_assert(CLOSURE_IS_BSDF(sc->type)); int label; float3 eval = zero_float3(); @@ -791,19 +319,29 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, *pdf = 0.0f; label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); - if (*pdf != 0.0f) - bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight, kernel_data.film.use_light_pass); + if (*pdf != 0.0f) { + const bool is_diffuse = (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || + CLOSURE_IS_BSDF_BSSRDF(sc->type)); + bsdf_eval_init(bsdf_eval, is_diffuse, eval * sc->weight); + + if (sd->num_closure > 1) { + const bool is_transmission = shader_bsdf_is_transmission(sd, *omega_in); + float sweight = sc->sample_weight; + *pdf = _shader_bsdf_multi_eval( + kg, sd, *omega_in, is_transmission, sc, bsdf_eval, *pdf * sweight, sweight, 0); + } + } return label; } -ccl_device float shader_bsdf_average_roughness(ShaderData *sd) +ccl_device float shader_bsdf_average_roughness(const ShaderData *sd) { float roughness = 0.0f; float sum_weight = 0.0f; for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSDF(sc->type)) { /* sqrt once to undo the squaring from multiplying roughness on the @@ -817,17 +355,7 @@ ccl_device float shader_bsdf_average_roughness(ShaderData *sd) return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f; } -ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness) -{ - for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; - - if (CLOSURE_IS_BSDF(sc->type)) - bsdf_blur(kg, sc, roughness); - } -} - -ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, const ShaderData *sd) +ccl_device float3 shader_bsdf_transparency(const KernelGlobals *kg, const ShaderData *sd) { if (sd->flag & SD_HAS_ONLY_VOLUME) { return one_float3(); @@ -840,7 +368,7 @@ ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, const ShaderData * } } -ccl_device void shader_bsdf_disable_transparency(KernelGlobals *kg, ShaderData *sd) +ccl_device void shader_bsdf_disable_transparency(const KernelGlobals *kg, ShaderData *sd) { if (sd->flag & SD_TRANSPARENT) { for (int i = 0; i < sd->num_closure; i++) { @@ -856,7 +384,7 @@ ccl_device void shader_bsdf_disable_transparency(KernelGlobals *kg, ShaderData * } } -ccl_device float3 shader_bsdf_alpha(KernelGlobals *kg, ShaderData *sd) +ccl_device float3 shader_bsdf_alpha(const KernelGlobals *kg, const ShaderData *sd) { float3 alpha = one_float3() - shader_bsdf_transparency(kg, sd); @@ -866,12 +394,12 @@ ccl_device float3 shader_bsdf_alpha(KernelGlobals *kg, ShaderData *sd) return alpha; } -ccl_device float3 shader_bsdf_diffuse(KernelGlobals *kg, ShaderData *sd) +ccl_device float3 shader_bsdf_diffuse(const KernelGlobals *kg, const ShaderData *sd) { float3 eval = zero_float3(); for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type)) @@ -881,12 +409,12 @@ ccl_device float3 shader_bsdf_diffuse(KernelGlobals *kg, ShaderData *sd) return eval; } -ccl_device float3 shader_bsdf_glossy(KernelGlobals *kg, ShaderData *sd) +ccl_device float3 shader_bsdf_glossy(const KernelGlobals *kg, const ShaderData *sd) { float3 eval = zero_float3(); for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) eval += sc->weight; @@ -895,12 +423,12 @@ ccl_device float3 shader_bsdf_glossy(KernelGlobals *kg, ShaderData *sd) return eval; } -ccl_device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd) +ccl_device float3 shader_bsdf_transmission(const KernelGlobals *kg, const ShaderData *sd) { float3 eval = zero_float3(); for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type)) eval += sc->weight; @@ -909,12 +437,12 @@ ccl_device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd) return eval; } -ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd) +ccl_device float3 shader_bsdf_average_normal(const KernelGlobals *kg, const ShaderData *sd) { float3 N = zero_float3(); for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) N += sc->N * fabsf(average(sc->weight)); } @@ -922,59 +450,44 @@ ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd) return (is_zero(N)) ? sd->N : normalize(N); } -ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N_) +ccl_device float3 shader_bsdf_ao_normal(const KernelGlobals *kg, const ShaderData *sd) { - float3 eval = zero_float3(); float3 N = zero_float3(); for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; - + const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc; - eval += sc->weight * ao_factor; N += bsdf->N * fabsf(average(sc->weight)); } } - *N_ = (is_zero(N)) ? sd->N : normalize(N); - return eval; + return (is_zero(N)) ? sd->N : normalize(N); } #ifdef __SUBSURFACE__ -ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_blur_) +ccl_device float3 shader_bssrdf_normal(const ShaderData *sd) { - float3 eval = zero_float3(); float3 N = zero_float3(); - float texture_blur = 0.0f, weight_sum = 0.0f; for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSSRDF(sc->type)) { const Bssrdf *bssrdf = (const Bssrdf *)sc; float avg_weight = fabsf(average(sc->weight)); N += bssrdf->N * avg_weight; - eval += sc->weight; - texture_blur += bssrdf->texture_blur * avg_weight; - weight_sum += avg_weight; } } - if (N_) - *N_ = (is_zero(N)) ? sd->N : normalize(N); - - if (texture_blur_) - *texture_blur_ = safe_divide(texture_blur, weight_sum); - - return eval; + return (is_zero(N)) ? sd->N : normalize(N); } #endif /* __SUBSURFACE__ */ /* Constant emission optimization */ -ccl_device bool shader_constant_emission_eval(KernelGlobals *kg, int shader, float3 *eval) +ccl_device bool shader_constant_emission_eval(const KernelGlobals *kg, int shader, float3 *eval) { int shader_index = shader & SHADER_MASK; int shader_flag = kernel_tex_fetch(__shaders, shader_index).flags; @@ -992,7 +505,7 @@ ccl_device bool shader_constant_emission_eval(KernelGlobals *kg, int shader, flo /* Background */ -ccl_device float3 shader_background_eval(ShaderData *sd) +ccl_device float3 shader_background_eval(const ShaderData *sd) { if (sd->flag & SD_EMISSION) { return sd->closure_emission_background; @@ -1004,7 +517,7 @@ ccl_device float3 shader_background_eval(ShaderData *sd) /* Emission */ -ccl_device float3 shader_emissive_eval(ShaderData *sd) +ccl_device float3 shader_emissive_eval(const ShaderData *sd) { if (sd->flag & SD_EMISSION) { return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background; @@ -1016,7 +529,7 @@ ccl_device float3 shader_emissive_eval(ShaderData *sd) /* Holdout */ -ccl_device float3 shader_holdout_apply(KernelGlobals *kg, ShaderData *sd) +ccl_device float3 shader_holdout_apply(const KernelGlobals *kg, ShaderData *sd) { float3 weight = zero_float3(); @@ -1041,7 +554,7 @@ ccl_device float3 shader_holdout_apply(KernelGlobals *kg, ShaderData *sd) } else { for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; + const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_HOLDOUT(sc->type)) { weight += sc->weight; } @@ -1053,14 +566,12 @@ ccl_device float3 shader_holdout_apply(KernelGlobals *kg, ShaderData *sd) /* Surface Evaluation */ -ccl_device void shader_eval_surface(KernelGlobals *kg, - ShaderData *sd, - ccl_addr_space PathState *state, - ccl_global float *buffer, +template<uint node_feature_mask> +ccl_device void shader_eval_surface(INTEGRATOR_STATE_CONST_ARGS, + ShaderData *ccl_restrict sd, + ccl_global float *ccl_restrict buffer, int path_flag) { - PROFILING_INIT(kg, PROFILING_SHADER_EVAL); - /* If path is being terminated, we are tracing a shadow ray or evaluating * emission, then we don't need to store closures. The emission and shadow * shader data also do not have a closure array to save GPU memory. */ @@ -1069,7 +580,7 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, max_closures = 0; } else { - max_closures = kernel_data.integrator.max_closures; + max_closures = kernel_data.max_closures; } sd->num_closure = 0; @@ -1078,17 +589,18 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, #ifdef __OSL__ if (kg->osl) { if (sd->object == OBJECT_NONE && sd->lamp == LAMP_NONE) { - OSLShader::eval_background(kg, sd, state, path_flag); + OSLShader::eval_background(INTEGRATOR_STATE_PASS, sd, path_flag); } else { - OSLShader::eval_surface(kg, sd, state, path_flag); + OSLShader::eval_surface(INTEGRATOR_STATE_PASS, sd, path_flag); } } else #endif { #ifdef __SVM__ - svm_eval_nodes(kg, sd, state, buffer, SHADER_TYPE_SURFACE, path_flag); + svm_eval_nodes<node_feature_mask, SHADER_TYPE_SURFACE>( + INTEGRATOR_STATE_PASS, sd, buffer, path_flag); #else if (sd->object == OBJECT_NONE) { sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f); @@ -1105,8 +617,11 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, #endif } - if (sd->flag & SD_BSDF_NEEDS_LCG) { - sd->lcg_state = lcg_state_init_addrspace(state, 0xb4bc3953); + if (KERNEL_NODES_FEATURE(BSDF) && (sd->flag & SD_BSDF_NEEDS_LCG)) { + sd->lcg_state = lcg_state_init(INTEGRATOR_STATE(path, rng_hash), + INTEGRATOR_STATE(path, rng_offset), + INTEGRATOR_STATE(path, sample), + 0xb4bc3953); } } @@ -1114,48 +629,47 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, #ifdef __VOLUME__ -ccl_device_inline void _shader_volume_phase_multi_eval(const ShaderData *sd, - const float3 omega_in, - float *pdf, - int skip_phase, - BsdfEval *result_eval, - float sum_pdf, - float sum_sample_weight) +ccl_device_inline float _shader_volume_phase_multi_eval(const ShaderData *sd, + const ShaderVolumePhases *phases, + const float3 omega_in, + int skip_phase, + BsdfEval *result_eval, + float sum_pdf, + float sum_sample_weight) { - for (int i = 0; i < sd->num_closure; i++) { + for (int i = 0; i < phases->num_closure; i++) { if (i == skip_phase) continue; - const ShaderClosure *sc = &sd->closure[i]; - - if (CLOSURE_IS_PHASE(sc->type)) { - float phase_pdf = 0.0f; - float3 eval = volume_phase_eval(sd, sc, omega_in, &phase_pdf); + const ShaderVolumeClosure *svc = &phases->closure[i]; + float phase_pdf = 0.0f; + float3 eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf); - if (phase_pdf != 0.0f) { - bsdf_eval_accum(result_eval, sc->type, eval, 1.0f); - sum_pdf += phase_pdf * sc->sample_weight; - } - - sum_sample_weight += sc->sample_weight; + if (phase_pdf != 0.0f) { + bsdf_eval_accum(result_eval, false, eval, 1.0f); + sum_pdf += phase_pdf * svc->sample_weight; } + + sum_sample_weight += svc->sample_weight; } - *pdf = (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f; + return (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f; } -ccl_device void shader_volume_phase_eval( - KernelGlobals *kg, const ShaderData *sd, const float3 omega_in, BsdfEval *eval, float *pdf) +ccl_device float shader_volume_phase_eval(const KernelGlobals *kg, + const ShaderData *sd, + const ShaderVolumePhases *phases, + const float3 omega_in, + BsdfEval *phase_eval) { - PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_EVAL); + bsdf_eval_init(phase_eval, false, zero_float3()); - bsdf_eval_init(eval, NBUILTIN_CLOSURES, zero_float3(), kernel_data.film.use_light_pass); - - _shader_volume_phase_multi_eval(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); + return _shader_volume_phase_multi_eval(sd, phases, omega_in, -1, phase_eval, 0.0f, 0.0f); } -ccl_device int shader_volume_phase_sample(KernelGlobals *kg, +ccl_device int shader_volume_phase_sample(const KernelGlobals *kg, const ShaderData *sd, + const ShaderVolumePhases *phases, float randu, float randv, BsdfEval *phase_eval, @@ -1163,41 +677,34 @@ ccl_device int shader_volume_phase_sample(KernelGlobals *kg, differential3 *domega_in, float *pdf) { - PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_SAMPLE); - int sampled = 0; - if (sd->num_closure > 1) { + if (phases->num_closure > 1) { /* pick a phase closure based on sample weights */ float sum = 0.0f; - for (sampled = 0; sampled < sd->num_closure; sampled++) { - const ShaderClosure *sc = &sd->closure[sampled]; - - if (CLOSURE_IS_PHASE(sc->type)) - sum += sc->sample_weight; + for (sampled = 0; sampled < phases->num_closure; sampled++) { + const ShaderVolumeClosure *svc = &phases->closure[sampled]; + sum += svc->sample_weight; } float r = randu * sum; float partial_sum = 0.0f; - for (sampled = 0; sampled < sd->num_closure; sampled++) { - const ShaderClosure *sc = &sd->closure[sampled]; + for (sampled = 0; sampled < phases->num_closure; sampled++) { + const ShaderVolumeClosure *svc = &phases->closure[sampled]; + float next_sum = partial_sum + svc->sample_weight; - if (CLOSURE_IS_PHASE(sc->type)) { - float next_sum = partial_sum + sc->sample_weight; - - if (r <= next_sum) { - /* Rescale to reuse for BSDF direction sample. */ - randu = (r - partial_sum) / sc->sample_weight; - break; - } - - partial_sum = next_sum; + if (r <= next_sum) { + /* Rescale to reuse for BSDF direction sample. */ + randu = (r - partial_sum) / svc->sample_weight; + break; } + + partial_sum = next_sum; } - if (sampled == sd->num_closure) { + if (sampled == phases->num_closure) { *pdf = 0.0f; return LABEL_NONE; } @@ -1205,23 +712,23 @@ ccl_device int shader_volume_phase_sample(KernelGlobals *kg, /* todo: this isn't quite correct, we don't weight anisotropy properly * depending on color channels, even if this is perhaps not a common case */ - const ShaderClosure *sc = &sd->closure[sampled]; + const ShaderVolumeClosure *svc = &phases->closure[sampled]; int label; float3 eval = zero_float3(); *pdf = 0.0f; - label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); + label = volume_phase_sample(sd, svc, randu, randv, &eval, omega_in, domega_in, pdf); if (*pdf != 0.0f) { - bsdf_eval_init(phase_eval, sc->type, eval, kernel_data.film.use_light_pass); + bsdf_eval_init(phase_eval, false, eval); } return label; } -ccl_device int shader_phase_sample_closure(KernelGlobals *kg, +ccl_device int shader_phase_sample_closure(const KernelGlobals *kg, const ShaderData *sd, - const ShaderClosure *sc, + const ShaderVolumeClosure *sc, float randu, float randv, BsdfEval *phase_eval, @@ -1229,8 +736,6 @@ ccl_device int shader_phase_sample_closure(KernelGlobals *kg, differential3 *domega_in, float *pdf) { - PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_SAMPLE); - int label; float3 eval = zero_float3(); @@ -1238,18 +743,18 @@ ccl_device int shader_phase_sample_closure(KernelGlobals *kg, label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); if (*pdf != 0.0f) - bsdf_eval_init(phase_eval, sc->type, eval, kernel_data.film.use_light_pass); + bsdf_eval_init(phase_eval, false, eval); return label; } /* Volume Evaluation */ -ccl_device_inline void shader_eval_volume(KernelGlobals *kg, - ShaderData *sd, - ccl_addr_space PathState *state, - ccl_addr_space VolumeStack *stack, - int path_flag) +template<typename StackReadOp> +ccl_device_inline void shader_eval_volume(INTEGRATOR_STATE_CONST_ARGS, + ShaderData *ccl_restrict sd, + const int path_flag, + StackReadOp stack_read) { /* If path is being terminated, we are tracing a shadow ray or evaluating * emission, then we don't need to store closures. The emission and shadow @@ -1259,7 +764,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg, max_closures = 0; } else { - max_closures = kernel_data.integrator.max_closures; + max_closures = kernel_data.max_closures; } /* reset closures once at the start, we will be accumulating the closures @@ -1268,14 +773,18 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg, sd->num_closure_left = max_closures; sd->flag = 0; sd->object_flag = 0; - sd->type = PRIMITIVE_VOLUME; - for (int i = 0; stack[i].shader != SHADER_NONE; i++) { + for (int i = 0;; i++) { + const VolumeStack entry = stack_read(i); + if (entry.shader == SHADER_NONE) { + break; + } + /* setup shaderdata from stack. it's mostly setup already in * shader_setup_from_volume, this switching should be quick */ - sd->object = stack[i].object; + sd->object = entry.object; sd->lamp = LAMP_NONE; - sd->shader = stack[i].shader; + sd->shader = entry.shader; sd->flag &= ~SD_SHADER_FLAGS; sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags; @@ -1295,18 +804,19 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg, # ifdef __SVM__ # ifdef __OSL__ if (kg->osl) { - OSLShader::eval_volume(kg, sd, state, path_flag); + OSLShader::eval_volume(INTEGRATOR_STATE_PASS, sd, path_flag); } else # endif { - svm_eval_nodes(kg, sd, state, NULL, SHADER_TYPE_VOLUME, path_flag); + svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_VOLUME, SHADER_TYPE_VOLUME>( + INTEGRATOR_STATE_PASS, sd, NULL, path_flag); } # endif - /* merge closures to avoid exceeding number of closures limit */ + /* Merge closures to avoid exceeding number of closures limit. */ if (i > 0) - shader_merge_closures(sd); + shader_merge_volume_closures(sd); } } @@ -1314,9 +824,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg, /* Displacement Evaluation */ -ccl_device void shader_eval_displacement(KernelGlobals *kg, - ShaderData *sd, - ccl_addr_space PathState *state) +ccl_device void shader_eval_displacement(INTEGRATOR_STATE_CONST_ARGS, ShaderData *sd) { sd->num_closure = 0; sd->num_closure_left = 0; @@ -1325,11 +833,12 @@ ccl_device void shader_eval_displacement(KernelGlobals *kg, #ifdef __SVM__ # ifdef __OSL__ if (kg->osl) - OSLShader::eval_displacement(kg, sd, state); + OSLShader::eval_displacement(INTEGRATOR_STATE_PASS, sd); else # endif { - svm_eval_nodes(kg, sd, state, NULL, SHADER_TYPE_DISPLACEMENT, 0); + svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_DISPLACEMENT, SHADER_TYPE_DISPLACEMENT>( + INTEGRATOR_STATE_PASS, sd, NULL, 0); } #endif } @@ -1337,29 +846,13 @@ ccl_device void shader_eval_displacement(KernelGlobals *kg, /* Transparent Shadows */ #ifdef __TRANSPARENT_SHADOWS__ -ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect) +ccl_device bool shader_transparent_shadow(const KernelGlobals *kg, Intersection *isect) { - int prim = kernel_tex_fetch(__prim_index, isect->prim); - int shader = 0; - -# ifdef __HAIR__ - if (isect->type & PRIMITIVE_ALL_TRIANGLE) { -# endif - shader = kernel_tex_fetch(__tri_shader, prim); -# ifdef __HAIR__ - } - else { - float4 str = kernel_tex_fetch(__curves, prim); - shader = __float_as_int(str.z); - } -# endif - int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags; - - return (flag & SD_HAS_TRANSPARENT_SHADOW) != 0; + return (intersection_get_shader_flags(kg, isect) & SD_HAS_TRANSPARENT_SHADOW) != 0; } #endif /* __TRANSPARENT_SHADOWS__ */ -ccl_device float shader_cryptomatte_id(KernelGlobals *kg, int shader) +ccl_device float shader_cryptomatte_id(const KernelGlobals *kg, int shader) { return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).cryptomatte_id; } |