Просмотр исходного кода

wallet: only allocate texture once. Instead use a ResourceManager

rsx 2 лет назад
Родитель
Сommit
663712f8b0
1 измененных файлов с 68 добавлено и 15 удалено
  1. 68 15
      bin/darkwallet/src/gfx.rs

+ 68 - 15
bin/darkwallet/src/gfx.rs

@@ -48,21 +48,70 @@ impl fmt::Debug for Face {
     }
     }
 }
 }
 
 
+type ResourceId = u32;
+
+struct ResourceManager<T> {
+    resources: Vec<(ResourceId, Option<T>)>,
+    freed: Vec<usize>,
+    id_counter: ResourceId,
+}
+
+impl<T> ResourceManager<T> {
+    fn new() -> Self {
+        Self {
+            resources: vec![],
+            freed: vec![],
+            id_counter: 0
+        }
+    }
+
+    fn alloc(&mut self, rsrc: T) -> ResourceId {
+        let id = self.id_counter;
+        self.id_counter += 1;
+
+        if self.freed.is_empty() {
+            let idx = self.resources.len();
+            self.resources.push((id, Some(rsrc)));
+        } else {
+            let idx = self.freed.pop().unwrap();
+            let _ = std::mem::replace(&mut self.resources[idx], (id, Some(rsrc)));
+        }
+        id
+    }
+
+    fn get(&self, id: ResourceId) -> Option<&T> {
+        for (idx, (rsrc_id, rsrc)) in self.resources.iter().enumerate() {
+            if self.freed.contains(&idx) {
+                continue
+            }
+            if *rsrc_id == id {
+                return rsrc.as_ref()
+            }
+        }
+        None
+    }
+}
+
 struct Stage {
 struct Stage {
     ctx: Box<dyn RenderingBackend>,
     ctx: Box<dyn RenderingBackend>,
     pipeline: Pipeline,
     pipeline: Pipeline,
 
 
     scene_graph: SceneGraphPtr,
     scene_graph: SceneGraphPtr,
 
 
-    white_texture: TextureId,
+    textures: ResourceManager<TextureId>,
     font: Font,
     font: Font,
 }
 }
 
 
 impl Stage {
 impl Stage {
+    const WHITE_TEXTURE_ID: ResourceId = 0;
+
     pub fn new(scene_graph: SceneGraphPtr) -> Stage {
     pub fn new(scene_graph: SceneGraphPtr) -> Stage {
         let mut ctx: Box<dyn RenderingBackend> = window::new_rendering_backend();
         let mut ctx: Box<dyn RenderingBackend> = window::new_rendering_backend();
 
 
         let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
         let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
+        let mut textures = ResourceManager::new();
+        let white_texture_id = textures.alloc(white_texture);
+        assert_eq!(white_texture_id, Self::WHITE_TEXTURE_ID);
 
 
         let mut shader_meta: ShaderMeta = shader::meta();
         let mut shader_meta: ShaderMeta = shader::meta();
         shader_meta
         shader_meta
@@ -146,7 +195,7 @@ impl Stage {
             ctx,
             ctx,
             pipeline,
             pipeline,
             scene_graph,
             scene_graph,
-            white_texture,
+            textures,
             font,
             font,
         };
         };
         stage.setup_scene_graph_window();
         stage.setup_scene_graph_window();
@@ -554,7 +603,7 @@ impl Stage {
         Ok(text_node_id)
         Ok(text_node_id)
     }
     }
 
 
-    fn load_texture(&self, node_name: String, filepath: String) -> Result<SceneNodeId> {
+    fn load_texture(&mut self, node_name: String, filepath: String) -> Result<SceneNodeId> {
         let Ok(img) = image::open(filepath) else {
         let Ok(img) = image::open(filepath) else {
             return Err(Error::FileNotFound)
             return Err(Error::FileNotFound)
         };
         };
@@ -576,12 +625,13 @@ impl Stage {
             .unwrap()
             .unwrap()
             .set_u32(height)
             .set_u32(height)
             .unwrap();
             .unwrap();
+        let texture = self.ctx.new_texture_from_rgba8(width as u16, height as u16, &bmp);
+        let id = self.textures.alloc(texture);
         img_node
         img_node
-            .add_property("bmp", PropertyType::Buffer)
+            .add_property("texture_id", PropertyType::Uint32)
             .unwrap()
             .unwrap()
-            .set_buf(bmp)
+            .set_u32(id)
             .unwrap();
             .unwrap();
-        //let king_texture = ctx.new_texture_from_rgba8(width, height, &king_bitmap);
         Ok(img_node.id)
         Ok(img_node.id)
     }
     }
 }
 }
@@ -750,9 +800,9 @@ impl EventHandler for Stage {
                     glam::Mat4::from_translation(glam::Vec3::new(x, y, 0.)) *
                     glam::Mat4::from_translation(glam::Vec3::new(x, y, 0.)) *
                     glam::Mat4::from_scale(glam::Vec3::new(scale, scale, 1.));
                     glam::Mat4::from_scale(glam::Vec3::new(scale, scale, 1.));
 
 
-                let texture_id = 'texture: {
+                let texture = 'texture: {
                     let Some(texture_node) = obj.iter_children(&scene_graph, SceneNodeType::RenderTexture).next() else {
                     let Some(texture_node) = obj.iter_children(&scene_graph, SceneNodeType::RenderTexture).next() else {
-                        break 'texture self.white_texture
+                        break 'texture self.textures.get(Self::WHITE_TEXTURE_ID).unwrap()
                     };
                     };
 
 
                     let Some(width_prop) = texture_node.get_property("width") else {
                     let Some(width_prop) = texture_node.get_property("width") else {
@@ -773,17 +823,20 @@ impl EventHandler for Stage {
                         continue 'outer
                         continue 'outer
                     };
                     };
 
 
-                    let Some(bmp_prop) = texture_node.get_property("bmp") else {
-                        error!("texture '{}':{} missing property bmp", texture_node.name, texture_node.id);
+                    let Some(id_prop) = texture_node.get_property("texture_id") else {
+                        error!("texture '{}':{} missing property texture_id", texture_node.name, texture_node.id);
                         continue 'outer
                         continue 'outer
                     };
                     };
-                    let Ok(bmp) = bmp_prop.get_buf() else {
-                        error!("texture '{}':{} bmp property has wrong type", texture_node.name, texture_node.id);
+                    let Ok(id) = id_prop.get_u32() else {
+                        error!("texture '{}':{} texture_id property has wrong type", texture_node.name, texture_node.id);
                         continue 'outer
                         continue 'outer
                     };
                     };
 
 
-                    let texture_id = self.ctx.new_texture_from_rgba8(width as u16, height as u16, &bmp);
-                    texture_id
+                    let Some(texture) = self.textures.get(id) else {
+                        error!("texture '{}':{} texture with id {} is missing!", texture_node.name, texture_node.id, id);
+                        continue 'outer
+                    };
+                    texture
                 };
                 };
 
 
                 for mesh in obj.iter_children(&scene_graph, SceneNodeType::RenderMesh) {
                 for mesh in obj.iter_children(&scene_graph, SceneNodeType::RenderMesh) {
@@ -828,7 +881,7 @@ impl EventHandler for Stage {
                     let bindings = Bindings {
                     let bindings = Bindings {
                         vertex_buffers: vec![vertex_buffer],
                         vertex_buffers: vec![vertex_buffer],
                         index_buffer: index_buffer,
                         index_buffer: index_buffer,
-                        images: vec![texture_id],
+                        images: vec![*texture],
                     };
                     };
 
 
                     self.ctx.apply_bindings(&bindings);
                     self.ctx.apply_bindings(&bindings);