caching Renderables for agents

This commit is contained in:
Dustin Carlino 2019-02-01 14:44:21 -08:00
parent ff80d0d445
commit bc4ba647bc
4 changed files with 82 additions and 21 deletions

View File

@ -3,7 +3,8 @@
## Performance ## Performance
- cache draw stuff - 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 ## Quick n easy

View File

@ -98,6 +98,10 @@ impl TimeTravel {
} }
impl GetDrawAgents for TimeTravel { impl GetDrawAgents for TimeTravel {
fn tick(&self) -> Tick {
self.current_tick.unwrap()
}
fn get_draw_car(&self, id: CarID, _map: &Map) -> Option<DrawCarInput> { fn get_draw_car(&self, id: CarID, _map: &Map) -> Option<DrawCarInput> {
self.get_current_state().cars.get(&id).cloned() self.get_current_state().cars.get(&id).cloned()
} }

View File

@ -19,8 +19,9 @@ use map_model::{
AreaID, BuildingID, BusStopID, FindClosest, IntersectionID, Lane, LaneID, Map, ParcelID, AreaID, BuildingID, BusStopID, FindClosest, IntersectionID, Lane, LaneID, Map, ParcelID,
RoadID, Traversable, Turn, TurnID, LANE_THICKNESS, RoadID, Traversable, Turn, TurnID, LANE_THICKNESS,
}; };
use sim::GetDrawAgents; use sim::{GetDrawAgents, Tick};
use std::borrow::Borrow; use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(PartialEq)] #[derive(PartialEq)]
@ -39,6 +40,8 @@ pub struct DrawMap {
pub bus_stops: HashMap<BusStopID, DrawBusStop>, pub bus_stops: HashMap<BusStopID, DrawBusStop>,
pub areas: Vec<DrawArea>, pub areas: Vec<DrawArea>,
agents: RefCell<AgentCache>,
quadtree: QuadTree<ID>, quadtree: QuadTree<ID>,
} }
@ -171,6 +174,11 @@ impl DrawMap {
bus_stops, bus_stops,
areas, areas,
agents: RefCell::new(AgentCache {
tick: None,
agents_per_on: HashMap::new(),
}),
quadtree, quadtree,
} }
} }
@ -282,9 +290,8 @@ impl DrawMap {
let mut extra_shapes: Vec<Box<&Renderable>> = Vec::new(); let mut extra_shapes: Vec<Box<&Renderable>> = Vec::new();
let mut bus_stops: Vec<Box<&Renderable>> = Vec::new(); let mut bus_stops: Vec<Box<&Renderable>> = Vec::new();
let mut turn_icons: Vec<Box<&Renderable>> = Vec::new(); let mut turn_icons: Vec<Box<&Renderable>> = Vec::new();
// We can't immediately grab the Renderables; we need to do it all at once at the end.
let mut cars: Vec<Box<Renderable>> = Vec::new(); let mut agents_on: Vec<Traversable> = Vec::new();
let mut peds: Vec<Box<Renderable>> = Vec::new();
for &(id, _, _) in &self.quadtree.query(screen_bounds.as_bbox()) { for &(id, _, _) in &self.quadtree.query(screen_bounds.as_bbox()) {
if show_objs.show(*id) { if show_objs.show(*id) {
@ -294,12 +301,18 @@ impl DrawMap {
ID::Lane(id) => { ID::Lane(id) => {
lanes.push(Box::new(self.get_l(*id))); lanes.push(Box::new(self.get_l(*id)));
if !show_objs.show_icons_for(map.get_l(*id).dst_i) { 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() { let on = Traversable::Lane(*id);
cars.push(draw_vehicle(c, map)); if !self.agents.borrow().has(sim.tick(), on) {
} let mut list: Vec<Box<Renderable>> = Vec::new();
for p in sim.get_draw_peds(Traversable::Lane(*id), map).into_iter() { for c in sim.get_draw_cars(on, map).into_iter() {
peds.push(Box::new(DrawPedestrian::new(p, map))); 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) => { ID::Intersection(id) => {
@ -308,12 +321,18 @@ impl DrawMap {
if show_objs.show_icons_for(*id) { if show_objs.show_icons_for(*id) {
turn_icons.push(Box::new(self.get_t(*t))); turn_icons.push(Box::new(self.get_t(*t)));
} else { } else {
for c in sim.get_draw_cars(Traversable::Turn(*t), map).into_iter() { let on = Traversable::Turn(*t);
cars.push(draw_vehicle(c, map)); if !self.agents.borrow().has(sim.tick(), on) {
} let mut list: Vec<Box<Renderable>> = Vec::new();
for p in sim.get_draw_peds(Traversable::Turn(*t), map).into_iter() { for c in sim.get_draw_cars(on, map).into_iter() {
peds.push(Box::new(DrawPedestrian::new(p, map))); 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(extra_shapes);
borrows.extend(bus_stops); borrows.extend(bus_stops);
borrows.extend(turn_icons); borrows.extend(turn_icons);
for c in &cars { let cache = self.agents.borrow();
borrows.push(Box::new(c.borrow())); for on in agents_on {
} for obj in cache.get(on) {
for p in &peds { borrows.push(obj);
borrows.push(Box::new(p.borrow())); }
} }
// This is a stable sort. // This is a stable sort.
@ -361,3 +380,35 @@ impl DrawMap {
} }
} }
} }
struct AgentCache {
tick: Option<Tick>,
agents_per_on: HashMap<Traversable, Vec<Box<Renderable>>>,
}
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<Box<&Renderable>> {
self.agents_per_on[&on]
.iter()
.map(|obj| Box::new(obj.borrow()))
.collect()
}
fn put(&mut self, tick: Tick, on: Traversable, agents: Vec<Box<Renderable>>) {
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);
}
}

View File

@ -1,4 +1,4 @@
use crate::{CarID, PedestrianID, Sim, VehicleType}; use crate::{CarID, PedestrianID, Sim, Tick, VehicleType};
use geom::{PolyLine, Pt2D}; use geom::{PolyLine, Pt2D};
use map_model::{LaneType, Map, Trace, Traversable, TurnID}; 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 // 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? // otherwise? except we don't know what to calculate. maybe cache it?
pub trait GetDrawAgents { pub trait GetDrawAgents {
fn tick(&self) -> Tick;
fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput>; fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput>;
fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput>; fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput>;
fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput>; fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput>;
@ -46,6 +47,10 @@ pub trait GetDrawAgents {
} }
impl GetDrawAgents for Sim { impl GetDrawAgents for Sim {
fn tick(&self) -> Tick {
self.time
}
fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> { fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
self.driving_state self.driving_state
.get_draw_car(id, self.time, map) .get_draw_car(id, self.time, map)