Code cleanup: move rng into path state.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 19 Aug 2017 02:11:25 +0000 (04:11 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 19 Aug 2017 16:14:16 +0000 (18:14 +0200)
Also pass by value and don't write back now that it is just a hash for seeding
and no longer an LCG state. Together this makes CUDA a tiny bit faster in my
tests, but mainly simplifies code.

28 files changed:
intern/cycles/kernel/kernel_bake.h
intern/cycles/kernel/kernel_emission.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_path_branched.h
intern/cycles/kernel/kernel_path_common.h
intern/cycles/kernel/kernel_path_state.h
intern/cycles/kernel/kernel_path_subsurface.h
intern/cycles/kernel/kernel_path_surface.h
intern/cycles/kernel/kernel_path_volume.h
intern/cycles/kernel/kernel_random.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_shadow.h
intern/cycles/kernel/kernel_subsurface.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/kernel_volume.h
intern/cycles/kernel/split/kernel_branched.h
intern/cycles/kernel/split/kernel_buffer_update.h
intern/cycles/kernel/split/kernel_direct_lighting.h
intern/cycles/kernel/split/kernel_do_volume.h
intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
intern/cycles/kernel/split/kernel_next_iteration_setup.h
intern/cycles/kernel/split/kernel_path_init.h
intern/cycles/kernel/split/kernel_scene_intersect.h
intern/cycles/kernel/split/kernel_shader_eval.h
intern/cycles/kernel/split/kernel_shadow_blocked_ao.h
intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
intern/cycles/kernel/split/kernel_split_data_types.h
intern/cycles/kernel/split/kernel_subsurface_scatter.h

index f18d145..ea30ee9 100644 (file)
@@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN
 ccl_device_inline void compute_light_pass(KernelGlobals *kg,
                                           ShaderData *sd,
                                           PathRadiance *L,
-                                          RNG rng,
+                                          uint rng_hash,
                                           int pass_filter,
                                           int sample)
 {
@@ -48,11 +48,11 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
        path_radiance_init(&L_sample, kernel_data.film.use_light_pass);
 
        /* init path state */
-       path_state_init(kg, &emission_sd, &state, &rng, sample, NULL);
+       path_state_init(kg, &emission_sd, &state, rng_hash, sample, NULL);
 
        /* evaluate surface shader */
-       float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF);
-       shader_eval_surface(kg, sd, &rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+       float rbsdf = path_state_rng_1D(kg, &state, PRNG_BSDF);
+       shader_eval_surface(kg, sd, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
 
        /* TODO, disable more closures we don't need besides transparent */
        shader_bsdf_disable_transparency(kg, sd);
@@ -64,7 +64,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
 
                /* sample ambient occlusion */
                if(pass_filter & BAKE_FILTER_AO) {
-                       kernel_path_ao(kg, sd, &emission_sd, &L_sample, &state, &rng, throughput, shader_bsdf_alpha(kg, sd));
+                       kernel_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput, shader_bsdf_alpha(kg, sd));
                }
 
                /* sample emission */
@@ -86,7 +86,6 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
                                                          &emission_sd,
                                                          &L_sample,
                                                          &state,
-                                                         &rng,
                                                          &ray,
                                                          &throughput,
                                                          &ss_indirect))
@@ -101,7 +100,6 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
                                        kernel_path_indirect(kg,
                                                             &indirect_sd,
                                                             &emission_sd,
-                                                            &rng,
                                                             &ray,
                                                             throughput,
                                                             state.num_samples,
@@ -116,14 +114,14 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
 
                /* sample light and BSDF */
                if(!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
-                       kernel_path_surface_connect_light(kg, &rng, sd, &emission_sd, throughput, &state, &L_sample);
+                       kernel_path_surface_connect_light(kg, sd, &emission_sd, throughput, &state, &L_sample);
 
-                       if(kernel_path_surface_bounce(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) {
+                       if(kernel_path_surface_bounce(kg, sd, &throughput, &state, &L_sample, &ray)) {
 #ifdef __LAMP_MIS__
                                state.ray_t = 0.0f;
 #endif
                                /* compute indirect light */
-                               kernel_path_indirect(kg, &indirect_sd, &emission_sd, &rng, &ray, throughput, 1, &state, &L_sample);
+                               kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, 1, &state, &L_sample);
 
                                /* sum and reset indirect light pass variables for the next samples */
                                path_radiance_sum_indirect(&L_sample);
@@ -137,7 +135,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
 
                /* sample ambient occlusion */
                if(pass_filter & BAKE_FILTER_AO) {
-                       kernel_branched_path_ao(kg, sd, &emission_sd, &L_sample, &state, &rng, throughput);
+                       kernel_branched_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput);
                }
 
                /* sample emission */
@@ -151,7 +149,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
                if((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
                        /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
                        kernel_branched_path_subsurface_scatter(kg, sd, &indirect_sd,
-                               &emission_sd, &L_sample, &state, &rng, &ray, throughput);
+                               &emission_sd, &L_sample, &state, &ray, throughput);
                }
 #endif
 
@@ -161,13 +159,13 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
                        /* direct light */
                        if(kernel_data.integrator.use_direct_light) {
                                int all = kernel_data.integrator.sample_all_lights_direct;
-                               kernel_branched_path_surface_connect_light(kg, &rng,
+                               kernel_branched_path_surface_connect_light(kg,
                                        sd, &emission_sd, &state, throughput, 1.0f, &L_sample, all);
                        }
 #endif
 
                        /* indirect light */
-                       kernel_branched_path_surface_indirect_light(kg, &rng,
+                       kernel_branched_path_surface_indirect_light(kg,
                                sd, &indirect_sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
                }
        }
@@ -225,7 +223,6 @@ ccl_device_inline float3 kernel_bake_shader_bsdf(KernelGlobals *kg,
 
 ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
                                                        ShaderData *sd,
-                                                       RNG *rng,
                                                        PathState *state,
                                                        float3 direct,
                                                        float3 indirect,
@@ -245,12 +242,12 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
                }
                else {
                        /* surface color of the pass only */
-                       shader_eval_surface(kg, sd, rng, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
+                       shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
                        return kernel_bake_shader_bsdf(kg, sd, type);
                }
        }
        else {
-               shader_eval_surface(kg, sd, rng, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
+               shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
                color = kernel_bake_shader_bsdf(kg, sd, type);
        }
 
@@ -292,14 +289,14 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
        int num_samples = kernel_data.integrator.aa_samples;
 
        /* random number generator */
-       RNG rng = cmj_hash(offset + i, kernel_data.integrator.seed);
+       uint rng_hash = cmj_hash(offset + i, kernel_data.integrator.seed);
 
        float filter_x, filter_y;
        if(sample == 0) {
                filter_x = filter_y = 0.5f;
        }
        else {
-               path_rng_2D(kg, &rng, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
+               path_rng_2D(kg, rng_hash, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
        }
 
        /* subpixel u/v offset */
@@ -335,14 +332,14 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
 
        /* light passes if we need more than color */
        if(pass_filter & ~BAKE_FILTER_COLOR)
-               compute_light_pass(kg, &sd, &L, rng, pass_filter, sample);
+               compute_light_pass(kg, &sd, &L, rng_hash, pass_filter, sample);
 
        switch(type) {
                /* data passes */
                case SHADER_EVAL_NORMAL:
                {
                        if((sd.flag & SD_HAS_BUMP)) {
-                               shader_eval_surface(kg, &sd, &rng, &state, 0.f, 0, SHADER_CONTEXT_MAIN);
+                               shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN);
                        }
 
                        /* compression: normal = (2 * color) - 1 */
@@ -356,7 +353,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
                }
                case SHADER_EVAL_EMISSION:
                {
-                       shader_eval_surface(kg, &sd, &rng, &state, 0.f, 0, SHADER_CONTEXT_EMISSION);
+                       shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_EMISSION);
                        out = shader_emissive_eval(kg, &sd);
                        break;
                }
@@ -409,7 +406,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
                {
                        out = kernel_bake_evaluate_direct_indirect(kg,
                                                                   &sd,
-                                                                  &rng,
                                                                   &state,
                                                                   L.direct_diffuse,
                                                                   L.indirect_diffuse,
@@ -421,7 +417,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
                {
                        out = kernel_bake_evaluate_direct_indirect(kg,
                                                                   &sd,
-                                                                  &rng,
                                                                   &state,
                                                                   L.direct_glossy,
                                                                   L.indirect_glossy,
@@ -433,7 +428,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
                {
                        out = kernel_bake_evaluate_direct_indirect(kg,
                                                                   &sd,
-                                                                  &rng,
                                                                   &state,
                                                                   L.direct_transmission,
                                                                   L.indirect_transmission,
@@ -446,7 +440,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
 #ifdef __SUBSURFACE__
                        out = kernel_bake_evaluate_direct_indirect(kg,
                                                                   &sd,
-                                                                  &rng,
                                                                   &state,
                                                                   L.direct_subsurface,
                                                                   L.indirect_subsurface,
index 36ae970..df63124 100644 (file)
@@ -72,7 +72,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
                /* no path flag, we're evaluating this for all closures. that's weak but
                 * we'd have to do multiple evaluations otherwise */
                path_state_modify_bounce(state, true);
-               shader_eval_surface(kg, emission_sd, NULL, state, 0.0f, 0, SHADER_CONTEXT_EMISSION);
+               shader_eval_surface(kg, emission_sd, state, 0.0f, 0, SHADER_CONTEXT_EMISSION);
                path_state_modify_bounce(state, false);
 
                /* evaluate emissive closure */
index c454228..5fc64b2 100644 (file)
@@ -55,14 +55,13 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
                                         ShaderData *emission_sd,
                                         PathRadiance *L,
                                         ccl_addr_space PathState *state,
-                                        RNG *rng,
                                         float3 throughput,
                                         float3 ao_alpha)
 {
        /* todo: solve correlation */
        float bsdf_u, bsdf_v;
 
-       path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+       path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
 
        float ao_factor = kernel_data.background.ao_factor;
        float3 ao_N;
@@ -101,7 +100,6 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
 ccl_device void kernel_path_indirect(KernelGlobals *kg,
                                      ShaderData *sd,
                                      ShaderData *emission_sd,
-                                     RNG *rng,
                                      Ray *ray,
                                      float3 throughput,
                                      int num_samples,
@@ -200,7 +198,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 
                                        /* direct light sampling */
                                        kernel_branched_path_volume_connect_light(kg,
-                                                                                 rng,
                                                                                  sd,
                                                                                  emission_sd,
                                                                                  throughput,
@@ -213,8 +210,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
                                        /* indirect sample. if we use distance sampling and take just
                                         * one sample for direct and indirect light, we could share
                                         * this computation, but makes code a bit complex */
-                                       float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
-                                       float rscatter = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
+                                       float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE);
+                                       float rscatter = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE);
 
                                        result = kernel_volume_decoupled_scatter(kg,
                                                                                 state,
@@ -233,7 +230,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 
                                if(result == VOLUME_PATH_SCATTERED) {
                                        if(kernel_path_volume_bounce(kg,
-                                                                    rng,
                                                                     sd,
                                                                     &throughput,
                                                                     state,
@@ -255,13 +251,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
                        {
                                /* integrate along volume segment with distance sampling */
                                VolumeIntegrateResult result = kernel_volume_integrate(
-                                       kg, state, sd, &volume_ray, L, &throughput, rng, heterogeneous);
+                                       kg, state, sd, &volume_ray, L, &throughput, heterogeneous);
 
 #  ifdef __VOLUME_SCATTER__
                                if(result == VOLUME_PATH_SCATTERED) {
                                        /* direct lighting */
                                        kernel_path_volume_connect_light(kg,
-                                                                        rng,
                                                                         sd,
                                                                         emission_sd,
                                                                         throughput,
@@ -270,7 +265,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 
                                        /* indirect light bounce */
                                        if(kernel_path_volume_bounce(kg,
-                                                                    rng,
                                                                     sd,
                                                                     &throughput,
                                                                     state,
@@ -309,8 +303,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
                                      sd,
                                      &isect,
                                      ray);
-               float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
-               shader_eval_surface(kg, sd, rng, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
+               float rbsdf = path_state_rng_1D_for_decision(kg, state, PRNG_BSDF);
+               shader_eval_surface(kg, sd, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
 #ifdef __BRANCHED_PATH__
                shader_merge_closures(sd);
 #endif  /* __BRANCHED_PATH__ */
@@ -360,7 +354,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
                        break;
                }
                else if(probability != 1.0f) {
-                       float terminate = path_state_rng_1D_for_decision(kg, rng, state, PRNG_TERMINATE);
+                       float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE);
 
                        if(terminate >= probability)
                                break;
@@ -373,7 +367,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 #ifdef __AO__
                /* ambient occlusion */
                if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
-                       kernel_path_ao(kg, sd, emission_sd, L, state, rng, throughput, make_float3(0.0f, 0.0f, 0.0f));
+                       kernel_path_ao(kg, sd, emission_sd, L, state, throughput, make_float3(0.0f, 0.0f, 0.0f));
                }
 #endif  /* __AO__ */
 
@@ -389,11 +383,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 
                        /* do bssrdf scatter step if we picked a bssrdf closure */
                        if(sc) {
-                               uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
+                               uint lcg_state = lcg_state_init(state, 0x68bc21eb);
 
                                float bssrdf_u, bssrdf_v;
                                path_state_rng_2D(kg,
-                                                 rng,
                                                  state,
                                                  PRNG_BSDF_U,
                                                  &bssrdf_u, &bssrdf_v);
@@ -414,7 +407,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
                        int all = (kernel_data.integrator.sample_all_lights_indirect) ||
                                  (state->flag & PATH_RAY_SHADOW_CATCHER);
                        kernel_branched_path_surface_connect_light(kg,
-                                                                  rng,
                                                                   sd,
                                                                   emission_sd,
                                                                   state,
@@ -425,7 +417,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
                }
 #endif  /* defined(__EMISSION__) */
 
-               if(!kernel_path_surface_bounce(kg, rng, sd, &throughput, state, L, ray))
+               if(!kernel_path_surface_bounce(kg, sd, &throughput, state, L, ray))
                        break;
        }
 }
@@ -433,7 +425,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 #endif /* defined(__BRANCHED_PATH__) || defined(__BAKING__) */
 
 ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
-                                             RNG *rng,
+                                             uint rng_hash,
                                              int sample,
                                              Ray ray,
                                              ccl_global float *buffer,
@@ -451,7 +443,7 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
        ShaderData emission_sd;
 
        PathState state;
-       path_state_init(kg, &emission_sd, &state, rng, sample, &ray);
+       path_state_init(kg, &emission_sd, &state, rng_hash, sample, &ray);
 
 #ifdef __SUBSURFACE__
        SubsurfaceIndirectRays ss_indirect;
@@ -478,7 +470,7 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
                        }
 
                        extmax = kernel_data.curve.maximum_width;
-                       lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d);
+                       lcg_state = lcg_state_init(&state, 0x51633e2d);
                }
 
                if(state.bounce > kernel_data.integrator.ao_bounces) {
@@ -558,15 +550,15 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
                                        int all = false;
 
                                        /* direct light sampling */
-                                       kernel_branched_path_volume_connect_light(kg, rng, &sd,
+                                       kernel_branched_path_volume_connect_light(kg, &sd,
                                                &emission_sd, throughput, &state, L, all,
                                                &volume_ray, &volume_segment);
 
                                        /* indirect sample. if we use distance sampling and take just
                                         * one sample for direct and indirect light, we could share
                                         * this computation, but makes code a bit complex */
-                                       float rphase = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_PHASE);
-                                       float rscatter = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_SCATTER_DISTANCE);
+                                       float rphase = path_state_rng_1D_for_decision(kg, &state, PRNG_PHASE);
+                                       float rscatter = path_state_rng_1D_for_decision(kg, &state, PRNG_SCATTER_DISTANCE);
 
                                        result = kernel_volume_decoupled_scatter(kg,
                                                &state, &volume_ray, &sd, &throughput,
@@ -577,7 +569,7 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
                                kernel_volume_decoupled_free(kg, &volume_segment);
 
                                if(result == VOLUME_PATH_SCATTERED) {
-                                       if(kernel_path_volume_bounce(kg, rng, &sd, &throughput, &state, L, &ray))
+                                       if(kernel_path_volume_bounce(kg, &sd, &throughput, &state, L, &ray))
                                                continue;
                                        else
                                                break;
@@ -591,15 +583,15 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
                        {
                                /* integrate along volume segment with distance sampling */
                                VolumeIntegrateResult result = kernel_volume_integrate(
-                                       kg, &state, &sd, &volume_ray, L, &throughput, rng, heterogeneous);
+                                       kg, &state, &sd, &volume_ray, L, &throughput, heterogeneous);
 
 #  ifdef __VOLUME_SCATTER__
                                if(result == VOLUME_PATH_SCATTERED) {
                                        /* direct lighting */
-                                       kernel_path_volume_connect_light(kg, rng, &sd, &emission_sd, throughput, &state, L);
+                                       kernel_path_volume_connect_light(kg, &sd, &emission_sd, throughput, &state, L);
 
                                        /* indirect light bounce */
-                                       if(kernel_path_volume_bounce(kg, rng, &sd, &throughput, &state, L, &ray))
+                                       if(kernel_path_volume_bounce(kg, &sd, &throughput, &state, L, &ray))
                                                continue;
                                        else
                                                break;
@@ -634,8 +626,8 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
 
                /* setup shading */
                shader_setup_from_ray(kg, &sd, &isect, &ray);
-               float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF);
-               shader_eval_surface(kg, &sd, rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+               float rbsdf = path_state_rng_1D_for_decision(kg, &state, PRNG_BSDF);
+               shader_eval_surface(kg, &sd, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
 
 #ifdef __SHADOW_TRICKS__
                if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
@@ -713,7 +705,7 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
                        break;
                }
                else if(probability != 1.0f) {
-                       float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE);
+                       float terminate = path_state_rng_1D_for_decision(kg, &state, PRNG_TERMINATE);
                        if(terminate >= probability)
                                break;
 
@@ -725,7 +717,7 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
 #ifdef __AO__
                /* ambient occlusion */
                if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
-                       kernel_path_ao(kg, &sd, &emission_sd, L, &state, rng, throughput, shader_bsdf_alpha(kg, &sd));
+                       kernel_path_ao(kg, &sd, &emission_sd, L, &state, throughput, shader_bsdf_alpha(kg, &sd));
                }
 #endif  /* __AO__ */
 
@@ -738,7 +730,6 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
                                                          &emission_sd,
                                                          L,
                                                          &state,
-                                                         rng,
                                                          &ray,
                                                          &throughput,
                                                          &ss_indirect))
@@ -749,10 +740,10 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
 #endif  /* __SUBSURFACE__ */
 
                /* direct lighting */
-               kernel_path_surface_connect_light(kg, rng, &sd, &emission_sd, throughput, &state, L);
+               kernel_path_surface_connect_light(kg, &sd, &emission_sd, throughput, &state, L);
 
                /* compute direct lighting and next bounce */
-               if(!kernel_path_surface_bounce(kg, rng, &sd, &throughput, &state, L, &ray))
+               if(!kernel_path_surface_bounce(kg, &sd, &throughput, &state, L, &ray))
                        break;
        }
 
@@ -793,17 +784,17 @@ ccl_device void kernel_path_trace(KernelGlobals *kg,
        buffer += index*pass_stride;
 
        /* initialize random numbers and ray */
-       RNG rng;
+       uint rng_hash;
        Ray ray;
 
-       kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray);
+       kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng_hash, &ray);
 
        /* integrate */
        PathRadiance L;
        bool is_shadow_catcher;
 
        if(ray.t != 0.0f) {
-               kernel_path_integrate(kg, &rng, sample, ray, buffer, &L, &is_shadow_catcher);
+               kernel_path_integrate(kg, rng_hash, sample, ray, buffer, &L, &is_shadow_catcher);
                kernel_write_result(kg, buffer, sample, &L, is_shadow_catcher);
        }
        else {
index abc291b..bce8d36 100644 (file)
@@ -23,7 +23,6 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
                                                ShaderData *emission_sd,
                                                PathRadiance *L,
                                                ccl_addr_space PathState *state,
-                                               RNG *rng,
                                                float3 throughput)
 {
        int num_samples = kernel_data.integrator.ao_samples;
@@ -35,7 +34,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
 
        for(int j = 0; j < num_samples; j++) {
                float bsdf_u, bsdf_v;
-               path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+               path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
 
                float3 ao_D;
                float ao_pdf;
@@ -69,7 +68,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
 
 /* bounce off surface and integrate indirect light */
 ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg,
-       RNG *rng, ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd,
+       ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd,
        float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L)
 {
        float sum_sample_weight = 0.0f;
@@ -113,7 +112,6 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
                num_samples = ceil_to_int(num_samples_adjust*num_samples);
 
                float num_samples_inv = num_samples_adjust/num_samples;
-               RNG bsdf_rng = cmj_hash(*rng, i);
 
                for(int j = 0; j < num_samples; j++) {
                        PathState ps = *state;
@@ -123,8 +121,9 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
                        float shadow_transparency = L->shadow_transparency;
 #endif
 
+                       ps.rng_hash = cmj_hash(state->rng_hash, i);
+
                        if(!kernel_branched_path_surface_bounce(kg,
-                                                               &bsdf_rng,
                                                                sd,
                                                                sc,
                                                                j,
@@ -138,10 +137,11 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
                                continue;
                        }
 
+                       ps.rng_hash = state->rng_hash;
+
                        kernel_path_indirect(kg,
                                             indirect_sd,
                                             emission_sd,
-                                            rng,
                                             &bsdf_ray,
                                             tp*num_samples_inv,
                                             num_samples,
@@ -167,7 +167,6 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                                                         ShaderData *emission_sd,
                                                         PathRadiance *L,
                                                         PathState *state,
-                                                        RNG *rng,
                                                         Ray *ray,
                                                         float3 throughput)
 {
@@ -178,17 +177,17 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                        continue;
 
                /* set up random number generator */
-               uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
+               uint lcg_state = lcg_state_init(state, 0x68bc21eb);
                int num_samples = kernel_data.integrator.subsurface_samples;
                float num_samples_inv = 1.0f/num_samples;
-               RNG bssrdf_rng = cmj_hash(*rng, i);
+               uint bssrdf_rng_hash = cmj_hash(state->rng_hash, i);
 
                /* 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;
                        float bssrdf_u, bssrdf_v;
-                       path_branched_rng_2D(kg, &bssrdf_rng, state, j, num_samples, PRNG_BSDF_U, &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,
                                                                          &ss_isect,
                                                                          sd,
@@ -241,7 +240,6 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                                                  (state->flag & PATH_RAY_SHADOW_CATCHER);
                                        kernel_branched_path_surface_connect_light(
                                                kg,
-                                               rng,
                                                &bssrdf_sd,
                                                emission_sd,
                                                &hit_state,
@@ -255,7 +253,6 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
                                /* indirect light */
                                kernel_branched_path_surface_indirect_light(
                                        kg,
-                                       rng,
                                        &bssrdf_sd,
                                        indirect_sd,
                                        emission_sd,
@@ -270,7 +267,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
 #endif  /* __SUBSURFACE__ */
 
 ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
-                                               RNG *rng,
+                                               uint rng_hash,
                                                int sample,
                                                Ray ray,
                                                ccl_global float *buffer,
@@ -288,7 +285,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
        ShaderData emission_sd, indirect_sd;
 
        PathState state;
-       path_state_init(kg, &emission_sd, &state, rng, sample, &ray);
+       path_state_init(kg, &emission_sd, &state, rng_hash, sample, &ray);
 
        /* Main Loop
         * Here we only handle transparency intersections from the camera ray.
@@ -311,7 +308,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                        }
 
                        extmax = kernel_data.curve.maximum_width;
-                       lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d);
+                       lcg_state = lcg_state_init(&state, 0x51633e2d);
                }
 
                bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
@@ -354,7 +351,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
 
                                int all = kernel_data.integrator.sample_all_lights_direct;
 
-                               kernel_branched_path_volume_connect_light(kg, rng, &sd,
+                               kernel_branched_path_volume_connect_light(kg, &sd,
                                        &emission_sd, throughput, &state, L, all,
                                        &volume_ray, &volume_segment);
 
@@ -373,8 +370,8 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                                        /* scatter sample. if we use distance sampling and take just one
                                         * sample for direct and indirect light, we could share this
                                         * computation, but makes code a bit complex */
-                                       float rphase = path_state_rng_1D_for_decision(kg, rng, &ps, PRNG_PHASE);
-                                       float rscatter = path_state_rng_1D_for_decision(kg, rng, &ps, PRNG_SCATTER_DISTANCE);
+                                       float rphase = path_state_rng_1D_for_decision(kg, &ps, PRNG_PHASE);
+                                       float rscatter = path_state_rng_1D_for_decision(kg, &ps, PRNG_SCATTER_DISTANCE);
 
                                        VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
                                                &ps, &pray, &sd, &tp, rphase, rscatter, &volume_segment, NULL, false);
@@ -383,7 +380,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                                        kernel_assert(result == VOLUME_PATH_SCATTERED);
 
                                        if(kernel_path_volume_bounce(kg,
-                                                                    rng,
                                                                     &sd,
                                                                     &tp,
                                                                     &ps,
@@ -393,7 +389,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                                                kernel_path_indirect(kg,
                                                                     &indirect_sd,
                                                                     &emission_sd,
-                                                                    rng,
                                                                     &pray,
                                                                     tp*num_samples_inv,
                                                                     num_samples,
@@ -432,16 +427,15 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                                path_state_branch(&ps, j, num_samples);
 
                                VolumeIntegrateResult result = kernel_volume_integrate(
-                                       kg, &ps, &sd, &volume_ray, L, &tp, rng, heterogeneous);
+                                       kg, &ps, &sd, &volume_ray, L, &tp, heterogeneous);
 
 #ifdef __VOLUME_SCATTER__
                                if(result == VOLUME_PATH_SCATTERED) {
                                        /* todo: support equiangular, MIS and all light sampling.
                                         * alternatively get decoupled ray marching working on the GPU */
-                                       kernel_path_volume_connect_light(kg, rng, &sd, &emission_sd, tp, &state, L);
+                                       kernel_path_volume_connect_light(kg, &sd, &emission_sd, tp, &state, L);
 
                                        if(kernel_path_volume_bounce(kg,
-                                                                    rng,
                                                                     &sd,
                                                                     &tp,
                                                                     &ps,
@@ -451,7 +445,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                                                kernel_path_indirect(kg,
                                                                     &indirect_sd,
                                                                     &emission_sd,
-                                                                    rng,
                                                                     &pray,
                                                                     tp,
                                                                     num_samples,
@@ -495,7 +488,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
 
                /* setup shading */
                shader_setup_from_ray(kg, &sd, &isect, &ray);
-               shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
+               shader_eval_surface(kg, &sd, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
                shader_merge_closures(&sd);
 
 #ifdef __SHADOW_TRICKS__
@@ -558,7 +551,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                                break;
                        }
                        else if(probability != 1.0f) {
-                               float terminate = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_TERMINATE);
+                               float terminate = path_state_rng_1D_for_decision(kg, &state, PRNG_TERMINATE);
 
                                if(terminate >= probability)
                                        break;
@@ -572,7 +565,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
 #ifdef __AO__
                /* ambient occlusion */
                if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
-                       kernel_branched_path_ao(kg, &sd, &emission_sd, L, &state, rng, throughput);
+                       kernel_branched_path_ao(kg, &sd, &emission_sd, L, &state, throughput);
                }
 #endif  /* __AO__ */
 
@@ -580,7 +573,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                /* bssrdf scatter to a different location on the same object */
                if(sd.flag & SD_BSSRDF) {
                        kernel_branched_path_subsurface_scatter(kg, &sd, &indirect_sd, &emission_sd,
-                                                               L, &state, rng, &ray, throughput);
+                                                               L, &state, &ray, throughput);
                }
 #endif  /* __SUBSURFACE__ */
 
@@ -592,13 +585,13 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
                        if(kernel_data.integrator.use_direct_light) {
                                int all = (kernel_data.integrator.sample_all_lights_direct) ||
                                          (state.flag & PATH_RAY_SHADOW_CATCHER);
-                               kernel_branched_path_surface_connect_light(kg, rng,
+                               kernel_branched_path_surface_connect_light(kg,
                                        &sd, &emission_sd, &hit_state, throughput, 1.0f, L, all);
                        }
 #endif  /* __EMISSION__ */
 
                        /* indirect light */
-                       kernel_branched_path_surface_indirect_light(kg, rng,
+                       kernel_branched_path_surface_indirect_light(kg,
                                &sd, &indirect_sd, &emission_sd, throughput, 1.0f, &hit_state, L);
 
                        /* continue in case of transparency */
@@ -645,17 +638,17 @@ ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
        buffer += index*pass_stride;
 
        /* initialize random numbers and ray */
-       RNG rng;
+       uint rng_hash;
        Ray ray;
 
-       kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray);
+       kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng_hash, &ray);
 
        /* integrate */
        PathRadiance L;
        bool is_shadow_catcher;
 
        if(ray.t != 0.0f) {
-               kernel_branched_path_integrate(kg, &rng, sample, ray, buffer, &L, &is_shadow_catcher);
+               kernel_branched_path_integrate(kg, rng_hash, sample, ray, buffer, &L, &is_shadow_catcher);
                kernel_write_result(kg, buffer, sample, &L, is_shadow_catcher);
        }
        else {
index 82f83de..54dd278 100644 (file)
@@ -22,7 +22,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
                                                ccl_global uint *rng_state,
                                                int sample,
                                                int x, int y,
-                                               RNG *rng,
+                                               uint *rng_hash,
                                                ccl_addr_space Ray *ray)
 {
        float filter_u;
@@ -34,20 +34,20 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
                *rng_state = hash_int_2d(x, y);
        }
 
-       path_rng_init(kg, rng_state, sample, num_samples, rng, x, y, &filter_u, &filter_v);
+       path_rng_init(kg, rng_state, sample, num_samples, rng_hash, x, y, &filter_u, &filter_v);
 
        /* sample camera ray */
 
        float lens_u = 0.0f, lens_v = 0.0f;
 
        if(kernel_data.cam.aperturesize > 0.0f)
-               path_rng_2D(kg, rng, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v);
+               path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v);
 
        float time = 0.0f;
 
 #ifdef __CAMERA_MOTION__
        if(kernel_data.cam.shuttertime != -1.0f)
-               time = path_rng_1D(kg, rng, sample, num_samples, PRNG_TIME);
+               time = path_rng_1D(kg, *rng_hash, sample, num_samples, PRNG_TIME);
 #endif
 
        camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, ray);
index 28582de..b539224 100644 (file)
@@ -19,12 +19,13 @@ CCL_NAMESPACE_BEGIN
 ccl_device_inline void path_state_init(KernelGlobals *kg,
                                        ShaderData *stack_sd,
                                        ccl_addr_space PathState *state,
-                                       RNG *rng,
+                                       uint rng_hash,
                                        int sample,
                                        ccl_addr_space Ray *ray)
 {
        state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP;
 
+       state->rng_hash = rng_hash;
        state->rng_offset = PRNG_BASE_NUM;
        state->sample = sample;
        state->num_samples = kernel_data.integrator.aa_samples;
@@ -58,7 +59,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg,
                /* Initialize volume stack with volume we are inside of. */
                kernel_volume_stack_init(kg, stack_sd, state, ray, state->volume_stack);
                /* Seed RNG for cases where we can't use stratified samples .*/
-               state->rng_congruential = lcg_init(*rng + sample*0x51633e2d);
+               state->rng_congruential = lcg_init(rng_hash + sample*0x51633e2d);
        }
        else {
                state->volume_stack[0].shader = SHADER_NONE;
index 10b568a..5fce5ed 100644 (file)
@@ -28,7 +28,6 @@ bool kernel_path_subsurface_scatter(
         ShaderData *emission_sd,
         PathRadiance *L,
         ccl_addr_space PathState *state,
-        RNG *rng,
         ccl_addr_space Ray *ray,
         ccl_addr_space float3 *throughput,
         ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
@@ -47,11 +46,11 @@ bool kernel_path_subsurface_scatter(
                 */
                kernel_assert(!ss_indirect->tracing);
 
-               uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
+               uint lcg_state = lcg_state_init(state, 0x68bc21eb);
 
                SubsurfaceIntersection ss_isect;
                float bssrdf_u, bssrdf_v;
-               path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+               path_state_rng_2D(kg, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
                int num_hits = subsurface_scatter_multi_intersect(kg,
                                                                  &ss_isect,
                                                                  sd,
@@ -94,10 +93,9 @@ bool kernel_path_subsurface_scatter(
                        hit_L->direct_throughput = L->direct_throughput;
                        path_radiance_copy_indirect(hit_L, L);
 
-                       kernel_path_surface_connect_light(kg, rng, sd, emission_sd, *hit_tp, state, hit_L);
+                       kernel_path_surface_connect_light(kg, sd, emission_sd, *hit_tp, state, hit_L);
 
                        if(kernel_path_surface_bounce(kg,
-                                                     rng,
                                                      sd,
                                                      hit_tp,
                                                      hit_state,
index dcb577e..3d10736 100644 (file)
@@ -20,7 +20,6 @@ CCL_NAMESPACE_BEGIN
 /* branched path tracing: connect path directly to position on one or more lights and add it to L */
 ccl_device_noinline void kernel_branched_path_surface_connect_light(
         KernelGlobals *kg,
-        RNG *rng,
         ShaderData *sd,
         ShaderData *emission_sd,
         ccl_addr_space PathState *state,
@@ -50,12 +49,12 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
 
                        int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i));
                        float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
-                       RNG lamp_rng = cmj_hash(*rng, i);
+                       uint lamp_rng_hash = cmj_hash(state->rng_hash, i);
 
                        for(int j = 0; j < num_samples; j++) {
                                float light_u, light_v;
-                               path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
-                               float terminate = path_branched_rng_light_termination(kg, &lamp_rng, state, j, num_samples);
+                               path_branched_rng_2D(kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+                               float terminate = path_branched_rng_light_termination(kg, lamp_rng_hash, state, j, num_samples);
 
                                LightSample ls;
                                if(lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
@@ -86,10 +85,10 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
                        float num_samples_inv = num_samples_adjust/num_samples;
 
                        for(int j = 0; j < num_samples; j++) {
-                               float light_t = path_branched_rng_1D(kg, rng, state, j, num_samples, PRNG_LIGHT);
+                               float light_t = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT);
                                float light_u, light_v;
-                               path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
-                               float terminate = path_branched_rng_light_termination(kg, rng, state, j, num_samples);
+                               path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+                               float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
 
                                /* only sample triangle lights */
                                if(kernel_data.integrator.num_all_lights)
@@ -119,10 +118,10 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
        }
        else {
                /* sample one light at random */
-               float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+               float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
                float light_u, light_v;
-               path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
-               float terminate = path_state_rng_light_termination(kg, rng, state);
+               path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+               float terminate = path_state_rng_light_termination(kg, state);
 
                LightSample ls;
                if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
@@ -147,7 +146,6 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
 /* branched path tracing: bounce off or through surface to with new direction stored in ray */
 ccl_device bool kernel_branched_path_surface_bounce(
         KernelGlobals *kg,
-        RNG *rng,
         ShaderData *sd,
         const ShaderClosure *sc,
         int sample,
@@ -164,7 +162,7 @@ ccl_device bool kernel_branched_path_surface_bounce(
        float3 bsdf_omega_in;
        differential3 bsdf_domega_in;
        float bsdf_u, bsdf_v;
-       path_branched_rng_2D(kg, rng, state, sample, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+       path_branched_rng_2D(kg, state->rng_hash, state, sample, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
        int label;
 
        label = shader_bsdf_sample_closure(kg, sd, sc, bsdf_u, bsdf_v, &bsdf_eval,
@@ -217,7 +215,7 @@ ccl_device bool kernel_branched_path_surface_bounce(
 #endif
 
 /* path tracing: connect path directly to position on a light and add it to L */
-ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG *rng,
+ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg,
        ShaderData *sd, ShaderData *emission_sd, float3 throughput, ccl_addr_space PathState *state,
        PathRadiance *L)
 {
@@ -228,7 +226,6 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
 #ifdef __SHADOW_TRICKS__
        if(state->flag & PATH_RAY_SHADOW_CATCHER) {
                kernel_branched_path_surface_connect_light(kg,
-                                                          rng,
                                                           sd,
                                                           emission_sd,
                                                           state,
@@ -241,9 +238,9 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
 #endif
 
        /* sample illumination from lights to find path contribution */
-       float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+       float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
        float light_u, light_v;
-       path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+       path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
 
        Ray light_ray;
        BsdfEval L_light;
@@ -255,7 +252,7 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
 
        LightSample ls;
        if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
-               float terminate = path_state_rng_light_termination(kg, rng, state);
+               float terminate = path_state_rng_light_termination(kg, state);
                if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
                        /* trace shadow ray */
                        float3 shadow;
@@ -274,7 +271,6 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG
 
 /* path tracing: bounce off or through surface to with new direction stored in ray */
 ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
-                                           RNG *rng,
                                            ShaderData *sd,
                                            ccl_addr_space float3 *throughput,
                                            ccl_addr_space PathState *state,
@@ -289,7 +285,7 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
                float3 bsdf_omega_in;
                differential3 bsdf_domega_in;
                float bsdf_u, bsdf_v;
-               path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+               path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
                int label;
 
                label = shader_bsdf_sample(kg, sd, bsdf_u, bsdf_v, &bsdf_eval,
index dcedf51..3661432 100644 (file)
@@ -20,7 +20,6 @@ CCL_NAMESPACE_BEGIN
 
 ccl_device_inline void kernel_path_volume_connect_light(
         KernelGlobals *kg,
-        RNG *rng,
         ShaderData *sd,
         ShaderData *emission_sd,
         float3 throughput,
@@ -32,9 +31,9 @@ ccl_device_inline void kernel_path_volume_connect_light(
                return;
 
        /* sample illumination from lights to find path contribution */
-       float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+       float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
        float light_u, light_v;
-       path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+       path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
 
        Ray light_ray;
        BsdfEval L_light;
@@ -48,7 +47,7 @@ ccl_device_inline void kernel_path_volume_connect_light(
 
        if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls))
        {
-               float terminate = path_state_rng_light_termination(kg, rng, state);
+               float terminate = path_state_rng_light_termination(kg, state);
                if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
                        /* trace shadow ray */
                        float3 shadow;
@@ -69,7 +68,6 @@ ccl_device
 #endif
 bool kernel_path_volume_bounce(
     KernelGlobals *kg,
-    RNG *rng,
     ShaderData *sd,
     ccl_addr_space float3 *throughput,
     ccl_addr_space PathState *state,
@@ -82,7 +80,7 @@ bool kernel_path_volume_bounce(
        float3 phase_omega_in;
        differential3 phase_domega_in;
        float phase_u, phase_v;
-       path_state_rng_2D(kg, rng, state, PRNG_PHASE_U, &phase_u, &phase_v);
+       path_state_rng_2D(kg, state, PRNG_PHASE_U, &phase_u, &phase_v);
        int label;
 
        label = shader_volume_phase_sample(kg, sd, phase_u, phase_v, &phase_eval,
@@ -120,7 +118,6 @@ bool kernel_path_volume_bounce(
 #ifndef __SPLIT_KERNEL__
 ccl_device void kernel_branched_path_volume_connect_light(
         KernelGlobals *kg,
-        RNG *rng,
         ShaderData *sd,
         ShaderData *emission_sd,
         float3 throughput,
@@ -150,12 +147,12 @@ ccl_device void kernel_branched_path_volume_connect_light(
 
                        int num_samples = light_select_num_samples(kg, i);
                        float num_samples_inv = 1.0f/(num_samples*kernel_data.integrator.num_all_lights);
-                       RNG lamp_rng = cmj_hash(*rng, i);
+                       uint lamp_rng_hash = cmj_hash(state->rng_hash, i);
 
                        for(int j = 0; j < num_samples; j++) {
                                /* sample random position on given light */
                                float light_u, light_v;
-                               path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+                               path_branched_rng_2D(kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
 
                                LightSample ls;
                                lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
@@ -163,8 +160,8 @@ ccl_device void kernel_branched_path_volume_connect_light(
                                float3 tp = throughput;
 
                                /* sample position on volume segment */
-                               float rphase = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_PHASE);
-                               float rscatter = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_SCATTER_DISTANCE);
+                               float rphase = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE);
+                               float rscatter = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
 
                                VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
                                        state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
@@ -177,7 +174,7 @@ ccl_device void kernel_branched_path_volume_connect_light(
                                        if(kernel_data.integrator.pdf_triangles != 0.0f)
                                                ls.pdf *= 2.0f;
 
-                                       float terminate = path_branched_rng_light_termination(kg, rng, state, j, num_samples);
+                                       float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
                                        if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
                                                /* trace shadow ray */
                                                float3 shadow;
@@ -198,9 +195,9 @@ ccl_device void kernel_branched_path_volume_connect_light(
 
                        for(int j = 0; j < num_samples; j++) {
                                /* sample random position on random triangle */
-                               float light_t = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_LIGHT);
+                               float light_t = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT);
                                float light_u, light_v;
-                               path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+                               path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
 
                                /* only sample triangle lights */
                                if(kernel_data.integrator.num_all_lights)
@@ -212,8 +209,8 @@ ccl_device void kernel_branched_path_volume_connect_light(
                                float3 tp = throughput;
 
                                /* sample position on volume segment */
-                               float rphase = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_PHASE);
-                               float rscatter = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_SCATTER_DISTANCE);
+                               float rphase = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE);
+                               float rscatter = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
 
                                VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
                                        state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
@@ -226,7 +223,7 @@ ccl_device void kernel_branched_path_volume_connect_light(
                                        if(kernel_data.integrator.num_all_lights)
                                                ls.pdf *= 2.0f;
 
-                                       float terminate = path_branched_rng_light_termination(kg, rng, state, j, num_samples);
+                                       float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
                                        if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
                                                /* trace shadow ray */
                                                float3 shadow;
@@ -242,9 +239,9 @@ ccl_device void kernel_branched_path_volume_connect_light(
        }
        else {
                /* sample random position on random light */
-               float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+               float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
                float light_u, light_v;
-               path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+               path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
 
                LightSample ls;
                light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
@@ -252,8 +249,8 @@ ccl_device void kernel_branched_path_volume_connect_light(
                float3 tp = throughput;
 
                /* sample position on volume segment */
-               float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
-               float rscatter = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
+               float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE);
+               float rscatter = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE);
 
                VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
                        state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
@@ -264,7 +261,7 @@ ccl_device void kernel_branched_path_volume_connect_light(
                /* todo: split up light_sample so we don't have to call it again with new position */
                if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
                        /* sample random light */
-                       float terminate = path_state_rng_light_termination(kg, rng, state);
+                       float terminate = path_state_rng_light_termination(kg, state);
                        if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
                                /* trace shadow ray */
                                float3 shadow;
index 073011a..459333f 100644 (file)
@@ -52,7 +52,7 @@ ccl_device uint sobol_dimension(KernelGlobals *kg, int index, int dimension)
 
 
 ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
-                                         RNG *rng,
+                                         uint rng_hash,
                                          int sample, int num_samples,
                                          int dimension)
 {
@@ -66,7 +66,7 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
 #  endif
        {
                /* Correlated multi-jitter. */
-               int p = *rng + dimension;
+               int p = rng_hash + dimension;
                return cmj_sample_1D(sample, num_samples, p);
        }
 #endif
@@ -82,7 +82,7 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
        /* Hash rng with dimension to solve correlation issues.
         * See T38710, T50116.
         */
-       RNG tmp_rng = cmj_hash_simple(dimension, *rng);
+       uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
        shift = tmp_rng * (1.0f/(float)0xFFFFFFFF);
 
        return r + shift - floorf(r + shift);
@@ -90,7 +90,7 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
 }
 
 ccl_device_forceinline void path_rng_2D(KernelGlobals *kg,
-                                        RNG *rng,
+                                        uint rng_hash,
                                         int sample, int num_samples,
                                         int dimension,
                                         float *fx, float *fy)
@@ -107,7 +107,7 @@ ccl_device_forceinline void path_rng_2D(KernelGlobals *kg,
 #  endif
        {
                /* Correlated multi-jitter. */
-               int p = *rng + dimension;
+               int p = rng_hash + dimension;
                cmj_sample_2D(sample, num_samples, p, fx, fy);
                return;
        }
@@ -115,24 +115,24 @@ ccl_device_forceinline void path_rng_2D(KernelGlobals *kg,
 
 #ifdef __SOBOL__
        /* Sobol. */
-       *fx = path_rng_1D(kg, rng, sample, num_samples, dimension);
-       *fy = path_rng_1D(kg, rng, sample, num_samples, dimension + 1);
+       *fx = path_rng_1D(kg, rng_hash, sample, num_samples, dimension);
+       *fy = path_rng_1D(kg, rng_hash, sample, num_samples, dimension + 1);
 #endif
 }
 
 ccl_device_inline void path_rng_init(KernelGlobals *kg,
                                      ccl_global uint *rng_state,
                                      int sample, int num_samples,
-                                     RNG *rng,
+                                     uint *rng_hash,
                                      int x, int y,
                                      float *fx, float *fy)
 {
        /* load state */
-       *rng = *rng_state;
-       *rng ^= kernel_data.integrator.seed;
+       *rng_hash = *rng_state;
+       *rng_hash ^= kernel_data.integrator.seed;
 
 #ifdef __DEBUG_CORRELATION__
-       srand48(*rng + sample);
+       srand48(*rng_hash + sample);
 #endif
 
        if(sample == 0) {
@@ -140,7 +140,7 @@ ccl_device_inline void path_rng_init(KernelGlobals *kg,
                *fy = 0.5f;
        }
        else {
-               path_rng_2D(kg, rng, sample, num_samples, PRNG_FILTER_U, fx, fy);
+               path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_FILTER_U, fx, fy);
        }
 }
 
@@ -177,19 +177,17 @@ ccl_device uint lcg_init(uint seed)
  */
 
 ccl_device_inline float path_state_rng_1D(KernelGlobals *kg,
-                                          RNG *rng,
                                           const ccl_addr_space PathState *state,
                                           int dimension)
 {
        return path_rng_1D(kg,
-                          rng,
+                          state->rng_hash,
                           state->sample, state->num_samples,
                           state->rng_offset + dimension);
 }
 
 ccl_device_inline float path_state_rng_1D_for_decision(
         KernelGlobals *kg,
-        RNG *rng,
         const ccl_addr_space PathState *state,
         int dimension)
 {
@@ -202,19 +200,18 @@ ccl_device_inline float path_state_rng_1D_for_decision(
         * the same decision. */
        const int rng_offset = state->rng_offset + state->transparent_bounce * PRNG_BOUNCE_NUM;
        return path_rng_1D(kg,
-                          rng,
+                          state->rng_hash,
                           state->sample, state->num_samples,
                           rng_offset + dimension);
 }
 
 ccl_device_inline void path_state_rng_2D(KernelGlobals *kg,
-                                         RNG *rng,
                                          const ccl_addr_space PathState *state,
                                          int dimension,
                                          float *fx, float *fy)
 {
        path_rng_2D(kg,
-                   rng,
+                   state->rng_hash,
                    state->sample, state->num_samples,
                    state->rng_offset + dimension,
                    fx, fy);
@@ -222,14 +219,14 @@ ccl_device_inline void path_state_rng_2D(KernelGlobals *kg,
 
 ccl_device_inline float path_branched_rng_1D(
         KernelGlobals *kg,
-        RNG *rng,
+        uint rng_hash,
         const ccl_addr_space PathState *state,
         int branch,
         int num_branches,
         int dimension)
 {
        return path_rng_1D(kg,
-                          rng,
+                          rng_hash,
                           state->sample * num_branches + branch,
                           state->num_samples * num_branches,
                           state->rng_offset + dimension);
@@ -237,7 +234,7 @@ ccl_device_inline float path_branched_rng_1D(
 
 ccl_device_inline float path_branched_rng_1D_for_decision(
         KernelGlobals *kg,
-        RNG *rng,
+        uint rng_hash,
         const ccl_addr_space PathState *state,
         int branch,
         int num_branches,
@@ -245,7 +242,7 @@ ccl_device_inline float path_branched_rng_1D_for_decision(
 {
        const int rng_offset = state->rng_offset + state->transparent_bounce * PRNG_BOUNCE_NUM;
        return path_rng_1D(kg,
-                          rng,
+                          rng_hash,
                           state->sample * num_branches + branch,
                           state->num_samples * num_branches,
                           rng_offset + dimension);
@@ -253,7 +250,7 @@ ccl_device_inline float path_branched_rng_1D_for_decision(
 
 ccl_device_inline void path_branched_rng_2D(
         KernelGlobals *kg,
-        RNG *rng,
+        uint rng_hash,
         const ccl_addr_space PathState *state,
         int branch,
         int num_branches,
@@ -261,7 +258,7 @@ ccl_device_inline void path_branched_rng_2D(
         float *fx, float *fy)
 {
        path_rng_2D(kg,
-                   rng,
+                   rng_hash,
                    state->sample * num_branches + branch,
                    state->num_samples * num_branches,
                    state->rng_offset + dimension,
@@ -273,25 +270,24 @@ ccl_device_inline void path_branched_rng_2D(
  */
 ccl_device_inline float path_state_rng_light_termination(
         KernelGlobals *kg,
-        RNG *rng,
         const ccl_addr_space PathState *state)
 {
        if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
-               return path_state_rng_1D_for_decision(kg, rng, state, PRNG_LIGHT_TERMINATE);
+               return path_state_rng_1D_for_decision(kg, state, PRNG_LIGHT_TERMINATE);
        }
        return 0.0f;
 }
 
 ccl_device_inline float path_branched_rng_light_termination(
         KernelGlobals *kg,
-        RNG *rng,
+        uint rng_hash,
         const ccl_addr_space PathState *state,
         int branch,
         int num_branches)
 {
        if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
                return path_branched_rng_1D_for_decision(kg,
-                                                        rng,
+                                                        rng_hash,
                                                         state,
                                                         branch,
                                                         num_branches,
@@ -311,12 +307,10 @@ ccl_device_inline void path_state_branch(ccl_addr_space PathState *state,
        state->num_samples = state->num_samples*num_branches;
 }
 
-ccl_device_inline uint lcg_state_init(RNG *rng,
-                                      int rng_offset,
-                                      int sample,
+ccl_device_inline uint lcg_state_init(ccl_addr_space PathState *state,
                                       uint scramble)
 {
-       return lcg_init(*rng + rng_offset + sample*scramble);
+       return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble);
 }
 
 ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng)
index f553599..01ba6d8 100644 (file)
@@ -863,7 +863,7 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
 
 /* Surface Evaluation */
 
-ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
+ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
        ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx)
 {
        sd->num_closure = 0;
@@ -887,8 +887,8 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
 #endif
        }
 
-       if(rng && (sd->flag & SD_BSDF_NEEDS_LCG)) {
-               sd->lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0xb4bc3953);
+       if(sd->flag & SD_BSDF_NEEDS_LCG) {
+               sd->lcg_state = lcg_state_init(state, 0xb4bc3953);
        }
 }
 
index 10e9083..e9ce4dd 100644 (file)
@@ -49,7 +49,6 @@ ccl_device_forceinline bool shadow_handle_transparent_isect(
                path_state_modify_bounce(state, true);
                shader_eval_surface(kg,
                                    shadow_sd,
-                                   NULL,
                                    state,
                                    0.0f,
                                    PATH_RAY_SHADOW,
index 6475d4b..f2c5e52 100644 (file)
@@ -219,7 +219,7 @@ ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
 
        if(bump || texture_blur > 0.0f) {
                /* average color and normal at incoming point */
-               shader_eval_surface(kg, sd, NULL, state, 0.0f, state_flag, SHADER_CONTEXT_SSS);
+               shader_eval_surface(kg, sd, state, 0.0f, state_flag, SHADER_CONTEXT_SSS);
                float3 in_color = shader_bssrdf_sum(sd, (bump)? N: NULL, NULL);
 
                /* we simply divide out the average color and multiply with the average
@@ -243,7 +243,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
         SubsurfaceIntersection *ss_isect,
         ShaderData *sd,
         ShaderClosure *sc,
-        RNG *lcg_state,
+        uint *lcg_state,
         float disk_u,
         float disk_v,
         bool all)
index f1b82ee..58371c5 100644 (file)
@@ -242,10 +242,6 @@ CCL_NAMESPACE_BEGIN
 #  undef __DENOISING_FEATURES__
 #endif
 
-/* Random Numbers */
-
-typedef uint RNG;
-
 /* Shader Evaluation */
 
 typedef enum ShaderEvalType {
@@ -1023,6 +1019,7 @@ typedef struct PathState {
        int flag;
 
        /* random number generator state */
+       uint rng_hash;          /* per pixel hash */
        int rng_offset;                 /* dimension offset */
        int sample;                     /* path sample number */
        int num_samples;                /* total number of times this path will be sampled */
@@ -1048,7 +1045,7 @@ typedef struct PathState {
        /* volume rendering */
 #ifdef __VOLUME__
        int volume_bounce;
-       RNG rng_congruential;
+       uint rng_congruential;
        VolumeStack volume_stack[VOLUME_STACK_SIZE];
 #endif
 } PathState;
index 1e472aa..8dcfe7f 100644 (file)
@@ -360,7 +360,6 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
     ShaderData *sd,
     PathRadiance *L,
     ccl_addr_space float3 *throughput,
-    RNG *rng,
     bool probalistic_scatter)
 {
        VolumeShaderCoefficients coeff;
@@ -380,13 +379,13 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
 
                /* pick random color channel, we use the Veach one-sample
                 * model with balance heuristic for the channels */
-               float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
+               float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE);
                int channel = (int)(rphase*3.0f);
                sd->randb_closure = rphase*3.0f - channel;
 
                /* decide if we will hit or miss */
                bool scatter = true;
-               float xi = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
+               float xi = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE);
 
                if(probalistic_scatter) {
                        float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
@@ -468,8 +467,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
     Ray *ray,
     ShaderData *sd,
     PathRadiance *L,
-    ccl_addr_space float3 *throughput,
-    RNG *rng)
+    ccl_addr_space float3 *throughput)
 {
        float3 tp = *throughput;
        const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
@@ -485,8 +483,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
 
        /* pick random color channel, we use the Veach one-sample
         * model with balance heuristic for the channels */
-       float xi = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
-       float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
+       float xi = path_state_rng_1D_for_decision(kg, state, PRNG_SCATTER_DISTANCE);
+       float rphase = path_state_rng_1D_for_decision(kg, state, PRNG_PHASE);
        int channel = (int)(rphase*3.0f);
        sd->randb_closure = rphase*3.0f - channel;
        bool has_scatter = false;
@@ -610,15 +608,14 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(
     Ray *ray,
     PathRadiance *L,
     ccl_addr_space float3 *throughput,
-    RNG *rng,
     bool heterogeneous)
 {
        shader_setup_from_volume(kg, sd, ray);
 
        if(heterogeneous)
-               return kernel_volume_integrate_heterogeneous_distance(kg, state, ray, sd, L, throughput, rng);
+               return kernel_volume_integrate_heterogeneous_distance(kg, state, ray, sd, L, throughput);
        else
-               return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, rng, true);
+               return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, true);
 }
 
 #ifndef __SPLIT_KERNEL__
index e2762a8..9fe4ec1 100644 (file)
@@ -110,7 +110,6 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(
        SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
 
        ShaderData *sd = saved_sd;
-       RNG rng = kernel_split_state.rng[ray_index];
        PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
        float3 throughput = branched_state->throughput;
        ccl_global PathState *ps = &kernel_split_state.path_state[ray_index];
@@ -157,20 +156,20 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(
                num_samples = ceil_to_int(num_samples_adjust*num_samples);
 
                float num_samples_inv = num_samples_adjust/num_samples;
-               RNG bsdf_rng = cmj_hash(rng, i);
 
                for(int j = branched_state->next_sample; j < num_samples; j++) {
                        if(reset_path_state) {
                                *ps = branched_state->path_state;
                        }
 
+                       ps->rng_hash = cmj_hash(branched_state->path_state.rng_hash, i);
+
                        ccl_global float3 *tp = &kernel_split_state.throughput[ray_index];
                        *tp = throughput;
 
                        ccl_global Ray *bsdf_ray = &kernel_split_state.ray[ray_index];
 
                        if(!kernel_branched_path_surface_bounce(kg,
-                                                               &bsdf_rng,
                                                                sd,
                                                                sc,
                                                                j,
@@ -184,6 +183,8 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(
                                continue;
                        }
 
+                       ps->rng_hash = branched_state->path_state.rng_hash;
+
                        /* update state for next iteration */
                        branched_state->next_closure = i;
                        branched_state->next_sample = j+1;
index 6aa0d69..de0c416 100644 (file)
@@ -83,7 +83,6 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
        PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
        ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
        ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
-       RNG rng = kernel_split_state.rng[ray_index];
        ccl_global float *buffer = kernel_split_params.buffer;
 
        unsigned int work_index;
@@ -135,7 +134,8 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
                        buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
 
                        /* Initialize random numbers and ray. */
-                       kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, &rng, ray);
+                       uint rng_hash;
+                       kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, &rng_hash, ray);
 
                        if(ray->t != 0.0f) {
                                /* Initialize throughput, path radiance, Ray, PathState;
@@ -143,7 +143,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
                                 */
                                *throughput = make_float3(1.0f, 1.0f, 1.0f);
                                path_radiance_init(L, kernel_data.film.use_light_pass);
-                               path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, &rng, sample, ray);
+                               path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, rng_hash, sample, ray);
 #ifdef __SUBSURFACE__
                                kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
 #endif
@@ -160,7 +160,6 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
                        }
                }
        }
-       kernel_split_state.rng[ray_index] = rng;
 
 #ifndef __COMPUTE_DEVICE_GPU__
        }
index 3336c96..8e3f755 100644 (file)
@@ -62,8 +62,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
 
                /* direct lighting */
 #ifdef __EMISSION__
-               RNG rng = kernel_split_state.rng[ray_index];
-
                bool flag = (kernel_data.integrator.use_direct_light &&
                             (sd->flag & SD_BSDF_HAS_EVAL));
 
@@ -83,10 +81,10 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
 
                if(flag) {
                        /* Sample illumination from lights to find path contribution. */
-                       float light_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT);
+                       float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
                        float light_u, light_v;
-                       path_state_rng_2D(kg, &rng, state, PRNG_LIGHT_U, &light_u, &light_v);
-                       float terminate = path_state_rng_light_termination(kg, &rng, state);
+                       path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+                       float terminate = path_state_rng_light_termination(kg, state);
 
                        LightSample ls;
                        if(light_sample(kg,
@@ -115,7 +113,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
                                }
                        }
                }
-               kernel_split_state.rng[ray_index] = rng;
 #endif  /* __EMISSION__ */
        }
 
index 9f8dd23..478d83d 100644 (file)
@@ -30,7 +30,6 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K
        SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
 
        ShaderData *sd = &kernel_split_state.sd[ray_index];
-       RNG rng = kernel_split_state.rng[ray_index];
        PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
        ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
 
@@ -58,15 +57,15 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K
 
                /* integrate along volume segment with distance sampling */
                VolumeIntegrateResult result = kernel_volume_integrate(
-                       kg, ps, sd, &volume_ray, L, tp, &rng, heterogeneous);
+                       kg, ps, sd, &volume_ray, L, tp, heterogeneous);
 
 #  ifdef __VOLUME_SCATTER__
                if(result == VOLUME_PATH_SCATTERED) {
                        /* direct lighting */
-                       kernel_path_volume_connect_light(kg, &rng, sd, emission_sd, *tp, &branched_state->path_state, L);
+                       kernel_path_volume_connect_light(kg, sd, emission_sd, *tp, &branched_state->path_state, L);
 
                        /* indirect light bounce */
-                       if(!kernel_path_volume_bounce(kg, &rng, sd, tp, ps, L, pray)) {
+                       if(!kernel_path_volume_bounce(kg, sd, tp, ps, L, pray)) {
                                continue;
                        }
 
@@ -141,7 +140,6 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
           IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
                ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
                ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
-               RNG rng = kernel_split_state.rng[ray_index];
                ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
                ShaderData *sd = &kernel_split_state.sd[ray_index];
                ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
@@ -165,15 +163,15 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
                                {
                                        /* integrate along volume segment with distance sampling */
                                        VolumeIntegrateResult result = kernel_volume_integrate(
-                                               kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous);
+                                               kg, state, sd, &volume_ray, L, throughput, heterogeneous);
 
 #  ifdef __VOLUME_SCATTER__
                                        if(result == VOLUME_PATH_SCATTERED) {
                                                /* direct lighting */
-                                               kernel_path_volume_connect_light(kg, &rng, sd, emission_sd, *throughput, state, L);
+                                               kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
 
                                                /* indirect light bounce */
-                                               if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray)) {
+                                               if(kernel_path_volume_bounce(kg, sd, throughput, state, L, ray)) {
                                                        ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
                                                }
                                                else {
@@ -194,8 +192,6 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
                        }
 #  endif  /* __BRANCHED_PATH__ */
                }
-
-               kernel_split_state.rng[ray_index] = rng;
        }
 
 #  ifdef __BRANCHED_PATH__
index 95f57fb..3fc45af 100644 (file)
@@ -100,7 +100,6 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
        unsigned int tile_y;
        unsigned int sample;
 
-       RNG rng = kernel_split_state.rng[ray_index];
        ccl_global PathState *state = 0x0;
        float3 throughput;
 
@@ -247,7 +246,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
 
                if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
                        if(probability != 1.0f) {
-                               float terminate = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_TERMINATE);
+                               float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE);
                                if(terminate >= probability) {
                                        kernel_split_path_end(kg, ray_index);
                                }
@@ -269,8 +268,6 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
        }
 #endif  /* __AO__ */
 
-       kernel_split_state.rng[ray_index] = rng;
-
 #ifndef __COMPUTE_DEVICE_GPU__
        }
 #endif
index 7758e35..4e0c966 100644 (file)
@@ -126,7 +126,6 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
        if(active) {
                ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
                ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
-               RNG rng = kernel_split_state.rng[ray_index];
                ShaderData *sd = &kernel_split_state.sd[ray_index];
                ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
                PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
@@ -135,7 +134,7 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
                if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
 #endif
                        /* Compute direct lighting and next bounce. */
-                       if(!kernel_path_surface_bounce(kg, &rng, sd, throughput, state, L, ray)) {
+                       if(!kernel_path_surface_bounce(kg, sd, throughput, state, L, ray)) {
                                kernel_split_path_end(kg, ray_index);
                        }
 #ifdef __BRANCHED_PATH__
@@ -157,8 +156,6 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
                        }
                }
 #endif  /* __BRANCHED_PATH__ */
-
-               kernel_split_state.rng[ray_index] = rng;
        }
 
        /* Enqueue RAY_UPDATE_BUFFER rays. */
index 8315b0b..8b70df1 100644 (file)
@@ -60,14 +60,14 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
        ccl_global float *buffer = kernel_split_params.buffer;
        buffer += (kernel_split_params.offset + pixel_x + pixel_y * kernel_split_params.stride) * kernel_data.film.pass_stride;
 
-       RNG rng = kernel_split_state.rng[ray_index];
+       uint rng_hash;
 
        /* Initialize random numbers and ray. */
        kernel_path_trace_setup(kg,
                                rng_state,
                                my_sample,
                                pixel_x, pixel_y,
-                               &rng,
+                               &rng_hash,
                                &kernel_split_state.ray[ray_index]);
 
        if(kernel_split_state.ray[ray_index].t != 0.0f) {
@@ -79,7 +79,7 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
                path_state_init(kg,
                                &kernel_split_state.sd_DL_shadow[ray_index],
                                &kernel_split_state.path_state[ray_index],
-                               &rng,
+                               rng_hash,
                                my_sample,
                                &kernel_split_state.ray[ray_index]);
 #ifdef __SUBSURFACE__
@@ -93,7 +93,6 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
                kernel_write_pass_float4(buffer, my_sample, L_rad);
                ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE);
        }
-       kernel_split_state.rng[ray_index] = rng;
 }
 
 CCL_NAMESPACE_END
index 5c6d90e..d0afd39 100644 (file)
@@ -74,7 +74,6 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
 #ifdef __HAIR__
        float difl = 0.0f, extmax = 0.0f;
        uint lcg_state = 0;
-       RNG rng = kernel_split_state.rng[ray_index];
 
        if(kernel_data.bvh.have_curves) {
                if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
@@ -84,7 +83,7 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
                }
 
                extmax = kernel_data.curve.maximum_width;
-               lcg_state = lcg_state_init(&rng, state.rng_offset, state.sample, 0x51633e2d);
+               lcg_state = lcg_state_init(&state, 0x51633e2d);
        }
 
        bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
index 2801b32..d0fa29e 100644 (file)
@@ -48,18 +48,17 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg)
 
        ccl_global char *ray_state = kernel_split_state.ray_state;
        if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
-               RNG rng = kernel_split_state.rng[ray_index];
                ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
 
 #ifndef __BRANCHED_PATH__
-               float rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF);
-               shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
+               float rbsdf = path_state_rng_1D_for_decision(kg, state, PRNG_BSDF);
+               shader_eval_surface(kg, &kernel_split_state.sd[ray_index], state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
 #else
                ShaderContext ctx = SHADER_CONTEXT_MAIN;
                float rbsdf = 0.0f;
 
                if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
-                       rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF);
+                       rbsdf = path_state_rng_1D_for_decision(kg, state, PRNG_BSDF);
 
                }
 
@@ -67,11 +66,9 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg)
                        ctx = SHADER_CONTEXT_INDIRECT;
                }
 
-               shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, ctx);
+               shader_eval_surface(kg, &kernel_split_state.sd[ray_index], state, rbsdf, state->flag, ctx);
                shader_merge_closures(&kernel_split_state.sd[ray_index]);
 #endif  /* __BRANCHED_PATH__ */
-
-               kernel_split_state.rng[ray_index] = rng;
        }
 }
 
index 4742862..79aa2c9 100644 (file)
@@ -37,21 +37,18 @@ ccl_device void kernel_shadow_blocked_ao(KernelGlobals *kg)
        ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
        PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
        ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
-       RNG rng = kernel_split_state.rng[ray_index];
        float3 throughput = kernel_split_state.throughput[ray_index];
 
 #ifdef __BRANCHED_PATH__
        if(!kernel_data.integrator.branched || IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
 #endif
-               kernel_path_ao(kg, sd, emission_sd, L, state, &rng, throughput, shader_bsdf_alpha(kg, sd));
+               kernel_path_ao(kg, sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, sd));
 #ifdef __BRANCHED_PATH__
        }
        else {
-               kernel_branched_path_ao(kg, sd, emission_sd, L, state, &rng, throughput);
+               kernel_branched_path_ao(kg, sd, emission_sd, L, state, throughput);
        }
 #endif
-
-       kernel_split_state.rng[ray_index] = rng;
 }
 
 CCL_NAMESPACE_END
index 78e6170..50c9ace 100644 (file)
@@ -45,7 +45,6 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
        PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
        ShaderData *sd = &kernel_split_state.sd[ray_index];
        float3 throughput = kernel_split_state.throughput[ray_index];
-       RNG rng = kernel_split_state.rng[ray_index];
 
        BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
        ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
@@ -75,7 +74,6 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
 
        if(use_branched) {
                kernel_branched_path_surface_connect_light(kg,
-                                                          &rng,
                                                           sd,
                                                           emission_sd,
                                                           state,
@@ -103,8 +101,6 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
                        path_radiance_accum_total_light(L, state, throughput, &L_light);
                }
        }
-
-       kernel_split_state.rng[ray_index] = rng;
 }
 
 CCL_NAMESPACE_END
index 4f32c68..3eae884 100644 (file)
@@ -114,7 +114,6 @@ typedef ccl_global struct SplitBranchedState {
 #endif /* __VOLUME__ */
 
 #define SPLIT_DATA_ENTRIES \
-       SPLIT_DATA_ENTRY(ccl_global RNG, rng, 1) \
        SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
        SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
        SPLIT_DATA_ENTRY(ccl_global Ray, ray, 1) \
@@ -133,7 +132,6 @@ typedef ccl_global struct SplitBranchedState {
 
 /* entries to be copied to inactive rays when sharing branched samples (TODO: which are actually needed?) */
 #define SPLIT_DATA_ENTRIES_BRANCHED_SHARED \
-       SPLIT_DATA_ENTRY(ccl_global RNG, rng, 1) \
        SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
        SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
        SPLIT_DATA_ENTRY(ccl_global Ray, ray, 1) \
index d5083b2..76d198a 100644 (file)
@@ -38,7 +38,6 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
        SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
 
        ShaderData *sd = &branched_state->sd;
-       RNG rng = kernel_split_state.rng[ray_index];
        PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
        ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
 
@@ -52,14 +51,12 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
                if(branched_state->ss_next_sample == 0 && branched_state->next_hit == 0 &&
                   branched_state->next_closure == 0 && branched_state->next_sample == 0)
                {
-                       branched_state->lcg_state = lcg_state_init(&rng,
-                                                                  branched_state->path_state.rng_offset,
-                                                                  branched_state->path_state.sample,
+                       branched_state->lcg_state = lcg_state_init(&branched_state->path_state,
                                                                   0x68bc21eb);
                }
                int num_samples = kernel_data.integrator.subsurface_samples;
                float num_samples_inv = 1.0f/num_samples;
-               RNG bssrdf_rng = cmj_hash(rng, i);
+               uint bssrdf_rng_hash = cmj_hash(branched_state->path_state.rng_hash, i);
 
                /* do subsurface scatter step with copy of shader data, this will
                 * replace the BSSRDF with a diffuse BSDF closure */
@@ -67,7 +64,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
                        ccl_global SubsurfaceIntersection *ss_isect = &branched_state->ss_isect;
                        float bssrdf_u, bssrdf_v;
                        path_branched_rng_2D(kg,
-                                            &bssrdf_rng,
+                                            bssrdf_rng_hash,
                                             &branched_state->path_state,
                                             j,
                                             num_samples,
@@ -77,7 +74,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) {
-                               RNG lcg_state = branched_state->lcg_state;
+                               uint lcg_state = branched_state->lcg_state;
                                SubsurfaceIntersection ss_isect_private;
 
                                branched_state->num_hits = subsurface_scatter_multi_intersect(kg,
@@ -152,7 +149,6 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
                                                int all = (kernel_data.integrator.sample_all_lights_direct) ||
                                                              (branched_state->path_state.flag & PATH_RAY_SHADOW_CATCHER);
                                                kernel_branched_path_surface_connect_light(kg,
-                                                                                          &rng,
                                                                                           bssrdf_sd,
                                                                                           emission_sd,
                                                                                           hit_state,
@@ -229,7 +225,6 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
        if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
                ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
                PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
-               RNG rng = kernel_split_state.rng[ray_index];
                ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
                ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
                ccl_global SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
@@ -246,7 +241,6 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
                                                                  emission_sd,
                                                                  L,
                                                                  state,
-                                                                 &rng,
                                                                  ray,
                                                                  throughput,
                                                                  ss_indirect))
@@ -264,10 +258,9 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
 
                                /* do bssrdf scatter step if we picked a bssrdf closure */
                                if(sc) {
-                                       uint lcg_state = lcg_state_init(&rng, state->rng_offset, state->sample, 0x68bc21eb);
+                                       uint lcg_state = lcg_state_init(state, 0x68bc21eb);
                                        float bssrdf_u, bssrdf_v;
                                        path_state_rng_2D(kg,
-                                                         &rng,
                                                          state,
                                                          PRNG_BSDF_U,
                                                          &bssrdf_u, &bssrdf_v);
@@ -290,7 +283,6 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
                        }
 #endif
                }
-               kernel_split_state.rng[ray_index] = rng;
        }
 
 #  ifdef __BRANCHED_PATH__