Sign in

Tomek Czajecki

@tchayen.com
940 followers 213 following 110 posts

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

PostsRepliesMedia
Tomek Czajecki @tchayen.com · 23/05/2025
This sounds exciting! I am sad I will miss FF this year (conflicts with App.js)
130
Tomek Czajecki @tchayen.com · 14/05/2025
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.
040
Tomek Czajecki @tchayen.com · 14/05/2025
I appreciate when computer says please and thank you
020
Tomek Czajecki @tchayen.com · 13/05/2025
I will be there too! Excited to see everyone in person!
120
Tomek Czajecki @tchayen.com · 08/05/2025
Yesss
010
Tomek Czajecki @tchayen.com · 06/05/2025
tchayen.com Programming, gamedev, reinventing things from scratch, maths (computational geometry), lots of research
020
Tomek Czajecki @tchayen.com · 05/05/2025
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.
050
Tomek Czajecki @tchayen.com · 05/05/2025
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
170
Tomek Czajecki @tchayen.com · 05/05/2025
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.
030
Tomek Czajecki @tchayen.com · 05/05/2025
Repo with this example here: github.com/tchayen/zig-...
github.com
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.
010
Tomek Czajecki @tchayen.com · 05/05/2025
And this is all it took on the JS side.
/// <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());
120
Tomek Czajecki @tchayen.com · 05/05/2025
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.
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];
        }
      }
    },
  };
}
110
Tomek Czajecki @tchayen.com · 05/05/2025
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.
Screenshot of the browser demonstrating HMR reload of the WASM module.
270
Tomek Czajecki @tchayen.com · 30/04/2025
Wow! Excited about this
020
Tomek Czajecki @tchayen.com · 25/04/2025
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.
040
Tomek Czajecki @tchayen.com · 22/04/2025
I am slightly biased but this blogpost is great
060
Tomek Czajecki @tchayen.com · 20/04/2025
Killer feature, would download
020
Reposted by Tomek Czajecki
Software Mansion @swmansion.com · 03/04/2025
⚙️ 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...
1152
Tomek Czajecki @tchayen.com · 31/03/2025
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
030
Tomek Czajecki @tchayen.com · 27/02/2025
Great point! I can fix that
000
Tomek Czajecki @tchayen.com · 27/02/2025
Thank you! It means a lot coming from you
010
Tomek Czajecki @tchayen.com · 27/02/2025
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 😅
210
Tomek Czajecki @tchayen.com · 22/02/2025
But end of Feb 23 what timezone? CET? PT? You might be several hours late if you send at midnight your time!
220
Tomek Czajecki @tchayen.com · 22/02/2025
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.
100
Tomek Czajecki @tchayen.com · 21/02/2025
Everything needed to re-create it can be found in this talk: www.youtube.com/watch?v=m3bW...
youtube.com
REAC 2023 DAY 1 Modern Mobile Rendering @ HypeHype
YouTube video by Rendering Engine Architecture Conference
130
Tomek Czajecki @tchayen.com · 21/02/2025
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.
wasm-draw-stream.expo.app
WASM Draw Stream
130
Tomek Czajecki @tchayen.com · 21/02/2025
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.
1121
Tomek Czajecki @tchayen.com · 11/02/2025
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).
070
Tomek Czajecki @tchayen.com · 08/02/2025
Many of us from @expo.dev will be there
160
Tomek Czajecki @tchayen.com · 07/02/2025
Friday is the day of hard decisions: which food that makes my tummy hurt should I order. Today it will be… drumroll 🥁 … chicken wings
050
Tomek Czajecki @tchayen.com · 03/02/2025
I learned two main things from this: 1) Don't wait until you are ready to start. You most likely have a very wrong idea what it takes and you wouldn't be able to get ready anyway. 2) Similarly, finishing something teaches you way more than any amount of unfinished attempts.
040
Tomek Czajecki @tchayen.com · 03/02/2025
Perfectionist me would love to see my blog read uniformly like a book. But that would mean I didn't improve at all and I am very proud of the progress I made since I started this blog 6 years ago.
130
Tomek Czajecki @tchayen.com · 03/02/2025
But I am keeping them all. They are a reminder that back then they were the best thing I could produce. And without getting them through the finish line, I wouldn't improve and wouldn't be able to write ones I can write now.
120
Tomek Czajecki @tchayen.com · 03/02/2025
Writing a blog over a span of several years is a great practice in fighting perfectionism. I hate most of my old blogposts. The problems I was solving were poorly defined, approach badly explained. The scope so small that I wouldn't bother posting about it now.
1130
Tomek Czajecki @tchayen.com · 02/02/2025
Still wouldn't use it in JS/TS because of conventions, but I am enjoying a lot my Zig code being easier to read
030
Tomek Czajecki @tchayen.com · 31/01/2025
Love the assertions! My code is also full of them
020
Tomek Czajecki @tchayen.com · 31/01/2025
Wow, not even origin point? I am using (origin, twin, next) to store the whole triangulation mesh, skipping face because every triangle is implicit (edge == edge->next->next->next)
110
Tomek Czajecki @tchayen.com · 29/01/2025
Me: I don't need half-edge for this. It's too complex for what I need to keep. Also me: * proceeds to incrementally reinvent half-edge as the project progresses *
240
Tomek Czajecki @tchayen.com · 29/01/2025
Recently Arc started randomly changing window size and now all the open non-pinned tabs went blank and don't refresh. How does unmaintained software get more buggy over time lol.
130
Tomek Czajecki @tchayen.com · 28/01/2025
This looks sooooo good. Is it bezier or some arc?
110
Tomek Czajecki @tchayen.com · 27/01/2025
Just copied some code from GitHub for a change, not from LLM. Someone tested it, ran who knows how many times and even wrote unit tests. Worked on the first try. Incredible feeling. I already miss it.
050
Tomek Czajecki @tchayen.com · 27/01/2025
Uhhh… hours_wasted_because_my_struct_was_stack_allocated_and_should_have_been_on_heap += 3. I was sitting with debugger staring at two memory regions and pulling my hair wondering why one and changes one doesn’t. Having code run orders of magnitude faster than equivalent JS comes at a price…
040
Tomek Czajecki @tchayen.com · 26/01/2025
First one says: this function in the end splits into two execution branches. Both are expected and likely to happen. Second: there's an edge case that we handle early and then there's the main flow. We focus on the latter. I hope this makes it clear that they are very much not the same!
140
Tomek Czajecki @tchayen.com · 26/01/2025
if (...) { ...; return ...; } else { ...; return ...; } and if (...) { return ...; } ...; return ...; syntactically mean the same thing but send different message.
130
Tomek Czajecki @tchayen.com · 26/01/2025
I am trying Biome on some side projects and loving it so far. Happily haven't had to touch the default config yet, but forcing me to omit else when there are earlier returns is just plain wrong.
120
Tomek Czajecki @tchayen.com · 23/01/2025
Every time I am in the US I go to Dunkin after arriving. I don't look for it, it's just there, sooner than I can remember about it.
010
Tomek Czajecki @tchayen.com · 22/01/2025
I did something like this… 10 years ago in 400 lines of C++. As long as you fit your graphics in a single large texture, expect to be able to render 10k+ moving rectangles in 60FPS. Anything less means the phone is busy with the wrong kind of work github.com/tchayen/2d-o...
github.com
GitHub - tchayen/2d-opengl-rendering: Minimal, fast OpenGL renderer for 2D sprites
Minimal, fast OpenGL renderer for 2D sprites. Contribute to tchayen/2d-opengl-rendering development by creating an account on GitHub.
120
Tomek Czajecki @tchayen.com · 22/01/2025
There’s a high chance it will work. In the end it’s just an abstraction on top of exactly the same thing. Haven’t used it myself though.
120
Tomek Czajecki @tchayen.com · 22/01/2025
Nothing will beat performance of doing it GPU friendly way! I think PNG texture atlas and a WebGPU-based renderer is the way to go. I can help with this if you want!
140
Tomek Czajecki @tchayen.com · 21/01/2025
When you are working on computational geometry problem using half-edge data structure, every problem is an edge case
080