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