diff --git a/intern/cycles/kernel/integrator/integrator_volume_stack.h b/intern/cycles/kernel/integrator/integrator_volume_stack.h index 5d11d6be04f..f7d86cf6040 100644 --- a/intern/cycles/kernel/integrator/integrator_volume_stack.h +++ b/intern/cycles/kernel/integrator/integrator_volume_stack.h @@ -167,7 +167,16 @@ ccl_device void volume_stack_init(INTEGRATOR_STATE_ARGS, } #endif -ccl_device void volume_stack_enter_exit(INTEGRATOR_STATE_ARGS, const ShaderData *sd) +template +ccl_device void volume_stack_enter_exit_common(INTEGRATOR_STATE_ARGS, + const ShaderData *sd, + const ReadShaderProc &read_shader_proc, + const ReadObjectProc &read_object_proc, + const WriteShaderProc &write_shader_proc, + const WriteObjectProc &write_object_proc) { /* todo: we should have some way for objects to indicate if they want the * world shader to work inside them. excluding it by default is problematic @@ -178,16 +187,14 @@ ccl_device void volume_stack_enter_exit(INTEGRATOR_STATE_ARGS, const ShaderData if (sd->flag & SD_BACKFACING) { /* Exit volume object: remove from stack. */ - for (int i = 0; INTEGRATOR_STATE_ARRAY(volume_stack, i, shader) != SHADER_NONE; i++) { - if (INTEGRATOR_STATE_ARRAY(volume_stack, i, object) == sd->object) { + for (int i = 0; read_shader_proc(i) != SHADER_NONE; i++) { + if (read_object_proc(i) == sd->object) { /* Shift back next stack entries. */ do { - INTEGRATOR_STATE_ARRAY_WRITE(volume_stack, i, shader) = INTEGRATOR_STATE_ARRAY( - volume_stack, i + 1, shader); - INTEGRATOR_STATE_ARRAY_WRITE(volume_stack, i, object) = INTEGRATOR_STATE_ARRAY( - volume_stack, i + 1, object); + write_shader_proc(i, read_shader_proc(i + 1)); + write_object_proc(i, read_object_proc(i + 1)); i++; - } while (INTEGRATOR_STATE_ARRAY(volume_stack, i, shader) != SHADER_NONE); + } while (read_shader_proc(i) != SHADER_NONE); return; } @@ -197,9 +204,9 @@ ccl_device void volume_stack_enter_exit(INTEGRATOR_STATE_ARGS, const ShaderData /* Enter volume object: add to stack. */ int i; - for (i = 0; INTEGRATOR_STATE_ARRAY(volume_stack, i, shader) != SHADER_NONE; i++) { + for (i = 0; read_shader_proc(i) != SHADER_NONE; i++) { /* Already in the stack? then we have nothing to do. */ - if (INTEGRATOR_STATE_ARRAY(volume_stack, i, object) == sd->object) { + if (read_object_proc(i) == sd->object) { return; } } @@ -210,58 +217,36 @@ ccl_device void volume_stack_enter_exit(INTEGRATOR_STATE_ARGS, const ShaderData } /* Add to the end of the stack. */ - INTEGRATOR_STATE_ARRAY_WRITE(volume_stack, i, shader) = sd->shader; - INTEGRATOR_STATE_ARRAY_WRITE(volume_stack, i, object) = sd->object; - INTEGRATOR_STATE_ARRAY_WRITE(volume_stack, i + 1, shader) = SHADER_NONE; + write_shader_proc(i, sd->shader); + write_object_proc(i, sd->object); + write_shader_proc(i + 1, SHADER_NONE); } } -ccl_device void shadow_volume_stack_enter_exit(INTEGRATOR_STATE_ARGS, const ShaderData *sd) +ccl_device void volume_stack_enter_exit(INTEGRATOR_STATE_ARGS, const ShaderData *sd) { - /* Duplicate of volume_stack_enter_exit, unclear how to deduplicate - * in an elegant way. */ - if (!(sd->flag & SD_HAS_VOLUME)) { - return; - } - - if (sd->flag & SD_BACKFACING) { - /* Exit volume object: remove from stack. */ - for (int i = 0; INTEGRATOR_STATE_ARRAY(shadow_volume_stack, i, shader) != SHADER_NONE; i++) { - if (INTEGRATOR_STATE_ARRAY(shadow_volume_stack, i, object) == sd->object) { - /* Shift back next stack entries. */ - do { - INTEGRATOR_STATE_ARRAY_WRITE(shadow_volume_stack, i, shader) = INTEGRATOR_STATE_ARRAY( - shadow_volume_stack, i + 1, shader); - INTEGRATOR_STATE_ARRAY_WRITE(shadow_volume_stack, i, object) = INTEGRATOR_STATE_ARRAY( - shadow_volume_stack, i + 1, object); - i++; - } while (INTEGRATOR_STATE_ARRAY(shadow_volume_stack, i, shader) != SHADER_NONE); - - return; - } - } - } - else { - /* Enter volume object: add to stack. */ - int i; - - for (i = 0; INTEGRATOR_STATE_ARRAY(shadow_volume_stack, i, shader) != SHADER_NONE; i++) { - /* Already in the stack? then we have nothing to do */ - if (INTEGRATOR_STATE_ARRAY(shadow_volume_stack, i, object) == sd->object) { - return; - } - } - - /* If we exceed the stack limit, ignore. */ - if (i >= VOLUME_STACK_SIZE - 1) { - return; - } + volume_stack_enter_exit_common( + INTEGRATOR_STATE_PASS, + sd, + [=](int i) -> int { return INTEGRATOR_STATE_ARRAY(volume_stack, i, shader); }, + [=](int i) -> int { return INTEGRATOR_STATE_ARRAY(volume_stack, i, object); }, + [=](int i, int shader) { INTEGRATOR_STATE_ARRAY_WRITE(volume_stack, i, shader) = shader; }, + [=](int i, int object) { INTEGRATOR_STATE_ARRAY_WRITE(volume_stack, i, object) = object; }); +} - /* Add to the end of the stack. */ - INTEGRATOR_STATE_ARRAY_WRITE(shadow_volume_stack, i, shader) = sd->shader; - INTEGRATOR_STATE_ARRAY_WRITE(shadow_volume_stack, i, object) = sd->object; - INTEGRATOR_STATE_ARRAY_WRITE(shadow_volume_stack, i + 1, shader) = SHADER_NONE; - } +ccl_device void shadow_volume_stack_enter_exit(INTEGRATOR_STATE_ARGS, const ShaderData *sd) +{ + volume_stack_enter_exit_common( + INTEGRATOR_STATE_PASS, + sd, + [=](int i) -> int { return INTEGRATOR_STATE_ARRAY(shadow_volume_stack, i, shader); }, + [=](int i) -> int { return INTEGRATOR_STATE_ARRAY(shadow_volume_stack, i, object); }, + [=](int i, int shader) { + INTEGRATOR_STATE_ARRAY_WRITE(shadow_volume_stack, i, shader) = shader; + }, + [=](int i, int object) { + INTEGRATOR_STATE_ARRAY_WRITE(shadow_volume_stack, i, object) = object; + }); } /* Clean stack after the last bounce.