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

SPIRV-VM does not follow SPIRV standarts and result is wrong #4

Open
danilw opened this issue May 23, 2021 · 3 comments
Open

SPIRV-VM does not follow SPIRV standarts and result is wrong #4

danilw opened this issue May 23, 2021 · 3 comments

Comments

@danilw
Copy link

danilw commented May 23, 2021

maybe im wrong, but

https://www.khronos.org/registry/spir-v/specs/unified1/GLSL.std.450.html

Pow
Result is x raised to the y power; xy. The resulting value is undefined if x < 0. Result is undefined if x = 0 and y ≤ 0.

FClamp
Result is min(max(x, minVal), maxVal). The resulting value is undefined if minVal > maxVal. The semantics used by min() and max() are those of FMin and FMax.

SmoothStep
The resulting value is undefined if edge0 ≥ edge1.

And others where the result should be inf or nan in SPIRV-VM its not.

Also dFd https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/dFdx.xhtml

Expressions that imply higher order derivatives such as dFdx(dFdx(n)) have undefined results, as do mixed-order derivatives such as dFdx(dFdy(n)). It is assumed that the expression p is continuous and therefore, expressions evaluated via non-uniform control flow may be undefined.

and dFd in the SPIRV-VM just does not work the same as on GPU (SPIRV-VM result incorrect):
shader code for test:

void mainImage( out vec4 Oc, in vec2 I )
{
    if(mod(I.x+I.y,5.)<2.5){
    vec4 tO = vec4(mod(I.x,2.),mod(I.y,2.),0.,0.);
    if(length(tO)==0.||int(I.x+I.y)==int(iResolution.x/2.)){Oc=vec4(1.);return;}
    vec4 a = dFdx(tO)*(mod(I.x,2.)>1.?-1.:1.);
    vec4 b = dFdy(tO)*(mod(I.y,2.)>1.?-1.:1.);
    if(length(abs(a)+abs(b))==0.||isnan((dot(a,b)))||isinf((dot(a,b)))||int(I.x+I.y-50.)==int(iResolution.x/2.)){Oc=vec4(1.,0.,1.,1.);return;}
    a+=tO;
    b+=tO;
    vec4 diag = a+b-tO;
    float t = 0.;
    if(t<1.){
        if(mod(I.x,2.)<1.) tO=b;
    } else if (t >2.&&t<3.) {
        if(mod(I.y,2.)<1.) tO=a;
    } else if (t >4.&&t<5.) {
        if(float(mod(I.y,2.)<1.)+float(mod(I.x,2.)<1.)==1. ) tO=diag;
    }
    Oc=tO;
    Oc.a=1.;
    }
    else Oc=vec4(I/iResolution.xy,0.,1.);
    
}

Correct/expected result (screenshot from Vulkan application, but it same in Browser in OpenGL mode):
1

Result from SPIRV-VM:
2

@ClaasJG
Copy link

ClaasJG commented May 24, 2021

My guess: That a return value is undefined, does not mean, that it is INF or NAN. To use some 'c' jargon slightly out of context 'it could even contain nasal demons', which means: The implementation may return whatever it wants even in inconsistent ways.

@danilw
Copy link
Author

danilw commented May 24, 2021

That a return value is undefined, does not mean, that it is INF or NAN.

on the GPU GLSL is NAN or INF and many people include me expect NAN or INF in many cases as a result

without NAN and INF any my own shader that longer than 100 lines of code will just work completely wrong

this fact makes it impossible to use SPIRV-VM to actually "debug" anything because behavior of emulation completely different to real GPU shaders result

@keith2018
Copy link

I have tested the shader code with my interpreter SPVM,seems like there is still a bit different with expected result

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants