小编rja*_*cks的帖子

OpenGL在辅助线程中渲染

我正在编写一个3D模型查看器应用程序作为业余爱好项目,也作为一个测试平台来尝试不同的渲染技术.我正在使用SDL来处理窗口管理和事件,以及用于3D渲染的OpenGL.我的程序的第一次迭代是单线程的,运行得很好.但是,我注意到单线程程序导致系统变得非常缓慢/滞后.我的解决方案是将所有呈现代码移动到不同的线程中,从而释放主线程来处理事件并防止应用程序无响应.

该解决方案间歇性地工作,程序经常因为主要来自X窗口系统的变化(并且在我看来奇怪)一组错误而崩溃.这让我质疑我最初的假设,即只要我的所有OpenGL调用都发生在创建上下文的线程中,一切都应该仍然有效.在花了一天的大部分时间在互联网上寻找答案后,我彻底难过了.

更简洁:是否可以在主线程以外的线程中使用OpenGL执行3D渲染?我是否仍可以使用此配置的跨平台窗口库(如SDL或GLFW)?有没有更好的方法来做我想做的事情?

到目前为止,我一直在使用C++在Linux(Ubuntu 11.04)上进行开发,尽管如果有一种在这些语言中效果更好的解决方案,我也对Java和Python感到满意.

更新:根据要求,一些澄清:

  • 当我说"系统变得迟钝"时,我的意思是与桌面交互(拖动窗口,与面板交互等)变得比正常情况慢得多.移动我的应用程序的窗口需要几秒钟的时间,而其他交互只是慢到足以令人讨厌.
  • 至于干扰合成窗口管理器...我正在使用Ubuntu 11.04附带的GNOME shell(现在远离Unity ...)我找不到任何禁用桌面效果的选项,例如以前的发行版.我认为这意味着我没有使用合成窗口管理器......虽然我可能是非常错误的.
  • 我认为"X错误"是由于我在终端上收到的错误消息导致的服务器错误.更多细节如下.

我的应用程序的多线程版本出现的错误:

XIO:X服务器上的致命IO错误11(资源暂时不可用)在73个请求(73个已知处理)之后":0.0",剩余0个事件.

X请求失败的错误:BadColor(无效的Colormap参数)失败请求的主要操作码:79(X_FreeColormap)失败请求中的资源ID:0x4600001失败请求的序列号:72输出流中的当前序列号:73

游戏:../../ src/xcb_io.c:140:dequeue_pending_request:断言`req == dpy-> xcb-> pending_requests'失败.中止

我总是得到上面三个错误中的一个,我得到的一个变化,显然是随机的,这(我的眼睛)似乎证实我的问题确实源于我使用线程.请记住,我正在学习,因此我很有可能在我的无知中,我有一些相当愚蠢的东西.

解决方案:对于遇到类似问题的任何人,我通过将调用移至SDL_Init(SDL_INIT_VIDEO)渲染线程并使用互斥锁锁定上下文初始化来解决我的问题.这可以确保在将要使用它的线程中创建上下文,并且它可以防止主循环在初始化任务完成之前启动.启动过程的简化概述:

1)主线程初始化struct将在两个线程之间共享,并包含互斥锁.
2)主线程生成渲染线程并暂停一段时间(1-5ms),使渲染线程有时间锁定互斥锁.暂停后,主线程在尝试锁定互斥锁时阻塞.
3)渲染线程锁互斥,初始化SDL的视频子系统并创建OpenGL上下文.
4)渲染线程解锁互斥锁并进入其"渲染循环".
5)主线程不再被阻塞,因此在完成初始化步骤之前锁定和解锁互斥锁.

请务必阅读答案和评论,那里有很多有用的信息.

opengl multithreading sdl

26
推荐指数
1
解决办法
2万
查看次数

OpenGL着色器编译问题 - 意外的EOF

所以我决定尝试使用Java编写一个简单的OpenGL应用程序,只是为了看看它与我的其他工作相比如何,我遇到了我的着色器拒绝编译的问题.他们真的不能简单得多,这是我的顶点着色器来展示我的意思:

//Minimal vertex shader

#version 330

in vec3 in_Position;
in vec3 in_Color;
out vec3 var_Color;

void main(void)
{
    gl_Position = vec4(in_Position, 1.0);
    var_Color = in_Color;
}
Run Code Online (Sandbox Code Playgroud)

片段着色器也很简单,所以除非有人要求,否则我不会打扰它.当我检查日志时,我收到以下错误(对于两个着色器):

(0) : error C0000: syntax error, unexpected $end at token "<EOF>"
Run Code Online (Sandbox Code Playgroud)

我不确定这是否相关......但我正在使用Java在Linux(Ubuntu 11.04)上进行开发.我使用的唯一库是JOGL(用于openGL绑定)和标准Java库(如果它甚至算......)我的显卡是Nvidia GeForce 9600M GS,我检查了扩展,它完全支持OpenGL 3.3.

帮我Stack Overflow,你是我唯一的希望.

编辑:

根据要求,这是负责加载和编译着色器源的函数.另外,说到GLSL,我是一个超级n00b,所以我真的不知道要找什么,以确保OpenGL的格式正确.关于该主题的最新(即处理OpenGL 3.x)教程的链接将不胜感激.

private int CreateCompiledShader(File source, int shader, GL3 gl){
        int shaderloc = gl.glCreateShader(shader);

        BufferedReader input = null;
        ArrayList<String> lines = new ArrayList<String>();
        ArrayList<Integer> lengths = new ArrayList<Integer>();
        try{
            input = new BufferedReader(new …
Run Code Online (Sandbox Code Playgroud)

opengl shader jogl

9
推荐指数
1
解决办法
9972
查看次数

一旦添加了信号/插槽,简单的Qt App就会拒绝编译

所以基本上,我正在制作一个非常简单的Qt应用程序来帮助我学习OpenGL.
我的想法是我有两个窗口,一个是GL上下文(GLWidget,派生自QGLWidget),另一个是带有几个进度条和文本区域的简单GUI.

我可以让应用程序编译和运行,一切都很美丽直到我试图连接两个窗口之间的信号和插槽.我已经阅读了关于QGLWidget的文档,关于信号和插槽的官方教程,以及文档int connect().

为了说明:我的main.cpp文件:

#include <QApplication>
#include <QObject>

#include "glwidget.h"
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MainWindow *mWindow = new MainWindow();
    GLWidget *gl = new GLWidget();

    //If this line is commented out, the program compiles and runs
    connect(gl, SIGNAL(fpsReport(float)), mWindow, SLOT(updateFPS(float));

    mWindow->show();
    gl->show();

    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

我得到的具体编译器错误是:

In function 'int qMain(int, char**)':
invalid conversion from 'GLWidget*' to 'SOCKET'
cannot convert 'const char*' to 'const sockaddr*' for argument '2' to 'int …

qt compiler-errors signals-slots

5
推荐指数
1
解决办法
2338
查看次数

使用GCC的函数检测,为什么使用C++ STL容器或流I/O会导致段错误?

我最近读到了使用GCC的代码生成功能(特别是-finstrument-functions编译器标志)来轻松地将检测添加到我的程序中.我认为这听起来很酷,并且在以前的C++项目中尝试过.经过我的补丁的几次修改后,我发现每当我尝试使用STL容器或使用C++流I/O打印到stdout时,我的程序会立即崩溃并发生段错误.我的第一个想法是要保持std::listEvent结构

typedef struct  
{
    unsigned char event_code;
    intptr_t func_addr;
    intptr_t caller_addr;
    pthread_t thread_id;
    timespec ts;
}Event;

list<Event> events;
Run Code Online (Sandbox Code Playgroud)

程序终止时将写入文件.GDB告诉我,当我尝试添加一个Event列表时,调用events.push_back(ev)自己启动了一个检测调用.在考虑了一下之后,这并不令人惊讶并且有意义,所以计划2.

博客中让我参与所有这些混乱的例子没有做任何疯狂的事情,它只是简单地将一个字符串写入文件中fprintf().我不认为使用C++的基于流的I/O而不是旧的I/O会有任何损害(f)printf(),但这种假设被证明是错误的.这一次,GDB报告了标准库中相当正常的下降,而不是几乎无限的死亡螺旋,然后是段错误.

一个简短的例子

#include <list>
#include <iostream>
#include <stdio.h>

using namespace std;

extern "C" __attribute__ ((no_instrument_function)) void __cyg_profile_func_enter(void*, void*);

list<string> text;

extern "C" void __cyg_profile_func_enter(void* /* unused */, void* /* unused */)
{
    // Method 1
    text.push_back("NOPE");

    // Method 2
    cout << "This explodes" << endl;

    // …
Run Code Online (Sandbox Code Playgroud)

c c++ instrumentation gcc

4
推荐指数
1
解决办法
2232
查看次数