Giter Site home page Giter Site logo

spirv-vm's Issues

Infinite loop in a simple shader

The following shader fails to execute correctly, the loop never terminates:

#version 430

layout(location = 0) out float _30;

void main()
{
    float _37;
    _37 = 0.5;
    for (int _36 = 0; _36 < 4; )
    {
        _37 = sin(_37);
        _36++;
        continue;
    }
    _30 = _37;
}

The SPIR-V corresponding to this shader:

; SPIR-V
; Version: 1.0
; Generator: Google Shaderc over Glslang; 10
; Bound: 34
; Schema: 0
               OpCapability Shader
          %1 = OpExtInstImport "GLSL.std.450"
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %4 "main" %30
               OpExecutionMode %4 OriginUpperLeft
               OpDecorate %30 Location 0
       %void = OpTypeVoid
          %3 = OpTypeFunction %void
      %float = OpTypeFloat 32
  %float_0_5 = OpConstant %float 0.5
        %int = OpTypeInt 32 1
      %int_0 = OpConstant %int 0
      %int_4 = OpConstant %int 4
       %bool = OpTypeBool
      %int_1 = OpConstant %int 1
%_ptr_Output_float = OpTypePointer Output %float
         %30 = OpVariable %_ptr_Output_float Output
          %4 = OpFunction %void None %3
          %5 = OpLabel
               OpBranch %14
         %14 = OpLabel
         %33 = OpPhi %float %float_0_5 %5 %24 %15
         %32 = OpPhi %int %int_0 %5 %27 %15
         %22 = OpSLessThan %bool %32 %int_4
               OpLoopMerge %16 %15 None
               OpBranchConditional %22 %15 %16
         %15 = OpLabel
         %24 = OpExtInst %float %1 Sin %33
         %27 = OpIAdd %int %32 %int_1
               OpBranch %14
         %16 = OpLabel
               OpStore %30 %33
               OpReturn
               OpFunctionEnd

After looking closely at the issue, it seems that the current version does not properly handle Phi nodes. The issue is related to incrementing counter in %27 and then jumping to %14 and then handling Phi node in %32. Due to the way the block labels are handled, %27 is never copied into %32 and this causes the infinite loop. I have created a PR that fixes the issue.

fnLocation passed into spvm_state_prepare is not valid.

Both in README.md and example.c, I found this code strange:

    spvm_source fnMain = spvm_state_get_result(state, "main");
    spvm_state_prepare(state, fnMain);

where fnMain is a pointer, but spvm_state_prepare declares as

void spvm_state_prepare(spvm_state_t state, spvm_word fnLocation)
{
	state->code_current = state->results[fnLocation].source_location;
	state->current_function = &state->results[fnLocation];

which makes state->results[fnLocation] accessed an invalid memory.

If I change the call to

spvm_state_prepare(state, *fnMain);

I got

0.00 0.00 0.00 0.00
discarded: 0

However from the source examples/shader.glsl, this is incorrect.

What did I do wrong? or there is a bug here?

wrong 32 bit float precision error

shader code:

#version 450

layout (location = 0) out uvec4 outColor;

void main()
{
    vec2 fragCoord=gl_FragCoord.xy+1000.;
    uint val0 = floatBitsToUint(0.4/(0.1*0.4-0.2*0.3));
    uint val1 = floatBitsToUint(0.4/(0.1*0.4-0.2*(0.3+min(fragCoord.x,0.))));
    uint val2 = floatBitsToUint(0.4/(0.1*(0.4+min(fragCoord.y,0.))-0.2*0.3));
    outColor = uvec4(val0, val1, val2, 0u);
}

Test shadertoy shader.

SPIRV-VM result: (first line float second uint)

-20.000000 -19.999996 -20.000004 0.000000 
3248488448 3248488446 3248488450 0

Expected result: (uint in range +-1 from 3248488448)

-20.000000 -19.999998 -20.000001 0.000000 
3248488448 3248488447 3248488449 0

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

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

Something wrong with this shader (unexpected result)

(not just this shader, my large shaders (200+Kb of SPV) result some very broken in SPIRV-VM)
this shader as an example
(spv file used in SPIRV-VM in attachment)

expected result and shader source (copy to shadertoy.com)

uvec4 decodeval32(uint varz) {
    return uvec4(varz>>24,(varz>>16)&0xffu,(varz>>8)&0xffu,(varz>>0)&0xffu);
}

uint encodeval32(uvec4 colz) {
    return uint((colz[0]<<24)&0xff000000u|(colz[1]<< 16)&0x00ff0000u|(colz[2]<< 8)&0x0000ff00u|(colz[3]<< 0)&0x000000ffu);
}


uint packSnorm3x10(vec3 x) {
    x = clamp(x,-1., 1.) * 511.;
    uvec3 sig = uvec3(mix(vec3(0), vec3(1), greaterThanEqual(sign(x),vec3(0))));
    uvec3 mag = uvec3(abs(x));
    uvec3 r = sig.xyz << 9 | mag.xyz;
    return r.x << 22 | r.y << 12 | r.z << 2;
}

vec3 unpackSnorm3x10(uint x) {
    uvec3 r = (uvec3(x) >> uvec3(22, 12, 2)) & uvec3(0x3FF);
    uvec3 sig = r >> 9;
    uvec3 mag = r & uvec3(0x1FF);
    vec3 fsig = mix(vec3(-1), vec3(1), greaterThanEqual(sig, uvec3(1)));
    vec3 fmag = vec3(mag) / 511.;
    return fsig * fmag;
}

uint my_packSnorm4x8(vec4 x) {
    x = clamp(x,-1.0, 1.0) * 127.0;
    uvec4 sig = uvec4(mix(vec4(0), vec4(1), greaterThanEqual(sign(x),vec4(0))));
    uvec4 mag = uvec4(abs(x));
    uvec4 r = sig << 7 | mag;
    return r.x << 24 | r.y << 16 | r.z << 8 | r.w;
}

vec4 my_unpackSnorm4x8(uint x) {
    uvec4 r = (uvec4(x) >> uvec4(24, 16, 8, 0)) & uvec4(0xFF);
    uvec4 sig = r >> 7;
    uvec4 mag = r & uvec4(0x7F);
    vec4 fsig = mix(vec4(-1), vec4(1), greaterThanEqual(sig,uvec4(1)));
    vec4 fmag = vec4(mag) / 127.0;
    return fsig * fmag;
}

int bits2int8(int map[8]){
    int ret = 0;
    int nBits=8;
    int ncv = 1;
    for(int i=nBits-1; i>=0; i--){
        int eval=map[nBits-i-1];
        if(eval == 1)
            ret+=ncv;
        ncv *= 2;
    }
    return ret;
}

void int2bits8(int n, out int map[8]){
    int nBits=8;
    for(int i = 0; i < nBits; i++) {
      if (n % 2==0)map[i]=0;
      else map[i]=1;
      n/=2;
   }
}

#define load_data32(val) decodeval32(floatBitsToUint(val))
#define pack_udata32(data) uintBitsToFloat(encodeval32(data))
#define pack_udata32x4(data1,data2,data3,data4) uintBitsToFloat(uvec4(encodeval32(data1),encodeval32(data2),encodeval32(data3),encodeval32(data4)))

#define pack_float3x10(x) uintBitsToFloat(packSnorm3x10(x))
#define unpack_float3x10(x) unpackSnorm3x10(floatBitsToUint(x))
#define pack_float4x8(x) uintBitsToFloat(my_packSnorm4x8(x))
#define unpack_float4x8(x) my_unpackSnorm4x8(floatBitsToUint(x))

float print_num(vec2, float, int);
float printBits(vec2, int[8]);

#define r vec3(0.9,0.4,0.4)
#define g vec3(0.4,0.9,0.4)
#define b vec3(0.4,0.4,0.9)
#define a vec3(0.9,0.9,0.4)

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 res = iResolution.xy/iResolution.y;
    vec2 uv = fragCoord/iResolution.y-0.5*res;

    vec4 data = vec4(uintBitsToFloat(0xaabbccddu),uintBitsToFloat(0xf1f2f3f4u),
    uintBitsToFloat(0x010f0a0du),uintBitsToFloat(0x010f0a0du));
    
    uvec4 udata32 = load_data32(data.x);
    vec4 fdata4x8 = unpack_float4x8(data.y);
    vec3 fdata3x10 = unpack_float3x10(data.z);
    
    int bits[8];
    int2bits8(int(udata32.x),bits);
    int int_value=bits2int8(bits);
    
    float t=iTime;
    t=0.;

    float timer1=fract((t+0.)/20.)*2.-1.;
    float timer2=fract((t+1.)/20.)*2.-1.;
    float timer3=fract((t+2.)/20.)*2.-1.;
    float timer4=fract((t+3.)/20.)*2.-1.;
    
    vec3 col = vec3(0.);
    float d = 0.;
    uv+= vec2(0.7,-0.4);
    d = step(abs(uv.y*20.),1.);
    if(d>0.){col=r*print_num(uv*20.,float(udata32.x),0);
             col+=r*print_num((uv+vec2(-0.2,0.))*20.,fdata4x8.x,6);
             col+=r*print_num((uv+vec2(-0.7,0.))*20.,fdata3x10.x,6);
             col+=r*print_num((uv+vec2(-1.18,0.))*20.,timer1,6);}
    uv+= vec2(0.0,0.1);
    d = step(abs(uv.y*20.),1.);
    if(d>0.){col=g*print_num(uv*20.,float(udata32.y),0);
             col+=g*print_num((uv+vec2(-0.2,0.))*20.,fdata4x8.y,6);
             col+=g*print_num((uv+vec2(-0.7,0.))*20.,fdata3x10.y,6);
             col+=g*print_num((uv+vec2(-1.18,0.))*20.,timer2,6);}
    uv+= vec2(0.0,0.1);
    d = step(abs(uv.y*20.),1.);
    if(d>0.){col=b*print_num(uv*20.,float(udata32.z),0);
             col+=b*print_num((uv+vec2(-0.2,0.))*20.,fdata4x8.z,6);
             col+=b*print_num((uv+vec2(-0.7,0.))*20.,fdata3x10.z,6);
             col+=b*print_num((uv+vec2(-1.18,0.))*20.,timer3,6);}
    uv+= vec2(0.0,0.1);
    d = step(abs(uv.y*20.),1.);
    if(d>0.){col=a*print_num(uv*20.,float(udata32.w),0);
             col+=a*print_num((uv+vec2(-0.2,0.))*20.,fdata4x8.w,6);
             col+=a*print_num((uv+vec2(-1.18,0.))*20.,timer4,6);}
    
    uv+= vec2(-0.7,0.1);
    d = step(abs(uv.y*20.),.5);
    if(d>0.)col=r*step(2.*uv.x/res.x,fdata4x8.x);
    uv+= vec2(0.0,0.05);
    d = step(abs(uv.y*20.),.5);
    if(d>0.)col=g*step(2.*uv.x/res.x,fdata4x8.y);
    uv+= vec2(0.0,0.05);
    d = step(abs(uv.y*20.),.5);
    if(d>0.)col=b*step(2.*uv.x/res.x,fdata4x8.z);
    uv+= vec2(0.0,0.05);
    d = step(abs(uv.y*20.),.5);
    if(d>0.)col=a*step(2.*uv.x/res.x,fdata4x8.w);
    
    uv+= vec2(0.0,0.15);
    d = step(abs(uv.y*20.),.5);
    if(d>0.)col=r*step(2.*uv.x/res.x,fdata3x10.x);
    uv+= vec2(0.0,0.05);
    d = step(abs(uv.y*20.),.5);
    if(d>0.)col=g*step(2.*uv.x/res.x,fdata3x10.y);
    uv+= vec2(0.0,0.05);
    d = step(abs(uv.y*20.),.5);
    if(d>0.)col=b*step(2.*uv.x/res.x,fdata3x10.z);
    
    uv+= vec2(0.0,0.06);
    d = step(abs(uv.y*20.),.5);
    if(d>0.){col=vec3(1.)*printBits(uv*20.+0.5,bits);
             col+=print_num((uv+vec2(-0.3,0.))*20.+0.5,float(int_value),0);}
    
    
    
    fragColor = vec4(col,1.0);
}



float printBits(vec2 p, int map[8]){
    float di=0.;
    int nBits=8;
    for(int i = 0; i < nBits; i++) {
      di=max(di,print_num(p,float(map[i]),0));
      p.x+=1.;
   }
   return di;
}

const mat3 fontb=mat3(vec3(480599.0,139810.0,476951.0),vec3(476999.0,350020.0,464711.0),vec3(464727.0,476228.0,481111.0));

int get_fvalue(float val, int idx){
    for(int i=0;i<idx+1;i++){
        val=(val-floor(val/10.)*10.)*10.;
    }
    return int(val/10.);
}

float print_num(vec2 uv, float value, int num) {
  if(uv.y < 0.0 || uv.y >= 1.0) return 0.0;
    if(uv.x < -4.0 || uv.x >= 10.0) return 0.0;
  float bits = 0.0;
  int di = - int(floor(uv.x))+ 1;
  if(-di <= num) {
    float pw = pow(10.0, float(di));
    float val = abs(value);
    float pivot = max(val, 1.5) * 10.0;
    if(pivot < pw) {
      if(value < 0.0 && pivot >= pw * 0.1) bits = 1792.0;
    } else {
            if(di == 0) {
                if(num > 0) bits = 2.0;
            } else {
                int idx=0;
                if(di < 0)idx=get_fvalue(val,int(-di));else idx=int(mod((val*10.) / pw, 10.0));
                if(idx<=9 && idx>=0)bits = idx<9?fontb[idx/3][idx%3]:481095.0;
            }
        }
  } else return 0.;
  return floor(mod(bits / pow(2.0, floor(fract(uv.x) * 4.0) + floor(uv.y * 5.0) * 4.0), 2.0));
}

Correct/expected result image:
1

Result from SPIRV-VM:
2

C code to launch same as in #2

I do not want to continue any testing, maybe I'm doing something wrong in C code because I see way too many incorrect results.

shader2.zip

Somethign wrong with this shader or SPIRV-VM (random segfault on some shaders)

(this shader code does work in GPU-GLSL and other CPU "GLSL emulators/environments")
shader spv file in attachment

I tried a few of my own shaders - works, but then next few shaders just do not work in SPIRV-VM, I think it because of large arrays in the shaders or something wrong with array logic in SPIRV-VM...

Or maybe I make error in C code.
C code of modified example.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <spvm/context.h>
#include <spvm/state.h>
#include <spvm/ext/GLSL450.h>

spvm_source load_source(const char* fname, size_t* src_size) {
  FILE* f = fopen(fname, "rb");
  if (f == 0) {
    printf("Failed to load file %s\n", fname);
    return 0;
  }

  fseek(f, 0, SEEK_END);
  long file_size = ftell(f);
  fseek(f, 0, SEEK_SET);

  size_t el_count = (file_size / sizeof(spvm_word));
  spvm_source ret = (spvm_source)malloc(el_count * sizeof(spvm_word));
  fread(ret, el_count, sizeof(spvm_word), f);
  fclose(f);

  *src_size = el_count;

  return ret;
}
int main()
{
  // context holds all opcode functions
  spvm_context_t ctx = spvm_context_initialize();

  // load source code
  size_t spv_length = 0;
  spvm_source spv = load_source("shader.spv", &spv_length);

  int ires[2] = { 10, 10 };
  float timeData = 0.0f;
  float iresf[2] = { ires[0], ires[1] };
  int index = 0;
  for(int y=0;y<ires[1];y++){
    for(int x=0;x<ires[0];x++){
      spvm_program_t prog = spvm_program_create(ctx, spv, spv_length);
      spvm_state_t state = spvm_state_create(prog);
      spvm_ext_opcode_func* glsl_ext_data = spvm_build_glsl450_ext();
      spvm_result_t glsl_std_450 = spvm_state_get_result(state, "GLSL.std.450");
      if (glsl_std_450)
        glsl_std_450->extension = glsl_ext_data;
      // get uBlock
      spvm_result_t uBlock = spvm_state_get_result(state, "uBlock");

      // set uBlock.time
      spvm_member_t uBlock_time = spvm_state_get_object_member(state, uBlock, "iTime");
      spvm_member_set_value_f(uBlock_time->members, uBlock_time->member_count, &timeData);

      // set uBlock.iResolution
      spvm_member_t uBlock_info = spvm_state_get_object_member(state, uBlock, "iResolution");
      spvm_member_set_value_f(uBlock_info->members, uBlock_info->member_count, iresf);

      // call main
      spvm_word fnMain = spvm_state_get_result_location(state, "main");
      spvm_state_prepare(state, fnMain);
      
      //spvm_state_set_frag_coord(state,x,y,0,0); //does not matter
      
      spvm_state_call_function(state); // crash on 3 loop
      
      spvm_result_t outColor = spvm_state_get_result(state, "outColor");
      for (int i = 0; i < outColor->member_count; i++)
        printf("%.2f ", outColor->members[i].value.f);
      printf("\n");
      printf("%d %d\n",x,y);
      
      spvm_state_delete(state);
      spvm_program_delete(prog);
      free(glsl_ext_data);
    }
  }

  // free memory
  //spvm_state_delete(state);
  //spvm_program_delete(prog);
  //free(glsl_ext_data);
  free(spv);

  spvm_context_deinitialize(ctx);

  return 0;
}

Launching this code with this shader result 100% crash on 3-rd loop iteration.

I tried to have only(recreate it) state and spvm_state_delete(state); inside loop - it still crash. (moving everything to loop does not fix it, it still crashes)
Crash on line spvm_state_call_function, crash only when it called using loop.
Crash same with spvm_state_step_into on line 0 on first call in 3-rd loop iteration.

Call only once does not have a crash.

Sorry if I missing something in the C code and its my error, I dont see error there.

shader.zip

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.