Skip to content

feat(core): add WGPU (WebGPU) compute and rendering bindings#1497

Draft
sqrew wants to merge 5 commits intocarp-lang:masterfrom
sqrew:wgpu-rendering-and-compute
Draft

feat(core): add WGPU (WebGPU) compute and rendering bindings#1497
sqrew wants to merge 5 commits intocarp-lang:masterfrom
sqrew:wgpu-rendering-and-compute

Conversation

@sqrew
Copy link
Contributor

@sqrew sqrew commented Mar 11, 2026

This PR introduces first-class support for WebGPU in Carp via the wgpu-native library.

Key Features:

  • Compute Bindings (WGPU.carp): Full support for GPGPU compute shaders (WGSL).
  • High-Level Abstraction (GpuArray.carp): An ergonomic wrapper for GPU-resident buffers that makes dispatching compute tasks feel like native Carp.
  • Rendering Support (WGPURender.carp): Bindings for modern 3D rendering, including surfaces (GLFW integration), pipelines, vertex/index buffers, uniforms, and depth testing.
  • Helpers & Headers: Clean C integration layer for sync-async management and WGPU handle tracking.
  • Examples & Tests: Includes several high-quality demos (rainbow pyramid, Mandelbrot, compute addition) and a new test suite in test/wgpu.carp.

Benefits:

  • Provides a modern, high-performance alternative to OpenGL.
  • Cross-platform portability (Vulkan, Metal, DX12) handled automatically by the backend.
  • Simplifies GPU programming in Carp through the dispatch-with macro.

Note: Requires wgpu-native installed on the system (linked via -lwgpu_native).

sqrew and others added 5 commits February 27, 2026 14:43
Adds GPU compute support to core via a synchronous Carp API over
wgpu-native (Vulkan / Metal / DX12 backend).

- WGPU.carp: context, pipeline, buffer, bind group, dispatch, readback
- GpuArray.carp: ergonomic multi-buffer dispatch abstraction
- wgpu_helpers.h: thin C shim that converts async wgpu-native callbacks
  into blocking synchronous calls via spin-poll on wgpuInstanceProcessEvents

All public API functions return (Result T String) for explicit error
handling. Requires libwgpu_native and webgpu.h headers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends the existing compute bindings with a full WebGPU rendering layer:

core/WGPURender.carp -- Carp bindings for GPU rendering:
  - Surface creation from a GLFW window (X11 + Windows via C helper)
  - Render pipelines (fullscreen triangle pass + geometry pass)
  - Offscreen render textures and samplers
  - Frame management: begin-frame / run-pass / end-frame
  - Geometry pipeline: vertex buffers, index buffers, uniform buffers,
    depth textures, indexed drawing (run-geom-pass-indexed)
  - Vertex layout: position float32x3 + color float32x3, stride 24
  - WGPURender.surface-format: queries actual GPU format to avoid
    pipeline/swapchain format mismatch

core/wgpu_render_helpers.h -- header-only C shim:
  - wgpu_create_surface_from_glfw: GLFW -> X11/Win32 native handles ->
    WGPUSurface; queries GPU capabilities for preferred swapchain format
  - Full geometry pipeline with depth testing (Depth24Plus, Less)
  - wgpu_run_geom_pass / wgpu_run_geom_pass_indexed with depth attachment
  - Uniform buffer create/update, index buffer, depth texture helpers
  - depthSlice = WGPU_DEPTH_SLICE_UNDEFINED on color attachments (wgpu 0.20+)
  - XSetWindowBackground on X11 to prevent screen imprint without compositor

core/GLFW.carp -- added GLFW_CLIENT_API / GLFW_NO_API constants
  (required: hint window before creation when using WGPU instead of OpenGL)

core/wgpu_helpers.h -- suppress -Wunused-function for header-only helpers

examples/wgpu-pyramid.carp -- spinning rainbow pyramid demo:
  - 5 vertices, 4 triangular faces, 12 indices (no base)
  - Per-vertex colors: yellow apex, red/green/blue/purple base corners
  - Uniform buffer: time + aspect ratio (16 bytes, GPU-side MVP)
  - WGSL computes rotate_y(t) * rotate_x(0.3) + perspective projection
  - Bounce: sin(t*2)*0.3 on Y translation
  - Detects surface format at runtime for pipeline compatibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three new headless/windowed GPU demos covering the full compute+render
surface, plus the small API additions needed to run them.

examples/wgpu-compute.carp -- GPU Array Add (headless compute)
  - Uploads two float arrays, runs WGSL element-wise add, reads back
  - Uses GpuArray for ergonomic buffer management
  - Demonstrates full compute path with zero render API surface

examples/wgpu-gradient.carp -- Animated Plasma Gradient (windowed render)
  - Fullscreen triangle from vertex index, no geometry buffers needed
  - Time uniform drives HSV plasma shader via sine combinations
  - Demonstrates fullscreen pass pipeline end-to-end

examples/wgpu-mandelbrot.carp -- Interactive Mandelbrot (compute + render)
  - Compute shader writes iteration counts into a storage buffer
  - Fullscreen fragment shader reads that buffer and maps to vivid colors
  - W/S zoom, arrow pan, ESC quit -- smooth_i log-normalized coloring
  - Demonstrates both pipelines in one frame loop

core/WGPURender.carp -- two new Carp bind group helpers:
  - create-render-uniform-bind-group (uniform at binding 0)
  - create-render-storage-uniform-bind-group (storage at 0, uniform at 1)
  Both derive layout from the render pipeline; return (Result bg String).

core/wgpu_render_helpers.h -- C implementations of the above:
  - wgpu_create_render_uniform_bind_group
  - wgpu_create_render_storage_uniform_bind_group
  Both use wgpuRenderPipelineGetBindGroupLayout to auto-derive layout,
  so no separate BindGroupLayout creation is needed in Carp.

core/GpuArray.carp -- fix load path case: "wgpu.carp" -> "WGPU.carp"
  (case-sensitive on Linux; was silently broken outside bullet-heaven)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
examples/wgpu-*.carp, examples/wgpu-pyramid.carp:
  Replace absolute /home/sqrew/Desktop/Carp-fork/core/... paths with
  bare filenames (GLFW.carp, WGPURender.carp, GpuArray.carp).
  Carp resolves these via CARP_DIR/core/ at build time, matching the
  convention used by all other examples (SDL.carp etc.).

test/wgpu.carp:
  GPU compute test suite. Runs element-wise array add through the full
  pipeline: create-context -> create-pipeline -> GpuArray upload ->
  dispatch-with -> download -> assert result == [11 22 33 44 55].
  If create-context returns Error (no GPU / headless CI), the suite
  reports one skipped pass and exits 0 rather than failing.
  Confirmed passing on real GPU: 1 passed, 0 failed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sqrew
Copy link
Contributor Author

sqrew commented Mar 12, 2026

I absolutely don't expect this to be merged as is but I wanted to show where I am at with it and see if it's something even interesting to anyone. WGPU would open up the world of cross platform GPU compute on top of cross platform rendering and has a few example test showcases of both. It's currently working locally without issues but there are sure to be concerns such as requiring wgpu-native. I'm totally open to simply contributing this as an external library but I posed it as a part of the core language due to Carp's current game-focused narrative. It would also open up the possibility of replacing the OpenGL api in favor of a more modern alternative that matches Carp's natural functional style more closely. Anyways, I know this is large and unexpected so no rush in looking at this. Thanks for checking it out.

@eriksvedang
Copy link
Collaborator

Cool stuff! You make an interesting point with it perhaps being a better alternative for the "bundled graphics api", but need to think about it a bit :)

@eriksvedang eriksvedang marked this pull request as draft March 19, 2026 08:40
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.

2 participants