openGL glBufferData usage - qt

I am using glBufferData to save some information for rendering.
glBufferData(GL_ARRAY_BUFFER, vertex_size * sizeof(VertexData), vertices, GL_DYNAMIC_DRAW);
where vertices save data for each vertexs. I changed vertices data later to render a different image. However, it is still showing the original one. I believe changing GL_STATIC_DRAW to GL_DYNAMIC_DRAW should solve the problem, but it failed. What should I do for that?

To update your entire buffer, you should call glBufferData() once again:
glBufferData(GL_ARRAY_BUFFER, vertex_size * sizeof(VertexData), vertices, GL_DYNAMIC_DRAW);
Furthermore, it is possible to update only part of the data using the glBufferSubData() call:
glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
The glBufferSubData() is faster since it will not reallocate the underlying buffer .

Each time you update your array, it needs to call glBindBuffer relative BufferObject handler to active this Array Buffer or Element Buffer. In addition, if your new array is larger than the old Buffer, calling glBufferData is needed, otherwise, it only needs to call glBufferSubData.

Related

OpenCL - Storing a large array in private memory

I have a large array of float called source_array with the size of around 50.000. I am current trying to implement a collections of modifications on the array and evaluate it. Basically in pseudo code:
__kernel void doSomething (__global float *source_array, __global boolean *res. __global int *mod_value) {
// Modify values of source_array with mod_value;
// Evaluate the modified array.
}
So in the process I would need to have a variable to hold modified array, because source_array should be a constant for all work item, if i modify it directly it might interfere with another work item (not sure if I am right here).
The problem is the array is too big for private memory therefore I can't initialize in kernel code. What should I do in this case ?
I considered putting another parameter into the method, serves as place holder for modified array, but again it would intefere with another work items.
Private "memory" on GPUs literally consists of registers, which generally are in short supply. So the __private address space in OpenCL is not suitable for this as I'm sure you've found.
Victor's answer is correct - if you really need temporary memory for each work item, you will need to create a (global) buffer object. If all work items need to independently mutate it, it will need a size of <WORK-ITEMS> * <BYTES-PER-ITEM> and each work-item will need to use its own slice of the buffer. If it's only temporary, you never need to copy it back to host memory.
However, this sounds like an access pattern that will work very inefficiently on GPUs. You will do much better if you decompose your problem differently. For example, you may be able to make whole work-groups coordinate work on some subrange of the array - copy the subrange into local (group-shared) memory, the work is divided between the work items in the group, and the results are written back to global memory, and the next subrange is read to local, etc. Coordinating between work-items in a group is much more efficient than each work item accessing a huge range of global memory We can only help you with this algorithmic approach if you are more specific about the computation you are trying to perform.
Why not to initialize this array in OpenCL host memory buffer. I.e.
const size_t buffer_size = 50000 * sizeof(float);
/* cl_malloc, malloc or new float [50000] or = {0.1f,0.2f,...} */
float *host_array_ptr = (float*)cl_malloc(buffer_size);
/*
put your data into host_array_ptr hear
*/
cl_int err_code;
cl_mem my_array = clCreateBuffer( my_cl_context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, buffer_size, host_array_ptr, &err_code );
Then you can use this cl_mem my_array in OpenCL kernel
Find out more

QOpenGLFramebufferObject toImage efficiency

The toImage() method seems to be very slow in terms of real-time rendering. I render to the frame buffer using OpenGL but I need to then fetch the colour data back effeciently, is there a better way to do this than with a Qt fbo's toImage method? I do want to return a QImage.
Note: Using the toImage() function I get ~ 10fps when my target is at least 30fps. The buffer needs to hold RGBA data on a texture that is 1200*674 (so 1200*674*4 bytes are fetched)

How to free resources of QString when use it inside std::vector

I have a structure "rs" for every record of my dataset.
All records are in a vector "r".
My record count is in “rc”.
....
struct rs{
uint ip_i;//index
QString ip_addr;//ip address
};
std::vector <rs> r;//rows ordered by key
int rc;//row count
....
I would like to control this memory usage.
That's why I don't want to use r.insert and r.erase.
When I need to insert a record, I will:
Increase size of r by r.resize(..);r.shrink_to_fit() (if needed).
Shift elements of r to the right (if needed) by std::rotate.
Put new values: r[i].ip_i=...;r[i].ip_addr=...
When I need to delete a record, I will:
Shift elements of r to the left (if needed) by std::rotate.
For example, std::rotate(r.begin()+i,r.begin()+i+1,r.begin()+rc);.
Free resources of r[rc].ip_addr.
How to free resouces of QString r[rc].ip_addr?
I've tried to do r[i].ip_addr.~QString() and catched an runtime error.
Make r.resize() (if needed).
I don't want to loose memory because of Qstring copies stayed after rows deleting.
How can I control them?
Thanks.
QString handles all memory control for you. Just treat it as a regular object and you'll be fine. std::vector is OO-aware, so it will call destructors when freeing elements.
The only thing you should not do is use low-level memory manipulation routines like memcpy or memset. std::vector operations are safe.
If you really want to free a string for a record that is within [0..size-1] range (that is, you do not actually decrease size with resize() after moving elements), then calling r[i].ip_addr.clear() would suffice. Or better yet, introduce the clear() method in your structure that will call ip_addr.clear() (in case you add more fields that need to be cleared). But you can only call it on a valid record, of course, not one beyond your actual vector size (no matter what the underlying capacity is, it's just an implementation detail).
On a side note, it probably makes sense to use QList instead since you're using Qt anyway, unless you have specific reasons to use std::vector. As far as memory control goes, QList offers reserve method which allows you reserve exactly as many elements as you need. Inserting then would look like
list.reserve(list.size() + 1);
list.insert(i, r);

Drawing with OpenGL in OOP

I try to code an OpenGL project with Qt (v5.1.1) on OS X 10.9, in the manner of the modern pipeline implementation. The program is supposed to be a multi-agent based system or particle system. However I lack in understanding how to draw something out of another class.
In cinder there were some simple drawThisAndThat() command you could call. I read the 6th edition of the 'OpenGL Superbible'. From this and several tutorials all examples seem to cover just programs where all modifications are made out of the class that initializes OpenGL.
I would like to instantiate some objects moving on a grid and draw pixel to display their position. I know I have to call void glVertexAttrib4fv(GLuint index, const GLfloat * vi); but this is not sufficient.
Do I need to call glEnableVertexAttribArray(1); and glDrawArrays(GL_POINTS, 0, 3); as well and what else?
Am I right, to instantiate the class controlling the particles after instantiating OpenGL and bevor the main loop?
How do I manage that the particle draws himself while erasing the position he was drawn bevor?
The program is based on this code.
To answer your questions completely I would have to write a wall of text, I will try to only point out the most important aspects. I hope this will help you enough to use your knowledge and probably further reading to get it to work.
all modifications are made out of the class that initializes OpenGL
You can encapsulate update(time) and draw() methods for your Objects which you then call in your main loop.
Do I need to call glEnableVertexAttribArray(1); and glDrawArrays(GL_POINTS, 0, 3); as well and what else?
I would put all particles into one vertex array to avoid rebinding of different vertex arrays after each particle. Then you would have to use glBindVertexArray(vaid); and glDrawArrays(GL_POINTS, 0, vertexCount); in your draw() call. Be careful with vertexCount, it's not the number of floats (as your question implies) but the number of vertices, which should be 1 in your example or the number of particles in my suggested approach (If I'm correct in assuming that the 3 stands for "x, y, and z of my vertex").
And since you only have particles glDrawElements(...); would probably already fit your needs.
Am I right, to instantiate the class controlling the particles after instantiating OpenGL and bevor the main loop?
Probably your instantiation order is correct that way. You definitely should do all instantiations before calling the main loop in your case.
How do I manage that the particle draws himself while erasing the position he was drawn bevor?
If understand your last question correctly: Simply by changing the elements in your buffer objects (glBufferData(...);). Since you will clear the screen and swap buffers after each loop this will make them move. Just update their position with an update(time) call, e.g. pos = pos + dir * time;, put the new positions into a buffer and push that buffer with glBufferData(...) to the vertex array. Remember to bind the vertex array before pushing the buffer.
Some additional things I'd like to point out.
glEnableVertexAttribArray(1); is to enable a vertex attribute in your shader program to be able to pass data to that attribute. You should create a shader program
id = glCreateProgram()
// ... create and attach shaders here
// then bind attribute locations, e.g. positionMC
glBindAttribLocation(id, 0, "positionMC");
glLinkProgram(id);
And after initializing the vertex array with glGenVertexArrays(); you should enable all attributes your vertex array needs in your shader program. In this example positionMC would be at location 0, so you would call something like
glUseProgram(pid);
glBindVertexArray(vaid);
glEnableVertexAttribArray(1);
glVertexAttribPointer(...);
This has only to be done once, since OpenGL stores the state for every particular vertex array. By rebinding a vertex array you will restore that state.
In the main loop all you have to do now is calling your update and draw methods, e.g.:
handleInputs();
update(deltaTime);
glClear(...);
draw();
swapBuffers();

Copying pointers to pointers 'contents' in C

I'm having some trouble copying pointers' contents. I'm simply trying this:
char* vigia1;
char* vigia2;
And..
char* aux = (char*) malloc (strlen (vigia1)+1);
aux=vigia1;
vigia1=vigia2;
vigia2=aux;
free (aux);
vigia1, vigia2 are pointers to a char pointer. They both have a malloc greater than their maximum possible size, that's OK.
Since I'm trying to make an order for a list, I need to make this change to order the nodes' content. But I'm getting confused: after the free(aux) , vigia2 doesn't have any value. I think I must be pointing vigia2 to the memory region where aux is, region that 'disappear' after the free. So what should I do?
Thanks!
Pointers, pointers, bad with them, worse without them
A pointer is a number that stores where in memory sth is stored, with that in mind, let's delve into what you've done there:
char* aux = (char*) malloc (strlen (vigia1)+1);
Good, you've created space somewhere in a part of the memory called heap, and stored the address of the newly created memory space at aux.
aux=vigia1;
Ops, now you've overwritten the address of the memory space you've "created" with the number stored at vigia1, that happens to be an address to another memory space.
vigia1=vigia2;
Now you're assinging to vigia1 the value of vigia2, another address of some memory space out there.
vigia2=aux;
And, by the end of it, you make vigia2 point to the memory region previously pointed by vigia1.
free (aux);
Now, you're freeing the memory pointed by aux. Wait a second, on the line above this one you've just made vigia2 point to this same address. No wonder it holds nothing useful :)
Trying to help you with what you want to do:
So long you don't have any constraint that obliges you to mantain your list nodes ordered in memory, you don't need to copy the content of the node, just make the pointer of the first node point to the memory region of the second node.
A perfect swap would be:
char *aux; // you'll need an aux to make the swap, the normal stuff
aux = vigia1; // now aux points to the same address as vigia1
vigia1 = vigia2; // vigia1 now points to the contents of vigia2
vigia2 = aux; // and now vigia2 points to the content pointed previously by vigia1
/* and tada! the swap is done :D */
Assigning one pointer to another simply copies the value of one pointer to another, i.e., an address. It doesn't copy what the pointer refers to into another location at a different address. So yes, you can have N pointers all pointing to the same chunk of memory, but once free() is called one of them they are all invalid.
So that means that this:
char* aux = (char*) malloc (strlen (vigia1)+1);
aux=vigia1;
Is a memory leak. You malloc'd some memory for aux and then immediately discarded the address. There is no way to get it back, no way to free() it any longer.
What you are making is just pointer assignments. Malloc'ed memory is just getting wasted causing a leak.
aux=vigia1; // Makes aux point to the location where vigia1 is pointing to
// Doesn't copy the contents of vigia1 to malloc'ed memory for aux
You need to make deep copy using strcpy.
strcpy(aux, vigia1);
Hope this gives you the hint.

Resources