Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Double VBO no performance increase or decrease?  (Read 1221 times)
0 Members and 1 Guest are viewing this topic.
Offline noodleBowl

Senior Newbie





« Posted 2014-01-17 02:02:17 »

I have been attempting to get a double VBO system going. To my understanding it is nothing really special just create 2 VBOs and then fill them up right? So that is what I have done, but I have no performance gain or performance decrease according to my DT times.

It does not matter how many buffers I use (keeping one VBO or having 2 at the ready) my DT times are roughly the same.
Both with single and double VBOs it sits around .0024 seconds.

Surely, I would think that my DT time would be better with a double VBO assuming I did it right or worse if it was done wrong. But them being the same? It has to be wrong, right?

Here is the code I got, let me know if more info I needed. I am rendering 100000 32x32 quads
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
   public void render()
   {
                //Clear the current buffer
      vertexBuffer[buffer].clear();

                //Set up a new random for the positions
      int x = 0; int y = 0;
      Random random = new Random();
     
      //X and Ys for the Quad; The Z is set to 1.0f; Remember 100000 quads
      for(int i = 0; i < MAX_QUADS; i++)
      {
         x = random.nextInt(800);
         y = random.nextInt(600);
         draw(x, y, 32.0f, 32.0f);
      }
     
      //Flip the current buffer
      vertexBuffer[buffer].flip();
     
      //Use the shader program
      glUseProgram(shaderProgramHandle);
     
                //Bind the current buffer and send it off to queue up in the GPU
      glBindBuffer(GL_ARRAY_BUFFER, vertexBufferHandle);
      glBufferData(GL_ARRAY_BUFFER, vertexBuffer[buffer], GL_STREAM_DRAW);
     
      //Get the Uniform for the MVP shader
      glUniformMatrix4(matrixBufferHandle, false, mvpBuffer);
     
      //Enable the VAO and its attributes
      glBindVertexArray(vertexArrayHandle);
      GL11.glDrawElements(GL_TRIANGLES, indexDrawCount, GL11.GL_UNSIGNED_INT, 0);
      glBindVertexArray(0);
     
      buffer = 1 - buffer;
   }

        //Put in here just in case
   private void createBuffers()
   {  
                //Create the Vertex Buffers
      vertexBuffer = new FloatBuffer[2];
      vertexBuffer[0] = BufferUtils.createFloatBuffer(MAX_VERTEX_COUNT);
      vertexBuffer[1] = BufferUtils.createFloatBuffer(MAX_VERTEX_COUNT);
   
                //Index Buffer used
      indexBuffer = BufferUtils.createIntBuffer(MAX_INDEX_COUNT);
   }


Other things to mention I'm using one VAO, one Vertex Buffer Handle, and a Index buffer handle like so
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
        //Init the VAO for the buffers, the Vertex Buffers will be Identical 
   private void initializeVAO()
   {
      //Bind the VAO
      glBindVertexArray(vertexArrayHandle);
     
      //Bind the Vertex Buffer and indicate where the Vertex are
      glEnableVertexAttribArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, vertexBufferHandle);
      glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
     
      //Bind the Index Buffer
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferHandle);
      glBindVertexArray(0);
   }

Offline HeroesGraveDev

JGO Kernel


Medals: 269
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #1 - Posted 2014-01-17 03:01:33 »

Double buffering, unless I'm mistaken, is for framebuffers, and it makes sure that the whole window is drawn before displaying it on screen.

LWJGL uses it by default.

Generally the bottleneck with OpenGL is the amount of glXXX commands you're using, so if you can cut more of them out, then you save time. (There are a few commands that are more expensive, but that's the general idea)

Offline Nate

JGO Kernel


Medals: 149
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #2 - Posted 2014-01-17 03:03:44 »

You might see an improvement with multiple buffers if doing many small batches.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline HeroesGraveDev

JGO Kernel


Medals: 269
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #3 - Posted 2014-01-17 03:10:21 »

Or if one set of data remains constant while another changes a lot.

Offline noodleBowl

Senior Newbie





« Reply #4 - Posted 2014-01-17 03:47:49 »

Double buffering, unless I'm mistaken, is for framebuffers, and it makes sure that the whole window is drawn before displaying it on screen.

LWJGL uses it by default.

Generally the bottleneck with OpenGL is the amount of glXXX commands you're using, so if you can cut more of them out, then you save time. (There are a few commands that are more expensive, but that's the general idea)

I think we are talking about 2 different things, I'm talking about the rendering technique where you use one VBO to write data to and then the GPU updates/uses the other VBO.

You might see an improvement with multiple buffers if doing many small batches.

Really? You think that would matter, I would figure that attempting to render 100000 quads every frame where the data changes would surely cause  a performance hit. I'll have to try it

Also I was wondering this, maybe I'm confusing the terms Vertex Buffer and Vertex Buffer Handle. When I use the glGenBuffers() command, this in my mind creates the Vertex Buffer Handle. Where the Vertex Buffer (as I think of it) is the FloatBuffer created. So maybe I'm really supposed to be swapping the Vertex Buffer Handles? Where then I would just have one FloatBuffer that us used for writing

Then when I bind the FloatBuffer and the Vertex Buffer Handle, this takes the data and 'dumps' it on the GPU. Where then the Vertex Buffer Handle is responsible for its association. And then I can just use the same FloatBuffer for my data

Or is that just completely off the wall?
Offline princec

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #5 - Posted 2014-01-17 11:03:44 »

That technique works fine and has the advantage of being easy to implement and follow.

Cas Smiley

Offline davedes
« Reply #6 - Posted 2014-01-17 14:49:11 »

Why bother? It's a lot of extra work for very little gain. Pretty much a premature optimization, unless you've actually benchmarked and found that buffer syncs is causing a problem.

Anyways, you should use mapped buffers for this.
http://www.java-gaming.org/index.php?topic=28209.0

Offline theagentd
« Reply #7 - Posted 2014-01-17 16:08:24 »

Double buffering when using glBufferData() doesn't really do anything. I believe what you're trying to avoid is overwriting vertex data before the GPU is done reading the previous data. However, on all drivers I've tested glBufferData() does this for you. It's up to the driver how this is done, but most drivers seem to either copy the data you submit with glBufferData() to a temporary internal buffer in RAM and then upload it once the GPU is done with the previous data, or doing pretty much the same thing but in VRAM. The GPU could be multiple frames behind the CPU, so there might even be multiple buffers involved, but the driver will always honor the OpenGL specification (e.g. not overwrite data while it's still needed).

Using multiple VBOs is only useful if you're updating the same buffer, in contrast to reallocating (AKA orphaning) your VBO. If you were to allocate your VBO once with glBufferData() and then update the same buffer with glBufferSubData() each frame your double buffering may improve performance, but here too glBufferSubData() may internally buffer the data in RAM similar to how glBufferData() works. The only really useful case for keeping multiple buffers is when mapping buffers glMapBuffer<Range>(). When you map the buffer, OpenGL will have to block until the previous data is no longer in use, alternating between several buffers will prevent the CPU from stalling due while waiting for the GPU to catch up. You can even completely disable OpenGL's built-in synchronization of buffers with glMapBufferRange() to achieve very high performance, but this requires you to either synchronize manually or use enough buffers to guarantee that you never overwrite a buffer that the GPU isn't done with yet. Take a look at Riven's excellent implementation here on how to implement that: http://www.java-gaming.org/topics/opengl-lightning-fast-managed-vbo-mapping/28209/view.html

Myomyomyo.
Offline lhkbob

JGO Knight


Medals: 32



« Reply #8 - Posted 2014-01-18 02:49:38 »

There are other aspects to consider as well.  200,000 calls to Math.random() may be the bottleneck in which case you won't see performance changes from the GPU.  Similarly, you might be fill-rate limited so you won't see performance changes until you reduce screen resolution, overdraw or simplify your fragment shader.

Offline princec

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #9 - Posted 2014-01-18 08:48:43 »

The double buffered VBO technique worked for me about 5 years ago on an integrated chipset Smiley But theagentd is basically right, the driver is already doing this for you.

Cas Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline badlogicgames
« Reply #10 - Posted 2014-01-18 13:30:58 »

Seems to be useless on the desktop these days, but can work miricals on mobile GPUs

http://www.badlogicgames.com - musings on Android and Java game development
Offline noodleBowl

Senior Newbie





« Reply #11 - Posted 2014-01-18 17:34:23 »


** Other part of quote **

Take a look at Riven's excellent implementation here on how to implement that: http://www.java-gaming.org/topics/opengl-lightning-fast-managed-vbo-mapping/28209/view.html

I see, I did not know this, either way I was going to work my way up to the glMapBufferRange. I guess I will just have to jump up to there. I'll have to take a look at that article again and try to implement it.

There are other aspects to consider as well.  200,000 calls to Math.random() may be the bottleneck in which case you won't see performance changes from the GPU.  Similarly, you might be fill-rate limited so you won't see performance changes until you reduce screen resolution, overdraw or simplify your fragment shader.

I don't know if this matters but since you mention this you could be right. I don't think it would effect it that much but I'm not sure.
I doing my tests on a 800 x 600 window. My Fragment Shader is as simple as possible I think, it just returns the color red. Could you explain overdraw I'm unfamiliar with this term in the openGL context.

Also was I confusing my terms for VBOs? Basically should I consider this my VBO
1  
2  
//VBO or just some storage space for Vertex Data
FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(MAX_VERTEX_COUNT);


or is my VBO really this
1  
2  
3  
4  
5  
//My VBO or just a pointer to the VBO and its data
IntBuffer buffers = BufferUtils.createIntBuffer(1);
glGenBuffers(buffers);
     
int vertexBufferHandle = buffers.get(0);

Offline Nate

JGO Kernel


Medals: 149
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #12 - Posted 2014-01-18 18:15:10 »

You might see an improvement with multiple buffers if doing many small batches.

Really?

With many small batches and a single buffer, you submit a buffer to be rendered, then very soon you submit the same buffer. This can stall, since the first batch needs to be flushed before the second batch. If you have a number of buffers and cycle thru them, you can avoid this problem. This exact thing happened with a game of mine on an HTC G1, the first Android phone. Maybe the improvement will be less pronounced with more modern phones. Likely it doesn't matter at all on the desktop.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (38 views)
2014-10-17 03:59:02

Norakomi (28 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (28 views)
2014-10-15 16:18:58

TehJavaDev (53 views)
2014-10-14 00:39:48

TehJavaDev (54 views)
2014-10-14 00:35:47

TehJavaDev (42 views)
2014-10-14 00:32:37

BurntPizza (64 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (78 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!