Compute Shader基礎

ComputeShader:
    GPGPU:General Purpose GPU Programming,GPU通用計算,利用GPU的並行特性。大量並行無序數據的少分支邏輯適合GPGPU。平臺或接口:DirectCompute,OpenCL,CUDA等。
    定義:GPGPU編程,運行在GPU上脫離於常規渲染管線以外的程序,而且能輸出數據的緩衝或貼圖。
    特定:數學、並行化,不影響渲染結果。
    用途:大量並行少分支的數學運算很適合使用compute shader,缺點是數據在cpu和gpu之間傳輸很慢。

 

  ComputeShader須要腳原本調用html

/*
     * 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等
 
參考:
相關文章
相關標籤/搜索