Skip to content

Cache uniform locations in ffglex::FFGLShader - #107

Open
vjandrea wants to merge 1 commit into
resolume:masterfrom
vjandrea:fix/issue-80-cache-uniform-locations
Open

Cache uniform locations in ffglex::FFGLShader#107
vjandrea wants to merge 1 commit into
resolume:masterfrom
vjandrea:fix/issue-80-cache-uniform-locations

Conversation

@vjandrea

@vjandrea vjandrea commented Aug 23, 2026

Copy link
Copy Markdown

FFGLShader::FindUniform called glGetUniformLocation unconditionally on every call. Every Set(...)
overload routes through it, so a plugin setting a uniform every frame (e.g. Particles, which calls
FindUniform by name around 19 times per frame across two shaders) paid a string-keyed driver round-trip per
uniform per frame, per instance, for no benefit: a uniform's location is fixed for the lifetime of a linked
program.

Adds a name → location cache to FFGLShader, populated lazily in FindUniform and invalidated (cleared)
whenever the underlying program changes: in FreeGLResources(), and defensively at the top of
LinkProgram(). No public API change.

Fixes #80.

Notes for reviewers:

  • Unbounded cache growth is intentional, not an oversight. uniformLocations never evicts entries. This
    is OK in practice because it's bounded by the number of distinct uniform names a given shader declares
    (single digits up to Particles' ~19, the largest user in this tree) not by frame count or anything
    that grows over the plugin's lifetime. An eviction policy would add complexity for a cache that already
    self-limits at the shader's actual uniform count.
  • The cache-clear I added at the top of LinkProgram() is currently dead code. I traced every caller of
    Compile()/FreeGLResources() in this repo (Add, AddSubtract, Gradients, CustomThumbnail,
    Particles' GLResources, ffglquickstart::Plugin) and all of them follow the same
    InitGL → Compile() then DeInitGL → FreeGLResources() lifecycle, once each, per instance, and none of them
    call Compile() a second time on an already-linked shader without freeing it first. So today, clearing in
    FreeGLResources() alone would be enough to keep the cache correct. I kept the extra clear in
    LinkProgram() anyway as cheap insurance: nothing in FFGLShader's public API actually prevents a future
    caller from calling Compile() twice without an intervening FreeGLResources(), and if that ever
    happened, the old cache entries would silently point at locations from the previous (now-replaced)
    programID without this clear. Flagging so it doesn't read as accidental defensive-programming clutter because
    it's addressing a real (if currently unexercised) gap in the class's invariants. Please don't hesitate to flag it for removal anyway, it if you think that it's just premature optimization.

FindUniform called glGetUniformLocation unconditionally on every call,
even though a uniform's location is fixed for the lifetime of a linked
program. Adds a name->location cache, populated lazily in FindUniform
and cleared whenever the underlying program changes (FreeGLResources,
and defensively at the top of LinkProgram).

Fixes resolume#80.
@vjandrea

vjandrea commented Aug 24, 2026

Copy link
Copy Markdown
Author

@MennoVink This is the same request as #83, closed without merging even after the find() based fix in that thread was confirmed correct.
Since the code wasn't the objection there, curious whether the underlying one still stands here: that caching in FFGLShader "doesn't help achieve maximum performance nor make anything easier" (your words on #83), versus staying a thin wrapper and leaving caching to callers. If that stance holds, happy to close this and document the manual cache-in-InitGL pattern instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ffglex::FFGLShader doesn't cache uniform locations

1 participant