GFX Brand Logo
gfx.graphics
Back to Articles

Mastering Antigravity and Gemini 4 Argon: Conquering Complex Graphics Engineering with `/teamwork-preview` Adversarial Implementation and `/boost` Extreme Optimization

Seto

Seto

@seto

2026-10-1928 min read

Mastering Antigravity and Gemini 4 Argon: Conquering Complex Graphics Engineering with /teamwork-preview Adversarial Implementation and /boost Extreme Optimization

Abstract: Across my previous three posts, I shared our journey building a high-performance WebGPU hybrid runtime (GFX_Runtime) on top of Google Dawn and WKWebView, our technical discussions with graphics architect Sebastian Aaltonen on NoGraphicsAPI, and our implementation of Dawn's Metal Bindless backend alongside a zero-macro WebGPU backend for NoGraphicsAPI.

> Many readers asked a very practical question after reading those deep dives: Working in your spare time across Chromium Dawn's C++ internals, Metal 3 driver APIs, Emscripten toolchains, Slang/WGSL compiler lowering, and WebKit cross-process IPC, how did you move so fast while maintaining production-grade code quality?

> The secret lies in how I use Google Antigravity. In my experience, the new Gemini 4 Argon is astonishingly capable, and the previous Gemini 3.8 Flash was no slouch either. Often, when developers feel an AI model isn't strong enough—producing brittle code or fixing one bug only to introduce two more—the bottleneck isn't the model's raw intelligence, but how it is orchestrated.

> Drawing directly from our project's conversation transcripts and gate logs, this post walks through how I combine /teamwork-preview (multi-agent adversarial implementation) with /boost (expert deep-dive debugging and performance tuning)—executing dozens of complex engineering tasks and extreme performance optimizations continuously inside a single main conversation without polluting the context window.

---

1. Core Methodology: Why "The Model Isn't Strong Enough" Usually Means Suboptimal Orchestration

In conventional AI-assisted coding, most developers interact with a single main agent in a linear chat loop: "Implement feature X" or "This crashed, please fix it."

While single-agent prompting works fine for simple scripts or CRUD apps, its limitations quickly surface in systems engineering projects like GFX_Runtime + Dawn + NoGraphicsAPI, where binary wire alignment, GPU hardware residency validation, and cross-process memory lifecycles intersect:

  1. The "Just Make It Compile" Shortcut Bias: When a single agent acts as both implementer and judge, hitting a tough compiler or test failure often tempts it to hardcode fake return values (facades), weaken test assertions, or pollute user headers with manual padding just to claim completion;
  2. Context Pollution from Blind Trial-and-Error: While debugging a subtle crash or performance regression, a single agent will repeatedly dump megabytes of logs and read dozens of large source files directly into the main chat. Within a dozen turns, a 200k+ context window gets flooded with noise, causing the model to forget earlier architectural constraints and spiral into regression loops.

In Antigravity—whether running on Gemini 3.8 Flash previously or the powerhouse Gemini 4 Argon today—unlocking 100% of the model's engineering ceiling comes down to pairing two built-in slash workflows: /teamwork-preview and /boost.

Mermaid Diagram
flowchart TD
    subgraph MainContext ["Main Conversation Window (Kept Razor-Sharp & Clean)"]
        User["Developer Prompts & Architectural Decisions"]
        Summary["Concise Victory Report / Root-Cause & Benchmark Summary"]
        User -->|"1. Build Major New Features"| TW["/teamwork-preview\n(Multi-Agent Adversarial Delivery Subagent)"]
        User -->|"2. Deep Debugging & Extreme Tuning"| BST["/boost\n(Deep Reasoning & Profiling Subagent)"]
        TW -->|"Returns Consolidated VICTORY Report"| Summary
        BST -->|"Returns Forensic Proof & Benchmark Table"| Summary
    end

    subgraph TeamworkSandbox ["Isolated Subspace A: /teamwork-preview Red-vs-Blue Pipeline"]
        Orch["Orchestrator (Decomposes Milestones M1~M5)"]
        Exp["Explorer / Spec Miner (Codebase & Spec Survey)"]
        Work["Worker (Implementation) + Test Writer (4-Tier E2E Suite)"]
        Gate{"5-Agent Gate Committee\n2 Reviewers + 2 Challengers\n+ 1 Forensic Auditor (Binary Veto)"}
        Remed["Remediation Worker\n(Fix & Retry Iteration 2/3...)"]
        Vic["Victory Auditor (Independent Final Audit)"]

        Orch --> Exp --> Work --> Gate
        Gate -->|"Unanimous APPROVE / CLEAN"| Vic
        Gate -->|"Any REJECT / Integrity Violation"| Remed --> Gate
    end

    subgraph BoostSandbox ["Isolated Subspace B: /boost Expert Triage Sandbox"]
        DI["DeepInvestigator\n(sample Flamegraphs / vmmap Tables / Disassembly)"]
        DT["DeepThinker\n(Cross-Layer Architecture & Math Proofs)"]
        DC["DeepCoder\n(Surgical Fixes & Full Benchmark Verification)"]
        DI --> DT --> DC
    end

    TW -.->|"Spawns 20~40+ Isolated Subagents"| TeamworkSandbox
    BST -.->|"Spawns Specialist Subagents"| BoostSandbox

1. Context Isolation: How to Run 90+ Consecutive Turns in a Single Conversation

A crucial architectural detail that many users overlook is that both /teamwork-preview and /boost execute inside completely isolated Subagent conversations (invoke_subagent)!

  • When you trigger /teamwork-preview, the background Orchestrator may spawn 30 to 40 subagents, running hundreds of compiler builds, thousands of lines of code diffs, and dozens of adversarial stress tests;
  • When you trigger /boost, a background DeepInvestigator may parse tens of thousands of lines of vmmap memory regions, disassemble crash binaries with lldb / objdump, or run 15 back-to-back benchmark passes;
  • Not a single token of that intermediate noise enters your main conversation window! The main conversation only receives the distilled root-cause synthesis and final verification summary.

Because the main context remains pristine, I was able to sustain over 90 consecutive high-signal turns inside a single conversation during this project: building a major subsystem with /teamwork-preview, spotting a subtle visual anomaly during manual inspection, firing /boost in the exact same chat to dissect the bug, and then chaining multiple /boost passes to slash memory usage and lock in 72 FPS—without the main agent ever losing track of the big picture.

---

2. /teamwork-preview in Action: Forging Code Robustness Through Adversarial Gating

The core philosophy of /teamwork-preview is institutionalized distrust. After a Worker completes any milestone, the code must face a 5-agent Gate Committee running in parallel: 2 Code Reviewers (Reviewer), 2 Red-Team Challengers (Challenger—tasked with writing boundary, concurrency, and malformed-input stress tests to break the implementation), and 1 Forensic Auditor (Auditor—armed with a binary veto to catch test tampering, hardcoded facades, or unauthorized file edits). A single REJECT or REQUEST_CHANGES fails the gate and triggers a remediation iteration until unanimous 5/5 approval is achieved.

In fact, the very first prototype of our entire GFX_Runtime hybrid runtime—spanning the macOS/iOS host container, transparent WKWebView over native MTKView compositing, custom WKURLSchemeHandler IPC pipe, and Dawn Wire Server bridge—was built from scratch using /teamwork-preview (though the earliest .agents gate logs from that initial bootstrap were accidentally deleted during a later repository cleanup).

From the preserved gate logs (GATE_STATUS.md) across our subsequent milestones, here are 5 major features we built with /teamwork-preview and the critical latent bugs caught and eliminated by the adversarial gates before delivery:

1. Implementing Google Dawn's Metal Bindless Backend (ResourceTableMTL)

  • Feature Scope: Implement ResourceTableMTL.{h,mm} and pipeline integration from scratch on Dawn's chromium/8103 branch using Metal 3 Argument Buffers Tier 2 (direct 64-bit gpuResourceID writes), Copy-on-Write (CoW) in-flight buffer protection, and GPU residency tracking—without touching any git submodules or existing Dawn test files.
  • Latent Bugs Caught and Fixed via Adversarial Gating:
    • Iteration 1 Vetoed by challenger_m1_2 (REJECT): worker_m1_1's initial implementation passed all 44 Dawn unit tests and all 47 standard Metal end-to-end tests, earning APPROVE from both Reviewers. However, red-team agent challenger_m1_2 went beyond default flags, enabling --enable-backend-validation=full (activating Metal Debug Layer and GPU Shader Validation) across a 10x stress loop—and immediately caught ResourceTableTests.UseDefaultSamplers failing with a hardware GPU validation fault: Invalid texture type MTLTextureTypeInvalid bound to shader!
    • Iteration 2 Root-Cause Fix: Three parallel Explorers discovered that creating a view on a Depth24Plus texture invokes [mtlTexture newTextureViewWithPixelFormat:... swizzle:kR001Swizzle], producing a distinct child id<MTLTexture> with its own gpuResourceID (3, versus 2 on the parent texture). Tracking only base Texture* pointers left the swizzled child view unresident in [encoder useResources:count:usage:]; additionally, the 35 default fallback textures at the tail of the table were missing from residency declarations. Refactoring ResourceTableMTL to track Ref<TextureViewBase> and cache all 35 default fallback textures achieved a unanimous 47 / 47 pass under full Metal GPU validation with 0 leaked bytes (/usr/bin/leaks).

2. Building a Zero-Macro WebGPU Backend for NoGraphicsAPI (NoGraphicsAPIWebGPU.cpp)

  • Feature Scope: Implement a complete WebGPU backend in pure C (webgpu.h) strictly adhering to AGENTS.md (zero C++ STL headers, -fno-exceptions -fno-rtti, no auto, no lambdas). Support 64-bit virtual BDA pointers via Slang's generic GpuPtr<T>, a 65,536-slot WGPUResourceTable bindless heap, persistent CPU shadow buffer synchronization, and Mesh Shader-to-Vertex Pulling lowering across both native macOS and GFX_Runtime WASM (triangle, cube, and the 262,144-object deferred_renderer).
  • Latent Bugs Caught and Fixed via Adversarial Gating:
    • Milestone 2 Gate Caught Odd-Byte Upload Overruns & Null-Root Draws: Red-team agent challenger_m2_1 wrote boundary tests allocating GpuHeap instances of 1, 3, 7 bytes, catching a bug where sync_cpu_heap rounded upload sizes up to a multiple of 4 for wgpuQueueWriteBuffer without clamping against heap->aligned_size. It also caught missing dummy bind group bindings when draw / dispatch was called with root == nullptr, plus 4 stateless callback lambdas that violated AGENTS.md.
    • Milestone 5 Iteration 1 Caught 32-Bit WASM vs. 64-Bit Native Matrix Alignment Mismatch: reviewer_m5_2 inspected the Emscripten WASM build and proved that because pointers shrink from 8 bytes on 64-bit macOS to 4 bytes on wasm32, the float4x4 mvp matrix in CubeRootArguments started at byte offset 12 in C++ while WGSL's std430 layout read it from offset 16—corrupting every transform matrix in WASM.
    • Milestone 5 Iteration 2 Caught "Gray Background Masking a Pitch-Black Cube": While inspecting live window screenshots, reviewer_m5_it2_1 realized that although the automated test reported "non-black pixels", those pixels came entirely from the RGB(51, 51, 51) dark-gray clear background—while the cube itself was rendered as a pitch-black silhouette (RGB(0, 0, 0)) due to inverted screen-space normal derivatives! Issuing an immediate REQUEST_CHANGES, the reviewer forced Iteration 3 to upgrade test_tier4_acceptance.py with foreground-vs-background pixel clustering that explicitly rejects unlit silhouettes (>10% black foreground).

3. End-to-End External Video & Image Pipeline in GFX_Runtime (<video> / VideoFrame / Dual-Plane NV12)

  • Feature Scope: Support all 7 WebGPU external image/video sources (HTMLVideoElement, VideoFrame, ImageBitmap, HTMLCanvasElement, OffscreenCanvas, HTMLImageElement, ImageData) across both JS Hook Wire and .a WASM Wire via importExternalTexture and copyExternalImageToTexture, including a WebCodecs dual-plane NV12 (R8Unorm Y + RG8Unorm UV) fast path that cuts cross-process IPC bandwidth by 62.5%.
  • Latent Bugs Caught and Fixed via Adversarial Gating:
    • Milestone 3 Iteration 1 Caught an Intrusive Doubly-Linked List Use-After-Free Bomb: Both reviewer_m3_wasm_1 and challenger_m3_wasm_1 flagged a critical memory-corruption bug in lib_webgpu_emdawnwebgpu.cpp: when cleaning up a temporary external texture at the end of wgpu_queue_copy_external_image_to_texture, the Worker called the internal helper _wgpu_object_destroy(extTexObj) (which freed the C++ struct without unlinking it from the global intrusive doubly-linked list gObjectListHead) instead of the public wgpu_object_destroy(tempExtTex). Calling wgpu_destroy_all_objects() on page reload or shutdown would have immediately triggered a Use-After-Free crash.
    • Milestone 4 Iterations 1 & 2 Caught a "Procedural Shader Facade" and Enforced an 8-Quadrant Live Verification: In Milestone 4 Iteration 1, both Reviewers caught the Worker cutting corners in test_external_texture_wasm.cpp—writing a procedural checkerboard shader in WGSL instead of actually binding and sampling texture_external, and forgetting to call wgpu_canvas_context_present()! After remediation, challenger_m4_r1 pushed the bar even higher in Iteration 2: demanding an 8-tile split-screen E2E harness that simultaneously renders all 7 external source types plus sub-region origin offsets and flipY in both Hook Wire and WASM Wire modes, verifying every tile's rendered RGB color via isolated Quartz window capture (screencapture -l). After 39 subagents across the full pipeline, the feature earned a 5/5 unanimous VICTORY CONFIRMED.

4. WebKit Injected JS WebGPU Hook & Dawn Wire Serializer Generator (generate_webgpu_hook_wire.py)

  • Feature Scope: Inject webgpu_hook_wire.js at document start via WKUserScript to intercept standard navigator.gpu calls on unmodified web pages and serialize them into Dawn Wire binary command streams.
  • Latent Bugs Caught and Fixed via Adversarial Gating: Caught a main-thread deadlock hazard where GFXSchemeHandler processed /send_sync synchronously on the Cocoa UI thread (remediated by offloading command execution via dispatch_async to a background global queue), and fixed 8-byte alignment padding inside inline WGPUBindGroupLayoutEntryTransfer serialization.

5. Full-Stack Direct Mode Purge & Automated Multi-Scene Batchmode Pipeline

  • Feature Scope: Purge over 10,000 lines of legacy experimental Direct Mode code across GFX_Runtime, Dawn emdawnwebgpu, and Unity projects, while establishing automated Unity Batchmode build scripts and two-pass benchmark harnesses across UniversalSample (4 scenes) and FactoryTraining.
  • Latent Bugs Caught and Fixed via Adversarial Gating: Reviewers and Challengers performed symbol-level and build-cache sweeps across all repositories, catching lingering CMake target references and stale Emscripten sysroot archives, while hardening the local HTTPS test server against socket TIME_WAIT port collisions during back-to-back scene switching.
/teamwork-preview DeliverableSubagents SpawnedGate RejectionsMost Critical Defect Caught by Adversarial Gate
GFX_Runtime Initial Prototype30+ AgentsMulti-round iterationsBuilt WKWebView + MTKView dual-layer architecture & Dawn Wire bridge from scratch (early gate logs deleted during repo cleanup)
Dawn Metal Bindless (ResourceTableMTL)15+ Agents1 (challenger_m1_2 REJECT)Depth24Plus swizzled child TextureView and 35 default fallback textures missing from GPU residency under --enable-backend-validation=full
NoGraphicsAPI WebGPU Backend40+ Agents3 (M2 / M5 It1 / M5 It2)Odd-byte heap upload overrun, wasm32 vs. 64-bit matrix offset mismatch, and dark-gray background masking a pitch-black cube silhouette
Dual-Mode External Video/Image (NV12 + 7 Sources)39 Agents3 (M3 It1 / M4 It1 / M4 It2)_wgpu_object_destroy skipping intrusive linked-list unlink (UAF), and procedural shader faking texture_external sampling in E2E test
JS WebGPU Hook Serializer Generator25+ Agents2WKURLSchemeHandler UI thread re-entrancy deadlock risk & BindGroupLayoutEntry 8-byte alignment padding mismatch
Direct Mode Purge & Benchmark Harness20+ Agents1Cross-repo residual symbol/sysroot cache cleanup & HTTPS server socket TIME_WAIT pre-flight hardening

---

3. /boost in Action (Part 1): Surgical Debugging After Implementation

Even after /teamwork-preview delivers a feature that passes every gate test, cross-project integration, engine branch upgrades, or my own strict architectural standards occasionally surface subtle bugs or design compromises.

When that happens, there is no need to start a new chat. Simply typing /boost in the same conversation dispatches DeepInvestigator, DeepThinker, and DeepCoder to perform forensic root-cause analysis. Here are three standout debugging war stories solved by /boost:

1. Defending NoGraphicsAPI's Zero-Intrusion Purity: Fixing Upside-Down Rendering, Black Metal Lighting, and Manual _pad Fields in One Stroke

After the NoGraphicsAPI WebGPU backend passed its E2E suite, I compiled the native Metal backend side-by-side to compare visuals, spotted three issues, and prompted directly in the same conversation:

/boost 1. WebGPU is upside-down compared to Metal 2. Fixing the cube texture in WebGPU seems to have turned the native Metal cube black, so cube.slang must not be modified 3. Padding should not be added to example headers; it should be handled automatically

/boost's diagnosis and fix were surgical:

  • One Build-Time Line Fixed Both Upside-Down WebGPU and Black Metal Normals: DeepThinker proved that both visual bugs shared a single root cause. Previously, to fix unlit black faces on the WebGPU cube, a subagent had swapped cross(ddx(pos), ddy(pos)) to cross(ddy(pos), ddx(pos)) inside cube.slang—which fixed WebGPU but inverted face normals on native Metal! Why? Because NoGraphicsAPI uses Vulkan window conventions (Y-up in clip space); the native Metal backend flips Y during rasterization using a negative viewport height (x, y + h, w, -h), whereas the WebGPU specification explicitly forbids negative viewport heights. Missing that flip not only rendered WebGPU upside-down, but also negated the screen-space derivative ddy(input.world_pos)! DeepCoder reverted cube.slang to 100% pristine upstream state and injected a single post-processing rule in fix_wgsl.py to negate @builtin(position).y (_nga_ret.position.y = -_nga_ret.position.y;) before returning from every @vertex entry point. That single build-time transformation simultaneously aligned the image orientation and restored outward screen-space derivatives across both Metal and WebGPU!
  • Eliminating Manual _pad Fields via ByteAddressBuffer + -fvk-use-c-layout: To remove the manual _pad fields that had been added to cube_shared.h and gbuffer_shared.h, /boost changed GPU_ROOT in shader.slang from StructuredBuffer<type> to ByteAddressBuffer + .Load<type>(0) (which lowers to an unaligned array<u32> in WGSL, bypassing WGSL's 16-byte struct alignment mandate on mat4x4<f32>) and passed -fvk-use-c-layout to slangc. Slang then automatically emitted exact byte-offset loads matching the target C ABI (offset 16 on 64-bit native, offset 12 on 32-bit wasm32), reducing git diff on all example headers to zero.

2. Cracking the Instant exit code: 6 (SIGABRT) Crash and Dawn Wire's "Poison Pill" Mechanism

After reverting FeatureInfo in the Dawn repository, launching GFX_Runtime printed a single log line and immediately died with Program ended with exit code: 6. Invoking /boost pinpointed the cause in seconds:
  • Git Commit SHA1 Assertion in dawnProcSetProcs: Dawn 8103 added a strict version check in dawnProcSetProcs: DAWN_CHECK(std::ranges::equal(procs_->version, dawn::kDawnVersion)). Because only libdawn_native.a had been incrementally rebuilt and copied (embedding the new Git Commit SHA1) while libdawn_proc.a still held the previous commit's SHA1 string, dawnProcSetProcs immediately called abort() on startup!
  • Uncovering Dawn Wire's DawnInjectedInvalidSType Poison Pill: When I asked whether we could pass WGPUDawnTogglesDescriptor unconditionally into Emscripten without #if !defined(__EMSCRIPTEN__), /boost traced Dawn Wire's serializer (WireCmd_autogen.cpp) and revealed a fascinating security mechanism: because "dawn toggles descriptor" is tagged "native" in dawn.json, passing it in WGPUDeviceDescriptor.nextInChain causes the Wire Client to deliberately serialize a wgpu::SType::DawnInjectedInvalidSType poison pill into the binary command stream, forcing the host Wire Server to throw a validation error and reject device creation!

3. Disassembly-Level Triage: The ARM64 8-Byte Alignment Crash & Full hook_wire Protocol Sync on Dawn 8103

After merging Dawn's chromium/8103 branch, newly built GardenWire bundles crashed immediately on the very first wire command, and hook_wire failed to render.
  • Disassembling the 4-Byte Offset SIGABRT: /boost inspected the macOS .ips crash report and disassembled GFX_Runtime around dawn::wire::InstanceRequestAdapterCmd::Deserialize:
      tst  x23, #0x7          ; Test if the command buffer pointer's low 3 bits are 0 (8-byte aligned)
      b.ne 0x1004bb9f0        ; Branch to abort() if unaligned!
      
    Our IPC payload layout was [4-byte logLength][log string][Wire Commands...]. Whenever logLength == 0, the command buffer started at bodyData.bytes + 4—which is 4-byte aligned (addr % 8 == 4), not 8-byte aligned! While Dawn 7587 used raw pointer casts that ARM64 hardware tolerated unaligned, Dawn 8103 refactored BufferConsumer to use ReinterpretSpan<T> with DAWN_CHECK(reinterpret_cast<uintptr_t>(s.data()) % alignof(T) == 0u), aborting on the first 8-byte-aligned transfer struct! Adding a 16-byte aligned span helper in DawnBridgeCore.mm fixed the crash instantly.
  • Synchronizing hook_wire with Dawn 8103's Wire Protocol: Prompting /boost to update hook_wire for Dawn 8103, the subagent diffed WireCmd_autogen.cpp and resolved every breaking protocol change in one pass: removing the 8-byte commandSize field from CmdHeader, widening all WebGPU Flags and array counts to 64-bit uint64_t, fixing out-of-line deserialization ordering between ShaderSourceWGSLTransfer and ShaderModuleDescriptor.label, and updating the 152-byte WGPULimitsTransfer sentinel values (0xFFFFFFFF).

---

4. /boost in Action (Part 2): From 4.4 FPS to Locked 72 FPS and Slashing Memory by 2.5 GB

Beyond bug hunting, /boost is an extraordinary weapon for performance and memory optimization. Paired with our automated /webgpu-benchmarker skill, I used /boost to drive two major optimization campaigns across Hook Wire (JS interception) and .a Wire (WASM static linking).

1. The 3-Step Frame Rate Leap: From 4.4 FPS \to 21 FPS \to 36 FPS \to 72 FPS Locked

When we first brought up UniversalSample (Garden scene) in Wire mode, performance was a slideshow at 4.4 FPS (222.41 ms frame time). Chaining /boost with macOS sample and Instruments peeled back three consecutive bottlenecks:

Mermaid Diagram
flowchart LR
    S1["Stage 1: 4.4 FPS\n(222.4 ms Frame Time)"] -->|"/boost sample profiler caught\n99.57% CPU blocked in stderr I/O"| S2["Stage 2: 21.7 FPS\n(46.3 ms Frame Time)"]
    S2 -->|"/boost caught missing Release flag\nin build_dawn_mac (-O0 Debug)"| S3["Stage 3: 36~40 FPS\n(16.8 ms VSync Cliff Jitter)"]
    S3 -->|"/boost eliminated 17 sync XHRs\n+ 1 Batched Flush per RAF"| S4["Final Steady State: 72.0 FPS\n(FactoryTraining +65.6%)"]
  1. Cut #1 (4.4 FPS \to 21.7 FPS): Eliminating fflush(stderr) Kernel Stalls Consuming 99.57% CPU
    • Prompting /boost to profile the running GFX_Runtime process revealed a shocking breakdown: actual Native Dawn / Metal command encoding and submission took less than 1.5 ms! Meanwhile, 211.30 ms (94.8% of the frame) was spent blocked inside macOS kernel __write_nocancel syscalls triggered by debug fprintf + fflush(stderr) calls inside DoQueueWriteBuffer (which dumped 88,285 lines of hex logs in 40 seconds)! Guarding those debug logs behind off-by-default macros dropped frame time from 222 ms to 46.3 ms.
  2. Cut #2 (21.7 FPS \to 36~40 FPS): Catching the -O0 Debug Build Oversight and VSync Quantization
    • With logs disabled, frame rate was still stuck around ~21 FPS. Running /boost again on the new CPU profile showed SetBindGroup (48.3%) and QueueSubmit (34.1%) spending massive time inside un-inlined Abseil Swiss Table hash lookups and std::visit calls. Inspecting CMakeCache.txt revealed that build_dawn_mac.sh had omitted -DCMAKE_BUILD_TYPE=Release, compiling all of libdawn_native.a and libdawn_wire.a at -g -O0 with debug assertions enabled! That caused HandleCommands on the host to take 34.2 ms (plus 12.1 ms on the client = 46.3 ms, crossing the third 72Hz VSync boundary at 41.67 ms and quantizing frame rate to ~21.7 FPS). Rebuilding Dawn in -O3 Release slashed host command decoding time by over 90%!
  3. Cut #3 (36~40 FPS \to 72.0 FPS Locked): Eliminating 17 Synchronous popErrorScope XHRs and Premature QueueSubmit Flushes
    • At 36~40 FPS, a third /boost profile dissected the millisecond budget: in scenes with 38 dynamic lights, Unity WASM spent 14.0 ms and the Wire bridge added 2.5 ms, totaling 16.5~17.0 ms—just barely missing the VSync deadline and dropping to half-rate.
    • IPC telemetry exposed two culprits: ① Unity defensively called device.popErrorScope() 17 times per frame, which our early hook had wired as synchronous XHR round-trips; ② Unity called wgpuQueueSubmit twice per frame, and Dawn's client flushed immediately inside each QueueSubmit plus once at Present (3 IPC flushes per frame), while server replies were encoded as hex strings.
    • The Fix: Making popErrorScope purely asynchronous, removing immediate flushes inside wgpuQueueSubmit so all commands batch into a single RAF tail flush (emwgpuWirePresent), and switching server replies to raw binary ArrayBuffers dropped per-frame command latency to 0.19 ms ~ 0.7 ms—locking every standard 3D scene at 72.0 FPS!

---

2. The Memory Reduction Campaign: Cross-Pollinating Hook Wire and .a Wire via /boost to Slash WebContent Memory by 1.5 GB ~ 2.5 GB!

Once frame rates were locked at 72 FPS and 8MB chunking prevented initial 194MB packet spikes, running our 3-mode benchmark suite (Default vs. Hook Wire vs. .a Wire) showed that Hook Wire's steady-state WebContent physical footprint was still higher than Default in heavy scenes (5.0 GB in FactoryTraining, 4.1 GB in Garden), and .a Wire also had room for improvement.

In the exact same conversation, I launched three consecutive /boost passes:

  1. Pass 1: /boost Try optimizing Hook Wire memory footprint so that it stays at or below Default
  2. Pass 2: /boost Hook Wire looks great now. Next, analyze whether the static .a Wire mode has room for optimization—strictly confining edits to emdawnwebgpu files without touching Dawn core.
  3. Pass 3 (Cross-Pollination): After asking how the two paths compared and what they could borrow from each other: /boost Apply all of those cross-pollinated optimizations to both .a Wire and Hook Wire.

By dissecting macOS vmmap physical memory snapshots (0x71 WebKit Malloc dirty and VM Compressor SWAPPED pages), /boost engineered and cross-ported 6 high-impact optimizations:

Mermaid Diagram
flowchart TD
    subgraph HookWireOpt ["Hook Wire (JS Interception Layer) Optimizations"]
        H1["1. beginInlineCommand Direct Stream Writes\n0 Closures, 0 Deferred Arrays, 0 Double Copies"]
        H2["2. Skip FinalizationRegistry on Transient Objects\nImmediate UnregisterObject in pass.end / encoder.finish"]
        H3["3. Power-of-2 Bucket Pool for getMappedRange (<=4MB)\n+ In-Place SwapChain GPUTexture/View Reuse"]
    end

    subgraph SharedOpt ["Cross-Pollinated Core Optimizations (Shared Across Hook Wire & .a Wire)"]
        S1["4. Reserve 8-Byte Aligned Header Space (Write logLength=0 at data - 4)\nxhr.send(HEAPU8.subarray) for Zero-Copy WASM Linear Memory Send"]
        S2["5. 120-Frame Sliding-Window Stream Buffer Cap (1M/2M/4M/8M)\nEliminates 500+ 3.3MB Orphan Blocks from Per-Frame 1MB Shrinking"]
        S3["6. Zero-Page-Fault nudgeJSCFullGC on Active Render Frames\nReclaims 400MB+ Dead Unity loader.js Buffers Promoted to JSC Old Gen"]
    end

    subgraph WasmWireOpt [".a Wire (emdawnwebgpu C++ Layer) Optimizations"]
        W1["7. Intrusive Doubly-Linked List Replacing Global _dawn_to_webgpu std::map\nO(1) Object Tracking with Zero Red-Black Tree Node Allocations"]
        W2["8. Pass WGPU_WHOLE_SIZE on Hot Paths to Skip Thousands of Queries\nStack Arrays Replacing Temp std::vectors + Direct Symbol Calls"]
    end

    HookWireOpt --> SharedOpt
    WasmWireOpt --> SharedOpt
  1. 8-Byte Aligned Header Reservation + Zero-Copy HEAPU8.subarray Send (Eliminating the JS Send Buffer & memcpy)
    • Previously, .a Wire serialized commands into a std::vector<char> in C++, and JS allocated a multi-megabyte globalSendBuffer to prepend the 4-byte logLength header and memcpy the entire command stream every frame.
    • Borrowing Hook Wire's single-buffer concept, /boost replaced EmscriptenCommandSerializer's std::vector with an unzeroed std::malloc buffer + cursor mOffset (eliminating vector::resize's memset(0) overhead) and reserved kHeaderOffset = 8 bytes at the front—keeping the command stream 8-byte aligned while leaving [data - 4, data) open for the 4-byte logLength = 0. In library_webgpuwire.js, when logLength === 0, JS writes 0 directly into [data - 4, data) and calls xhr.send(HEAPU8.subarray(data - 4, data + size))—transmitting directly out of WASM linear memory with zero JS buffer allocation and zero memcpy!
  2. 120-Frame Sliding-Window Buffer Capacity (Eliminating 500+ 3.3 MB Orphan Blocks)
    • Why did .a Wire previously have an 800 MB higher peak footprint than Hook Wire in FactoryTraining? Inspecting peak_vmmap_factorytraining_wire.txt revealed over 500 uncollected 3328K (~3.3 MB) blocks inside WebKit Malloc!
    • Because FactoryTraining generates ~3.3 MB of wire commands per frame, and the old code unconditionally shrank the buffer back to 1 MB inside both a microtask and the RAF tail, every single frame triggered a 1 MB -> 4 MB -> 1 MB reallocation churn—spawning 60~72 orphaned 3.3 MB buffers per second! Adopting a 120-frame sliding-window watermark (1MB / 2MB / 4MB / 8MB) kept the buffer steady at 4 MB during rendering, dropping per-frame reallocations to zero.
  3. Deterministic JSC Old Generation Full GC (nudgeJSCFullGC Reclaiming 400 MB+ of Startup Dead Cache)
    • Why did WebContent memory remain high after scene load even though GPU textures were offloaded to the native host?
    • /boost uncovered a subtle JavaScriptCore (JSC) GC interaction: during startup, Unity's loader.js allocates 400 MB+ of .data and .wasm Uint8Array chunks that survive across async streaming reads and get promoted into JSC Old Generation, pushing m_maxHeapSize to ~650 MB. In browser Default mode, WebKit's native C++ WebGPU objects call reportExtraMemoryAllocated, which trips the counter and triggers a Full GC that cleans up those dead startup buffers. In Hook Wire and .a Wire, lightweight JS/WASM handles don't report extra native memory to JSC—leaving 400 MB+ of dead startup buffers stranded in 0x71 WebKit Malloc forever!
    • By adding a zero-page-fault $nudgeJSCFullGC helper (strictly gated on active WebGPU render frames) to advance JSC's extra-memory counter, all 400 MB+ of dead startup cache is deterministically reclaimed right after scene load!
  4. Inline Stream Writing, Immediate UnregisterObject for Transient Handles, and Pooled getMappedRange Staging Buffers
    • Replaced closure-based emitCommand calls in Hook Wire with beginInlineCommand / endInlineCommand direct buffer writes;
    • Skipped FinalizationRegistry registration for transient per-frame objects (CommandEncoder, PassEncoder, CommandBuffer, BindGroup, TextureView), explicitly sending WireCmd.UnregisterObject inside finish() / end() / submit() to prevent hundreds of thousands of GC tokens from piling up in GPU Resident Drawer scenes;
    • Added a power-of-2 bucket pool (<= 4MB) for GPUBuffer.getMappedRange() staging ArrayBuffers and reused SwapChain GPUTexture / GPUTextureView wrappers in-place across frames.
  5. Replacing the Global _dawn_to_webgpu std::map Red-Black Tree with an O(1) Intrusive Doubly-Linked List
    • Inside lib_webgpu_emdawnwebgpu.cpp, /boost embedded prev / next pointers directly into struct _WGpuObject and deleted the global _dawn_to_webgpu std::map red-black tree, turning every object creation, lookup, and destruction into an O(1) operation with zero heap node allocations, while passing WGPU_WHOLE_SIZE on hot paths to eliminate thousands of cross-boundary wgpuBufferGetSize calls per frame.

3. Comprehensive Before & After Benchmark Results Across All 5 Scenes

Here is the final automated benchmark comparison across all 5 Unity 3D scenes × 3 modes on Apple Silicon (from webgpu_all_scenes_benchmark_report.md):

SceneModePre-Optimization Steady Memory / FPSPost-Optimization Steady Memory (WebContent)Post-Optimization Steady FPSHost Leaks (leaks)Net Improvement (vs. Pre-Opt & vs. Browser Default)
FactoryTraining
(Heavy URP Industrial Scene)
Default (WebKit)4.3 GB / 24.7 FPS4.3 GB (Peak 4.5 GB)24.7 FPS (40.49 ms)0 leaksBrowser native baseline
FactoryTrainingHook Wire5.0 GB / 35.3 FPS2.7 GB (Peak 3.2 GB)37.4 FPS (26.74 ms)0 leaks (0 B)Memory slashed by -2.3 GB (-46%), 1.6 GB below Default, FPS +51.4%
FactoryTraining.a Wire2.4 GB (Peak 3.9G) / 35.1 FPS2.2 GB (Peak 3.6 GB)40.9 FPS (24.45 ms)0 leaks (0 B)2.1 GB (-48.8%) below Default, FPS +65.6% faster than Default
Garden
(UniversalSample)
Default (WebKit)3.1 GB / 72.0 FPS3.1 GB (Peak 3.9 GB)72.0 FPS (13.89 ms)0 leaksBrowser native baseline
GardenHook Wire4.1 GB / 72.0 FPS2.5 GB (Peak 3.3 GB)72.0 FPS (13.89 ms)0 leaks (0 B)Memory slashed by -1.6 GB (-39%), 600 MB below Default
Garden.a Wire3.8 GB (Initial 4.4 FPS)2.3 GB (Peak 3.8 GB)72.0 FPS (13.89 ms)0 leaks (0 B)FPS jumped from 4.4 to locked 72 FPS, 800 MB below Default
Oasis
(UniversalSample)
Default (WebKit)3.1 GB / 72.0 FPS3.1 GB (Peak 4.0 GB)72.0 FPS (13.89 ms)0 leaksBrowser native baseline
OasisHook Wire3.4 GB / 72.0 FPS2.6 GB (Peak 3.3 GB)72.0 FPS (13.89 ms)0 leaks (0 B)Memory reduced by -800 MB, 500 MB below Default
Oasis.a Wire2.9 GB / 72.0 FPS2.2 GB (Peak 3.9 GB)72.0 FPS (13.89 ms)0 leaks (0 B)Memory reduced by -700 MB, 900 MB (-29%) below Default
CockpitDefault / Hook / Wire733M / 749M / 695M733M / 653.9M / 657.5MLocked 72.0 FPS0 leaks (0 B)Both Wire modes ~80 MB below Default
TerminalDefault / Hook / Wire1.2G / 1.3G / 1.2G1.2G / 1.1G / 1.1GLocked 72.0 FPS0 leaks (0 B)Both Wire modes reduced to 1.1 GB

Across all 5 benchmarks, both zero-intrusion Hook Wire and statically linked .a Wire now consume strictly less WebContent physical memory than browser-native Default mode (saving up to 2.1 GB ~ 2.3 GB), while outperforming native browser WebGPU frame rates by 51% to 65% in heavy GPU-driven scenes!

---

5. Summary & Practical Advice: A Candid Note on Token Consumption

Looking back at how Antigravity powered this entire engineering effort, three takeaways stand out:

1. Define Clear Guardrails (AGENTS.md & Skills), Then Let Multi-Agent Gates Enforce Them

Frontier models like Gemini 4 Argon (and Gemini 3.8 Flash before it) thrive when given crisp invariants and automated yardsticks. In NoGraphicsAPI, AGENTS.md defines non-negotiable rules (zero STL headers, -fno-exceptions -fno-rtti, pass Span by value, zero shader macros); in GFX_Runtime, our /webgpu-benchmarker skill provides deterministic two-pass telemetry. Armed with those specifications, /teamwork-preview's Reviewers, Challengers, and Forensic Auditors act as relentless gatekeepers that refuse to let shortcuts slip through.

2. The Golden Workflow Formula: /teamwork-preview for Implementation + /boost for Triage & Tuning

  • When building a complex new feature, backend, or cross-repo refactor: Reach for /teamwork-preview. Let the multi-agent team decompose milestones, write a 4-tier E2E suite, and hammer the implementation through red-vs-blue gate iterations before handing you a VICTORY CONFIRMED build;
  • When you spot a subtle bug, want a cleaner architectural solution, or need to squeeze out extra FPS and memory: Call /boost right inside the same conversation. Let specialist subagents run sample, vmmap, disassembly, and protocol diffs to solve the problem with hard evidence.
  • Because both run as Subagents, your main conversation stays completely free of build log spam—allowing you to drive an entire multi-week engineering arc inside a single chat window.

3. ⚠️ A Candid Reminder on Compute & Token Costs

Finally, a practical heads-up: the reliability of /teamwork-preview and the depth of /boost come from trading massive parallel compute and long reasoning chains for code quality—which means both workflows are heavy token consumers!
  • A single mid-to-large /teamwork-preview run routinely spawns 20 to 40 subagents (Orchestrator, Explorers, Workers, multiple 5-agent Gate Committees, and an independent Victory Auditor), consuming dozens of times more tokens than a standard single-agent turn;
  • /boost likewise burns through substantial reasoning tokens when dissecting gigabyte-scale vmmap dumps, disassembling binaries, and running full-suite benchmark verifications.

I personally use the Google AI Ultra ($200/month) subscription tier, which provides the generous quota needed to chain /teamwork-preview and /boost back-to-back without worrying about rate limits. If you are on a tighter token budget, I recommend handling routine edits directly in the main chat, reserving /teamwork-preview for foundational feature implementation and /boost for tough architectural bugs or high-value performance bottlenecks—deploying your heaviest artillery where it counts the most.

Read this article in another language:
Seto
WebGPUWGSLCompute ShadersReal-time Graphics

Article Discussion & Comments

0

Sign in to Join the Discussion

Welcome to the discussion. Anyone can register freely to engage with graphics authors and engineers.

Loading comments...