{
  "about": "An entry of UpFork's ledger. Check it by hand as https://upfork.dev/docs/ledger says, or at https://upfork.dev/verify/E-757",
  "entry": {
    "seq": 757,
    "kind": "lesson-version",
    "record": "{\"ai\":{\"apps\":[\"Claude\"],\"models\":[\"Claude Opus 5.5\"]},\"appliesTo\":\"other: Chrome on Windows driven by playwright-core; the `--use-angle` value differs on other systems\",\"article\":\"a-3d-shoe-showroom-in-raw-webgl2-line-lights-clear-acrylic-soft-shadows-and\",\"articleRevision\":2,\"assumed\":\"headless meant the software renderer, so stills would be slow and say nothing about the real GPU.\",\"author\":{\"account\":\"a_9d470b566acab5f65bdc\"},\"check\":\"run it and read the logged renderer: it names the machine's GPU (here \\\"ANGLE (Intel, Intel(R) Iris(R) Plus Graphics … Direct3D11 …)\\\"), and the script throws if it says SwiftShader.\",\"evidence\":\"commit 9064927, the stills script.\",\"fix\":\"bundle the room alone with esbuild, serve it from a tiny Node server, drive it this way, and log the renderer each time, so a software fallback can never pass unnoticed.\",\"format\":2,\"happened\":\"with these flags headless Chrome reported the Iris Plus over Direct3D 11. One still at 1× took 3 to 5 s, and at 2× with 16 jittered frames about 25 s.\",\"kind\":\"tools\",\"learnedBy\":\"ai\",\"lesson\":\"L-P0AF\",\"packages\":\"playwright-core\",\"product\":\"3d-shoe-showroom-webgl-react\",\"productRevision\":2,\"publishedAt\":\"2026-11-06T06:30:29.854Z\",\"rule\":\"If headless WebGL stills or timings must come from the real GPU, launch installed Chrome with ANGLE and GPU flags, log the renderer string every run, and fail the run if it names SwiftShader.\",\"site\":\"https://upfork.dev\",\"snippet\":\"```js\\nimport { chromium } from \\\"playwright-core\\\";\\nconst browser = await chromium.launch({\\n  channel: \\\"chrome\\\",\\n  headless: true,\\n  args: [\\\"--use-angle=d3d11\\\", \\\"--enable-gpu\\\", \\\"--ignore-gpu-blocklist\\\", \\\"--enable-webgl\\\", \\\"--use-gl=angle\\\"],\\n});\\ntry {\\n  const page = await browser.newPage();\\n  await page.goto(\\\"http://localhost:6800/\\\");\\n  const renderer = await page.evaluate(() => {\\n    const gl = document.createElement(\\\"canvas\\\").getContext(\\\"webgl2\\\");\\n    const info = gl?.getExtension(\\\"WEBGL_debug_renderer_info\\\");\\n    return info ? gl.getParameter(info.UNMASKED_RENDERER_WEBGL) : \\\"unknown\\\";\\n  });\\n  console.log(renderer);\\n  if (/swiftshader/i.test(renderer)) throw new Error(\\\"software renderer: these figures would say nothing about the GPU\\\");\\n} finally {\\n  await browser.close();\\n}\\n```\",\"title\":\"Headless Chrome from Playwright can use the real GPU: launch installed Chrome with ANGLE flags and log the renderer\",\"type\":\"lesson-version\",\"url\":\"https://upfork.dev/lessons/L-P0AF\",\"version\":2,\"why\":\"\"}",
    "recordHash": "bcc6b16f5c531eb82f1ac794a76176f2af3c2badd43284a6bb6da04ad53c5091",
    "prevHash": "8dda3d7f44858e5b3d34ae01f25daf3ac74296a93bc49c7cf88c139abfb56d0e",
    "entryHash": "d59ced9b023d85459a97329e48e4651b6a7d97d83f71acc20e21fc830302527d",
    "keyId": "k1",
    "signature": "Gs9QCWD5XwyvoWrO9qNlvE8C4E19H9ILshcAWqOx3AFNOHDH1l7OWw4RnGGcxUUAa8rzoc1lSr2eU7EOxYgNDA==",
    "recordedAt": "2026-11-06T06:30:31.812937+00:00",
    "publicKey": "VuHuHXAtO3XAqgnwvMenp0f/3vTV061hnAIizYvwh40=",
    "algorithm": "Ed25519"
  },
  "path": [
    {
      "seq": 758,
      "prevHash": "d59ced9b023d85459a97329e48e4651b6a7d97d83f71acc20e21fc830302527d",
      "recordHash": "594cba1276f9f885d9ab47c43d2e71d53198a1a57c27d76dc9b56216cb457b7c",
      "entryHash": "cab63f99197c5c31f48bc9191f8a568dd69f4de84b69760388fa45a9d0f5ebc7"
    },
    {
      "seq": 759,
      "prevHash": "cab63f99197c5c31f48bc9191f8a568dd69f4de84b69760388fa45a9d0f5ebc7",
      "recordHash": "50e0cfd3811480470005091a496f6e40f06444b292796f2bab7da4b7cf2ccf8d",
      "entryHash": "32a4d0742ea943ad23b40241146fc1b4e04a172d701f241d6d71f755049014c0"
    },
    {
      "seq": 760,
      "prevHash": "32a4d0742ea943ad23b40241146fc1b4e04a172d701f241d6d71f755049014c0",
      "recordHash": "30df2884e99a192ce35e29e71be31a87622ac5614555a5b9b87bf17adfea2fc9",
      "entryHash": "b4d0d0c970c318b2344c10cc2ab84e2ec095fbeac07b6fc92eab04837ae03dc6"
    },
    {
      "seq": 761,
      "prevHash": "b4d0d0c970c318b2344c10cc2ab84e2ec095fbeac07b6fc92eab04837ae03dc6",
      "recordHash": "77ef4676264cb63923f0ecff250ca1facf8e9c2d0a5183e8ba62f634673cf42c",
      "entryHash": "a7b074341426f1ccc126e1c9b545ab135962529fdc674106d240429d8004925c"
    },
    {
      "seq": 762,
      "prevHash": "a7b074341426f1ccc126e1c9b545ab135962529fdc674106d240429d8004925c",
      "recordHash": "eb49c68428598c6a1edd9dff33863361279fe9927fb0d570d1925f7bd1413c9b",
      "entryHash": "7bbb1fba0754a33ffea8b7f95fb0d032c61ab827435e0dd4aa13585e41f002e0"
    }
  ],
  "checkpoint": {
    "seq": 762,
    "kind": "checkpoint",
    "record": "{\"day\":\"2026-11-07\",\"entries\":761,\"head\":\"a7b074341426f1ccc126e1c9b545ab135962529fdc674106d240429d8004925c\",\"site\":\"https://upfork.dev\",\"type\":\"checkpoint\"}",
    "recordHash": "eb49c68428598c6a1edd9dff33863361279fe9927fb0d570d1925f7bd1413c9b",
    "prevHash": "a7b074341426f1ccc126e1c9b545ab135962529fdc674106d240429d8004925c",
    "entryHash": "7bbb1fba0754a33ffea8b7f95fb0d032c61ab827435e0dd4aa13585e41f002e0",
    "keyId": "k1",
    "signature": "Wwk7TeUhO1kU7EH4YgwtYEQjCC2H1k2ZJCSVRREvtij2rfFaE/iPSr6kWQBMUHcN5JyvZkV8XGJH3OBJG0xpCw==",
    "recordedAt": "2026-11-07T00:05:30.164123+00:00",
    "publicKey": "VuHuHXAtO3XAqgnwvMenp0f/3vTV061hnAIizYvwh40=",
    "algorithm": "Ed25519"
  },
  "author": {
    "account": "a_9d470b566acab5f65bdc",
    "handle": "ramin-valadan",
    "former": false,
    "recordFormat": 2
  },
  "keys": "https://upfork.dev/ledger/keys.json"
}