Hello !
I’m currently having fun with shaders but I’m noticing quite an extreme slowdown when running the glLinkProgram function on shaders in specific cases.
The slowdown only seems to happen when the shader is first compiled (meaning that if I run the program, the first time around the glLinkProgram can take up to 30-40s to execute, but if I close the program and open it again, which calls glLinkProgram again, it is instantaneous). It happens if I launch the program after I restart my computer, but only the first time it is executed, or when the shader file is modified.
If the shader fails to compile, then the functions is instantaneous (and calling glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, success);
yields an error code, which is expected since in that case my code resorts to a default basic fragment shader) and, weirdly, the same shader, with the same functions and uniforms but that, for example, only returns a black color, is linked instantaneously aswell…
Here is an example of a shader that is slow (not all are, the simple shaders are always pretty fast to link, and also note that this is OpenGL 3.0 shaders and that I know that this is really old OpenGL). This shader creates fractal noise maps :
Vertex Shader
void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
}
Fragment Shader
uniform sampler2D screenTexture;
uniform ivec2 screenResolution;
uniform vec4 region = vec4(0, 0, 1, 1);
uniform int seed;
uniform int numOctaves = 1;
uniform vec2 baseFrequency = vec2(0.01, 0.01);
uniform bool type = false;
uniform bool stitchTiles = false;
uniform float time = 0;
uint hash(uint x) {
x += ( x << 10u );
x ^= ( x >> 6u );
x += ( x << 3u );
x ^= ( x >> 11u );
x += ( x << 15u );
return x;
}
float random(int i, vec3 pos) {
const uint mantissaMask = 0x007FFFFFu;
const uint one = 0x3F800000u;
uint h = hash(i + hash(floatBitsToUint(pos.x)) + hash(hash(floatBitsToUint(pos.y))) + hash(hash(hash(floatBitsToUint(pos.z)))));
h &= mantissaMask;
h |= one;
float r2 = uintBitsToFloat(h);
return r2 - 1.0;
}
vec3 hashVect(int i, vec3 p) {
return vec3(
2 * random(i , p) - 1,
2 * random(i+1, p) - 1,
2 * random(i+2, p) - 1);
}
float noise(int seed, vec3 p, float freq, bool repeat){
vec3 i = floor(p * freq);
vec3 f = fract(p * freq);
vec3 u = f*f*f*(10.0-15.0*f+6.0*f*f);
float v1, v2, v3, v4, v5, v6, v7, v8;
if(repeat){
float fact1 = (round(screenResolution.x * max(baseFrequency.x, 0)) * freq == i.x + 1) ? 0 : 1;
float fact2 = (round(screenResolution.y * max(baseFrequency.y, 0)) * freq == i.y + 1) ? 0 : 1;
v1 = dot(hashVect(seed, vec3(i.x , i.y , i.z )), f - vec3(0.,0.,0.));
v2 = dot(hashVect(seed, vec3(fact1 * (i.x + 1), i.y , i.z )), f - vec3(1.,0.,0.));
v3 = dot(hashVect(seed, vec3(i.x , fact2 * (i.y + 1), i.z )), f - vec3(0.,1.,0.));
v4 = dot(hashVect(seed, vec3(fact1 * (i.x + 1), fact2 * (i.y + 1), i.z )), f - vec3(1.,1.,0.));
v5 = dot(hashVect(seed, vec3(i.x , i.y , i.z + 1)), f - vec3(0.,0.,1.));
v6 = dot(hashVect(seed, vec3(fact1 * (i.x + 1), i.y , i.z + 1)), f - vec3(1.,0.,1.));
v7 = dot(hashVect(seed, vec3(i.x , fact2 * (i.y + 1), i.z + 1)), f - vec3(0.,1.,1.));
v8 = dot(hashVect(seed, vec3(fact1 * (i.x + 1), fact2 * (i.y + 1), i.z + 1)), f - vec3(1.,1.,1.));
}
else{
v1 = dot(hashVect(seed, i + vec3(0.,0.,0.)), f - vec3(0.,0.,0.));
v2 = dot(hashVect(seed, i + vec3(1.,0.,0.)), f - vec3(1.,0.,0.));
v3 = dot(hashVect(seed, i + vec3(0.,1.,0.)), f - vec3(0.,1.,0.));
v4 = dot(hashVect(seed, i + vec3(1.,1.,0.)), f - vec3(1.,1.,0.));
v5 = dot(hashVect(seed, i + vec3(0.,0.,1.)), f - vec3(0.,0.,1.));
v6 = dot(hashVect(seed, i + vec3(1.,0.,1.)), f - vec3(1.,0.,1.));
v7 = dot(hashVect(seed, i + vec3(0.,1.,1.)), f - vec3(0.,1.,1.));
v8 = dot(hashVect(seed, i + vec3(1.,1.,1.)), f - vec3(1.,1.,1.));
}
return mix(
mix(
mix(v1, v2, u.x),
mix(v3, v4, u.x), u.y),
mix(
mix(v5, v6, u.x),
mix(v7, v8, u.x), u.y), u.z);
}
float floatAbs(float f){
if(f >= 0) return f;
return -f;
}
vec4 pNoise(int s, vec3 p, int octave, bool repeat, bool turbulent){
vec4 col = vec4(0, 0, 0, 0);
float amp = 0;
for(int i = octave; i > 0; i--){
if(turbulent){
vec4 colNew = vec4(
pow(floatAbs(noise(s+1, p, pow(2, i - 1), repeat)), 0.8),
pow(floatAbs(noise(s+2, p, pow(2, i - 1), repeat)), 0.8),
pow(floatAbs(noise(s+3, p, pow(2, i - 1), repeat)), 0.8),
pow(floatAbs(noise(s , p, pow(2, i - 1), repeat)), 0.8));
col = col + colNew * pow(0.5, i) * (1 - col.a);
amp = pow(0.5, i);
}
else{
float colNewA = 0.5 * noise(s, p, pow(2, i - 1), repeat) + 0.5;
vec4 colNew = vec4(
0.5 * noise(s+1, p, pow(2, i - 1), repeat) + 0.5,
0.5 * noise(s+2, p, pow(2, i - 1), repeat) + 0.5,
0.5 * noise(s+3, p, pow(2, i - 1), repeat) + 0.5,
0.5 * noise(s, p, pow(2, i - 1), repeat) + 0.5);
col = pow(0.5, i) * colNew + col;
amp += pow(0.5, i);
}
}
return col/amp;
}
bool insideRect(vec2 position, vec4 box){
return position.x >= box.x && position.y >= box.y && position.x <= box.x + box.z && position.y <= box.y + box.w;
}
void main(){
if(insideRect(gl_FragCoord.xy / screenResolution, region)){
vec2 actualFrequency;
if(stitchTiles) actualFrequency = round(screenResolution * max(baseFrequency, vec2(0, 0))) / screenResolution;
else actualFrequency = max(baseFrequency, vec2(0, 0));
gl_FragColor = pNoise(seed, vec3(gl_FragCoord.xy * actualFrequency, time), numOctaves, stitchTiles, !type);
}
else gl_FragColor = vec4(0, 0, 0, 0);
}
Thanks for any help