Compute Shader基礎


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等
 
參考:

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM