Compare commits
12 Commits
custom
...
release-0.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6acf932cc9 | ||
![]() |
31af9d4ee1 | ||
![]() |
ef5c8e83ad | ||
![]() |
3ae96dd307 | ||
![]() |
523e7af739 | ||
![]() |
98cf6268dc | ||
![]() |
ec88fcacca | ||
![]() |
d11409028a | ||
![]() |
df3d100315 | ||
![]() |
398b15db5c | ||
![]() |
b9337debb9 | ||
![]() |
470f94d19e |
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
categories = ["game-engines", "graphics", "gui", "rendering"]
|
||||
description = "A refreshingly simple data-driven game engine and app framework"
|
||||
|
@ -469,15 +469,18 @@ mod tests {
|
||||
#[test]
|
||||
fn times_finished_precise() {
|
||||
let mut t = Timer::from_seconds(0.01, true);
|
||||
let duration = Duration::from_secs_f64(1.0 / 3.0);
|
||||
let duration = Duration::from_secs_f64(0.333);
|
||||
|
||||
// total duration: 0.333 => 33 times finished
|
||||
t.tick(duration);
|
||||
assert_eq!(t.times_finished(), 33);
|
||||
// total duration: 0.666 => 33 times finished
|
||||
t.tick(duration);
|
||||
assert_eq!(t.times_finished(), 33);
|
||||
// total duration: 0.999 => 33 times finished
|
||||
t.tick(duration);
|
||||
assert_eq!(t.times_finished(), 33);
|
||||
// It has one additional tick this time to compensate for missing 100th tick
|
||||
// total duration: 1.332 => 34 times finished
|
||||
t.tick(duration);
|
||||
assert_eq!(t.times_finished(), 34);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "bevy_crevice"
|
||||
description = "Create GLSL-compatible versions of structs with explicitly-initialized padding (Bevy version)"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
|
||||
documentation = "https://docs.rs/crevice"
|
||||
|
@ -268,7 +268,7 @@ where
|
||||
offset = item.write_std430(writer)?;
|
||||
}
|
||||
|
||||
for item in self.iter() {
|
||||
for item in iter {
|
||||
item.write_std430(writer)?;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_ecs"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
description = "Bevy Engine's entity component system"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -132,7 +132,7 @@ impl ParallelSystemExecutor for ParallelExecutor {
|
||||
.finish_receiver
|
||||
.recv()
|
||||
.await
|
||||
.unwrap_or_else(|error| unreachable!(error));
|
||||
.unwrap_or_else(|error| unreachable!("{}", error));
|
||||
self.process_finished_system(index);
|
||||
// Gather other systems than may have finished.
|
||||
while let Ok(index) = self.finish_receiver.try_recv() {
|
||||
@ -208,7 +208,7 @@ impl ParallelExecutor {
|
||||
start_receiver
|
||||
.recv()
|
||||
.await
|
||||
.unwrap_or_else(|error| unreachable!(error));
|
||||
.unwrap_or_else(|error| unreachable!("{}", error));
|
||||
#[cfg(feature = "trace")]
|
||||
let system_guard = system_span.enter();
|
||||
unsafe { system.run_unsafe((), world) };
|
||||
@ -217,7 +217,7 @@ impl ParallelExecutor {
|
||||
finish_sender
|
||||
.send(index)
|
||||
.await
|
||||
.unwrap_or_else(|error| unreachable!(error));
|
||||
.unwrap_or_else(|error| unreachable!("{}", error));
|
||||
};
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
@ -268,7 +268,7 @@ impl ParallelExecutor {
|
||||
.start_sender
|
||||
.send(())
|
||||
.await
|
||||
.unwrap_or_else(|error| unreachable!(error));
|
||||
.unwrap_or_else(|error| unreachable!("{}", error));
|
||||
self.running.set(index, true);
|
||||
if !system_metadata.is_send {
|
||||
self.non_send_running = true;
|
||||
|
@ -925,24 +925,30 @@ impl World {
|
||||
// the ptr value / drop is called when T is dropped
|
||||
unsafe { column.swap_remove_and_forget_unchecked(0) }
|
||||
};
|
||||
// SAFE: pointer is of type T
|
||||
let value = Mut {
|
||||
value: unsafe { &mut *ptr.cast::<T>() },
|
||||
// SAFE: pointer is of type T and valid to move out of
|
||||
// Read the value onto the stack to avoid potential mut aliasing.
|
||||
let mut value = unsafe { std::ptr::read(ptr.cast::<T>()) };
|
||||
let value_mut = Mut {
|
||||
value: &mut value,
|
||||
ticks: Ticks {
|
||||
component_ticks: &mut ticks,
|
||||
last_change_tick: self.last_change_tick(),
|
||||
change_tick: self.change_tick(),
|
||||
},
|
||||
};
|
||||
let result = f(self, value);
|
||||
let result = f(self, value_mut);
|
||||
assert!(!self.contains_resource::<T>());
|
||||
let resource_archetype = self.archetypes.resource_mut();
|
||||
let unique_components = resource_archetype.unique_components_mut();
|
||||
let column = unique_components
|
||||
.get_mut(component_id)
|
||||
.unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::<T>()));
|
||||
|
||||
// Wrap the value in MaybeUninit to prepare for passing the value back into the ECS
|
||||
let mut nodrop_wrapped_value = std::mem::MaybeUninit::new(value);
|
||||
unsafe {
|
||||
// SAFE: pointer is of type T
|
||||
column.push(ptr, ticks);
|
||||
// SAFE: pointer is of type T, and valid to move out of
|
||||
column.push(nodrop_wrapped_value.as_mut_ptr() as *mut _, ticks);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_pbr"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
description = "Adds PBR rendering to Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -641,7 +641,7 @@ pub fn prepare_lights(
|
||||
}
|
||||
|
||||
let mut gpu_point_lights = [GpuPointLight::default(); MAX_POINT_LIGHTS];
|
||||
for (index, &(entity, light)) in point_lights.iter().enumerate() {
|
||||
for (index, &(entity, light)) in point_lights.iter().enumerate().take(MAX_POINT_LIGHTS) {
|
||||
let mut flags = PointLightFlags::NONE;
|
||||
// Lights are sorted, shadow enabled lights are first
|
||||
if light.shadows_enabled && index < MAX_POINT_LIGHT_SHADOW_MAPS {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_render"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
description = "Provides rendering functionality for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -15,8 +15,16 @@ pub struct WgpuOptions {
|
||||
pub backends: Option<Backends>,
|
||||
pub power_preference: PowerPreference,
|
||||
pub priority: WgpuOptionsPriority,
|
||||
/// The enabled features. Setting features will require them to be enabled when initializing
|
||||
/// the renderer.
|
||||
pub features: WgpuFeatures,
|
||||
/// The features to ensure are disabled regardless of what the adapter/backend supports
|
||||
pub disabled_features: Option<WgpuFeatures>,
|
||||
/// The imposed limits. Updated based on adapter/backend limits when initializing the renderer
|
||||
/// if using WgpuOptionsPriority::Functionality
|
||||
pub limits: WgpuLimits,
|
||||
/// The constraints on limits allowed regardless of what the adapter/backend supports
|
||||
pub constrained_limits: Option<WgpuLimits>,
|
||||
}
|
||||
|
||||
impl Default for WgpuOptions {
|
||||
@ -50,7 +58,9 @@ impl Default for WgpuOptions {
|
||||
power_preference: PowerPreference::HighPerformance,
|
||||
priority,
|
||||
features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
|
||||
disabled_features: None,
|
||||
limits,
|
||||
constrained_limits: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ impl ShaderImportProcessor {
|
||||
|
||||
pub fn get_imports_from_str(&self, shader: &str) -> Vec<ShaderImport> {
|
||||
let mut imports = Vec::new();
|
||||
for line in shader.split('\n') {
|
||||
for line in shader.lines() {
|
||||
if let Some(cap) = self.import_asset_path_regex.captures(line) {
|
||||
let import = cap.get(1).unwrap();
|
||||
imports.push(ShaderImport::AssetPath(import.as_str().to_string()));
|
||||
@ -366,7 +366,7 @@ impl ShaderProcessor {
|
||||
let shader_defs_unique = HashSet::<String>::from_iter(shader_defs.iter().cloned());
|
||||
let mut scopes = vec![true];
|
||||
let mut final_string = String::new();
|
||||
for line in shader_str.split('\n') {
|
||||
for line in shader_str.lines() {
|
||||
if let Some(cap) = self.ifdef_regex.captures(line) {
|
||||
let def = cap.get(1).unwrap();
|
||||
scopes.push(*scopes.last().unwrap() && shader_defs_unique.contains(def.as_str()));
|
||||
@ -417,7 +417,6 @@ impl ShaderProcessor {
|
||||
final_string.push('\n');
|
||||
}
|
||||
}
|
||||
final_string.pop();
|
||||
|
||||
if scopes.len() != 1 {
|
||||
return Err(ProcessShaderError::NotEnoughEndIfs);
|
||||
|
@ -73,7 +73,8 @@ pub async fn initialize_renderer(
|
||||
.await
|
||||
.expect("Unable to find a GPU! Make sure you have installed required drivers!");
|
||||
|
||||
info!("{:?}", adapter.get_info());
|
||||
let adapter_info = adapter.get_info();
|
||||
info!("{:?}", adapter_info);
|
||||
|
||||
#[cfg(feature = "wgpu_trace")]
|
||||
let trace_path = {
|
||||
@ -85,10 +86,120 @@ pub async fn initialize_renderer(
|
||||
#[cfg(not(feature = "wgpu_trace"))]
|
||||
let trace_path = None;
|
||||
|
||||
// Maybe get features and limits based on what is supported by the adapter/backend
|
||||
let mut features = wgpu::Features::empty();
|
||||
let mut limits = options.limits.clone();
|
||||
if matches!(options.priority, WgpuOptionsPriority::Functionality) {
|
||||
options.features =
|
||||
adapter.features() | wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES;
|
||||
options.limits = adapter.limits();
|
||||
features = adapter.features() | wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES;
|
||||
if adapter_info.device_type == wgpu::DeviceType::DiscreteGpu {
|
||||
// `MAPPABLE_PRIMARY_BUFFERS` can have a significant, negative performance impact for
|
||||
// discrete GPUs due to having to transfer data across the PCI-E bus and so it
|
||||
// should not be automatically enabled in this case. It is however beneficial for
|
||||
// integrated GPUs.
|
||||
features -= wgpu::Features::MAPPABLE_PRIMARY_BUFFERS;
|
||||
}
|
||||
limits = adapter.limits();
|
||||
}
|
||||
|
||||
// Enforce the disabled features
|
||||
if let Some(disabled_features) = options.disabled_features {
|
||||
features -= disabled_features;
|
||||
}
|
||||
// NOTE: |= is used here to ensure that any explicitly-enabled features are respected.
|
||||
options.features |= features;
|
||||
|
||||
// Enforce the limit constraints
|
||||
if let Some(constrained_limits) = options.constrained_limits.as_ref() {
|
||||
// NOTE: Respect the configured limits as an 'upper bound'. This means for 'max' limits, we
|
||||
// take the minimum of the calculated limits according to the adapter/backend and the
|
||||
// specified max_limits. For 'min' limits, take the maximum instead. This is intended to
|
||||
// err on the side of being conservative. We can't claim 'higher' limits that are supported
|
||||
// but we can constrain to 'lower' limits.
|
||||
options.limits = wgpu::Limits {
|
||||
max_texture_dimension_1d: limits
|
||||
.max_texture_dimension_1d
|
||||
.min(constrained_limits.max_texture_dimension_1d),
|
||||
max_texture_dimension_2d: limits
|
||||
.max_texture_dimension_2d
|
||||
.min(constrained_limits.max_texture_dimension_2d),
|
||||
max_texture_dimension_3d: limits
|
||||
.max_texture_dimension_3d
|
||||
.min(constrained_limits.max_texture_dimension_3d),
|
||||
max_texture_array_layers: limits
|
||||
.max_texture_array_layers
|
||||
.min(constrained_limits.max_texture_array_layers),
|
||||
max_bind_groups: limits
|
||||
.max_bind_groups
|
||||
.min(constrained_limits.max_bind_groups),
|
||||
max_dynamic_uniform_buffers_per_pipeline_layout: limits
|
||||
.max_dynamic_uniform_buffers_per_pipeline_layout
|
||||
.min(constrained_limits.max_dynamic_uniform_buffers_per_pipeline_layout),
|
||||
max_dynamic_storage_buffers_per_pipeline_layout: limits
|
||||
.max_dynamic_storage_buffers_per_pipeline_layout
|
||||
.min(constrained_limits.max_dynamic_storage_buffers_per_pipeline_layout),
|
||||
max_sampled_textures_per_shader_stage: limits
|
||||
.max_sampled_textures_per_shader_stage
|
||||
.min(constrained_limits.max_sampled_textures_per_shader_stage),
|
||||
max_samplers_per_shader_stage: limits
|
||||
.max_samplers_per_shader_stage
|
||||
.min(constrained_limits.max_samplers_per_shader_stage),
|
||||
max_storage_buffers_per_shader_stage: limits
|
||||
.max_storage_buffers_per_shader_stage
|
||||
.min(constrained_limits.max_storage_buffers_per_shader_stage),
|
||||
max_storage_textures_per_shader_stage: limits
|
||||
.max_storage_textures_per_shader_stage
|
||||
.min(constrained_limits.max_storage_textures_per_shader_stage),
|
||||
max_uniform_buffers_per_shader_stage: limits
|
||||
.max_uniform_buffers_per_shader_stage
|
||||
.min(constrained_limits.max_uniform_buffers_per_shader_stage),
|
||||
max_uniform_buffer_binding_size: limits
|
||||
.max_uniform_buffer_binding_size
|
||||
.min(constrained_limits.max_uniform_buffer_binding_size),
|
||||
max_storage_buffer_binding_size: limits
|
||||
.max_storage_buffer_binding_size
|
||||
.min(constrained_limits.max_storage_buffer_binding_size),
|
||||
max_vertex_buffers: limits
|
||||
.max_vertex_buffers
|
||||
.min(constrained_limits.max_vertex_buffers),
|
||||
max_vertex_attributes: limits
|
||||
.max_vertex_attributes
|
||||
.min(constrained_limits.max_vertex_attributes),
|
||||
max_vertex_buffer_array_stride: limits
|
||||
.max_vertex_buffer_array_stride
|
||||
.min(constrained_limits.max_vertex_buffer_array_stride),
|
||||
max_push_constant_size: limits
|
||||
.max_push_constant_size
|
||||
.min(constrained_limits.max_push_constant_size),
|
||||
min_uniform_buffer_offset_alignment: limits
|
||||
.min_uniform_buffer_offset_alignment
|
||||
.max(constrained_limits.min_uniform_buffer_offset_alignment),
|
||||
min_storage_buffer_offset_alignment: limits
|
||||
.min_storage_buffer_offset_alignment
|
||||
.max(constrained_limits.min_storage_buffer_offset_alignment),
|
||||
max_inter_stage_shader_components: limits
|
||||
.max_inter_stage_shader_components
|
||||
.min(constrained_limits.max_inter_stage_shader_components),
|
||||
max_compute_workgroup_storage_size: limits
|
||||
.max_compute_workgroup_storage_size
|
||||
.min(constrained_limits.max_compute_workgroup_storage_size),
|
||||
max_compute_invocations_per_workgroup: limits
|
||||
.max_compute_invocations_per_workgroup
|
||||
.min(constrained_limits.max_compute_invocations_per_workgroup),
|
||||
max_compute_workgroup_size_x: limits
|
||||
.max_compute_workgroup_size_x
|
||||
.min(constrained_limits.max_compute_workgroup_size_x),
|
||||
max_compute_workgroup_size_y: limits
|
||||
.max_compute_workgroup_size_y
|
||||
.min(constrained_limits.max_compute_workgroup_size_y),
|
||||
max_compute_workgroup_size_z: limits
|
||||
.max_compute_workgroup_size_z
|
||||
.min(constrained_limits.max_compute_workgroup_size_z),
|
||||
max_compute_workgroups_per_dimension: limits
|
||||
.max_compute_workgroups_per_dimension
|
||||
.min(constrained_limits.max_compute_workgroups_per_dimension),
|
||||
};
|
||||
} else {
|
||||
options.limits = limits;
|
||||
}
|
||||
|
||||
let (device, queue) = adapter
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_ui"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
description = "A custom ECS-driven UI framework built specifically for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -72,14 +72,9 @@ pub fn ui_focus_system(
|
||||
Option<&CalculatedClip>,
|
||||
)>,
|
||||
) {
|
||||
let cursor_position = if let Some(cursor_position) = windows
|
||||
let cursor_position = windows
|
||||
.get_primary()
|
||||
.and_then(|window| window.cursor_position())
|
||||
{
|
||||
cursor_position
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
.and_then(|window| window.cursor_position());
|
||||
|
||||
// reset entities that were both clicked and released in the last frame
|
||||
for entity in state.entities_to_reset.drain(..) {
|
||||
@ -120,13 +115,20 @@ pub fn ui_focus_system(
|
||||
}
|
||||
// if the current cursor position is within the bounds of the node, consider it for
|
||||
// clicking
|
||||
if (min.x..max.x).contains(&cursor_position.x)
|
||||
&& (min.y..max.y).contains(&cursor_position.y)
|
||||
{
|
||||
let contains_cursor = if let Some(cursor_position) = cursor_position {
|
||||
(min.x..max.x).contains(&cursor_position.x)
|
||||
&& (min.y..max.y).contains(&cursor_position.y)
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if contains_cursor {
|
||||
Some((entity, focus_policy, interaction, FloatOrd(position.z)))
|
||||
} else {
|
||||
if let Some(mut interaction) = interaction {
|
||||
if *interaction == Interaction::Hovered {
|
||||
if *interaction == Interaction::Hovered
|
||||
|| (cursor_position.is_none() && *interaction != Interaction::None)
|
||||
{
|
||||
*interaction = Interaction::None;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bevy_winit"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
edition = "2021"
|
||||
description = "A winit window and input backend for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
|
@ -127,10 +127,12 @@ impl WinitWindows {
|
||||
|
||||
let winit_window = winit_window_builder.build(event_loop).unwrap();
|
||||
|
||||
match winit_window.set_cursor_grab(window_descriptor.cursor_locked) {
|
||||
Ok(_) => {}
|
||||
Err(winit::error::ExternalError::NotSupported(_)) => {}
|
||||
Err(err) => Err(err).unwrap(),
|
||||
if window_descriptor.cursor_locked {
|
||||
match winit_window.set_cursor_grab(true) {
|
||||
Ok(_) => {}
|
||||
Err(winit::error::ExternalError::NotSupported(_)) => {}
|
||||
Err(err) => Err(err).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
winit_window.set_cursor_visible(window_descriptor.cursor_visible);
|
||||
|
Loading…
Reference in New Issue
Block a user