diff options
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 26 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path_branched.h | 51 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path_state.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path_surface.h | 10 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 7 | ||||
-rw-r--r-- | intern/cycles/kernel/split/kernel_next_iteration_setup.h | 63 | ||||
-rw-r--r-- | intern/cycles/kernel/split/kernel_queue_enqueue.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/split/kernel_shader_setup.h | 10 |
8 files changed, 124 insertions, 45 deletions
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index aef350b0658..b0f53aef2d5 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -445,8 +445,15 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, break; } - /* Setup and evaluate shader. */ + /* Setup shader data. */ shader_setup_from_ray(kg, sd, &isect, ray); + + /* Skip most work for volume bounding surface. */ +#ifdef __VOLUME__ + if(!(sd->flag & SD_HAS_ONLY_VOLUME)) { +#endif + + /* Evaluate shader. */ shader_eval_surface(kg, sd, state, state->flag); shader_prepare_closures(sd, state); @@ -523,6 +530,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, } #endif /* defined(__EMISSION__) */ +#ifdef __VOLUME__ + } +#endif + if(!kernel_path_surface_bounce(kg, sd, &throughput, state, &L->state, ray)) break; } @@ -605,8 +616,15 @@ ccl_device_forceinline void kernel_path_integrate( break; } - /* Setup and evaluate shader. */ + /* Setup shader data. */ shader_setup_from_ray(kg, &sd, &isect, ray); + + /* Skip most work for volume bounding surface. */ +#ifdef __VOLUME__ + if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { +#endif + + /* Evaluate shader. */ shader_eval_surface(kg, &sd, state, state->flag); shader_prepare_closures(&sd, state); @@ -669,6 +687,10 @@ ccl_device_forceinline void kernel_path_integrate( /* direct lighting */ kernel_path_surface_connect_light(kg, &sd, emission_sd, throughput, state, L); +#ifdef __VOLUME__ + } +#endif + /* compute direct lighting and next bounce */ if(!kernel_path_surface_bounce(kg, &sd, &throughput, state, &L->state, ray)) break; diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index 441a06eeba3..d43d418db29 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -480,6 +480,12 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, /* Setup and evaluate shader. */ shader_setup_from_ray(kg, &sd, &isect, &ray); + + /* Skip most work for volume bounding surface. */ +#ifdef __VOLUME__ + if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { +#endif + shader_eval_surface(kg, &sd, &state, state.flag); shader_merge_closures(&sd); @@ -533,37 +539,46 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, } #endif /* __SUBSURFACE__ */ - if(!(sd.flag & SD_HAS_ONLY_VOLUME)) { - PathState hit_state = state; + PathState hit_state = state; #ifdef __EMISSION__ - /* direct light */ - 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, - &sd, emission_sd, &hit_state, throughput, 1.0f, L, all); - } + /* direct light */ + 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, + &sd, emission_sd, &hit_state, throughput, 1.0f, L, all); + } #endif /* __EMISSION__ */ - /* indirect light */ - kernel_branched_path_surface_indirect_light(kg, - &sd, &indirect_sd, emission_sd, throughput, 1.0f, &hit_state, L); + /* indirect light */ + kernel_branched_path_surface_indirect_light(kg, + &sd, &indirect_sd, emission_sd, throughput, 1.0f, &hit_state, L); - /* continue in case of transparency */ - throughput *= shader_bsdf_transparency(kg, &sd); + /* continue in case of transparency */ + throughput *= shader_bsdf_transparency(kg, &sd); - if(is_zero(throughput)) - break; - } + if(is_zero(throughput)) + break; /* Update Path State */ path_state_next(kg, &state, LABEL_TRANSPARENT); +#ifdef __VOLUME__ + } + else { + /* For volume bounding meshes we pass through without counting transparent + * bounces, only sanity check in case self intersection gets us stuck. */ + state.volume_bounds_bounce++; + if (state.volume_bounds_bounce > VOLUME_BOUNDS_MAX) { + break; + } + } +#endif + ray.P = ray_offset(sd.P, -sd.Ng); ray.t -= sd.ray_length; /* clipping works through transparent */ - #ifdef __RAY_DIFFERENTIALS__ ray.dP = sd.dP; ray.dD.dx = -sd.dI.dx; diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 15d81fcddf4..ff7d1307a6c 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -55,6 +55,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, #ifdef __VOLUME__ state->volume_bounce = 0; + state->volume_bounds_bounce = 0; if(kernel_data.integrator.use_volumes) { /* Initialize volume stack with volume we are inside of. */ diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index 7b566b01b04..bca346d5ee0 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -329,10 +329,12 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg, } #ifdef __VOLUME__ else if(sd->flag & SD_HAS_ONLY_VOLUME) { - /* no surface shader but have a volume shader? act transparent */ - - /* update path state, count as transparent */ - path_state_next(kg, state, LABEL_TRANSPARENT); + /* For volume bounding meshes we pass through without counting transparent + * bounces, only sanity check in case self intersection gets us stuck. */ + state->volume_bounds_bounce++; + if (state->volume_bounds_bounce > VOLUME_BOUNDS_MAX) { + return false; + } if(state->bounce == 0) ray->t -= sd->ray_length; /* clipping works through transparent */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index d967edca75d..2a437cdbdc6 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -49,6 +49,8 @@ CCL_NAMESPACE_BEGIN #define BSSRDF_MAX_BOUNCES 256 #define LOCAL_MAX_HITS 4 +#define VOLUME_BOUNDS_MAX 1024 + #define BECKMANN_TABLE_SIZE 256 #define SHADER_NONE (~0) @@ -1107,6 +1109,7 @@ typedef struct PathState { /* volume rendering */ #ifdef __VOLUME__ int volume_bounce; + int volume_bounds_bounce; uint rng_congruential; VolumeStack volume_stack[VOLUME_STACK_SIZE]; #endif @@ -1497,8 +1500,10 @@ enum RayState { RAY_ACTIVE, /* Denotes ray has completed processing all samples and is inactive. */ RAY_INACTIVE, - /* Denoted ray has exited path-iteration and needs to update output buffer. */ + /* Denotes ray has exited path-iteration and needs to update output buffer. */ RAY_UPDATE_BUFFER, + /* Denotes ray needs to skip most surface shader work. */ + RAY_HAS_ONLY_VOLUME, /* Donotes ray has hit background */ RAY_HIT_BACKGROUND, /* Denotes ray has to be regenerated */ diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h index 81024f0cf99..8092419e796 100644 --- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h +++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h @@ -53,39 +53,52 @@ ccl_device_inline void kernel_split_branched_indirect_light_init(KernelGlobals * ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT); } -ccl_device void kernel_split_branched_indirect_light_end(KernelGlobals *kg, int ray_index) +ccl_device void kernel_split_branched_transparent_bounce(KernelGlobals *kg, int ray_index) { - kernel_split_branched_path_indirect_loop_end(kg, ray_index); - ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; ShaderData *sd = kernel_split_sd(sd, ray_index); ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - /* continue in case of transparency */ - *throughput *= shader_bsdf_transparency(kg, sd); +# ifdef __VOLUME__ + if(!(sd->flag & SD_HAS_ONLY_VOLUME)) { +# endif + /* continue in case of transparency */ + *throughput *= shader_bsdf_transparency(kg, sd); + + if(is_zero(*throughput)) { + kernel_split_path_end(kg, ray_index); + return; + } - if(is_zero(*throughput)) { - kernel_split_path_end(kg, ray_index); - } - else { /* Update Path State */ path_state_next(kg, state, LABEL_TRANSPARENT); +# ifdef __VOLUME__ + } + else { + /* For volume bounding meshes we pass through without counting transparent + * bounces, only sanity check in case self intersection gets us stuck. */ + state->volume_bounds_bounce++; + if (state->volume_bounds_bounce > VOLUME_BOUNDS_MAX) { + kernel_split_path_end(kg, ray_index); + return; + } + } +# endif - ray->P = ray_offset(sd->P, -sd->Ng); - ray->t -= sd->ray_length; /* clipping works through transparent */ + ray->P = ray_offset(sd->P, -sd->Ng); + ray->t -= sd->ray_length; /* clipping works through transparent */ # ifdef __RAY_DIFFERENTIALS__ - ray->dP = sd->dP; - ray->dD.dx = -sd->dI.dx; - ray->dD.dy = -sd->dI.dy; + ray->dP = sd->dP; + ray->dD.dx = -sd->dI.dx; + ray->dD.dy = -sd->dI.dy; # endif /* __RAY_DIFFERENTIALS__ */ # ifdef __VOLUME__ - /* enter/exit volume */ - kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); + /* enter/exit volume */ + kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); # endif /* __VOLUME__ */ - } } #endif /* __BRANCHED_PATH__ */ @@ -121,6 +134,13 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, ccl_global char *ray_state = kernel_split_state.ray_state; +# ifdef __VOLUME__ + /* Reactivate only volume rays here, most surface work was skipped. */ + if(IS_STATE(ray_state, ray_index, RAY_HAS_ONLY_VOLUME)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_ACTIVE); + } +# endif + bool active = IS_STATE(ray_state, ray_index, RAY_ACTIVE); if(active) { ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; @@ -138,6 +158,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, } #ifdef __BRANCHED_PATH__ } + else if(sd->flag & SD_HAS_ONLY_VOLUME) { + kernel_split_branched_transparent_bounce(kg, ray_index); + } else { kernel_split_branched_indirect_light_init(kg, ray_index); @@ -151,7 +174,8 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); } else { - kernel_split_branched_indirect_light_end(kg, ray_index); + kernel_split_branched_path_indirect_loop_end(kg, ray_index); + kernel_split_branched_transparent_bounce(kg, ray_index); } } #endif /* __BRANCHED_PATH__ */ @@ -196,7 +220,8 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); } else { - kernel_split_branched_indirect_light_end(kg, ray_index); + kernel_split_branched_path_indirect_loop_end(kg, ray_index); + kernel_split_branched_transparent_bounce(kg, ray_index); } } diff --git a/intern/cycles/kernel/split/kernel_queue_enqueue.h b/intern/cycles/kernel/split/kernel_queue_enqueue.h index 66ce2dfb6f1..df67fabab19 100644 --- a/intern/cycles/kernel/split/kernel_queue_enqueue.h +++ b/intern/cycles/kernel/split/kernel_queue_enqueue.h @@ -56,6 +56,7 @@ ccl_device void kernel_queue_enqueue(KernelGlobals *kg, queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS; } else if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) || + IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME) || IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED)) { queue_number = QUEUE_ACTIVE_AND_REGENERATED_RAYS; } diff --git a/intern/cycles/kernel/split/kernel_shader_setup.h b/intern/cycles/kernel/split/kernel_shader_setup.h index 9d428ee8139..ea3ec2ec83f 100644 --- a/intern/cycles/kernel/split/kernel_shader_setup.h +++ b/intern/cycles/kernel/split/kernel_shader_setup.h @@ -59,12 +59,20 @@ ccl_device void kernel_shader_setup(KernelGlobals *kg, if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) { Intersection isect = kernel_split_state.isect[ray_index]; Ray ray = kernel_split_state.ray[ray_index]; + ShaderData *sd = kernel_split_sd(sd, ray_index); shader_setup_from_ray(kg, - kernel_split_sd(sd, ray_index), + sd, &isect, &ray); + +#ifdef __VOLUME__ + if(sd->flag & SD_HAS_ONLY_VOLUME) { + ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME); + } +#endif } + } CCL_NAMESPACE_END |