gpu.js: Important: Unable to return vector value in kernel sub-functions

We cannot return vector value from functions using by kernel. This feature is very important especially when we want to make process some vector and return other vector construct using processed values.

Example of usage: procedure that normalize vector, procedure that multiply vector by some matrix (e.g. rotation) procedure that find normal vector on(to) surface at given point … currently it is imposible to delegate such tasks to separate functions

Here is fiddle test case with this bug (which shows that we are unable to delegate vector normalization to separate function - of course we can create two functions - first for calc nx and second for calc ny but we duplicate length calculations and lose performance…): https://jsfiddle.net/8mqokauw/1/

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 1
  • Comments: 27 (17 by maintainers)

Most upvoted comments

Ok, now full on working with static declarations like this:

    var gpu = new GPU({ mode: mode });
    function typedFunction() {
      return [1, 2];
    }
    gpu.addFunction(typedFunction, {
      returnType: 'vec2'
    });
    var kernel = gpu.createKernel(function() {
      var result = typedFunction();
      return result[0] + result[1];
    })
      .setOutput([1]);

The glsl 1 to 1 of this outputs as:

vec2 typedFunction() {
return vec2(1.0, 2.0);
}
void kernel() {
vec2 user_result=typedFunction();
kernelResult = (user_result[0]+user_result[1]);return;

I consider this to only really be half done though, because I believe we can be much more automated with type detection, but this gives us a starting point for when the values are detected. However, this could easily be part of the API if the type detection is more overhead than we’re comfortable with. Also, this looks a little deceiving, in that the type detection (although extremely simple) partially is working, because if I do something like this (note change array size):

    var gpu = new GPU({ mode: mode });
    function typedFunction() {
      return [1, 2, 3]; //<-- look here
    }
    gpu.addFunction(typedFunction, {
      returnType: 'vec2'
    });
    var kernel = gpu.createKernel(function() {
      var result = typedFunction();
      return result[0] + result[1];
    })
      .setDebug(true)
      .setOutput([1]);

The compilation breaks (which is what we actually want) because the array returned is being detected as a vec3, but the function is declared as returning vec2, and so compilation fails:

An error occurred compiling the shaders: ERROR: 0:161: 'return' : function return is not matching type:

which is transpiled to:

vec2 typedFunction() {
return vec3(1.0, 2.0, 3.0);
}
void kernel() {
vec2 user_result=typedFunction();
kernelResult = (user_result[0]+user_result[1]);return;
}

I’d say we are like 90% there now with https://github.com/gpujs/gpu.js/commit/d561fcf22828425e3267b0a37e469e56e9a09328

All unit tests now passing and use cases (as far as my naive understanding of the universe goes) covered using strongly typed means, which after I think about it more and more may be simply all and exactly what this needs. There are a couple internal artifacts I’d like to clean up before release, but this should be enough for production usage.

I may have something that at least gets this partially working if I get time tonight or tomorrow morning, fyi.