I try to write some very fast logic to detect all collisions in game.
So I using GPU.js for this and my code was crashing because I trying to create new array variable inside function?
I need list of all objects from constant (loaded to GPU/CPU memory) and this is fastest than in any call with new context.
import {GPU, KernelFunction, IKernelRunShortcut, IConstantsThis, IKernelFunctionThis, Texture} from 'gpu.js';
interface IConstants extends IConstantsThis {
elementsSize: number,
elements: Array<[number, number, number]>,
}
interface IThis extends IKernelFunctionThis {
constants: IConstants,
}
const gpu = new GPU({mode: 'cpu'});
gpu.addFunction<number[]>(function distance(x1, y1, z1, x2, y2, z2) {
const dx = x1 - x2;
const dy = y1 - y2;
const dz = z1 - z2;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}, {
argumentTypes: {x1: 'Float', y1: 'Float', z1: 'Float', x2: 'Float', y2: 'Float', z2: 'Float'},
returnType: 'Float',
});
const kernelMap = gpu.createKernel(function kernelFunction(this: IThis, objPosition: [number, number, number]) {
// @ts-ignore
const d = distance(
this.constants.elements[0][0],
this.constants.elements[0][1],
this.constants.elements[0][2],
objPosition[0],
objPosition[1],
objPosition[2],
)
const distances = []; // can't create here new variable
for (let i = 0; i < this.constants.elementsSize; i++) {
distances[i] = d;
}
return distances;
}, {
argumentTypes: {objPosition: 'Array(3)'},
constants: <IConstants>{
elementsSize: 2,
elements: [
[1, 1, 1],
[2, 2, 2],
// ... 100k elements
],
},
output: [1],
pipeline: true,
precision: 'single',
immutable: true
})
const result = kernelMap([0, 0, 0]);
console.log(JSON.stringify(result, null, 2));
How can I check all objects from constants and get result distance of every object?
Try this, I'll explain below
First of all, if you aren't using
this.thread.x
in the GPU.js kernel function, you are certainly doing something wrong. I'll try to explain this as easy as possible.So the kernel function is like the content of the for-loop. If you
setOutput([ <number> ])
(an array with single number as argument) then it's a one dimensional for-loop. Therefore,setOutput([ <number>, <number> ])
is 2d, andsetOutput([1,2,3])
is 3d.Then the kernel function is being executed given with
this.thread.x
this.thread.y
this.thread.z
, they're just basicallyi j k
. What makes GPU.js kernel function powerful (with downsides) is that it's executed in parallel with a HUGE amount of 'threads' (compared to cpu).The downside is, the order of execution is uncertain. So you cannot run the kernel function relying on some output in the same for loop (unless you go for chain execution).
(I was thinking to do a side by side comparison with a for loop but I don't have the patience and I think the code is obvious enough)
By the way, as you can see I moved declaration of
distance()
to the top level so typescript doesn't complain (and therefore no use of //@ts-ignore)