Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
test:
name: Test Suite
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 10
strategy:
matrix:
crate: ['bevy_gpu_compute_macro', 'bevy_gpu_compute_core', 'bevy_gpu_compute']
Expand Down Expand Up @@ -41,7 +41,7 @@ jobs:
clippy_check:
name: Clippy
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 10
strategy:
matrix:
crate: ['bevy_gpu_compute_macro', 'bevy_gpu_compute_core', 'bevy_gpu_compute']
Expand Down Expand Up @@ -71,7 +71,7 @@ jobs:
format:
name: Format
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 5
strategy:
matrix:
crate: ['bevy_gpu_compute_macro', 'bevy_gpu_compute_core', 'bevy_gpu_compute']
Expand All @@ -84,4 +84,32 @@ jobs:
components: rustfmt
- name: Run cargo fmt
run: cargo fmt -- --check
working-directory: ${{ matrix.crate }}
working-directory: ${{ matrix.crate }}

# examples:
# name: Run examples
# runs-on: ubuntu-latest
# timeout-minutes: 10
# strategy:
# matrix:
# example: ['collision_detection_demonstration']
# steps:
# - name: Checkout sources
# uses: actions/checkout@v4
# - name: Cache
# uses: actions/cache@v4
# with:
# path: |
# ~/.cargo/bin/
# ~/.cargo/registry/index/
# ~/.cargo/registry/cache/
# ~/.cargo/git/db/
# target/
# key: ${{ runner.os }}-cargo-example-bevy_gpu_compute-${{ hashFiles('**/Cargo.toml') }}
# - name: Install nightly toolchain
# uses: dtolnay/rust-toolchain@nightly
# - name: Install Dependencies
# run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev
# - name: Run cargo examples
# run: cargo run --example ${{ matrix.example }}
# working-directory: bevy_gpu_compute
21 changes: 14 additions & 7 deletions bevy_gpu_compute/examples/collision_detection_barebones/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@ fn main() {
.add_systems(Update, (handle_task_results, exit_and_show_results).chain())
.run();
}

// constants used to produce predictable collision results
const SPAWN_RANGE_MIN: i32 = -2;
const SPAWN_RANGE_MAX: i32 = 2;
const ENTITY_RADIUS: f32 = 1.1;
const EXIT_AFTER_FRAMES: u32 = 2;
const EXIT_AFTER_FRAMES: u32 = 3;
// expected results
const EXPECTED_NUM_ENTITIES: u32 = 16;
// 16 entities 100% intersecting should produce 120 collisions
const EXPECTED_COLLISIONS_PER_FRAME: usize = 58;

#[derive(Resource, Default)]
struct State {
pub num_entities: u32,
pub collision_count: usize,
pub collisions_per_frame: Vec<usize>,
}

#[wgsl_shader_module]
Expand Down Expand Up @@ -75,7 +79,7 @@ mod collision_detection_module {
let current_pos = WgslVecInput::vec_val::<Position>(current_entity);
let other_pos = WgslVecInput::vec_val::<Position>(other_entity);
let dist_squared = calculate_distance_squared(current_pos.v, other_pos.v);
let radius_sum = (current_radius + other_radius);
let radius_sum = current_radius + other_radius;
let rad_sum_sq = radius_sum * radius_sum;
let is_collision = dist_squared < rad_sum_sq;
if is_collision {
Expand Down Expand Up @@ -141,15 +145,18 @@ fn handle_task_results(mut gpu_task_reader: GpuTaskReader, mut state: ResMut<Sta
// your logic here
let count = collision_results.len();
log::info!("collisions this frame: {}", count);
log::info!("collision_results: {:?}", collision_results);
state.collision_count += count;
log::trace!("collision_results: {:?}", collision_results);
assert!(count == EXPECTED_COLLISIONS_PER_FRAME);
state.collisions_per_frame.push(count);
}
}

// when the local variable "count" goes above a certain number (representing frame count), exit the app
fn exit_and_show_results(mut count: Local<u32>, state: Res<State>, mut exit: EventWriter<AppExit>) {
if *count > EXIT_AFTER_FRAMES {
log::info!("collisions count: {}", state.collision_count);
let total_collisions = state.collisions_per_frame.iter().sum::<usize>();
log::trace!("total collisions count at exit: {}", total_collisions);
log::info!("Example completed successfully");
exit.send(AppExit::Success);
}
*count += 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use bevy::{
utils::default,
};

use crate::{ENTITY_RADIUS, SPAWN_RANGE_MAX, SPAWN_RANGE_MIN, State};
use crate::{ENTITY_RADIUS, EXPECTED_NUM_ENTITIES, SPAWN_RANGE_MAX, SPAWN_RANGE_MIN, State};

#[derive(Debug, Component)]
pub struct BoundingCircleComponent(pub BoundingCircle);
Expand Down Expand Up @@ -46,6 +46,7 @@ pub fn spawn_entities(
}
}
log::info!("total of {} entities spawned", count);
assert!(count == EXPECTED_NUM_ENTITIES);
state.num_entities = count;
}

Expand Down
66 changes: 48 additions & 18 deletions bevy_gpu_compute/examples/collision_detection_demonstration/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Demonstrates all features of the BevyGpuCompute library

use bevy::{
DefaultPlugins,
app::{App, AppExit, Startup, Update},
log,
app::{App, AppExit, PluginGroup, Startup, Update},
log::{self, LogPlugin},
prelude::{EventWriter, IntoSystemConfigs, Local, Query, Res, ResMut, Resource},
};
use bevy_gpu_compute::prelude::*;
Expand All @@ -15,7 +15,10 @@ use visuals::{BoundingCircleComponent, ColorHandles, spawn_camera, spawn_entitie
fn main() {
let mut binding = App::new();
let _app = binding
.add_plugins(DefaultPlugins)
.add_plugins(DefaultPlugins.set(LogPlugin {
level: log::Level::INFO,
..Default::default()
}))
.add_plugins(BevyGpuComputePlugin::default())
.init_resource::<ColorHandles>()
.init_resource::<State>()
Expand All @@ -28,15 +31,25 @@ fn main() {
.run();
}

// constants used to produce predictable collision results
const SPAWN_RANGE_MIN: i32 = -2;
const SPAWN_RANGE_MAX: i32 = 2;
const ENTITY_RADIUS: f32 = 1.1;
const EXIT_AFTER_FRAMES: u32 = 2;
const ENTITY_RADIUS: f32 = 100.1;
const RADIUS_MULTIPLIER_FRAME_0: f32 = 1.0;
const RADIUS_MULTIPLIER_FRAME_1: f32 = 0.01;
const RADIUS_MULTIPLIER_FRAME_2: f32 = 0.002;
const EXIT_AFTER_FRAMES: u32 = 3;
// expected results
const EXPECTED_NUM_ENTITIES: u32 = 16;
// 16 entities 100% intersecting should produce 120 collisions
const EXPECTED_COLLISIONS_FRAME_0: usize = 120;
const EXPECTED_COLLISIONS_FRAME_1: usize = 58;
const EXPECTED_COLLISIONS_FRAME_2: usize = 0;

#[derive(Resource, Default)]
struct State {
pub num_entities: u32,
pub collision_count: usize,
pub collisions_per_frame: Vec<usize>,
}

#[wgsl_shader_module]
Expand Down Expand Up @@ -161,13 +174,13 @@ fn modify_task(mut gpu_tasks: GpuTaskRunner, state: Res<State>) {
gpu_tasks.run_commands(pending_commands);
}
fn modify_task_config_inputs(mut count: Local<u32>, mut gpu_tasks: GpuTaskRunner) {
let radius_multiplier =
(EXIT_AFTER_FRAMES as i32 - *count as i32) as f32 / EXIT_AFTER_FRAMES as f32;
log::info!("rad_mult: {}", radius_multiplier);
// below needs to simplify
// let mut config = ConfigInputData::<collision_detection_module::Types>::empty();
// config.set_input0(collision_detection_module::Config { radius_multiplier });

let radius_multiplier = if *count <= 0 {
RADIUS_MULTIPLIER_FRAME_0
} else if *count == 1 {
RADIUS_MULTIPLIER_FRAME_1
} else {
RADIUS_MULTIPLIER_FRAME_2
};
let configs = collision_detection_module::ConfigInputDataBuilder::new()
.set_config(collision_detection_module::Config { radius_multiplier })
.finish();
Expand Down Expand Up @@ -202,25 +215,42 @@ fn handle_task_results(mut gpu_task_reader: GpuTaskReader, mut state: ResMut<Sta
let results = gpu_task_reader
.latest_results::<collision_detection_module::OutputDataBuilder>("collision_detection");

// log::info!("results: {:?}", results);c
if let Ok(results) = results {
#[allow(unused_variables)]
let debug_results = results.my_debug_info.unwrap();
// log::info!("debug results: {:?}", debug_results);
log::debug!("debug results: {:?}", debug_results);
//fully type-safe results
let collision_results = results.collision_result.unwrap();
// your logic here
let count = collision_results.len();
log::info!("collisions this frame: {}", count);
log::info!("collision_results: {:?}", collision_results);
state.collision_count += count;
log::trace!("collision_results: {:?}", collision_results);
state.collisions_per_frame.push(count);
}
}

// when the local variable "count" goes above a certain number (representing frame count), exit the app
fn exit_and_show_results(mut count: Local<u32>, state: Res<State>, mut exit: EventWriter<AppExit>) {
if *count > EXIT_AFTER_FRAMES {
log::info!("collisions count: {}", state.collision_count);
let total_collisions = state.collisions_per_frame.iter().sum::<usize>();
log::trace!("total collisions count at exit: {}", total_collisions);
// verify results are what we expect
assert_eq!(
state.collisions_per_frame[0], EXPECTED_COLLISIONS_FRAME_0,
"unexpected collision count for frame 0: {}",
state.collisions_per_frame[0]
);
assert_eq!(
state.collisions_per_frame[1], EXPECTED_COLLISIONS_FRAME_1,
"unexpected collision count for frame 1: {}",
state.collisions_per_frame[1]
);
assert_eq!(
state.collisions_per_frame[2], EXPECTED_COLLISIONS_FRAME_2,
"unexpected collision count for frame 2: {}",
state.collisions_per_frame[2]
);
log::info!("Example completed successfully");
exit.send(AppExit::Success);
}
*count += 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use bevy::{
utils::default,
};

use crate::{ENTITY_RADIUS, SPAWN_RANGE_MAX, SPAWN_RANGE_MIN, State};
use crate::{ENTITY_RADIUS, EXPECTED_NUM_ENTITIES, SPAWN_RANGE_MAX, SPAWN_RANGE_MIN, State};

#[derive(Debug, Component)]
pub struct BoundingCircleComponent(pub BoundingCircle);
Expand Down Expand Up @@ -46,6 +46,7 @@ pub fn spawn_entities(
}
}
log::info!("total of {} entities spawned", count);
assert!(count == EXPECTED_NUM_ENTITIES);
state.num_entities = count;
}

Expand Down
4 changes: 2 additions & 2 deletions bevy_gpu_compute/src/spawn_fallback_camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn spawn_fallback_camera(
let len = cameras.iter().len();
match len {
0 => {
log::info!(
log::debug!(
"GPU Compute: Spawning fallback camera in order to improve gpu performance."
);
commands.spawn((
Expand All @@ -42,7 +42,7 @@ pub fn spawn_fallback_camera(
// do nothing
}
_ => {
log::info!("GPU Compute: Despawning extra fallback cameras.");
log::trace!("GPU Compute: Despawning extra fallback cameras.");
let fallback_cam_len = fallback_cameras.iter().len();
if fallback_cam_len > 0 {
fallback_cameras.iter().for_each(|(e, _)| {
Expand Down
2 changes: 1 addition & 1 deletion bevy_gpu_compute/src/system_params/task_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl GpuTaskRunner<'_, '_> {
.expect("Task entity not found");
let mut should_recompute_memory = false;
for cmd in commands.commands {
log::info!("Running command: {}", cmd);
log::trace!("Running command: {}", cmd);
match cmd {
GpuTaskCommand::SetConfigInputs(inputs) => {
task.current_data_mut().set_config_input(*inputs);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use bevy::{
log::{self, info},
log::{self},
render::renderer::RenderDevice,
};
use wgpu::{BufferUsages, util::BufferInitDescriptor};

use crate::task::lib::BevyGpuComputeTask;

pub fn update_config_input_buffers(task: &mut BevyGpuComputeTask, render_device: &RenderDevice) {
log::info!("Creating config input buffers for task {}", task.name());
log::trace!("Creating config input buffers for task {}", task.name());
task.buffers_mut().config.clear();
let mut new_buffers = Vec::new();
for s in task.configuration().inputs().configs().iter() {
Expand All @@ -23,7 +23,7 @@ pub fn update_config_input_buffers(task: &mut BevyGpuComputeTask, render_device:
.unwrap(),
usage: BufferUsages::UNIFORM,
});
info!(
log::trace!(
"Created config input buffer for task {} with label {}",
task.name(),
label
Expand Down
7 changes: 5 additions & 2 deletions bevy_gpu_compute/src/task/buffers/create_input_buffers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use bevy::{log::info, render::renderer::RenderDevice};
use bevy::{
log::{self},
render::renderer::RenderDevice,
};
use wgpu::{BufferUsages, util::BufferInitDescriptor};

use crate::task::lib::BevyGpuComputeTask;
Expand All @@ -20,7 +23,7 @@ pub fn update_input_buffers(task: &mut BevyGpuComputeTask, render_device: &Rende
usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,
});
new_buffers.push(buffer);
info!(
log::trace!(
"Created input buffer for task {} with label {}",
task.name(),
label
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub fn update_compute_pipeline(task: &mut BevyGpuComputeTask, render_device: &Re
if task.current_data().input_lengths().is_none() {
return;
}
log::info!("Updating pipeline for task {}", task.name());
log::trace!("Updating pipeline for task {}", task.name());
let key = PipelineKey {
pipeline_consts_version: task.configuration().version(),
};
Expand All @@ -21,8 +21,11 @@ pub fn update_compute_pipeline(task: &mut BevyGpuComputeTask, render_device: &Re
.contains_key(&key)
{
} else {
log::info!("Creating new pipeline for task {}", task.name());
log::info!(" layout {:?}", task.runtime_state().pipeline_layout());
log::trace!("Creating new pipeline for task {}", task.name());
log::trace!(
"pipeline layout {:?}",
task.runtime_state().pipeline_layout()
);
let compute_pipeline = render_device.create_compute_pipeline(&ComputePipelineDescriptor {
label: Some(task.name()),
layout: Some(task.runtime_state().pipeline_layout()),
Expand Down
2 changes: 1 addition & 1 deletion bevy_gpu_compute/src/task/dispatch/create_bind_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ For example, this might be the wgsl code:
The numbers in the `@binding` are the bind group entry numbers. The `@group` is the bind group number. We are only using a single bind group in the current library version.
*/
pub fn create_bind_group(task: &mut BevyGpuComputeTask, render_device: &RenderDevice) {
log::info!("Creating bind group for task {}", task.name());
log::trace!("Creating bind group for task {}", task.name());
let mut bindings = Vec::new();
for (i, s) in task.configuration().inputs().configs().iter().enumerate() {
if let Some(conf_in_buff) = task.buffers().config.get(i) {
Expand Down
Loading