在最近的專案中,必須透過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;
}
}
