ComputerShader處理後由CPU後續處理的方法

在最近的專案中,必須透過ComputerShader(CS)處理大量的點雲判斷,並回傳處理後的點來後續處理。

通常的狀態下,是使用GetData來將CS處理完的buffer資料塞回陣列再處理

_kernelIndex = Shader.FindKernel("CS_PointCloudMove");
_buffer = new ComputeBuffer(Count, sizeof(float));
Shader.SetBuffer(_kernelIndex, "floatBuffer", _buffer);
int groupX = (Count / _num);         
Shader.Dispatch(_kernelIndex, groupX, 1, 1);

var data = new float[Count]; 
_buffer.GetData(data);

但GPU到CPU的處理時間相當耗時,會使得FPS大幅地降低,我研究了一下後發現Unity有新的語法AsyncGPUReadback.Request(COMPUTE_BUFFER, METHOD),可以非同步地處理回傳的資料,能大大提升GPU<->CPU的運算效能

using System.Runtime.InteropServices;

...
AsyncGPUReadback.Request(_buffer, OnParticleCallback);
...

void OnParticleCallback() 
{
   if (request.hasError)
      return;
   // CPU particle data process
   _tmpParticles = request.GetData().ToArray();
   int pCount = 0;
   for (int i = 0; i < _tmpParticles.Length; i++)
   {
      if (_tmpParticles[i].hit > 0f)
      {
         _interactiveCount++;
         hitPoints.Add(_tmpParticles[i].position);
         pCount++;
      }
      if (pCount > touchCheckMaxNums)
         break;
      }
}