Calling glBufferSubData several times per frame - c++

I´m doing a rendering where i call glBufferSubData several times per frame.
Here is how i do it in my code :
glBindBuffer(GL_ARRAY_BUFFER,_vboID);
//Buffering the data
glBufferData(GL_ARRAY_BUFFER,_vboDATA[type].size()*sizeof(vboData),nullptr,GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER,0,_vboDATA[type].size()*sizeof(vboData),_vboDATA[type].data());
glBindBuffer(GL_ARRAY_BUFFER,0);
I´m asking because i have a different types of elements and each has it´s own vector to represent vbo data(im using 1 VBO(for colors,UVs,positions - and 1 VAO) in my program and i´m doing the rendering like :
1.) Load vector of element 1 to buffer
2.) Render element 1
3.) Load vector of element 2 to buffer
4.) Render element 2
...
Is it a proper way to do it like that?

The proper way depends on your usage scenario. When the data is mostly static, then the best way is to upload the data once to the GPU. This can either be done by creating a VBO for each object, or by patching all objects together into a single VBO.
In case the data is fully dynamic (and changing in every frame), then you will have to upload the data anyway, so using just one buffer could be fine. But you should still try to get along with just uploading the data (glBufferSubData) and avoid allocating new memory (glBufferData) all over. You can, for example, choose an initial size of the buffer that is large enough to fit all your data. Another option would be to use persistently mapped buffer.

Related

How to update vertex buffer data frequently in DirectX 11?

I am trying to update my vertex buffer data with the map function in dx. Though it does update the data once, but if i iterate over it the model disappears. i am actually trying to manipulate vertices in real-time by user input and to do so i have to update the vertex buffer every frame while the vertex is selected.
Perhaps this happens because the Map function disables GPU access to the vertices until the Unmap function is called. So if the access is blocked every frame, it kind of makes sense for it to not be able render the mesh. However when i update the vertex every frame and then stop after sometime, theatrically the mesh should show up again, but it doesn't.
i know that the proper way to update data every frame is to use constant buffers, but manipulating vertices with constant buffers might not be a good idea. and i don't think that there is any other way to update the vertex data. i expect dynamic vertex buffers to be able to handle being updated every frame.
D3D11_MAPPED_SUBRESOURCE mappedResource;
ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE));
// Disable GPU access to the vertex buffer data.
pRenderer->GetDeviceContext()->Map(pVBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
// Update the vertex buffer here.
memcpy((Vertex*)mappedResource.pData + index, pData, sizeof(Vertex));
// Reenable GPU access to the vertex buffer data.
pRenderer->GetDeviceContext()->Unmap(pVBuffer, 0);
As this has been already answered the key issue that you are using Discard (which means you won't be able to retrieve the contents from the GPU), I thought I would add a little in terms of options.
The question I have is whether you require performance or the convenience of having the data in one location?
There are a few configurations you can try.
Set up your Buffer to have both CPU Read and Write Access. This though mean you will be pushing and pulling your buffer up and down the bus. In the end, it also causes performance issues on the GPU such as blocking etc (waiting for the data to be moved back onto the GPU). I personally don't use this in my editor.
If memory is not the issue, set up a copy of your buffer on CPU side, each frame map with Discard and block copy the data across. This is performant, but also memory intensive. You obviously have to manage the data partioning and indexing into this space. I don't use this, but I toyed with it, too much effort!
You bite the bullet, you map to the buffer as per 2, and write each vertex object into the mapped buffer. I do this, and unless the buffer is freaking huge, I havent had issue with it in my own editor.
Use the Computer shader to update the buffer, create a resource view and access view and pass the updates via a constant buffer. Bit of a Sledgehammer to crack a wallnut. And still doesn't stop the fact you may need pull the data back off the GPU ala as per item 1.
There are some variations on managing the buffer, such as interleaving you can play with also (2 copies, one on GPU while the other is being written to) which you can try also. There are some rather ornate mechanisms such as building the content of the buffer in another thread and then flagging the update.
At the end of the day, DX 11 doesn't offer the ability (someone might know better) to edit the data in GPU memory directly, there is alot shifting between CPU and GPU.
Good luck on which ever technique you choose.
Mapping buffer with D3D11_MAP_WRITE_DISCARD flag will cause entire buffer content to become invalid. You can not use it to update just a single vertex. Keep buffer on the CPU side instead and then update entire buffer on GPU side once per frame.
If you develop for UWP - use of map/unmap may result in sync problems. ID3D11DeviceContext methods are not thread safe: https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-render-multi-thread-intro.
If you update buffer from one thread and render from another - you may get different errors. In this case you must use some synchronization mechanism, such as critical sections. Example is here https://developernote.com/2015/11/synchronization-mechanism-in-directx-11-and-xaml-winrt-application/

Correct storage allocation for textures in GL_TEXTURE_2D_ARRAY

Assume I have GL_TEXTURE_2D_ARRAY including 6 textures I'm loading it with:
vector<string>::iterator vsit;
for(vsit=filenameTable.begin();vsit!=filenameTable.end();++vsit)
{
string filename = *vsit;
BMPData* bmpData = LoadTextureBMPData_custom(filename);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY,0,0,0,i++,bmpData->width,bmpData->height,1,GL_BGR,GL_UNSIGNED_BYTE,(GLvoid*)&(bmpData->data[0]));
}
Before this code I have to allocate storage for every texture, if I have good understand
I can do this with glTexImage3D() or glTexStorage3D(), for example:
glTexImage3D(GL_TEXTURE_2D_ARRAY,0,GL_RGB,1024,1024,filenameTable.size(),0,GL_BGR,GL_UNSIGNED_BYTE,NULL);
or
glTexStorage3D(GL_TEXTURE_2D_ARRAY,0,GL_RGB,1024,1024,filenameTable.size());
================================================================================
But when I allocate size for every texture in table I have only one pair of parameters
for [width,height] of texture. What if I want every texture image to have another dimmensions? Is there any solution for this problem without scaling every texture to one size in graphic editor?
Another problem is fact that glTexStorage3D() I'm presenting on third code snipper causing crash of my program. Information about glTexStorage3D() I found there:
http://www.opengl.org/wiki/Array_Texture
All images in an array texture have the same size. Just like if you make a C array of some struct, each struct must be of the same type (and therefore the same size).
Well, if you do not care about wasting memory, you can use the biggest image (separate for each dimesnion) to define the size of the TA. You can load each image separately into a layer using glTexSubImage3D. You will have to modify the texcoords when accesin the textures, though, so your shader needs to know the size of each image in the array it needs to access. You should also be aware that the builtin wrap functionality cannot be used and has to be emulated in the shader (if needed).

opengl - rendering design (beginner)

I have a simulation program where I want to render about 500 - 1000 objects (rather small, max 50 triangles) in an animation (let's say 500 timesteps) or interactively (altering one object means recalculating all other objects in the worst case).
What would be the best approach for such a rendreing task?
I was thinking of VBOs and using glBufferSubData to update the objects for each timestep. Or is there some other method?
Also, as there are about 20 types of objects should I use 20 different VBOs so I can set up the attributes accordingly?
If you're doing keyframe animation (one set of vertices per frame), then either upload them all as separate VBOs and change which one you bind, or upload them all in a single VBO and change the attributes. I doubt that there would be much of a performance difference between these two solutions.
I would avoid glBufferSubData, since OpenGL should be able to manage all your memory for you. If this were a significantly larger set of data, I would suggest this method as you could stream the vertices you needed from disk to avoid having it all in memory at once, but with a small set of data this isn't an issue.
If you're doing bone-based animation, the glBufferSubData method is basically the only way to do it if you're skinning on the CPU. A vertex shader that does skinning (on the GPU) will perform much better than CPU skinning, just store your frames in a mat3x4 uniform.
For such a small number of objects, you probably should select the very easiest way to do it and optimize only if you really have to...
And by easy, I mean conceptually easiest for you.
You can use a single VBO object with just different offsets into it if you like, there's no need to use several.

OpenGL. Updating vertex buffer with glBufferData

I'm using OpenGL to implement some kind of batched drawing. For this I create a vertex buffer to store data.
Note: this buffer generally will update on each frame, but will never decrease size (but still can increase).
My question is: is it technically correct to use glBufferData (with streaming write-only mode) for updating it (instead of e.g. glMapBuffer)? I suppose there's no need to map it, since full data is updated, so I just send a full pack at once. And if the current buffer size is less, than I'm sending, it will automatically increase, won't it? I'm just now sure about the way it really works (maybe it will recreate buffer on each call, no?).
It would be better to have buffer with fixed size and do not recreate it every frame.
You can achieve this by:
creating buffer with max size, for instance space for 1000 verts
update only the beginning of the buffer with new data. So if you changed data for 500 verts then fill ony first half of the buffer using glMapBuffer
change count of drawn vertices when drawing. You can, for instance, use only some range of verts (eg. from 200 to 500) from the whole 1000 verts buffer. Use glDrawArrays(mode, first, count)
ideas from comments:
glMapBufferRange and glBufferSubData could also help
also consider double buffering of buffers
link: http://hacksoflife.blogspot.com/2010/02/double-buffering-vbos.html
hope that helps
In addition to what fen and datenwolf said, see Chapter 22 of OpenGL Insights; in particular, it includes timings for a variety of hardware & techniques.

what is the best way of managing and updating VBOs for a high throughput opengl data monitor visualizer?

I'm trying to implement something like a data visualizer similar to the following two screenshots (gnome-system-monitor):
As you can see this is a simple line plot of some network traffic, which gets updated every second. But instead of updating the plot once a second, I would like to plot 'realtime' data every 10ms or so. Because I will end up plotting a lot of data points, I decided to use vertex buffer objects (VBOs) so that data only needs to be uploaded once to the GPU.
But even using VBOs, performance can vary a lot, and therefore I was wondering what the best approach for implementing this is. So far I came up with the following scenarios:
split graph up into many segments, so that each segment is mapped to a single VBO. After receiving some new data, I will delete the first VOB (the one that will be moved out of the graph to the left), create a new VBO and upload the new data. Then I will shift the 'camera' with glTranslatef and finally re-render the scene
same as before, but instead of deleting a VBO and creating a new one, I will bind the old one and upload new data into it
since going through a large list of VBOs and rendering the contents takes a very long (many gl* calls), I was also considering the following two approaches:
create one VBO for all data points in the graph. Once we get new data, I get access to the data on the GPU using glMapBuffer. I will then rotate the data so that the first few points are at the end. I would then overwrite those points at the end of the new incoming data
create for example 5 VBOs: one which holds data for majority of the screen. And four remaining once which hold data for the last four packages of incoming data. This way I could always just rotate through the 4 last VBOs and update the last one with new data. But I would also have to rotate the data in the big VBO.
Are there maybe better ways of implementing what I plan to do? How can I minimize the amount of gl* calls so that I get something like 100FPs? Is that even realistic (with let's say 300000 points)?
EDIT:
I understand that I can't really render 300000 data points. However, this is not my question. My question is really how to update this much data most efficiently. With approach one and two I get something like 10FPS which is an extremely low number.
split graph up into many segments, so that each segment is mapped to a single VBO. After receiving some new data, I will delete the first VOB (the one that will be moved out of the graph to the left), create a new VBO and upload the new data. Then I will shift the 'camera' with glTranslatef and finally re-render the scene
No, keep the data in one VBO, but don't try do draw the whole thing at a time. You can perfectly well draw only subsets of data. Also VBO recreation is a costly operation. Just update it.
same as before, but instead of deleting a VBO and creating a new one, I will bind the old one and upload new data into it
Better, but make sure to use only glBufferSubData and only update changed data points, not the whole thing.
create one VBO for all data points in the graph. Once we get new data, I get access to the data on the GPU using glMapBuffer. I will then rotate the data so that the first few points are at the end. I would then overwrite those points at the end of the new incoming data
Why so complicated? Just offset the base index into the VBO and draw from there.
create for example 5 VBOs: one which holds data for majority of the screen. And four remaining once which hold data for the last four packages of incoming data. This way I could always just rotate through the 4 last VBOs and update the last one with new data. But I would also have to rotate the data in the big VBO.
You can do this with a single VBO perfectly well. Just try to see the VBO as some bunch of memory you use only slices of.
Your screen probably has about 2000 pixels horizontally. So your plot will only have at most 2000 distinguishable data points on screen at any given time. That's not a huge amount of data. Have you tried the naive approach of just transferring it all with every frame, and determined that that doesn't perform well enough, before trying to be clever about complex management of VBOs?