ComputeShader:
GPGPU:General Purpose GPU Programming,GPU通用計算,利用GPU的並行特性。大量並行無序數據的少分支邏輯適合GPGPU。平台或接口:DirectCompute,OpenCL,CUDA等。
定義:GPGPU編程,運行在GPU上脫離於常規渲染管線之外的程序,並且能輸出數據的緩沖或貼圖。
特定:數學、並行化,不影響渲染結果。
用途:大量並行少分支的數學運算很適合使用compute shader,缺點是數據在cpu和gpu之間傳輸很慢。
ComputeShader需要腳本來調用
/* * test.compute */ // main函數,一個compute shader多個kernal函數,使用時在腳本中手動指定調用哪一個 #pragma kernel CSMain // 聲明一可讀寫貼圖 RWTexture2D<float4> Result; // numthreads:創建線程組的大小,也就是一個線程組包含多少個線程,下面的指令表示:指定每個線程組包含64個線程 // id:該線程所在的總的線程結構中的索引 [numthreads(8,8,1)] void CSMain (uint3 id : SV_DispatchThreadID) { Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0); } /* * 調用test.compute的cs腳本 */ public ComputeShader shader; void RunShader() { int kernelHandle = shader.FindKernel("CSMain"); RenderTexture tex = new RenderTexture(256,256,24) // 手動標記為可隨機讀寫 tex.enableRandomWrite = true; tex.Create(); // 把CPU的數據傳到GPU(在不同的存儲空間移動數據會產生延遲,使用時需要考慮優化) shader.SetTexture(kernelHandle, "Result", tex); // 指定線程組是如何划分的 shader.Dispatch(kernelHandle, 256/8, 256/8, 1); }
Structured Buffers:一種數據類型的一個數組,可以是浮點數、整數、結構體:
StructuctedBuffer<float> floatBuffer; RWStructuredBuffer<int> readWriteIntBuffer; struct VecMatPair { public Vector3 point; public Matrix4x4 matrix; } RWStructuredBuffer<VecMatPair> dataBuffer;
/* * test.compute */ #pragma kernel Multiply struct VecMatPair { float3 pos; float4x4 mat; }; RWStructuredBuffer<VecMatPair> dataBuffer; [numthreads(16,1,1)] void Multiply (uint3 id : SV_DispatchThreadID) { dataBuffer[id.x].pos = mul(dataBuffer[id.x].mat, float4(dataBuffer[id.x].pos, 1.0)); } /* * 調用test.compute的cs腳本 */ public ComputeShader shader; void RunShader() { VecMatPair[] data = new VecMatPair[5]; VecMatPair[] output = new VecMatPair[5]; //INITIALIZE DATA HERE // 76 = 3個float + 4*4個float,buffer需要手動指定大小為多少個byte ComputeBuffer buffer = new ComputeBuffer(data.Length, 76); buffer.SetData(data); int kernel = shader.FindKernel("Multiply"); // 設置buffer shader.SetBuffer(kernel, "dataBuffer", buffer); shader.Dispatch(kernel, data.Length, 1,1); // 和texture不一樣,structured buffers需要明確的從GPU存儲空間轉移到CPU(性能消耗非常大,一般只有需要從shader中拉數據時才需要用到) buffer.GetData(output); }
可以看出,對texture的處理不需要手動傳回CPU,所以速度比compute buffer更快。
注意點:
(1)OpenGL ES 3.1一次只能支持4個compute buffers
(2)可以在Show complied code里面查看cs的版本,是cs_4_x還是cs_5_0等
參考:
