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.

Reply via email to