)]}'
{
  "commit": "c687f1229ab31568de2f3196b4f6f7d955aa3956",
  "tree": "14b7f20e5a60607c7d6749640fb5c4ce8a1a4c76",
  "parents": [
    "9e706bb8f0ad05b5287b20901cc3be26c8b284b5"
  ],
  "author": {
    "name": "Tom Churchman",
    "email": "thomas@churchman.nl",
    "time": "Fri May 08 18:15:39 2026 +0200"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Fri May 08 16:15:39 2026 +0000"
  },
  "message": "vello_hybrid: Implement sampling external textures (with atlas support) (#1552)\n\nOn top of https://github.com/linebender/vello/pull/1559.\n\nThis adds `Scene::draw_texture_rects` that takes an opaque `TextureId`,\none or more rectangles that are to be sampled from that texture, and\ntransforms that determine where the result is to be placed in the\ndestination. The `TextureId`s are mapped by the user at render-time, and\nare not interned by the renderer.\n\nSome rough benchmark info here:\nhttps://github.com/linebender/vello/pull/1552#pullrequestreview-4040920322,\nwith the newest numbers in\nhttps://github.com/linebender/vello/pull/1552#pullrequestreview-4108776026\nfor the newest numbers. In that specific benchmark, rendering glyphs\nwith this texture sampling versus current glifo has about ~1.32x\nrendering throughput (not measuring building `Scene`), and 1.77x\nend-to-end throughput versus `glyph_run` with Glifo atlasing enabled\n(i.e., measuring building `Scene` with hot caches along with measuring\nrendering the Scene).\n\nThis is useful for sampling textures without requiring copying into (and\ntaking space in) the internal atlas. This API can also be used by users\nto draw from an atlas or spritesheet they manage themselves.\n\nThe texture is given to the shader by binding it. If the texture needs\nto change, the previous operations are emitted with a draw call and the\nnext texture is bound. For simplicity, this currently binds only one\ntexture at a time, though we could bind a handful more. I did experiment\nwith that, but that requires some more invasive changes, e.g., it\nrequires re-encoding the paints to track slots. Theoretically we could\nre-order operations to try to prevent unnecessary re-binding when, e.g.,\ndrawing with Texture A, then B, then A could be re-ordered without\nvisual changes to A, A, B, but that goes into deeper scheduler changes.\n\nBindless support would be useful here.\n\nI\u0027ve currently only implemented this for wgpu, but the same sort of\nthing should work for WebGL.\n\nThe `Scene` API in this PR already allows quite a bit in practice, but\nit\u0027s not a generalized brush. In the form this now takes (relative to\nthe form of last week), also implementing something like\n`ImageSource::ExternalTexture` is probably not too difficult. This atlas\nAPI (i.e., with low per-instance overhead) is probably simpler and more\nimportant to land.\n\nSome of the GPU plumbing (bindings, etc.) is AI-generated code that I\nstill need to give another look later.\n\nRun the example using `cargo run -p vello_hybrid --example\ntexture_rects`, which generates the following.\n\n\u003cimg width\u003d\"512\" height\u003d\"512\" alt\u003d\"texture_rects_output\"\nsrc\u003d\"https://github.com/user-attachments/assets/58869e60-53a9-4404-a7cc-ff73b503c966\"\n/\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "e06f969069a234548bc69ebef3f9d92bac01ebff",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_common/CHANGELOG.md",
      "new_id": "d84018914ff8631c622c75903313656fcb0c123e",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_common/CHANGELOG.md"
    },
    {
      "type": "modify",
      "old_id": "91a931425ce2f4aa026a47b0a611814d41c4dc91",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_common/src/coarse.rs",
      "new_id": "9f198086c9a7ef874f424466c66834b932996531",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_common/src/coarse.rs"
    },
    {
      "type": "modify",
      "old_id": "5acd769ba4f075e7d715cd3a7915ed462dc30673",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_common/src/encode.rs",
      "new_id": "5161fe021aa3981975302355fe7edffea3112235",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_common/src/encode.rs"
    },
    {
      "type": "modify",
      "old_id": "32b4040a8c15e0d35ae3790381f47d1c72ba7873",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_common/src/lib.rs",
      "new_id": "6862ea431db40e77a2cf0180f1fa6509e1003713",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_common/src/lib.rs"
    },
    {
      "type": "modify",
      "old_id": "a84bc788f2da046c80608931ac0efaf4b7123bb8",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_cpu/examples/wasm_cpu/src/lib.rs",
      "new_id": "242e46b8756c60f7831a19b815af48330af196cc",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_cpu/examples/wasm_cpu/src/lib.rs"
    },
    {
      "type": "modify",
      "old_id": "89b93cdafc0b9afffc0aa8218917122d2bda3858",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_cpu/examples/winit/src/main.rs",
      "new_id": "4530f8d0cb60dcccd77641b1f7b1d4c37132749a",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_cpu/examples/winit/src/main.rs"
    },
    {
      "type": "modify",
      "old_id": "609ee4fa341fbd3969d6c649fc3c9e0416dd66a6",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_cpu/src/fine/mod.rs",
      "new_id": "b48a21034101f65c29507d4f4a880d6f3e4395d5",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_cpu/src/fine/mod.rs"
    },
    {
      "type": "modify",
      "old_id": "9d0b6cd230a53b93cdf5a2cd3be5cd818d4233b9",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_example_scenes/src/lib.rs",
      "new_id": "9d8d4b81ef788f7d580881111175afe6d9fad38e",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_example_scenes/src/lib.rs"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "9673421c1519f4aa1941a9ae9c197337153f3e06",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_example_scenes/src/spritesheet.rs"
    },
    {
      "type": "modify",
      "old_id": "bfbec1f491310a5627ac3c95ba709d9d39ffbc38",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/CHANGELOG.md",
      "new_id": "4c02ef425d65bef2dcef2bede4deac47adc57a37",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/CHANGELOG.md"
    },
    {
      "type": "modify",
      "old_id": "f1947f27b5f61d35f58e0a4193912c58ac571fcc",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/examples/native_webgl/src/lib.rs",
      "new_id": "7be6e362d28a4bc521c0683865f125ecdc4acd39",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/examples/native_webgl/src/lib.rs"
    },
    {
      "type": "modify",
      "old_id": "345c1377bcc60cb4fd7a8ffa80b0f9a3f44a9fb3",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/examples/render_to_file.rs",
      "new_id": "38862587d8038db73d4eb4aa381d31d8546b5cb7",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/examples/render_to_file.rs"
    },
    {
      "type": "modify",
      "old_id": "9b697fc2ee0395d59126eb62f657f1cacd1d92a5",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/examples/wgpu_webgl/src/lib.rs",
      "new_id": "ec4f5f4b4db69cf360f3aaa02923a8d184c28658",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/examples/wgpu_webgl/src/lib.rs"
    },
    {
      "type": "modify",
      "old_id": "80863615ef52e5c883ca255d507425e48f15ef12",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/examples/winit/src/main.rs",
      "new_id": "7e3f949949a4d75ddca002440672357bb51b1107",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/examples/winit/src/main.rs"
    },
    {
      "type": "modify",
      "old_id": "08244a7c2c55d1b32cc7c15d93655dcbb9402abd",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/src/lib.rs",
      "new_id": "781514521752d9b11657d9ec0675fea06f0743ef",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/src/lib.rs"
    },
    {
      "type": "modify",
      "old_id": "0a776a190e63daa7d589196d56916ebf4f49407f",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/src/render/mod.rs",
      "new_id": "62e93dc1b42a6c541401fe2a257cff136d238466",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/src/render/mod.rs"
    },
    {
      "type": "modify",
      "old_id": "8958d0fec8f4a956b73452f45acba6a0e92c0f8e",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/src/render/webgl.rs",
      "new_id": "a0b1072708ef17f504eb4abf96107fb0fb025f8f",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/src/render/webgl.rs"
    },
    {
      "type": "modify",
      "old_id": "112f16243a77d39275a8c8a3e28ed7c2c90a8618",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/src/render/wgpu.rs",
      "new_id": "3a9d728fdac447a9d425b32b5e79e7d3d2773c28",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/src/render/wgpu.rs"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "6e014524a5a74f603450322746d37a5cb5036972",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/src/sampling.rs"
    },
    {
      "type": "modify",
      "old_id": "8207bb3745a56783c5cafdc9c5463e4db3dfdf19",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/src/scene.rs",
      "new_id": "b62cccb2b8c823a6c2cf88e3fb8d7c193a3db423",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/src/scene.rs"
    },
    {
      "type": "modify",
      "old_id": "97cf1b2809c3956617b0d16b3cdf1f3cfb4d50e6",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_hybrid/src/schedule.rs",
      "new_id": "17eadefc1e506c21795cc8f1ada39e3e5ee036f1",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_hybrid/src/schedule.rs"
    },
    {
      "type": "modify",
      "old_id": "3b8247aedb5b1c1efc55eef8a7f9289713de29e5",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_sparse_shaders/shaders/render_strips.wgsl",
      "new_id": "de80d98f546cbaf5f090c76abd1a07885c429054",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_shaders/shaders/render_strips.wgsl"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "a4adac847afb083f9c7f6f247816ee054261adc4",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/snapshots/external_texture_blurred.png"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "a7bd841eaba722ee58459022df44d24a422fe76f",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/snapshots/external_texture_clipped.png"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "df445fd399065ba0739c34670060378e59de256c",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/snapshots/external_texture_composite.png"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "a25b90bd7d39f76785f277d7aaca20cb104329cb",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/snapshots/external_texture_many_sprites.png"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1ae171ee573cace82318720b1ff7fe70b5b75625",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/snapshots/external_texture_skewed.png"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "086e1b6ecd5772ed1150fd29381fb152a7b3eedb",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/snapshots/external_texture_with_scene_transform.png"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1ae171ee573cace82318720b1ff7fe70b5b75625",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/snapshots/texture_rects_basic_hybrid.png"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "7909099785d6a6b06ac55d33488657f0ad50e99c",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/tests/assets/glyphs_colr_noto.png"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "5db0e281b5ab853764da3d1c1bfdbd1046cb111f",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/tests/external_texture.rs"
    },
    {
      "type": "modify",
      "old_id": "8fd586aa936dee38ac7252aabeb7b8f81771dd43",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_sparse_tests/tests/mod.rs",
      "new_id": "66bcfb44e787342a5db78e39509e9106dc680b55",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/tests/mod.rs"
    },
    {
      "type": "modify",
      "old_id": "3c68f5bc955cac816bcae318d0c7cc3ddd516c14",
      "old_mode": 33188,
      "old_path": "sparse_strips/vello_sparse_tests/tests/renderer.rs",
      "new_id": "56c7bb4e08cfa1651a1907a4d2c8a73eb140cb71",
      "new_mode": 33188,
      "new_path": "sparse_strips/vello_sparse_tests/tests/renderer.rs"
    }
  ]
}
