Skip to content

Releases: richardbiely/gaia-ecs

v0.7.8

15 Nov 09:39
Compare
Choose a tag to compare

A smaller release with something big cooking inside and some handy new features.

Components can now be added and removed in batches which results in less archetype-switching of the modified entity and way better performance. In the example bellow a single archetype movement is performed after the last call to add():

ecs::World w;

// Create an entity with Position.
ecs::Entity e = w.add();
w.add<Position>();

...

w.bulk(e)
 // add Velocity to entity e
 .add<Velocity>()
 // remove Position from entity e
 .del<Position>()
 // add Rotation to entity e
 .add<Rotation>()
 // add a bunch of other components to entity e
 .add<Something1, Something2, Something3>();

With this syntax new in place the batch version of set() function has been slightly altered to match it:

// Old version of the set function
w.set<Position>(e, {1,2,3})
  .set<Velocity>({1,0,0});

// New version
w.set(e)
  .set<Position>({1,2,3})
  .set<Velocity>({1,0,0});

Each entity can be assigned a unique name now. This is useful for debugging or entity lookup when entity id is not present for any reason. If you try to assign an already existing name to some entity, the function does nothing (and triggers an assert if you have them enabled).

ecs::World w;
ecs::Entity e = w.add();

// Entity "e" named "my_unique_name".
// The string is copied and stored internally.
w.name(e, "my_unique_name");

// If you know the length of the string, you can provide it as well
w.name(e, "my_unique_name", 14);

// Pointer to the string used as entity name for entity "e"
const char* name = w.name(e);

// Entity identified by the string returned.
// In this case, "e_by_name" and "e" are equal.
ecs::Entity e_by_name = w.get("my_unique_name");

// The name can be unset by setting it to nullptr
w.name(e, nullptr);

If you already have a dedicated string storage it would be a waste to duplicate the memory. In this case you can use ecs::world::name_raw to name entities. In this case the string is NOT copied and NOT stored internally. You are responsible for its lifetime. The pointer also needs to be stable. Otherwise, any time your storage tries to move the string to a different place you have to unset the name before it happens and set it anew after the move is done.

const char* pUserManagedString = ...;
w.name_raw(e, pUserManagedString);

// If you now the length, you can provide it
w.name_raw(e, pUserManagedString, userManagedStringLength);

// If the user-managed string pointer is not stable, you need to unset the name before the pointer changes location
w.name_raw(e, nullptr);
...
// ... the change of pointer happens
...
// After the user-managed string changed location and obtained a new pointer, you set the name again
w.name_raw(e, pUserManagedString);

Fixed:

  • entities with uni components could be moved to a non-matching uni chunk by defragmentation b18f56f
  • deleting an empty archetype might have cause wrong query matching e13d754eb44ff309dc831f5de1a982c5d36b71f
  • proper checks for the root archetype 36f3f4f
  • ecs::world::cleanup not clearing everything properly 0d7e26a
  • various theoretical issues with bash scripts 743f38a

Changed:

  • bulk operations behavior bd3dd6a
  • internal refactoring in preparation for Entity and Component merger 6e3ead1

Tweaked:

  • slightly less work when comparing queries c4e8de7

Added:

  • ability to bulk-add/del components b03ea78
  • support for naming entities 30b9ed6
  • GAIA_ASSUME as a wrapper for [[assume]] and similar compiler-specific attributes 4531995

Full Changelog: v0.7.7...v0.7.8

v0.7.7

10 Nov 17:52
Compare
Choose a tag to compare

This version serves primarily as a big stability update. Some critical parts of the code were fixed and more unit tests were added.

No real new features were added for the end-user but a lot of tweaking happened behind the scenes which helped improve performance and memory consumption of the system.
One such example is removal of archetype. If left empty (no entity in the world belonging to them) for a few dozen of frames, the world automatically deletes the archetype making it a bit more faster for any new queries to match archetypes. Memory consumption is also lowered.
Components now have meta-data encoded inside their identifier directly which means we no longer have to make component descriptor lookups so often.

World iteration was simplified. Any iteration has to happen explicitly via queries now. Previously existing ecs::world::each was removed because it was not flexible enough and served as just another way to iterate the world. This way, the API is cleaner and more expressive.

Fixed:

  • chunk allocator would break if a huge number of pages were requested at once c6fba0f
  • query lookup no longer hacked in 40d22de
  • ecs::Query::arr() used chunk view rather than iterator view to match results 20b8113
  • constructors/destructors were not called in some cases in containers 45151d5
  • container reallocation not handled correctly in some cases 45151d5
  • container erase functions not working correctly in some cases 45151d5
  • container comparisons not working correctly 45151d5
  • container resizing 78821f8
  • GAIA_ASSERT not working with complex expressions b1c9253
  • unique component constructors not called only automatically with chunk creation ab5d9f4
  • GCC 13 stringop-overflow bug workaround f7f48e7 d1fbd93
  • wrong type deduction on view_auto 3b1f433
  • component cache wouldn't properly zero-initialize for component descriptors 42b179c 149bc99
  • empty archetype lifetime handling 840c613
  • empty chunks not removed properly f08d5f005d188c0e6a8987f6bf4c32a254eb342

Changed:

  • Archetype::archetype_id() renamed toArchetype::id() d686233
  • CK_Generic renamed to CK_Gen 56c0e8a
  • CK_Chunk renamed to CK_Uni 56c0e8a
  • components turned into uint64_t with meta-data encoded inside 36068d3
  • archetype graph diagnostics turned back on after being disabled accidentally 6c5b643
  • chunk component renamed to unique component to avoid confusion with Chunk 56c0e8a
  • quom installed into a virtual Python environment if not previously available af49471
  • [breaking change] T& used for mutable type in queries so it is less confusing and more in-line with how c++ type system works eb39152
  • some template guides replaced with decltype(auto) for improved readability and type deduction e02f7cb

Removed:

  • [breaking change] ComponentInfo merged with ComponentDesc 36068d3
  • GAIA_USE_SIMD_COMP_IDX removed 36068d3
  • [breaking change] Iterator*::each template removed because some compilers wouldn't vectorize it (MSVC) and it didn't really help with anything cdfb6ea
  • [breaking change] world::each removed in favor of query::each as it was not flexible and served as just another way to iterate the world 67f66b4

Tweaked:

  • fast-path for component descriptors up to 1024 elements. Use a map after that 149bc99
  • components turned into uint64_t with meta-data encoded inside in order to eliminate component descriptor lookups in many places 36068d3

Added:

  • profiling mode added to each performance benchmark 929f50b
  • number of defragmented entities per tick can be changed via world::defrag_entities_per_tick d25d8b6
  • added GAIA_FOR family of macros 720568d
  • added GAIA_EACH family of macros cdfb6ea
  • archetypes removed when kept empty for a few frames df08d5f

Full Changelog: v0.7.6...v0.7.7

v0.7.6

27 Oct 07:40
Compare
Choose a tag to compare

Building on the previous version, 0.7.6 finishes code refactoring which means:

  • namespaces are all set the way they should be now
  • ComponentType is now ComponentKind so its name does not collide with the component type system
  • any chunk iteration is done using chunk iterators which simplifies code a lot in many places and helps with readability
  • has_entities renamed replaced with empty
  • calc_entity_cnt renamed to count
  • set_structural_changes renamed to lock
  • get_structural_changes renamed to locked
    This also means new features can finally start being added to the framework.

Additionally, iterator refactoring helped also with iterator performance and usability.
Unlike IteratorDisabled or IteratorAll, Iterator suffered by not getting its code vectorized in all cases. This was because compilers were not able to guarantee the memory it iterates was contiguous. All it took was changing its loop from
for (uint32_t i = from; i<to; ++i) ...
to
for (uint32_t i = 0; i<to; ++i) ...
and making sure the span of data it receives is already offset.

Any usage of std::forward and std::move has been replaced with custom GAIA_FWD and GAIA_MOVE performing casts directly.
Besides shorter name, it helps with compilation time and performance of non-optimized builds. Albeit, mostly with older compilers.
In non-optimized bulids older compilers would treat both as functions calls rather than intrinsics which is pretty terrible. Most of all in framework/library code such as Gaia-ECS where a lot of perfect forwarding and moves are used.

Changed:

  • query, component and archetype namespaces dropped 6705b2e
  • ComponentType renamed to ComponentKind 3ba4e60
  • has_entities replaced with empty 15dbb8d
  • calc_entity_cnt renamed to count 15dbb8d
  • set_structural_changes renamed to lock, get_structural_changes renamed to locked e03e169

Fixed:

  • project would not compile on Clang 8 7d2cb2b
  • check for lock when enabling entities e03e169
  • core::each_tuple and core::each_tuple_ext not iterating properly c306db9

Tweaked:

Added:

  • std::forward replaced with GAIA_FWD be4b920
  • std::move replaced with GAIA_MOV 42e72be

Full Changelog: v0.7.5...v0.7.6

v0.7.5

25 Oct 08:56
Compare
Choose a tag to compare

This release contains major refactoring. Both in folder structure and function naming. No new features were introduced.

All functions have been renamed so they are shorter and require less time typing. While this may look unnecessary, I believe it really helps with the experience and makes developing a project using the framework a lot smoother and easier to understand.

Folder structure has changed, with each folder containing a different namespace. Namespaces are standalone now, with no cross references (aka namespace A using namespace B and vice-verse).

Code was further simplified by removing the no-fragmentation mode which could previously be enforced via GAIA_AVOID_CHUNK_FRAGMENTATION. I believe defragmentation is good-enough solution that optimizes performance over time to a point where no-fragmentation mode is no longer necessary. Instead, GAIA_DEFRAG_ENTITIES_PER_FRAME was introduced which is used to control how many entities per frame can be defragmented.

Fixed:

  • missing virtual in BaseSystemManager 6704024
  • chunk indices handling above 15-bits e9579bd
  • entities not deleted correctly 954529a
  • memory leak in move operators on darray, darray_ext, sarray_ext 3c3452f)

Changed:

  • DataBuffer_SerializationWrapper merged with DataBuffer and renamed to SerializationBuffer cd59d44
  • enabling entities refactored 7be6fc3
  • iterators refactored f2b1464
  • folder structure refactoring e361561
  • naming refactoring

Removed:

  • GAIA_AVOID_CHUNK_FRAGMENTATION (replaced fully with defragmentation) 422f7b1

Added:

  • GAIA_DEFRAG_ENTITIES_PER_FRAME for controlling how many entities per frame are defragmented 422f7b1

Full Changelog: v0.7.4...v0.7.5

v0.7.4

18 Oct 08:23
Compare
Choose a tag to compare

Fixed:

  • ChunkAllocator block indices written/read incorrectly 8ad4547
  • MSVC build 43f9385
  • parts of the benchmarks could be optimized away 85e4742

Changed:

  • duel benchmark simplified b7e2b9f
  • serialization moved to a separate namespace 21b7a23

Added:

Full Changelog: v0.7.3...v0.7.4

v0.7.3

14 Oct 10:06
Compare
Choose a tag to compare

Fixed:

  • mem_alloc_align would not work it the requested memory size was not a multiple of the alignment 1bd265a
  • build issues on some compilers e5ab096

Changed:

  • archetype map no longer handles hash collisions in a hacky way d81ca23
  • precise SoA data size calculation for archetypes a8d6d12

Added:

Full Changelog: v0.7.2...v0.7.3

v0.7.2

03 Oct 16:49
Compare
Choose a tag to compare

Fixed:

  • handling of ARM in CMake 66aef05
  • handling of libc++ in CMake 35303be
  • single header gaia.h issues with C++20 and later c4e310d
  • broken type deduction when ComponentType::CT_Generic was stated explicitely 134c604
  • defragmentation on chunkless archetypes 1fc0603

Changed:

  • STL compatibility layer dropped 73750c6
  • ImplicitList renamed to ilist d07eef2

Tweaked:

  • packages lookup in CMake improved 6987ac3
  • less template instantiation 47f41b5 65e0db5
  • improved chunk utilization

Added:

  • uncached querries 08506d9
  • custom data serialization 9fc149e
  • chunks of multiple sizes (8K and 16K) c514275

Full Changelog: v0.7.1...v0.7.2

v0.7.1

23 Sep 18:29
Compare
Choose a tag to compare

Fixed:

  • incorrect container assertions cec1248
  • DataBuffer::SaveComponent wouldn't work correctly with rvalues fc4b1fe
  • chunks would be filled with 1 less entity than their capacity allowed 85d2341
  • GAIA_USE_LIBCPP usage 9cec3a3
  • C++20 and later compilation issues 53a8da5

Changed:

Tweaked:

  • component cache inlining cb873f5
  • improved performance of ComponentInfo comparison 9e03ee9
  • containers::bitset::flip performance improvement 0a58afb

Full Changelog: v0.7.0...v0.7.1

v0.7.0

17 Sep 17:40
Compare
Choose a tag to compare

Fixed:

  • sort_ct would not sort properly 307d3cc
  • find, find_if, find_if_not would always return the first item in the list if a match was found and iterators were used for range 655ed7e
  • ChunkAllocator life-time issues 5f5001c
  • adding components via CommandBuffer would not force registration 2da2636
  • non-trivial components would not work correctly with CommandBuffer 04abc39
  • duel benchmark would optimize away the output variables making the results meaningless 0196777
  • dynamic containers would not release on pop_back 5d386d1)
  • build issues when using GAIA_USE_STL_CONTAINERS 1

Changed:

  • utils::for_each can be used with argument-less functors now 461adbd
  • more informative assertions 046a0b1
  • garbage collector called only via ecs::World::Update() now 0c81d53
  • ecs::World::Update() calls GAIA_PROF_FRAME at the end to mark the end of the frame 0c81d53
  • Enabling entities done without archetype change 82f1791
  • Max 512 entities per chunk (temporary) 82f1791
  • empty entities always bound to the root archetype 84bbcd1

Tweaked:

Added:

  • ThreadPool 008edb8
  • RingBuffer container 008edb8
  • ImplicitList container ed51af2
  • bitset - b9cb2ef
  • dbitest - 82f1791
  • IteratorEnabled, IteratorDisabled 82f1791
  • support for serialization of types containing data() and size(). Use resize() if possible. 989eb15
  • #define GAIA_AVOID_CHUNK_FRAGMENTATION 1 - chunk fragmentation is avoided at the cost of entity removal / component movement performance fcb0ad7
  • #define GAIA_AVOID_CHUNK_FRAGMENTATION 0 - chunk defragmentation done at each world update 0c81d53
  • ecs::World::IsEntityUsed 84bbcd1
  • ecs::World::IsEntityEnabled 84bbcd1

Full Changelog: v0.6.2...v0.7.0

v0.6.2

15 May 06:27
Compare
Choose a tag to compare

The first official stable release of Gaia-ECS is here :)

This version comes with the following features:

  • creating, removing and enabling entities
  • basic data operations such as adding, removing components and checking their presence
  • support for generic and chunk components
  • support for organizing data in AoS (default) and SoA layout
  • cached data queries with support for AND, OR and NOT operators, change of constraints and ability to detect changes
  • systems with dependency management