From 5962499147607fe920f363f0c3dbf30931ec0bb8 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 25 Jul 2025 12:40:38 +0800 Subject: [PATCH] [Improvement] (MG_Util/Misc): Replace byte array with 64-bit bitmap in IndexGenerator. --- MobileGL/Includes.h | 2 +- MobileGL/MG_Util/Miscellany/IndexGenerator.h | 73 ++++++++++++++------ 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/MobileGL/Includes.h b/MobileGL/Includes.h index d3d997f0..22bfc91c 100644 --- a/MobileGL/Includes.h +++ b/MobileGL/Includes.h @@ -89,7 +89,7 @@ typedef int android_LogPriority; -inline int __android_log_print(int prio, const char* tag, const char* fmt, ...) { } +inline int __android_log_print(int prio, const char* tag, const char* fmt, ...) { return 0; } #endif #include "MG_Util/GLExtensions.h" diff --git a/MobileGL/MG_Util/Miscellany/IndexGenerator.h b/MobileGL/MG_Util/Miscellany/IndexGenerator.h index 83a19ef5..0f7aa19e 100644 --- a/MobileGL/MG_Util/Miscellany/IndexGenerator.h +++ b/MobileGL/MG_Util/Miscellany/IndexGenerator.h @@ -1,7 +1,4 @@ #pragma once -#include -#include -#include namespace MobileGL { template @@ -10,49 +7,79 @@ namespace MobileGL { explicit IndexGenerator(size_t initial_capacity = 1024, IndexType first_index = 0) : next_index_(first_index) { - is_valid_.reserve(initial_capacity); + const size_t words_needed = (initial_capacity + 63) / 64; + is_valid_.resize(words_needed, ~0ull); + freed_indices_.reserve(initial_capacity); } void Generate(size_t n, IndexType* indices) { if (n == 0) return; size_t from_freed = std::min(n, freed_indices_.size()); - for (size_t i = 0; i < from_freed; ++i) { - indices[i] = freed_indices_.back(); - freed_indices_.pop_back(); - is_valid_[indices[i]] = 1; + if (from_freed > 0) { + std::copy_n(freed_indices_.end() - from_freed, from_freed, indices); + freed_indices_.resize(freed_indices_.size() - from_freed); + + for (size_t i = 0; i < from_freed; ++i) { + SetValid(indices[i], true); + } } size_t need_new = n - from_freed; if (need_new > 0) { - size_t required = next_index_ + need_new; - if (required > is_valid_.size()) { - size_t new_cap = std::max(required, is_valid_.size() * 2); - is_valid_.resize(new_cap, 0); + size_t required_index = next_index_ + need_new; + size_t required_words = (required_index + 63) / 64; + if (required_words > is_valid_.size()) { + is_valid_.resize(required_words, ~0ull); } + for (size_t i = 0; i < need_new; ++i) { - indices[from_freed + i] = next_index_; - is_valid_[next_index_] = 1; - ++next_index_; + indices[from_freed + i] = next_index_++; } } } void Delete(IndexType index) { - if (index < is_valid_.size() && is_valid_[index]) { - is_valid_[index] = 0; - freed_indices_.push_back(index); + SetValid(index, false); + freed_indices_.push_back(index); + if (freed_indices_.size() > 1024 && freed_indices_.size() > next_index_ / 2) { + CompactFreeList(); } } bool IsValid(IndexType index) const { - return index < is_valid_.size() && is_valid_[index]; + size_t word = index >> 6; + size_t bit = index & 0x3F; + return word < is_valid_.size() && (is_valid_[word] & (1ull << bit)); + } + + size_t FreeListSize() const { return freed_indices_.size(); } + size_t ActiveCount() const { return next_index_ - freed_indices_.size(); } + + private: + inline void SetValid(IndexType index, bool valid) { + size_t word = index >> 6; + uint64_t mask = 1ull << (index & 0x3F); + + if (word >= is_valid_.size()) return; + + if (valid) { + is_valid_[word] |= mask; + } + else { + is_valid_[word] &= ~mask; + } + } + + void CompactFreeList() { + std::sort(freed_indices_.begin(), freed_indices_.end()); + auto last = std::unique(freed_indices_.begin(), freed_indices_.end()); + freed_indices_.erase(last, freed_indices_.end()); } private: IndexType next_index_ = 0; - std::vector freed_indices_; - std::vector is_valid_; + std::vector freed_indices_; + std::vector is_valid_; }; - -} +} \ No newline at end of file