Tomek Czajecki's Avatar

Tomek Czajecki

@tchayen.com

EM @expo.dev working on EAS product infrastructure I blog about my hobbies – a mix of graphics programming and gamedev – see tchayen.com

905
Followers
212
Following
110
Posts
05.05.2023
Joined
Posts Following

Latest posts by Tomek Czajecki @tchayen.com

This sounds exciting! I am sad I will miss FF this year (conflicts with App.js)

23.05.2025 15:07 👍 3 🔁 0 💬 1 📌 0

I am very curious about all things optimization. How you optimized the library, what you optimized, how you measured performance, how you knew what bets to take. What techniques you used.

14.05.2025 12:50 👍 4 🔁 0 💬 0 📌 0

I appreciate when computer says please and thank you

14.05.2025 09:37 👍 2 🔁 0 💬 0 📌 0

I will be there too! Excited to see everyone in person!

13.05.2025 14:44 👍 3 🔁 0 💬 1 📌 0

Yesss

08.05.2025 18:59 👍 2 🔁 0 💬 0 📌 0

tchayen.com

Programming, gamedev, reinventing things from scratch, maths (computational geometry), lots of research

06.05.2025 22:34 👍 2 🔁 0 💬 0 📌 0

Then every couple months I ask ChatGPT deep research to find something. And it works great so far! I often end up on exact store page where I just have to make an order and I am done.

05.05.2025 14:47 👍 5 🔁 0 💬 0 📌 0

A use case for LLMs where they shine the most for me is doing research for non-urgent online shopping.

Sometimes I have very specific requirements, like Japanese rice cooker that cooks rice for a single person not a village and ships to Finland. Or a 5K IPS screen, ideally >60Hz

05.05.2025 14:47 👍 7 🔁 0 💬 1 📌 0

For me it's usually for simulations where low level code with manual memory control makes a difference between unusable and real time.

Not long ago I played with triangulations: tchayen.com/handmade-pat...

For the same data, the most optimized JS code I could write took 900ms, Zig version 25ms.

05.05.2025 12:02 👍 3 🔁 0 💬 0 📌 0
Preview
GitHub - tchayen/zig-wasm-hmr: Example setup of HMR of Zig WASM module with Vite Example setup of HMR of Zig WASM module with Vite. Contribute to tchayen/zig-wasm-hmr development by creating an account on GitHub.

Repo with this example here: github.com/tchayen/zig-...

05.05.2025 11:43 👍 1 🔁 0 💬 0 📌 0
/// <reference types="vite/client" />
  
let wasm: {
  exports: {
    version: () => number;
  };
  memory: WebAssembly.Memory;
};

async function loadWasm() {
  const init = (await import("./bin/lib.wasm?init")).default;
  wasm = (await init()) as typeof wasm;
  console.log(wasm.exports.version());
}

loadWasm();

if (import.meta.hot) {
  import.meta.hot.accept("./bin/lib.wasm?init", () => {
    console.log("🔄 WASM rebuilt, re-loading…");
    loadWasm();
  });
}

console.log(new Date());

/// <reference types="vite/client" /> let wasm: { exports: { version: () => number; }; memory: WebAssembly.Memory; }; async function loadWasm() { const init = (await import("./bin/lib.wasm?init")).default; wasm = (await init()) as typeof wasm; console.log(wasm.exports.version()); } loadWasm(); if (import.meta.hot) { import.meta.hot.accept("./bin/lib.wasm?init", () => { console.log("🔄 WASM rebuilt, re-loading…"); loadWasm(); }); } console.log(new Date());

And this is all it took on the JS side.

05.05.2025 11:43 👍 2 🔁 0 💬 1 📌 0
function zigWasmPlugin() {
  const zigDir = path.resolve(__dirname, "zig");

  return {
    name: "zig-wasm-watch",
    configureServer(server) {
      server.watcher.add(zigDir);
      server.watcher.on("change", (file) => {
        console.log(file, "changed");
        if (file.startsWith(zigDir)) {
          exec("npm run wasm", (_err, _stdout, stderr) => {
            console.error(stderr);
          });
        }
      });
    },

    handleHotUpdate({ file, server }) {
      if (file.endsWith(".wasm")) {
        const mods = server.moduleGraph.getModulesByFile(file);
        if (mods && mods.size) {
          return [...mods];
        }
      }
    },
  };
}

function zigWasmPlugin() { const zigDir = path.resolve(__dirname, "zig"); return { name: "zig-wasm-watch", configureServer(server) { server.watcher.add(zigDir); server.watcher.on("change", (file) => { console.log(file, "changed"); if (file.startsWith(zigDir)) { exec("npm run wasm", (_err, _stdout, stderr) => { console.error(stderr); }); } }); }, handleHotUpdate({ file, server }) { if (file.endsWith(".wasm")) { const mods = server.moduleGraph.getModulesByFile(file); if (mods && mods.size) { return [...mods]; } } }, }; }

I have a 'wasm' command declared in package.json which compiles the binary and places it in web/bin. Plugin is listening for changes in zig/ and runs that command. Finally handleHotUpdate() notices that a *.wasm file changed and sends HMR to the browser.

05.05.2025 11:43 👍 1 🔁 0 💬 1 📌 0
Screenshot of the browser demonstrating HMR reload of the WASM module.

Screenshot of the browser demonstrating HMR reload of the WASM module.

I don't know how I survived this long recompiling WASM binary after every change but I finally wrote a mini Vite plugin for HMR.

Now when I change anything and save the file, WASM module is automatically compiled and reloaded.

05.05.2025 11:43 👍 7 🔁 0 💬 2 📌 0

Wow! Excited about this

30.04.2025 09:21 👍 2 🔁 0 💬 0 📌 0

It's crazy how Cursor packs two opposite user experiences in one app. Tab autocomplete is reading my mind, while chat agent mode feels like trying to get the dumbest coder I have ever met to fix my code without giving him ability to run it.

25.04.2025 20:59 👍 4 🔁 0 💬 0 📌 0

I am slightly biased but this blogpost is great

22.04.2025 20:52 👍 6 🔁 0 💬 0 📌 0

Killer feature, would download

20.04.2025 14:17 👍 2 🔁 0 💬 0 📌 0
Post image

⚙️ Over-the-air updates made easy by @expo.dev team! Learn the ins and outs of EAS Update, including native fingerprints, preview deployments, and the latest JS API features at the App.js 2025 workshop.

🎟️ appjs.co/tickets#Work...

03.04.2025 13:18 👍 15 🔁 2 💬 1 📌 1

My watch told me my sleep goal was met but then I checked the app and turns out it included yesterday evening nap. Well, explains why I don't feel like my sleep goal was met

31.03.2025 09:20 👍 3 🔁 0 💬 0 📌 0

Great point! I can fix that

27.02.2025 22:16 👍 0 🔁 0 💬 0 📌 0

Thank you! It means a lot coming from you

27.02.2025 21:34 👍 1 🔁 0 💬 0 📌 0

Let me know your thoughts! I made so much progress this time to the point that I'd rather delete the last year's one. Feels completely surface-level in comparison 😅

27.02.2025 20:32 👍 1 🔁 0 💬 2 📌 0

But end of Feb 23 what timezone? CET? PT? You might be several hours late if you send at midnight your time!

22.02.2025 15:43 👍 2 🔁 0 💬 2 📌 0

That’s true. That’s also the case with the engine Sebastian Aaltonen is working on – they don’t use textures yet.

I read that some WebGPU contributors want to make bindless finally happen but that probably means it’s more than a year away.

22.02.2025 01:54 👍 0 🔁 0 💬 1 📌 0
REAC 2023 DAY 1 Modern Mobile Rendering @ HypeHype
REAC 2023 DAY 1 Modern Mobile Rendering @ HypeHype YouTube video by Rendering Engine Architecture Conference

Everything needed to re-create it can be found in this talk: www.youtube.com/watch?v=m3bW...

21.02.2025 22:52 👍 3 🔁 0 💬 1 📌 0
WASM Draw Stream

Check it yourself here: wasm-draw-stream.expo.app. Runs in 250fps on M3 Air. 120fps on Samsung Galaxy S25.

Requires WebGPU so it won't run on iPhones.

21.02.2025 22:52 👍 3 🔁 0 💬 1 📌 0
Video thumbnail

I was working on a WebGPU demo and decided to try how fast I can make it. Zig in WASM generates a buffer with command stream sorted to minimize GPU state changes.

This is 10k individual draw calls, unoptimized, no instancing, no render bundles. Every object is controlled separately.

21.02.2025 22:52 👍 12 🔁 1 💬 1 📌 0
Video thumbnail

Asked gemini for WebGPU setup with several cylinder models and orbiting camera. Got interstellar scene (unfortunately had to first spend 15 minutes to fix it).

11.02.2025 00:28 👍 7 🔁 0 💬 0 📌 0

Many of us from @expo.dev will be there

08.02.2025 13:02 👍 6 🔁 0 💬 1 📌 0

Friday is the day of hard decisions: which food that makes my tummy hurt should I order.

Today it will be… drumroll 🥁 … chicken wings

07.02.2025 19:29 👍 5 🔁 0 💬 0 📌 0