ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
GPU-powered interactive science simulations, running in the browser on WebGPU.
Built with Next.js 16 (App Router, Turbopack), React 19, Tailwind 4 and vgpu.
The catalog in src/lib/subjects.ts lists many more planned simulations (marked "Coming Soon").
See docs/ROADMAP.md for the improvement plan.
You need a browser with WebGPU (recent Chrome, Edge or Safari). Without it, simulation pages show an
explanatory message instead of a blank canvas.README 전문 보기 ↗GPU-powered interactive science simulations, running in the browser on WebGPU. Built with Next.js 16 (App Router, Turbopack), React 19, Tailwind 4 and vgpu.
| Simulation | Subject | GPU technique |
|---|---|---|
| Wave Interference & Diffraction | Physics | Fragment shader; Huygens–Fresnel slits as phasor sums |
| N-Body Orbital Mechanics | Physics | Tiled all-pairs gravity compute shader (up to 16 384 bodies), leapfrog integrator, instanced rendering |
| Double Pendulum Chaos | Physics | One RK4 compute kernel for every view: a 32-bit GPU crowd of up to 10 000 pendulums against a 64-bit CPU pair, and a flip-time fractal of up to 1024² pendulums (one per pixel) |
| Axons & Nerves | Biology | Hodgkin–Huxley cables, one GPU invocation per fibre solving its tridiagonal system implicitly (Thomas algorithm); a nerve of up to 1 000 fibres and its compound action potential |
| Hodgkin–Huxley Neuron | Biology | Compute shader integrates the ODEs; fragment shader plots the traces |
| Cellular Automata | Computer Science | Ping-pong compute shader over grids up to 2048²; a reduction shader counts and fingerprints every generation; pan/zoom renderer |
| How AI Learns | Computer Science | A neural network trained on the GPU: forward, backpropagation, gradient and momentum-SGD kernels over the whole mini-batch (deterministic, no atomics); a live decision map and every neuron's own map; real handwritten digits (MNIST) with a draw pad |
The catalog in src/lib/subjects.ts lists many more planned simulations (marked "Coming Soon").
See docs/ROADMAP.md for the improvement plan.
pnpm install
pnpm dev # http://localhost:3000
You need a browser with WebGPU (recent Chrome, Edge or Safari). Without it, simulation pages show an explanatory message instead of a blank canvas.
This repo uses a newer Next.js than most training data covers — see
AGENTS.mdand readnode_modules/next/dist/docs/before changing framework-level code.
| Command | What it does |
|---|---|
pnpm lint | ESLint |
pnpm typecheck | next typegen (route types) + tsc --noEmit |
pnpm test | Vitest: pure logic and headless-GPU tests of every shader |
pnpm check:wgsl | Validates every .wgsl file against a real WebGPU device (next build does not) |
pnpm build | Production build (all simulation routes are statically generated) |
pnpm smoke | Browser smoke test of a running server (BASE_URL=http://localhost:3000) |
pnpm e2e | Full browser suite (86 scenarios: every sim, URL state, measurement tools, challenges, shortcuts, no-WebGPU, phone) against BASE_URL. Works on pnpm start, pnpm dev with E2E_DEV=1 (React strict mode; skips size budgets) and a static export. E2E_GREP=<regex> runs only the scenarios whose name matches |
pnpm smoke:local | Builds, serves on a spare port, runs the smoke test, stops the server |
pnpm export | Fully static offline build in out/ — serve with any static file server, no Node or internet |
pnpm verify | lint → typecheck → test → check:wgsl → build |
pnpm install enables .githooks/pre-push, which runs pnpm verify before every push so a broken build
never reaches GitHub (GitHub Actions may be unavailable). Bypass in an emergency with git push --no-verify.
pnpm test and pnpm check:wgsl need a WebGPU adapter. On a machine without one (containers, CI):
npx vgpu install-software-renderer # one-off: downloads a CPU Vulkan renderer
REQUIRE_GPU=1 pnpm test # REQUIRE_GPU makes a missing adapter a failure instead of a skip
src/
app/
page.tsx landing page, grouped by subject
[subject]/[sim]/page.tsx the single simulation route (generateStaticParams, 404 for the rest)
components/ SimLayout, ParameterSlider, SimCard, GpuStatusOverlay
lib/
subjects.ts simulation catalog (single source of truth)
gpu/runtime.ts WebGPU lifecycle: init, surface, clock, safe teardown
gpu/useGpuSim.ts React hook wrapping the runtime
simulations/
loaders.tsx sim id -> lazily loaded, client-only component
<subject>/<sim>/
sim.ts creates the GPU resources and the frame loop; returns a handle
controls.tsx React UI built on SimLayout + useGpuSim
*.wgsl shaders, loaded through vgpu's bundler loader
usePersistedParams(simId, schema, defaults) keeps settings in the URL (and, as a fallback,
localStorage). Schemas in lib/urlState.ts clamp/validate everything, so a bad link can't break a sim.SimLayout: copy link, save image, reset to defaults, keyboard shortcuts (Space, ., R, ?) and an
optional Challenges tab. On phones the sidebar is a bottom drawer (peek / half / full) with Play always in reach.summary to SimLayout (one sentence on what the canvas shows, announced through a
throttled polite live region), use usePlaying(sim, autoplay) so a sim starts paused under reduced motion,
and keep every simulation page clean in the axe audit (pnpm e2e checks desktop and phone).lib/gestures.ts turns two-finger input into pan and pinch-zoom steps; canvases with a view (Cellular
Automata, N-body) apply them, and keep one finger for their own tool.lib/challenges.ts format (predict → set up → goal check → explanation), rendered by
ChallengesPanel. See challenges.ts next to each simulation. Each has a test that its setup does not already
solve it, that the intended answer does, and that obvious shortcuts do not.wave.ts, hh.ts, life.ts) used for graphs,
readouts and tests, and a GPU test proving the two agree. MiniChart is a small SVG chart for readouts like the
firing-rate curve and the population graph.gravity.wgsl sums softened gravity over all pairs in 64-body tiles of workgroup memory, integrate.wgsl
does leapfrog (or Euler, for the numerics lesson). engine.ts is the GPU physics without drawing, shared by the sim
and the GPU tests; renderer.ts copies positions into vertex buffers (vertex shaders may not read storage buffers
on compatibility-mode devices) and draws instanced discs and fading trails. Energies, orbital elements and measured
periods come from small read-backs, sampled every ≤ 16 steps so fast planets are never aliased. The orbit lab's
units are AU, years and solar masses (G = 4π²), so Earth's period is exactly 1 year.pendulum.ts is the 64-bit twin (equations of motion, RK4/Euler, energy, flips, the energy
boundary, normal modes, the spread and its growth rate λ); turns states into readouts, shared by the sim
and the challenge tests. The Pendulum view and the measured Butterfly pair are integrated on the CPU in 64-bit (two
pendulums cost nothing, and 32-bit floats cannot even store a 10⁻⁹ rad nudge near 2 rad), and only drawn by the GPU;
the Butterfly crowd ( keeps its 32-bit starts distinct) and the Fractal run on the GPU.
The fractal is seeded on the GPU (), coloured by straight from the flip-time buffer, and
the cursor readout copies out a single pixel instead of reading the map back.A compact editorial layout (about one screen on a desktop, 1.35 on a phone): numbered plates for the working
simulations (one row that scrolls sideways with snap: four at a time on a desktop, a swipe on a phone) and a typographic index of the planned ones. Design tokens (colours, type scale, motion) live in
src/app/globals.css; components in src/components/home/. The plan and measurements are in
docs/HOMEPAGE-PLAN.md.
pnpm posters builds, serves, drives
each simulation from fixed settings, reads only the canvas pixels, and writes public/plates/<id>.webp plus the
social-preview image src/app/opengraph-image.jpg. Re-run it after changing how a simulation looks.simulations/previews.ts, loaded only then). Rules, in components/home/intent.ts: one live plate at a time;
never on touch, with prefers-reduced-motion or without WebGPU; stops when scrolled out of view or the tab is
hidden; a GPU failure leaves the poster. The home page uses no GPU until the visitor shows intent.pnpm e2e): ≤ 1.15 screens tall on desktop, ≤ 1.4 on a phone, no horizontal overflow,
JavaScript ≤ 470 KB (the React + Next runtime is ~457 KB of that), HTML ≤ 14 KB gzipped, zero axe violations.Simulations run through a paced render loop (ctx.loop): it skips ticks while the GPU is still busy, so a slow
device never builds a backlog (Pause/sliders stay responsive), and a governor (lib/gpu/pacing.ts) lowers the
canvas resolution — down to 35% — when frames cost too much, raising it again only when the predicted cost fits.
A badge shows when resolution is reduced. To pin full resolution (projector, screenshots), run
localStorage.setItem("edusim:quality", "full") in the browser console.
src/simulations/<subject>/<id>/ with *.wgsl, sim.ts (a SimFactory that returns a handle with
dispose()), and controls.tsx (default export; use useGpuSim(factory) and SimLayout).implemented: true for it in src/lib/subjects.ts, with a tagline and posterAlt.src/simulations/loaders.tsx and add its home-page preview to src/simulations/previews.ts.pnpm posters to generate its plate poster (add its capture settings to scripts/make-posters.mjs).src/lib/subjects.test.ts fails if the catalog and the loaders disagree. Put pure logic in its own module
(see hh.ts, rules.ts) so it can be unit-tested, and add a headless-GPU test for any new shader in
src/simulations/gpu-shaders.test.ts.
launchSim / useGpuSim. Teardown must be synchronous and
safe at any point, which is what makes React strict mode (double mount) leak-free.frameDelta(ctx.clock)), never a fixed per-frame increment, so speed does not
depend on the display refresh rate.set(): the first call for a struct must include every member; later calls may send a subset.meta; pnpm check:wgsl will tell you.measure.tscrowdAnglespendulum.wgslseed.wgslfractal.wgslcable.ts is the 64-bit twin: HH membranes (shared with the neuron sim) joined into
compartments, a bare axon in equal compartments or a myelinated one as nodes of Ranvier and internodes (myelin
thickness ∝ diameter, nodes ~1 µm: Rushton's similarity, so speed ∝ diameter). Each step relaxes the gates, then
solves the voltages implicitly along the fibre (conductances linearised, Thomas algorithm): an explicit step would
need Δt < 0.004 ms for the squid axon. cable.wgsl runs one fibre per invocation for many steps per dispatch and
writes the kymograph, two electrode traces and each fibre's extracellular signal into one output buffer (four
storage buffers in all, within compatibility-mode limits); cap.wgsl sums the signals into the compound action
potential. Tested: HH 1952's 18.8 m/s (within 2 %), √d for bare and ∝ d for myelinated fibres, annihilation,
refractoriness, TTX/lidocaine and demyelination block, heat block.net.ts is the 64-bit twin (layout, activations, cross-entropy, backpropagation checked against
centred finite differences, momentum SGD with L2, seeded initialisation, the datasets and the batch order, the step
probe). mlp.wgsl trains one mini-batch step as a fixed sequence of dispatches (a forward pass per hidden layer, the
output layer with its softmax or sigmoid, a backward pass per hidden layer, one gradient and one update over every
parameter); every sum runs in a fixed order, so 20 GPU steps match 20 twin steps on the same batches. eval.wgsl
evaluates thousands of samples at once in private memory, also along the last step (w + (s − 1)·(−η·v), which is the
step probe); boundary.wgsl computes the decision map and each hidden neuron's map into a buffer that
playground.wgsl draws; the weights reach links.wgsl as a vertex buffer copied layer by layer. The digits are a
10 000 + 2 000 subset of MNIST (Yann LeCun, Corinna Cortes, Christopher Burges; CC BY-SA 3.0), built by
scripts/build-digits.mjs into public/data/mnist-12k.dat (gzip, 1.9 MB) and stored on the GPU four pixels per word.count.wgsl reduces the grid to a live-cell count and an order-independent
fingerprint every generation (into a 1024-slot ring buffer); sim.ts reads it back at most every 100 ms and
tracker.ts classifies the history (extinct / still life / oscillator with period / moving pattern). It only runs
when a host passes onStats, so the home-page preview pays nothing. A shared link reproduces the rules, grid,
speed, colours and the starting pattern (a library pattern, random soup or empty grid) — not hand-drawn cells.