2016-11-18 5 views
0

私は、1を使って3D配列の形でHLSLに一連の整数を送る必要があります。私は数日の間これをやろうとしましたが、何の利益もありません。私はお互いにバッファーをパックしようとしましたが(StructuredBuffer<StructuredBuffer<StructuredBuffer<int>>>)、それは単に動作しません。そして、私はこの事をサイズ変更可能にする必要があるので、配列をstructに使用することはできません。私は何をすべきか?HLSLの3Dバッファー?

編集:私がここでやろうとしていることをもう少し明確にするために、これは医療プログラムです。あなたの体をスキャンすると、いくつかのファイルが生成されます。これらのファイルはDICOMファイル(.dcm)と呼ばれます。これらのファイルは医師に渡されます。医師はプログラムを開き、すべてのDICOMファイルを選択してロードする必要があります。各DICOMファイルにはイメージが含まれています。しかし、それらの画像は、私たちの日常生活で使用される通常の画像とは異なります。これらのイメージはグレースケールであり、各ピクセルは-1000〜数千の範囲の値を持つため、各ピクセルは2バイト(またはInt16)として保存されます。スキャンしたボディの3Dモデルを生成する必要があります。そのため、Marching Cubesアルゴリズムを使用して生成しています(Polygonising a Scalar Fieldをご覧ください)。問題は、約360×512×512サイズの画像で各ピクセルをループすることになりました。私は、CPUを使用したときに必要になった時点で、各ファイルからピクセルデータを読み込みました。今私はこのプロセスを実行時に行わせようとしています。私はそれを処理する前にすべてのピクセルデータをGPUに送る必要があります。それが私の問題です。ディスクからデータを読み込むにはGPUが必要です。それは不可能なので、360 * 512 * 512 * 4バイトのデータを3DのIntsの形式でGPUに送る必要があります。私はまた、その膨大な量のメモリの再転送を避けるためにそこにデータを保存する予定です。私は何をすべきか?我々は現在、これがさえ甘く作るためにSetMatrixArraySetVectorArrayを可能にし、MaterialPropertyBlockを持っているユニティでRefer to this link to know more about what I'm doing

+1

アレイを平坦化できますか? 3DArr [HEIGHT、WIDTH、DEPTH] – TheDjentleman

+0

でのFlatArr [x + WIDTH *(y + DEPTH * z)] = 3DArr [x、y、z]のようにHLSLのバッファの最大サイズは2048バイトです私の目的のために小さい@xyLe_ – None

答えて

1

私が理解したものから、私は次のことをしようとすることをお勧め:

  1. は、あなたのデータをフラット化(ネストされたバッファは、あなたのGPU上で欲しいものではありません)

  2. 間でデータを分割(もし私がNvidia Titan XIでそれらを使って遊んでいたときには、バッファあたり約1GBのデータを保存することができました)1.5GBのデータを持つ3Dポイントクラウドをレンダリングしていましたが、360MBytesのデータは問題が発生したとき)

  3. あなたは、複数のバッファが必要な場合:あなたのマーチングキューブアルゴリズム

  4. ために必要に応じてそれらをオーバーラップしてみましょう(私はあなたが複数のバッファを持っている場合は、それを複数回実行し、蓄積し、DX11を必要だと思うComputeShaderであなたのすべての計算を行い、あなたのその後、結果)と(あなたにも面白いかもしれません)OnPostRender関数からのお電話()だけのポイントを描くか、GPU上のメッシュを構築するために内部Graphics.DrawProceduralを使用

編集標準シェーダで結果を使用

データをgpuバッファに追加する場合は、正確なサイズがわからないか、GPUにすぐに書き込むことができないため、AppendBuffersComputeShaderを使用できます。

C#スクリプト断片:

struct DataStruct 
{ 
    ... 
} 

DataStruct[] yourData; 
yourData = loadStuff();  

ComputeBuffer tmpBuffer = new ComputeBuffer(512, Marshal.SizeOf(typeof(DataStruct))); 
ComputeBuffer gpuData = new ComputeBuffer(MAX_SIZE, Marshal.SizeOf(typeof(DataStruct)), ComputeBufferType.Append); 

for (int i = 0; i < yourData.Length/512; i++) { 

    // write data subset to temporary buffer on gpu 
    tmpBuffer.SetData(DataStruct.Skip(i*512).Take((i+1)*512).ToArray()); // Use fancy Linq stuff to select data subset 

    // set up and run compute shader for appending data to "gpuData" buffer 
    AppendComputeShader.SetBuffer(0, "inBuffer", tmpBuffer); 
    AppendComputeShader.SetBuffer(0, "appendBuffer", gpuData); 
    AppendComputeShader.Dispatch(0, 512/8, 1, 1); // 8 = gpu work group size -> use 512/8 work groups 
} 

ComputeShader:

struct DataStruct // replicate struct in shader 
{ 
    ... 
} 

#pragma kernel append 
StructuredBuffer<DataStruct> inBuffer; 
AppendStructuredBuffer<DataStruct> appendBuffer; 

[numthreads(8,1,1)] 
void append(int id: SV_DispatchThreadID) { 
    appendBuffer.Append(inBuffer[id]); 
} 

  • AppendComputeShaderインスペクタ
  • 512を介して割り当てられなければならないが、任意のバッチサイズであり、データの量の上限がありますあなたは一度にGPUのバッファに追加することができますが、私はハードウェアに依存していると思います(私にとっては65536 * 4バイトと思われます)
  • gpuバッファの最大サイズを指定する必要があります〜1GB)
+0

ちなみに、クラウドレンダリングシステム@xyLe_を達成したら、GPUに1GBのデータを送るのにどれくらいの時間がかかりましたか? – None

+1

@None最後には約15分。私が複数のスレッドを使ってデータを読んでいて、gpuに〜65kの「粒子」のバッチでそれらを書き込んだので、かなり速く進んでいました – TheDjentleman

1

、我々はシェーダ静的ヘルパーSetGlobalVectorArraySetGlobalMatrixArrayを使用してグローバルに設定することができます。私はこれらがあなたを助けると信じています。

古い方法が好きな場合は、this quite nice articleを参照してベクターの配列を渡す方法をご覧ください。

+0

私の3D配列の寸法は大きく異なり、y/z寸法の2つの値から成っているだけでなく、 – None