Cycles: reduce subsurface stack memory usage.
This is done by storing only a subset of PathRadiance, and by storing direct light immediately in the main PathRadiance. Saves about 10% of CUDA stack memory, and simplifies subsurface indirect ray code.
This commit is contained in:
parent
9ddee885ae
commit
400e6f37b8
@ -181,7 +181,6 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
|
|||||||
|
|
||||||
if(use_light_pass) {
|
if(use_light_pass) {
|
||||||
L->indirect = make_float3(0.0f, 0.0f, 0.0f);
|
L->indirect = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->direct_throughput = make_float3(0.0f, 0.0f, 0.0f);
|
|
||||||
L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
|
L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
|
L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
@ -202,18 +201,19 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
|
|||||||
L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
|
L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
|
L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
|
|
||||||
L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
|
|
||||||
L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
|
|
||||||
L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
|
|
||||||
L->path_scatter = make_float3(0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
L->transparent = 0.0f;
|
L->transparent = 0.0f;
|
||||||
L->emission = make_float3(0.0f, 0.0f, 0.0f);
|
L->emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->background = make_float3(0.0f, 0.0f, 0.0f);
|
L->background = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->ao = make_float3(0.0f, 0.0f, 0.0f);
|
L->ao = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
L->mist = 0.0f;
|
L->mist = 0.0f;
|
||||||
|
|
||||||
|
L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
L->state.glossy = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
L->state.transmission = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
L->state.subsurface = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
L->state.scatter = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
L->state.direct = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -245,26 +245,34 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput,
|
ccl_device_inline void path_radiance_bsdf_bounce(
|
||||||
BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label)
|
KernelGlobals *kg,
|
||||||
|
PathRadianceState *L_state,
|
||||||
|
ccl_addr_space float3 *throughput,
|
||||||
|
BsdfEval *bsdf_eval,
|
||||||
|
float bsdf_pdf, int bounce, int bsdf_label)
|
||||||
{
|
{
|
||||||
float inverse_pdf = 1.0f/bsdf_pdf;
|
float inverse_pdf = 1.0f/bsdf_pdf;
|
||||||
|
|
||||||
#ifdef __PASSES__
|
#ifdef __PASSES__
|
||||||
if(L->use_light_pass) {
|
if(kernel_data.film.use_light_pass) {
|
||||||
if(bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
|
if(bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
|
||||||
/* first on directly visible surface */
|
/* first on directly visible surface */
|
||||||
float3 value = *throughput*inverse_pdf;
|
float3 value = *throughput*inverse_pdf;
|
||||||
|
|
||||||
L->path_diffuse = bsdf_eval->diffuse*value;
|
L_state->diffuse = bsdf_eval->diffuse*value;
|
||||||
L->path_glossy = bsdf_eval->glossy*value;
|
L_state->glossy = bsdf_eval->glossy*value;
|
||||||
L->path_transmission = bsdf_eval->transmission*value;
|
L_state->transmission = bsdf_eval->transmission*value;
|
||||||
L->path_subsurface = bsdf_eval->subsurface*value;
|
L_state->subsurface = bsdf_eval->subsurface*value;
|
||||||
L->path_scatter = bsdf_eval->scatter*value;
|
L_state->scatter = bsdf_eval->scatter*value;
|
||||||
|
|
||||||
*throughput = L->path_diffuse + L->path_glossy + L->path_transmission + L->path_subsurface + L->path_scatter;
|
*throughput = L_state->diffuse +
|
||||||
|
L_state->glossy +
|
||||||
|
L_state->transmission +
|
||||||
|
L_state->subsurface +
|
||||||
|
L_state->scatter;
|
||||||
|
|
||||||
L->direct_throughput = *throughput;
|
L_state->direct = *throughput;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* transparent bounce before first hit, or indirectly visible through BSDF */
|
/* transparent bounce before first hit, or indirectly visible through BSDF */
|
||||||
@ -493,19 +501,19 @@ ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
|
|||||||
* only a single throughput further along the path, here we recover just
|
* only a single throughput further along the path, here we recover just
|
||||||
* the indirect path that is not influenced by any particular BSDF type */
|
* the indirect path that is not influenced by any particular BSDF type */
|
||||||
if(L->use_light_pass) {
|
if(L->use_light_pass) {
|
||||||
L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput);
|
L->direct_emission = safe_divide_color(L->direct_emission, L->state.direct);
|
||||||
L->direct_diffuse += L->path_diffuse*L->direct_emission;
|
L->direct_diffuse += L->state.diffuse*L->direct_emission;
|
||||||
L->direct_glossy += L->path_glossy*L->direct_emission;
|
L->direct_glossy += L->state.glossy*L->direct_emission;
|
||||||
L->direct_transmission += L->path_transmission*L->direct_emission;
|
L->direct_transmission += L->state.transmission*L->direct_emission;
|
||||||
L->direct_subsurface += L->path_subsurface*L->direct_emission;
|
L->direct_subsurface += L->state.subsurface*L->direct_emission;
|
||||||
L->direct_scatter += L->path_scatter*L->direct_emission;
|
L->direct_scatter += L->state.scatter*L->direct_emission;
|
||||||
|
|
||||||
L->indirect = safe_divide_color(L->indirect, L->direct_throughput);
|
L->indirect = safe_divide_color(L->indirect, L->state.direct);
|
||||||
L->indirect_diffuse += L->path_diffuse*L->indirect;
|
L->indirect_diffuse += L->state.diffuse*L->indirect;
|
||||||
L->indirect_glossy += L->path_glossy*L->indirect;
|
L->indirect_glossy += L->state.glossy*L->indirect;
|
||||||
L->indirect_transmission += L->path_transmission*L->indirect;
|
L->indirect_transmission += L->state.transmission*L->indirect;
|
||||||
L->indirect_subsurface += L->path_subsurface*L->indirect;
|
L->indirect_subsurface += L->state.subsurface*L->indirect;
|
||||||
L->indirect_scatter += L->path_scatter*L->indirect;
|
L->indirect_scatter += L->state.scatter*L->indirect;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -514,11 +522,11 @@ ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
|
|||||||
{
|
{
|
||||||
#ifdef __PASSES__
|
#ifdef __PASSES__
|
||||||
if(L->use_light_pass) {
|
if(L->use_light_pass) {
|
||||||
L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
|
L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
|
L->state.glossy = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
|
L->state.transmission = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
|
L->state.subsurface = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->path_scatter = make_float3(0.0f, 0.0f, 0.0f);
|
L->state.scatter = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
|
L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
L->indirect = make_float3(0.0f, 0.0f, 0.0f);
|
L->indirect = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
@ -531,11 +539,7 @@ ccl_device_inline void path_radiance_copy_indirect(PathRadiance *L,
|
|||||||
{
|
{
|
||||||
#ifdef __PASSES__
|
#ifdef __PASSES__
|
||||||
if(L->use_light_pass) {
|
if(L->use_light_pass) {
|
||||||
L->path_diffuse = L_src->path_diffuse;
|
L->state = L_src->state;
|
||||||
L->path_glossy = L_src->path_glossy;
|
|
||||||
L->path_transmission = L_src->path_transmission;
|
|
||||||
L->path_subsurface = L_src->path_subsurface;
|
|
||||||
L->path_scatter = L_src->path_scatter;
|
|
||||||
|
|
||||||
L->direct_emission = L_src->direct_emission;
|
L->direct_emission = L_src->direct_emission;
|
||||||
L->indirect = L_src->indirect;
|
L->indirect = L_src->indirect;
|
||||||
|
@ -103,7 +103,6 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
|
|||||||
throughput,
|
throughput,
|
||||||
&state,
|
&state,
|
||||||
&L_sample);
|
&L_sample);
|
||||||
kernel_path_subsurface_accum_indirect(&ss_indirect, &L_sample);
|
|
||||||
}
|
}
|
||||||
is_sss_sample = true;
|
is_sss_sample = true;
|
||||||
}
|
}
|
||||||
@ -114,7 +113,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
|
|||||||
if(!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
|
if(!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
|
||||||
kernel_path_surface_connect_light(kg, 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, sd, &throughput, &state, &L_sample, &ray)) {
|
if(kernel_path_surface_bounce(kg, sd, &throughput, &state, &L_sample.state, &ray)) {
|
||||||
#ifdef __LAMP_MIS__
|
#ifdef __LAMP_MIS__
|
||||||
state.ray_t = 0.0f;
|
state.ray_t = 0.0f;
|
||||||
#endif
|
#endif
|
||||||
|
@ -222,7 +222,7 @@ ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(
|
|||||||
kernel_volume_decoupled_free(kg, &volume_segment);
|
kernel_volume_decoupled_free(kg, &volume_segment);
|
||||||
|
|
||||||
if(result == VOLUME_PATH_SCATTERED) {
|
if(result == VOLUME_PATH_SCATTERED) {
|
||||||
if(kernel_path_volume_bounce(kg, sd, throughput, state, L, ray))
|
if(kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, ray))
|
||||||
return VOLUME_PATH_SCATTERED;
|
return VOLUME_PATH_SCATTERED;
|
||||||
else
|
else
|
||||||
return VOLUME_PATH_MISSED;
|
return VOLUME_PATH_MISSED;
|
||||||
@ -244,7 +244,7 @@ ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(
|
|||||||
kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
|
kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
|
||||||
|
|
||||||
/* indirect light bounce */
|
/* indirect light bounce */
|
||||||
if(kernel_path_volume_bounce(kg, sd, throughput, state, L, ray))
|
if(kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, ray))
|
||||||
return VOLUME_PATH_SCATTERED;
|
return VOLUME_PATH_SCATTERED;
|
||||||
else
|
else
|
||||||
return VOLUME_PATH_MISSED;
|
return VOLUME_PATH_MISSED;
|
||||||
@ -519,7 +519,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
|
|||||||
}
|
}
|
||||||
#endif /* defined(__EMISSION__) */
|
#endif /* defined(__EMISSION__) */
|
||||||
|
|
||||||
if(!kernel_path_surface_bounce(kg, sd, &throughput, state, L, ray))
|
if(!kernel_path_surface_bounce(kg, sd, &throughput, state, &L->state, ray))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -648,13 +648,11 @@ ccl_device_forceinline void kernel_path_integrate(
|
|||||||
kernel_path_surface_connect_light(kg, &sd, emission_sd, throughput, state, L);
|
kernel_path_surface_connect_light(kg, &sd, emission_sd, throughput, state, L);
|
||||||
|
|
||||||
/* compute direct lighting and next bounce */
|
/* compute direct lighting and next bounce */
|
||||||
if(!kernel_path_surface_bounce(kg, &sd, &throughput, state, L, ray))
|
if(!kernel_path_surface_bounce(kg, &sd, &throughput, state, &L->state, ray))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __SUBSURFACE__
|
#ifdef __SUBSURFACE__
|
||||||
kernel_path_subsurface_accum_indirect(&ss_indirect, L);
|
|
||||||
|
|
||||||
/* Trace indirect subsurface rays by restarting the loop. this uses less
|
/* Trace indirect subsurface rays by restarting the loop. this uses less
|
||||||
* stack memory than invoking kernel_path_indirect.
|
* stack memory than invoking kernel_path_indirect.
|
||||||
*/
|
*/
|
||||||
|
@ -128,7 +128,7 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
|
|||||||
num_samples,
|
num_samples,
|
||||||
&tp,
|
&tp,
|
||||||
&ps,
|
&ps,
|
||||||
L,
|
&L->state,
|
||||||
&bsdf_ray,
|
&bsdf_ray,
|
||||||
sum_sample_weight))
|
sum_sample_weight))
|
||||||
{
|
{
|
||||||
@ -350,7 +350,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
|
|||||||
&sd,
|
&sd,
|
||||||
&tp,
|
&tp,
|
||||||
&ps,
|
&ps,
|
||||||
L,
|
&L->state,
|
||||||
&pray))
|
&pray))
|
||||||
{
|
{
|
||||||
kernel_path_indirect(kg,
|
kernel_path_indirect(kg,
|
||||||
@ -405,7 +405,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
|
|||||||
&sd,
|
&sd,
|
||||||
&tp,
|
&tp,
|
||||||
&ps,
|
&ps,
|
||||||
L,
|
&L->state,
|
||||||
&pray))
|
&pray))
|
||||||
{
|
{
|
||||||
kernel_path_indirect(kg,
|
kernel_path_indirect(kg,
|
||||||
|
@ -43,7 +43,7 @@ bool kernel_path_subsurface_scatter(
|
|||||||
* the second one should be converted to a diffuse BSDF to
|
* the second one should be converted to a diffuse BSDF to
|
||||||
* avoid this.
|
* avoid this.
|
||||||
*/
|
*/
|
||||||
kernel_assert(!ss_indirect->tracing);
|
kernel_assert(!(state->flag & PATH_RAY_DIFFUSE_ANCESTOR));
|
||||||
|
|
||||||
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
|
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ bool kernel_path_subsurface_scatter(
|
|||||||
bssrdf_u, bssrdf_v,
|
bssrdf_u, bssrdf_v,
|
||||||
false);
|
false);
|
||||||
# ifdef __VOLUME__
|
# ifdef __VOLUME__
|
||||||
ss_indirect->need_update_volume_stack =
|
bool need_update_volume_stack =
|
||||||
kernel_data.integrator.use_volumes &&
|
kernel_data.integrator.use_volumes &&
|
||||||
sd->object_flag & SD_OBJECT_INTERSECTS_VOLUME;
|
sd->object_flag & SD_OBJECT_INTERSECTS_VOLUME;
|
||||||
# endif /* __VOLUME__ */
|
# endif /* __VOLUME__ */
|
||||||
@ -75,28 +75,25 @@ bool kernel_path_subsurface_scatter(
|
|||||||
sc,
|
sc,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
|
kernel_path_surface_connect_light(kg, sd, emission_sd, *throughput, state, L);
|
||||||
|
|
||||||
ccl_addr_space PathState *hit_state = &ss_indirect->state[ss_indirect->num_rays];
|
ccl_addr_space PathState *hit_state = &ss_indirect->state[ss_indirect->num_rays];
|
||||||
ccl_addr_space Ray *hit_ray = &ss_indirect->rays[ss_indirect->num_rays];
|
ccl_addr_space Ray *hit_ray = &ss_indirect->rays[ss_indirect->num_rays];
|
||||||
ccl_addr_space float3 *hit_tp = &ss_indirect->throughputs[ss_indirect->num_rays];
|
ccl_addr_space float3 *hit_tp = &ss_indirect->throughputs[ss_indirect->num_rays];
|
||||||
PathRadiance *hit_L = &ss_indirect->L[ss_indirect->num_rays];
|
PathRadianceState *hit_L_state = &ss_indirect->L_state[ss_indirect->num_rays];
|
||||||
|
|
||||||
*hit_state = *state;
|
*hit_state = *state;
|
||||||
*hit_ray = *ray;
|
*hit_ray = *ray;
|
||||||
*hit_tp = *throughput;
|
*hit_tp = *throughput;
|
||||||
|
*hit_L_state = L->state;
|
||||||
|
|
||||||
hit_state->rng_offset += PRNG_BOUNCE_NUM;
|
hit_state->rng_offset += PRNG_BOUNCE_NUM;
|
||||||
|
|
||||||
path_radiance_init(hit_L, kernel_data.film.use_light_pass);
|
|
||||||
hit_L->direct_throughput = L->direct_throughput;
|
|
||||||
path_radiance_copy_indirect(hit_L, L);
|
|
||||||
|
|
||||||
kernel_path_surface_connect_light(kg, sd, emission_sd, *hit_tp, state, hit_L);
|
|
||||||
|
|
||||||
if(kernel_path_surface_bounce(kg,
|
if(kernel_path_surface_bounce(kg,
|
||||||
sd,
|
sd,
|
||||||
hit_tp,
|
hit_tp,
|
||||||
hit_state,
|
hit_state,
|
||||||
hit_L,
|
hit_L_state,
|
||||||
hit_ray))
|
hit_ray))
|
||||||
{
|
{
|
||||||
# ifdef __LAMP_MIS__
|
# ifdef __LAMP_MIS__
|
||||||
@ -104,7 +101,7 @@ bool kernel_path_subsurface_scatter(
|
|||||||
# endif /* __LAMP_MIS__ */
|
# endif /* __LAMP_MIS__ */
|
||||||
|
|
||||||
# ifdef __VOLUME__
|
# ifdef __VOLUME__
|
||||||
if(ss_indirect->need_update_volume_stack) {
|
if(need_update_volume_stack) {
|
||||||
Ray volume_ray = *ray;
|
Ray volume_ray = *ray;
|
||||||
/* Setup ray from previous surface point to the new one. */
|
/* Setup ray from previous surface point to the new one. */
|
||||||
volume_ray.D = normalize_len(hit_ray->P - volume_ray.P,
|
volume_ray.D = normalize_len(hit_ray->P - volume_ray.P,
|
||||||
@ -117,12 +114,8 @@ bool kernel_path_subsurface_scatter(
|
|||||||
hit_state->volume_stack);
|
hit_state->volume_stack);
|
||||||
}
|
}
|
||||||
# endif /* __VOLUME__ */
|
# endif /* __VOLUME__ */
|
||||||
path_radiance_reset_indirect(L);
|
|
||||||
ss_indirect->num_rays++;
|
ss_indirect->num_rays++;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
path_radiance_accum_sample(L, hit_L);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -132,23 +125,9 @@ bool kernel_path_subsurface_scatter(
|
|||||||
ccl_device_inline void kernel_path_subsurface_init_indirect(
|
ccl_device_inline void kernel_path_subsurface_init_indirect(
|
||||||
ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
|
ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
|
||||||
{
|
{
|
||||||
ss_indirect->tracing = false;
|
|
||||||
ss_indirect->num_rays = 0;
|
ss_indirect->num_rays = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device void kernel_path_subsurface_accum_indirect(
|
|
||||||
ccl_addr_space SubsurfaceIndirectRays *ss_indirect,
|
|
||||||
PathRadiance *L)
|
|
||||||
{
|
|
||||||
if(ss_indirect->tracing) {
|
|
||||||
path_radiance_sum_indirect(L);
|
|
||||||
path_radiance_accum_sample(&ss_indirect->direct_L, L);
|
|
||||||
if(ss_indirect->num_rays == 0) {
|
|
||||||
*L = ss_indirect->direct_L;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ccl_device void kernel_path_subsurface_setup_indirect(
|
ccl_device void kernel_path_subsurface_setup_indirect(
|
||||||
KernelGlobals *kg,
|
KernelGlobals *kg,
|
||||||
ccl_addr_space SubsurfaceIndirectRays *ss_indirect,
|
ccl_addr_space SubsurfaceIndirectRays *ss_indirect,
|
||||||
@ -157,20 +136,15 @@ ccl_device void kernel_path_subsurface_setup_indirect(
|
|||||||
PathRadiance *L,
|
PathRadiance *L,
|
||||||
ccl_addr_space float3 *throughput)
|
ccl_addr_space float3 *throughput)
|
||||||
{
|
{
|
||||||
if(!ss_indirect->tracing) {
|
|
||||||
ss_indirect->direct_L = *L;
|
|
||||||
}
|
|
||||||
ss_indirect->tracing = true;
|
|
||||||
|
|
||||||
/* Setup state, ray and throughput for indirect SSS rays. */
|
/* Setup state, ray and throughput for indirect SSS rays. */
|
||||||
ss_indirect->num_rays--;
|
ss_indirect->num_rays--;
|
||||||
|
|
||||||
ccl_addr_space Ray *indirect_ray = &ss_indirect->rays[ss_indirect->num_rays];
|
path_radiance_sum_indirect(L);
|
||||||
PathRadiance *indirect_L = &ss_indirect->L[ss_indirect->num_rays];
|
path_radiance_reset_indirect(L);
|
||||||
|
|
||||||
*state = ss_indirect->state[ss_indirect->num_rays];
|
*state = ss_indirect->state[ss_indirect->num_rays];
|
||||||
*ray = *indirect_ray;
|
*ray = ss_indirect->rays[ss_indirect->num_rays];
|
||||||
*L = *indirect_L;
|
L->state = ss_indirect->L_state[ss_indirect->num_rays];
|
||||||
*throughput = ss_indirect->throughputs[ss_indirect->num_rays];
|
*throughput = ss_indirect->throughputs[ss_indirect->num_rays];
|
||||||
|
|
||||||
state->rng_offset += ss_indirect->num_rays * PRNG_BOUNCE_NUM;
|
state->rng_offset += ss_indirect->num_rays * PRNG_BOUNCE_NUM;
|
||||||
|
@ -150,7 +150,7 @@ ccl_device bool kernel_branched_path_surface_bounce(
|
|||||||
int num_samples,
|
int num_samples,
|
||||||
ccl_addr_space float3 *throughput,
|
ccl_addr_space float3 *throughput,
|
||||||
ccl_addr_space PathState *state,
|
ccl_addr_space PathState *state,
|
||||||
PathRadiance *L,
|
PathRadianceState *L_state,
|
||||||
ccl_addr_space Ray *ray,
|
ccl_addr_space Ray *ray,
|
||||||
float sum_sample_weight)
|
float sum_sample_weight)
|
||||||
{
|
{
|
||||||
@ -170,7 +170,7 @@ ccl_device bool kernel_branched_path_surface_bounce(
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* modify throughput */
|
/* modify throughput */
|
||||||
path_radiance_bsdf_bounce(L, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
|
path_radiance_bsdf_bounce(kg, L_state, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
|
||||||
|
|
||||||
#ifdef __DENOISING_FEATURES__
|
#ifdef __DENOISING_FEATURES__
|
||||||
state->denoising_feature_weight *= sc->sample_weight / (sum_sample_weight * num_samples);
|
state->denoising_feature_weight *= sc->sample_weight / (sum_sample_weight * num_samples);
|
||||||
@ -271,7 +271,7 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
|
|||||||
ShaderData *sd,
|
ShaderData *sd,
|
||||||
ccl_addr_space float3 *throughput,
|
ccl_addr_space float3 *throughput,
|
||||||
ccl_addr_space PathState *state,
|
ccl_addr_space PathState *state,
|
||||||
PathRadiance *L,
|
PathRadianceState *L_state,
|
||||||
ccl_addr_space Ray *ray)
|
ccl_addr_space Ray *ray)
|
||||||
{
|
{
|
||||||
/* no BSDF? we can stop here */
|
/* no BSDF? we can stop here */
|
||||||
@ -292,7 +292,7 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* modify throughput */
|
/* modify throughput */
|
||||||
path_radiance_bsdf_bounce(L, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
|
path_radiance_bsdf_bounce(kg, L_state, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
|
||||||
|
|
||||||
/* set labels */
|
/* set labels */
|
||||||
if(!(label & LABEL_TRANSPARENT)) {
|
if(!(label & LABEL_TRANSPARENT)) {
|
||||||
|
@ -68,7 +68,7 @@ bool kernel_path_volume_bounce(
|
|||||||
ShaderData *sd,
|
ShaderData *sd,
|
||||||
ccl_addr_space float3 *throughput,
|
ccl_addr_space float3 *throughput,
|
||||||
ccl_addr_space PathState *state,
|
ccl_addr_space PathState *state,
|
||||||
PathRadiance *L,
|
PathRadianceState *L_state,
|
||||||
ccl_addr_space Ray *ray)
|
ccl_addr_space Ray *ray)
|
||||||
{
|
{
|
||||||
/* sample phase function */
|
/* sample phase function */
|
||||||
@ -87,7 +87,7 @@ bool kernel_path_volume_bounce(
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* modify throughput */
|
/* modify throughput */
|
||||||
path_radiance_bsdf_bounce(L, throughput, &phase_eval, phase_pdf, state->bounce, label);
|
path_radiance_bsdf_bounce(kg, L_state, throughput, &phase_eval, phase_pdf, state->bounce, label);
|
||||||
|
|
||||||
/* set labels */
|
/* set labels */
|
||||||
state->ray_pdf = phase_pdf;
|
state->ray_pdf = phase_pdf;
|
||||||
|
@ -466,6 +466,18 @@ typedef struct DebugData {
|
|||||||
} DebugData;
|
} DebugData;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef ccl_addr_space struct PathRadianceState {
|
||||||
|
#ifdef __PASSES__
|
||||||
|
float3 diffuse;
|
||||||
|
float3 glossy;
|
||||||
|
float3 transmission;
|
||||||
|
float3 subsurface;
|
||||||
|
float3 scatter;
|
||||||
|
|
||||||
|
float3 direct;
|
||||||
|
#endif
|
||||||
|
} PathRadianceState;
|
||||||
|
|
||||||
typedef ccl_addr_space struct PathRadiance {
|
typedef ccl_addr_space struct PathRadiance {
|
||||||
#ifdef __PASSES__
|
#ifdef __PASSES__
|
||||||
int use_light_pass;
|
int use_light_pass;
|
||||||
@ -478,7 +490,6 @@ typedef ccl_addr_space struct PathRadiance {
|
|||||||
float3 ao;
|
float3 ao;
|
||||||
|
|
||||||
float3 indirect;
|
float3 indirect;
|
||||||
float3 direct_throughput;
|
|
||||||
float3 direct_emission;
|
float3 direct_emission;
|
||||||
|
|
||||||
float3 color_diffuse;
|
float3 color_diffuse;
|
||||||
@ -499,16 +510,12 @@ typedef ccl_addr_space struct PathRadiance {
|
|||||||
float3 indirect_subsurface;
|
float3 indirect_subsurface;
|
||||||
float3 indirect_scatter;
|
float3 indirect_scatter;
|
||||||
|
|
||||||
float3 path_diffuse;
|
|
||||||
float3 path_glossy;
|
|
||||||
float3 path_transmission;
|
|
||||||
float3 path_subsurface;
|
|
||||||
float3 path_scatter;
|
|
||||||
|
|
||||||
float4 shadow;
|
float4 shadow;
|
||||||
float mist;
|
float mist;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PathRadianceState state;
|
||||||
|
|
||||||
#ifdef __SHADOW_TRICKS__
|
#ifdef __SHADOW_TRICKS__
|
||||||
/* Total light reachable across the path, ignoring shadow blocked queries. */
|
/* Total light reachable across the path, ignoring shadow blocked queries. */
|
||||||
float3 path_total;
|
float3 path_total;
|
||||||
@ -1032,8 +1039,7 @@ typedef struct PathState {
|
|||||||
/* Subsurface */
|
/* Subsurface */
|
||||||
|
|
||||||
/* Struct to gather multiple SSS hits. */
|
/* Struct to gather multiple SSS hits. */
|
||||||
typedef struct SubsurfaceIntersection
|
typedef struct SubsurfaceIntersection {
|
||||||
{
|
|
||||||
Ray ray;
|
Ray ray;
|
||||||
float3 weight[BSSRDF_MAX_HITS];
|
float3 weight[BSSRDF_MAX_HITS];
|
||||||
|
|
||||||
@ -1043,17 +1049,14 @@ typedef struct SubsurfaceIntersection
|
|||||||
} SubsurfaceIntersection;
|
} SubsurfaceIntersection;
|
||||||
|
|
||||||
/* Struct to gather SSS indirect rays and delay tracing them. */
|
/* Struct to gather SSS indirect rays and delay tracing them. */
|
||||||
typedef struct SubsurfaceIndirectRays
|
typedef struct SubsurfaceIndirectRays {
|
||||||
{
|
|
||||||
bool need_update_volume_stack;
|
|
||||||
bool tracing;
|
|
||||||
PathState state[BSSRDF_MAX_HITS];
|
PathState state[BSSRDF_MAX_HITS];
|
||||||
struct PathRadiance direct_L;
|
|
||||||
|
|
||||||
int num_rays;
|
int num_rays;
|
||||||
|
|
||||||
struct Ray rays[BSSRDF_MAX_HITS];
|
struct Ray rays[BSSRDF_MAX_HITS];
|
||||||
float3 throughputs[BSSRDF_MAX_HITS];
|
float3 throughputs[BSSRDF_MAX_HITS];
|
||||||
struct PathRadiance L[BSSRDF_MAX_HITS];
|
struct PathRadianceState L_state[BSSRDF_MAX_HITS];
|
||||||
} SubsurfaceIndirectRays;
|
} SubsurfaceIndirectRays;
|
||||||
|
|
||||||
/* Constant Kernel Data
|
/* Constant Kernel Data
|
||||||
|
@ -87,7 +87,6 @@ ccl_device_inline bool kernel_split_branched_indirect_start_shared(KernelGlobals
|
|||||||
PathRadiance *inactive_L = &kernel_split_state.path_radiance[inactive_ray];
|
PathRadiance *inactive_L = &kernel_split_state.path_radiance[inactive_ray];
|
||||||
|
|
||||||
path_radiance_init(inactive_L, kernel_data.film.use_light_pass);
|
path_radiance_init(inactive_L, kernel_data.film.use_light_pass);
|
||||||
inactive_L->direct_throughput = L->direct_throughput;
|
|
||||||
path_radiance_copy_indirect(inactive_L, L);
|
path_radiance_copy_indirect(inactive_L, L);
|
||||||
|
|
||||||
ray_state[inactive_ray] = RAY_REGENERATED;
|
ray_state[inactive_ray] = RAY_REGENERATED;
|
||||||
@ -176,7 +175,7 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(
|
|||||||
num_samples,
|
num_samples,
|
||||||
tp,
|
tp,
|
||||||
ps,
|
ps,
|
||||||
L,
|
&L->state,
|
||||||
bsdf_ray,
|
bsdf_ray,
|
||||||
sum_sample_weight))
|
sum_sample_weight))
|
||||||
{
|
{
|
||||||
|
@ -65,7 +65,7 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K
|
|||||||
kernel_path_volume_connect_light(kg, 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 */
|
/* indirect light bounce */
|
||||||
if(!kernel_path_volume_bounce(kg, sd, tp, ps, L, pray)) {
|
if(!kernel_path_volume_bounce(kg, sd, tp, ps, &L->state, pray)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
|
|||||||
kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
|
kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
|
||||||
|
|
||||||
/* indirect light bounce */
|
/* indirect light bounce */
|
||||||
if(kernel_path_volume_bounce(kg, sd, throughput, state, L, ray)) {
|
if(kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, ray)) {
|
||||||
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -54,7 +54,6 @@ ccl_device void kernel_indirect_subsurface(KernelGlobals *kg)
|
|||||||
#endif
|
#endif
|
||||||
if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
|
if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
|
||||||
ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
|
ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
|
||||||
kernel_path_subsurface_accum_indirect(ss_indirect, L);
|
|
||||||
|
|
||||||
/* Trace indirect subsurface rays by restarting the loop. this uses less
|
/* Trace indirect subsurface rays by restarting the loop. this uses less
|
||||||
* stack memory than invoking kernel_path_indirect.
|
* stack memory than invoking kernel_path_indirect.
|
||||||
|
@ -134,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)) {
|
if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||||
#endif
|
#endif
|
||||||
/* Compute direct lighting and next bounce. */
|
/* Compute direct lighting and next bounce. */
|
||||||
if(!kernel_path_surface_bounce(kg, sd, throughput, state, L, ray)) {
|
if(!kernel_path_surface_bounce(kg, sd, throughput, state, &L->state, ray)) {
|
||||||
kernel_split_path_end(kg, ray_index);
|
kernel_split_path_end(kg, ray_index);
|
||||||
}
|
}
|
||||||
#ifdef __BRANCHED_PATH__
|
#ifdef __BRANCHED_PATH__
|
||||||
|
Loading…
Reference in New Issue
Block a user