Using the GPU instead of multiple threads

I have made tiles of water, each of them made of a mesh whose vertices and normals are updated on each frame to generate waves.

This is using a lot of CPU power. So far I managed to make this multi-threaded by performing some calculations in separate threads while the main thread awaits, after what I assign the vertices/normals arrays back into the mesh in the main thread once the other threads have finished updating them.

This is how it works using pseudo code :

Awake() begin.
    start threads and let them wait
Awake() end.

Update() begin
    let the threads compute new vertices and normals for each water tile
    wait for the threads to finish their work
    assign the vertices and normals back into the mesh (here, on the main thread)
Update() end

... more Update() calls ...

OnDestroy() begin.
    stop threads
OnDestroy() end.

This multithreading optimisation allowed for a huge performance gain on a quad core CPU. However, it is still very greedy in terms of power, and I have the feeling that I would be able to compute even more stuff in an even faster way if I could use the GPU.

My question is : How can I use the GPU to perform calculations that can be performed in parallel ? I.e the calculations that I currently do in separate threads and only use Vector3, Mathf and other parts of the Unity API which are allowed to be used in another thread than the main one ?

Could I create some kind of “dummy shader” that would not be used to display stuff as its supposed to be, provide it with the arrays of vertices and normals I want to update, and then retreive the resulting values in C# ?

Just a bit of detail about what I actually compute in threads, if it matters : Basically I have, for each water tile, a two dimensional array of “base” points that represent the water when there is no wave at all and a second two dimensional array of directions wich represent the normal of the water at each of these base points. Then, for each “base point”, I’m moving the base point along the direction using a Simplex noise function. Something like :
vertices[xzIn1D] = basePoints[x,z] + directions[x, z] * GetNoise(something)

Thank you :smiley:

How can I use the GPU to perform
calculations that can be performed in
parallel ?
Well, for your specific thing, waves on the water mesh, you just have to write a vertex shader, assign it to your material and watch it wave. No need to actually modify and update the mesh, CPU does not have to be involved at all. Vertex shader will do exactly what you want, without transferring the data between CPU and GPU (which is super slow).
The vertex shader recalculates each displayed vertex in every frame, that’s it’s purpose. To place the vertex on the screen. Simply write your own vertex shader that will apply some distortion (the waves) to your vertex position, based on time and some other value (world position, wave offset texture, etc)(you might want to recalculate normals as well, but you will live without it)

You can find tutorials on how to write shaders on official unity docs