简体   繁体   English

在std :: thread中用SOIL加载OpenGL纹理会引发“整数除以零”

[英]Loading OpenGL texture with SOIL in std::thread raises “Integer Division by Zero”

I can load a texture just fine in SOIL/OpenGL normally. 我可以正常在SOIL / OpenGL中加载纹理。 No errors, everything works fine: 没有错误,一切正常:

// 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
    );

However, using that same code and calling it from an std::thread, at the line image = SOIL_load_OGL_texture I get unhandled exception Integer Division by Zero : 但是,使用相同的代码并从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"

Here's some relevant code from my Texture class: 这是我的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);
}

It raises the exception exactly at image = SOIL_load_OGL_texture , and when I go into the debugger, I see things like w = -816294792 and w = -816294792 , but I guess that just means it hasn't been set yet, as it also shows that in the debugger for loading the other textures. 它恰好在image = SOIL_load_OGL_texture处引发了异常,当我进入调试器时,我看到类似w = -816294792w = -816294792 ,但是我想这只是意味着它尚未设置,因为它也显示在调试器中加载其他纹理。

Also, the SOIL_load_OGL_texture part of the code works fine by itself, outside of the Texture class, even in a std::thread. 而且,代码的SOIL_load_OGL_texture部分即使在std :: thread中,也可以在Texture类之外单独运行。

Any idea what's going on here? 知道这里发生了什么吗?

This is how you do it. 这就是你的做法。 Note that, as others have mentioned in the comments, a context needs to be maintained current for every thread that uses GL. 请注意,正如其他人在评论中提到的那样,需要为使用GL的每个线程保持最新的上下文。 What this means is practically there cannot be a GL API call made in multiple threads without making one thread the owner of the GL context. 这实际上意味着在没有使一个线程成为GL上下文所有者的情况下,无法在多个线程中进行GL API调用。 Hence if the intention is to separate the Image loading overhead it is recommended to load the image file into a buffer using a library in a separate thread, then use that buffer to glTexImage2D in the main thread. 因此,如果要分开图像加载开销,建议使用单独线程中的库将图像文件加载到缓冲区中,然后使用该缓冲区在主线程中使用glTexImage2D。 Till the image is loaded, a dummy texture can be displayed. 直到加载图像,才能显示虚拟纹理。

I tried checking what platform you are on (see comment above), since I did not see a response, I am assuming Linux for below. 我尝试检查您所使用的平台(请参见上面的注释),因为没有看到响应,因此我假设在下面使用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 */

====== ======

And this is the loader thread function: 这是加载程序线程函数:

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);
}

Tested on Ubuntu 14.04, Mesa, and glfw3. 在Ubuntu 14.04,Mesa和glfw3上进行了测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM