Hello everyone,
I’m stuck on a segfault since few days, I tried many things to find and debug the program, it was crashing randomly but I finally found what case makes segfault.
It’s a basic 2d application who draw only triangles, I have two shader, one for basic polygones and another one for text.
I have one draw call for each of those two category, to be able to do only one draw call I made a c++ class that handle an opengl buffer with a preallocated size. A ManagedBuffer is able to increase the size of its buffer, it basically double the size (like in std::vector)
The segfault happens when a certain amount of items is reached. More specifically, it happens when the triangles buffer increased its size 3 times, and the text buffer 2 times. I must precise that the segfault happens only if the text buffer increased its size.
From this moment, the next draw call for triangles will crash.
BUT, if I comment the texts’s draw call, it will not crash ! The same if I comment triangle’s draw call.
After some tries, I figured out that one line in my text shader lead in segfault.
#version 110
// 0b10000000000000000000000000000000 in hexa :
#define ALL_VIEWS_VISIBILITY_FLAG 0x80000000
// because literral binary is not supported in GLSL 110
// view_id and flags are supposed to be uint view_id and uvec2 flags. But is not
supported by glsl 110
uniform mat3 camera;
uniform vec2 viewport;
uniform int view_id;
attribute vec4 vertex;
attribute vec4 color;
attribute vec2 char_position;
attribute vec2 flags;
varying vec2 textureCoordFrag;
varying vec4 colorFrag;
// Tricks to get a bit from a float number. As OpenGL 2.0 does not support bitwise operation..
float getBit(float num, int position) {
bool tmp = fract(floor(num / pow(2., float(position))) / 2.) != 0.;
// We can't return a boot in GLSL
return tmp ? 1. : 0.;
}
void main() {
// Get the visibility of this character. 22 is the MSB.
// MSB and the bit associed to the view must be to 1 to draw the character.
// This line could be written with if statement, but it's inefficient on GPU.
float visibility = getBit(flags.x, 22) * getBit(flags.x, 22 - view_id);
// If visibility is 0, v will be equal to (0,0)
// all vertex of the glyph will be equal to (0,0) and the drawing will be ignored.
vec2 v = visibility * ((camera * vec3(char_position.xy, 1)).xy + vertex.xy / viewport * 22.5 * 2.);
v.y *= -1.;
// z component as close as possible to always have text over other items
gl_Position = vec4(v, 0, 1);
textureCoordFrag = vertex.zw;
colorFrag = color; <---- THIS LINE
}
If I comment out the copy of the color attribute, I don’t segfault anymore. For example :
colorFrag = vec4(vertex.xy, 1, 1);
works perfectly.
I checked my buffers to see if I ask OpenGL to draw more items than the size of the buffers, but It seems to be correct.
Also, the SAME program works perfectly on another machine.
This is how I draw texts
mProgram->bind();
buffer.bind();
mProgram->setAttributeBuffer("vertex", GL_FLOAT, 0, 4, sizeof(GLfloat) * 12);
mProgram->enableAttributeArray("vertex");
mProgram->setAttributeBuffer("color", GL_FLOAT, sizeof(GLfloat) * 4, 4, sizeof(GLfloat) * 12);
mProgram->enableAttributeArray("color");
mProgram->setAttributeBuffer("char_position", GL_FLOAT, sizeof(GLfloat) * 8, 2, sizeof(GLfloat) * 12);
mProgram->enableAttributeArray("char_position");
mProgram->setAttributeBuffer("flags", GL_FLOAT, sizeof(GLfloat) * 10, 2, sizeof(GLfloat) * 12);
mProgram->enableAttributeArray("flags");
glBindTexture(GL_TEXTURE_2D, font.getTexture());
mProgram->setUniformValue("tex", 0);
auto mat = camera.getMatrix();
gl.glUniformMatrix3fv(mProgram->uniformLocation("camera"), 1, false, (GLfloat *) &mat);
glm::vec2 viewport = camera.getViewport();
mProgram->setUniformValueArray("viewport", (GLfloat *) &viewport, 1, 2);
mProgram->setUniformValue("view_id", (unsigned int) viewId);
// buffer.count returns the count of characters, and there is 6 vertex per characters
glDrawArrays(GL_TRIANGLES, 0, buffer.count() * 6);
On GDB, the segfault happens in the nvidia shared library with no stack.
The machine is a Linux 32bit on nvidia Quadro FX 1500.
I tried also to check memory with valgrind and opengl error with apitrace, without any success…
Some idea ?