From 5ac1f810e910bda9abc776c81cc63f2fd51e35b9 Mon Sep 17 00:00:00 2001 From: Dandielo Date: Wed, 11 Feb 2026 20:40:07 +0900 Subject: [PATCH 1/3] [iceshard] Improvements to collection types. * Reimplemented previously existing methods for HeapVarString. * Fixed MultiHashMap iterator not skipping * Fixed ShardContainer missing 'push_back' version for C style arrays. * Fixed sort still using old api in some cases. --- .../collections/public/ice/heap_varstring.hxx | 63 ++++++++++++++----- .../collections/public/ice/multi_hashmap.hxx | 18 ++++-- .../public/ice/shard_container.hxx | 10 +++ .../code/core/collections/public/ice/sort.hxx | 2 +- 4 files changed, 71 insertions(+), 22 deletions(-) diff --git a/source/code/core/collections/public/ice/heap_varstring.hxx b/source/code/core/collections/public/ice/heap_varstring.hxx index 0a592c32d..541a3e42e 100644 --- a/source/code/core/collections/public/ice/heap_varstring.hxx +++ b/source/code/core/collections/public/ice/heap_varstring.hxx @@ -27,20 +27,23 @@ namespace ice ice::Allocator* _allocator; ValueType* _data; - inline explicit HeapVarString(ice::Allocator& alloc) noexcept; - inline HeapVarString(ice::Allocator& allocator, ice::BasicString string) noexcept; - inline ~HeapVarString() noexcept; + constexpr explicit HeapVarString(ice::Allocator& alloc) noexcept; + constexpr HeapVarString(ice::Allocator& allocator, ice::BasicString string) noexcept; + constexpr ~HeapVarString() noexcept; - inline HeapVarString(HeapVarString&& other) noexcept; - inline HeapVarString(HeapVarString const& other) noexcept; + constexpr HeapVarString(HeapVarString&& other) noexcept; + constexpr HeapVarString(HeapVarString const& other) noexcept; constexpr auto data() const noexcept -> ValueType*; constexpr auto size() const noexcept -> SizeType; - inline auto data_view() const noexcept -> ice::Data; + constexpr void clear() noexcept; + constexpr auto deserialize(ice::Data data) noexcept -> ice::Data; - inline operator ice::BasicString() const noexcept; - inline operator ice::VarStringBase() const noexcept; + constexpr auto data_view() const noexcept -> ice::Data; + + constexpr operator ice::BasicString() const noexcept; + constexpr operator ice::VarStringBase() const noexcept; }; namespace varstring @@ -77,34 +80,34 @@ namespace ice } // namespace string::detail template - inline HeapVarString::HeapVarString(ice::Allocator& alloc) noexcept + inline constexpr HeapVarString::HeapVarString(ice::Allocator& alloc) noexcept : _allocator{ ice::addressof(alloc) } , _data{ nullptr } { } template - inline HeapVarString::HeapVarString(ice::Allocator& alloc, ice::BasicString string) noexcept + inline constexpr HeapVarString::HeapVarString(ice::Allocator& alloc, ice::BasicString string) noexcept : _allocator{ ice::addressof(alloc) } , _data{ ice::varstring::create(alloc, string) } { } template - inline HeapVarString::HeapVarString(ice::HeapVarString&& other) noexcept + inline constexpr HeapVarString::HeapVarString(ice::HeapVarString&& other) noexcept : _allocator{ other._allocator } , _data{ ice::exchange(other._data, nullptr) } { } template - inline HeapVarString::HeapVarString(ice::HeapVarString const& other) noexcept + inline constexpr HeapVarString::HeapVarString(ice::HeapVarString const& other) noexcept : HeapVarString{ other._allocator, ice::String{ other } } { } template - inline HeapVarString::~HeapVarString() noexcept + inline constexpr HeapVarString::~HeapVarString() noexcept { if (_data != nullptr) { @@ -125,7 +128,35 @@ namespace ice } template - inline auto HeapVarString::data_view() const noexcept -> ice::Data + inline constexpr void HeapVarString::clear() noexcept + { + _allocator->deallocate(std::exchange(_data, nullptr)); + } + + template + inline constexpr auto HeapVarString::deserialize(ice::Data data) noexcept -> ice::Data + { + ICE_ASSERT_CORE(data.size >= 2_B); // 1 byte for size + 1 for a single character + this->clear(); // Clear the current contents + + ice::usize bytes; + ice::ncount const size = ice::varstring::read_size(reinterpret_cast(data.location), bytes); + if (size > 0) + { + char* const new_str = ice::varstring::allocate_exact(*_allocator, size, bytes); + if (new_str != nullptr) + { + ice::memcpy(new_str + bytes.value, ice::ptr_add(data.location, bytes), size.bytes()); + new_str[bytes.value + size.native()] = '\0'; + } + _data = new_str; // Assign the new allocated data + } + + return ice::ptr_add(data, bytes + size.bytes()); + } + + template + inline constexpr auto HeapVarString::data_view() const noexcept -> ice::Data { ice::usize bytes = 0_B; ice::ncount const size = ice::varstring::read_size(_data, bytes); @@ -138,7 +169,7 @@ namespace ice } template - inline HeapVarString::operator ice::BasicString::CharType>() const noexcept + inline constexpr HeapVarString::operator ice::BasicString::CharType>() const noexcept { ice::usize bytes = 0_B; ice::ncount const size = ice::varstring::read_size(_data, bytes); @@ -153,7 +184,7 @@ namespace ice } template - inline HeapVarString::operator ice::VarStringBase::CharType>() const noexcept + inline constexpr HeapVarString::operator ice::VarStringBase::CharType>() const noexcept { return _data; } diff --git a/source/code/core/collections/public/ice/multi_hashmap.hxx b/source/code/core/collections/public/ice/multi_hashmap.hxx index f37600971..71f85c1fa 100644 --- a/source/code/core/collections/public/ice/multi_hashmap.hxx +++ b/source/code/core/collections/public/ice/multi_hashmap.hxx @@ -74,12 +74,20 @@ namespace ice { ICE_ASSERT_CORE(valid()); - _current = _entries[_current].next; - if (_current == ice::detail::hashmap::Constant_EndOfList) + ice::u64 const expected_key = this->key(); + + do { - _entries = nullptr; - _values = nullptr; - } + _current = _entries[_current].next; + if (_current == ice::detail::hashmap::Constant_EndOfList) + { + _entries = nullptr; + _values = nullptr; + break; + } + + // Test against the new key if we are not at the end. + } while (this->key() != expected_key); } constexpr auto key() const noexcept -> ice::u64 const& { return _entries[_current].key; } diff --git a/source/code/core/collections/public/ice/shard_container.hxx b/source/code/core/collections/public/ice/shard_container.hxx index 094b458e1..890452efd 100644 --- a/source/code/core/collections/public/ice/shard_container.hxx +++ b/source/code/core/collections/public/ice/shard_container.hxx @@ -11,6 +11,7 @@ namespace ice struct ShardContainer : public ice::Array { using ice::Array::Array; + using ice::Array::push_back; constexpr bool contains(ice::ShardID shardid) const noexcept; constexpr auto count_of(ice::ShardID shardid) const noexcept -> ice::ncount; @@ -60,6 +61,9 @@ namespace ice this ShardContainer& self, ice::ShardID shardid ) noexcept; + + template + inline constexpr void push_back(ice::Shard const(&shards_array)[Count]) noexcept; }; inline constexpr bool ShardContainer::contains(ice::ShardID expected_shard) const noexcept @@ -203,4 +207,10 @@ namespace ice self.resize(count); } + template + inline constexpr void ShardContainer::push_back(ice::Shard const(&shards_array)[Count]) noexcept + { + this->push_back(ice::Span{ shards_array }); + } + } // namespace ice diff --git a/source/code/core/collections/public/ice/sort.hxx b/source/code/core/collections/public/ice/sort.hxx index 6be99b1cc..40a871a0f 100644 --- a/source/code/core/collections/public/ice/sort.hxx +++ b/source/code/core/collections/public/ice/sort.hxx @@ -291,7 +291,7 @@ namespace ice inline void sort_many(ice::Span keys, Pred&& pred, ice::Span... values) noexcept { ice::i32 const first_index = 0; - ice::i32 const last_index = ice::count(keys) - 1; + ice::i32 const last_index = keys.size().u32() - 1; ice::detail::qsort_many(std::forward(pred), first_index, last_index, keys, values...); } From 1577e5f411c441aa90561c2504ce2415d9648aea Mon Sep 17 00:00:00 2001 From: Dandielo Date: Wed, 11 Feb 2026 20:53:07 +0900 Subject: [PATCH 2/3] [iceshard] Minor improvements after collections refactor. * More temporary fixes for GfxRunner. --- .../framework_base/private/framework_main.cxx | 4 ++-- .../public/ice/ecs/ecs_query_operations.hxx | 4 ++-- .../engine/public/ice/gfx/gfx_runner.hxx | 6 ++++-- .../iceshard/private/iceshard_gfx_runner.cxx | 17 ++++++++++------- .../iceshard/private/iceshard_gfx_runner.hxx | 6 ++++-- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/source/code/framework/framework_base/private/framework_main.cxx b/source/code/framework/framework_base/private/framework_main.cxx index d7dde11fa..43b1bf2f7 100644 --- a/source/code/framework/framework_base/private/framework_main.cxx +++ b/source/code/framework/framework_base/private/framework_main.cxx @@ -542,7 +542,7 @@ auto ice_resume( runtime.input_tracker->register_device_type(ice::input::DeviceType::Keyboard, ice::input::get_default_device_factory()); //runtime.gfx_rendergraph_runtime = state.game->rendergraph(runtime.gfx_runner->device()); - ice::wait_for(runtime.gfx_runner->update_rendergraph(state.game->rendergraph(runtime.gfx_runner->context()))); + runtime.gfx_runner->update_rendergraph(state.game->rendergraph(runtime.gfx_runner->context())); runtime.gfx_wait.set(); } @@ -660,7 +660,7 @@ auto ice_update( //runtime.gfx_wait.wait(); runtime.gfx_runner->context().recreate_swapchain(); - ice::wait_for(runtime.gfx_runner->update_rendergraph(state.game->rendergraph(runtime.gfx_runner->context()))); + runtime.gfx_runner->update_rendergraph(state.game->rendergraph(runtime.gfx_runner->context())); } // Since the frame updates the values we are safe to access them any time. They won't change until a new frame is awaited, and awaitng frames is happening on the same thread. diff --git a/source/code/iceshard/engine/public/ice/ecs/ecs_query_operations.hxx b/source/code/iceshard/engine/public/ice/ecs/ecs_query_operations.hxx index 9e959a6ac..74b70c3f2 100644 --- a/source/code/iceshard/engine/public/ice/ecs/ecs_query_operations.hxx +++ b/source/code/iceshard/engine/public/ice/ecs/ecs_query_operations.hxx @@ -329,7 +329,7 @@ namespace ice::ecs ice::ecs::detail::ArchetypeInstanceInfo const* arch = nullptr; ice::ecs::detail::DataBlock const* block = nullptr; - ice::u32 const arch_count = ice::count(query.archetype_instances); + ice::u32 const arch_count = query.archetype_instances.size().u32(); for (; arch_idx < arch_count; ++arch_idx) { arch = query.archetype_instances[arch_idx]; @@ -552,7 +552,7 @@ namespace ice::ecs void* helper_pointer_array[component_count]{ nullptr }; - ice::u32 const arch_count = ice::count(query.archetype_instances); + ice::u32 const arch_count = query.archetype_instances.size().u32(); for (ice::u32 arch_idx = 0; arch_idx < arch_count; ++arch_idx) { ice::ecs::detail::ArchetypeInstanceInfo const* arch = query.archetype_instances[arch_idx]; diff --git a/source/code/iceshard/engine/public/ice/gfx/gfx_runner.hxx b/source/code/iceshard/engine/public/ice/gfx/gfx_runner.hxx index 3aa2e40af..550b66647 100644 --- a/source/code/iceshard/engine/public/ice/gfx/gfx_runner.hxx +++ b/source/code/iceshard/engine/public/ice/gfx/gfx_runner.hxx @@ -23,10 +23,12 @@ namespace ice::gfx { virtual ~GfxRunner() noexcept = default; + virtual bool has_rendergraph() const noexcept = 0; + //! \brief Sets a rendergraph to used for execution each frame. - virtual auto update_rendergraph( + virtual void update_rendergraph( ice::UniquePtr rendergraph - ) noexcept -> ice::Task<> = 0; + ) noexcept = 0; virtual auto update_data( ice::EngineFrame& frame, diff --git a/source/code/iceshard/iceshard/private/iceshard_gfx_runner.cxx b/source/code/iceshard/iceshard/private/iceshard_gfx_runner.cxx index e937ceb0e..965583330 100644 --- a/source/code/iceshard/iceshard/private/iceshard_gfx_runner.cxx +++ b/source/code/iceshard/iceshard/private/iceshard_gfx_runner.cxx @@ -113,12 +113,10 @@ namespace ice::gfx _context->device().destroy_fence(_present_fence); } - auto IceshardGfxRunner::update_rendergraph( + void IceshardGfxRunner::update_rendergraph( ice::UniquePtr rendergraph - ) noexcept -> ice::Task<> + ) noexcept { - co_await _scheduler; - if (_rendergraph != nullptr) { ice::gfx::GfxFrameStages gpu_stages{ @@ -135,8 +133,8 @@ namespace ice::gfx } } } - - _rendergraph = ice::move(rendergraph); + + _scheduled_rendergraph = ice::move(rendergraph); } auto IceshardGfxRunner::update_data( @@ -214,7 +212,7 @@ namespace ice::gfx } // Check if we have a scheduled render graph and if we can replace - if (_scheduled_rendergraph != nullptr && _rendergraph->ready()) + if (_scheduled_rendergraph != nullptr && (_rendergraph == nullptr || _rendergraph->ready())) { _rendergraph = ice::move(_scheduled_rendergraph); } @@ -227,6 +225,11 @@ namespace ice::gfx ice::execute_tasks(tasks); } + if (_rendergraph->ready() == false) + { + co_return; + } + if (_queue_transfer.not_empty() || _gfx_tasks.running_tasks() > 0) { IPT_ZONE_SCOPED_NAMED("gfx_await_tasks"); diff --git a/source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx b/source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx index b8ad79e71..8f5502869 100644 --- a/source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx +++ b/source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx @@ -46,9 +46,11 @@ namespace ice::gfx ) noexcept; ~IceshardGfxRunner() noexcept override; - auto update_rendergraph( + bool has_rendergraph() const noexcept override { return _rendergraph != nullptr; } + + void update_rendergraph( ice::UniquePtr rendergraph - ) noexcept -> ice::Task<> override; + ) noexcept; auto update_data( ice::EngineFrame& frame, From 6ff4f6b57101be42bb84b0a7764ce930681ae6a0 Mon Sep 17 00:00:00 2001 From: Dandielo Date: Wed, 11 Feb 2026 23:24:37 +0900 Subject: [PATCH 3/3] [iceshard] Small warning as errors fix. --- source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx b/source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx index 8f5502869..47e78b9e9 100644 --- a/source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx +++ b/source/code/iceshard/iceshard/private/iceshard_gfx_runner.hxx @@ -50,7 +50,7 @@ namespace ice::gfx void update_rendergraph( ice::UniquePtr rendergraph - ) noexcept; + ) noexcept override; auto update_data( ice::EngineFrame& frame,