【问题标题】:SDL / OpenGL: Implementing a "Loading thread"SDL / OpenGL:实现“加载线程”
【发布时间】:2011-10-12 20:48:58
【问题描述】:

我目前尝试为一个非常基本的游戏引擎实现一个“加载线程”,它负责加载例如纹理或音频,而主线程不断渲染正确的消息/屏幕,直到操作完成,甚至渲染常规游戏场景,同时在后台加载较小的对象。

现在,我到目前为止还不是 OpenGL 专家,但是当我实现了这样一种“加载”机制时,我很快发现 OGL 不喜欢从一个线程访问渲染上下文,而不是它创建的线程。很多。我搜索了一下,解决方案似乎是:

“在线程上创建第二个渲染上下文,并与主线程的上下文共享”

问题在于我使用 SDL 来处理我的窗口管理和上下文创建,据我检查 API 可以看出,没有办法告诉 SDL 在彼此之间共享上下文:(

我得出的结论是,我的案例的最佳解决方案是:

方法 A) 更改 SDL 库以支持与平台特定函数的上下文共享(我假设为 wglShareLists() 和 glXCreateContext())

方法 B)让“加载线程”仅将数据加载到内存中并将其处理为 OpenGL 友好的格式并将其传递给主线程,例如负责将纹理上传到图形适配器。当然,这仅适用于需要完成有效 OpenGL 上下文的数据

我猜第一个解决方案是效率最低的。我真的不想使用 SDL,除此之外,我读到上下文共享不是一种高性能操作。所以我的下一步将是目前为止的第二种方法。

编辑:关于“高性能操作”:我读错了文章,实际上并不是性能密集型。该文章建议将 CPU 密集型操作转移到具有第二个上下文的第二个线程。很抱歉

在所有这些介绍之后,如果有人能给我一些提示和解决以下问题,我将不胜感激:

1) 有没有办法与 SDL 共享上下文?这样做有什么好处吗?

2) 有没有其他更“优雅”的方式来在后台加载我可能错过或没想到的数据?

3) 我打算采用方法 B 的意图是否被认为是一个不错的选择?我的主线程上的 OpenGL 操作仍然会产生轻微的开销,这会阻塞渲染,还是小到可以忽略?

【问题讨论】:

  • 我会选择解决方案 B。让后台线程加载所有必要的数据,让主线程处理绘图。
  • 谢谢,我现在正在重构我的代码,以便以这种方式加载我的数据。但也许有人仍然有一些 cmets 让这个问题提供更多信息,以防有人遇到同样的问题:)
  • 请记住,这个解决方案说起来容易做起来难:根据您应用程序的细节,您的线程很可能必须正确同步,这并不总是简单的任务。我假设您已经研究过单线程替代方案,但没有找到适合您的方案。
  • 不幸的是,我没有找到合适的单线程解决方案:(但我仍在搜索。对于同步:我考虑过在每帧完成后查询线程,如果是这样,我知道我的数据已准备好由 OpenGL 处理。完成此步骤后,我的应用程序可以使用数据。如果我有一个正在运行的加载屏幕,我认为不需要做更多的事情 - 对于延迟在游戏场景运行时加载我还必须检查数据是否真的准备好。另外,还有一点点开销,但我认为没有其他解决方法
  • “我读到上下文共享不是高性能操作。”你在哪里读到的?因为这显然是错误的。

标签: c++ opengl sdl


【解决方案1】:

有什么方法可以与 SDL 共享上下文

没有。

是的!

您必须使用特定于平台的调用来获取当前上下文。从那里,您可以创建一个新的上下文并使其共享,也可以使用特定于平台的调用。

还有其他更“优雅”的方式来在后台加载我可能错过或没有想到的数据吗?

不是真的。您很好地列举了选项:破解 SDL 以获取您需要的数据,或低效地加载数据。

但是,您可以将数据加载到映射缓冲区对象和transfer the data to OpenGL。您只能在 OpenGL 线程上进行映射/取消映射,但映射时获得的指针可以在任何线程上使用。所以映射一个缓冲区,将它传递给工作线程。它将数据加载到映射的内存中,并翻转一个开关。 GL 线程取消映射指针(工作线程现在应该忘记指针)并上传纹理数据。

我打算采用方法 B 的意图是否被认为是一个不错的选择?

定义“好”?如果不进一步了解您的问题域,就无法回答这个问题。

【讨论】:

  • “好”实际上是指无论如何让上下文共享进行通常是一个更好或更专业的想法。不过谢谢你的建议,我明天一定会调查的。
  • @Nicol Bolas:实际上你可以与 SDL 共享上下文,如果你不会因为编写平台相关代码而感到困惑:wglGetCurrent{DC,Context}, glXGetCurrent{Display,Drawable,Context},你想其余的部分。我在我的 PBuffer 便利库中使用了这些。
  • @datenworlf:我完全忘记了你只能得到当前的上下文。
  • @datenwolf 完美运行!首先,我按照建议获得了带有 wglGetCurrent{DC,Context} 的 DC/RC,从线程内创建了一个新上下文并将其设为当前,然后与 wglShareLists(mainContext, threadContext) 共享显示列表空间。谢谢!
猜你喜欢
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多