renderer: reduce a lot of glcalls and cache various states (#10757)

* opengl: cache viewport state

according to nvidia docs calling glViewPort unnecessarily on the same
already set viewport is wasteful and can cause state changes when not
needed. cache it in a struct and only call it when the viewport is
actually changing.

* opengl: cache glenable/gldisable state

avoid making multiple glenable/gldisable calls on already set caps, can
cause state changes and incur driver overhead.

* opengl: cache glscissor box

only call glscissor if the box actually has changed, try to avoid state
changes.

* opengl: cache gluniform calls

cache the gluniform calls, the uniform values are cached in driver per
program only the drawcalls setting the uniform yet again with the same
value on same location is causing more overhead then caching it ourself
and just no oping on it if no changes.

* shader: rewrite handling of uniforms and state

this is way faster as we don't need to mess with maps (hashing, etc) and instead can just use an array

* opengl: stuff and 300 shaders

* opengl: typo

* opengl: get the uniform locations properly

now that the legacy shaders are gone get the uniformlocations for
SKIP_CM etc, so they can be properly set and used depending on if
cm_enabled is set to false or true, before it was falling back to a
legacy shader that didnt even have those uniforms.

* opengl: check epsilon on float and remove extra glcall

seems an extra unset glcall was added, remove it. and check the float
epsilon on the glfloat.

* opengl: remove instanced shader draw

remove the instanced boolean from the vertex shader, might be neglible
differences, needs more benchmark/work to see if its even worth it.

* texture: cache texture paramaters

parameters where occasionally set twice or more on same texture, short
version wrap it and cache it. and move gpu churn to cpu churn.

add a bind/unbind to texture aswell.

* texture: use fast std::array caching

cache the texparameter values in fast array lookups
and incase we dont want it cached, apply it anyways.

* shader: fix typo and hdr typo

actually use Matrix4x2fv in the 4x2fv cache function, and send the
proper float array for hdr.

* texture: make caching not linear lookup

make caching of texture params not linear.

* minor style changes

* opengl: revert drawarrays

revert the mostly code style reduce loc change of drawarrays, and focus
on the caching. its a if else case going wrong here breaking
blur/contrast amongst others drawing.

---------

Co-authored-by: Vaxry <vaxry@vaxry.net>
This commit is contained in:
Tom Englund 2025-06-25 12:42:32 +02:00 committed by GitHub
parent 5a348fb7df
commit f4f090e4b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 871 additions and 892 deletions

View file

@ -1,6 +1,5 @@
#version 100
#version 300 es
precision highp float;
varying highp vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float radius;
@ -9,6 +8,8 @@ uniform int passes;
uniform float vibrancy;
uniform float vibrancy_darkness;
in vec2 v_texcoord;
// see http://alienryderflex.com/hsp.html
const float Pr = 0.299;
const float Pg = 0.587;
@ -107,6 +108,7 @@ vec3 hsl2rgb(vec3 col) {
return rgb;
}
layout(location = 0) out vec4 fragColor;
void main() {
vec2 uv = v_texcoord * 2.0;
@ -119,7 +121,7 @@ void main() {
vec4 color = sum / 8.0;
if (vibrancy == 0.0) {
gl_FragColor = color;
fragColor = color;
} else {
// Invert it so that it correctly maps to the config setting
float vibrancy_darkness1 = 1.0 - vibrancy_darkness;
@ -136,6 +138,6 @@ void main() {
vec3 newColor = hsl2rgb(vec3(hsl[0], saturation, hsl[2]));
gl_FragColor = vec4(newColor, color[3]);
fragColor = vec4(newColor, color[3]);
}
}

View file

@ -1,11 +1,15 @@
#version 100
#version 300 es
precision highp float;
varying highp vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float radius;
uniform vec2 halfpixel;
in vec2 v_texcoord;
out vec4 v_color;
layout(location = 0) out vec4 fragColor;
void main() {
vec2 uv = v_texcoord / 2.0;
@ -19,5 +23,5 @@ void main() {
sum += texture2D(tex, uv + vec2(0.0, -halfpixel.y * 2.0) * radius);
sum += texture2D(tex, uv + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
gl_FragColor = sum / 12.0;
fragColor = sum / 12.0;
}

View file

@ -1,28 +0,0 @@
precision highp float;
varying vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float noise;
uniform float brightness;
float hash(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * 1689.1984);
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.x + p3.y) * p3.z);
}
void main() {
vec4 pixColor = texture2D(tex, v_texcoord);
// noise
float noiseHash = hash(v_texcoord);
float noiseAmount = (mod(noiseHash, 1.0) - 0.5);
pixColor.rgb += noiseAmount * noise;
// brightness
if (brightness < 1.0) {
pixColor.rgb *= brightness;
}
gl_FragColor = pixColor;
}

View file

@ -1,29 +0,0 @@
precision highp float;
varying vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float contrast;
uniform float brightness;
float gain(float x, float k) {
float a = 0.5 * pow(2.0 * ((x < 0.5) ? x : 1.0 - x), k);
return (x < 0.5) ? a : 1.0 - a;
}
void main() {
vec4 pixColor = texture2D(tex, v_texcoord);
// contrast
if (contrast != 1.0) {
pixColor.r = gain(pixColor.r, contrast);
pixColor.g = gain(pixColor.g, contrast);
pixColor.b = gain(pixColor.b, contrast);
}
// brightness
if (brightness > 1.0) {
pixColor.rgb *= brightness;
}
gl_FragColor = pixColor;
}

View file

@ -1,174 +0,0 @@
#extension GL_ARB_shading_language_include : enable
precision highp float;
varying vec4 v_color;
varying vec2 v_texcoord;
uniform vec2 fullSizeUntransformed;
uniform float radiusOuter;
uniform float thick;
// Gradients are in OkLabA!!!! {l, a, b, alpha}
uniform vec4 gradient[10];
uniform vec4 gradient2[10];
uniform int gradientLength;
uniform int gradient2Length;
uniform float angle;
uniform float angle2;
uniform float gradientLerp;
uniform float alpha;
#include "rounding.glsl"
float linearToGamma(float x) {
return x >= 0.0031308 ? 1.055 * pow(x, 0.416666666) - 0.055 : 12.92 * x;
}
vec4 okLabAToSrgb(vec4 lab) {
float l = pow(lab[0] + lab[1] * 0.3963377774 + lab[2] * 0.2158037573, 3.0);
float m = pow(lab[0] + lab[1] * (-0.1055613458) + lab[2] * (-0.0638541728), 3.0);
float s = pow(lab[0] + lab[1] * (-0.0894841775) + lab[2] * (-1.2914855480), 3.0);
return vec4(linearToGamma(l * 4.0767416621 + m * -3.3077115913 + s * 0.2309699292),
linearToGamma(l * (-1.2684380046) + m * 2.6097574011 + s * (-0.3413193965)),
linearToGamma(l * (-0.0041960863) + m * (-0.7034186147) + s * 1.7076147010),
lab[3]);
}
vec4 getOkColorForCoordArray1(vec2 normalizedCoord) {
if (gradientLength < 2)
return gradient[0];
float finalAng = 0.0;
if (angle > 4.71 /* 270 deg */) {
normalizedCoord[1] = 1.0 - normalizedCoord[1];
finalAng = 6.28 - angle;
} else if (angle > 3.14 /* 180 deg */) {
normalizedCoord[0] = 1.0 - normalizedCoord[0];
normalizedCoord[1] = 1.0 - normalizedCoord[1];
finalAng = angle - 3.14;
} else if (angle > 1.57 /* 90 deg */) {
normalizedCoord[0] = 1.0 - normalizedCoord[0];
finalAng = 3.14 - angle;
} else {
finalAng = angle;
}
float sine = sin(finalAng);
float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradientLength - 1);
int bottom = int(floor(progress));
int top = bottom + 1;
return gradient[top] * (progress - float(bottom)) + gradient[bottom] * (float(top) - progress);
}
vec4 getOkColorForCoordArray2(vec2 normalizedCoord) {
if (gradient2Length < 2)
return gradient2[0];
float finalAng = 0.0;
if (angle2 > 4.71 /* 270 deg */) {
normalizedCoord[1] = 1.0 - normalizedCoord[1];
finalAng = 6.28 - angle;
} else if (angle2 > 3.14 /* 180 deg */) {
normalizedCoord[0] = 1.0 - normalizedCoord[0];
normalizedCoord[1] = 1.0 - normalizedCoord[1];
finalAng = angle - 3.14;
} else if (angle2 > 1.57 /* 90 deg */) {
normalizedCoord[0] = 1.0 - normalizedCoord[0];
finalAng = 3.14 - angle2;
} else {
finalAng = angle2;
}
float sine = sin(finalAng);
float progress = (normalizedCoord[1] * sine + normalizedCoord[0] * (1.0 - sine)) * float(gradient2Length - 1);
int bottom = int(floor(progress));
int top = bottom + 1;
return gradient2[top] * (progress - float(bottom)) + gradient2[bottom] * (float(top) - progress);
}
vec4 getColorForCoord(vec2 normalizedCoord) {
vec4 result1 = getOkColorForCoordArray1(normalizedCoord);
if (gradient2Length <= 0)
return okLabAToSrgb(result1);
vec4 result2 = getOkColorForCoordArray2(normalizedCoord);
return okLabAToSrgb(mix(result1, result2, gradientLerp));
}
void main() {
highp vec2 pixCoord = vec2(gl_FragCoord);
highp vec2 pixCoordOuter = pixCoord;
highp vec2 originalPixCoord = v_texcoord;
originalPixCoord *= fullSizeUntransformed;
float additionalAlpha = 1.0;
vec4 pixColor = vec4(1.0, 1.0, 1.0, 1.0);
bool done = false;
pixCoord -= topLeft + fullSize * 0.5;
pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0;
pixCoordOuter = pixCoord;
pixCoord -= fullSize * 0.5 - radius;
pixCoordOuter -= fullSize * 0.5 - radiusOuter;
// center the pixes dont make it top-left
pixCoord += vec2(1.0, 1.0) / fullSize;
pixCoordOuter += vec2(1.0, 1.0) / fullSize;
if (min(pixCoord.x, pixCoord.y) > 0.0 && radius > 0.0) {
float dist = pow(pow(pixCoord.x,roundingPower)+pow(pixCoord.y,roundingPower),1.0/roundingPower);
float distOuter = pow(pow(pixCoordOuter.x,roundingPower)+pow(pixCoordOuter.y,roundingPower),1.0/roundingPower);
float h = (thick / 2.0);
if (dist < radius - h) {
// lower
float normalized = smoothstep(0.0, 1.0, (dist - radius + thick + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0));
additionalAlpha *= normalized;
done = true;
} else if (min(pixCoordOuter.x, pixCoordOuter.y) > 0.0) {
// higher
float normalized = 1.0 - smoothstep(0.0, 1.0, (distOuter - radiusOuter + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0));
additionalAlpha *= normalized;
done = true;
} else if (distOuter < radiusOuter - h) {
additionalAlpha = 1.0;
done = true;
}
}
// now check for other shit
if (!done) {
// distance to all straight bb borders
float distanceT = originalPixCoord[1];
float distanceB = fullSizeUntransformed[1] - originalPixCoord[1];
float distanceL = originalPixCoord[0];
float distanceR = fullSizeUntransformed[0] - originalPixCoord[0];
// get the smallest
float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR));
if (smallest > thick)
discard;
}
if (additionalAlpha == 0.0)
discard;
pixColor = getColorForCoord(v_texcoord);
pixColor.rgb *= pixColor[3];
pixColor *= alpha * additionalAlpha;
gl_FragColor = pixColor;
}

View file

@ -1,8 +1,10 @@
#version 300 es
#extension GL_ARB_shading_language_include : enable
#extension GL_OES_EGL_image_external : require
precision highp float;
varying vec2 v_texcoord;
in vec2 v_texcoord;
uniform samplerExternalOES texture0;
uniform float alpha;
@ -15,6 +17,7 @@ uniform int discardAlphaValue;
uniform int applyTint;
uniform vec3 tint;
layout(location = 0) out vec4 fragColor;
void main() {
vec4 pixColor = texture2D(texture0, v_texcoord);
@ -31,5 +34,5 @@ void main() {
if (radius > 0.0)
pixColor = rounding(pixColor);
gl_FragColor = pixColor * alpha;
fragColor = pixColor * alpha;
}

View file

@ -1,5 +1,7 @@
#version 300 es
precision highp float;
varying vec2 v_texcoord;
in vec2 v_texcoord;
uniform sampler2D tex;
uniform float time; // quirk: time is set to 0 at the beginning, should be around 10 when crash.
uniform float distort;
@ -24,6 +26,7 @@ float noise(vec2 point) {
return mixed * mixed;
}
layout(location = 0) out vec4 fragColor;
void main() {
float ABERR_OFFSET = 4.0 * (distort / 5.5) * time;
float TEAR_AMOUNT = 9000.0 * (1.0 - (distort / 5.5));
@ -60,5 +63,5 @@ void main() {
pixColor[0] += distort / 90.0;
gl_FragColor = pixColor;
fragColor = pixColor;
}

View file

@ -1,7 +1,10 @@
#version 300 es
precision highp float;
varying vec2 v_texcoord; // is in 0-1
in vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
layout(location = 0) out vec4 fragColor;
void main() {
gl_FragColor = texture2D(tex, v_texcoord);
fragColor = texture2D(tex, v_texcoord);
}

View file

@ -1,14 +1,17 @@
#version 300 es
#extension GL_ARB_shading_language_include : enable
precision highp float;
varying vec4 v_color;
in vec4 v_color;
#include "rounding.glsl"
layout(location = 0) out vec4 fragColor;
void main() {
vec4 pixColor = v_color;
if (radius > 0.0)
pixColor = rounding(pixColor);
gl_FragColor = pixColor;
fragColor = pixColor;
}

View file

@ -1,6 +1,8 @@
#version 300 es
#extension GL_ARB_shading_language_include : enable
precision highp float;
varying vec2 v_texcoord; // is in 0-1
in vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float alpha;
@ -13,6 +15,7 @@ uniform float discardAlphaValue;
uniform int applyTint;
uniform vec3 tint;
layout(location = 0) out vec4 fragColor;
void main() {
vec4 pixColor = texture2D(tex, v_texcoord);
@ -32,5 +35,5 @@ void main() {
if (radius > 0.0)
pixColor = rounding(pixColor);
gl_FragColor = pixColor * alpha;
fragColor = pixColor * alpha;
}

View file

@ -1,8 +1,11 @@
#version 300 es
precision highp float;
varying vec2 v_texcoord; // is in 0-1
in vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform sampler2D texMatte;
layout(location = 0) out vec4 fragColor;
void main() {
gl_FragColor = texture2D(tex, v_texcoord) * texture2D(texMatte, v_texcoord)[0]; // I know it only uses R, but matte should be black/white anyways.
fragColor = texture2D(tex, v_texcoord) * texture2D(texMatte, v_texcoord)[0]; // I know it only uses R, but matte should be black/white anyways.
}

View file

@ -1,6 +1,7 @@
#version 300 es
#extension GL_ARB_shading_language_include : enable
precision highp float;
varying vec2 v_texcoord;
in vec2 v_texcoord;
uniform sampler2D tex;
uniform float alpha;
@ -13,6 +14,7 @@ uniform int discardAlphaValue;
uniform int applyTint;
uniform vec3 tint;
layout(location = 0) out vec4 fragColor;
void main() {
if (discardOpaque == 1 && alpha == 1.0)
@ -21,13 +23,13 @@ void main() {
vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
if (applyTint == 1) {
pixColor[0] = pixColor[0] * tint[0];
pixColor[1] = pixColor[1] * tint[1];
pixColor[2] = pixColor[2] * tint[2];
pixColor[0] = pixColor[0] * tint[0];
pixColor[1] = pixColor[1] * tint[1];
pixColor[2] = pixColor[2] * tint[2];
}
if (radius > 0.0)
pixColor = rounding(pixColor);
gl_FragColor = pixColor * alpha;
fragColor = pixColor * alpha;
}

View file

@ -1,86 +0,0 @@
#extension GL_ARB_shading_language_include : enable
precision highp float;
varying vec4 v_color;
varying vec2 v_texcoord;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform float roundingPower;
uniform float range;
uniform float shadowPower;
float pixAlphaRoundedDistance(float distanceToCorner) {
if (distanceToCorner > radius) {
return 0.0;
}
if (distanceToCorner > radius - range) {
return pow((range - (distanceToCorner - radius + range)) / range, shadowPower); // i think?
}
return 1.0;
}
float modifiedLength(vec2 a) {
return pow(pow(abs(a.x),roundingPower)+pow(abs(a.y),roundingPower),1.0/roundingPower);
}
void main() {
vec4 pixColor = v_color;
float originalAlpha = pixColor[3];
bool done = false;
vec2 pixCoord = fullSize * v_texcoord;
// ok, now we check the distance to a border.
if (pixCoord[0] < topLeft[0]) {
if (pixCoord[1] < topLeft[1]) {
// top left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - topLeft));
done = true;
} else if (pixCoord[1] > bottomRight[1]) {
// bottom left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(topLeft[0], bottomRight[1])));
done = true;
}
} else if (pixCoord[0] > bottomRight[0]) {
if (pixCoord[1] < topLeft[1]) {
// top right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(bottomRight[0], topLeft[1])));
done = true;
} else if (pixCoord[1] > bottomRight[1]) {
// bottom right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - bottomRight));
done = true;
}
}
if (!done) {
// distance to all straight bb borders
float distanceT = pixCoord[1];
float distanceB = fullSize[1] - pixCoord[1];
float distanceL = pixCoord[0];
float distanceR = fullSize[0] - pixCoord[0];
// get the smallest
float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR));
if (smallest < range) {
pixColor[3] = pixColor[3] * pow((smallest / range), shadowPower);
}
}
if (pixColor[3] == 0.0) {
discard; return;
}
// premultiply
pixColor.rgb *= pixColor[3];
gl_FragColor = pixColor;
}

View file

@ -1,15 +0,0 @@
uniform mat3 proj;
uniform vec4 color;
attribute vec2 pos;
attribute vec2 texcoord;
attribute vec2 texcoordMatte;
varying vec4 v_color;
varying vec2 v_texcoord;
varying vec2 v_texcoordMatte;
void main() {
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
v_color = color;
v_texcoord = texcoord;
v_texcoordMatte = texcoordMatte;
}

View file

@ -2,9 +2,11 @@
uniform mat3 proj;
uniform vec4 color;
in vec2 pos;
in vec2 texcoord;
in vec2 texcoordMatte;
out vec4 v_color;
out vec2 v_texcoord;
out vec2 v_texcoordMatte;

View file

@ -2,9 +2,11 @@
uniform mat3 proj;
uniform vec4 color;
in vec2 pos;
in vec2 texcoord;
in vec2 texcoordMatte;
out vec4 v_color;
out vec2 v_texcoord;
out vec2 v_texcoordMatte;