OSMesa performance regression starting with 19.0.0
There seems to be some performance regression with OSMesa since version 19.0.0.
The code below (built with the command given below) runs reasonably fast with Mesa versions 8.0.5 - 18.3.6, but becomes much slower starting with version 19.0.0.
The example code is a minimal example extracted from much more complex code. The performance regression is also noticable in the original code which we cannot provide here. It is present with a lot of different input geometry - small and big - and with different image buffer sizes, though these variables can have a big impact on the scale of the regression measured.
Linux (Ubuntu 14.04 & 20.04) and Windows (10) are affected, both on x86 64bit.
Mesa versions tested: 8.0.5, 18.0.1, 18.3.6, 19.0.0, 23.0.2.
Example Code
#include "GL/glu.h"
#include "GL/gl.h"
#include "GL/osmesa.h"
#include <iostream>
#include <chrono>
#include <vector>
std::vector<GLfloat> getVertexBuffer(){
// 12 triangles of a cube
return {
-1, -1, -1, 1, -1, 1, 1, -1, -1,
1, -1, 1, 0, 0, 0, -1, 1, -1,
-1, -1, 1, -1, 1, 1, 0, 0, 0,
1, 1, 1, 0, 0, 0, -1, 1, 1,
1, -1, -1, -1, 1, -1, 1, 1, 1,
-1, -1, -1, 1, 1, 1, -1, 1, 1,
-1, -1, -1, -1, -1, 1, 1, -1, 1,
1, -1, 1, -1, -1, 1, 0, 0, 0,
-1, -1, 1, -1, -1, -1, -1, 1, 1,
1, 1, 1, -1, 1, -1, 0, 0, 0,
1, -1, -1, 1, -1, 1, -1, 1, -1,
-1, -1, -1, 1, -1, -1, 1, 1, 1
};
}
std::vector<GLubyte> getColorBuffer(){
// 12 "RGBA" color values
return{
1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48
};
}
void renderGeo(){
std::vector<GLfloat> vertex_buffer = getVertexBuffer();
std::vector<GLubyte> color_buffer = getColorBuffer();
glVertexPointer(3, GL_FLOAT, 0, vertex_buffer.data());
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, color_buffer.data());
glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 12);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
void render(){
const GLsizei width = 44;
const GLsizei height = 44;
OSMesaContext context = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL);
std::vector<GLubyte> image_buffer = std::vector<GLubyte>(4 * width * height);
OSMesaMakeCurrent(context, image_buffer.data(), GL_UNSIGNED_BYTE, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-11.0, 11.0, -11.0, 11.0, 11.0, -11.0);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderGeo();
glFlush();
glFinish();
OSMesaDestroyContext(context);
}
int main(){
std::chrono::time_point before = std::chrono::steady_clock::now();
render();
std::chrono::time_point after = std::chrono::steady_clock::now();
std::chrono::milliseconds diff = std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
std::cerr << "Time: "; << diff.count() << "ms\n";;
return EXIT_SUCCESS;
}
Build Command
g++ -isystem "./mesa/include" -Wall -Wextra -Wno-deprecated -Werror -O3 -DNDEBUG -std=gnu++17 -o "./bin/example" "./sources/main.cpp" -Wl,-rpath,"\$ORIGIN:\$ORIGIN/../mesa/lib" "./mesa/lib/libGLU.so" "./mesa/lib/libOSMesa.so"
Tested on "Intel i5-8500" with 32GB RAM (Ubuntu 20.04):
- Mesa 18.3.6 or older: ~40ms
- Mesa 19.0.0 or newer: ~600ms
Additional Info:
- Using VertexArrayObject & VertexBufferObject does not help.
- Mesa 18.x is fast both when built with autogen and meson, so that's not the issue it seems.
- Mesa built with: Release, with LLVM, x86, with OSMESA, gallium (swr/swrast)
- Build instructions used (for some versions): https://www.paraview.org/Wiki/ParaView/ParaView_And_Mesa_3D