Skip to content

Releases: gogpu/wgpu

v0.29.14

11 Jun 14:17
7e3da6b

Choose a tag to compare

What's Changed

Fix: Missing vertexBuffers in Linux RenderPipeline

One-line fix that enables full gg rendering on GLES Linux — SDF shapes, text, widgets all working.

device_linux.go CreateRenderPipeline did not store desc.Vertex.Buffers in the pipeline struct. The Windows device.go had it. Without vertex buffer layout, vertex attributes were never configured → all geometry silently discarded → blank window.

gg Six-Tier GPU Rendering on GLES Linux Wayland — SDF shapes, text, widgets
gg rendering on GLES Linux Wayland (WSL2, Mesa d3d12 gallium, GL 4.1) — SDF shapes, text, widgets at ~57 FPS

Found by @lkmavi (PR #215). Thank you Vladimir!

Full Changelog: v0.29.13...v0.29.14

v0.29.13

11 Jun 05:54
91c204c

Choose a tag to compare

What's Changed

Enterprise GLES Parity for Linux

Major release for GLES backend on Linux — 18 files, +1159/-58. First Pure Go GLES rendering on Linux Wayland (triangle verified on WSL2 Mesa d3d12 GL 4.1).

First Pure Go GLES triangle on Linux Wayland — WSL2, Mesa d3d12 gallium, GL 4.1, #version 410 core
First Pure Go GLES rendering on Linux Wayland (WSL2, Mesa d3d12 gallium, GL 4.1 Core Profile)

GLSL version propagation (Rust wgpu-hal parity): compileWGSLToGLSL no longer hardcodes #version 430. The detected GL_SHADING_LANGUAGE_VERSION flows from adapter → device → naga GLSL writer. On GL 4.1 emits #version 410 core.

Runtime binding fallback for GL < 4.2 (Rust device.rs:438-461): When layout(binding=N) is unavailable (GLSL < 420), bindings are assigned after glLinkProgram via glGetUniformBlockIndex + glUniformBlockBinding (UBOs) and glGetUniformLocation + glUniform1i (samplers).

MSAA validation: CreateTexture validates sample count against GL_MAX_SAMPLES and checks glGetError after texture allocation — returns proper error instead of leaving stale GL errors in queue.

GLES-aware GL function loading: gl.Context.Load() accepts isGLES flag. On GLES contexts, loads glClearDepthf (not glClearDepth), tries OES suffix for VAO functions.

Lazy VAO creation: Persistent VAO allocated in CreateCommandEncoder (after Configure), not during Adapter.Open (before Configure).

Compute dispatch barrier: VERTEX_ATTRIB_ARRAY_BARRIER_BIT added for SSBO→vertex buffer reads (particles). Found by @lkmavi.

Wayland EGL fixes: WindowBit-only tier (Mesa no PbufferBit), skip instance context, GLES 3.0 fallback, CoreProfile guard for GLES. Credits: @lkmavi (PR #210, #215).

Dependencies

  • naga v0.17.14 — SupportsExplicitLocations(), UniformInfo reflection, version-gated layout(binding=N) emission

Known Issues

  • gg rendering (SDF shapes, text) not yet working on GL 4.1 — Wayland EGL alpha channel + gg-specific rendering pipeline. Separate gg task.

Full Changelog: v0.29.12...v0.29.13

v0.29.12

08 Jun 06:17
57c71c0

Choose a tag to compare

What's Changed

Fix: Wayland EGL nativeDisplay=0 fallback to surfaceless

GetEGLDisplay with nativeDisplay=0 on Wayland tried eglGetPlatformDisplay(WAYLAND, 0) which opens a second wl_display connection via wl_display_connect(NULL). When CreateSurface later used the app's real wl_surface* (on the app's display) with EGL's separate display → "Proxy and queue point to different wl_displays" crash.

Fix: Skip Wayland platform when nativeDisplay=0 (Instance init), fall back to Mesa surfaceless. CreateSurface calls again with the real wl_display*. Also: CreateSurface Path A skips sharing Instance context when it used surfaceless display (can't eglCreateWindowSurface on surfaceless).

Validated against Rust wgpu-hal egl.rs:905-968 platform detection chain. Found by @lkmavi.

Full Changelog: v0.29.11...v0.29.12

v0.29.11

08 Jun 05:30
30521be

Choose a tag to compare

What's Changed

GLES Enterprise Parity — Shared Context + Tiered Config + CI GL Test

Completes ADR-045 (items 4-6 that v0.29.10 missed):

1. Shared context in CreateSurface: When Instance has a pre-created EGL context (X11/headless), CreateSurface shares it (ownsContext=false) instead of creating a new one. On Wayland (no Instance context), creates its own (ownsContext=true). Matches Windows AdapterContext pattern where Surface is lightweight.

2. Tiered EGL config selection (Rust wgpu-hal egl.rs:218-293): chooseEGLConfig now tries WINDOW+PBUFFER first, falls back to PBUFFER-only. Ensures the config supports both headless rendering and window presentation.

3. CI GL object creation test: TestGLObjectCreation verifies GenBuffers, GenTextures, GenVertexArrays, GenFramebuffers return non-zero IDs through goffi on Mesa surfaceless. Catches the FFI pointer convention bug found by @lkmavi (PR #210, ADR-044).

4. ROADMAP updated to v0.29.11 — all v0.29.x releases documented.

Full Changelog: v0.29.10...v0.29.11

v0.29.10

08 Jun 04:54
01ae285

Choose a tag to compare

What's Changed

Instance-level EGL context on Linux (Rust wgpu-hal parity)

CreateInstance now creates an EGL context via surfaceless/pbuffer at init time, matching Rust wgpu-hal egl.rs:846 and the Windows hidden window pattern (v0.28.6). EnumerateAdapters returns real GPU name, vendor, and driver version instead of placeholder "Unknown" values.

On Wayland (no wl_display* at init), gracefully degrades — CreateSurface provides the context later. @lkmavi's nil guard (PR #210) protects the edge case.

EGL surfaceless context fallback

NewContext checks for EGL_KHR_surfaceless_context or EGL 1.5+ before creating a pbuffer surface (Rust wgpu-hal egl.rs:735-758 parity). When surfaceless is supported, eglMakeCurrent(EGL_NO_SURFACE) works without a dummy 1×1 pbuffer — saves a surface allocation on modern Mesa/NVIDIA/ANGLE drivers.

FFI pointer convention fix (PR #210, @lkmavi)

30+ GL calls in context_linux.go fixed: pointer-type arguments now correctly use unsafe.Pointer(&pointer) instead of unsafe.Pointer(&value) for goffi CallFunction. This was a fundamental bug that prevented GLES rendering on Linux entirely. See ADR-044 for the full convention documentation. Thank you Vladimir (@lkmavi) for this critical contribution!

Full Changelog: v0.29.9...v0.29.10

v0.29.9

07 Jun 15:59
0ab21cf

Choose a tag to compare

What's Changed

Fix Wayland SHM triple-buffer freeze (gogpu#292)

Two bugs caused presentation to freeze after 3 frames on Wayland software backend:

1. bufferBusyMap pointer mismatch: waylandCreateShmBuffer stored a pointer to a temporary heap struct in bufferBusyMap. The caller then did *buf = *newBuf (value copy into wl.buffers[idx]), creating two separate memory locations. The release callback set busy=false on the dead temporary, not on the array element that waylandPresent checks. After 3 commits (one per buffer), all buffers were permanently busy=true.

Fix: register in bufferBusyMap AFTER the value copy, with pointer to &wl.buffers[idx].

2. dispatch_queue_pending empty queue: wl_display_dispatch_queue_pending only processes events already read from the socket. But nobody was reading wire data into shmQueue on the render thread — gogpu's read_events runs independently on the main thread.

Fix: use wl_display_roundtrip_queue(display, shmQueue) which does the full prepare_read → read_events → dispatch cycle.

Verified

Particles example (4096 compute-driven particles) renders continuously for 10+ seconds on WSL2 Wayland. Triple-buffer cycles correctly with release callbacks.

Full Changelog: v0.29.8...v0.29.9

v0.29.8

06 Jun 20:48
7d4ebc7

Choose a tag to compare

What's Changed

Wayland display wrapper pattern — queue mismatch fix (gogpu#292)

obtainWlShm() created wl_registry and wl_shm proxies via raw wl_display*, placing them on the DEFAULT queue. Since gogpu dispatches only its own appQueue (ADR-041), events for DEFAULT queue objects were never delivered.

Fix: uses the wl_proxy_create_wrapper pattern (Qt6 qwaylandwindow.cpp:1799-1802) so all software backend proxies (registry, wl_shm, pool, buffer) inherit shmQueue:

wrapper = wl_proxy_create_wrapper(display)
wl_proxy_set_queue(wrapper, shmQueue)
registry = wl_display_get_registry(wrapper)  → inherits shmQueue
wl_shm = wl_registry_bind(registry)          → inherits shmQueue
pool/buffer                                   → inherit from wl_shm

Uses wl_display_roundtrip_queue instead of wl_display_roundtrip to dispatch the correct queue.

Also fixes two proxy leaks: wl_registry and wl_shm are now properly destroyed in destroyWaylandBlitState(). Removes manual wl_proxy_set_queue on buffer proxies — queue inheritance is automatic via libwayland proxy_create (wayland-client.c:492: proxy->queue = factory->queue).

Validated against enterprise references: Qt6 (ephemeral wrapper), SDL3 (long-lived wrapper), winit (registry_queue_init). Confirmed on WSL2 via debug traces.

Full Changelog: v0.29.7...v0.29.8

v0.29.7

06 Jun 18:38
3bc2f74

Choose a tag to compare

What's Changed

Fix Wayland SIGSEGV on first present (gogpu#292)

obtainWlShm() called wl_display_roundtrip() on the render thread during first present, concurrent with the main thread's Wayland event dispatch. Two concurrent dispatches on the same wl_display corrupt proxy state → SIGSEGV at offset 0x18 (wl_proxy.display field from NULL).

Fix: moved Wayland detection + wl_shm binding from lazy init (first blit on render thread) to eager init in Surface.Configure() (main thread, before event loop). This matches all enterprise Wayland implementations:

  • GLFW: glfwInit()wl_init.c:568, fatal error if wl_shm missing
  • SDL3: SDL_Init(SDL_INIT_VIDEO)SDL_waylandvideo.c:1548
  • Qt6: QWaylandDisplay()qwaylanddisplay.cpp:531, explicit comment: "We have to wait until we have an eventDispatcher before creating the eventThread, otherwise forceRoundTrip() may block"
  • winit: EventLoop::new()event_loop/mod.rs:92

Affects both reporters from gogpu#292: @lkmavi (ARM64 Fedora) and @omer316 (x86_64 Pop!_OS).

Files changed

  • hal/software/blit_linux.go — add configurePlatformBlit() with eager Wayland init; remove lazy detection from blitFramebufferToWindow and blitDamageRectsToWindow
  • hal/software/resource.go — call configurePlatformBlit() from Configure()
  • hal/software/blit_windows.go, blit_darwin.go, blit_other.go — no-op stubs

Full Changelog: v0.29.6...v0.29.7

v0.29.6

06 Jun 16:58
8782431

Choose a tag to compare

What's Changed

Fence.Signal returns error on glFenceSync failure (Rust parity)

Fence.Signal() silently fell back to marking submissions as immediately complete when glFenceSync returned 0 (GPU out of memory). Now returns error, propagated through Queue.Submit(). Matches Rust wgpu-hal fence.rs:37-52 which returns Result<(), DeviceError::OutOfMemory>.

Follow-up to v0.29.5 fence ordering fix — found during method-by-method comparison of our fence lifecycle against Rust wgpu-hal.

Files changed

  • hal/gles/resource.goFence.Signal signature: Signal(value uint64)Signal(value uint64) error
  • hal/gles/queue.go — propagate Signal error in Submit (Windows)
  • hal/gles/queue_linux.go — propagate Signal error in Submit (Linux)

Full Changelog: v0.29.5...v0.29.6

v0.29.5

06 Jun 07:45
a7b8420

Choose a tag to compare

What's Changed

Bug fix: GLES fence sync ordering (Windows + Linux)

Fixed glFenceSync being called after glFlush in Queue.Submit(). The fence sync object must be inserted into the GL command stream before the flush — otherwise the fence sits in an unflushed client-side buffer and PollCompleted (which uses non-blocking glGetSynciv) never sees it signal.

Impact: deferred resource destruction could stall in headless or compute-only workloads where no SwapBuffers provides an implicit flush. Headed rendering was unaffected because SwapBuffers masks the bug.

Verified against:

  • Rust wgpu-hal queue.rs:1915-1921 — identical fence→flush ordering with explicit comment
  • ANGLE (Chromium) bug 6464 — Samsung discovered the same class of bug in production
  • Virglrenderer commit 21bbc9ea — same fix for Windows/macOS GL stalls
  • Mesa Gallium state tracker — internally flushes during glFenceSync, explaining why the bug was masked on Linux Mesa drivers

Optimized PollCompleted

Removed redundant Maintain() call from PollCompleted(). Rust wgpu-hal only calls get_latest() in the poll path (device.rs:1564); fence cleanup happens during Submit(). This avoids double GetLatest() calls per poll.

Files changed

  • hal/gles/queue.go — fence ordering + PollCompleted (Windows)
  • hal/gles/queue_linux.go — fence ordering + PollCompleted (Linux)
  • hal/gles/resource.go — updated Fence.Signal doc comment

Full Changelog: v0.29.4...v0.29.5