Skip to content

Commit

Permalink
refactor: codec abstraction and benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
mosure committed Nov 14, 2023
1 parent 13964ee commit b326da2
Show file tree
Hide file tree
Showing 16 changed files with 260 additions and 73 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: test

on:
pull_request:
types: [ labeled ]
branches: [ "main" ]

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1

jobs:
bench:
if: ${{ github.event.label.name == 'bench' }}

strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest]

runs-on: ${{ matrix.os }}
timeout-minutes: 120

steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-build-stable-${{ hashFiles('**/Cargo.toml') }}

- name: criterion compare
uses: boa-dev/[email protected]
with:
branchName: ${{ github.base_ref }}
token: ${{ secrets.GITHUB_TOKEN }}
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,15 @@ jobs:
target/
key: ${{ runner.os }}-cargo-build-stable-${{ hashFiles('**/Cargo.toml') }}

- name: check
run: cargo check

- name: build
run: cargo build

- name: build_tools
run: cargo build --bin ply_to_gcloud

- name: lint
run: cargo clippy

Expand Down
17 changes: 17 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ exclude = [".devcontainer", ".github", "docs", "dist", "build", "assets", "credi
default-run = "viewer"


[features]
default = ["io_flexbuffers"]

io_bincode2 = []
io_capnp = []
io_flexbuffers = []


# TODO: separate dev-dependencies
[dependencies]
bevy-inspector-egui = "0.21"
Expand Down Expand Up @@ -49,6 +57,10 @@ features = [
]


[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }


[profile.dev.package."*"]
opt-level = 3

Expand Down Expand Up @@ -77,3 +89,8 @@ path = "viewer/viewer.rs"
[[bin]]
name = "ply_to_gcloud"
path = "tools/ply_to_gcloud.rs"


[[bench]]
name = "io"
harness = false
47 changes: 47 additions & 0 deletions benches/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use criterion::{
BenchmarkId,
criterion_group,
criterion_main,
Criterion,
Throughput,
};

use bevy_gaussian_splatting::{
Gaussian,
GaussianCloud,
io::codec::GaussianCloudCodec,
random_gaussians,
};


const GAUSSIAN_COUNTS: [usize; 4] = [
1000,
10000,
84_348,
1_244_819,
// 6_131_954,
];

fn gaussian_cloud_decode_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("encode gaussian clouds");
for count in GAUSSIAN_COUNTS.iter() {
group.throughput(Throughput::Bytes(*count as u64 * std::mem::size_of::<Gaussian>() as u64));
group.bench_with_input(
BenchmarkId::new("decode", count),
&count,
|b, &count| {
let gaussians = random_gaussians(*count);
let bytes = gaussians.encode();

b.iter(|| GaussianCloud::decode(bytes.as_slice()));
},
);
}
}

criterion_group!{
name = io_benches;
config = Criterion::default().sample_size(10);
targets = gaussian_cloud_decode_benchmark
}
criterion_main!(io_benches);
70 changes: 5 additions & 65 deletions src/gaussian.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,26 @@
use rand::{seq::SliceRandom, prelude::Distribution, Rng};
use std::{
io::{
BufReader,
Cursor,
ErrorKind,
},
marker::Copy,
use rand::{
seq::SliceRandom,
prelude::Distribution,
Rng,
};
use std::marker::Copy;

use bevy::{
prelude::*,
asset::{
AssetLoader,
AsyncReadExt,
LoadContext,
io::Reader,
},
reflect::TypeUuid,
render::render_resource::ShaderType,
utils::BoxedFuture,
};
use bytemuck::{
Pod,
Zeroable,
};
use flexbuffers::Reader as FlexReader;
use serde::{
Deserialize,
Serialize,
Serializer,
ser::SerializeTuple,
};

use crate::ply::parse_ply;


const fn num_sh_coefficients(degree: usize) -> usize {
if degree == 0 {
Expand Down Expand Up @@ -230,53 +217,6 @@ impl Default for GaussianCloudSettings {
}
}


#[derive(Default)]
pub struct GaussianCloudLoader;

impl AssetLoader for GaussianCloudLoader {
type Asset = GaussianCloud;
type Settings = ();
type Error = std::io::Error;

fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a Self::Settings,
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {

Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;

match load_context.path().extension() {
Some(ext) if ext == "ply" => {
let cursor = Cursor::new(bytes);
let mut f = BufReader::new(cursor);

let ply_cloud = parse_ply(&mut f)?;
let cloud = GaussianCloud(ply_cloud);

Ok(cloud)
},
Some(ext) if ext == "gcloud" => {
let reader = FlexReader::get_root(bytes.as_slice()).expect("failed to read flexbuffer");
let cloud = GaussianCloud::deserialize(reader).expect("deserialization failed");

Ok(cloud)
},
_ => Err(std::io::Error::new(ErrorKind::Other, "only .ply and .gcloud supported")),
}
})
}

fn extensions(&self) -> &[&str] {
&["ply", "gcloud"]
}
}


impl Distribution<Gaussian> for rand::distributions::Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Gaussian {
Gaussian {
Expand Down
6 changes: 6 additions & 0 deletions src/io/codec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

// TODO: support streamed codecs
pub trait GaussianCloudCodec {
fn encode(&self) -> Vec<u8>;
fn decode(data: &[u8]) -> Self;
}
Empty file added src/io/gcloud/bincode2.rs
Empty file.
2 changes: 2 additions & 0 deletions src/io/gcloud/capnp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@


30 changes: 30 additions & 0 deletions src/io/gcloud/flexbuffers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use flexbuffers::{
FlexbufferSerializer,
Reader,
};
use serde::{
Deserialize,
Serialize,
};

use crate::{
GaussianCloud,
io::codec::GaussianCloudCodec,
};


impl GaussianCloudCodec for GaussianCloud {
fn encode(&self) -> Vec<u8> {
let mut serializer = FlexbufferSerializer::new();
self.serialize(&mut serializer).expect("failed to serialize cloud");

serializer.view().to_vec()
}

fn decode(data: &[u8]) -> Self {
let reader = Reader::get_root(data).expect("failed to read flexbuffer");
let cloud = GaussianCloud::deserialize(reader).expect("deserialization failed");

cloud
}
}
8 changes: 8 additions & 0 deletions src/io/gcloud/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[cfg(feature = "io_bincode2")]
pub mod bincode2;

#[cfg(feature = "io_capnp")]
pub mod capnp;

#[cfg(feature = "io_flexbuffers")]
pub mod flexbuffers;
68 changes: 68 additions & 0 deletions src/io/loader.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::io::{
BufReader,
Cursor,
ErrorKind,
};

use bevy::{
asset::{
AssetLoader,
AsyncReadExt,
LoadContext,
io::Reader,
},
utils::BoxedFuture,
};

use crate::{
GaussianCloud,
io::{
codec::GaussianCloudCodec,
ply::parse_ply,
},
};


#[derive(Default)]
pub struct GaussianCloudLoader;

impl AssetLoader for GaussianCloudLoader {
type Asset = GaussianCloud;
type Settings = ();
type Error = std::io::Error;

fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a Self::Settings,
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {

Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;

match load_context.path().extension() {
Some(ext) if ext == "ply" => {
let cursor = Cursor::new(bytes);
let mut f = BufReader::new(cursor);

let ply_cloud = parse_ply(&mut f)?;
let cloud = GaussianCloud(ply_cloud);

Ok(cloud)
},
Some(ext) if ext == "gcloud" => {
let cloud = GaussianCloud::decode(bytes.as_slice());

Ok(cloud)
},
_ => Err(std::io::Error::new(ErrorKind::Other, "only .ply and .gcloud supported")),
}
})
}

fn extensions(&self) -> &[&str] {
&["ply", "gcloud"]
}
}
4 changes: 4 additions & 0 deletions src/io/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod codec;
pub mod gcloud;
pub mod loader;
pub mod ply;
File renamed without changes.
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ use bevy::prelude::*;
pub use gaussian::{
Gaussian,
GaussianCloud,
GaussianCloudLoader,
GaussianCloudSettings,
SphericalHarmonicCoefficients,
random_gaussians,
};

use io::loader::GaussianCloudLoader;

use render::RenderPipelinePlugin;

pub mod gaussian;
pub mod ply;
pub mod io;
pub mod render;
pub mod utils;

Expand Down
Loading

0 comments on commit b326da2

Please sign in to comment.