グラフィックカードの計算、マニュアル、簡単

このガイドでは、最も単純なGPUコンピューティングプログラムの操作について説明します。 このプログラムのUnityプロジェクトへのリンクは次のとおりです。

プロジェクトファイル.unitypackageへのリンク

彼女はマンデルブロのフラクタルを描きます。

コードの各行については説明しません。GPUで計算を実装するために必要な手順のみを示します。 したがって、Unityでプログラムコードを開き、説明されたコード行がどのように使用されるかを確認するのが最善です。

フラクタルシェーダーはHLSLで記述されています。 以下はそのテキストです。 関連する行について簡単にコメントしましたが、詳細な説明は以下になります。

//   GPU       : RWTexture2D<float4> textureOut; //  ,       RWStructuredBuffer<double> rect; //      ,    RWStructuredBuffer<float4> colors; //    ,      CPU     #pragma kernel pixelCalc //    ,          CPU [numthreads(32,32,1)] //     ,      void pixelCalc (uint3 id : SV_DispatchThreadID){ //     .  id   ,      float k = 0.0009765625; //       10241024     22   double dx, dy; double p, q; double x, y, xnew, ynew, d = 0; //    ,           uint itn = 0; dx = rect[2] - rect[0]; dy = rect[3] - rect[1]; p = rect[0] + ((int)id.x) * k * dx; q = rect[1] + ((int)id.y) * k * dy; x = p; y = q; while (itn < 255 && d < 4){ //   :      ,      2x2 xnew = x * x - y * y + p; ynew = 2 * x * y + q; x = xnew; y = ynew; d = x * x + y * y; itn++; } textureOut[id.xy] = colors[itn]; //      :    ,    -   } 

注意深い読者は言う:著者、説明してください! テクスチャサイズは1024×1024で、スレッド数は32×32です。 id.xyパラメーターは、テクスチャ内のすべてのピクセルにどのように対処しますか?
丁寧でありながら、GPUリーダーでのコンピューティングの問題については経験の浅い人が殺します。 そして、スレッドの数が32x32であるということはどこに続きますか? そして、「id.xy」の理解方法は?

次のように2番目に答えます。ディレクティブ[numthreads(32,32,1)]は、32x32x1スレッドがあることを示しています。 同時に、idパラメーターは32x32x1空間の座標形式で値を取るため、フローは3次元グリッドを形成します。 値の範囲はid.x [0、31]、値の範囲はid.y [0、31]、id.zは0です。また、id.xyは短いレコードuint2(id.x、id.y)です。

コマンドでCPU側からこのカーネルを呼び出すと、32x32スレッドになります(この最初の注意深い読者に既に答えています)。

 ComputeShader.Dispatch(kernelIndex, 1, 1, 1) 

これらの3つのユニットを参照してください? これは、ディレクティブ[numthreads(32,32,1)]の番号と同じであり、互いに乗算されます。

次のパラメーターでシェーダーを開始した場合:

 ComputeShader.Dispatch(kernelIndex, 2, 4, 1) 

これは、x軸に沿って32 * 2 = 64、y軸に沿って32 * 4 = 128、つまり合計64x128スレッドになります。 パラメータは、各軸で単純に乗算されます。

ただし、この場合、カーネルは次のように起動されます。

 ComputeShader.Dispatch(kernelIndex, 32, 32, 1) 

これにより、合計1024x1024のスレッドが得られます。 そして、それはid.xyインデックスが1024x1024のテクスチャ空間全体をカバーする値を取ることを意味します

これは便宜上行われています。 データは配列に格納され、各ストリームはデータ単位で同じ操作を実行し、データ単位の数に等しいスレッド数を作成し、ストリームインデックスがそのデータ単位をアドレス指定するようにします。 とても快適です。

私たちのフラクタル化プログラムのシェーダーコードについて知る必要があるのはそれだけです。

次に、シェーダーコードを実行するためにCPU側で行ったことを見てみましょう。

変数の宣言:シェーダー、バッファー、およびテクスチャ

 ComputeShader _shader RenderTexture outputTexture ComputeBuffer colorsBuffer 

enableRandomWriteを有効にすることを忘れずに、テクスチャを初期化します

 outputTexture = new RenderTexture(1024, 1024, 32); outputTexture.enableRandomWrite = true; outputTexture.Create(); 

オブジェクトの数とオブジェクトのサイズを設定して、バッファーを初期化します。 事前に入力された色の配列のデータをビデオメモリに書き込む

 colorsBuffer = new ComputeBuffer(colorArray.Length, 4 * 4); colorsBuffer.SetData(colorArray); 

シェーダーを初期化し、カーネルにテクスチャとバッファーを設定して、データを書き込むことができるようにします

 _shader = Resources.Load<ComputeShader>("csFractal"); kiCalc = _shader.FindKernel("pixelCalc"); _shader.SetBuffer(kiCalc, "colors", colorsBuffer); _shader.SetTexture(kiCalc, "textureOut", outputTexture); 

これがデータの準備です。 あとは、シェーダーカーネルを起動するだけです

 _shader.Dispatch(kiCalc, 32, 32, 1); 

このコマンドを実行すると、RenderTextureテクスチャがカメラが見ているImageコンポーネントのmainTextureとして使用されるため、テクスチャはすぐに見える色で塗りつぶされます。

Source: https://habr.com/ru/post/J346260/


All Articles