From bc4ba647bc343fe1969ad7e9efc17548161c45fe Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Fri, 1 Feb 2019 14:44:21 -0800 Subject: [PATCH] caching Renderables for agents --- docs/TODO_ux.md | 3 +- editor/src/plugins/sim/time_travel.rs | 4 ++ editor/src/render/map.rs | 89 +++++++++++++++++++++------ sim/src/render.rs | 7 ++- 4 files changed, 82 insertions(+), 21 deletions(-) diff --git a/docs/TODO_ux.md b/docs/TODO_ux.md index 856e5391fa..f5c5d929f4 100644 --- a/docs/TODO_ux.md +++ b/docs/TODO_ux.md @@ -3,7 +3,8 @@ ## Performance - cache draw stuff - - carefully. dont upload unbounded stuff to GPU in time travel. + - use a Drawable in DrawPed/DrawCar/DrawBike. + - fix the process_objects callback nonsense ## Quick n easy diff --git a/editor/src/plugins/sim/time_travel.rs b/editor/src/plugins/sim/time_travel.rs index 7a2dbed0d5..9ab058793d 100644 --- a/editor/src/plugins/sim/time_travel.rs +++ b/editor/src/plugins/sim/time_travel.rs @@ -98,6 +98,10 @@ impl TimeTravel { } impl GetDrawAgents for TimeTravel { + fn tick(&self) -> Tick { + self.current_tick.unwrap() + } + fn get_draw_car(&self, id: CarID, _map: &Map) -> Option { self.get_current_state().cars.get(&id).cloned() } diff --git a/editor/src/render/map.rs b/editor/src/render/map.rs index fb03c5a756..b417bf3a4d 100644 --- a/editor/src/render/map.rs +++ b/editor/src/render/map.rs @@ -19,8 +19,9 @@ use map_model::{ AreaID, BuildingID, BusStopID, FindClosest, IntersectionID, Lane, LaneID, Map, ParcelID, RoadID, Traversable, Turn, TurnID, LANE_THICKNESS, }; -use sim::GetDrawAgents; +use sim::{GetDrawAgents, Tick}; use std::borrow::Borrow; +use std::cell::RefCell; use std::collections::HashMap; #[derive(PartialEq)] @@ -39,6 +40,8 @@ pub struct DrawMap { pub bus_stops: HashMap, pub areas: Vec, + agents: RefCell, + quadtree: QuadTree, } @@ -171,6 +174,11 @@ impl DrawMap { bus_stops, areas, + agents: RefCell::new(AgentCache { + tick: None, + agents_per_on: HashMap::new(), + }), + quadtree, } } @@ -282,9 +290,8 @@ impl DrawMap { let mut extra_shapes: Vec> = Vec::new(); let mut bus_stops: Vec> = Vec::new(); let mut turn_icons: Vec> = Vec::new(); - - let mut cars: Vec> = Vec::new(); - let mut peds: Vec> = Vec::new(); + // We can't immediately grab the Renderables; we need to do it all at once at the end. + let mut agents_on: Vec = Vec::new(); for &(id, _, _) in &self.quadtree.query(screen_bounds.as_bbox()) { if show_objs.show(*id) { @@ -294,12 +301,18 @@ impl DrawMap { ID::Lane(id) => { lanes.push(Box::new(self.get_l(*id))); if !show_objs.show_icons_for(map.get_l(*id).dst_i) { - for c in sim.get_draw_cars(Traversable::Lane(*id), map).into_iter() { - cars.push(draw_vehicle(c, map)); - } - for p in sim.get_draw_peds(Traversable::Lane(*id), map).into_iter() { - peds.push(Box::new(DrawPedestrian::new(p, map))); + let on = Traversable::Lane(*id); + if !self.agents.borrow().has(sim.tick(), on) { + let mut list: Vec> = Vec::new(); + for c in sim.get_draw_cars(on, map).into_iter() { + list.push(draw_vehicle(c, map)); + } + for p in sim.get_draw_peds(on, map).into_iter() { + list.push(Box::new(DrawPedestrian::new(p, map))); + } + self.agents.borrow_mut().put(sim.tick(), on, list); } + agents_on.push(on); } } ID::Intersection(id) => { @@ -308,12 +321,18 @@ impl DrawMap { if show_objs.show_icons_for(*id) { turn_icons.push(Box::new(self.get_t(*t))); } else { - for c in sim.get_draw_cars(Traversable::Turn(*t), map).into_iter() { - cars.push(draw_vehicle(c, map)); - } - for p in sim.get_draw_peds(Traversable::Turn(*t), map).into_iter() { - peds.push(Box::new(DrawPedestrian::new(p, map))); + let on = Traversable::Turn(*t); + if !self.agents.borrow().has(sim.tick(), on) { + let mut list: Vec> = Vec::new(); + for c in sim.get_draw_cars(on, map).into_iter() { + list.push(draw_vehicle(c, map)); + } + for p in sim.get_draw_peds(on, map).into_iter() { + list.push(Box::new(DrawPedestrian::new(p, map))); + } + self.agents.borrow_mut().put(sim.tick(), on, list); } + agents_on.push(on); } } } @@ -340,11 +359,11 @@ impl DrawMap { borrows.extend(extra_shapes); borrows.extend(bus_stops); borrows.extend(turn_icons); - for c in &cars { - borrows.push(Box::new(c.borrow())); - } - for p in &peds { - borrows.push(Box::new(p.borrow())); + let cache = self.agents.borrow(); + for on in agents_on { + for obj in cache.get(on) { + borrows.push(obj); + } } // This is a stable sort. @@ -361,3 +380,35 @@ impl DrawMap { } } } + +struct AgentCache { + tick: Option, + agents_per_on: HashMap>>, +} + +impl AgentCache { + fn has(&self, tick: Tick, on: Traversable) -> bool { + if Some(tick) != self.tick { + return false; + } + self.agents_per_on.contains_key(&on) + } + + // Must call has() first. + fn get(&self, on: Traversable) -> Vec> { + self.agents_per_on[&on] + .iter() + .map(|obj| Box::new(obj.borrow())) + .collect() + } + + fn put(&mut self, tick: Tick, on: Traversable, agents: Vec>) { + if Some(tick) != self.tick { + self.agents_per_on.clear(); + self.tick = Some(tick); + } + + assert!(!self.agents_per_on.contains_key(&on)); + self.agents_per_on.insert(on, agents); + } +} diff --git a/sim/src/render.rs b/sim/src/render.rs index 5088ebb2d3..400809dcb4 100644 --- a/sim/src/render.rs +++ b/sim/src/render.rs @@ -1,4 +1,4 @@ -use crate::{CarID, PedestrianID, Sim, VehicleType}; +use crate::{CarID, PedestrianID, Sim, Tick, VehicleType}; use geom::{PolyLine, Pt2D}; use map_model::{LaneType, Map, Trace, Traversable, TurnID}; @@ -37,6 +37,7 @@ pub enum CarState { // actually good for main sim too; we're constantly calculating stuff while sim is paused // otherwise? except we don't know what to calculate. maybe cache it? pub trait GetDrawAgents { + fn tick(&self) -> Tick; fn get_draw_car(&self, id: CarID, map: &Map) -> Option; fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option; fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec; @@ -46,6 +47,10 @@ pub trait GetDrawAgents { } impl GetDrawAgents for Sim { + fn tick(&self) -> Tick { + self.time + } + fn get_draw_car(&self, id: CarID, map: &Map) -> Option { self.driving_state .get_draw_car(id, self.time, map)