Skip to content

Commit be1bc42

Browse files
committed
use associated const for is_dense
1 parent c529535 commit be1bc42

File tree

8 files changed

+68
-85
lines changed

8 files changed

+68
-85
lines changed

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
115115
let mut field_type_infos = Vec::new();
116116
let mut field_get_components = Vec::new();
117117
let mut field_from_components = Vec::new();
118-
let mut is_dense_const_exprs = Vec::new();
119-
let mut is_dense_fn_exprs = Vec::new();
118+
let mut is_dense_exprs = Vec::new();
120119
for ((field_type, is_bundle), field) in
121120
field_type.iter().zip(is_bundle.iter()).zip(field.iter())
122121
{
@@ -130,8 +129,8 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
130129
field_from_components.push(quote! {
131130
#field: <#field_type as #ecs_path::bundle::Bundle>::from_components(&mut func),
132131
});
133-
is_dense_fn_exprs.push(quote! {
134-
<#field_type as #ecs_path::bundle::Bundle>::is_dense()
132+
is_dense_exprs.push(quote! {
133+
<#field_type as #ecs_path::bundle::Bundle>::IS_DENSE
135134
});
136135
} else {
137136
field_type_infos.push(quote! {
@@ -144,9 +143,11 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
144143
field_from_components.push(quote! {
145144
#field: func().cast::<#field_type>().read(),
146145
});
147-
is_dense_const_exprs.push(quote! {
148-
<<#field_type as #ecs_path::component::Component>::Storage as #ecs_path::component::ComponentStorage>::STORAGE_TYPE
149-
== #ecs_path::component::StorageType::Table
146+
is_dense_exprs.push(quote! {
147+
match <<#field_type as #ecs_path::component::Component>::Storage as #ecs_path::component::ComponentStorage>::STORAGE_TYPE {
148+
#ecs_path::component::StorageType::Table => true,
149+
#ecs_path::component::StorageType::SparseSet => false,
150+
}
150151
});
151152
}
152153
}
@@ -158,18 +159,14 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
158159
TokenStream::from(quote! {
159160
/// SAFE: TypeInfo is returned in field-definition-order. [from_components] and [get_components] use field-definition-order
160161
unsafe impl #impl_generics #ecs_path::bundle::Bundle for #struct_name#ty_generics #where_clause {
162+
const IS_DENSE: bool = true #(&& #is_dense_exprs)*;
163+
161164
fn type_info() -> Vec<#ecs_path::component::TypeInfo> {
162165
let mut type_info = Vec::with_capacity(#field_len);
163166
#(#field_type_infos)*
164167
type_info
165168
}
166169

167-
#[inline(always)]
168-
fn is_dense() -> bool {
169-
// insert const expressions in front to avoid evaluating non-const functions if possible
170-
true #(&& (#is_dense_const_exprs))* #(&& #is_dense_fn_exprs)*
171-
}
172-
173170
#[allow(unused_variables, unused_mut, non_snake_case)]
174171
unsafe fn from_components(mut func: impl FnMut() -> *mut u8) -> Self {
175172
Self {

crates/bevy_ecs/src/bundle.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,26 @@ use std::{any::TypeId, collections::HashMap};
2323
///
2424
/// You can nest bundles like so:
2525
/// ```
26-
/// # use bevy_ecs::bundle::Bundle;
26+
/// # use bevy_ecs::{component::Component, bundle::Bundle};
27+
///
28+
/// #[derive(Component)]
29+
/// struct X(i32);
30+
/// #[derive(Component)]
31+
/// struct Y(u64);
32+
/// #[derive(Component)]
33+
/// struct Z(String);
2734
///
2835
/// #[derive(Bundle)]
2936
/// struct A {
30-
/// x: i32,
31-
/// y: u64,
37+
/// x: X,
38+
/// y: Y,
3239
/// }
3340
///
3441
/// #[derive(Bundle)]
3542
/// struct B {
3643
/// #[bundle]
3744
/// a: A,
38-
/// z: String,
45+
/// z: Z,
3946
/// }
4047
/// ```
4148
///
@@ -45,6 +52,8 @@ use std::{any::TypeId, collections::HashMap};
4552
/// [Bundle::from_components] must call `func` exactly once for each [TypeInfo] returned by
4653
/// [Bundle::type_info]
4754
pub unsafe trait Bundle: Send + Sync + 'static {
55+
const IS_DENSE: bool;
56+
4857
/// Gets this [Bundle]'s components type info, in the order of this bundle's Components
4958
fn type_info() -> Vec<TypeInfo>;
5059

@@ -62,8 +71,6 @@ pub unsafe trait Bundle: Send + Sync + 'static {
6271
/// "mem::forget" the bundle fields, so callers are responsible for dropping the fields if
6372
/// that is desirable.
6473
fn get_components(self, func: impl FnMut(*mut u8));
65-
66-
fn is_dense() -> bool;
6774
}
6875

6976
macro_rules! tuple_impl {
@@ -74,10 +81,12 @@ macro_rules! tuple_impl {
7481
vec![$(TypeInfo::of::<$name>()),*]
7582
}
7683

77-
#[inline(always)]
78-
fn is_dense() -> bool {
79-
true $(&& $name::Storage::STORAGE_TYPE == StorageType::Table)*
80-
}
84+
const IS_DENSE: bool = true $(&&
85+
match $name::Storage::STORAGE_TYPE {
86+
StorageType::Table => true,
87+
StorageType::SparseSet => false,
88+
}
89+
)*;
8190

8291
#[allow(unused_variables, unused_mut)]
8392
unsafe fn from_components(mut func: impl FnMut() -> *mut u8) -> Self {

crates/bevy_ecs/src/query/fetch.rs

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub trait Fetch<'w>: Sized {
6767
/// for "dense" queries. If this returns true, [`Fetch::set_table`] and [`Fetch::table_fetch`]
6868
/// will be called for iterators. If this returns false, [`Fetch::set_archetype`] and
6969
/// [`Fetch::archetype_fetch`] will be called for iterators.
70-
fn is_dense(&self) -> bool;
70+
const IS_DENSE: bool;
7171

7272
/// Adjusts internal state to account for the next [`Archetype`]. This will always be called on
7373
/// archetypes that match this [`Fetch`].
@@ -177,10 +177,7 @@ impl<'w> Fetch<'w> for EntityFetch {
177177
type Item = Entity;
178178
type State = EntityState;
179179

180-
#[inline]
181-
fn is_dense(&self) -> bool {
182-
true
183-
}
180+
const IS_DENSE: bool = true;
184181

185182
unsafe fn init(
186183
_world: &World,
@@ -296,13 +293,12 @@ impl<'w, T: Component> Fetch<'w> for ReadFetch<T> {
296293
type Item = &'w T;
297294
type State = ReadState<T>;
298295

299-
#[inline]
300-
fn is_dense(&self) -> bool {
296+
const IS_DENSE: bool = {
301297
match T::Storage::STORAGE_TYPE {
302298
StorageType::Table => true,
303299
StorageType::SparseSet => false,
304300
}
305-
}
301+
};
306302

307303
unsafe fn init(
308304
world: &World,
@@ -454,13 +450,12 @@ impl<'w, T: Component> Fetch<'w> for WriteFetch<T> {
454450
type Item = Mut<'w, T>;
455451
type State = WriteState<T>;
456452

457-
#[inline]
458-
fn is_dense(&self) -> bool {
453+
const IS_DENSE: bool = {
459454
match T::Storage::STORAGE_TYPE {
460455
StorageType::Table => true,
461456
StorageType::SparseSet => false,
462457
}
463-
}
458+
};
464459

465460
unsafe fn init(
466461
world: &World,
@@ -613,10 +608,7 @@ impl<'w, T: Fetch<'w>> Fetch<'w> for OptionFetch<T> {
613608
type Item = Option<T::Item>;
614609
type State = OptionState<T::State>;
615610

616-
#[inline]
617-
fn is_dense(&self) -> bool {
618-
self.fetch.is_dense()
619-
}
611+
const IS_DENSE: bool = T::IS_DENSE;
620612

621613
unsafe fn init(
622614
world: &World,
@@ -803,13 +795,12 @@ impl<'w, T: Component> Fetch<'w> for ChangeTrackersFetch<T> {
803795
type Item = ChangeTrackers<T>;
804796
type State = ChangeTrackersState<T>;
805797

806-
#[inline]
807-
fn is_dense(&self) -> bool {
798+
const IS_DENSE: bool = {
808799
match T::Storage::STORAGE_TYPE {
809800
StorageType::Table => true,
810801
StorageType::SparseSet => false,
811802
}
812-
}
803+
};
813804

814805
unsafe fn init(
815806
world: &World,
@@ -910,12 +901,7 @@ macro_rules! impl_tuple_fetch {
910901
($($name::init(_world, $name, _last_change_tick, _change_tick),)*)
911902
}
912903

913-
914-
#[inline]
915-
fn is_dense(&self) -> bool {
916-
let ($($name,)*) = self;
917-
true $(&& $name.is_dense())*
918-
}
904+
const IS_DENSE: bool = true $(&& $name::IS_DENSE)*;
919905

920906
#[inline]
921907
unsafe fn set_archetype(&mut self, _state: &Self::State, _archetype: &Archetype, _tables: &Tables) {

crates/bevy_ecs/src/query/filter.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,12 @@ impl<'a, T: Component> Fetch<'a> for WithFetch<T> {
133133
}
134134
}
135135

136-
#[inline]
137-
fn is_dense(&self) -> bool {
138-
T::Storage::STORAGE_TYPE == StorageType::Table
139-
}
136+
const IS_DENSE: bool = {
137+
match T::Storage::STORAGE_TYPE {
138+
StorageType::Table => true,
139+
StorageType::SparseSet => false,
140+
}
141+
};
140142

141143
#[inline]
142144
unsafe fn set_table(&mut self, _state: &Self::State, _table: &Table) {}
@@ -250,10 +252,12 @@ impl<'a, T: Component> Fetch<'a> for WithoutFetch<T> {
250252
}
251253
}
252254

253-
#[inline]
254-
fn is_dense(&self) -> bool {
255-
T::Storage::STORAGE_TYPE == StorageType::Table
256-
}
255+
const IS_DENSE: bool = {
256+
match T::Storage::STORAGE_TYPE {
257+
StorageType::Table => true,
258+
StorageType::SparseSet => false,
259+
}
260+
};
257261

258262
#[inline]
259263
unsafe fn set_table(&mut self, _state: &Self::State, _table: &Table) {}
@@ -343,10 +347,7 @@ impl<'a, T: Bundle> Fetch<'a> for WithBundleFetch<T> {
343347
}
344348
}
345349

346-
#[inline]
347-
fn is_dense(&self) -> bool {
348-
T::is_dense()
349-
}
350+
const IS_DENSE: bool = T::IS_DENSE;
350351

351352
#[inline]
352353
unsafe fn set_table(&mut self, _state: &Self::State, _table: &Table) {}
@@ -449,11 +450,7 @@ macro_rules! impl_query_filter_tuple {
449450
},)*))
450451
}
451452

452-
#[inline]
453-
fn is_dense(&self) -> bool {
454-
let ($($filter,)*) = &self.0;
455-
true $(&& $filter.fetch.is_dense())*
456-
}
453+
const IS_DENSE: bool = true $(&& $filter::IS_DENSE)*;
457454

458455
#[inline]
459456
unsafe fn set_table(&mut self, state: &Self::State, table: &Table) {
@@ -627,10 +624,12 @@ macro_rules! impl_tick_filter {
627624
value
628625
}
629626

630-
#[inline]
631-
fn is_dense(&self) -> bool {
632-
T::Storage::STORAGE_TYPE == StorageType::Table
633-
}
627+
const IS_DENSE: bool = {
628+
match T::Storage::STORAGE_TYPE {
629+
StorageType::Table => true,
630+
StorageType::SparseSet => false,
631+
}
632+
};
634633

635634
unsafe fn set_table(&mut self, state: &Self::State, table: &Table) {
636635
self.table_ticks = table

crates/bevy_ecs/src/query/iter.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ where
7474
// NOTE: this mimics the behavior of `QueryIter::next()`, except that it
7575
// never gets a `Self::Item`.
7676
unsafe {
77-
if self.fetch.is_dense() && self.filter.is_dense() {
77+
if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
7878
loop {
7979
if self.current_index == self.current_len {
8080
let table_id = match self.table_id_iter.next() {
@@ -137,7 +137,7 @@ where
137137
#[inline(always)]
138138
fn next(&mut self) -> Option<Self::Item> {
139139
unsafe {
140-
if self.fetch.is_dense() && self.filter.is_dense() {
140+
if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
141141
loop {
142142
if self.current_index == self.current_len {
143143
let table_id = self.table_id_iter.next()?;
@@ -477,7 +477,7 @@ where
477477
#[inline]
478478
unsafe fn peek_last<'w>(&mut self) -> Option<<Q::Fetch as Fetch<'w>>::Item> {
479479
if self.current_index > 0 {
480-
if self.fetch.is_dense() && self.filter.is_dense() {
480+
if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
481481
Some(self.fetch.table_fetch(self.current_index - 1))
482482
} else {
483483
Some(self.fetch.archetype_fetch(self.current_index - 1))
@@ -497,7 +497,7 @@ where
497497
archetypes: &'w Archetypes,
498498
query_state: &'s QueryState<Q, F>,
499499
) -> Option<<Q::Fetch as Fetch<'w>>::Item> {
500-
if self.fetch.is_dense() && self.filter.is_dense() {
500+
if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
501501
loop {
502502
if self.current_index == self.current_len {
503503
let table_id = self.table_id_iter.next()?;

crates/bevy_ecs/src/query/state.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ where
406406
<Q::Fetch as Fetch>::init(world, &self.fetch_state, last_change_tick, change_tick);
407407
let mut filter =
408408
<F::Fetch as Fetch>::init(world, &self.filter_state, last_change_tick, change_tick);
409-
if fetch.is_dense() && filter.is_dense() {
409+
if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
410410
let tables = &world.storages().tables;
411411
for table_id in self.matched_table_ids.iter() {
412412
let table = &tables[*table_id];
@@ -457,12 +457,7 @@ where
457457
// NOTE: If you are changing query iteration code, remember to update the following places, where relevant:
458458
// QueryIter, QueryIterationCursor, QueryState::for_each_unchecked_manual, QueryState::par_for_each_unchecked_manual
459459
task_pool.scope(|scope| {
460-
let fetch =
461-
<Q::Fetch as Fetch>::init(world, &self.fetch_state, last_change_tick, change_tick);
462-
let filter =
463-
<F::Fetch as Fetch>::init(world, &self.filter_state, last_change_tick, change_tick);
464-
465-
if fetch.is_dense() && filter.is_dense() {
460+
if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
466461
let tables = &world.storages().tables;
467462
for table_id in self.matched_table_ids.iter() {
468463
let table = &tables[*table_id];

crates/bevy_ecs/src/system/commands.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ impl<T: Resource> Command for RemoveResource<T> {
445445
mod tests {
446446
use crate::{
447447
self as bevy_ecs,
448-
component::{Component, ComponentDescriptor, StorageType},
448+
component::Component,
449449
system::{CommandQueue, Commands},
450450
world::World,
451451
};

crates/bevy_sprite/src/lib.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,10 @@ pub use texture_atlas_builder::*;
2828

2929
use bevy_app::prelude::*;
3030
use bevy_asset::{AddAsset, Assets, Handle, HandleUntyped};
31-
use bevy_ecs::{
32-
component::{ComponentDescriptor, StorageType},
33-
system::IntoSystem,
34-
};
31+
use bevy_ecs::system::IntoSystem;
3532
use bevy_math::Vec2;
3633
use bevy_reflect::TypeUuid;
3734
use bevy_render::{
38-
draw::OutsideFrustum,
3935
mesh::{shape, Mesh},
4036
pipeline::PipelineDescriptor,
4137
render_graph::RenderGraph,
@@ -96,6 +92,7 @@ impl Plugin for SpritePlugin {
9692
frustum_culling::atlas_frustum_culling_system.system(),
9793
);
9894
}
95+
let world = app.world_mut();
9996
let world_cell = world.cell();
10097
let mut render_graph = world_cell.get_resource_mut::<RenderGraph>().unwrap();
10198
let mut pipelines = world_cell

0 commit comments

Comments
 (0)