mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Instrument all par joins, defer ubiquitous pos/vel writes with a component instead of using vecs
This commit is contained in:
parent
767686b579
commit
ac03f818d7
@ -78,8 +78,8 @@ pub use self::{
|
||||
misc::Object,
|
||||
ori::Ori,
|
||||
phys::{
|
||||
Collider, ForceUpdate, Gravity, Mass, PhysicsState, Pos, PreviousPhysCache, Scale, Sticky,
|
||||
Vel,
|
||||
Collider, ForceUpdate, Gravity, Mass, PhysicsState, Pos, PosVelDefer, PreviousPhysCache,
|
||||
Scale, Sticky, Vel,
|
||||
},
|
||||
player::Player,
|
||||
poise::{Poise, PoiseChange, PoiseSource, PoiseState},
|
||||
|
@ -4,19 +4,34 @@ use specs::{Component, DerefFlaggedStorage, NullStorage};
|
||||
use specs_idvs::IdvStorage;
|
||||
use vek::*;
|
||||
|
||||
// Position
|
||||
/// Position
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Pos(pub Vec3<f32>);
|
||||
|
||||
impl Component for Pos {
|
||||
// TODO: why not regular vec storage????
|
||||
// TODO: component occupancy metrics
|
||||
type Storage = IdvStorage<Self>;
|
||||
}
|
||||
|
||||
// Velocity
|
||||
/// Velocity
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Vel(pub Vec3<f32>);
|
||||
|
||||
impl Component for Vel {
|
||||
// TODO: why not regular vec storage????
|
||||
type Storage = IdvStorage<Self>;
|
||||
}
|
||||
|
||||
/// Used to defer writes to Pos/Vel in nested join loops
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct PosVelDefer {
|
||||
pub pos: Pos,
|
||||
pub vel: Vel,
|
||||
}
|
||||
|
||||
impl Component for PosVelDefer {
|
||||
// TODO: why not regular vec storage????
|
||||
type Storage = IdvStorage<Self>;
|
||||
}
|
||||
|
||||
@ -37,6 +52,7 @@ pub struct PreviousPhysCache {
|
||||
}
|
||||
|
||||
impl Component for PreviousPhysCache {
|
||||
// TODO: why not regular vec storage????
|
||||
type Storage = IdvStorage<Self>;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ use common::{
|
||||
comp::{Ori, Pos, Vel},
|
||||
resources::{PlayerEntity, Time},
|
||||
};
|
||||
use common_base::prof_span;
|
||||
use common_ecs::{Job, Origin, Phase, System};
|
||||
use common_net::sync::InterpolatableComponent;
|
||||
use specs::{
|
||||
@ -44,20 +45,38 @@ impl<'a> System<'a> for InterpolationSystem {
|
||||
)
|
||||
.par_join()
|
||||
.filter(|(e, _, _, _)| Some(e) != player.as_ref())
|
||||
.for_each(|(_, pos, interp, vel)| {
|
||||
*pos = pos.interpolate(interp, time, vel);
|
||||
});
|
||||
.for_each_init(
|
||||
|| {
|
||||
prof_span!(guard, "interpolate pos rayon job");
|
||||
guard
|
||||
},
|
||||
|_guard, (_, pos, interp, vel)| {
|
||||
*pos = pos.interpolate(interp, time, vel);
|
||||
},
|
||||
);
|
||||
(&data.entities, &mut data.vel, &data.vel_interpdata)
|
||||
.par_join()
|
||||
.filter(|(e, _, _)| Some(e) != player.as_ref())
|
||||
.for_each(|(_, vel, interp)| {
|
||||
*vel = vel.interpolate(interp, time, &());
|
||||
});
|
||||
.for_each_init(
|
||||
|| {
|
||||
prof_span!(guard, "interpolate vel rayon job");
|
||||
guard
|
||||
},
|
||||
|_guard, (_, vel, interp)| {
|
||||
*vel = vel.interpolate(interp, time, &());
|
||||
},
|
||||
);
|
||||
(&data.entities, &mut data.ori, &data.ori_interpdata)
|
||||
.par_join()
|
||||
.filter(|(e, _, _)| Some(e) != player.as_ref())
|
||||
.for_each(|(_, ori, interp)| {
|
||||
*ori = ori.interpolate(interp, time, &());
|
||||
});
|
||||
.for_each_init(
|
||||
|| {
|
||||
prof_span!(guard, "interpolate ori rayon job");
|
||||
guard
|
||||
},
|
||||
|_guard, (_, ori, interp)| {
|
||||
*ori = ori.interpolate(interp, time, &());
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ use spatial_grid::SpatialGrid;
|
||||
use common::{
|
||||
comp::{
|
||||
body::ship::figuredata::VOXEL_COLLIDER_MANIFEST, BeamSegment, Body, CharacterState,
|
||||
Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos, PreviousPhysCache, Projectile,
|
||||
Scale, Shockwave, Sticky, Vel,
|
||||
Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos, PosVelDefer, PreviousPhysCache,
|
||||
Projectile, Scale, Shockwave, Sticky, Vel,
|
||||
},
|
||||
consts::{FRIC_GROUND, GRAVITY},
|
||||
event::{EventBus, ServerEvent},
|
||||
@ -17,7 +17,6 @@ use common::{
|
||||
};
|
||||
use common_base::{prof_span, span};
|
||||
use common_ecs::{Job, Origin, ParMode, Phase, PhysicsMetrics, System};
|
||||
use hashbrown::HashMap;
|
||||
use rayon::iter::ParallelIterator;
|
||||
use specs::{
|
||||
shred::{ResourceId, World},
|
||||
@ -99,6 +98,7 @@ pub struct PhysicsWrite<'a> {
|
||||
physics_states: WriteStorage<'a, PhysicsState>,
|
||||
positions: WriteStorage<'a, Pos>,
|
||||
velocities: WriteStorage<'a, Vel>,
|
||||
pos_vel_defers: WriteStorage<'a, PosVelDefer>,
|
||||
orientations: WriteStorage<'a, Ori>,
|
||||
previous_phys_cache: WriteStorage<'a, PreviousPhysCache>,
|
||||
}
|
||||
@ -238,7 +238,6 @@ impl<'a> PhysicsData<'a> {
|
||||
}
|
||||
|
||||
fn apply_pushback(&mut self, job: &mut Job<Sys>, spatial_grid: &SpatialGrid) {
|
||||
// TODO: make sure to check git stash show -p to make sure nothing was missed
|
||||
span!(_guard, "Apply pushback");
|
||||
job.cpu_stats.measure(ParMode::Rayon);
|
||||
let PhysicsData {
|
||||
@ -357,7 +356,7 @@ impl<'a> PhysicsData<'a> {
|
||||
let mass_other = mass_other
|
||||
.map(|m| m.0)
|
||||
.unwrap_or(previous_cache_other.scale);
|
||||
//This check after the pos check, as we currently don't have
|
||||
// This check after the pos check, as we currently don't have
|
||||
// that many
|
||||
// massless entites [citation needed]
|
||||
if mass_other == 0.0 {
|
||||
@ -453,6 +452,31 @@ impl<'a> PhysicsData<'a> {
|
||||
ref read,
|
||||
ref mut write,
|
||||
} = self;
|
||||
|
||||
prof_span!(guard, "insert PosVelDefer");
|
||||
// NOTE: keep in sync with join below
|
||||
(
|
||||
&read.entities,
|
||||
read.colliders.mask(),
|
||||
&write.positions,
|
||||
&write.velocities,
|
||||
write.orientations.mask(),
|
||||
write.physics_states.mask(),
|
||||
!&write.pos_vel_defers, // This is the one we are adding
|
||||
write.previous_phys_cache.mask(),
|
||||
!&read.mountings,
|
||||
)
|
||||
.join()
|
||||
.map(|t| (t.0, *t.2, *t.3))
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.for_each(|(entity, pos, vel)| {
|
||||
let _ = write
|
||||
.pos_vel_defers
|
||||
.insert(entity, PosVelDefer { pos, vel });
|
||||
});
|
||||
drop(guard);
|
||||
|
||||
// Apply movement inputs
|
||||
span!(guard, "Apply movement and terrain collision");
|
||||
let (positions, velocities, previous_phys_cache, orientations) = (
|
||||
@ -473,14 +497,19 @@ impl<'a> PhysicsData<'a> {
|
||||
!&read.mountings,
|
||||
)
|
||||
.par_join()
|
||||
.for_each(|(entity, pos, vel, physics_state, _)| {
|
||||
let in_loaded_chunk = read
|
||||
.terrain
|
||||
.get_key(read.terrain.pos_key(pos.0.map(|e| e.floor() as i32)))
|
||||
.is_some();
|
||||
// Integrate forces
|
||||
// Friction is assumed to be a constant dependent on location
|
||||
let friction = if physics_state.on_ground { 0.0 } else { FRIC_AIR }
|
||||
.for_each_init(
|
||||
|| {
|
||||
prof_span!(guard, "velocity update rayon job");
|
||||
guard
|
||||
},
|
||||
|_guard, (entity, pos, vel, physics_state, _)| {
|
||||
let in_loaded_chunk = read
|
||||
.terrain
|
||||
.get_key(read.terrain.pos_key(pos.0.map(|e| e.floor() as i32)))
|
||||
.is_some();
|
||||
// Integrate forces
|
||||
// Friction is assumed to be a constant dependent on location
|
||||
let friction = if physics_state.on_ground { 0.0 } else { FRIC_AIR }
|
||||
// .max(if physics_state.on_ground {
|
||||
// FRIC_GROUND
|
||||
// } else {
|
||||
@ -491,26 +520,27 @@ impl<'a> PhysicsData<'a> {
|
||||
} else {
|
||||
0.0
|
||||
});
|
||||
let downward_force =
|
||||
if !in_loaded_chunk {
|
||||
0.0 // No gravity in unloaded chunks
|
||||
} else if physics_state
|
||||
.in_liquid
|
||||
.map(|depth| depth > 0.75)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
(1.0 - BOUYANCY) * GRAVITY
|
||||
} else {
|
||||
GRAVITY
|
||||
} * read.gravities.get(entity).map(|g| g.0).unwrap_or_default();
|
||||
let downward_force =
|
||||
if !in_loaded_chunk {
|
||||
0.0 // No gravity in unloaded chunks
|
||||
} else if physics_state
|
||||
.in_liquid
|
||||
.map(|depth| depth > 0.75)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
(1.0 - BOUYANCY) * GRAVITY
|
||||
} else {
|
||||
GRAVITY
|
||||
} * read.gravities.get(entity).map(|g| g.0).unwrap_or_default();
|
||||
|
||||
vel.0 = integrate_forces(read.dt.0, vel.0, downward_force, friction);
|
||||
});
|
||||
vel.0 = integrate_forces(read.dt.0, vel.0, downward_force, friction);
|
||||
},
|
||||
);
|
||||
|
||||
let velocities = &write.velocities;
|
||||
|
||||
// Second pass: resolve collisions
|
||||
let (pos_writes, vel_writes, land_on_grounds) = (
|
||||
let land_on_grounds = (
|
||||
&read.entities,
|
||||
read.scales.maybe(),
|
||||
read.stickies.maybe(),
|
||||
@ -521,13 +551,17 @@ impl<'a> PhysicsData<'a> {
|
||||
read.bodies.maybe(),
|
||||
read.character_states.maybe(),
|
||||
&mut write.physics_states,
|
||||
&mut write.pos_vel_defers,
|
||||
previous_phys_cache,
|
||||
!&read.mountings,
|
||||
)
|
||||
.par_join()
|
||||
.fold(
|
||||
|| (Vec::new(), Vec::new(), Vec::new()),
|
||||
|(mut pos_writes, mut vel_writes, mut land_on_grounds),
|
||||
.map_init(
|
||||
|| {
|
||||
prof_span!(guard, "physics e<>t rayon job");
|
||||
guard
|
||||
},
|
||||
|_guard,
|
||||
(
|
||||
entity,
|
||||
scale,
|
||||
@ -539,16 +573,18 @@ impl<'a> PhysicsData<'a> {
|
||||
body,
|
||||
character_state,
|
||||
mut physics_state,
|
||||
pos_vel_defer,
|
||||
_previous_cache,
|
||||
_,
|
||||
)| {
|
||||
let mut land_on_ground = None;
|
||||
// Defer the writes of positions and velocities to allow an inner loop over
|
||||
// terrain-like entities
|
||||
let mut vel = *vel;
|
||||
let old_vel = vel;
|
||||
|
||||
if sticky.is_some() && physics_state.on_surface().is_some() {
|
||||
vel.0 = physics_state.ground_vel;
|
||||
return (pos_writes, vel_writes, land_on_grounds);
|
||||
return land_on_ground;
|
||||
}
|
||||
|
||||
let scale = if let Collider::Voxel { .. } = collider {
|
||||
@ -615,7 +651,7 @@ impl<'a> PhysicsData<'a> {
|
||||
was_on_ground,
|
||||
block_snap,
|
||||
climbing,
|
||||
|entity, vel| land_on_grounds.push((entity, vel)),
|
||||
|entity, vel| land_on_ground = Some((entity, vel)),
|
||||
);
|
||||
tgt_pos = cpos.0;
|
||||
},
|
||||
@ -644,7 +680,7 @@ impl<'a> PhysicsData<'a> {
|
||||
was_on_ground,
|
||||
block_snap,
|
||||
climbing,
|
||||
|entity, vel| land_on_grounds.push((entity, vel)),
|
||||
|entity, vel| land_on_ground = Some((entity, vel)),
|
||||
);
|
||||
tgt_pos = cpos.0;
|
||||
},
|
||||
@ -806,8 +842,8 @@ impl<'a> PhysicsData<'a> {
|
||||
block_snap,
|
||||
climbing,
|
||||
|entity, vel| {
|
||||
land_on_grounds
|
||||
.push((entity, Vel(ori_from.mul_direction(vel.0))))
|
||||
land_on_ground =
|
||||
Some((entity, Vel(ori_from.mul_direction(vel.0))));
|
||||
},
|
||||
);
|
||||
|
||||
@ -841,48 +877,52 @@ impl<'a> PhysicsData<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
if tgt_pos != pos.0 {
|
||||
pos_writes.push((entity, Pos(tgt_pos)));
|
||||
}
|
||||
if vel != old_vel {
|
||||
vel_writes.push((entity, vel));
|
||||
}
|
||||
*pos_vel_defer = PosVelDefer {
|
||||
pos: Pos(tgt_pos),
|
||||
vel,
|
||||
};
|
||||
|
||||
(pos_writes, vel_writes, land_on_grounds)
|
||||
land_on_ground
|
||||
},
|
||||
)
|
||||
.fold(
|
||||
|| Vec::new(),
|
||||
|mut land_on_grounds, land_on_ground| {
|
||||
land_on_ground.map(|log| land_on_grounds.push(log));
|
||||
land_on_grounds
|
||||
},
|
||||
)
|
||||
.reduce(
|
||||
|| (Vec::new(), Vec::new(), Vec::new()),
|
||||
|(mut pos_writes_a, mut vel_writes_a, mut land_on_grounds_a),
|
||||
(mut pos_writes_b, mut vel_writes_b, mut land_on_grounds_b)| {
|
||||
pos_writes_a.append(&mut pos_writes_b);
|
||||
vel_writes_a.append(&mut vel_writes_b);
|
||||
|| Vec::new(),
|
||||
|mut land_on_grounds_a, mut land_on_grounds_b| {
|
||||
land_on_grounds_a.append(&mut land_on_grounds_b);
|
||||
(pos_writes_a, vel_writes_a, land_on_grounds_a)
|
||||
land_on_grounds_a
|
||||
},
|
||||
);
|
||||
drop(guard);
|
||||
job.cpu_stats.measure(ParMode::Single);
|
||||
|
||||
let pos_writes: HashMap<Entity, Pos> = pos_writes.into_iter().collect();
|
||||
let vel_writes: HashMap<Entity, Vel> = vel_writes.into_iter().collect();
|
||||
for (entity, pos, vel) in
|
||||
(&read.entities, &mut write.positions, &mut write.velocities).join()
|
||||
prof_span!(guard, "write deferred pos and vel");
|
||||
for (_, pos, vel, pos_vel_defer) in (
|
||||
&read.entities,
|
||||
&mut write.positions,
|
||||
&mut write.velocities,
|
||||
&write.pos_vel_defers,
|
||||
)
|
||||
.join()
|
||||
{
|
||||
if let Some(new_pos) = pos_writes.get(&entity) {
|
||||
*pos = *new_pos;
|
||||
}
|
||||
|
||||
if let Some(new_vel) = vel_writes.get(&entity) {
|
||||
*vel = *new_vel;
|
||||
}
|
||||
*pos = pos_vel_defer.pos;
|
||||
*vel = pos_vel_defer.vel;
|
||||
}
|
||||
drop(guard);
|
||||
|
||||
prof_span!(guard, "record ori into phys_cache");
|
||||
for (ori, previous_phys_cache) in
|
||||
(&write.orientations, &mut write.previous_phys_cache).join()
|
||||
{
|
||||
previous_phys_cache.ori = ori.to_quat();
|
||||
}
|
||||
drop(guard);
|
||||
|
||||
let mut event_emitter = read.event_bus.emitter();
|
||||
land_on_grounds.into_iter().for_each(|(entity, vel)| {
|
||||
|
@ -161,6 +161,10 @@ impl State {
|
||||
ecs.register::<comp::Ori>();
|
||||
ecs.register::<comp::Inventory>();
|
||||
|
||||
// Register common unsynced components
|
||||
ecs.register::<comp::PreviousPhysCache>();
|
||||
ecs.register::<comp::PosVelDefer>();
|
||||
|
||||
// Register client-local components
|
||||
// TODO: only register on the client
|
||||
ecs.register::<comp::LightAnimation>();
|
||||
@ -188,7 +192,6 @@ impl State {
|
||||
ecs.register::<comp::invite::Invite>();
|
||||
ecs.register::<comp::invite::PendingInvites>();
|
||||
ecs.register::<comp::Beam>();
|
||||
ecs.register::<comp::PreviousPhysCache>();
|
||||
|
||||
// Register synced resources used by the ECS.
|
||||
ecs.insert(TimeOfDay(0.0));
|
||||
|
Loading…
Reference in New Issue
Block a user