Cleaning deleted Items - opengl

In my application user creates and deletes geometry at runtime.
i store vertex data within memory on the graphics card as managed by a vertex buffer object named VBO.
the user deletes the object but the application is still running.
void CleanUp()
{
if (!this->isInited)
{
return;
}
if (this->m_VAO)
glDeleteVertexArrays(1, &this->m_VAO);
if (this->m_VBO)
glDeleteBuffers(1, &this->m_VBO);
}
Will this release the allocated memory from the graphics card ?

Related

Opengl only binds buffers from function that created them

I'm trying to write a very barebones game engine to learn how they work internally and I've gotten to the point where I have a "client" app sending work to the engine. This works so far but the problem I am having is that my test triangle only renders when I bind the buffer from the "main" function (or wherever the buffers were created)
This is even the case when the buffers are abstracted and have the same function with the same member values (validated using clion's debugger) but they still have to be bound in the function that created them
for example I have this code to create the buffers and set their data
...
Venlette::Graphics::Buffer vertexBuffer;
Venlette::Graphics::Buffer indexBuffer;
vertexBuffer.setTarget(GL_ARRAY_BUFFER);
indexBuffer.setTarget(GL_ELEMENT_ARRAY_BUFFER);
vertexBuffer.setData(vertices, sizeof(vertices));
indexBuffer.setData(indices, sizeof(indices));
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, nullptr);
...
where vertices is a c array of 6 floats and indices being 3 unsigned int's
the buffers are then passed to a "context" to be stored for rendering later using the following code
...
context.addBuffer(vertexBuffer);
context.addBuffer(indexBuffer);
context.setNumVertices(3);
context.setNumIndices(3);
context.
...
which calls: addBuffer
Task& task = m_tasks.back();
task.buffers.push_back(std::move(buffer));
this again, works. The buffers are stored correctly, the buffers still exist when the code reaches here and nothing is wrong.
then it gets to the drawing part where the buffers are: bound, drawn, then unbound, as shown
...
for (auto& buffer : task.buffers) {
buffer.upload();
buffer.bind();
}
glDrawElements(GL_TRIANGLES, task.numIndices, GL_UNSIGNED_INT, nullptr);
for (auto& buffer : task.buffers) {
buffer.unbind();
}
...
bind and unbind being these functions
void Buffer::bind() const noexcept {
if (m_id == -1) return;
glBindBuffer(m_target, m_id);
spdlog::info("bind() -{}-{}-", m_id, m_target);
}
void Buffer::unbind() const noexcept {
if (m_id == -1) return;
glBindBuffer(m_target, 0);
spdlog::info("unbind() -{}-{}-", m_id, m_target);
}
but this is where nothing works. If I call buffer.bind() from the "doWork" function where the buffers are drawn, nothing renders, but if I call buffer.bind() from the main function I get a white triangle in the middle of the screen
Even when I bound then unbound the buffers from the main buffer encase that was the issue it still doesn't draw. Only when the buffers are bound and remain bound from the main function, that is draws
a pastebin of the full code (no headers)
pastebin
Does anyone know why this happens, even if you don't know how to fix it. is it something to do with buffer lifetime, or with moving the buffer into the vector?
it is just buffer.bind() that doesn't work, uploading data works from the context, just not binding it
You seem to not bind the vertex buffer to the GL_ARRAY_BUFFER buffer binding point before calling glVertexAttribPointer.
glVertexAttribPointer uses the buffer bound to GL_ARRAY_BUFFER in order to know which buffer is the vertex attribute source for that generic vertex attribute.
So, you should bind the vertexBuffer before calling glVertexAttribPointer.

OpenCV Mat to OpenGL - error on glBindTexture()

I'm trying to convert an OpenCV cv::Mat image to an OpenGL texture (I need a GLuint that points to the texture). Here's the code I have so far, pieced together from numerous Google searches:
void otherFunction(cv::Mat tex_img) // tex_img is a loaded image
{
GLuint* texID;
cvMatToGlTex(tex_img, texID);
// Operations on the texture here
}
void cvMatToGlTex(cv::Mat tex_img, GLuint* texID)
{
glGenTextures(1, texID);
// Crashes on the next line:
glBindTexture(GL_TEXTURE_2D, *texID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_img.cols, tex_img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, tex_img.ptr());
return;
}
The crash happens when calling glBindTextures.
I tried a try-catch for all exceptions with catch (const std::exception& ex) and catch (...), but it didn't seem to throw anything, just crash my program.
I apologize if I'm doing anything blatantly wrong, this has been my first experience with OpenGL, and it's still early days for me with C++. I've been stuck on this since yesterday. Do I have a fundamental misunderstanding of OpenGL textures? I'm open to a major reworking of the code if necessary. I'm running Ubuntu 16.04 if that changes anything.
OK, here's what's happening:
void otherFunction(cv::Mat tex_img)
{
GLuint* texID; // You've created a pointer but not initialised it. It could be pointing
// to anywhere in memory.
cvMatToGlTex(tex_img, texID); // You pass in the value of the GLuint*
}
void cvMatToGlTex(cv::Mat tex_img, GLuint* texID)
{
glGenTextures(1, texID); // OpenGL will dereference the pointer and write the
// value of the new texture ID here. The pointer value you passed in is
// indeterminate because you didn't assign it to anything.
// Dereferencing a pointer pointing to memory that you don't own is
// undefined behaviour. The reason it's not crashing here is because I'll
// bet your compiler initialised the pointer value to null, and
// glGenTextures() checks if it's null before writing to it.
glBindTexture(GL_TEXTURE_2D, *texID); // Here you dereference an invalid pointer yourself.
// It has a random value, probably null, and that's
// why you get a crash
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_img.cols, tex_img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, tex_img.ptr());
return;
}
One way to fix this would be to allocate the pointer to a GLuint like:
GLuint* texID = new GLuint; // And pass it in
That will work for starters, but you should be careful about how you go about this. Anything allocated with new will have to be deleted with a call to delete or you'll leak memory. Smart pointers delete the object automatically once it goes out of scope.
You could also do this:
GLuint texID;
cvMatToGlTex(tex_img, &texID);
Remember though that the lifetime of GLuint texID is only within that function you declared it in, because it's a local variable. I'm not sure what better way to do this because I don't know what your program looks like, but at least that should make the crash go away.

What is the proper way of using multiple context for multithreading in OpenGL?

I am trying to parallelize a program I have made in OpenGL. I have fully tested the single threaded version of my code and it works. I ran it with valgrind and things were fine, no errors and no memory leaks, and the code behaved exactly as expected in all tests I managed to do.
In the single threaded version, I am sending a bunch of cubes to be rendered. I do this by creating the cubes in a data structure called "world", sending the OpenGL information to another structure called "Renderer" by appending them to a stack, and then finally I iterate through the queue and render every object.
Since the single threaded version works I think my issue is that I am not using the multiple OpenGL contexts properly.
These are the 3 functions that pipeline my entire process:
The main function, which initializes the global structures and threads.
int main(int argc, char **argv)
{
//Init OpenGL
GLFWwindow* window = create_context();
Rendering_Handler = new Renderer();
int width, height;
glfwGetWindowSize(window, &width, &height);
Rendering_Handler->set_camera(new Camera(mat3(1),
vec3(5*CHUNK_DIMS,5*CHUNK_DIMS,2*CHUNK_DIMS), width, height));
thread world_thread(world_handling, window);
//Render loop
render_loop(window);
//cleanup
world_thread.join();
end_rendering(window);
}
The world handling, which should run as it's own thread:
void world_handling(GLFWwindow* window)
{
GLFWwindow* inv_window = create_inv_context(window);
glfwMakeContextCurrent(inv_window);
World c = World();
//TODO: this is temprorary, implement this correctly
loadTexture(Rendering_Handler->current_program, *(Cube::textures[0]));
while (!glfwWindowShouldClose(window))
{
c.center_frame(ivec3(Rendering_Handler->cam->getPosition()));
c.send_render_data(Rendering_Handler);
openGLerror();
}
}
And the render loop, which runs in the main thread:
void render_loop(GLFWwindow* window)
{
//Set default OpenGL values for rendering
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glPointSize(10.f);
//World c = World();
//loadTexture(Rendering_Handler->current_program, *(Cube::textures[0]));
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
Rendering_Handler->update(window);
//c.center_frame(ivec3(Rendering_Handler->cam->getPosition()));
//c.send_render_data(Rendering_Handler);
Rendering_Handler->render();
openGLerror();
}
}
Notice the comments on the third function, if I uncomment those out and then comment out the multi-threading statemnts on the main function (i.e single thread my program) everything works.
I don't think this is caused by a race condition, because the queue, where the OpenGL info is being put before rendering, is always locked before being used (i.e whenever a thread needs to read or write to the queue, the thread locks a mutex, reads or writes to the queue, then unlocks the mutex).
Does anybody have an intuition on what I could be doing wrong? Is it the OpenGL context?

How does glDeleteTextures and glDeleteBuffers work?

Basically, in my code I hook the glDeleteTextures and glBufferData functions. I store a list of textures and a list of buffers. The buffer list holds checksums and pointers to the buffer. The below code intercepts the data before it reaches the graphics card.
Hook_glDeleteTextures(GLsizei n, const GLuint* textures)
{
for (int I = 0; I < n; ++I)
{
if (ListOfTextures[I] == textures[I]) //??? Not sure if correct..
{
//Erase them from list of textures..
}
}
(*original_glDeleteTextures)(n, textures);
}
And I do the same thing for my buffers. I save the buffers and textures to a list like below:
void Hook_glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
{
Buffer.size = size;
Buffer.target = target;
Buffer.data = data;
Buffer.usage = usage;
ListOfBuffers.push_back(Buffer);
(*original_glBufferData(target, size, data, usage);
}
Now I need to delete whenever the client deletes. How can I do this? I used a debugger and it seems to know exactly which textures and buffers are being deleted.
Am I doing it wrong? Should I be iterating the pointers passed and deleting the textures?
You do realize, that you should to it other way round: Have a list of texture-info objects and when you delete one of them, call OpenGL to delete the textures. BTW: OpenGL calls don't go to the graphics card, they go to the driver and textures may be stored not on GPU memory at all but be swapped out to system memory.
Am I doing it wrong? Should I be iterating the pointers passed and deleting the textures?
Yes. You should not intercept OpenGL calls to trigger data management in your program. For one, you'd have to track the active OpenGL context as well. But more importantly, it's your program that does the OpenGL calls in the first place. And unless your program/compiler/CPU is schizophrenic it should be easier to track the data first and manage OpenGL objects according to this. Also the usual approach is to keep texture image data in a cache, but delete OpenGL textures of those images, if you don't need them right now, but may need them in the near future.
Your approach is basically inside-out, you're putting the cart before the horse.

OpenGL 2d texture not working

I'm working on a 2D game project, and I wanted to wrap the openGl texture in a simple class. The texture is read from a 128x128px .png (with alpha channel) using libpng. Since the amount of code is pretty large, I'm using pastebin.
The code files:
Texture class: http://pastebin.com/gbGMEF2Z
PngReader class: http://pastebin.com/h6uP5Uc8 (seems to work okay, so I removed the description).
OpenGl code: http://pastebin.com/PVhwnDif
To avoid wasting your time, I will explain the code a little bit:
Texture class: a wrapper for an OpenGL texture. The loadData function sets up the texture in gl (this is the function I suspect that doesn't work).
OpenGl code: the debugSetTexture function puts a texture in the temp variable which is used in the graphicsDraw() function. This is because it is not in the same source file as main(). In the graphicsMainLoop() function, I use the Fork() function which in fact calls fork(), and stores the pid of the spawned process.
From main(), this is what I do:
Strategy::IO::PngReader reader ("/cygdrive/c/Users/Tibi/Desktop/128x128.png");
reader.read();
grahpicsInit2D(&argc, argv);
debugSetTexture(reader.generateTexture());
graphicsMainLoop();
reader.close();
I tried an application called gDEBugger, and in the texture viewer, there was a texture generated, but size was 0x0px.
I suspect that the problem happens when the texture is loaded using Texture::loadTexture().
You need to check GL error codes after GL calls.
For example add this method to your class:
GLuint Texture::checkError(const char *context)
{
GLuint err = glGetError();
if (err > 0 ) {
std::cout << "0x" << std::hex << err << " glGetError() in " << context
<< std::endl;
}
return err;
}
then call it like so:
glBindTexture(GL_TEXTURE_2D, handle);
checkError("glBindTexture");
Assuming it succeeds in loading the png file, suppose your program fails in glBindTexture? (strong hint)
You did call your Error function for your file handling, but does your program halt then or chug on?
Here's a serious issue: Texture PngReader::generateTexture() returns Texture by value. This will cause your Texture object to be copied on return (handle and all) and then ~Texture() to be called, destroying the stack-based copy. So your program will call glDeleteTextures a couple times!
If you want to return it by value, you could wrap it in a shared_ptr<> which does reference counting. This would cause the destructor to be called only once:
#include <tr1/memory>
typedef std::tr1::shared_ptr<Texture> TexturePtr;
Use TexturePtr as your return type. Initialize it in generateTexture() like this:
TexturePtr t(new Texture);
then change all the method access to go through -> instead of .