LWJGL glGenVertexArrays()阻止执行 [英] LWJGL glGenVertexArrays() is blocking the execution

查看:63
本文介绍了LWJGL glGenVertexArrays()阻止执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在论坛上问了一个问题,为什么ExecutorService在获得期货后为何阻止我的程序: ExecutorService和Future阻止了主线程

问题是经过大量调试后,罪魁祸首不是将来.get()而是 int vaoID = GL30.glGenVertexArrays();

我将总结我想做的事情,然后发布代码.基本上,随着玩家的移动,我正在生成地形.为了避免每当发生这种情况时就冻结游戏,我使用callables和ExecutorService和Futures实现了多线程.因此,当我必须生成地形时,我要向ExecutorService提交新任务(任务是计算地形的所有顶点/法线/颜色),然后对于每个将来,如果完成,我都会得到结果并生成地形模型.但是在每一帧中,完成的第一个未来都会导致冻结.实际上,造成这种情况的不是未来本身,而是模型的创建,更确切地说,是 int vaoID = GL30.glGenVertexArrays(); 方法.

总而言之,我认为glGenVertexArrays();正在阻塞线程,等待其他线程完成,并且我对发生的事情一无所知.我正在使用LWJGL 2和OpenGL 3.0 +.

以下是处理多线程的代码:

 //调用每个框架的方法private void checkForFutures(List< Future< SomeClass>> terrainsInCreation){尝试{List< Future< SomeClass>>futuresToRemove = new ArrayList< Future< SomeClass>>();for(Future< SomeClass> future:terrainsInCreation){if(future.isDone()){浮动时间= DisplayManager.getCurrentTime();尝试 {SomeClass t = future.get();密钥=新密钥(t.terrain.getChunkX(),t.terrain.getChunkZ());t.terrain.generateTerrain(加载程序,t.vertices,t.indices,t.colors,t.normals);//有罪的线!futuresToRemove.add(future);} catch(ExecutionException e){e.printStackTrace();Thread.sleep(1000000);}}}terrainsInCreation.removeAll(futuresToRemove);}抓(InterruptedException即){System.err.println(地形管理器上的大问题");}}//当我要生成地形时调用的方法私人void generate(List< Callable< SomeClass>> terrainsToCreate){for(int i = 0; i< terrainsToCreate.size(); i ++){terrainsInCreation.add(executor.submit(terrainsToCreate.get(i)));}} 

这是generateTerrain()方法:

  int vaoID = createVAO();bindIndicesBuffer(indices);storeDataInAttributeList(0,3,职位);storeDataInAttributeList(1,3,颜色);storeDataInAttributeList(2,3,法线);unbindVAO();返回新的RawModel(vaoID,index.length); 

(我简化了代码)

这是createVao()方法:

 私人int createVAO(){长的开始= DisplayManager.getCurrentTime();int vaoID = GL30.glGenVertexArrays();//每帧的第一帧大约需要40-200mslong glGen = DisplayManager.getCurrentTime();vaos.add(vaoID);长添加= DisplayManager.getCurrentTime();GL30.glBindVertexArray(vaoID);长绑定= DisplayManager.getCurrentTime();System.out.println(String.format("Vao:gen:%d + add:%d + bind:%d =%d",(glGen-start),(add-glGen),(绑定添加),(DisplayManager.getCurrentTime()-开始)));返回vaoID;} 

最后是常规生成的打印输出:

 新支票新支票Vao:Gen:7 +添加:0 +绑定:0 = 7Vao:gen:1 + add:0 + bind:0 = 1Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0新支票Vao:Gen:209 +添加:0 +绑定:0 = 209(为什么????)Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:gen:1 + add:0 + bind:0 = 1Vao:gen:1 + add:0 + bind:0 = 1Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:gen:0 + add:0 + bind:1 = 1Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:Gen:0 +添加:0 +绑定:0 = 0新支票Vao:Gen:4 +添加:0 +绑定:0 = 4Vao:Gen:0 +添加:0 +绑定:0 = 0Vao:gen:0 + 添加:0 + 绑定:0 = 0新支票新支票 

我正在打印的每一帧NEW CHECK";正如你所看到的,它不是每一帧的第一个,有时不是,但是当发生生成事件时,第一个总是超级慢.

我的问题是这里发生了什么,我该怎么做/测试/更新?

感谢您的帮助.

编辑

我必须精确说明在主线程中调用了GL30.glGenVertexArrays().下面是在程序开始之前执行的上下文代码:

 ContextAttribs属性=新的ContextAttribs(3,2).withForwardCompatible(true).withProfileCore(true);Mouse.setGrabbed(true);尝试 {DisplayMode displayMode = new DisplayMode(WIDTH, HEIGHT);Display.setDisplayMode(displayMode);Display.create(new PixelFormat(),attribs);Display.setTitle(CubeLand");} catch(LWJGLException e){e.printStackTrace();} 

编辑2

我通过在主线程中进行所有操作来删除多线程,并且在生成时发生了大致相同的冻结,这是正常的,因为计算量很大,但但是 GL30.glGenVertexArrays()不是花费任何时间进行计算.这证明该方法正在等待所有其他线程结束,但为什么以及如何避免这种情况??

 新支票蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0蒸气数:0新支票 

编辑3 一些消息,当我拔下笔记本电脑的电源时,图形卡已关闭,主板图形芯片组已将其更换.突然,问题消失了.当然,由于我的性能被切断,即使使用多线程,处理器也难以生成地形,但是我仍然停滞不前,但是vao gen时间回到了0.这很令人困惑.

解决方案

好的,因此经过2周的努力,我终于找到了解决方法.经过长时间的性能分析会话后,我90%确信glGenVertexArrays()正在等待某些线程完成其任务,我不知道为什么,但是它有2/3倍的关联性.解决方法是等待所有期货推出,然后生成地形(也称为glGenVertexArrays()).这样,glGenVertexArrays()不会暂停主线程,并且为了避免同时创建数十个地形,我每帧只能创建2-3个,这并不引人注目.

I recently asked a question on the forum on why the ExecutorService was blocking my program after getting the futures: ExecutorService and Future are blocking the main thread

The thing is that after a lot of debugging, the guilty line wasn't the future.get() but int vaoID = GL30.glGenVertexArrays();

I'll sum up what I'm trying to do, and then post the code. Basically, I'm generating terrains as the player moves. To avoid freezing the game whenever the generation happens, I implemented multithreading with callables and ExecutorService and Futures. So when I have to generate terrains I'm submitting new tasks to the ExecutorService (the task is to calculate all the vertices/normals/colors of the terrain), and then for each future, if it is done I'm getting the result and generate the model of the terrain. But at each frame, the first future that finishes is causing a freeze. Actually, it's not the future itself that is causing it but the creation of the model, and more precisely the int vaoID = GL30.glGenVertexArrays(); method.

To sum up, I think that glGenVertexArrays(); is blocking the thread, waiting for maybe the other threads to finish, and I don't have a single clue of what is going on. I am using LWJGL 2 and OpenGL 3.0+.

Here is the code that handles the multithreading:


//method called each frame
private void checkForFutures(List<Future<SomeClass>> terrainsInCreation) {
        try
        {
            List<Future<SomeClass>> futuresToRemove = new ArrayList<Future<SomeClass>>();
            for(Future<SomeClass> future:terrainsInCreation) {
                if(future.isDone()) {
                    float time = DisplayManager.getCurrentTime();
                    try {
                        SomeClass t = future.get();
                        Key key = new Key(t.terrain.getChunkX(),t.terrain.getChunkZ());
                        t.terrain.generateTerrain(loader, t.vertices, t.indices,t.colors, t.normals); // Guilty line !
                        futuresToRemove.add(future);
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                        Thread.sleep(1000000);
                    }
                }
            }
            terrainsInCreation.removeAll(futuresToRemove);
        }
        catch (InterruptedException ie)
        {
            System.err.println("BIG PROBLEM ON TERRAIN MANAGER");          
        }
    }

//method called when I have terrains to generate
    private void generate(List<Callable<SomeClass>> terrainsToCreate) {

        for(int i = 0; i < terrainsToCreate.size();i++) {
            terrainsInCreation.add(executor.submit(terrainsToCreate.get(i)));
        } 
    }

Here is the generateTerrain() method:

        int vaoID = createVAO();
        bindIndicesBuffer(indices);
        storeDataInAttributeList(0,3, positions);
        storeDataInAttributeList(1,3, colors);
        storeDataInAttributeList(2, 3, normals);

        unbindVAO();
        
        return new RawModel(vaoID, indices.length);


(I simplified the code)

And here is the createVao() method:


private int createVAO() {
        long start = DisplayManager.getCurrentTime();
        int vaoID = GL30.glGenVertexArrays(); // The first of each frame takes ~40-200ms
        long glGen = DisplayManager.getCurrentTime();

        vaos.add(vaoID);
        long add = DisplayManager.getCurrentTime();

        GL30.glBindVertexArray(vaoID);
        long bind = DisplayManager.getCurrentTime();
        
        System.out.println(String.format("Vao: gen: %d + add: %d + bind: %d = %d", 
                (glGen-start),
                (add-glGen),
                (bind-add),
                (DisplayManager.getCurrentTime()-start)));
        return vaoID;
    }

And finally here is the print output in a regular generation:


NEW CHECK
NEW CHECK
Vao: gen: 7 + add: 0 + bind: 0 = 7
Vao: gen: 1 + add: 0 + bind: 0 = 1
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
NEW CHECK
Vao: gen: 209 + add: 0 + bind: 0 = 209 (why????)
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 1 + add: 0 + bind: 0 = 1
Vao: gen: 1 + add: 0 + bind: 0 = 1
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 1 = 1
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
NEW CHECK
Vao: gen: 4 + add: 0 + bind: 0 = 4
Vao: gen: 0 + add: 0 + bind: 0 = 0
Vao: gen: 0 + add: 0 + bind: 0 = 0
NEW CHECK
NEW CHECK

Each frame I'm printing "NEW CHECK" and as you can see it is not exactly the first of each frame sometimes it is not but when a generation event occurs the first is always super slow.

My question is what is going on here and what can I do / test / update ?

Thanks for your help.

EDIT

I must precise that GL30.glGenVertexArrays() is called in the main thread. Here is the context code executed before anything else at the start of the program:


ContextAttribs attribs = new ContextAttribs(3,2)
        .withForwardCompatible(true)
        .withProfileCore(true);
        Mouse.setGrabbed(true);

        try {
            DisplayMode displayMode = new DisplayMode(WIDTH, HEIGHT);
            Display.setDisplayMode(displayMode);
            Display.create(new PixelFormat(),attribs);
            Display.setTitle("CubeLand");
        } catch (LWJGLException e) {
            e.printStackTrace();
        }

EDIT 2

I removed the multithreading, by doing everything in the main thread, and about the same freeze happens when generating, which is normal because the calculations are huge, BUT the GL30.glGenVertexArrays() is not taking any time to compute. This proves that this method is waiting for all the other threads to end, but why and how to avoid that??


NEW CHECK
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
Vao gen: 0
NEW CHECK

EDIT 3 Some news, when I unplug my laptop, the graphic card is turned off and the motherboard graphic chipset replace it. Suddenly, the issue is gone. Off course I still have freezes because now that my performance are cut off, the processor struggles to generate the terrain even with multithreading, but the vao gen time is back to 0. This is confusing.

解决方案

Okay, so after 2 weeks of struggling with this, I finally found a workaround. After a long profiling session, I'm 90% sure that glGenVertexArrays() is waiting for some threads to finish their tasks, I don't know why, but it correlates 2/3 times. The workaround is to wait for all the futures to come out, and then generate the terrains (aka call glGenVertexArrays()). This way, the glGenVertexArrays() is not pausing the main thread, and to avoid creating dozens of terrains at the same time I'm only creating like 2-3 per frames, which is unnoticeable.

这篇关于LWJGL glGenVertexArrays()阻止执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆