diff options
author | Brecht Van Lommel <brecht@blender.org> | 2021-11-03 19:28:12 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-11-05 22:50:19 +0300 |
commit | d1a9425a2fde32b6786b333ab55661da507e818b (patch) | |
tree | 42f5068d3c6377a4c20be579766af361b2d1c360 /intern/cycles/kernel/integrator | |
parent | 4b56eed0f786562dfe961e23091f4f20c16a9e90 (diff) |
Fix T91733, T92486: Cycles wrong shadow catcher with volumes
Changes:
* After hitting a shadow catcher, re-initialize the volume stack taking
into account shadow catcher ray visibility. This ensures that volume objects
are included in the stack only if they are shadow catchers.
* If there is a volume to be shaded in front of the shadow catcher, the split
is now performed in the shade_volume kernel after volume shading is done.
* Previously the background pass behind a shadow catcher was done as part of
the regular path, now it is done as part of the shadow catcher path.
For a shadow catcher path with volumes and visible background, operations are
done in this order now:
* intersect_closest
* shade_volume
* shadow catcher split
* intersect_volume_stack
* shade_background
* shade_surface
The world volume is currently assumed to be CG, that is it does not exist in
the footage. We may consider adding an option to control this, or change the
default. With a volume object this control is already possible.
This includes refactoring to centralize the logic for next kernel scheduling
in intersect_closest.h.
Differential Revision: https://developer.blender.org/D13093
Diffstat (limited to 'intern/cycles/kernel/integrator')
-rw-r--r-- | intern/cycles/kernel/integrator/intersect_closest.h | 270 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/intersect_volume_stack.h | 42 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shade_background.h | 20 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shade_volume.h | 22 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shadow_catcher.h | 27 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/state.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/state_util.h | 8 |
7 files changed, 232 insertions, 165 deletions
diff --git a/intern/cycles/kernel/integrator/intersect_closest.h b/intern/cycles/kernel/integrator/intersect_closest.h index 2cac18ed889..5522b46205b 100644 --- a/intern/cycles/kernel/integrator/intersect_closest.h +++ b/intern/cycles/kernel/integrator/intersect_closest.h @@ -31,7 +31,6 @@ CCL_NAMESPACE_BEGIN -template<uint32_t current_kernel> ccl_device_forceinline bool integrator_intersect_terminate(KernelGlobals kg, IntegratorState state, const int shader_flags) @@ -86,36 +85,75 @@ ccl_device_forceinline bool integrator_intersect_terminate(KernelGlobals kg, return false; } -/* Note that current_kernel is a template value since making this a variable - * leads to poor performance with CUDA atomics. */ -template<uint32_t current_kernel> -ccl_device_forceinline void integrator_intersect_shader_next_kernel( - KernelGlobals kg, - IntegratorState state, - ccl_private const Intersection *ccl_restrict isect, - const int shader, - const int shader_flags) +#ifdef __SHADOW_CATCHER__ +/* Split path if a shadow catcher was hit. */ +ccl_device_forceinline void integrator_split_shadow_catcher( + KernelGlobals kg, IntegratorState state, ccl_private const Intersection *ccl_restrict isect) { - /* Note on scheduling. - * - * When there is no shadow catcher split the scheduling is simple: schedule surface shading with - * or without raytrace support, depending on the shader used. - * - * When there is a shadow catcher split the general idea is to have the following configuration: - * - * - Schedule surface shading kernel (with corresponding raytrace support) for the ray which - * will trace shadow catcher object. - * - * - When no alpha-over of approximate shadow catcher is needed, schedule surface shading for - * the matte ray. - * - * - Otherwise schedule background shading kernel, so that we have a background to alpha-over - * on. The background kernel will then schedule surface shading for the matte ray. + /* Test if we hit a shadow catcher object, and potentially split the path to continue tracing two + * paths from here. */ + const int object_flags = intersection_get_object_flags(kg, isect); + if (!kernel_shadow_catcher_is_path_split_bounce(kg, state, object_flags)) { + return; + } + + /* Mark state as having done a shadow catcher split so that it stops contributing to + * the shadow catcher matte pass, but keeps contributing to the combined pass. */ + INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SHADOW_CATCHER_HIT; + + /* Copy current state to new state. */ + state = integrator_state_shadow_catcher_split(kg, state); + + /* Initialize new state. * * Note that the splitting leaves kernel and sorting counters as-is, so use INIT semantic for * the matte path. */ - const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE); + /* Mark current state so that it will only track contribution of shadow catcher objects ignoring + * non-catcher objects. */ + INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SHADOW_CATCHER_PASS; + + if (kernel_data.film.pass_background != PASS_UNUSED && !kernel_data.background.transparent) { + /* If using background pass, schedule background shading kernel so that we have a background + * to alpha-over on. The background kernel will then continue the path afterwards. */ + INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SHADOW_CATCHER_BACKGROUND; + INTEGRATOR_PATH_INIT(DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND); + return; + } + + if (!integrator_state_volume_stack_is_empty(kg, state)) { + /* Volume stack is not empty. Re-init the volume stack to exclude any non-shadow catcher + * objects from it, and then continue shading volume and shadow catcher surface after. */ + INTEGRATOR_PATH_INIT(DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK); + return; + } + + /* Continue with shading shadow catcher surface. */ + const int shader = intersection_get_shader(kg, isect); + const int flags = kernel_tex_fetch(__shaders, shader).flags; + const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); + + if (use_raytrace_kernel) { + INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader); + } + else { + INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader); + } +} + +/* Schedule next kernel to be executed after updating volume stack for shadow catcher. */ +template<uint32_t current_kernel> +ccl_device_forceinline void integrator_intersect_next_kernel_after_shadow_catcher_volume( + KernelGlobals kg, IntegratorState state) +{ + /* Continue with shading shadow catcher surface. Same as integrator_split_shadow_catcher, but + * using NEXT instead of INIT. */ + Intersection isect ccl_optional_struct_init; + integrator_state_read_isect(kg, state, &isect); + + const int shader = intersection_get_shader(kg, &isect); + const int flags = kernel_tex_fetch(__shaders, shader).flags; + const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); if (use_raytrace_kernel) { INTEGRATOR_PATH_NEXT_SORTED( @@ -124,23 +162,132 @@ ccl_device_forceinline void integrator_intersect_shader_next_kernel( else { INTEGRATOR_PATH_NEXT_SORTED(current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader); } +} -#ifdef __SHADOW_CATCHER__ - const int object_flags = intersection_get_object_flags(kg, isect); - if (kernel_shadow_catcher_split(kg, state, object_flags)) { - if (kernel_data.film.pass_background != PASS_UNUSED && !kernel_data.background.transparent) { - INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SHADOW_CATCHER_BACKGROUND; +/* Schedule next kernel to be executed after executing background shader for shadow catcher. */ +template<uint32_t current_kernel> +ccl_device_forceinline void integrator_intersect_next_kernel_after_shadow_catcher_background( + KernelGlobals kg, IntegratorState state) +{ + /* Same logic as integrator_split_shadow_catcher, but using NEXT instead of INIT. */ + if (!integrator_state_volume_stack_is_empty(kg, state)) { + /* Volume stack is not empty. Re-init the volume stack to exclude any non-shadow catcher + * objects from it, and then continue shading volume and shadow catcher surface after. */ + INTEGRATOR_PATH_NEXT(current_kernel, DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK); + return; + } + + /* Continue with shading shadow catcher surface. */ + integrator_intersect_next_kernel_after_shadow_catcher_volume<current_kernel>(kg, state); +} +#endif - INTEGRATOR_PATH_INIT(DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND); +/* Schedule next kernel to be executed after intersect closest. + * + * Note that current_kernel is a template value since making this a variable + * leads to poor performance with CUDA atomics. */ +template<uint32_t current_kernel> +ccl_device_forceinline void integrator_intersect_next_kernel( + KernelGlobals kg, + IntegratorState state, + ccl_private const Intersection *ccl_restrict isect, + const bool hit) +{ + /* Continue with volume kernel if we are inside a volume, regardless if we hit anything. */ +#ifdef __VOLUME__ + if (!integrator_state_volume_stack_is_empty(kg, state)) { + const bool hit_surface = hit && !(isect->type & PRIMITIVE_LAMP); + const int shader = (hit_surface) ? intersection_get_shader(kg, isect) : SHADER_NONE; + const int flags = (hit_surface) ? kernel_tex_fetch(__shaders, shader).flags : 0; + + if (!integrator_intersect_terminate(kg, state, flags)) { + INTEGRATOR_PATH_NEXT(current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME); } - else if (use_raytrace_kernel) { - INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader); + else { + INTEGRATOR_PATH_TERMINATE(current_kernel); + } + return; + } +#endif + + if (hit) { + /* Hit a surface, continue with light or surface kernel. */ + if (isect->type & PRIMITIVE_LAMP) { + INTEGRATOR_PATH_NEXT(current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT); } else { - INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader); + /* Hit a surface, continue with surface kernel unless terminated. */ + const int shader = intersection_get_shader(kg, isect); + const int flags = kernel_tex_fetch(__shaders, shader).flags; + + if (!integrator_intersect_terminate(kg, state, flags)) { + const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); + if (use_raytrace_kernel) { + INTEGRATOR_PATH_NEXT_SORTED( + current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader); + } + else { + INTEGRATOR_PATH_NEXT_SORTED( + current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader); + } + +#ifdef __SHADOW_CATCHER__ + /* Handle shadow catcher. */ + integrator_split_shadow_catcher(kg, state, isect); +#endif + } + else { + INTEGRATOR_PATH_TERMINATE(current_kernel); + } } } + else { + /* Nothing hit, continue with background kernel. */ + INTEGRATOR_PATH_NEXT(current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND); + } +} + +/* Schedule next kernel to be executed after shade volume. + * + * The logic here matches integrator_intersect_next_kernel, except that + * volume shading and termination testing have already been done. */ +template<uint32_t current_kernel> +ccl_device_forceinline void integrator_intersect_next_kernel_after_volume( + KernelGlobals kg, IntegratorState state, ccl_private const Intersection *ccl_restrict isect) +{ + if (isect->prim != PRIM_NONE) { + /* Hit a surface, continue with light or surface kernel. */ + if (isect->type & PRIMITIVE_LAMP) { + INTEGRATOR_PATH_NEXT(current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT); + return; + } + else { + /* Hit a surface, continue with surface kernel unless terminated. */ + const int shader = intersection_get_shader(kg, isect); + const int flags = kernel_tex_fetch(__shaders, shader).flags; + const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE); + + if (use_raytrace_kernel) { + INTEGRATOR_PATH_NEXT_SORTED( + current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader); + } + else { + INTEGRATOR_PATH_NEXT_SORTED( + current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader); + } + +#ifdef __SHADOW_CATCHER__ + /* Handle shadow catcher. */ + integrator_split_shadow_catcher(kg, state, isect); #endif + return; + } + } + else { + /* Nothing hit, continue with background kernel. */ + INTEGRATOR_PATH_NEXT(current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND); + return; + } } ccl_device void integrator_intersect_closest(KernelGlobals kg, IntegratorState state) @@ -192,56 +339,9 @@ ccl_device void integrator_intersect_closest(KernelGlobals kg, IntegratorState s /* Write intersection result into global integrator state memory. */ integrator_state_write_isect(kg, state, &isect); -#ifdef __VOLUME__ - if (!integrator_state_volume_stack_is_empty(kg, state)) { - const bool hit_surface = hit && !(isect.type & PRIMITIVE_LAMP); - const int shader = (hit_surface) ? intersection_get_shader(kg, &isect) : SHADER_NONE; - const int flags = (hit_surface) ? kernel_tex_fetch(__shaders, shader).flags : 0; - - if (!integrator_intersect_terminate<DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST>( - kg, state, flags)) { - /* Continue with volume kernel if we are inside a volume, regardless - * if we hit anything. */ - INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST, - DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME); - } - else { - INTEGRATOR_PATH_TERMINATE(DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST); - } - return; - } -#endif - - if (hit) { - /* Hit a surface, continue with light or surface kernel. */ - if (isect.type & PRIMITIVE_LAMP) { - INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST, - DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT); - return; - } - else { - /* Hit a surface, continue with surface kernel unless terminated. */ - const int shader = intersection_get_shader(kg, &isect); - const int flags = kernel_tex_fetch(__shaders, shader).flags; - - if (!integrator_intersect_terminate<DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST>( - kg, state, flags)) { - integrator_intersect_shader_next_kernel<DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST>( - kg, state, &isect, shader, flags); - return; - } - else { - INTEGRATOR_PATH_TERMINATE(DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST); - return; - } - } - } - else { - /* Nothing hit, continue with background kernel. */ - INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST, - DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND); - return; - } + /* Setup up next kernel to be executed. */ + integrator_intersect_next_kernel<DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST>( + kg, state, &isect, hit); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/integrator/intersect_volume_stack.h b/intern/cycles/kernel/integrator/intersect_volume_stack.h index dd0587db9d8..9fa5ff63ad2 100644 --- a/intern/cycles/kernel/integrator/intersect_volume_stack.h +++ b/intern/cycles/kernel/integrator/intersect_volume_stack.h @@ -42,10 +42,13 @@ ccl_device void integrator_volume_stack_update_for_subsurface(KernelGlobals kg, /* Store to avoid global fetches on every intersection step. */ const uint volume_stack_size = kernel_data.volume_stack_size; + const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); + const uint32_t visibility = SHADOW_CATCHER_PATH_VISIBILITY(path_flag, PATH_RAY_ALL_VISIBILITY); + #ifdef __VOLUME_RECORD_ALL__ Intersection hits[2 * MAX_VOLUME_STACK_SIZE + 1]; uint num_hits = scene_intersect_volume_all( - kg, &volume_ray, hits, 2 * volume_stack_size, PATH_RAY_ALL_VISIBILITY); + kg, &volume_ray, hits, 2 * volume_stack_size, visibility); if (num_hits > 0) { Intersection *isect = hits; @@ -60,7 +63,7 @@ ccl_device void integrator_volume_stack_update_for_subsurface(KernelGlobals kg, Intersection isect; int step = 0; while (step < 2 * volume_stack_size && - scene_intersect_volume(kg, &volume_ray, &isect, PATH_RAY_ALL_VISIBILITY)) { + scene_intersect_volume(kg, &volume_ray, &isect, visibility)) { shader_setup_from_ray(kg, stack_sd, &volume_ray, &isect); volume_stack_enter_exit(kg, state, stack_sd); @@ -74,7 +77,7 @@ ccl_device void integrator_volume_stack_update_for_subsurface(KernelGlobals kg, #endif } -ccl_device void integrator_intersect_volume_stack(KernelGlobals kg, IntegratorState state) +ccl_device void integrator_volume_stack_init(KernelGlobals kg, IntegratorState state) { PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME_STACK); @@ -89,14 +92,20 @@ ccl_device void integrator_intersect_volume_stack(KernelGlobals kg, IntegratorSt volume_ray.D = make_float3(0.0f, 0.0f, 1.0f); volume_ray.t = FLT_MAX; - const uint visibility = (INTEGRATOR_STATE(state, path, flag) & PATH_RAY_ALL_VISIBILITY); int stack_index = 0, enclosed_index = 0; - /* Write background shader. */ + const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); + const uint32_t visibility = SHADOW_CATCHER_PATH_VISIBILITY(path_flag, PATH_RAY_CAMERA); + + /* Initialize volume stack with background volume For shadow catcher the + * background volume is always assumed to be CG. */ if (kernel_data.background.volume_shader != SHADER_NONE) { - const VolumeStack new_entry = {OBJECT_NONE, kernel_data.background.volume_shader}; - integrator_state_write_volume_stack(state, stack_index, new_entry); - stack_index++; + if (!(path_flag & PATH_RAY_SHADOW_CATCHER_PASS)) { + INTEGRATOR_STATE_ARRAY_WRITE(state, volume_stack, stack_index, object) = OBJECT_NONE; + INTEGRATOR_STATE_ARRAY_WRITE( + state, volume_stack, stack_index, shader) = kernel_data.background.volume_shader; + stack_index++; + } } /* Store to avoid global fetches on every intersection step. */ @@ -202,9 +211,22 @@ ccl_device void integrator_intersect_volume_stack(KernelGlobals kg, IntegratorSt /* Write terminator. */ const VolumeStack new_entry = {OBJECT_NONE, SHADER_NONE}; integrator_state_write_volume_stack(state, stack_index, new_entry); +} - INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK, - DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST); +ccl_device void integrator_intersect_volume_stack(KernelGlobals kg, IntegratorState state) +{ + integrator_volume_stack_init(kg, state); + + if (INTEGRATOR_STATE(state, path, flag) & PATH_RAY_SHADOW_CATCHER_PASS) { + /* Volume stack re-init for shadow catcher, continue with shading of hit. */ + integrator_intersect_next_kernel_after_shadow_catcher_volume< + DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK>(kg, state); + } + else { + /* Volume stack init for camera rays, continue with intersection of camera ray. */ + INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK, + DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST); + } } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/integrator/shade_background.h b/intern/cycles/kernel/integrator/shade_background.h index 71a590749bd..24482e85b05 100644 --- a/intern/cycles/kernel/integrator/shade_background.h +++ b/intern/cycles/kernel/integrator/shade_background.h @@ -192,23 +192,11 @@ ccl_device void integrator_shade_background(KernelGlobals kg, #ifdef __SHADOW_CATCHER__ if (INTEGRATOR_STATE(state, path, flag) & PATH_RAY_SHADOW_CATCHER_BACKGROUND) { + /* Special case for shadow catcher where we want to fill the background pass + * behind the shadow catcher but also continue tracing the path. */ INTEGRATOR_STATE_WRITE(state, path, flag) &= ~PATH_RAY_SHADOW_CATCHER_BACKGROUND; - - const int isect_prim = INTEGRATOR_STATE(state, isect, prim); - const int isect_type = INTEGRATOR_STATE(state, isect, type); - const int shader = intersection_get_shader_from_isect_prim(kg, isect_prim, isect_type); - const int shader_flags = kernel_tex_fetch(__shaders, shader).flags; - - if (shader_flags & SD_HAS_RAYTRACE) { - INTEGRATOR_PATH_NEXT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND, - DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, - shader); - } - else { - INTEGRATOR_PATH_NEXT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND, - DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, - shader); - } + integrator_intersect_next_kernel_after_shadow_catcher_background< + DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND>(kg, state); return; } #endif diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h index 05959bef220..412be289ebe 100644 --- a/intern/cycles/kernel/integrator/shade_volume.h +++ b/intern/cycles/kernel/integrator/shade_volume.h @@ -1023,25 +1023,9 @@ ccl_device void integrator_shade_volume(KernelGlobals kg, } else { /* Continue to background, light or surface. */ - if (isect.prim == PRIM_NONE) { - INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME, - DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND); - return; - } - else if (isect.type & PRIMITIVE_LAMP) { - INTEGRATOR_PATH_NEXT(DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME, - DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT); - return; - } - else { - /* Hit a surface, continue with surface kernel unless terminated. */ - const int shader = intersection_get_shader(kg, &isect); - const int flags = kernel_tex_fetch(__shaders, shader).flags; - - integrator_intersect_shader_next_kernel<DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME>( - kg, state, &isect, shader, flags); - return; - } + integrator_intersect_next_kernel_after_volume<DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME>( + kg, state, &isect); + return; } #endif /* __VOLUME__ */ } diff --git a/intern/cycles/kernel/integrator/shadow_catcher.h b/intern/cycles/kernel/integrator/shadow_catcher.h index 7beae235dbc..ac55678c9cb 100644 --- a/intern/cycles/kernel/integrator/shadow_catcher.h +++ b/intern/cycles/kernel/integrator/shadow_catcher.h @@ -76,33 +76,6 @@ ccl_device_inline bool kernel_shadow_catcher_path_can_split(KernelGlobals kg, return (path_flag & PATH_RAY_TRANSPARENT_BACKGROUND) != 0; } -/* NOTE: Leaves kernel scheduling information untouched. Use INIT semantic for one of the paths - * after this function. */ -ccl_device_inline bool kernel_shadow_catcher_split(KernelGlobals kg, - IntegratorState state, - const int object_flags) -{ -#ifdef __SHADOW_CATCHER__ - - if (!kernel_shadow_catcher_is_path_split_bounce(kg, state, object_flags)) { - return false; - } - - /* The split is to be done. Mark the current state as such, so that it stops contributing to the - * shadow catcher matte pass, but keeps contributing to the combined pass. */ - INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_SHADOW_CATCHER_HIT; - - /* Split new state from the current one. This new state will only track contribution of shadow - * catcher objects ignoring non-catcher objects. */ - integrator_state_shadow_catcher_split(kg, state); - - return true; -#else - (void)object_flags; - return false; -#endif -} - #ifdef __SHADOW_CATCHER__ ccl_device_forceinline bool kernel_shadow_catcher_is_matte_path(const uint32_t path_flag) diff --git a/intern/cycles/kernel/integrator/state.h b/intern/cycles/kernel/integrator/state.h index 86dac0a65cf..ed2a0be3068 100644 --- a/intern/cycles/kernel/integrator/state.h +++ b/intern/cycles/kernel/integrator/state.h @@ -173,10 +173,10 @@ typedef const IntegratorShadowStateCPU *ccl_restrict ConstIntegratorShadowState; /* Array access on GPU with Structure-of-Arrays. */ -typedef const int IntegratorState; -typedef const int ConstIntegratorState; -typedef const int IntegratorShadowState; -typedef const int ConstIntegratorShadowState; +typedef int IntegratorState; +typedef int ConstIntegratorState; +typedef int IntegratorShadowState; +typedef int ConstIntegratorShadowState; # define INTEGRATOR_STATE_NULL -1 diff --git a/intern/cycles/kernel/integrator/state_util.h b/intern/cycles/kernel/integrator/state_util.h index dafe06e7009..99dae83233c 100644 --- a/intern/cycles/kernel/integrator/state_util.h +++ b/intern/cycles/kernel/integrator/state_util.h @@ -326,8 +326,8 @@ ccl_device_inline void integrator_shadow_state_move(KernelGlobals kg, /* NOTE: Leaves kernel scheduling information untouched. Use INIT semantic for one of the paths * after this function. */ -ccl_device_inline void integrator_state_shadow_catcher_split(KernelGlobals kg, - IntegratorState state) +ccl_device_inline IntegratorState integrator_state_shadow_catcher_split(KernelGlobals kg, + IntegratorState state) { #if defined(__KERNEL_GPU__) ConstIntegratorState to_state = atomic_fetch_and_add_uint32( @@ -337,14 +337,14 @@ ccl_device_inline void integrator_state_shadow_catcher_split(KernelGlobals kg, #else IntegratorStateCPU *ccl_restrict to_state = state + 1; - /* Only copy the required subset, since shadow intersections are big and irrelevant here. */ + /* Only copy the required subset for performance. */ to_state->path = state->path; to_state->ray = state->ray; to_state->isect = state->isect; integrator_state_copy_volume_stack(kg, to_state, state); #endif - INTEGRATOR_STATE_WRITE(to_state, path, flag) |= PATH_RAY_SHADOW_CATCHER_PASS; + return to_state; } #ifdef __KERNEL_CPU__ |