Skip to content

Instantly share code, notes, and snippets.

@tildearrow
Created May 10, 2019 21:39
Show Gist options
  • Save tildearrow/dce93cc1116cabea3bae15397a594e6c to your computer and use it in GitHub Desktop.
Save tildearrow/dce93cc1116cabea3bae15397a594e6c to your computer and use it in GitHub Desktop.
Mesa VSync bug test program
// as seen on https://gfycat.com/UniqueSpiritedApatosaur
// compile with:
// g++ -o triangle main.cpp -lGL -lGLEW -lglfw
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <time.h>
#include <GL/glew.h>
#include <GL/glxew.h>
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
#include <X11/Xlib.h>
double curVPos;
int frameCount;
bool useOML;
int pc1, pc2;
long cust, cmsc, csbc;
Display* disp;
GLXWindow gxw;
float v[6]={
0.0f, 0.5f, // Vertex 1 (X, Y)
0.5f, -0.5f, // Vertex 2 (X, Y)
-0.5f, -0.5f // Vertex 3 (X, Y)
};
const char* vertS="\
#version 150\n\
in vec2 position;\n\
void main() {\n\
gl_Position=vec4(position, 0.0, 1.0);\n\
}";
const char* fragS="\
#version 150\n\
out vec4 outColor;\n\
void main() {\n\
outColor=vec4(1.0, 1.0, 1.0, 1.0);\n\
}";
long long perfCount() {
#ifdef _WIN32
LARGE_INTEGER temp, prec;
QueryPerformanceCounter(&temp);
QueryPerformanceFrequency(&prec);
return temp.QuadPart*(1000000000/prec.QuadPart);
#else
#ifdef __MACH__
return mach_absolute_time();
#else
struct timespec temp;
clock_gettime(CLOCK_MONOTONIC,&temp);
return (temp.tv_sec*1000000000)+temp.tv_nsec;
#endif
#endif
}
char* load(const char* name) {
char* ret;
size_t siz;
FILE* f;
f=fopen(name,"r");
if (f==NULL) {
return NULL;
}
fseek(f,0,SEEK_END);
siz=ftell(f);
ret=new char[siz+1];
fseek(f,0,SEEK_SET);
fread(ret,1,siz,f);
ret[siz]=0;
fclose(f);
return ret;
}
int main(int argc, char** argv) {
GLFWwindow* window;
GLuint vertexBuffer;
// IF UNDER MESA, CHANGE THIS TO "true" TO SIMULATE
// HOW IT SHOULD REALLY BEHAVE
useOML=false;
/* Initialize the library */
if (!glfwInit()) {
printf("no init\n");
return 1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(512, 512, "Hello World", NULL, NULL);
if (!window) {
glfwTerminate();
return 1;
}
disp=glfwGetX11Display();
gxw=glfwGetGLXWindow(window);
/* Make the window's context current */
glfwMakeContextCurrent(window);
glewExperimental=1;
glewInit();
if (GLXEW_OML_sync_control) {
printf("good. good!\n");
}
glGenBuffers(1,&vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(v),v,GL_DYNAMIC_DRAW);
GLint status;
GLuint vertexShader=glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertS, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if (!status) {
printf("can't load v\n"); exit(1);
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragS, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if (!status) {
printf("can't load f\n"); exit(1);
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
//glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLint posAttrib=glGetAttribLocation(shaderProgram, "position");
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(posAttrib);
/* set */
//glfwSwapInterval(0);
glfwSwapInterval(1);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window)) {
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
curVPos+=0.005;
curVPos-=(int)curVPos;
for (int i=0; i<3; i++) {
v[i*2]=cos(((i*0.33333333333)+curVPos)*2*M_PI)*0.5;
v[i*2+1]=sin(((i*0.33333333333)+curVPos)*2*M_PI)*0.5;
}
glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(v),v,GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, 3);
frameCount++;
pc2=pc1;
pc1=perfCount();
printf("pc for %d: %d\n",frameCount,(pc1-pc2)/1000);
glXGetSyncValuesOML(disp,gxw,&cust,&cmsc,&csbc);
printf("%d %d %d\n",cust,cmsc,csbc);
if ((frameCount%30)==0) {
printf("sleeping 500ms...\n");
usleep(500000);
}
/* Swap front and back buffers */
if (useOML) glXWaitForMscOML(disp,gxw,csbc+1,1,0,&cust,&cmsc,&csbc);
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment