Fix T53270: crash with multiscatter GGX after recent refactoring.

In fact this was an existing issue when exceeding the number of available
closure, but it's more common now that we set the number to 0 for shadows
and emission
This commit is contained in:
Brecht Van Lommel 2017-11-08 21:58:17 +01:00
parent 1ffa01b6f8
commit 21a535840d
3 changed files with 216 additions and 170 deletions

@ -45,7 +45,7 @@ ccl_device ccl_addr_space void *closure_alloc_extra(ShaderData *sd, int size)
int num_extra = ((size + sizeof(ShaderClosure) - 1) / sizeof(ShaderClosure));
if(num_extra > sd->num_closure_left) {
/* Remove previous closure. */
/* Remove previous closure if it was allocated. */
sd->num_closure--;
sd->num_closure_left++;
return NULL;

@ -186,22 +186,22 @@ public:
MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
{
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->extra = extra;
bsdf->ior = 1.5f;
bsdf->alpha_x = clearcoat_roughness;
bsdf->alpha_y = clearcoat_roughness;
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
bsdf->extra->clearcoat = clearcoat;
return bsdf;
if(!bsdf) {
return NULL;
}
return NULL;
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
return NULL;
}
bsdf->extra = extra;
bsdf->ior = 1.5f;
bsdf->alpha_x = clearcoat_roughness;
bsdf->alpha_y = clearcoat_roughness;
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
bsdf->extra->clearcoat = clearcoat;
return bsdf;
}
void setup(ShaderData *sd, int path_flag, float3 weight)
@ -359,18 +359,24 @@ public:
/* Technically, the MultiGGX Glass closure may also transmit. However,
* since this is set statically and only used for caustic flags, this
* is probably as good as it gets. */
if(!skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->extra = extra;
bsdf->extra->color = color;
bsdf->extra->cspec0 = cspec0;
return bsdf;
}
if(skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
return NULL;
}
return NULL;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
if(!bsdf) {
return NULL;
}
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
return NULL;
}
bsdf->extra = extra;
bsdf->extra->color = color;
bsdf->extra->cspec0 = cspec0;
return bsdf;
}
};
@ -437,17 +443,23 @@ public:
/* Technically, the MultiGGX closure may also transmit. However,
* since this is set statically and only used for caustic flags, this
* is probably as good as it gets. */
if(!skip(sd, path_flag, LABEL_GLOSSY|LABEL_REFLECT)) {
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->extra = extra;
bsdf->extra->color = color;
return bsdf;
}
if(skip(sd, path_flag, LABEL_GLOSSY|LABEL_REFLECT)) {
return NULL;
}
return NULL;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
if(!bsdf) {
return NULL;
}
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
return NULL;
}
bsdf->extra = extra;
bsdf->extra->color = color;
return bsdf;
}
};
@ -536,18 +548,24 @@ public:
/* Technically, the MultiGGX closure may also transmit. However,
* since this is set statically and only used for caustic flags, this
* is probably as good as it gets. */
if(!skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->extra = extra;
bsdf->extra->color = color;
bsdf->extra->cspec0 = cspec0;
return bsdf;
}
if(skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
return NULL;
}
return NULL;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
if(!bsdf) {
return NULL;
}
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
return NULL;
}
bsdf->extra = extra;
bsdf->extra->color = color;
bsdf->extra->cspec0 = cspec0;
return bsdf;
}
};

@ -269,33 +269,38 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float3 spec_weight = weight * specular_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->N = N;
bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
bsdf->T = T;
bsdf->extra = extra;
float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
float r2 = roughness * roughness;
bsdf->alpha_x = r2 / aspect;
bsdf->alpha_y = r2 * aspect;
float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y + 0.1f * base_color.z; // luminance approx.
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) + m_ctint * specular_tint;
bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic;
bsdf->extra->color = base_color;
/* setup bsdf */
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || roughness <= 0.075f) /* use single-scatter GGX */
sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
else /* use multi-scatter GGX */
sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
if(!bsdf){
break;
}
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
break;
}
bsdf->N = N;
bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
bsdf->T = T;
bsdf->extra = extra;
float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
float r2 = roughness * roughness;
bsdf->alpha_x = r2 / aspect;
bsdf->alpha_y = r2 * aspect;
float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y + 0.1f * base_color.z; // luminance approx.
float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) + m_ctint * specular_tint;
bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic;
bsdf->extra->color = base_color;
/* setup bsdf */
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || roughness <= 0.075f) /* use single-scatter GGX */
sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
else /* use multi-scatter GGX */
sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
}
#ifdef __CAUSTICS_TRICKS__
}
@ -318,22 +323,27 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
{
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight*fresnel);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->N = N;
bsdf->extra = extra;
bsdf->alpha_x = refl_roughness * refl_roughness;
bsdf->alpha_y = refl_roughness * refl_roughness;
bsdf->ior = ior;
bsdf->extra->color = base_color;
bsdf->extra->cspec0 = cspec0;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
if(!bsdf) {
break;
}
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
break;
}
bsdf->N = N;
bsdf->extra = extra;
bsdf->alpha_x = refl_roughness * refl_roughness;
bsdf->alpha_y = refl_roughness * refl_roughness;
bsdf->ior = ior;
bsdf->extra->color = base_color;
bsdf->extra->cspec0 = cspec0;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
}
/* refraction */
@ -342,43 +352,49 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
{
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), base_color*glass_weight*(1.0f - fresnel));
if(bsdf) {
bsdf->N = N;
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
transmission_roughness = 1.0f - (1.0f - refl_roughness) * (1.0f - transmission_roughness);
else
transmission_roughness = refl_roughness;
bsdf->alpha_x = transmission_roughness * transmission_roughness;
bsdf->alpha_y = transmission_roughness * transmission_roughness;
bsdf->ior = ior;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
if(!bsdf) {
break;
}
bsdf->N = N;
if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
transmission_roughness = 1.0f - (1.0f - refl_roughness) * (1.0f - transmission_roughness);
else
transmission_roughness = refl_roughness;
bsdf->alpha_x = transmission_roughness * transmission_roughness;
bsdf->alpha_y = transmission_roughness * transmission_roughness;
bsdf->ior = ior;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
}
}
else { /* use multi-scatter GGX */
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->N = N;
bsdf->extra = extra;
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
bsdf->alpha_x = roughness * roughness;
bsdf->alpha_y = roughness * roughness;
bsdf->ior = ior;
bsdf->extra->color = base_color;
bsdf->extra->cspec0 = cspec0;
/* setup bsdf */
sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
if(!bsdf) {
break;
}
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
break;
}
bsdf->N = N;
bsdf->extra = extra;
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
bsdf->alpha_x = roughness * roughness;
bsdf->alpha_y = roughness * roughness;
bsdf->ior = ior;
bsdf->extra->color = base_color;
bsdf->extra->cspec0 = cspec0;
/* setup bsdf */
sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
}
}
#ifdef __CAUSTICS_TRICKS__
@ -391,22 +407,27 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
if(clearcoat > CLOSURE_WEIGHT_CUTOFF) {
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->N = clearcoat_normal;
bsdf->ior = 1.5f;
bsdf->extra = extra;
bsdf->alpha_x = clearcoat_roughness * clearcoat_roughness;
bsdf->alpha_y = clearcoat_roughness * clearcoat_roughness;
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
bsdf->extra->clearcoat = clearcoat;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
if(!bsdf) {
break;
}
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
break;
}
bsdf->N = clearcoat_normal;
bsdf->ior = 1.5f;
bsdf->extra = extra;
bsdf->alpha_x = clearcoat_roughness * clearcoat_roughness;
bsdf->alpha_y = clearcoat_roughness * clearcoat_roughness;
bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
bsdf->extra->clearcoat = clearcoat;
/* setup bsdf */
sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
}
#ifdef __CAUSTICS_TRICKS__
}
@ -461,30 +482,33 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float3 weight = sd->svm_closure_weight * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
if(bsdf) {
bsdf->N = N;
bsdf->alpha_x = param1;
bsdf->alpha_y = param1;
bsdf->ior = 0.0f;
bsdf->extra = NULL;
if(!bsdf) {
break;
}
/* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID)
sd->flag |= bsdf_reflection_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
kernel_assert(stack_valid(data_node.z));
bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf->extra) {
bsdf->extra->color = stack_load_float3(stack, data_node.z);
sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
}
bsdf->N = N;
bsdf->alpha_x = param1;
bsdf->alpha_y = param1;
bsdf->ior = 0.0f;
bsdf->extra = NULL;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID)
sd->flag |= bsdf_reflection_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
kernel_assert(stack_valid(data_node.z));
bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf->extra) {
bsdf->extra->color = stack_load_float3(stack, data_node.z);
sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
}
else
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
}
else {
sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
}
break;
@ -586,25 +610,29 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
float3 weight = sd->svm_closure_weight * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf && extra) {
bsdf->N = N;
bsdf->extra = extra;
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
bsdf->alpha_x = param1;
bsdf->alpha_y = param1;
float eta = fmaxf(param2, 1e-5f);
bsdf->ior = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
kernel_assert(stack_valid(data_node.z));
bsdf->extra->color = stack_load_float3(stack, data_node.z);
/* setup bsdf */
sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
if(!bsdf) {
break;
}
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(!extra) {
break;
}
bsdf->N = N;
bsdf->extra = extra;
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
bsdf->alpha_x = param1;
bsdf->alpha_y = param1;
float eta = fmaxf(param2, 1e-5f);
bsdf->ior = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
kernel_assert(stack_valid(data_node.z));
bsdf->extra->color = stack_load_float3(stack, data_node.z);
/* setup bsdf */
sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
break;
}
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID: