PDA

View Full Version : Implementing a VBO as a circular buffer?



tomb18
02-07-2017, 11:05 PM
I have a program that streams data from an external source and then plots a 3D height map of that data. Basically I am plotting 2048 X points by 100 Z points about 10 times a second. So a total of 2,000,000 vertices per second. Currently this is done as follows:

Read in 2048 points. Put this into a circular buffer of 2048x100. This buffer is then copied into a VBO linearly and then plotted using glBufferSubData. This all works fine but it seems very inefficient to have to copy the data from the circular buffer to the VBO and then transfer it to the GPU when only the first row contains new data, and all the remaining rows minus 1 are just translated in the Z direction by one row. Can this be done in another way using the VBO as a circular buffer?

Currently, frames are rendered within 16ms but CPU utilization on a core i7 laptop with a NVidia 750m processor is about 15%. If I use the Intel 4500 GPU rendering takes about 280ms(!) per frame.

I should mention that to plot this VBO I use one glDrawElements call using a triangle strip and indices ( the strip changes but not the indices).

Suggestions are appreciated!
Thanks, Tom

john_connor
02-08-2017, 12:38 AM
Currently, frames are rendered within 16ms but CPU utilization on a core i7 laptop with a NVidia 750m processor is about 15%. If I use the Intel 4500 GPU rendering takes about 280ms(!) per frame

16ms means 60 frames / sec, which is usually the monitors refresh rate, that could be due to enabled "vsync"
here is how you can ask opengl to measure the time needed for 1 frame:
https://sites.google.com/site/john87connor/home/tutorial-13-performance



Read in 2048 points. Put this into a circular buffer of 2048x100. This buffer is then copied into a VBO linearly and then plotted using glBufferSubData. This all works fine but it seems very inefficient to have to copy the data from the circular buffer to the VBO and then transfer it to the GPU when only the first row contains new data, and all the remaining rows minus 1 are just translated in the Z direction by one row. Can this be done in another way using the VBO as a circular buffer?

try this:
https://www.khronos.org/opengl/wiki/Buffer_Object#Persistent_mapping
https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming

double buffered VAO:
-- use 2 VAO (vertex array) +2 VBO (vertex buffer) + 2 IBO (element buffer)
-- switch each frame the VAO you want to draw from
-- while drawing with VAO 1, update buffer VBO 2
-- while drawing with VAO 2, update buffer VBO 1
-- you can use the same IBO for both VAOs

beside that:
2048 x 100 x sizeof(vec3) = 2.45MByte, thats not much memory to update i'd assume

Silence
02-08-2017, 01:32 AM
to have to copy the data from the circular buffer to the VBO and then transfer it to the GPU

To copy data to the VBO usually means transfering these data to the GPU. You have your data on your RAM, then you put them into the GPU with a call like glBufferSubData. What did I miss ?


when only the first row contains new data

Then you might want to copy only the relevant (here changed) data. You're not obliged to copy all the buffer each time. This is what glBufferSubData is meant to.


and all the remaining rows minus 1 are just translated in the Z direction by one row

Not really sure what you mean here. If what you mean is that row n data are row n-1 data with a translation, then you might be interested in instancing.

GClements
02-08-2017, 04:15 AM
I should mention that to plot this VBO I use one glDrawElements call using a triangle strip and indices ( the strip changes but not the indices).

A circular buffer requires two draw calls: One for the range from the chronological start of the data to the end of the buffer, one from the start of the buffer to the chronological end of the data.

You only need to copy the modified data each frame, as the unmodified data doesn't change its position in the buffer (that's the point of a circular buffer).