mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Improvement] (MG_Util/Misc): Replace byte array with 64-bit bitmap in IndexGenerator.
This commit is contained in:
+1
-1
@@ -89,7 +89,7 @@
|
|||||||
|
|
||||||
typedef int android_LogPriority;
|
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
|
#endif
|
||||||
|
|
||||||
#include "MG_Util/GLExtensions.h"
|
#include "MG_Util/GLExtensions.h"
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
template <typename IndexType>
|
template <typename IndexType>
|
||||||
@@ -10,49 +7,79 @@ namespace MobileGL {
|
|||||||
explicit IndexGenerator(size_t initial_capacity = 1024, IndexType first_index = 0)
|
explicit IndexGenerator(size_t initial_capacity = 1024, IndexType first_index = 0)
|
||||||
: next_index_(first_index)
|
: 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) {
|
void Generate(size_t n, IndexType* indices) {
|
||||||
if (n == 0) return;
|
if (n == 0) return;
|
||||||
|
|
||||||
size_t from_freed = std::min(n, freed_indices_.size());
|
size_t from_freed = std::min(n, freed_indices_.size());
|
||||||
|
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) {
|
for (size_t i = 0; i < from_freed; ++i) {
|
||||||
indices[i] = freed_indices_.back();
|
SetValid(indices[i], true);
|
||||||
freed_indices_.pop_back();
|
}
|
||||||
is_valid_[indices[i]] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t need_new = n - from_freed;
|
size_t need_new = n - from_freed;
|
||||||
if (need_new > 0) {
|
if (need_new > 0) {
|
||||||
size_t required = next_index_ + need_new;
|
size_t required_index = next_index_ + need_new;
|
||||||
if (required > is_valid_.size()) {
|
size_t required_words = (required_index + 63) / 64;
|
||||||
size_t new_cap = std::max(required, is_valid_.size() * 2);
|
if (required_words > is_valid_.size()) {
|
||||||
is_valid_.resize(new_cap, 0);
|
is_valid_.resize(required_words, ~0ull);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < need_new; ++i) {
|
for (size_t i = 0; i < need_new; ++i) {
|
||||||
indices[from_freed + i] = next_index_;
|
indices[from_freed + i] = next_index_++;
|
||||||
is_valid_[next_index_] = 1;
|
|
||||||
++next_index_;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Delete(IndexType index) {
|
void Delete(IndexType index) {
|
||||||
if (index < is_valid_.size() && is_valid_[index]) {
|
SetValid(index, false);
|
||||||
is_valid_[index] = 0;
|
|
||||||
freed_indices_.push_back(index);
|
freed_indices_.push_back(index);
|
||||||
|
if (freed_indices_.size() > 1024 && freed_indices_.size() > next_index_ / 2) {
|
||||||
|
CompactFreeList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValid(IndexType index) const {
|
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:
|
private:
|
||||||
IndexType next_index_ = 0;
|
IndexType next_index_ = 0;
|
||||||
std::vector<IndexType> freed_indices_;
|
std::vector<IndexType> freed_indices_;
|
||||||
std::vector<Uint8> is_valid_;
|
std::vector<Uint64> is_valid_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user