This is an automated email from the git hooks/post-receive script.
git pushed a commit to reference refs/pull/114/head
in repository efl.
View the commit online.
commit 93d8887c8dd2d0e87afb43dbb644b6c7f22f5889
Author: [email protected] <[email protected]>
AuthorDate: Tue May 5 10:08:50 2026 -0600
perf(evas_ector_gl): narrow span-shader precision to mediump for V3D 4.2
The span-buffer renderer's GLSL fragment shaders declare all float uniforms
and locals as `precision highp float`, which keeps too many values live on
Broadcom V3D 4.2's narrow register file. Per Igalia's V3D compiler
documentation, this forces the fragment shader from 4-threaded to 2-threaded
execution mode, and in worst-case scenarios can trigger register spills that
disable TMU (texture memory unit) pipelining — the GPU's critical path for
throughput on tiling-deferred renderers.
This change narrows the global precision default to `mediump float` (which
desktop GL drivers ignore, treating as fp32), and explicitly restores `highp`
only where required:
1. Pool dimensions (u_inv_tw, u_inv_th) and offsets (u_fill_offset, etc.):
These scale gl_FragCoord coordinates, which can exceed 2048 pixels on
large surfaces. mediump fp16 lacks sufficient range/precision for
coordinate arithmetic on such surfaces.
2. Gradient coefficients (u_fill_grad_a/b/c, etc.): These multiply
gl_FragCoord and are squared in the radial path (quadratic solve);
mediump would lose precision in the gradient parameter calculation.
3. scan_spans, scan_gradient_spans, and grad_spread function signatures
and their per-pixel coordinate locals (px, py, fy, fx, rx, ry, t, etc.):
All depend on gl_FragCoord arithmetic and must stay highp.
Coverage and color blending values remain mediump (clamped to [0, 1],
no precision loss) to further reduce register pressure.
Verification: Byte-identical Expedite VG benchmark output (10 images) on
desktop GL; ector test suite 13 passed. No hardware access to V3D 4.2
(Raspberry Pi 4); community testing will measure actual throughput impact.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
.../engines/gl_generic/evas_ector_gl_span_shader.c | 125 ++++++++++++---------
1 file changed, 69 insertions(+), 56 deletions(-)
diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_span_shader.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_span_shader.c
index 7417ecffb1..604fb733fa 100644
--- a/src/modules/evas/engines/gl_generic/evas_ector_gl_span_shader.c
+++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_span_shader.c
@@ -41,22 +41,26 @@ static const char _span_vertex_glsl[] =
/* Shared GLSL fragment shader source fragments */
/* ------------------------------------------------------------------ */
-/* Shared by all four shaders. */
+/* Default precision: mediump for register pressure on tilers (V3D 4.2 / Mali).
+ * Locals and uniforms that need fp32 (gradient coefficients, gl_FragCoord
+ * arithmetic) are explicitly qualified highp at their declaration site. */
static const char _glsl_precision[] =
- "precision highp float;\n";
+ "precision mediump float;\n";
/* 15 base uniforms + MAX_SPANS macro shared by all four shaders.
- * #define MAX_SPANS must match SPAN_COLLECTOR_DEFAULT_MAX_SPANS (64). */
+ * #define MAX_SPANS must match SPAN_COLLECTOR_DEFAULT_MAX_SPANS (64).
+ * u_inv_tw/th and u_fbo_offset participate in pixel-coordinate math that
+ * can overflow fp16 on large surfaces — mark highp. */
static const char _glsl_uniforms_common[] =
"uniform sampler2D u_fill_spans;\n"
"uniform sampler2D u_stroke_spans;\n"
- "uniform float u_inv_tw;\n"
- "uniform float u_inv_th;\n"
+ "uniform highp float u_inv_tw;\n"
+ "uniform highp float u_inv_th;\n"
"uniform int u_max_spans;\n"
"uniform vec4 u_mul_col;\n"
- "uniform vec2 u_fill_offset;\n"
- "uniform vec2 u_stroke_offset;\n"
- "uniform vec2 u_fbo_offset;\n"
+ "uniform highp vec2 u_fill_offset;\n"
+ "uniform highp vec2 u_stroke_offset;\n"
+ "uniform highp vec2 u_fbo_offset;\n"
"uniform int u_has_fill;\n"
"uniform int u_has_stroke;\n"
"uniform int u_fill_x_min;\n"
@@ -68,32 +72,36 @@ static const char _glsl_uniforms_solid[] =
"uniform vec4 u_fill_col;\n"
"uniform vec4 u_stroke_col;\n";
-/* 18 gradient coefficient uniforms (fill + stroke). */
+/* 18 gradient coefficient uniforms (fill + stroke).
+ *
+ * highp is mandatory: these multiply gl_FragCoord (which can be > 2048 on
+ * large surfaces) and are squared in the radial path, so mediump (fp16)
+ * would lose precision in the gradient parameter. */
static const char _glsl_uniforms_gradient[] =
"uniform sampler2D u_fill_grad_ramp;\n"
- "uniform float u_fill_grad_a;\n"
- "uniform float u_fill_grad_b;\n"
- "uniform float u_fill_grad_c;\n"
+ "uniform highp float u_fill_grad_a;\n"
+ "uniform highp float u_fill_grad_b;\n"
+ "uniform highp float u_fill_grad_c;\n"
"uniform int u_fill_grad_spread;\n"
"uniform sampler2D u_stroke_grad_ramp;\n"
- "uniform float u_stroke_grad_a;\n"
- "uniform float u_stroke_grad_b;\n"
- "uniform float u_stroke_grad_c;\n"
+ "uniform highp float u_stroke_grad_a;\n"
+ "uniform highp float u_stroke_grad_b;\n"
+ "uniform highp float u_stroke_grad_c;\n"
"uniform int u_stroke_grad_spread;\n"
"uniform int u_fill_grad_type;\n"
- "uniform float u_fill_grad_d;\n"
- "uniform float u_fill_grad_e;\n"
- "uniform float u_fill_grad_f;\n"
- "uniform float u_fill_grad_ra;\n"
- "uniform float u_fill_grad_rdx;\n"
- "uniform float u_fill_grad_rdy;\n"
+ "uniform highp float u_fill_grad_d;\n"
+ "uniform highp float u_fill_grad_e;\n"
+ "uniform highp float u_fill_grad_f;\n"
+ "uniform highp float u_fill_grad_ra;\n"
+ "uniform highp float u_fill_grad_rdx;\n"
+ "uniform highp float u_fill_grad_rdy;\n"
"uniform int u_stroke_grad_type;\n"
- "uniform float u_stroke_grad_d;\n"
- "uniform float u_stroke_grad_e;\n"
- "uniform float u_stroke_grad_f;\n"
- "uniform float u_stroke_grad_ra;\n"
- "uniform float u_stroke_grad_rdx;\n"
- "uniform float u_stroke_grad_rdy;\n";
+ "uniform highp float u_stroke_grad_d;\n"
+ "uniform highp float u_stroke_grad_e;\n"
+ "uniform highp float u_stroke_grad_f;\n"
+ "uniform highp float u_stroke_grad_ra;\n"
+ "uniform highp float u_stroke_grad_rdx;\n"
+ "uniform highp float u_stroke_grad_rdy;\n";
/* Composite mask uniforms (present only in *_mask variants). */
static const char _glsl_uniforms_mask[] =
@@ -115,12 +123,12 @@ static const char _glsl_scan_spans[] =
"\n"
"/* Scan one span texture row, accumulating coverage-weighted base_col\n"
" * via premultiplied-alpha src-over into result. */\n"
- "vec4 scan_spans(sampler2D tex, vec2 off, vec4 base_col, float px,\n"
- " float fy, float inv_tw, int max_s, int x_min, vec4 res) {\n"
+ "vec4 scan_spans(sampler2D tex, highp vec2 off, vec4 base_col, highp float px,\n"
+ " highp float fy, highp float inv_tw, int max_s, int x_min, vec4 res) {\n"
" int sx = x_min;\n"
" for (int i = 0; i < MAX_SPANS; i++) {\n"
" if (i >= max_s) break;\n"
- " float fx = (off.x + float(i) + 0.5) * inv_tw;\n"
+ " highp float fx = (off.x + float(i) + 0.5) * inv_tw;\n"
" vec4 t = texture2D(tex, vec2(fx, fy));\n"
" int gap = int(t.r * 255.0 + 0.5);\n"
" int len = int(t.g * 255.0 + 0.5);\n"
@@ -146,13 +154,16 @@ static const char _glsl_scan_spans[] =
*/
static const char _glsl_grad_spread[] =
"\n"
- "/* Apply gradient spread mode to t in [-inf, +inf] -> [0, 1]. */\n"
- "float grad_spread(float t, int spread) {\n"
+ "/* Apply gradient spread mode to t in [-inf, +inf] -> [0, 1].\n"
+ " * Parameter and return type are highp to preserve precision for\n"
+ " * REFLECT/REPEAT on surfaces wider than ~1024 px (mediump fract\n"
+ " * loses mantissa bits once t > 1024). */\n"
+ "highp float grad_spread(highp float t, int spread) {\n"
" if (spread == 1) {\n"
- " /* REFLECT: mirror at 0 and 1 */\n"
+ " /* REFLECT: mirror at 0 and 1; arithmetic stays highp */\n"
" t = 1.0 - abs(fract(t * 0.5) * 2.0 - 1.0);\n"
" } else if (spread == 2) {\n"
- " /* REPEAT */\n"
+ " /* REPEAT; fract in highp */\n"
" t = fract(t);\n"
" } else {\n"
" /* PAD (default) */\n"
@@ -172,17 +183,17 @@ static const char _glsl_scan_gradient_spans[] =
"/* Scan one gradient span texture row. On hit, compute t per-pixel\n"
" * (linear or radial) and sample the gradient ramp, then src-over\n"
" * blend into result. */\n"
- "vec4 scan_gradient_spans(sampler2D span_tex, vec2 off,\n"
- " sampler2D ramp, float ga, float gb, float gc,\n"
+ "vec4 scan_gradient_spans(sampler2D span_tex, highp vec2 off,\n"
+ " sampler2D ramp, highp float ga, highp float gb, highp float gc,\n"
" int gspread, int gtype,\n"
- " float gd, float ge, float gf,\n"
- " float gra, float grdx, float grdy,\n"
- " float px, float py,\n"
- " float fy, float inv_tw, int max_s, int x_min, vec4 res) {\n"
+ " highp float gd, highp float ge, highp float gf,\n"
+ " highp float gra, highp float grdx, highp float grdy,\n"
+ " highp float px, highp float py,\n"
+ " highp float fy, highp float inv_tw, int max_s, int x_min, vec4 res) {\n"
" int sx = x_min;\n"
" for (int i = 0; i < MAX_SPANS; i++) {\n"
" if (i >= max_s) break;\n"
- " float fx = (off.x + float(i) + 0.5) * inv_tw;\n"
+ " highp float fx = (off.x + float(i) + 0.5) * inv_tw;\n"
" vec4 s = texture2D(span_tex, vec2(fx, fy));\n"
" int gap = int(s.r * 255.0 + 0.5);\n"
" int len = int(s.g * 255.0 + 0.5);\n"
@@ -190,20 +201,22 @@ static const char _glsl_scan_gradient_spans[] =
" if (len == 0) break;\n"
" sx += gap;\n"
" if (int(px) >= sx && int(px) < sx + len) {\n"
- " float t;\n"
+ " highp float t;\n"
" if (gtype == 1) {\n"
" /* Radial gradient: quadratic solve in gradient space */\n"
- " float rx = ga * px + gb * py + gc;\n"
- " float ry = gd * px + ge * py + gf;\n"
- " float b_val = 2.0 * (rx * grdx + ry * grdy);\n"
+ " highp float rx = ga * px + gb * py + gc;\n"
+ " highp float ry = gd * px + ge * py + gf;\n"
+ " highp float b_val = 2.0 * (rx * grdx + ry * grdy);\n"
" /* gra = inv2a = 0.5/a, precomputed on CPU to avoid\n"
" * per-fragment division. Pre-scale b and det like\n"
" * the software forward-differencing path does. */\n"
- " float b_s = b_val * gra;\n"
- " float det = b_s * b_s + (rx * rx + ry * ry) * 2.0 * gra;\n"
+ " highp float b_s = b_val * gra;\n"
+ " highp float det = b_s * b_s + (rx * rx + ry * ry) * 2.0 * gra;\n"
" t = sqrt(max(det, 0.0)) - b_s;\n"
" } else {\n"
- " /* Linear gradient: affine dot product */\n"
+ " /* Linear gradient: affine dot product.\n"
+ " * All operands (ga, gb, gc, px, py) and destination t\n"
+ " * are highp; result lands in highp t. */\n"
" t = ga * px + gb * py + gc;\n"
" }\n"
" t = grad_spread(t, gspread);\n"
@@ -222,17 +235,17 @@ static const char _glsl_scan_gradient_spans[] =
static const char _glsl_main_solid_body[] =
"\n"
"void main() {\n"
- " float px = gl_FragCoord.x - u_fbo_offset.x;\n"
- " float py = gl_FragCoord.y - u_fbo_offset.y;\n"
+ " highp float px = gl_FragCoord.x - u_fbo_offset.x;\n"
+ " highp float py = gl_FragCoord.y - u_fbo_offset.y;\n"
" vec4 result = vec4(0.0);\n"
"\n"
" if (u_has_fill == 1) {\n"
- " float fy = (u_fill_offset.y + py) * u_inv_th;\n"
+ " highp float fy = (u_fill_offset.y + py) * u_inv_th;\n"
" result = scan_spans(u_fill_spans, u_fill_offset, u_fill_col,\n"
" px, fy, u_inv_tw, u_max_spans, u_fill_x_min, result);\n"
" }\n"
" if (u_has_stroke == 1) {\n"
- " float fy = (u_stroke_offset.y + py) * u_inv_th;\n"
+ " highp float fy = (u_stroke_offset.y + py) * u_inv_th;\n"
" result = scan_spans(u_stroke_spans, u_stroke_offset, u_stroke_col,\n"
" px, fy, u_inv_tw, u_max_spans, u_stroke_x_min, result);\n"
" }\n";
@@ -241,12 +254,12 @@ static const char _glsl_main_solid_body[] =
static const char _glsl_main_gradient_body[] =
"\n"
"void main() {\n"
- " float px = gl_FragCoord.x - u_fbo_offset.x;\n"
- " float py = gl_FragCoord.y - u_fbo_offset.y;\n"
+ " highp float px = gl_FragCoord.x - u_fbo_offset.x;\n"
+ " highp float py = gl_FragCoord.y - u_fbo_offset.y;\n"
" vec4 result = vec4(0.0);\n"
"\n"
" if (u_has_fill == 1) {\n"
- " float fy = (u_fill_offset.y + py) * u_inv_th;\n"
+ " highp float fy = (u_fill_offset.y + py) * u_inv_th;\n"
" result = scan_gradient_spans(\n"
" u_fill_spans, u_fill_offset,\n"
" u_fill_grad_ramp,\n"
@@ -257,7 +270,7 @@ static const char _glsl_main_gradient_body[] =
" px, py, fy, u_inv_tw, u_max_spans, u_fill_x_min, result);\n"
" }\n"
" if (u_has_stroke == 1) {\n"
- " float fy = (u_stroke_offset.y + py) * u_inv_th;\n"
+ " highp float fy = (u_stroke_offset.y + py) * u_inv_th;\n"
" result = scan_gradient_spans(\n"
" u_stroke_spans, u_stroke_offset,\n"
" u_stroke_grad_ramp,\n"
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.