0

通常、SOIL/OpenGL でテクスチャを問題なくロードできます。エラーはありません。すべて正常に動作します。

// this is inside my texture loading code in my texture class
// that i normally use for loading textures
image = SOIL_load_OGL_texture
    (
    file,
    SOIL_LOAD_AUTO,
    SOIL_CREATE_NEW_ID,
    NULL
    );

ただし、同じコードを使用して std::thread から呼び出すと、次の行image = SOIL_load_OGL_textureで未処理の例外が発生しInteger Division by Zeroます。

void loadMe() {
    Texture* abc = new Texture("res/img/office.png");
}

void loadStuff() {
    Texture* loading = new Texture("res/img/head.png"); // < always works

    loadMe() // < always works
    std::thread textures(loadMe); // < always "integer division by zero"

Texture クラスの関連コードを次に示します。

// inside the class
private:
    GLint w, h;
    GLuint image;

// loading the texture (called by constructor if filename is given)
void Texture::loadImage(const char* file)
{

    image = SOIL_load_OGL_texture
        (
        file,
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        NULL
        );

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, image);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
    glBindTexture(GL_TEXTURE_2D, 0);

    if (image <= 0)
        std::cout << file << " failed to load!\n";
    else
        std::cout << file << " loaded.\n";

    glDisable(GL_TEXTURE_2D);
}

で正確に例外が発生し、デバッガーに移動すると、 やimage = SOIL_load_OGL_textureのようなものが表示されますが、デバッガーで他のテクスチャをロードすることも示されているため、まだ設定されていないことを意味していると思います。w = -816294792w = -816294792

また、コードの SOIL_load_OGL_texture 部分は、std::thread 内であっても Texture クラスの外部で、それ自体で正常に動作します。

ここで何が起こっているのか分かりますか?

4

1 に答える 1

0

これがあなたのやり方です。他の人がコメントで述べているように、GL を使用するすべてのスレッドでコンテキストを最新に保つ必要があることに注意してください。これが意味することは、実際には、1 つのスレッドを GL コンテキストの所有者にしない限り、複数のスレッドで GL API 呼び出しを行うことはできないということです。したがって、イメージのロード オーバーヘッドを分離することが目的の場合は、別のスレッドでライブラリを使用してイメージ ファイルをバッファにロードし、そのバッファをメイン スレッドで glTexImage2D に使用することをお勧めします。画像が読み込まれるまで、ダミーのテクスチャを表示できます。

使用しているプラ​​ットフォームを確認してみました (上記のコメントを参照)。応答がなかったので、以下は Linux を想定しています。

/* Regular GL context creation foo */
/* Regular attribute, uniform, shader creation foo */
/* Create a thread that does loading with SOIL in function SOIL_loader */
std::thread textureloader(SOIL_loader);
/* Wait for loader thread to finish, 
thus defeating the purpose of a thread. Ideally, 
only the image file read/decode should happen in separate thread */
textureloader.join();
/* Make the GL context current back again in the main thread 
for other actions */
glfwMakeContextCurrent((GLFWwindow*)window);
/* Some other foo */

======

そして、これはローダースレッド関数です:

void SOIL_loader()
{
   glfwMakeContextCurrent((GLFWwindow*)window);
    SOIL_load_OGL_texture
        (
        "./img_test.png",
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID /* or passed ID */,
        NULL
        );
   GL_CHECK(SOIL);
}

Ubuntu 14.04、Mesa、glfw3 でテスト済み。

于 2016-01-29T18:09:49.987 に答える