Skip to content

Commit

Permalink
Merge pull request #37 from hecrj/feature/batch-extend
Browse files Browse the repository at this point in the history
Implement `Extend` and `ParallelExtend` for `Batch`
  • Loading branch information
hecrj authored May 31, 2019
2 parents 1eed5af + 81f54e6 commit 817245f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 11 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `Transformation::rotate`. Creates a transformation representing a rotation. [#28]
- `Batch::clear`. Clears the batch contents, useful to reuse batches in different
frames.
- Implementation of `Extend` for `Batch`. [#37]
- Implementation of `ParallelExtend` for `Batch`. A `Batch` can now be populated
using multiple threads, useful to improve performance when dealing with many
thousands of quads. [#37]
- Multiple gravity centers based on mouse clicks in the particles example. [#30]

### Changed
- The performance of the particles example has been improved on Windows.
- The performance of the particles example has been improved considerably on all
platforms. [#37]

[#25]: https://github.com/hecrj/coffee/pull/25
[#26]: https://github.com/hecrj/coffee/pull/26
[#28]: https://github.com/hecrj/coffee/pull/28
[#30]: https://github.com/hecrj/coffee/pull/30
[#37]: https://github.com/hecrj/coffee/pull/37


## [0.2.0] - 2019-04-28
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ debug = []
[dependencies]
image = "0.21"
nalgebra = "0.18"
rayon = "1.0"

# gfx (OpenGL)
gfx = { version = "0.18", optional = true }
Expand All @@ -47,4 +48,3 @@ wgpu_glyph = { version = "0.3", optional = true }
[dev-dependencies]
# Example dependencies
rand = "0.6"
rayon = "1.0"
24 changes: 15 additions & 9 deletions examples/particles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ struct Particles {
}

impl Particles {
// Try increasing this value! I (@hecrj) can render 350k particles at 100fps
// on my system. I have not tried going above that, yet...
// Try increasing this value! I (@hecrj) can render 1 MILLION particles at
// 90 fps on my system (4790k, GTX 980, Windows 7) using Vulkan.
const AMOUNT: u32 = 50_000;

// Play with these values to alter the way gravity works.
Expand Down Expand Up @@ -148,30 +148,36 @@ impl Game for Particles {
fn draw(&self, view: &mut View, frame: &mut Frame, timer: &Timer) {
frame.clear(Color::BLACK);

// Draw particles all at once!
view.batch.clear();

// When interpolating, we need to know how close the next tick is
let delta_factor = if view.interpolate {
timer.next_tick_proximity()
} else {
0.0
};

for particle in &self.particles {
// Generate sprites in parallel! <3 rayon
let sprites = self.particles.par_iter().map(|particle| {
let velocity =
particle.velocity + particle.acceleration * delta_factor;

view.batch.add(Sprite {
Sprite {
source: Rectangle {
x: View::particle_color(velocity),
y: 0,
width: 1,
height: 1,
},
position: particle.position + velocity * delta_factor,
});
}
}
});

// Clear batch contents from previous frame
view.batch.clear();

// Use the parallel iterator to populate the batch efficiently
view.batch.par_extend(sprites);

// Draw particles all at once!
view.batch
.draw(Point::new(0.0, 0.0), &mut frame.as_target());

Expand Down
43 changes: 43 additions & 0 deletions src/graphics/batch.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use rayon::prelude::*;

use crate::graphics::gpu;
use crate::graphics::{Image, IntoQuad, Point, Target, Transformation, Vector};

Expand Down Expand Up @@ -66,3 +68,44 @@ impl std::fmt::Debug for Batch {
write!(f, "Batch {{ image: {:?} }}", self.image,)
}
}

impl<Q: IntoQuad> Extend<Q> for Batch {
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = Q>,
{
let iter = iter.into_iter();
let x_unit = self.x_unit;
let y_unit = self.y_unit;

self.instances.extend(
iter.map(|quad| {
gpu::Instance::from(quad.into_quad(x_unit, y_unit))
}),
);
}
}

/// Extend the [`Batch`] using a parallel iterator from [`rayon`].
///
/// If you are dealing with many thousands of quads, `par_extend` can help you
/// speed up your drawing by using multiple threads to populate a [`Batch`].
///
/// [`Batch`]: struct.Batch.html
/// [`rayon`]: https://docs.rs/rayon/1.0/rayon/
impl<Q: IntoQuad + Send> ParallelExtend<Q> for Batch {
fn par_extend<I>(&mut self, par_iter: I)
where
I: IntoParallelIterator<Item = Q>,
{
let par_iter = par_iter.into_par_iter();
let x_unit = self.x_unit;
let y_unit = self.y_unit;

self.instances.par_extend(
par_iter.map(|quad| {
gpu::Instance::from(quad.into_quad(x_unit, y_unit))
}),
);
}
}

0 comments on commit 817245f

Please sign in to comment.