Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在单独的线程中将VBO发送到GPU_Java_Multithreading_Opengl_Lwjgl_Vbo - Fatal编程技术网

Java 在单独的线程中将VBO发送到GPU

Java 在单独的线程中将VBO发送到GPU,java,multithreading,opengl,lwjgl,vbo,Java,Multithreading,Opengl,Lwjgl,Vbo,我正在开发一个LWJGL游戏,在这个游戏中,世界变化非常频繁,因为它相当大,每次世界更新时,它都会导致游戏冻结几分之一秒,从而更新相应的VBO。我通过将所有逻辑移动到单独的线程(实际上,渲染代码位于单独的线程中),减少了游戏冻结的时间,但将数据推送到图形卡似乎仍然会造成明显的延迟。有没有可能在我的逻辑线程中发送VBO,以免减慢游戏速度 此外,如果这属于gamedev.so,请告诉我,以便我可以移动它。我不太确定,所以我决定在这里发布。一般来说,一个GL上下文在任何时候都可以是单个线程的当前上下文

我正在开发一个LWJGL游戏,在这个游戏中,世界变化非常频繁,因为它相当大,每次世界更新时,它都会导致游戏冻结几分之一秒,从而更新相应的VBO。我通过将所有逻辑移动到单独的线程(实际上,渲染代码位于单独的线程中),减少了游戏冻结的时间,但将数据推送到图形卡似乎仍然会造成明显的延迟。有没有可能在我的逻辑线程中发送VBO,以免减慢游戏速度


此外,如果这属于gamedev.so,请告诉我,以便我可以移动它。我不太确定,所以我决定在这里发布。

一般来说,一个GL上下文在任何时候都可以是单个线程的当前上下文,一个线程在任何时候都可以有一个当前GL上下文。如果要并行更新总账对象,有两个选项:

  • 使用共享上下文。这样,每个trhead都可以有自己的GL上下文,但是像缓冲区纹理这样的对象。。。可以由两个线程使用(和修改)
  • 对于您的特定场景。使用映射的VBO(可能是一个环形缓冲区)就足够了。您只需要GL上下文来映射/取消映射缓冲区,但是当它被映射时,您可以在任意线程中访问它-这根本不需要GL上下文。在这种情况下,通常使用VBOs的环形缓冲区来避免线程之间的过度同步

  • 一般来说,GL上下文可以在任何时间对单个线程是当前的,并且线程可以在任何时间具有一个当前GL上下文。如果要并行更新总账对象,有两个选项:

  • 使用共享上下文。这样,每个trhead都可以有自己的GL上下文,但是像缓冲区纹理这样的对象。。。可以由两个线程使用(和修改)
  • 对于您的特定场景。使用映射的VBO(可能是一个环形缓冲区)就足够了。您只需要GL上下文来映射/取消映射缓冲区,但是当它被映射时,您可以在任意线程中访问它-这根本不需要GL上下文。在这种情况下,通常使用VBOs的环形缓冲区来避免线程之间的过度同步
  • 不能使用多任务处理来使用OpenGL进行渲染。显然,我错了,不过如果您只想使用单个OpenGL上下文来解决问题,答案的其余部分仍然很好

    虽然我在制作无限程序地形生成器时遇到了相同的问题,但问题与您的问题相同,每次世界更新或生成新的地形块时,它都会冻结一小部分秒

    如何解决这个问题 基本上,我是通过以下步骤来解决这个问题的

    创建一个线程池/线程队列,每当世界发生变化时,您都会让一个单独的
    线程
    处理/更新或重新创建
    浮动缓冲区
    (或您使用的其他缓冲区)。因为通常这就是冻结的原因,只是因为创建缓冲区、输入和更改所有数据等需要花费大量时间

    这里是我的意思布局

    class VBOAntiFreeze {
        FloatBuffer vertex_data;
        // Just add the rest of the FloatBuffers you use as well, like FloatBuffer
        // normal_data; FloatBuffer color_data; etc.
    
        // You would also have all the other variables as the vbo_handle, vertices count, etc.
    
        boolean fresh = true;
        boolean dirty, updating;
    
        public void updateVBO() {
            if (fresh && !updating) {
                updating = true;
    
                // You could execute new Threads by creating a
                // Thread Pool/Thread Queue, that way, you will
                // have some more control over all the threads.
    
                new Thread(new Runnable() {
                    public void run() {
                        // Update and process all the FloatBuffers here!
    
                        dirty = true;
                        fresh = false;
                        updating = false;
                    }
                }).start();
            }
        }
    
        public void renderVBO() {
            if (updating) {
                return;
            }
            else if (fresh) {
                updateVBO();
    
                return;
            }
    
            if (dirty) {
                // Buffer all the newly updated data
            }
    
            // Render the VBO here
        }
    }
    
    通过使用这种想法,您可能不会经历随机冻结,除非您的VBO异常庞大,因此
    if(dirty)buffer new data
    将/可能仍然会冻结一点,尽管我以前从未经历过。只是说,告诉你

    不能使用多任务处理来使用OpenGL进行渲染。显然,我错了,不过如果您只想使用单个OpenGL上下文来解决问题,答案的其余部分仍然很好

    虽然我在制作无限程序地形生成器时遇到了相同的问题,但问题与您的问题相同,每次世界更新或生成新的地形块时,它都会冻结一小部分秒

    如何解决这个问题 基本上,我是通过以下步骤来解决这个问题的

    创建一个线程池/线程队列,每当世界发生变化时,您都会让一个单独的
    线程
    处理/更新或重新创建
    浮动缓冲区
    (或您使用的其他缓冲区)。因为通常这就是冻结的原因,只是因为创建缓冲区、输入和更改所有数据等需要花费大量时间

    这里是我的意思布局

    class VBOAntiFreeze {
        FloatBuffer vertex_data;
        // Just add the rest of the FloatBuffers you use as well, like FloatBuffer
        // normal_data; FloatBuffer color_data; etc.
    
        // You would also have all the other variables as the vbo_handle, vertices count, etc.
    
        boolean fresh = true;
        boolean dirty, updating;
    
        public void updateVBO() {
            if (fresh && !updating) {
                updating = true;
    
                // You could execute new Threads by creating a
                // Thread Pool/Thread Queue, that way, you will
                // have some more control over all the threads.
    
                new Thread(new Runnable() {
                    public void run() {
                        // Update and process all the FloatBuffers here!
    
                        dirty = true;
                        fresh = false;
                        updating = false;
                    }
                }).start();
            }
        }
    
        public void renderVBO() {
            if (updating) {
                return;
            }
            else if (fresh) {
                updateVBO();
    
                return;
            }
    
            if (dirty) {
                // Buffer all the newly updated data
            }
    
            // Render the VBO here
        }
    }
    

    通过使用这种想法,您可能不会经历随机冻结,除非您的VBO异常庞大,因此
    if(dirty)buffer new data
    将/可能仍然会冻结一点,尽管我以前从未经历过。只是说,告诉你

    我决定写我的评论作为答案,因为它与绘图线程上的其他两个答案略有不同。在上载顶点数据或取消映射缓冲区时,我建议使用双缓冲区,并在工作线程完成更新后将用于绘制的VBO与用于提交数据的VBO交换,而不是暂停管道

    这种方法需要两个渲染上下文,每个上下文共享资源

    在工作线程中,您可以像在当前方法中通常那样将子数据分配/流式传输到VBO中,唯一的区别是您将对不用于绘图的VBO执行此操作。用数据填充此VBO后,请让绘图线程知道,然后在绘图时将用于绘图的VBO与用于流式顶点数据的VBO交换。在这种情况下,工作线程应该阻塞,直到图形线程交换VBO

    这样,当必须将新数据提交到GPU时,您将暂停用于流式传输新数据的线程,直到图形线程交换VBO,而不是暂停图形线程。因此,渲染将是平滑的(er),但更新可能以更可变的频率发生。这通常是像游戏这样的交互式软件的一个可取的特征——在某些事情发生之前有一个额外的延迟帧