0

データの配列としましょう

int data[256][256][256];

0 と 1 の値が含まれます。このデータはデバイス メモリにコピーされ (フラット化され)、cuda カーネルによって処理され、値の一部が 0 から 1 に、またはその逆に変更されます。そのような方法でデータを表示するにはどうすればよいですか

if data[x]][y][z]==1
{
//a point of size 1 will be displayed in (x,y,z) coords
}

その配列をホスト メモリにコピーして戻す必要はありません。デバイス(gpu)メモリから直接実行したい。簡単な例は非常に役に立ちます。

4

1 に答える 1

2

頭に浮かぶ最初のアプローチは、最初に単純なストリーム圧縮手法を使用して、ストリームからすべての 0 値を削除することです。概念的にブール形式のデータが既にあるため、これはそれらの値のスキャン/プレフィックス合計に相当するため、その後、各配列要素はその前の要素の数を格納します。次に、これらの計算されたオフセットを使用して、配列要素を新しいバッファーに再配置します (すべての 1 アイテムを連続して効果的に格納します)。ただし、(現在は無関係な) オフセットをコピーするだけでなく、3D 位置を格納します (古い配列インデックスから簡単に計算できます)。 )。

次に、ホストへのコピーなしで、OpenGL で簡単に描画できるバッファー内の 3D ポイントの単純なリストが得られます。1 ポイント (スキャンの副産物) の最終的な数を追加のバッファーに書き込む場合、間接レンダリングを使用することもでき、ホストからポイントの数を照会する必要さえないため、読み返しなしですべて

これらは、これがどのように機能するかについての一般的な考えにすぎません。私が何について話しているのかわからない場合は、個々のキーワードを自由にグーグルで検索してください. また、OpenGL で何かを描画する方法がわからない場合は、GPU から何かを描画する前に、まず OpenGL または Direct3D に慣れる必要があります (CUDA はそれを行いません)。


編集:まあ、CUDA でこの全体を描画する方法があります。それが本当にポイントの集まりであり、洗練されたラスタライズが必要ない場合は、OpenGL のようにそれらのポイントを 3D から 2D に単純に変換できます (OpenGL も魔法ではありません。間に専用ハードウェアのビットがあります)。したがって、データ項目ごとにスレッドがあり、この項目が1の場合、通常のモデルビューと同次 4D 座標での射影変換を使用して、ポイントの 3D 座標 (スレッド ID で指定) を変換するだけです (ただし、パースペクティブの分割とビューポートの変換は、自分で行うための固定機能のハードウェアがないためです)。そして、この最終的な 2D 座標を使用して、出力イメージに単一のピクセルを設定します。

もちろん、これは、ラスタライズや考えられる効果ではないものなど、OpenGL の他の洗練されたものから利益を得ることができません (少なくともそれほど簡単ではなく、簡単でもありません)。しかし、ストリームの圧縮ステップを回避し、少なくとも既存の OpenGL でレンダリングされた画像 (座標系やテキストなど、視覚化シーンの残りの部分を含む) の上にこれらのポイントをレンダリングすることができます。テスト実装。


編集:ストリームの圧縮を回避する別の方法は、ジオメトリ シェーダーを使用して座標の計算と削除を行い、 0s とs のバッファー全体を OpenGL で直接描画することです。したがって、整数配列全体を使用して単一の属性をフィードし、次のシェーダーに渡すことで、すべてのポイントを描画します。まず、単純なパススルー頂点シェーダー:10int

layout(location=0) in int flag;    //single integer attribute
out int vFlag;                     //just passed through

void main()
{
    vFlag = flag;        //GS does the real work
}

ジオメトリ シェーダーは、ポイントが有効かどうか (値1がポイントを描画しているだけなので、配列インデックス:

layout(points) in;
layout(points,max_vertices=1) out;

uniform mat4 modelViewProj;

in int vFlag[];

void main()
{
    if(vFlag[0] == 1)
    {
        vec3 position = simpleIndexMagic(gl_PrimitiveID);
        gl_Position = modelViewProj * vec4(position, 1.0);
        EmitVertex();
    }
}

フラグメント シェーダーは通常のシェーダーです。もちろん、これらのシェーダーは必要に応じてカスタマイズできます。1しかし、一般的なアプローチは明確です。整数値を直接描画し、配列インデックスをジオメトリ シェーダーにある値のみのポイントに変換します。しかし、これが以前のストリーム圧縮よりもどの程度改善されるかを評価する必要があります。

于 2013-04-04T10:03:32.453 に答える