MaterialX icon indicating copy to clipboard operation
MaterialX copied to clipboard

[wgsl error]: 'fwidth' must only be called from uniform control flow

Open ashwinbhat opened this issue 2 months ago • 2 comments

While transpiling glsl shaders to wgsl tint throws this error and fails.

error: 'fwidth' must only be called from uniform control flow

The error is from use of derivatives in a loop that might not have a uniform flow. I think the root cause might be mx_subsurface_bsdf where mx_subsurface_scattering_approx based on the closureType.

Here is the function:

vec3 mx_subsurface_scattering_approx(vec3 N, vec3 L, vec3 P, vec3 albedo, vec3 mfp)
{
    float curvature = length(fwidth(N)) / length(fwidth(P));
    float radius = 1.0 / max(curvature, 0.01);
    return albedo * mx_integrate_burley_diffusion(N, L, radius, mfp) / vec3(M_PI);
}

and loop

for (int activeLightIndex = 0; activeLightIndex < numLights; ++activeLightIndex)
...
  mx_subsurface_bsdf(mx_subsurface_bsdf(closureData, subsurface, coat_affected_subsurface_color_out, subsurface_radius_scaled_out, subsurface_anisotropy, normal, subsurface_bsdf_out);
  BSDF selected_subsurface_bsdf_out = BSDF(vec3(0.0),vec3(1.0));
...

Probably a suitable workaround would be to split mx_subsurface_bsdf?

ashwinbhat avatar Dec 05 '25 18:12 ashwinbhat

One simple fix is to move the curvature computation outside the function

    float curvature = length(fwidth(N)) / length(fwidth(P));
    if (closureData.closureType == CLOSURE_TYPE_REFLECTION)
    {
        vec3 sss = mx_subsurface_scattering_approx(N, L, P, color, radius, curvature);
        float NdotL = clamp(dot(N, L), M_FLOAT_EPS, 1.0);
        float visibleOcclusion = 1.0 - NdotL * (1.0 - occlusion);
        bsdf.response = sss * visibleOcclusion * weight;
    }

ashwinbhat avatar Dec 08 '25 21:12 ashwinbhat

Are there performance concerns introducing two length() calls (aka square root) for the indirect case where they aren't necessary? I know recently there have been a number of different conversations about render time performance. Maybe there's a way to stage this so it only affects WGSL? Or maybe the performance is less of a concern here...

ld-kerley avatar Dec 08 '25 22:12 ld-kerley

I'm wondering if we need mx_subsurface_scattering in Web. Is there a use for this?

ashwinbhat avatar Dec 15 '25 23:12 ashwinbhat