CUDA / OpenGL相互運用:サーフェスオブジェクトへの書き込みは以前のコンテンツを消去しません

ベンジャミンブレイ

CUDAカーネルを使用してOpenGLテクスチャを変更しようとしsurf2Dwrite()ていますが、下の画像に示すように、呼び出しがテクスチャの以前のコンテンツと混ざり合っいるように見えるという奇妙な問題が発生しています。背面の木製のテクスチャは、CUDAカーネルで変更する前のテクスチャに含まれています。期待される出力には、色のグラデーションのみが含まれ、背後にある木のテクスチャは含まれません。なぜこのブレンドが起こっているのかわかりません。

奇妙なテクスチャのブレンド

考えられる問題/誤解

私はCUDAとOpenGLの両方に不慣れです。ここでは、私をこのコードに導いた思考プロセスを説明しようと思います。

  • cudaArrayテクスチャの読み取り/書き込み時のキャッシュの局所性に適していると読んだため、(floatの配列などではなく)テクスチャにアクセスするためにを使用しています。
  • サーフェスを使用しているのは、それが変更する唯一の方法であるとどこかで読んだからです。 cudaArray
  • サーフェスオブジェクトを使用したかったのですが、これは新しい方法であると理解しています。古い方法は、サーフェス参照を使用することです。

チェック/テストの方法がわからない、コードに関するいくつかの考えられる問題:

  • 画像形式に一貫性がありませんか?たぶん私はどこかで正しいビット/チャネル数を指定しなかったのですか?多分私はfloatsの代わりにunsigned charsを使うべきですか?

コードの概要

このGitHubGistで完全に最小限の作業例を見つけることができます可動部分があるのでかなり長いですが、まとめてみます。MWEを短縮する方法についての提案を歓迎します。全体の構造は次のとおりです。

  1. ローカルに保存されたファイルからOpenGLテクスチャを作成する
  2. を使用してテクスチャをCUDAに登録します cudaGraphicsGLRegisterImage()
  3. テクスチャを表すcudaGraphicsSubResourceGetMappedArray()を取得するための呼び出しcudaArray
  4. 作成しcudaSurfaceObject_t、私はへの書き込みに使用することができますcudaArray
  5. でテクスチャに書き込むカーネルにサーフェスオブジェクトを渡します。 surf2Dwrite()
  6. テクスチャを使用して画面上に長方形を描画します

OpenGLテクスチャの作成

私はOpenGLを初めて使用するため、LearnOpenGLチュートリアルの「テクスチャ」セクションを出発点として使用しています。これが私がテクスチャを設定する方法です(画像ライブラリを使用してstb_image.h

GLuint initTexturesGL(){
    // load texture from file
    int numChannels;
    unsigned char *data = stbi_load("img/container.jpg", &g_imageWidth, &g_imageHeight, &numChannels, 4);
    if(!data){
        std::cerr << "Error:  Failed to load texture image!" << std::endl;
        exit(1);
    }

    // opengl texture
    GLuint textureId;
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);

    // wrapping
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

    // filtering
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // set texture image
    glTexImage2D(
        GL_TEXTURE_2D,    // target
        0,                // mipmap level
        GL_RGBA8,         // internal format (#channels, #bits/channel, ...)
        g_imageWidth,     // width
        g_imageHeight,    // height
        0,                // border (must be zero)
        GL_RGBA,          // format of input image
        GL_UNSIGNED_BYTE, // type
        data              // data
    );
    glGenerateMipmap(GL_TEXTURE_2D);

    // unbind and free image
    glBindTexture(GL_TEXTURE_2D, 0);
    stbi_image_free(data);

    return textureId;
}

CUDAグラフィックス相互運用

上記の関数を呼び出した後、テクスチャをCUDAに登録します。

void initTexturesCuda(GLuint textureId){
    // register texture
    HANDLE(cudaGraphicsGLRegisterImage(
        &g_textureResource,                       // resource
        textureId,                                // image
        GL_TEXTURE_2D,                            // target
        cudaGraphicsRegisterFlagsSurfaceLoadStore // flags
    ));

    // resource description for surface
    memset(&g_resourceDesc, 0, sizeof(g_resourceDesc));
    g_resourceDesc.resType = cudaResourceTypeArray;
}

レンダリングループ

フレームごとに、次のコマンドを実行してテクスチャを変更し、画像をレンダリングします。

while(!glfwWindowShouldClose(window)){
        // -- CUDA --

        // map
        HANDLE(cudaGraphicsMapResources(1, &g_textureResource));


        HANDLE(cudaGraphicsSubResourceGetMappedArray(
            &g_textureArray,   // array through which to access subresource
            g_textureResource, // mapped resource to access
            0,                 // array index
            0                  // mipLevel
        ));

        // create surface object (compute >= 3.0)
        g_resourceDesc.res.array.array = g_textureArray;
        HANDLE(cudaCreateSurfaceObject(&g_surfaceObj, &g_resourceDesc));

        // run kernel
        kernel<<<gridDim, blockDim>>>(g_surfaceObj, g_imageWidth, g_imageHeight);

        // unmap
        HANDLE(cudaGraphicsUnmapResources(1, &g_textureResource));

        // --- OpenGL ---

        // clear
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // use program
        shader.use();

        // triangle
        glBindVertexArray(vao);
        glBindTexture(GL_TEXTURE_2D, textureId);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);

        // glfw:  swap buffers and poll i/o events
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

CUDAカーネル

実際のCUDAカーネルは次のとおりです。

__global__ void kernel(cudaSurfaceObject_t surface, int nx, int ny){
    int x = blockIdx.x * blockDim.x + threadIdx.x;
    int y = blockIdx.y * blockDim.y + threadIdx.y;
    if(x < nx && y < ny){
        uchar4 data = make_uchar4(x % 255, 
                                  y % 255, 
                                  0, 255);
        surf2Dwrite(data, surface, x * sizeof(uchar4), y);
    }
}
マイケルケンゼル

私が正しく理解していれば、最初にテクスチャを登録し、一度マップし、マップされたテクスチャを表す配列のサーフェスオブジェクトを作成してから、テクスチャのマップを解除します。フレームごとに、リソースを再度マップし、マップされたテクスチャを表す配列を要求し、それを完全に無視して、リソースを最初にマップしたときに取得した配列用に作成されたサーフェスオブジェクトを使用します。ドキュメントから

[…]で設定された値は、マップさarrayれるたびに変更される可能性がありますresource

毎回異なる配列を取得する可能性があるため、リソースをマップするたびに新しいサーフェスオブジェクトを作成する必要があります。そして、私の経験では、あなたは実際に時々異なるものを手に入れるでしょう。配列が実際に変更されるたびに、新しいサーフェスオブジェクトのみを作成することは有効なことかもしれません。ドキュメントはそれを可能にしているようですが、私は試したことがないので、それが確実に機能するかどうかはわかりません…

それとは別に、テクスチャのミップマップを生成します。ミップレベル0のみを上書きします。次に、トリリニア補間を使用したミップマッピングを使用してテクスチャをレンダリングします。したがって、私の推測では、mipレベル0の解像度と正確に一致しない解像度でテクスチャをレンダリングするだけなので、レベル0(作成した)とレベル1(レベル1)の間で補間することになります。元のテクスチャから生成されました)…

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

実行可能ファイルへのCUDAコンパイラオブジェクト

分類Dev

cuDevicePrimaryCtxRetain()は、複数のプロセス間で永続的なCUDAコンテキストオブジェクトを持つために使用されますか?

分類Dev

Cuda helloworldの例

分類Dev

CUDAの削減

分類Dev

cuda_ndarray.cuのコンパイルに失敗しました:libcublas.so.7.5:共有オブジェクトファイルを開くことができません

分類Dev

バックエンドCPUのオブジェクトが必要ですが、引数#2のバックエンドCUDAを取得しました 'ソース'

分類Dev

リモートマシンからCUDA / OpenGL相互運用(パーティクル)サンプルを実行する方法

分類Dev

cuda、OpenGLの相互運用性:cudaGraphicsGLRegisterBufferでのcudaErrorMemoryAllocationエラー

分類Dev

CUBIN中間表現から生成されたCUDAオブジェクトファイルをリンクできません

分類Dev

Cudaは白黒画像からテクスチャオブジェクトを作成します

分類Dev

構造体にCUDAテクスチャオブジェクトを埋め込む方法は?

分類Dev

通常のCudaとCuBLAS?

分類Dev

Cudaの奇妙なPrintf

分類Dev

glDispatchComputeIndirectと同等のCUDA

分類Dev

CUDAドット積

分類Dev

CUDA不明エラー

分類Dev

Cudaを使用したTensorflow、libcudart.so.7.5:共有オブジェクトを開くことができません。日食(リクリプス)

分類Dev

CUDA用のスケーラブルなコモディティGPUサーバーのオプション?

分類Dev

cudaスラスト:NULLポインターのチェック

分類Dev

RuntimeError:バックエンドCUDAのオブジェクトが必要ですが、引数#4'mat1 'のバックエンドCPUを取得しました

分類Dev

WindowsへのTensorflow用CUDAのインストール

分類Dev

CUDA:CUDAツールキットなしのnvcc

分類Dev

CUDA Direct3Dの相互運用性は廃止されましたか?

分類Dev

既存のCプロジェクトでのCUDAスラストの使用:コンパイルエラー

分類Dev

MATLAB CUDAカーネルオブジェクト-gatherの使用中にエラーが発生しましたか?

分類Dev

cudaのインストール時に壊れたパッケージを修正できません

分類Dev

RuntimeError:CUDAデバイス2でオブジェクトを逆シリアル化しようとしていますが、torch.cuda.device_count()は1です

分類Dev

Ubuntu16へのCUDA8のインストール:パッケージcudaが見つかりません

分類Dev

Ubuntu16へのCUDA8のインストール:パッケージcudaが見つかりません

Related 関連記事

  1. 1

    実行可能ファイルへのCUDAコンパイラオブジェクト

  2. 2

    cuDevicePrimaryCtxRetain()は、複数のプロセス間で永続的なCUDAコンテキストオブジェクトを持つために使用されますか?

  3. 3

    Cuda helloworldの例

  4. 4

    CUDAの削減

  5. 5

    cuda_ndarray.cuのコンパイルに失敗しました:libcublas.so.7.5:共有オブジェクトファイルを開くことができません

  6. 6

    バックエンドCPUのオブジェクトが必要ですが、引数#2のバックエンドCUDAを取得しました 'ソース'

  7. 7

    リモートマシンからCUDA / OpenGL相互運用(パーティクル)サンプルを実行する方法

  8. 8

    cuda、OpenGLの相互運用性:cudaGraphicsGLRegisterBufferでのcudaErrorMemoryAllocationエラー

  9. 9

    CUBIN中間表現から生成されたCUDAオブジェクトファイルをリンクできません

  10. 10

    Cudaは白黒画像からテクスチャオブジェクトを作成します

  11. 11

    構造体にCUDAテクスチャオブジェクトを埋め込む方法は?

  12. 12

    通常のCudaとCuBLAS?

  13. 13

    Cudaの奇妙なPrintf

  14. 14

    glDispatchComputeIndirectと同等のCUDA

  15. 15

    CUDAドット積

  16. 16

    CUDA不明エラー

  17. 17

    Cudaを使用したTensorflow、libcudart.so.7.5:共有オブジェクトを開くことができません。日食(リクリプス)

  18. 18

    CUDA用のスケーラブルなコモディティGPUサーバーのオプション?

  19. 19

    cudaスラスト:NULLポインターのチェック

  20. 20

    RuntimeError:バックエンドCUDAのオブジェクトが必要ですが、引数#4'mat1 'のバックエンドCPUを取得しました

  21. 21

    WindowsへのTensorflow用CUDAのインストール

  22. 22

    CUDA:CUDAツールキットなしのnvcc

  23. 23

    CUDA Direct3Dの相互運用性は廃止されましたか?

  24. 24

    既存のCプロジェクトでのCUDAスラストの使用:コンパイルエラー

  25. 25

    MATLAB CUDAカーネルオブジェクト-gatherの使用中にエラーが発生しましたか?

  26. 26

    cudaのインストール時に壊れたパッケージを修正できません

  27. 27

    RuntimeError:CUDAデバイス2でオブジェクトを逆シリアル化しようとしていますが、torch.cuda.device_count()は1です

  28. 28

    Ubuntu16へのCUDA8のインストール:パッケージcudaが見つかりません

  29. 29

    Ubuntu16へのCUDA8のインストール:パッケージcudaが見つかりません

ホットタグ

アーカイブ