dfranx / SPIRV-VM

Virtual machine for executing SPIR-V
MIT License
294 stars 27 forks source link

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

Open danilw opened 3 years ago

danilw commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 2 years ago

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