I maintain various builds of the Cura slicer application and that has a display of the sliced model that is implemented using a geometry shader. Until now, the Pi 4 build has used a simpler display that didn't have the GS. Now, I have a working build that does use the GS.

Here's the hoops I had to jump through to get a working GS....
- use mesa version 20.1.0 from their git repo at https://gitlab.freedesktop.org/mesa/mesa.git
- in meson_options.txt set platforms to ['drm', 'x11', 'surfaceless'] and gallium-drivers to ['kmsro', 'v3d', 'vc4', 'swrast']
- install the mesa stuff into somewhere like /opt/mesa-20.1 and use a script (or do the equivalent in your app) that does this:
Code: Select all
MESA_LIB_DIR="/opt/mesa-20.1/lib/arm-linux-gnueabihf" if [ -d "$MESA_LIB_DIR" ]; then echo "Found $MESA_LIB_DIR" export LD_LIBRARY_PATH="$MESA_LIB_DIR" export MESA_GLES_VERSION_OVERRIDE="3.2" fi - put "#version 320 es" at the top of the GS shader code.
- due to the limited number of GPU registers and what looks like a poor strategy in the mesa compiler, you need to make sure that vertices are emitted at the point at which their values are calculated otherwise the compiler tends to move the storing of the outputs to the end of the shader and then that clogs up registers that could otherwise be freed. The easiest way to do that is to enclose the code that emits the vertex in an if() statement so that the compiler will not delay its output.
There is also a bug in the current mesa that causes the output to be corrupted with lots of random filled triangles if the GS doesn't output a primitive. i.e. when the vertices were culled. I worked around that by always outputting a primitive even when one wasn't required by setting gl_Position to 0.0 for all of the primitive's vertices. In the example below, I use a zero value of alpha to indicate that the vertex should be culled.
[/code]Code: Select all
void outputVertex(const bool is_horizontal_surface, const int index, const float sign, const float offset) { f_vertex = v_vertex[index]; f_color = v_color[index]; if (v_color[index].a != 0.0) { vec4 vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; vec3 normal = normalize(vec3(vertex_delta.z, vertex_delta.y, -vertex_delta.x)); vec4 pos_offset; if (is_horizontal_surface) { f_normal = sign * vec3(0.0, 1.0, 0.0); // up/down pos_offset = vec4(normal * offset, 0.0); // left/right } else { f_normal = sign * normal; // left/right pos_offset = vec4(0.0, offset, 0.0, 0.0); // up/down } gl_Position = viewProjectionMatrix * (gl_in[index].gl_Position + pos_offset); EmitVertex(); } else { // workaround mesa bug, must always emit a vertex even when line is not being displayed gl_Position = vec4(0.0); EmitVertex(); } }