Moved away from stl containers. Also added missing classes.

This commit is contained in:
Relintai 2023-12-30 23:40:20 +01:00
parent 3d04ef9d1e
commit 65e8c7ec13
18 changed files with 971 additions and 137 deletions

View File

@ -27,6 +27,7 @@ ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/safe_refcount.cpp
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/transform_2d.cpp -o sfw/core/transform_2d.o ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/transform_2d.cpp -o sfw/core/transform_2d.o
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/transform.cpp -o sfw/core/transform.o ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/transform.cpp -o sfw/core/transform.o
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/ustring.cpp -o sfw/core/ustring.o ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/ustring.cpp -o sfw/core/ustring.o
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/string_name.cpp -o sfw/core/string_name.o
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector2.cpp -o sfw/core/vector2.o ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector2.cpp -o sfw/core/vector2.o
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector2i.cpp -o sfw/core/vector2i.o ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector2i.cpp -o sfw/core/vector2i.o
ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector3.cpp -o sfw/core/vector3.o ccache g++ -Wall -D_REENTRANT -g -Isfw -Isfw/core -c sfw/core/vector3.cpp -o sfw/core/vector3.o
@ -67,7 +68,8 @@ ccache g++ -Wall -lm -ldl -lpthread -lX11 -D_REENTRANT -g sfw/core/aabb.o sfw/c
sfw/core/face3.o sfw/core/logger.o sfw/core/math_funcs.o \ sfw/core/face3.o sfw/core/logger.o sfw/core/math_funcs.o \
sfw/core/memory.o sfw/core/pcg.o sfw/core/plane.o sfw/core/projection.o sfw/core/quaternion.o sfw/core/random_pcg.o \ sfw/core/memory.o sfw/core/pcg.o sfw/core/plane.o sfw/core/projection.o sfw/core/quaternion.o sfw/core/random_pcg.o \
sfw/core/rect2.o sfw/core/rect2i.o sfw/core/safe_refcount.o sfw/core/transform_2d.o sfw/core/transform.o \ sfw/core/rect2.o sfw/core/rect2i.o sfw/core/safe_refcount.o sfw/core/transform_2d.o sfw/core/transform.o \
sfw/core/ustring.o sfw/core/vector2.o sfw/core/vector2i.o sfw/core/vector3.o \ sfw/core/ustring.o sfw/core/string_name.o \
sfw/core/vector2.o sfw/core/vector2i.o sfw/core/vector3.o \
sfw/core/vector3i.o sfw/core/vector4.o sfw/core/vector4i.o \ sfw/core/vector3i.o sfw/core/vector4.o sfw/core/vector4i.o \
sfw/core/pool_vector.o sfw/core/pool_allocator.o sfw/core/mutex.o sfw/core/stime.o \ sfw/core/pool_vector.o sfw/core/pool_allocator.o sfw/core/mutex.o sfw/core/stime.o \
sfw/render_core/application.o sfw/render_core/scene.o sfw/render_core/window.o \ sfw/render_core/application.o sfw/render_core/scene.o sfw/render_core/window.o \

View File

@ -234,10 +234,21 @@ _FORCE_INLINE_ void _RLOG_MACRO_TEMPLATE_FUNC(STR str, A p0, B p1, C p2, D p3, E
} else \ } else \
((void)0) ((void)0)
#define CRASH_COND_MSG(cond, msg) \
if (cond) { \
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, msg); \
GENERATE_TRAP \
} else \
((void)0)
#define CRASH_MSG(msg) \ #define CRASH_MSG(msg) \
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, msg); \ RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, msg); \
GENERATE_TRAP GENERATE_TRAP
#define CRASH_NOW(msg) \
RLogger::log_error(__FUNCTION__, __FILE__, __LINE__, "CRASH!"); \
GENERATE_TRAP
/** /**
* This should be a 'free' assert for program flow and should not be needed in any releases, * This should be a 'free' assert for program flow and should not be needed in any releases,
* only used in dev builds. * only used in dev builds.

View File

@ -35,8 +35,9 @@
#include "hashfuncs.h" #include "hashfuncs.h"
#include "paged_allocator.h" #include "paged_allocator.h"
#include "pair.h" #include "pair.h"
#include "core/math/math_funcs.h" #include "math_funcs.h"
#include "memory.h" #include "memory.h"
#include "list.h"
/** /**
* A HashMap implementation that uses open addressing with Robin Hood hashing. * A HashMap implementation that uses open addressing with Robin Hood hashing.

View File

@ -34,7 +34,7 @@
#include "hash_map.h" #include "hash_map.h"
#include "hashfuncs.h" #include "hashfuncs.h"
#include "core/math/math_funcs.h" #include "math_funcs.h"
#include "memory.h" #include "memory.h"
/** /**

View File

@ -32,22 +32,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "rid.h" #include "aabb.h"
#include "core/math/aabb.h" #include "math_defs.h"
#include "core/math/math_defs.h" #include "math_funcs.h"
#include "core/math/math_funcs.h" #include "rect2.h"
#include "core/math/rect2.h" #include "rect2i.h"
#include "core/math/rect2i.h" #include "vector2.h"
#include "core/math/vector2.h" #include "vector2i.h"
#include "core/math/vector2i.h" #include "vector3.h"
#include "core/math/vector3.h" #include "vector3i.h"
#include "core/math/vector3i.h" #include "vector4.h"
#include "core/math/vector4.h" #include "vector4i.h"
#include "core/math/vector4i.h" #include "string_name.h"
#include "core/object/object_id.h" #include "ustring.h"
#include "core/string/node_path.h"
#include "core/string/string_name.h"
#include "core/string/ustring.h"
#include "core/typedefs.h" #include "core/typedefs.h"
/** /**
@ -321,10 +318,7 @@ struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(p_wchar); } static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(p_wchar); }
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); } static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); } static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); } static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
//static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); } static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); }

52
sfw/core/spin_lock.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef SPIN_LOCK_H
#define SPIN_LOCK_H
/*************************************************************************/
/* spin_lock.h */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* https://github.com/Relintai/pandemonium_engine */
/*************************************************************************/
/* Copyright (c) 2022-present Péter Magyar. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "core/typedefs.h"
#include <atomic>
class SpinLock {
std::atomic_flag locked = ATOMIC_FLAG_INIT;
public:
_ALWAYS_INLINE_ void lock() {
while (locked.test_and_set(std::memory_order_acquire)) {
;
}
}
_ALWAYS_INLINE_ void unlock() {
locked.clear(std::memory_order_release);
}
};
#endif // SPIN_LOCK_H

544
sfw/core/string_name.cpp Normal file
View File

@ -0,0 +1,544 @@
/*************************************************************************/
/* string_name.cpp */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* https://github.com/Relintai/pandemonium_engine */
/*************************************************************************/
/* Copyright (c) 2022-present Péter Magyar. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "string_name.h"
StaticCString StaticCString::create(const char *p_ptr) {
StaticCString scs;
scs.ptr = p_ptr;
return scs;
}
StringName::_Data *StringName::_table[STRING_TABLE_LEN];
StringName _scs_create(const char *p_chr, bool p_static) {
return (p_chr[0] ? StringName(StaticCString::create(p_chr), p_static) : StringName());
}
bool StringName::configured = false;
Mutex StringName::lock;
#ifdef DEBUG_ENABLED
bool StringName::debug_stringname = false;
#endif
void StringName::setup() {
ERR_FAIL_COND(configured);
for (int i = 0; i < STRING_TABLE_LEN; i++) {
_table[i] = nullptr;
}
configured = true;
}
void StringName::cleanup() {
lock.lock();
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
Vector<_Data *> data;
for (int i = 0; i < STRING_TABLE_LEN; i++) {
_Data *d = _table[i];
while (d) {
data.push_back(d);
d = d->next;
}
}
print_line("\nStringName reference ranking (from most to least referenced):\n");
data.sort_custom<DebugSortReferences>();
int unreferenced_stringnames = 0;
int rarely_referenced_stringnames = 0;
for (int i = 0; i < data.size(); i++) {
print_line(itos(i + 1) + ": " + data[i]->get_name() + " - " + itos(data[i]->debug_references));
if (data[i]->debug_references == 0) {
unreferenced_stringnames += 1;
} else if (data[i]->debug_references < 5) {
rarely_referenced_stringnames += 1;
}
}
print_line(vformat("\nOut of %d StringNames, %d StringNames were never referenced during this run (0 times) (%.2f%%).", data.size(), unreferenced_stringnames, unreferenced_stringnames / float(data.size()) * 100));
print_line(vformat("Out of %d StringNames, %d StringNames were rarely referenced during this run (1-4 times) (%.2f%%).", data.size(), rarely_referenced_stringnames, rarely_referenced_stringnames / float(data.size()) * 100));
}
#endif
//int lost_strings = 0;
for (int i = 0; i < STRING_TABLE_LEN; i++) {
while (_table[i]) {
_Data *d = _table[i];
/*
if (d->static_count.get() != d->refcount.get()) {
lost_strings++;
if (OS::get_singleton()->is_stdout_verbose()) {
if (d->cname) {
print_line("Orphan StringName: " + String(d->cname));
} else {
print_line("Orphan StringName: " + String(d->name));
}
}
}
*/
_table[i] = _table[i]->next;
memdelete(d);
}
}
/*
if (lost_strings) {
print_verbose("StringName: " + itos(lost_strings) + " unclaimed string names at exit.");
}
*/
configured = false;
lock.unlock();
}
void StringName::unref() {
ERR_FAIL_COND(!configured);
if (_data && _data->refcount.unref()) {
lock.lock();
if (_data->static_count.get() > 0) {
if (_data->cname) {
ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->cname));
} else {
ERR_PRINT("BUG: Unreferenced static string to 0: " + String(_data->name));
}
}
if (_data->prev) {
_data->prev->next = _data->next;
} else {
if (_table[_data->idx] != _data) {
ERR_PRINT("BUG!");
}
_table[_data->idx] = _data->next;
}
if (_data->next) {
_data->next->prev = _data->prev;
}
memdelete(_data);
lock.unlock();
}
_data = nullptr;
}
bool StringName::operator==(const String &p_name) const {
if (!_data) {
return (p_name.length() == 0);
}
return (_data->get_name() == p_name);
}
bool StringName::operator==(const char *p_name) const {
if (!_data) {
return (p_name[0] == 0);
}
return (_data->get_name() == p_name);
}
bool StringName::operator!=(const String &p_name) const {
return !(operator==(p_name));
}
bool StringName::operator!=(const StringName &p_name) const {
// the real magic of all this mess happens here.
// this is why path comparisons are very fast
return _data != p_name._data;
}
void StringName::operator=(const StringName &p_name) {
if (this == &p_name) {
return;
}
unref();
if (p_name._data && p_name._data->refcount.ref()) {
_data = p_name._data;
}
}
StringName::StringName(const StringName &p_name) {
_data = nullptr;
ERR_FAIL_COND(!configured);
if (p_name._data && p_name._data->refcount.ref()) {
_data = p_name._data;
}
}
StringName::StringName(const char *p_name, bool p_static) {
_data = nullptr;
ERR_FAIL_COND(!configured);
if (!p_name || p_name[0] == 0) {
return; //empty, ignore
}
lock.lock();
uint32_t hash = String::hash(p_name);
uint32_t idx = hash & STRING_TABLE_MASK;
_data = _table[idx];
while (_data) {
// compare hash first
if (_data->hash == hash && _data->get_name() == p_name) {
break;
}
_data = _data->next;
}
if (_data) {
if (_data->refcount.ref()) {
// exists
if (p_static) {
_data->static_count.increment();
}
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
_data->debug_references++;
}
#endif
lock.unlock();
return;
}
}
_data = memnew(_Data);
_data->name = p_name;
_data->refcount.init();
_data->static_count.set(p_static ? 1 : 0);
_data->hash = hash;
_data->idx = idx;
_data->cname = NULL;
_data->next = _table[idx];
_data->prev = NULL;
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
// Keep in memory, force static.
_data->refcount.ref();
_data->static_count.increment();
}
#endif
if (_table[idx]) {
_table[idx]->prev = _data;
}
_table[idx] = _data;
lock.unlock();
}
StringName::StringName(const StaticCString &p_static_string, bool p_static) {
_data = NULL;
ERR_FAIL_COND(!configured);
ERR_FAIL_COND(!p_static_string.ptr || !p_static_string.ptr[0]);
lock.lock();
uint32_t hash = String::hash(p_static_string.ptr);
uint32_t idx = hash & STRING_TABLE_MASK;
_data = _table[idx];
while (_data) {
// compare hash first
if (_data->hash == hash && _data->get_name() == p_static_string.ptr) {
break;
}
_data = _data->next;
}
if (_data) {
if (_data->refcount.ref()) {
// exists
if (p_static) {
_data->static_count.increment();
}
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
_data->debug_references++;
}
#endif
lock.unlock();
return;
}
}
_data = memnew(_Data);
_data->refcount.init();
_data->static_count.set(p_static ? 1 : 0);
_data->hash = hash;
_data->idx = idx;
_data->cname = p_static_string.ptr;
_data->next = _table[idx];
_data->prev = NULL;
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
// Keep in memory, force static.
_data->refcount.ref();
_data->static_count.increment();
}
#endif
if (_table[idx]) {
_table[idx]->prev = _data;
}
_table[idx] = _data;
lock.unlock();
}
StringName::StringName(const String &p_name, bool p_static) {
_data = nullptr;
ERR_FAIL_COND(!configured);
if (p_name.empty()) {
return;
}
lock.lock();
uint32_t hash = p_name.hash();
uint32_t idx = hash & STRING_TABLE_MASK;
_data = _table[idx];
while (_data) {
if (_data->hash == hash && _data->get_name() == p_name) {
break;
}
_data = _data->next;
}
if (_data) {
if (_data->refcount.ref()) {
// exists
if (p_static) {
_data->static_count.increment();
}
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
_data->debug_references++;
}
#endif
lock.unlock();
return;
}
}
_data = memnew(_Data);
_data->name = p_name;
_data->refcount.init();
_data->static_count.set(p_static ? 1 : 0);
_data->hash = hash;
_data->idx = idx;
_data->cname = NULL;
_data->next = _table[idx];
_data->prev = NULL;
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
// Keep in memory, force static.
_data->refcount.ref();
_data->static_count.increment();
}
#endif
if (_table[idx]) {
_table[idx]->prev = _data;
}
_table[idx] = _data;
lock.unlock();
}
StringName StringName::search(const char *p_name) {
ERR_FAIL_COND_V(!configured, StringName());
ERR_FAIL_COND_V(!p_name, StringName());
if (!p_name[0]) {
return StringName();
}
lock.lock();
uint32_t hash = String::hash(p_name);
uint32_t idx = hash & STRING_TABLE_MASK;
_Data *_data = _table[idx];
while (_data) {
// compare hash first
if (_data->hash == hash && _data->get_name() == p_name) {
break;
}
_data = _data->next;
}
if (_data && _data->refcount.ref()) {
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
_data->debug_references++;
}
#endif
lock.unlock();
return StringName(_data);
}
lock.unlock();
return StringName(); //does not exist
}
StringName StringName::search(const CharType *p_name) {
ERR_FAIL_COND_V(!configured, StringName());
ERR_FAIL_COND_V(!p_name, StringName());
if (!p_name[0]) {
return StringName();
}
lock.lock();
uint32_t hash = String::hash(p_name);
uint32_t idx = hash & STRING_TABLE_MASK;
_Data *_data = _table[idx];
while (_data) {
// compare hash first
if (_data->hash == hash && _data->get_name() == p_name) {
break;
}
_data = _data->next;
}
if (_data && _data->refcount.ref()) {
lock.unlock();
return StringName(_data);
}
lock.unlock();
return StringName(); //does not exist
}
StringName StringName::search(const String &p_name) {
ERR_FAIL_COND_V(p_name == "", StringName());
lock.lock();
uint32_t hash = p_name.hash();
uint32_t idx = hash & STRING_TABLE_MASK;
_Data *_data = _table[idx];
while (_data) {
// compare hash first
if (_data->hash == hash && p_name == _data->get_name()) {
break;
}
_data = _data->next;
}
if (_data && _data->refcount.ref()) {
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
_data->debug_references++;
}
#endif
lock.unlock();
return StringName(_data);
}
lock.unlock();
return StringName(); //does not exist
}
StringName::StringName() {
_data = nullptr;
}
/*
bool operator==(const String &p_name, const StringName &p_string_name) {
return p_name == p_string_name.operator String();
}
bool operator!=(const String &p_name, const StringName &p_string_name) {
return p_name != p_string_name.operator String();
}
bool operator==(const char *p_name, const StringName &p_string_name) {
return p_name == p_string_name.operator String();
}
bool operator!=(const char *p_name, const StringName &p_string_name) {
return p_name != p_string_name.operator String();
}
*/

231
sfw/core/string_name.h Normal file
View File

@ -0,0 +1,231 @@
#ifndef STRING_NAME_H
#define STRING_NAME_H
/*************************************************************************/
/* string_name.h */
/*************************************************************************/
/* This file is part of: */
/* PANDEMONIUM ENGINE */
/* https://github.com/Relintai/pandemonium_engine */
/*************************************************************************/
/* Copyright (c) 2022-present Péter Magyar. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "mutex.h"
#include "safe_refcount.h"
#include "ustring.h"
struct StaticCString {
const char *ptr;
static StaticCString create(const char *p_ptr);
};
class StringName {
enum {
STRING_TABLE_BITS = 14,
STRING_TABLE_LEN = 1 << STRING_TABLE_BITS,
STRING_TABLE_MASK = STRING_TABLE_LEN - 1
};
struct _Data {
SafeRefCount refcount;
SafeNumeric<uint32_t> static_count;
const char *cname;
String name;
#ifdef DEBUG_ENABLED
uint32_t debug_references;
#endif
String get_name() const {
return cname ? String(cname) : name;
}
int idx;
uint32_t hash;
_Data *prev;
_Data *next;
_Data() {
#ifdef DEBUG_ENABLED
debug_references = 0;
#endif
cname = nullptr;
prev = nullptr;
next = nullptr;
idx = 0;
hash = 0;
}
};
static _Data *_table[STRING_TABLE_LEN];
_Data *_data;
union _HashUnion {
_Data *ptr;
uint32_t hash;
_HashUnion() {
ptr = nullptr;
}
};
void unref();
friend void register_core_types();
friend void unregister_core_types();
static Mutex lock;
static void setup();
static void cleanup();
static bool configured;
#ifdef DEBUG_ENABLED
struct DebugSortReferences {
bool operator()(const _Data *p_left, const _Data *p_right) const {
return p_left->debug_references > p_right->debug_references;
}
};
static bool debug_stringname;
#endif
StringName(_Data *p_data) {
_data = p_data;
}
public:
operator const void *() const {
return (_data && (_data->cname || !_data->name.empty())) ? (void *)1 : nullptr;
}
bool operator==(const String &p_name) const;
bool operator==(const char *p_name) const;
bool operator!=(const String &p_name) const;
_FORCE_INLINE_ bool is_node_unique_name() const {
if (!_data) {
return false;
}
if (_data->cname != nullptr) {
return _data->cname[0] == '%';
} else {
return _data->name[0] == '%';
}
}
_FORCE_INLINE_ bool operator<(const StringName &p_name) const {
return _data < p_name._data;
}
_FORCE_INLINE_ bool operator==(const StringName &p_name) const {
// the real magic of all this mess happens here.
// this is why path comparisons are very fast
return _data == p_name._data;
}
_FORCE_INLINE_ uint32_t hash() const {
if (_data) {
return _data->hash;
} else {
return 0;
}
}
_FORCE_INLINE_ const void *data_unique_pointer() const {
return (void *)_data;
}
bool operator!=(const StringName &p_name) const;
_FORCE_INLINE_ operator String() const {
if (_data) {
if (_data->cname) {
return String(_data->cname);
} else {
return _data->name;
}
}
return String();
}
static StringName search(const char *p_name);
static StringName search(const CharType *p_name);
static StringName search(const String &p_name);
struct AlphCompare {
_FORCE_INLINE_ bool operator()(const StringName &l, const StringName &r) const {
const char *l_cname = l._data ? l._data->cname : "";
const char *r_cname = r._data ? r._data->cname : "";
if (l_cname) {
if (r_cname) {
return is_str_less(l_cname, r_cname);
} else {
return is_str_less(l_cname, r._data->name.ptr());
}
} else {
if (r_cname) {
return is_str_less(l._data->name.ptr(), r_cname);
} else {
return is_str_less(l._data->name.ptr(), r._data->name.ptr());
}
}
}
};
void operator=(const StringName &p_name);
StringName(const char *p_name, bool p_static = false);
StringName(const StringName &p_name);
StringName(const String &p_name, bool p_static = false);
StringName(const StaticCString &p_static_string, bool p_static = false);
StringName();
_FORCE_INLINE_ ~StringName() {
if (likely(configured) && _data) { //only free if configured
unref();
}
}
};
/*
bool operator==(const String &p_name, const StringName &p_string_name);
bool operator!=(const String &p_name, const StringName &p_string_name);
bool operator==(const char *p_name, const StringName &p_string_name);
bool operator!=(const char *p_name, const StringName &p_string_name);
*/
StringName _scs_create(const char *p_chr, bool p_static = false);
/*
* The SNAME macro is used to speed up StringName creation, as it allows caching it after the first usage in a very efficient way.
* It should NOT be used everywhere, but instead in places where high performance is required and the creation of a StringName
* can be costly. Places where it should be used are:
* - Control::get_theme_*(<name> and Window::get_theme_*(<name> functions.
* - emit_signal(<name>,..) function
* - call_deferred(<name>,..) function
* - Comparisons to a StringName in overridden _set and _get methods.
*
* Use in places that can be called hundreds of times per frame (or more) is recommended, but this situation is very rare. If in doubt, do not use.
*/
//#define SNAME(m_arg) ([]() -> const StringName & { static StringName sname = _scs_create(m_arg, true); return sname; })()
#endif // STRING_NAME_H

View File

@ -36,7 +36,7 @@
#include "memory.h" #include "memory.h"
#include <memory.h> #include <memory.h>
#include <stdio.h> #include <stdio.h>
#include <map> #include "hash_map.h"
const char *Image::format_names[Image::FORMAT_MAX] = { const char *Image::format_names[Image::FORMAT_MAX] = {
"Lum8", // luminance "Lum8", // luminance
@ -1748,7 +1748,7 @@ void Image::create(const char **p_xpm) {
Status status = READING_HEADER; Status status = READING_HEADER;
int line = 0; int line = 0;
std::map<String, Color> colormap; HashMap<String, Color> colormap;
int colormap_size = 0; int colormap_size = 0;
uint32_t pixel_size = 0; uint32_t pixel_size = 0;
uint8_t *w_ptr; uint8_t *w_ptr;

View File

@ -9,7 +9,7 @@ void Material::bind() {
shader = ShaderCache::get_singleton()->get_shader(get_material_id()); shader = ShaderCache::get_singleton()->get_shader(get_material_id());
if (!shader) { if (!shader) {
shader = new Shader(); shader = memnew(Shader());
shader->set_vertex_shader_source(get_vertex_shader_source()); shader->set_vertex_shader_source(get_vertex_shader_source());
shader->set_fragment_shader_source(get_fragment_shader_source()); shader->set_fragment_shader_source(get_fragment_shader_source());

View File

@ -64,18 +64,18 @@ void Mesh::upload() {
glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, NULL, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_vbo_size, &vertices[0]); glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_vbo_size, vertices.ptr());
if (normals_vbo_size > 0) { if (normals_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size, normals_vbo_size, &normals[0]); glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size, normals_vbo_size, normals.ptr());
} }
if (colors_vbo_size > 0) { if (colors_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size, colors_vbo_size, &colors[0]); glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size, colors_vbo_size, colors.ptr());
} }
if (uvs_vbo_size > 0) { if (uvs_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size, uvs_vbo_size, &uvs[0]); glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size, uvs_vbo_size, uvs.ptr());
} }
if (indices_vbo_size > 0) { if (indices_vbo_size > 0) {
@ -84,7 +84,7 @@ void Mesh::upload() {
} }
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_vbo_size, &indices[0], GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_vbo_size, indices.ptr(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }

View File

@ -1,7 +1,7 @@
#ifndef MESH_H #ifndef MESH_H
#define MESH_H #define MESH_H
#include <vector> #include "vector.h"
#include <inttypes.h> #include <inttypes.h>
#include "3rd_glad.h" #include "3rd_glad.h"
@ -34,11 +34,11 @@ public:
int vertex_dimesions; int vertex_dimesions;
std::vector<float> vertices; Vector<float> vertices;
std::vector<float> normals; Vector<float> normals;
std::vector<float> colors; Vector<float> colors;
std::vector<float> uvs; Vector<float> uvs;
std::vector<uint32_t> indices; Vector<uint32_t> indices;
protected: protected:
uint32_t vertices_vbo_size; uint32_t vertices_vbo_size;

View File

@ -1,7 +1,7 @@
#include "shader.h" #include "shader.h"
#include <vector>
#include <stdio.h> #include <stdio.h>
#include <vector>
bool Shader::bind() { bool Shader::bind() {
if (current_shader != this) { if (current_shader != this) {
@ -50,7 +50,6 @@ void Shader::compile() {
glAttachShader(program, vertex_shader); glAttachShader(program, vertex_shader);
const GLchar **fragment_shader_source = get_fragment_shader_source(); const GLchar **fragment_shader_source = get_fragment_shader_source();
glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
@ -101,12 +100,13 @@ void Shader::set_fragment_shader_source(const GLchar **source) {
void Shader::print_shader_errors(const GLuint p_program, const char *name) { void Shader::print_shader_errors(const GLuint p_program, const char *name) {
int max_length = 5000; int max_length = 5000;
std::vector<GLchar> error_log(max_length); Vector<GLchar> error_log;
error_log.resize(max_length);
glGetShaderInfoLog(p_program, max_length, &max_length, &error_log[0]); glGetShaderInfoLog(p_program, max_length, &max_length, error_log.ptrw());
printf("Error %s!\n", name); printf("Error %s!\n", name);
printf("%s!\n", &error_log[0]); printf("%s!\n", error_log.ptr());
} }
void Shader::print_program_errors(const GLuint p_program) { void Shader::print_program_errors(const GLuint p_program) {
@ -162,10 +162,9 @@ void ShaderCache::add_shader(const int id, Shader *shader) {
ShaderCache::ShaderCache() { ShaderCache::ShaderCache() {
} }
ShaderCache::~ShaderCache() { ShaderCache::~ShaderCache() {
for (const std::pair<int, Shader *> n : shaders) { for (HashMap<int, Shader *>::Element *E = shaders.front(); E; E = E->next) {
delete n.second; memdelete(E->get());
} }
shaders.clear(); shaders.clear();
} }

View File

@ -2,7 +2,7 @@
#define SHADER_H #define SHADER_H
#include "3rd_glad.h" #include "3rd_glad.h"
#include <unordered_map> #include "hash_map.h"
class Shader { class Shader {
public: public:
@ -53,7 +53,7 @@ public:
~ShaderCache(); ~ShaderCache();
protected: protected:
std::unordered_map<int, Shader *> shaders; HashMap<int, Shader *> shaders;
}; };
#endif // SHADER_H #endif // SHADER_H

View File

@ -17,7 +17,7 @@ void MeshInstance2D::render() {
mesh->render(); mesh->render();
for (uint32_t i = 0; i < children.size(); ++i) { for (int i = 0; i < children.size(); ++i) {
MeshInstance2D * c = children[i]; MeshInstance2D * c = children[i];
if (c) { if (c) {

View File

@ -1,7 +1,7 @@
#ifndef MESH_INSTACE_2D_H #ifndef MESH_INSTACE_2D_H
#define MESH_INSTACE_2D_H #define MESH_INSTACE_2D_H
#include <vector> #include "vector.h"
#include "material.h" #include "material.h"
#include "mesh.h" #include "mesh.h"
@ -20,7 +20,7 @@ public:
Transform2D transform; Transform2D transform;
std::vector<MeshInstance2D *> children; Vector<MeshInstance2D *> children;
}; };
#endif // MESH_INSTACE_H #endif // MESH_INSTACE_H

View File

@ -17,7 +17,7 @@ void MeshInstance3D::render() {
mesh->render(); mesh->render();
for (uint32_t i = 0; i < children.size(); ++i) { for (int i = 0; i < children.size(); ++i) {
MeshInstance3D * c = children[i]; MeshInstance3D * c = children[i];
if (c) { if (c) {

View File

@ -1,7 +1,7 @@
#ifndef MESH_INSTACE_3D_H #ifndef MESH_INSTACE_3D_H
#define MESH_INSTACE_3D_H #define MESH_INSTACE_3D_H
#include <vector> #include "vector.h"
#include "object_3d.h" #include "object_3d.h"
@ -20,7 +20,7 @@ public:
Material *material; Material *material;
Mesh *mesh; Mesh *mesh;
std::vector<MeshInstance3D *> children; Vector<MeshInstance3D *> children;
}; };
#endif // MESH_INSTACE_H #endif // MESH_INSTACE_H