Commit4a3c86c1Recorded19 Sep 2026Repositorysigil-graphics
Set the uniform block to 512 bytes (128 floats)
Message
David's ruling at review: 512 B over 1 KiB. sokol_gp's uniform pool is max_commands copies of the per-draw struct, so this is an 8.4 MB pool rather than 16.8 MB, on every target including wasm linear memory. SIGIL_GFX_UNIFORM_BUFFER_SIZE and SGP_UNIFORM_CONTENT_SLOTS move together; the block-overflow probe fills it with eight mat4 instead of sixteen.
Changed
README.md | 2 +-
src/c/graphics.c | 9 +++++----
src/c/sokol-graphics.c | 12 ++++++------
test/test-shader-limits/src/test-shader-limits/scene.sgl | 6 +++---
4 files changed, 15 insertions(+), 14 deletions(-)Diff
README.mdmodified
@@ -58,7 +58,7 @@ both prefixes the version line under `cond-expand`.
58
`load-shader` scans the fragment source for `uniform` declarations of `float`, 59
`vec2`, `vec3`, `vec4` and `mat4`, scalar or array (`uniform vec4 palette[8];`, a 60
literal count; a `lowp`/`mediump`/`highp` qualifier is fine). `sampler2D` is not a−61
uniform-block entry. Up to 16 declarations (an array is one) and 1 KiB in total,+61
uniform-block entry. Up to 16 declarations (an array is one) and 512 bytes in total, 62
both checked by `load-shader` (the error names the limit); a GLSL compile error 63
is an error too, with sokol's log line before it. Entries are 64
packed in declaration order.src/c/graphics.cmodified
@@ -149,15 +149,16 @@ typedef struct {
149
* 150
* SIGIL_GFX_UNIFORM_BUFFER_SIZE must equal SGP_UNIFORM_CONTENT_SLOTS * 151
* sizeof(float) (see sokol-graphics.c): sgp_set_uniform asserts the−152
* pushed size fits its per-draw slot. 1 KiB holds 16 members of up to−153
* `vec4 name[16]` each, minus the auto-uniforms; a larger block costs−154
* sokol_gp `max_commands` (16384) copies of it in its uniform pool.+152
* pushed size fits its per-draw slot. 512 B holds `vec4 name[8]` arrays four+153
* times over beside the auto-uniforms; a larger block costs sokol_gp+154
* `max_commands` (16384) copies of it in its uniform pool (David, 2026-09-19:+155
* 512 B over 1 KiB, an 8.4 MB pool over 16.8 MB). 156
* 157
* sokol_gfx caps a uniform block at SG_MAX_UNIFORMBLOCK_MEMBERS (16) 158
* declared members; an array counts as one member, so the 16 here is 159
* that cap, not a float budget. */ 160
#define SIGIL_GFX_MAX_UNIFORMS 16−160
#define SIGIL_GFX_UNIFORM_BUFFER_SIZE 1024 /* matches SGP_UNIFORM_CONTENT_SLOTS=256 floats */+161
#define SIGIL_GFX_UNIFORM_BUFFER_SIZE 512 /* matches SGP_UNIFORM_CONTENT_SLOTS=128 floats */ 162
#define SIGIL_GFX_UNIFORM_NAME_MAX 64 163
164
typedef struct {src/c/sokol-graphics.cmodified
@@ -16,18 +16,18 @@
16
* is not linked on web. 17
*/ 18
−19
/* sgp's per-draw uniform buffer: 256 floats (1 KiB). Must equal+19
/* sgp's per-draw uniform buffer: 128 floats (512 B). Must equal 20
* SIGIL_GFX_UNIFORM_BUFFER_SIZE / sizeof(float) in graphics.c, which 21
* mirrors the block on the CPU side and asserts nothing larger is pushed. 22
* sokol_gp's default is 8 floats (32 bytes), too small for even the 23
* auto-uniforms (u_time, u_resolution) plus one vec4; 64 floats (v0.10)−24
* held a handful of vec4s; 256 floats holds uniform arrays such as−25
* `vec4 palette[16]` beside them. Cost: sokol_gp keeps max_commands+24
* held a handful of vec4s; 128 floats holds uniform arrays such as+25
* `vec4 palette[8]` beside them. Cost: sokol_gp keeps max_commands 26
* (16384) copies of the sgp_uniform struct in its pool, so the pool goes−27
* from 4.3 MB to 16.8 MB, allocated and zeroed once in sgp_setup; per draw−28
* under a custom shader it memcmps one 1 KiB struct. Default-pipeline+27
* from 4.3 MB to 8.4 MB, allocated and zeroed once in sgp_setup; per draw+28
* under a custom shader it memcmps one 512 B struct. Default-pipeline 29
* draws (no shader bound) skip the uniform path entirely. */−30
#define SGP_UNIFORM_CONTENT_SLOTS 256+30
#define SGP_UNIFORM_CONTENT_SLOTS 128 31
32
#if defined(__wasm__) 33
test/test-shader-limits/src/test-shader-limits/scene.sglmodified
@@ -322,10 +322,10 @@
322
;; failed sg_make_shader still returns an id) 323
(expect-error "shader-compile-error" 324
(lambda () (load-shader VERT-SOURCE (string-append GLSL-PREFIX "out vec4 fragColor;\nvoid main() { fragColor = ; }\n"))))−325
;; the block caps are errors, not silent drops: 16 mat4 fill the−326
;; 1 KiB exactly, so u_resolution after them does not fit+325
;; the block caps are errors, not silent drops: 8 mat4 fill the+326
;; 512 B exactly, so u_resolution after them does not fit 327
(expect-error "uniform-block-too-large"−328
(lambda () (load-shader VERT-SOURCE (string-append GLSL-PREFIX "uniform mat4 m[16];\nuniform vec2 u_resolution;\nout vec4 fragColor;\nvoid main() { fragColor = m[3][0] * u_resolution.x; }\n"))))+328
(lambda () (load-shader VERT-SOURCE (string-append GLSL-PREFIX "uniform mat4 m[8];\nuniform vec2 u_resolution;\nout vec4 fragColor;\nvoid main() { fragColor = m[3][0] * u_resolution.x; }\n")))) 329
(expect-error "uniform-too-many" 330
(lambda () (load-shader VERT-SOURCE (string-append GLSL-PREFIX SEVENTEEN-FLOATS "out vec4 fragColor;\nvoid main() { fragColor = vec4(f0 + f16); }\n")))) 331
(expect-ok "uniform-nested"