gpt4 book ai didi

c++ - 从后台线程调用时 glewInit 失败

转载 作者:行者123 更新时间:2023-11-30 02:23:18 29 4
gpt4 key购买 nike

在我的应用程序中,我有一个用于离屏渲染的隐藏 GLFW 窗口。我想使用此窗口从多个后台线程进行渲染。保证一次只有一个线程使用窗口。

在后台线程上的每个渲染操作之前,我执行以下操作:

glfwMakeContextCurrent((GLFWwindow *)window);
glewExperimental = withGlewExperimental ? GL_TRUE : GL_FALSE;
const auto glewInitStatus = glewInit();
if (glewInitStatus != GLEW_OK)
LOG(ERROR) << "Could not initialize glew, error: " << glewGetErrorString(glewInitStatus);

第一次,它正常执行,但是当第二个线程获取上下文时,glewInit 失败。

Could not initialize glew, error: Missing GL version

当我为每个线程创建一个新的隐藏窗口时,这似乎没有重现,但是 GLFW 禁止在主线程之外创建窗口,并且为每个线程维护窗口池变得复杂实现并创建了许多不必要的窗口。这就是为什么我希望所有线程都呈现到同一个窗口。

有一个叫做GLEW_MX的东西支持多上下文,但是它只存在于旧版本的GLEW2.0.0之前,而我的 GLEW 版本没有这个选项。

所以,我想知道以下问题的答案:

  1. 这个想法是否可行(从多个线程呈现到单个窗口)?
  2. 如果是这种情况,我该如何使用 GLEW 修复错误
  3. 如果不是这种情况,您有什么解决方法建议?

最佳答案

  1. Is this idea viable at all (rendering to a single window from multiple threads)?

技术上正确的答案是肯定的。

实际上是正确的答案是否定的。

OpenGL 设计用于每个上下文的单个线程。如果您尝试同时使用多个线程,那么它的 API 几乎没有任何行为是正确的,虽然完全有可能通过将上下文所有权从一个线程传递到另一个线程来让 OpenGL 自行运行,确保在多线程场景中,一次只有一个线程与上下文交互,我无法想象您实际上会通过这样做获得显着性能提升的场景。

一般来说,我处理多线程渲染的方式是构建一个消息队列,多个线程可以写入,但只有渲染线程可以读取和执行。

class Renderer {
//Roll your own or find a good implementation somewhere online
concurrent::queue<std::function<void()>> rendering_queue;
std::thread rendering_thread;
GLFWwindow * window;
/*...*/
public:
Renderer(GLFWwindow * window) : window(window) {
rendering_thread = std::thread([this]{
glfwMakeContextCurrent(window);
glewInit(); //Check for error if necessary
while(!glfwWindowShouldClose(window)) {
draw();
glfwSwapBuffers(window);
}
});
}

Renderer(Renderer const&) = delete;

~Renderer() noexcept {
glfwSetWindowShouldClose(window, GLFW_TRUE);
rendering_thread.join();
}

void push_task(std::function<void()> func) {
rendering_queue.push(std::move(func));
}

void draw() {
std::function<void()> func;
while(rendering_queue.try_pop(func)) func();
/*Normal Rendering Tasks*/
}
};

int main() {
glfwInit();
GLFWwindow * window = glfwCreateWindow(800, 600, "Hello World!", nullptr, nullptr);
Renderer renderer(window);

std::thread circle_drawer{[&renderer]{
renderer.push_task([]{/*Draw a Circle*/});
renderer.push_task([]{/*Draw a Circle*/});
renderer.push_task([]{/*Draw a Circle*/});
renderer.push_task([]{/*Draw a Circle*/});
renderer.push_task([]{/*Draw a Circle*/});
renderer.push_task([]{/*Draw a Circle*/});
renderer.push_task([]{/*Draw a Circle*/});
renderer.push_task([]{/*Draw a Circle*/});
renderer.push_task([]{/*Draw a Circle*/});
}};
circle_drawer.detach();

std::thread square_drawer{[&renderer]{
renderer.push_task([]{/*Draw a Square*/});
renderer.push_task([]{/*Draw a Square*/});
renderer.push_task([]{/*Draw a Square*/});
renderer.push_task([]{/*Draw a Square*/});
}};
square_drawer.detach();

/*Etc...*/

while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
}

显然我抽象掉了很多细节,但这主要是因为您的问题非常广泛。对于至少在表面上需要多线程渲染能力的大多数应用程序,该模型应该适用并且具有可塑性。

关于c++ - 从后台线程调用时 glewInit 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46350082/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com