Problem with GPU computation on mobile devices


I have a galaxy simulation example that uses the GPU to update the particles positions and velocities:

Everything works fine on my desktop, but when I test it on mobiles I get very weird results.
At first I thought it was a float precision issue, but looking at the effects I don’t think this is the reason.

Anyone know what could be the origin of the problem? My guess is that it’s produced on the texture access, but I’m really lost.


1 Like

First, you should check if the mobile browser logs any error messages or warnings when using the app. In context of Chrome, you can use remote debugging in order to see the content of the browser console on your computer:

Besides, can you try to unroll the for loop in frag-galaxies-vel.glsl?

Hi @Mugen87,

Yes, I did that before, and there is no console errors, just some warning but I get the same warnings with the birds example, so I assumed they were not related.

I will try to unroll the loop, but it’s not a satisfactory solution if instead of two iterations I have to make many of them:

I have similar problems with this sim and in this case I need to loop over all the sources:

It this case the mobile version works a bit better, but this is because I limiting the total number of sources for the mobile version. Still, some particles freeze and don’t move anymore after some seconds.

These are the two warnings that I get in my mobile:

three.min.js:35 THREE.WebGLRenderer: WEBGL_depth_texture extension not supported.
three.min.js:35 THREE.WebGLRenderer: OES_texture_float_linear extension not supported

I don’t think these warnings are relevant to you. Especially if the birds example is working on your devices.

I have tested your app on my Pixel phone. Indeed, the movement of the particles looks weird. The loop unroll is just a test in order to see if the loop itself is the problem. It’s basically possible to perform an automatic loop unroll via three.js if you place a certain pragma on top of your loop and if your for loop has a canocial form.

BTW: Is there a special reason for using a float as a loop variable? You normally use an integer.

I just uploaded the unrolled version and it is still showing the same problem.

Also tried to use only 16x16 particles and the same result.

I use float in the loop because i need to take the mod and floor and they complain if I use integers, but probably there is a way? I’m still quite new with shader programming. Anyway, the birds example is also using floats in the loop, so I guess that’s not the problem.

What it doesn’t make sense to me is that the weird effect seems to group particles according to their coordinates, but I put the particles in the texture randomly…

Thank you for your help!

Hi again,

I simplified the example to make it easier to find the bug, but still not success…

Here is the test that shows the problem on mobile devices:

I see the problem you mention on my iPhone. What kind of type constant are you using on your textures when you generate them in gpuSimulator.createTexture();? I’ve ran into this issue before where desktops support THREE.FloatType but mobile devices only support THREE.HalfFloatType… should be why you’re seeing OES_texture_float_linear extension not supported

Here’s the solution I ended up using: GPGPUComputationRenderer in case that’s the cause of the clumping in positions you’re seeing.

1 Like

Thank you for your input!

I’m using the methods inside the GPUComputationRenderer class, which is in the three.js examples/js directory:

this.createTexture = function() {

	var a = new Float32Array( sizeX * sizeY * 4 );
	var texture = new THREE.DataTexture( a, sizeX, sizeY, THREE.RGBAFormat, THREE.FloatType );
	texture.needsUpdate = true;

	return texture;


The problem is that if I change the type, it seems that I also need to change the array. Which array should I use instead? Note that I need floats for the particle positions and velocities.

Thank you for your help!

Hmm… I don’t think you’d need to change the array. FloatType is a 32-bit component, and HalfFloat is 16-bit: see here.

With that in mind, you could easily fit 16-bit data in a 32-bit array with a lot room to spare. It would be ideal if there were a Float16Array for efficiency, but they don’t exist.

1 Like

Hi @marquizzo

I did several tests today, but I still didn’t manage to solve the problem.

I’m quite sure the problem is not directly related with the Float32 support, because GPUComputationRenderer is testing the support in the init method and it would have printed an error in that case:

Any other idea to explore?

This example seems to also have the problem on mobiles and it’s not using three.js:

Darn, I think you’re right. I’m trying your example, creating the texture with HalfFloatType:

var a = new Float32Array( sizeX * sizeY * 4 );
var texture = new THREE.DataTexture( a, sizeX, sizeY, THREE.RGBAFormat, THREE.HalfFloatType );

And I get the error:

WebGL: INVALID_OPERATION: texImage2D: type HALF_FLOAT_OES but ArrayBufferView is not NULL

So I guess that approach won’t work. But it definitely looks like a precision issue on mobile devices. I even tried adding precision highp float; precision highp int; to all shaders, and it didn’t change anything. So I’m all out of ideas. Sorry!

1 Like

Thank you for trying anyway.

I’m going to give up for the moment. I don’t really that the examples work on mobiles, so I guess I can live with that.

Thank you again for your replies, @marquizzo and @Mugen87!