mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'sam/parallelize-beam' into 'master'
Parallelized beam See merge request veloren/veloren!1944
This commit is contained in:
commit
bf5be892d8
@ -9,10 +9,11 @@ use common::{
|
|||||||
uid::{Uid, UidAllocator},
|
uid::{Uid, UidAllocator},
|
||||||
GroupTarget,
|
GroupTarget,
|
||||||
};
|
};
|
||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, ParMode, Phase, System};
|
||||||
|
use rayon::iter::ParallelIterator;
|
||||||
use specs::{
|
use specs::{
|
||||||
saveload::MarkerAllocator, shred::ResourceId, Entities, Join, Read, ReadStorage, SystemData,
|
saveload::MarkerAllocator, shred::ResourceId, Entities, Join, ParJoin, Read, ReadStorage,
|
||||||
World, WriteStorage,
|
SystemData, World, WriteStorage,
|
||||||
};
|
};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -51,34 +52,36 @@ impl<'a> System<'a> for Sys {
|
|||||||
const ORIGIN: Origin = Origin::Common;
|
const ORIGIN: Origin = Origin::Common;
|
||||||
const PHASE: Phase = Phase::Create;
|
const PHASE: Phase = Phase::Create;
|
||||||
|
|
||||||
fn run(_job: &mut Job<Self>, (read_data, mut beam_segments, mut beams): Self::SystemData) {
|
fn run(job: &mut Job<Self>, (read_data, mut beam_segments, mut beams): Self::SystemData) {
|
||||||
let mut server_emitter = read_data.server_bus.emitter();
|
let mut server_emitter = read_data.server_bus.emitter();
|
||||||
|
|
||||||
let time = read_data.time.0;
|
let time = read_data.time.0;
|
||||||
let dt = read_data.dt.0;
|
let dt = read_data.dt.0;
|
||||||
|
|
||||||
|
job.cpu_stats.measure(ParMode::Rayon);
|
||||||
|
|
||||||
// Beams
|
// Beams
|
||||||
for (entity, pos, ori, beam_segment) in (
|
let (server_events, add_hit_entities) = (
|
||||||
&read_data.entities,
|
&read_data.entities,
|
||||||
&read_data.positions,
|
&read_data.positions,
|
||||||
&read_data.orientations,
|
&read_data.orientations,
|
||||||
&beam_segments,
|
&beam_segments,
|
||||||
)
|
)
|
||||||
.join()
|
.par_join()
|
||||||
|
.fold(|| (Vec::new(), Vec::new()), |(mut server_events, mut add_hit_entities), (entity, pos, ori, beam_segment)|
|
||||||
{
|
{
|
||||||
let creation_time = match beam_segment.creation {
|
let creation_time = match beam_segment.creation {
|
||||||
Some(time) => time,
|
Some(time) => time,
|
||||||
// Skip newly created beam segments
|
// Skip newly created beam segments
|
||||||
None => continue,
|
None => return (server_events, add_hit_entities),
|
||||||
};
|
};
|
||||||
|
|
||||||
let end_time = creation_time + beam_segment.duration.as_secs_f64();
|
let end_time = creation_time + beam_segment.duration.as_secs_f64();
|
||||||
|
|
||||||
// If beam segment is out of time emit destroy event but still continue since it
|
// If beam segment is out of time emit destroy event but still continue since it
|
||||||
// may have traveled and produced effects a bit before reaching it's
|
// may have traveled and produced effects a bit before reaching it's
|
||||||
// end point
|
// end point
|
||||||
if end_time < time {
|
if end_time < time {
|
||||||
server_emitter.emit(ServerEvent::Destroy {
|
server_events.push(ServerEvent::Destroy {
|
||||||
entity,
|
entity,
|
||||||
cause: HealthSource::World,
|
cause: HealthSource::World,
|
||||||
});
|
});
|
||||||
@ -87,9 +90,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
// Determine area that was covered by the beam in the last tick
|
// Determine area that was covered by the beam in the last tick
|
||||||
let frame_time = dt.min((end_time - time) as f32);
|
let frame_time = dt.min((end_time - time) as f32);
|
||||||
if frame_time <= 0.0 {
|
if frame_time <= 0.0 {
|
||||||
continue;
|
return (server_events, add_hit_entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: min() probably uneeded
|
// Note: min() probably uneeded
|
||||||
let time_since_creation = (time - creation_time) as f32;
|
let time_since_creation = (time - creation_time) as f32;
|
||||||
let frame_start_dist =
|
let frame_start_dist =
|
||||||
@ -104,10 +106,10 @@ impl<'a> System<'a> for Sys {
|
|||||||
// Might make this more nuanced if beams are used for non damage effects
|
// Might make this more nuanced if beams are used for non damage effects
|
||||||
let group = beam_owner.and_then(|e| read_data.groups.get(e));
|
let group = beam_owner.and_then(|e| read_data.groups.get(e));
|
||||||
|
|
||||||
let hit_entities = if let Some(beam) = beam_owner.and_then(|e| beams.get_mut(e)) {
|
let hit_entities = if let Some(beam) = beam_owner.and_then(|e| beams.get(e)) {
|
||||||
&mut beam.hit_entities
|
&beam.hit_entities
|
||||||
} else {
|
} else {
|
||||||
continue;
|
return (server_events, add_hit_entities);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Go through all other effectable entities
|
// Go through all other effectable entities
|
||||||
@ -176,12 +178,29 @@ impl<'a> System<'a> for Sys {
|
|||||||
ori.look_dir(),
|
ori.look_dir(),
|
||||||
false,
|
false,
|
||||||
1.0,
|
1.0,
|
||||||
|e| server_emitter.emit(e),
|
|e| server_events.push(e),
|
||||||
);
|
);
|
||||||
|
|
||||||
hit_entities.push(*uid_b);
|
add_hit_entities.push((beam_owner, *uid_b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(server_events, add_hit_entities)
|
||||||
|
}).reduce(|| (Vec::new(), Vec::new()), |(mut events_a, mut hit_entities_a), (mut events_b, mut hit_entities_b)| {
|
||||||
|
events_a.append(&mut events_b);
|
||||||
|
hit_entities_a.append(&mut hit_entities_b);
|
||||||
|
(events_a, hit_entities_a)
|
||||||
|
});
|
||||||
|
|
||||||
|
job.cpu_stats.measure(ParMode::Single);
|
||||||
|
|
||||||
|
for event in server_events {
|
||||||
|
server_emitter.emit(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (owner, hit_entity) in add_hit_entities {
|
||||||
|
if let Some(ref mut beam) = owner.and_then(|e| beams.get_mut(e)) {
|
||||||
|
beam.hit_entities.push(hit_entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for beam in (&mut beams).join() {
|
for beam in (&mut beams).join() {
|
||||||
|
Loading…
Reference in New Issue
Block a user