Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[spv-in] Spirv Shader with Uniform Sampling/TextureGrad Fails Uniformity Analysis #4359

Closed
cwfitzgerald opened this issue Sep 13, 2021 · 11 comments
Labels
area: naga front-end lang: SPIR-V Vulkan's Shading Language naga Shader Translator type: bug Something isn't working

Comments

@cwfitzgerald
Copy link
Member

cwfitzgerald commented Sep 13, 2021

A shader which passed validation in 0.6.3 fails to validate in naga master due to:

Function [1] 'main' is invalid:
        Required uniformity of control flow for IMPLICIT_LEVEL in [419] is not fulfilled because of Expression([390])

This shader uses either textureGrad or sampling inside of uniform control flow. and shouldn't fail.

opaque.frag.cpu.zip


This was found because I found a hlsl compile error in naga 0.6.3 that I wondered might be fixed by the new spirv control flow stuff. If you compile this shader to hlsl with 0.6.3, it'll try to use a inside-scope variable outside of that scope, causing a compile error.

@cwfitzgerald cwfitzgerald added area: validation Issues related to validation, diagnostics, and error handling kind: bug lang: SPIR-V Vulkan's Shading Language labels Sep 13, 2021
@kvark kvark added area: naga front-end and removed area: validation Issues related to validation, diagnostics, and error handling labels Sep 13, 2021
@kvark
Copy link
Member

kvark commented Sep 13, 2021

It's a problem with SPV-in, the generated IR doesn't have anything about grads:

                [419]: ImageSample {
                    image: [19],
                    sampler: [2],
                    coordinate: [416],
                    array_index: Some(
                        [418],
                    ),
                    offset: None,
                    level: Auto,
                    depth_ref: Some(
                        [412],
                    ),
                },

@cwfitzgerald cwfitzgerald changed the title Spirv Shader with Uniform Sampling/TextureGrad Fails Uniformity Analysis [spv-in] Spirv Shader with Uniform Sampling/TextureGrad Fails Uniformity Analysis Sep 13, 2021
@cwfitzgerald
Copy link
Member Author

Interesting, the grad code is there 🤔

@kvark
Copy link
Member

kvark commented Sep 14, 2021

It seems that it should been spewing zero:

                    level = if options.compare {
                        log::debug!(
                            "Assuming gradients {:?} and {:?} are not greater than 1",
                            grad_x_handle,
                            grad_y_handle
                        );
                        crate::SampleLevel::Zero
                    } else {
                        crate::SampleLevel::Gradient {
                            x: grad_x_handle,
                            y: grad_y_handle,
                        }
                    };

But the resulting IR has Auto 🤯

@JCapucho
Copy link

Your shader does have an implicit sample

Spir-v disassembly

       %1145 = OpLoad %1142 %shadow
       %1147 = OpLoad %69 %shadow_sampler
       %1149 = OpSampledImage %1148 %1145 %1147
       %1152 = OpImageSampleDrefImplicitLod %float %1149 %1140 %1139
               OpLine %1 76 0

You have this in the debug data

    if (MATERIAL_FLAG(FLAGS_UNLIT)) {
        o_color = pixel.albedo;
        // o_normal = vec4(i_normal, 0.0);
    } else {
        vec3 v = -normalize(i_view_position.xyz);

        vec3 color = vec3(pixel.emissive);
        for (uint i = 0; i < directional_light_header.total_lights; ++i) {
            DirectionalLight light = directional_lights[i];

            vec3 shadow_ndc = (directional_lights[i].view_proj * uniforms.inv_view * i_view_position).xyz;
            vec2 shadow_flipped = (shadow_ndc.xy * 0.5) + 0.5;
            vec4 shadow_shadow_coords = vec4(shadow_flipped.x, 1 - shadow_flipped.y, float(i), shadow_ndc.z);

            float shadow_value;
            shadow_value = texture(sampler2DArrayShadow(shadow, shadow_sampler), shadow_shadow_coords);
            if (shadow_shadow_coords.x < 0 || shadow_shadow_coords.x > 1 || shadow_shadow_coords.y < 0 || shadow_shadow_coords.y > 1 || shadow_ndc.z < -1 || shadow_ndc.z > 1) {
                shadow_value = 1.0;
            }

            color += surface_shading(directional_lights[i], pixel, v, shadow_value * pixel.ambient_occlusion);
        }

        o_color = max(vec4(color, pixel.albedo.a), uniforms.ambient * pixel.albedo);
        // o_normal = vec4(pixel.normal, 0.0);
    }

Clearly there's a texture call in a If statement

@kvark
Copy link
Member

kvark commented Sep 20, 2021

Having the texture call in an If statement could still be unconditional if we statically know that this branch is taken either 100% of time or 0% of time.

@cwfitzgerald
Copy link
Member Author

Yeah the if and the for loop are both based on uniform values, and as such should be valid to use implicit derivatives there. Incidentally, I'm only using implicit derivatives there because textureLod doesn't exist for sampler2DArrayShadow in GLSL :|

@JCapucho
Copy link

This is related to #4320

Also had this problem, textureLod isn't available for shadow textures but you can use a textureGrad instead with vec2(0) as the gradients, internally naga will convert it to a texture sample with Zero lod

float textureGrad(sampler2DArrayShadow, sampler, vec4 P, vec2 dPdx, vec2 dPdy)

@cwfitzgerald
Copy link
Member Author

This is unfortunately not available through glslang, there was a PR, but it went stale and got closed.

@JCapucho
Copy link

wdym?

This worked for me on glslang

#version 460

layout (location = 0) out vec4 fragColor;
layout (set = 0, binding = 0) uniform texture2DArray tex;
layout (set = 0, binding = 0) uniform sampler samp;

void main()
{
    float a = textureGrad(sampler2DArrayShadow(tex,samp), vec4(0), vec2(0), vec2(0));
	fragColor = vec4(a);
}

http://shader-playground.timjones.io/50f33d0eb84ce1eb744225e701d882fc

@cwfitzgerald
Copy link
Member Author

Well hot diggity dog, I didn't realize that worked, I must have thought I tried it, but didn't.

@cwfitzgerald cwfitzgerald added the naga Shader Translator label Oct 25, 2023
@cwfitzgerald cwfitzgerald transferred this issue from gfx-rs/naga Oct 25, 2023
@cwfitzgerald cwfitzgerald added type: bug Something isn't working and removed kind: bug labels Oct 25, 2023
@teoxoy
Copy link
Member

teoxoy commented Nov 3, 2023

Let's track this in #4369.

@teoxoy teoxoy closed this as not planned Won't fix, can't repro, duplicate, stale Nov 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: naga front-end lang: SPIR-V Vulkan's Shading Language naga Shader Translator type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants