Skip to content

Enterprise API & Quality Audit — gg (June 2026) #365

Description

@kolkov

Enterprise API & Quality Audit — gg (June 2026)

Comprehensive audit of gogpu/gg conducted with 8 independent research agents + manual code validation. All findings confirmed against source code (10/11 claims validated, 1 already fixed).

Scope: Thread safety, correctness, performance, API quality, test coverage

🔴 P0 — Data Races (must fix)

  • BUG-RACE-001 — Global cache pointer race (text/glyph_cache.go:459, text/subpixel.go:418). SetGlobalGlyphCache() / GetGlobalGlyphCache() without any synchronization. Detectable by go test -race.
  • BUG-GLES-002 — Glyph mask quadOffset not advanced on nil bind group skip (render_session.go:2199). Subsequent batches read wrong quads → invisible text in offscreen textures. GLES-specific manifestation.

🟡 P1 — Correctness

  • BUG-RACE-002Context.closed TOCTOU: concurrent Close() → double-free of GPU resources (context.go:248). Fix: atomic.Bool + CompareAndSwap.
  • BUG-RACE-003ensureGPUCtx() lazy init without sync.Once → lost GPU context under concurrent Fill/Stroke (context.go:1509).

⚡ P2 — Performance (5-15% headroom)

  • TASK-PERF-001 — Deep-copy scissor groups: 7× make+copy per flush. Fix: ownership transfer pattern. ~5-10% CPU.
  • TASK-PERF-002 — Path conversion allocations: convertGGPathToCorePath creates fresh slices every Fill. Fix: scratch buffer reuse (Skia pattern). ~2-4% CPU.
  • TASK-PERF-003 — Stroke verb conversion: make([]stroke.PathVerb, N) when unsafe.Slice possible. ~1-2% CPU.
  • TASK-PERF-004 — Atlas full recreation + fmt.Sprintf in hot path. Fix: incremental page upload, pre-computed labels.

📋 P2 — Test Coverage

  • TASK-TEST-002gpu_render_context.go has 0 tests for ~40K LOC. Create dedicated test file.
  • TASK-TEST-003render_session.go has only 31 tests for 3,314 LOC.
  • TASK-TEST-004 — 0 t.Parallel() in 4,039 test functions. Enable for CPU-only tests (3-5× CI speedup).
  • TASK-TEST-005 — No GLES-specific test file.

📐 P3 — API Quality (v1.0 planning)

  • TASK-API-003 — 7 type aliases in public API violate project policy: ImageBuf, InterpolationMode, ImageFormat, BlendMode, LCDLayout, Align, DeviceHandle. Replace with real types (breaking change for v1.0).
  • TASK-API-004 — Duplicate internal TextureFormat (uint8 stub) can be consolidated to gputypes.TextureFormat.
  • TASK-API-005 — wgpu#218 migration prep: 13 files, 86 lines mechanical find-replace.
  • TASK-API-006 — Deprecated Paint fields (Pattern, LineWidth, LineCap, LineJoin) without removal timeline.

✅ Validated as Enterprise-Grade

  • Resource lifecycle: 362 GPU resources created / 362 released — zero leaks. Deferred destruction + WaitIdle.
  • Pipeline cache: double-check locking (RWMutex), atomic stats.
  • Text shaper: RWMutex protected, glyph cache 16-shard concurrent-safe.
  • FontSource: RWMutex + copy detection.
  • Worker pool: channel-based, lock-free.
  • Texture pool: 128MB budget, LRU eviction.
  • Benchmarks: 606 benchmark functions covering hot paths.

Cross-references


💬 We want your input

This audit was conducted systematically, but no audit is perfect. We may have missed something, misunderstood a design decision, or misjudged a priority.

If you've worked with gg and noticed something that doesn't feel right — an API that surprised you, a performance cliff you hit, a pattern that seemed off — this is the place to share it. Even small observations help.

Specifically, we'd love feedback on:

  • Are the priority levels right? Should anything be higher or lower?
  • Do you disagree with any of the findings? Some "issues" may be intentional design trade-offs we don't fully appreciate.
  • Have you encountered bugs or rough edges not listed here?
  • For the v1.0 API items (P3) — which matter most to you as a user?

One head is good — two is better. Help us make gg the best 2D graphics library it can be.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions