gpu/internal/shaders: generate shader variants

We're about to add Direct3D support, where shaders are written in
HLSL. Rather than write shaders twice (or more), convert them to
a GLSL variant understood by the glslcc cross-compiler and generate
the OpenGL ES 2.0 and HLSL variants. The HLSL is used by a future
change.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2020-02-16 21:53:19 +01:00
parent 1f43bfa0e4
commit ac7029fa24
15 changed files with 1263 additions and 301 deletions
+15
View File
@@ -0,0 +1,15 @@
#version 310 es
// SPDX-License-Identifier: Unlicense OR MIT
precision mediump float;
layout(location=0) in vec2 vUV;
{{.Header}}
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = {{.FetchColorExpr}};
}
+27
View File
@@ -0,0 +1,27 @@
#version 310 es
// SPDX-License-Identifier: Unlicense OR MIT
precision highp float;
layout(binding = 0) uniform Block {
float z;
vec2 scale;
vec2 offset;
vec2 uvScale;
vec2 uvOffset;
} uniforms;
layout(location = 0) in vec2 pos;
layout(location = 1) in vec2 uv;
layout(location = 0) out vec2 vUV;
void main() {
vec2 p = pos;
p *= uniforms.scale;
p += uniforms.offset;
gl_Position = vec4(p, uniforms.z, 1);
vUV = uv*uniforms.uvScale + uniforms.uvOffset;
}
+22
View File
@@ -0,0 +1,22 @@
#version 310 es
// SPDX-License-Identifier: Unlicense OR MIT
precision mediump float;
{{.Header}}
// Use high precision to be pixel accurate for
// large cover atlases.
layout(location = 0) in highp vec2 vCoverUV;
layout(location = 1) in vec2 vUV;
layout(binding = 1) uniform sampler2D cover;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = {{.FetchColorExpr}};
float cover = abs(texture(cover, vCoverUV).r);
fragColor *= cover;
}
+28
View File
@@ -0,0 +1,28 @@
#version 310 es
// SPDX-License-Identifier: Unlicense OR MIT
precision highp float;
layout(binding = 0) uniform Block {
float z;
vec2 scale;
vec2 offset;
vec2 uvScale;
vec2 uvOffset;
vec2 uvCoverScale;
vec2 uvCoverOffset;
} uniforms;
layout(location = 0) in vec2 pos;
layout(location = 0) out vec2 vCoverUV;
layout(location = 1) in vec2 uv;
layout(location = 1) out vec2 vUV;
void main() {
gl_Position = vec4(pos*uniforms.scale + uniforms.offset, uniforms.z, 1);
vUV = uv*uniforms.uvScale + uniforms.uvOffset;
vCoverUV = uv*uniforms.uvCoverScale+uniforms.uvCoverOffset;
}
+18
View File
@@ -0,0 +1,18 @@
#version 310 es
// SPDX-License-Identifier: Unlicense OR MIT
precision mediump float;
// Use high precision to be pixel accurate for
// large cover atlases.
layout(location = 0) in highp vec2 vUV;
layout(binding = 0) uniform sampler2D cover;
layout(location = 0) out vec4 fragColor;
void main() {
float cover = abs(texture(cover, vUV).r);
fragColor.r = cover;
}
+22
View File
@@ -0,0 +1,22 @@
#version 310 es
// SPDX-License-Identifier: Unlicense OR MIT
precision highp float;
layout(location = 0) in vec2 pos;
layout(location = 1) in vec2 uv;
layout(binding = 0) uniform Block {
vec2 scale;
vec2 offset;
} uvparams;
layout(location = 0) out vec2 vUV;
void main() {
vec2 p = pos;
p.y = -p.y;
gl_Position = vec4(p, 0, 1);
vUV = uv*uvparams.scale + uvparams.offset;
}
+83
View File
@@ -0,0 +1,83 @@
#version 310 es
// SPDX-License-Identifier: Unlicense OR MIT
precision mediump float;
layout(location=0) in vec2 vFrom;
layout(location=1) in vec2 vCtrl;
layout(location=2) in vec2 vTo;
layout(binding=0) uniform sampler2D areaLUT;
layout(location = 0) out vec4 fragCover;
void main() {
float dx = vTo.x - vFrom.x;
// Sort from and to in increasing order so the root below
// is always the positive square root, if any.
// We need the direction of the curve below, so this can't be
// done from the vertex shader.
bool increasing = vTo.x >= vFrom.x;
vec2 left = increasing ? vFrom : vTo;
vec2 right = increasing ? vTo : vFrom;
// The signed horizontal extent of the fragment.
vec2 extent = clamp(vec2(vFrom.x, vTo.x), -0.5, 0.5);
// Find the t where the curve crosses the middle of the
// extent, x₀.
// Given the Bézier curve with x coordinates P₀, P₁, P₂
// where P₀ is at the origin, its x coordinate in t
// is given by:
//
// x(t) = 2(1-t)tP₁ + t²P₂
//
// Rearranging:
//
// x(t) = (P₂ - 2P₁)t² + 2P₁t
//
// Setting x(t) = x₀ and using Muller's quadratic formula ("Citardauq")
// for robustnesss,
//
// t = 2x₀/(2P₁±√(4P₁²+4(P₂-2P₁)x₀))
//
// which simplifies to
//
// t = x₀/(P₁±√(P₁²+(P₂-2P₁)x₀))
//
// Setting v = P₂-P₁,
//
// t = x₀/(P₁±√(P₁²+(v-P₁)x₀))
//
// t lie in [0; 1]; P₂ ≥ P₁ and P₁ ≥ 0 since we split curves where
// the control point lies before the start point or after the end point.
// It can then be shown that only the positive square root is valid.
float midx = mix(extent.x, extent.y, 0.5);
float x0 = midx - left.x;
vec2 p1 = vCtrl - left;
vec2 v = right - vCtrl;
float t = x0/(p1.x+sqrt(p1.x*p1.x+(v.x-p1.x)*x0));
// Find y(t) on the curve.
float y = mix(mix(left.y, vCtrl.y, t), mix(vCtrl.y, right.y, t), t);
// And the slope.
vec2 d_half = mix(p1, v, t);
float dy = d_half.y/d_half.x;
// Together, y and dy form a line approximation.
// Compute the fragment area above the line.
// The area is symmetric around dy = 0. Scale slope with extent width.
float width = extent.y - extent.x;
dy = abs(dy*width);
vec4 sides = vec4(dy*+0.5 + y, dy*-0.5 + y, (+0.5-y)/dy, (-0.5-y)/dy);
sides = clamp(sides+0.5, 0.0, 1.0);
float area = 0.5*(sides.z - sides.z*sides.y + 1.0 - sides.x+sides.x*sides.w);
area *= width;
// Work around issue #13.
if (width == 0.0)
area = 0.0;
fragCover.r = area;
}
+53
View File
@@ -0,0 +1,53 @@
#version 310 es
// SPDX-License-Identifier: Unlicense OR MIT
precision highp float;
layout(binding = 0) uniform Block {
vec2 scale;
vec2 offset;
vec2 pathOffset;
} uniforms;
layout(location=0) in vec2 corner;
layout(location=1) in float maxy;
layout(location=2) in vec2 from;
layout(location=3) in vec2 ctrl;
layout(location=4) in vec2 to;
layout(location=0) out vec2 vFrom;
layout(location=1) out vec2 vCtrl;
layout(location=2) out vec2 vTo;
void main() {
// Add a one pixel overlap so curve quads cover their
// entire curves. Could use conservative rasterization
// if available.
vec2 from = from + uniforms.pathOffset;
vec2 ctrl = ctrl + uniforms.pathOffset;
vec2 to = to + uniforms.pathOffset;
float maxy = maxy + uniforms.pathOffset.y;
vec2 pos;
if (corner.x > 0.0) {
// East.
pos.x = max(max(from.x, ctrl.x), to.x)+1.0;
} else {
// West.
pos.x = min(min(from.x, ctrl.x), to.x)-1.0;
}
if (corner.y > 0.0) {
// North.
pos.y = maxy + 1.0;
} else {
// South.
pos.y = min(min(from.y, ctrl.y), to.y) - 1.0;
}
vFrom = from-pos;
vCtrl = ctrl-pos;
vTo = to-pos;
pos *= uniforms.scale;
pos += uniforms.offset;
gl_Position = vec4(pos, 1, 1);
}