floooh / sokol-tools

Command line tools for use with sokol headers
MIT License
229 stars 57 forks source link

Shader compiler seems to silently fail when using bool uniform #53

Closed kavika13 closed 2 years ago

kavika13 commented 3 years ago

Uncomment the boolean parameter and its usage in the fragment shader, and the shader compiler will not output any error message, and will not output any .h file

@vs vs
in vec3 position;
in vec3 normal;
in vec2 texcoord0;

out vec3 vs_world_position;
out vec3 vs_view_position;
out vec3 vs_unscaled_normal;
out vec2 vs_uv;

uniform vs_params {
    mat4 local_to_world_matrix;
    mat4 local_to_view_matrix;
    mat4 local_to_projection_matrix;
    mat4 transpose_world_to_local_matrix;
    vec2 uv_offset;
};

void main() {
    vec4 pos = vec4(position, 1.0);
    vs_world_position = vec3(local_to_world_matrix * pos);
    vs_view_position = vec3(local_to_view_matrix * pos);
    vs_unscaled_normal = normalize(vec3(transpose_world_to_local_matrix * vec4(normal, 0.0)));
    vs_uv = texcoord0 + uv_offset;
    gl_Position = local_to_projection_matrix * pos;
}
@end

@fs fs
in vec3 vs_world_position;
in vec3 vs_view_position;
in vec3 vs_unscaled_normal;
in vec2 vs_uv;

out vec4 frag_color;

uniform sampler2D tex;

uniform fs_params {
    vec3 scene_ambient_color;

    vec3 material_ambient_tint;
    vec3 material_diffuse_tint;

    vec3 light_ambient_color;
    vec3 light_diffuse_color;
    vec3 light_position;
    float light_range;

    // bool is_fog_enabled;
    vec3 fog_color;
    float fog_start;
    float fog_end;
};

void main() {
    vec4 albedo = texture(tex, vs_uv);
    float out_alpha = albedo.a;

    vec3 ambient_color = material_ambient_tint * (scene_ambient_color + light_ambient_color);

    vec3 diffuse_color = vec3(0.0);

    if(length(light_position - vs_world_position) < light_range) {
        vec3 light_direction = normalize(light_position - vs_world_position);
        vec3 uninterpolated_normal = normalize(vs_unscaled_normal);
        diffuse_color = material_diffuse_tint *
            light_diffuse_color * max(dot(uninterpolated_normal, light_direction), 0.0);
    }

    vec3 out_color = (ambient_color + diffuse_color) * albedo.rgb;

    // if(is_fog_enabled) {
        out_color = mix(fog_color, out_color, clamp((fog_end - vs_view_position.z) / (fog_end - fog_start), 0.0, 1.0));
    // }

    frag_color = vec4(out_color, out_alpha);
}
@end

@program shd vs fs
kavika13 commented 3 years ago

Same is true if trying to change it to an int parameter it seems

kavika13 commented 3 years ago

This is using the version available in downloads , which I am starting to think is out of sync with sokol_gfx since several defines seem to have been renamed.

Edit: I compiled from source and the problem still persists.

Re strikeout text above - I thought I had updated sokol_gfx, but turns out I just updated the directory name but hadn't updated the source code. After updating the source code and updating my app, the generator seems to be working correctly, besides this bug.

floooh commented 3 years ago

Hi, yes, this is part oversight and part "known limitation".

The oversight is that this shouldn't silently fail, but instead output a proper error message.

The limitation is that sokol-gfx only supports floating point uniforms (float, vec2, vec3 and vec4). This limitation mainly has the reason that for OpenGL backends, uniforms are packed into arrays, so that updates happen with a single glUniform4fv() call. Such a packed uniform array cannot contains items of bool or integer type.

There are a number of related issues in the sokol repository (to allow more uniform types here:

https://github.com/floooh/sokol/blob/d7936e4f56dbf6056fa1bfcf1cc5da888ab1db06/sokol_gfx.h#L1204-L1213

...but this also requires a matching solution for the shader compiler (maybe pack uniforms into array by base type - bool, int and float), but I'm not sure SPIRVCross has support for this).

floooh commented 2 years ago

I'm going to close this issue because of the latest uniform-type changes in sokol-shdc and sokol_gfx.h.

The following new uniform types are allowed: int, ivec2, ivec3 and ivec4, but no bool types. Bools are out unfortunately because SPIRVCross generally wants to convert those to uint, which isn't supported by GLES2/WebGL. SPIRVCross basically errors out on the first bool it encounters when the target shader dialect is GLSL100... which is probably an oversight in SPIRVCross (I guess it could just as well have used int instead of uint as 'target type').

sokol-shdc now also has a check that only the expected "base types" (float and int) are used in uniform blocks.

Once the GLES2 and WebGL backends can be dropped from sokol_gfx.h this type of stuff won't be an issue anymore, because then sokol_gfx.h doesn't need to care about the uniform block interior anymore.