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 = -816294792and的内容w = -816294792,但我想这只是意味着它尚未设置,因为它还在调试器中显示了用于加载其他纹理的内容。

此外,代码的 SOIL_load_OGL_texture 部分在 Texture 类之外,即使在 std::thread 中也可以正常工作。

知道这里发生了什么吗?

4

1 回答 1

0

这就是你的做法。请注意,正如其他人在评论中提到的那样,需要为每个使用 GL 的线程保持当前的上下文。这意味着实际上不能在多个线程中进行 GL API 调用,而不使一个线程成为 GL 上下文的所有者。因此,如果打算分离图像加载开销,建议使用单独线程中的库将图像文件加载到缓冲区中,然后将该缓冲区用于主线程中的 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 回答