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
- 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

View File

@ -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<DrawCarInput> {
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,
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<BusStopID, DrawBusStop>,
pub areas: Vec<DrawArea>,
agents: RefCell<AgentCache>,
quadtree: QuadTree<ID>,
}
@ -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<Box<&Renderable>> = Vec::new();
let mut bus_stops: Vec<Box<&Renderable>> = Vec::new();
let mut turn_icons: Vec<Box<&Renderable>> = Vec::new();
let mut cars: Vec<Box<Renderable>> = Vec::new();
let mut peds: 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 agents_on: Vec<Traversable> = 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<Box<Renderable>> = 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<Box<Renderable>> = 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<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 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<DrawCarInput>;
fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput>;
fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput>;
@ -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<DrawCarInput> {
self.driving_state
.get_draw_car(id, self.time, map)