fix: share renderer resources across example scenes
diff --git a/sparse_strips/vello_cpu/examples/wasm_cpu/src/lib.rs b/sparse_strips/vello_cpu/examples/wasm_cpu/src/lib.rs
index 5a38f8f..6fa9643 100644
--- a/sparse_strips/vello_cpu/examples/wasm_cpu/src/lib.rs
+++ b/sparse_strips/vello_cpu/examples/wasm_cpu/src/lib.rs
@@ -28,6 +28,7 @@
     width: u32,
     height: u32,
     renderer: RenderContext,
+    resources: vello_cpu::Resources,
     pixmap: vello_common::pixmap::Pixmap,
     need_render: bool,
     canvas: HtmlCanvasElement,
@@ -58,6 +59,7 @@
             width,
             height,
             renderer,
+            resources: vello_cpu::Resources::new(),
             pixmap,
             need_render: true,
             canvas,
@@ -69,13 +71,14 @@
             return;
         }
         self.renderer.reset();
-        self.scenes[self.current_scene].render(&mut self.renderer, self.transform);
+        self.scenes[self.current_scene].render(
+            &mut self.renderer,
+            &mut self.resources,
+            self.transform,
+        );
 
         // Render the current scene with transform
-        self.renderer.render(
-            &mut self.pixmap,
-            self.scenes[self.current_scene].resources_mut(),
-        );
+        self.renderer.render(&mut self.pixmap, &mut self.resources);
         let rgba_bytes = self.pixmap.data_as_u8_slice();
         let image_data = web_sys::ImageData::new_with_u8_clamped_array_and_sh(
             wasm_bindgen::Clamped(rgba_bytes),
diff --git a/sparse_strips/vello_cpu/examples/winit/src/main.rs b/sparse_strips/vello_cpu/examples/winit/src/main.rs
index cef0c18..eb30e63 100644
--- a/sparse_strips/vello_cpu/examples/winit/src/main.rs
+++ b/sparse_strips/vello_cpu/examples/winit/src/main.rs
@@ -36,6 +36,7 @@
     current_scene: usize,
     render_state: RenderState,
     renderer: RenderContext,
+    resources: vello_cpu::Resources,
     pixmap: Pixmap,
     transform: Affine,
     mouse_down: bool,
@@ -120,6 +121,7 @@
                 ..Default::default()
             },
         ),
+        resources: vello_cpu::Resources::new(),
         pixmap: Pixmap::new(width, height),
         transform: Affine::IDENTITY,
         mouse_down: false,
@@ -448,12 +450,13 @@
                 // Render the scene
                 self.renderer.reset();
 
-                self.scenes[self.current_scene].render(&mut self.renderer, self.transform);
-                self.renderer.flush();
-                self.renderer.render(
-                    &mut self.pixmap,
-                    self.scenes[self.current_scene].resources_mut(),
+                self.scenes[self.current_scene].render(
+                    &mut self.renderer,
+                    &mut self.resources,
+                    self.transform,
                 );
+                self.renderer.flush();
+                self.renderer.render(&mut self.pixmap, &mut self.resources);
 
                 // Copy pixmap to window surface
                 let mut buffer = surface.buffer_mut().unwrap();
diff --git a/sparse_strips/vello_example_scenes/src/lib.rs b/sparse_strips/vello_example_scenes/src/lib.rs
index dcd2312..4167d57 100644
--- a/sparse_strips/vello_example_scenes/src/lib.rs
+++ b/sparse_strips/vello_example_scenes/src/lib.rs
@@ -354,7 +354,6 @@
 pub struct AnyScene<T: RenderingContext> {
     /// The render function that calls the wrapped scene's render method.
     render_fn: RenderFn<T>,
-    resources: T::Resources,
     /// The key handler function.
     key_handler_fn: KeyHandlerFn,
     /// The status query function.
@@ -383,7 +382,6 @@
 impl<T> AnyScene<T>
 where
     T: RenderingContext,
-    T::Resources: Default,
 {
     /// Create a new `AnyScene` from any type that implements `ExampleScene`.
     pub fn new<S: ExampleScene + 'static>(scene: S) -> Self {
@@ -395,7 +393,6 @@
             render_fn: Box::new(move |s, resources, transform| {
                 scene.borrow_mut().render(s, resources, transform);
             }),
-            resources: T::Resources::default(),
             key_handler_fn: Box::new(move |key| scene_clone.borrow_mut().handle_key(key)),
             status_fn: Box::new(move || scene_status.borrow().status()),
             show_widetile_columns: false,
@@ -403,9 +400,9 @@
     }
 
     /// Render the scene.
-    pub fn render(&mut self, ctx: &mut T, root_transform: Affine) {
+    pub fn render(&mut self, ctx: &mut T, resources: &mut T::Resources, root_transform: Affine) {
         // Render the actual scene content
-        (self.render_fn)(ctx, &mut self.resources, root_transform);
+        (self.render_fn)(ctx, resources, root_transform);
 
         // Draw tile grid overlay if enabled
         if self.show_widetile_columns {
@@ -434,11 +431,6 @@
         (self.status_fn)()
     }
 
-    /// Access the scene-owned resources.
-    pub fn resources_mut(&mut self) -> &mut T::Resources {
-        &mut self.resources
-    }
-
     /// Toggle the tile grid overlay.
     pub fn toggle_tile_grid(&mut self) {
         self.show_widetile_columns = !self.show_widetile_columns;
@@ -470,10 +462,7 @@
     capabilities: Capabilities,
     svg_paths: Option<Vec<&str>>,
     img_sources: Vec<ImageSource>,
-) -> Box<[AnyScene<T>]>
-where
-    T::Resources: Default,
-{
+) -> Box<[AnyScene<T>]> {
     let mut scenes = Vec::new();
 
     // Create SVG scenes for each provided path.
@@ -528,10 +517,7 @@
 pub fn get_example_scenes<T: RenderingContext + 'static>(
     capabilities: Capabilities,
     img_sources: Vec<ImageSource>,
-) -> Box<[AnyScene<T>]>
-where
-    T::Resources: Default,
-{
+) -> Box<[AnyScene<T>]> {
     let mut scenes = vec![
         AnyScene::new(svg::SvgScene::tiger()),
         AnyScene::new(text::TextScene::new("Hello, Vello!")),
diff --git a/sparse_strips/vello_hybrid/examples/native_webgl/Cargo.toml b/sparse_strips/vello_hybrid/examples/native_webgl/Cargo.toml
index 3747465..f8227de 100644
--- a/sparse_strips/vello_hybrid/examples/native_webgl/Cargo.toml
+++ b/sparse_strips/vello_hybrid/examples/native_webgl/Cargo.toml
@@ -26,6 +26,9 @@
 web-sys = { workspace = true, features = [
     "AddEventListenerOptions",
     "Window",
+    "Location",
+    "History",
+    "UrlSearchParams",
     "Document",
     "DomRect",
     "Element",
diff --git a/sparse_strips/vello_hybrid/examples/native_webgl/src/lib.rs b/sparse_strips/vello_hybrid/examples/native_webgl/src/lib.rs
index cdf848e..6caef6e 100644
--- a/sparse_strips/vello_hybrid/examples/native_webgl/src/lib.rs
+++ b/sparse_strips/vello_hybrid/examples/native_webgl/src/lib.rs
@@ -18,19 +18,26 @@
 };
 use vello_example_scenes::AnyScene;
 use vello_example_scenes::image::ImageScene;
-use vello_hybrid::Scene;
+use vello_hybrid::{RenderSettings, Scene};
 use wasm_bindgen::prelude::*;
 use web_sys::{Event, HtmlCanvasElement, KeyboardEvent, MouseEvent, WheelEvent};
 
 struct RendererWrapper {
     renderer: vello_hybrid::WebGlRenderer,
+    resources: vello_hybrid::Resources,
 }
 
 impl RendererWrapper {
     fn new(canvas: HtmlCanvasElement) -> Self {
-        let renderer = vello_hybrid::WebGlRenderer::new(&canvas);
+        let settings = RenderSettings::default();
+        let resources =
+            vello_hybrid::Resources::new_with_config(settings.memory_settings.image_atlas_config);
+        let renderer = vello_hybrid::WebGlRenderer::new_with(&canvas, settings);
 
-        Self { renderer }
+        Self {
+            renderer,
+            resources,
+        }
     }
 }
 
@@ -53,7 +60,6 @@
 /// State that handles scene rendering and interactions
 struct AppState {
     scenes: Box<[AnyScene<Scene>]>,
-    uploaded_scene_images: Box<[bool]>,
     current_scene: usize,
     scene: Scene,
     transform: Affine,
@@ -71,14 +77,13 @@
     fn new(canvas: HtmlCanvasElement, scenes: Box<[AnyScene<Scene>]>) -> Self {
         let width = canvas.width();
         let height = canvas.height();
-        let uploaded_scene_images = vec![false; scenes.len()].into_boxed_slice();
+        let current_scene = initial_scene_index(scenes.len());
 
         let renderer_wrapper = RendererWrapper::new(canvas.clone());
 
         let mut app_state = Self {
             scenes,
-            uploaded_scene_images,
-            current_scene: 0,
+            current_scene,
             scene: Scene::new(width as u16, height as u16),
             transform: Affine::IDENTITY,
             mouse_down: false,
@@ -91,6 +96,8 @@
             canvas,
         };
 
+        update_page_url(app_state.current_scene);
+        app_state.update_title();
         app_state.upload_images_to_atlas();
 
         app_state
@@ -104,7 +111,11 @@
         self.scene.reset();
 
         // Render the current scene with transform
-        self.scenes[self.current_scene].render(&mut self.scene, self.transform);
+        self.scenes[self.current_scene].render(
+            &mut self.scene,
+            &mut self.renderer_wrapper.resources,
+            self.transform,
+        );
 
         let render_size = vello_hybrid::RenderSize {
             width: self.width,
@@ -115,7 +126,7 @@
             .renderer
             .render(
                 &self.scene,
-                self.scenes[self.current_scene].resources_mut(),
+                &mut self.renderer_wrapper.resources,
                 &render_size,
             )
             .unwrap();
@@ -135,7 +146,8 @@
 
     fn next_scene(&mut self) {
         self.current_scene = (self.current_scene + 1) % self.scenes.len();
-        self.upload_images_to_atlas();
+        update_page_url(self.current_scene);
+        self.update_title();
         self.transform = Affine::IDENTITY;
         self.need_render = true;
     }
@@ -146,11 +158,24 @@
         } else {
             self.current_scene - 1
         };
-        self.upload_images_to_atlas();
+        update_page_url(self.current_scene);
+        self.update_title();
         self.transform = Affine::IDENTITY;
         self.need_render = true;
     }
 
+    fn update_title(&self) {
+        web_sys::window()
+            .unwrap()
+            .document()
+            .unwrap()
+            .set_title(&format!(
+                "Vello Hybrid WebGL - Page {}/{}",
+                self.current_scene + 1,
+                self.scenes.len()
+            ));
+    }
+
     fn reset_transform(&mut self) {
         self.transform = Affine::IDENTITY;
         self.need_render = true;
@@ -225,24 +250,18 @@
     /// Upload images to the WebGL atlas texture
     /// This is the WebGL analogue of the winit example's `upload_images_to_atlas` function
     fn upload_images_to_atlas(&mut self) {
-        if self.uploaded_scene_images[self.current_scene] {
-            return;
-        }
-
         // 1st example — uploading pixmap directly to WebGL atlas
         let pixmap1 = ImageScene::read_flower_image();
         self.renderer_wrapper
             .renderer
-            .upload_image(self.scenes[self.current_scene].resources_mut(), &pixmap1);
+            .upload_image(&mut self.renderer_wrapper.resources, &pixmap1);
 
         // 2nd example — uploading from a WebGL texture
         let pixmap2 = ImageScene::read_cowboy_image();
         let texture2 = self.pixmap_to_webgl_texture(&pixmap2);
         self.renderer_wrapper
             .renderer
-            .upload_image(self.scenes[self.current_scene].resources_mut(), &texture2);
-
-        self.uploaded_scene_images[self.current_scene] = true;
+            .upload_image(&mut self.renderer_wrapper.resources, &texture2);
     }
 
     /// Convert a pixmap to WebGL texture
@@ -519,15 +538,39 @@
         .append_child(&canvas)
         .unwrap();
 
-    let mut renderer = vello_hybrid::WebGlRenderer::new(&canvas);
+    let RendererWrapper {
+        mut renderer,
+        mut resources,
+    } = RendererWrapper::new(canvas);
 
     let render_size = vello_hybrid::RenderSize {
         width: width as u32,
         height: height as u32,
     };
-    let mut resources = vello_hybrid::Resources::new();
-
     renderer
         .render(&scene, &mut resources, &render_size)
         .unwrap();
 }
+
+fn initial_scene_index(scene_count: usize) -> usize {
+    web_sys::window()
+        .and_then(|window| window.location().search().ok())
+        .and_then(|search| web_sys::UrlSearchParams::new_with_str(&search).ok())
+        .and_then(|params| params.get("page"))
+        .and_then(|page| page.parse::<usize>().ok())
+        .filter(|page| (1..=scene_count).contains(page))
+        .map_or(0, |page| page - 1)
+}
+
+fn update_page_url(scene_index: usize) {
+    web_sys::window()
+        .unwrap()
+        .history()
+        .unwrap()
+        .replace_state_with_url(
+            &JsValue::NULL,
+            "",
+            Some(&format!("?page={}", scene_index + 1)),
+        )
+        .unwrap();
+}
diff --git a/sparse_strips/vello_hybrid/examples/wgpu_webgl/Cargo.toml b/sparse_strips/vello_hybrid/examples/wgpu_webgl/Cargo.toml
index 30be052..2662e5b 100644
--- a/sparse_strips/vello_hybrid/examples/wgpu_webgl/Cargo.toml
+++ b/sparse_strips/vello_hybrid/examples/wgpu_webgl/Cargo.toml
@@ -25,6 +25,9 @@
 wasm-bindgen-futures = { workspace = true }
 web-sys = { workspace = true, features = [
     "Window",
+    "Location",
+    "History",
+    "UrlSearchParams",
     "Document",
     "Element",
     "HtmlElement",
diff --git a/sparse_strips/vello_hybrid/examples/wgpu_webgl/src/lib.rs b/sparse_strips/vello_hybrid/examples/wgpu_webgl/src/lib.rs
index 5fba993..b9f2dd1 100644
--- a/sparse_strips/vello_hybrid/examples/wgpu_webgl/src/lib.rs
+++ b/sparse_strips/vello_hybrid/examples/wgpu_webgl/src/lib.rs
@@ -35,6 +35,7 @@
 
 struct RendererWrapper {
     renderer: Renderer,
+    resources: vello_hybrid::Resources,
     device: wgpu::Device,
     queue: wgpu::Queue,
     surface: wgpu::Surface<'static>,
@@ -88,6 +89,12 @@
         };
         surface.configure(&device, &surface_config);
 
+        let settings = RenderSettings {
+            level: Level::try_detect().unwrap_or(Level::baseline()),
+            ..Default::default()
+        };
+        let resources =
+            vello_hybrid::Resources::new_with_config(settings.memory_settings.image_atlas_config);
         let renderer = Renderer::new_with(
             &device,
             &RenderTargetConfig {
@@ -95,14 +102,12 @@
                 width,
                 height,
             },
-            RenderSettings {
-                level: Level::try_detect().unwrap_or(Level::baseline()),
-                ..Default::default()
-            },
+            settings,
         );
 
         Self {
             renderer,
+            resources,
             device,
             queue,
             surface,
@@ -127,7 +132,6 @@
 /// State that handles scene rendering and interactions
 struct AppState {
     scenes: Box<[AnyScene<Scene>]>,
-    uploaded_scene_images: Box<[bool]>,
     current_scene: usize,
     scene: Scene,
     transform: Affine,
@@ -144,14 +148,13 @@
     async fn new(canvas: HtmlCanvasElement, scenes: Box<[AnyScene<Scene>]>) -> Self {
         let width = canvas.width();
         let height = canvas.height();
-        let uploaded_scene_images = vec![false; scenes.len()].into_boxed_slice();
+        let current_scene = initial_scene_index(scenes.len());
 
         let renderer_wrapper = RendererWrapper::new(canvas.clone()).await;
 
         let mut app_state = Self {
             scenes,
-            uploaded_scene_images,
-            current_scene: 0,
+            current_scene,
             scene: Scene::new(width as u16, height as u16),
             transform: Affine::IDENTITY,
             mouse_down: false,
@@ -163,6 +166,8 @@
             canvas,
         };
 
+        update_page_url(app_state.current_scene);
+        app_state.update_title();
         // Upload images to the WebGL atlas
         app_state.upload_images_to_atlas();
 
@@ -177,7 +182,11 @@
         self.scene.reset();
 
         // Render the current scene with transform
-        self.scenes[self.current_scene].render(&mut self.scene, self.transform);
+        self.scenes[self.current_scene].render(
+            &mut self.scene,
+            &mut self.renderer_wrapper.resources,
+            self.transform,
+        );
 
         let render_size = vello_hybrid::RenderSize {
             width: self.width,
@@ -210,7 +219,7 @@
             .renderer
             .render(
                 &self.scene,
-                self.scenes[self.current_scene].resources_mut(),
+                &mut self.renderer_wrapper.resources,
                 &self.renderer_wrapper.device,
                 &self.renderer_wrapper.queue,
                 &mut encoder,
@@ -240,7 +249,8 @@
 
     fn next_scene(&mut self) {
         self.current_scene = (self.current_scene + 1) % self.scenes.len();
-        self.upload_images_to_atlas();
+        update_page_url(self.current_scene);
+        self.update_title();
         self.transform = Affine::IDENTITY;
         self.need_render = true;
     }
@@ -251,11 +261,24 @@
         } else {
             self.current_scene - 1
         };
-        self.upload_images_to_atlas();
+        update_page_url(self.current_scene);
+        self.update_title();
         self.transform = Affine::IDENTITY;
         self.need_render = true;
     }
 
+    fn update_title(&self) {
+        web_sys::window()
+            .unwrap()
+            .document()
+            .unwrap()
+            .set_title(&format!(
+                "Vello Hybrid WGPU WebGL - Page {}/{}",
+                self.current_scene + 1,
+                self.scenes.len()
+            ));
+    }
+
     fn reset_transform(&mut self) {
         self.transform = Affine::IDENTITY;
         self.need_render = true;
@@ -309,10 +332,6 @@
     }
 
     fn upload_images_to_atlas(&mut self) {
-        if self.uploaded_scene_images[self.current_scene] {
-            return;
-        }
-
         let mut encoder =
             self.renderer_wrapper
                 .device
@@ -323,7 +342,7 @@
         // 1st example — uploading pixmap directly to WebGL atlas
         let pixmap1 = ImageScene::read_flower_image();
         self.renderer_wrapper.renderer.upload_image(
-            self.scenes[self.current_scene].resources_mut(),
+            &mut self.renderer_wrapper.resources,
             &self.renderer_wrapper.device,
             &self.renderer_wrapper.queue,
             &mut encoder,
@@ -338,7 +357,7 @@
             &pixmap2,
         );
         self.renderer_wrapper.renderer.upload_image(
-            self.scenes[self.current_scene].resources_mut(),
+            &mut self.renderer_wrapper.resources,
             &self.renderer_wrapper.device,
             &self.renderer_wrapper.queue,
             &mut encoder,
@@ -346,7 +365,6 @@
         );
 
         self.renderer_wrapper.queue.submit([encoder.finish()]);
-        self.uploaded_scene_images[self.current_scene] = true;
     }
 
     fn upload_image_to_texture(
@@ -608,6 +626,7 @@
 
     let RendererWrapper {
         mut renderer,
+        mut resources,
         device,
         queue,
         surface,
@@ -627,7 +646,6 @@
 
     let mut encoder =
         device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
-    let mut resources = vello_hybrid::Resources::new();
 
     renderer
         .render(
@@ -645,3 +663,26 @@
     queue.submit([encoder.finish()]);
     surface_texture.present();
 }
+
+fn initial_scene_index(scene_count: usize) -> usize {
+    web_sys::window()
+        .and_then(|window| window.location().search().ok())
+        .and_then(|search| web_sys::UrlSearchParams::new_with_str(&search).ok())
+        .and_then(|params| params.get("page"))
+        .and_then(|page| page.parse::<usize>().ok())
+        .filter(|page| (1..=scene_count).contains(page))
+        .map_or(0, |page| page - 1)
+}
+
+fn update_page_url(scene_index: usize) {
+    web_sys::window()
+        .unwrap()
+        .history()
+        .unwrap()
+        .replace_state_with_url(
+            &JsValue::NULL,
+            "",
+            Some(&format!("?page={}", scene_index + 1)),
+        )
+        .unwrap();
+}
diff --git a/sparse_strips/vello_hybrid/examples/winit/src/main.rs b/sparse_strips/vello_hybrid/examples/winit/src/main.rs
index d59b556..70179c8 100644
--- a/sparse_strips/vello_hybrid/examples/winit/src/main.rs
+++ b/sparse_strips/vello_hybrid/examples/winit/src/main.rs
@@ -15,7 +15,7 @@
 use vello_example_scenes::image::ImageScene;
 use vello_example_scenes::spritesheet::{SPRITESHEET_TEXTURE_ID, SpritesheetScene};
 use vello_example_scenes::{AnyScene, Capabilities, get_example_scenes};
-use vello_hybrid::{Pixmap, RenderSize, Renderer, Scene, TextureBindings};
+use vello_hybrid::{Pixmap, RenderSize, Renderer, Resources, Scene, TextureBindings};
 use wgpu::CurrentSurfaceTexture;
 use winit::{
     application::ApplicationHandler,
@@ -32,7 +32,8 @@
     scenes: Box<[AnyScene<Scene>]>,
     current_scene: usize,
     renderers: Vec<Option<Renderer>>,
-    uploaded_scene_images: Vec<Vec<bool>>,
+    resources: Vec<Option<Resources>>,
+    uploaded_images: Vec<bool>,
     spritesheet_textures: Vec<Option<wgpu::Texture>>,
     render_state: RenderState<'s>,
     scene: Scene,
@@ -98,7 +99,8 @@
     let mut app = App {
         context: RenderContext::new(),
         renderers: vec![],
-        uploaded_scene_images: vec![],
+        resources: vec![],
+        uploaded_images: vec![],
         spritesheet_textures: vec![],
         scenes,
         current_scene: start_scene_index,
@@ -161,14 +163,15 @@
 
         self.renderers
             .resize_with(self.context.devices.len(), || None);
-        self.uploaded_scene_images
-            .resize_with(self.context.devices.len(), || {
-                vec![false; self.scenes.len()]
-            });
+        self.resources
+            .resize_with(self.context.devices.len(), || None);
+        self.uploaded_images
+            .resize(self.context.devices.len(), false);
         self.spritesheet_textures
             .resize_with(self.context.devices.len(), || None);
         self.renderers[surface.dev_id]
             .get_or_insert_with(|| create_vello_renderer(&self.context, &surface));
+        self.resources[surface.dev_id].get_or_insert_with(Resources::new);
 
         self.upload_images_to_atlas(surface.dev_id);
         self.ensure_spritesheet_uploaded(surface.dev_id);
@@ -193,8 +196,6 @@
             return;
         }
 
-        let dev_id = surface.dev_id;
-
         match event {
             WindowEvent::CloseRequested => event_loop.exit(),
             WindowEvent::Resized(size) => {
@@ -214,13 +215,10 @@
                     },
                 ..
             } => {
-                let mut upload_images = false;
-
                 match logical_key {
                     Key::Named(NamedKey::ArrowRight) => {
                         self.current_scene = (self.current_scene + 1) % self.scenes.len();
                         self.transform = Affine::IDENTITY;
-                        upload_images = true;
                         window.request_redraw();
                     }
                     Key::Named(NamedKey::ArrowLeft) => {
@@ -230,7 +228,6 @@
                             self.current_scene - 1
                         };
                         self.transform = Affine::IDENTITY;
-                        upload_images = true;
                         window.request_redraw();
                     }
                     Key::Named(NamedKey::Space) => {
@@ -250,12 +247,6 @@
                     }
                     _ => {}
                 }
-
-                // Each scene has it's own resources struct, so in case the images
-                // haven't been uploaded previously, we need to do it now.
-                if upload_images {
-                    self.upload_images_to_atlas(dev_id);
-                }
             }
             WindowEvent::MouseInput {
                 state,
@@ -355,7 +346,11 @@
                 let render_start = Instant::now();
 
                 self.scene.set_transform(self.transform);
-                self.scenes[self.current_scene].render(&mut self.scene, self.transform);
+                self.scenes[self.current_scene].render(
+                    &mut self.scene,
+                    self.resources[surface.dev_id].as_mut().unwrap(),
+                    self.transform,
+                );
 
                 let device_handle = &self.context.devices[surface.dev_id];
                 let render_size = RenderSize {
@@ -401,7 +396,7 @@
                     .unwrap()
                     .render(
                         &self.scene,
-                        self.scenes[self.current_scene].resources_mut(),
+                        self.resources[surface.dev_id].as_mut().unwrap(),
                         &device_handle.device,
                         &device_handle.queue,
                         &mut encoder,
@@ -428,7 +423,7 @@
 
 impl App<'_> {
     fn upload_images_to_atlas(&mut self, device_id: usize) {
-        if self.uploaded_scene_images[device_id][self.current_scene] {
+        if self.uploaded_images[device_id] {
             return;
         }
 
@@ -443,7 +438,7 @@
         // 1st example — uploading pixmap directly
         let pixmap1 = ImageScene::read_flower_image();
         self.renderers[device_id].as_mut().unwrap().upload_image(
-            self.scenes[self.current_scene].resources_mut(),
+            self.resources[device_id].as_mut().unwrap(),
             &device_handle.device,
             &device_handle.queue,
             &mut encoder,
@@ -455,7 +450,7 @@
         let texture2 =
             self.upload_image_to_texture(&device_handle.device, &device_handle.queue, &pixmap2);
         self.renderers[device_id].as_mut().unwrap().upload_image(
-            self.scenes[self.current_scene].resources_mut(),
+            self.resources[device_id].as_mut().unwrap(),
             &device_handle.device,
             &device_handle.queue,
             &mut encoder,
@@ -463,7 +458,7 @@
         );
 
         device_handle.queue.submit([encoder.finish()]);
-        self.uploaded_scene_images[device_id][self.current_scene] = true;
+        self.uploaded_images[device_id] = true;
     }
 
     fn ensure_spritesheet_uploaded(&mut self, device_id: usize) {