summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/engine.cpp4
-rw-r--r--core/config/engine.h2
-rw-r--r--core/core_bind.cpp1
-rw-r--r--core/core_bind.h1
-rw-r--r--core/io/image.cpp23
-rw-r--r--core/io/image.h2
-rw-r--r--core/io/resource_loader.cpp20
-rw-r--r--core/io/resource_loader.h2
-rw-r--r--core/math/aabb.h23
-rw-r--r--core/math/rect2.h16
-rw-r--r--core/object/class_db.cpp23
-rw-r--r--core/object/class_db.h1
-rw-r--r--core/os/memory.cpp33
-rw-r--r--core/os/memory.h24
-rw-r--r--core/variant/variant_call.cpp3
15 files changed, 152 insertions, 26 deletions
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 3574430cf7..9cdc21fe8e 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -263,6 +263,10 @@ bool Engine::is_generate_spirv_debug_info_enabled() const {
return generate_spirv_debug_info;
}
+bool Engine::is_extra_gpu_memory_tracking_enabled() const {
+ return extra_gpu_memory_tracking;
+}
+
void Engine::set_print_error_messages(bool p_enabled) {
CoreGlobals::print_error_enabled = p_enabled;
}
diff --git a/core/config/engine.h b/core/config/engine.h
index 7e617d8773..f858eba328 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -72,6 +72,7 @@ private:
bool abort_on_gpu_errors = false;
bool use_validation_layers = false;
bool generate_spirv_debug_info = false;
+ bool extra_gpu_memory_tracking = false;
int32_t gpu_idx = -1;
uint64_t _process_frames = 0;
@@ -181,6 +182,7 @@ public:
bool is_abort_on_gpu_errors_enabled() const;
bool is_validation_layers_enabled() const;
bool is_generate_spirv_debug_info_enabled() const;
+ bool is_extra_gpu_memory_tracking_enabled() const;
int32_t get_gpu_index() const;
void increment_frames_drawn();
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index a15085bcde..36f662b92b 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -692,6 +692,7 @@ void OS::_bind_methods() {
BIND_ENUM_CONSTANT(RENDERING_DRIVER_VULKAN);
BIND_ENUM_CONSTANT(RENDERING_DRIVER_OPENGL3);
BIND_ENUM_CONSTANT(RENDERING_DRIVER_D3D12);
+ BIND_ENUM_CONSTANT(RENDERING_DRIVER_METAL);
BIND_ENUM_CONSTANT(SYSTEM_DIR_DESKTOP);
BIND_ENUM_CONSTANT(SYSTEM_DIR_DCIM);
diff --git a/core/core_bind.h b/core/core_bind.h
index 69a359e4ed..d744da2551 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -132,6 +132,7 @@ public:
RENDERING_DRIVER_VULKAN,
RENDERING_DRIVER_OPENGL3,
RENDERING_DRIVER_D3D12,
+ RENDERING_DRIVER_METAL,
};
PackedByteArray get_entropy(int p_bytes);
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 499364826d..003646d095 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -30,6 +30,7 @@
#include "image.h"
+#include "core/config/project_settings.h"
#include "core/error/error_list.h"
#include "core/error/error_macros.h"
#include "core/io/image_loader.h"
@@ -2734,6 +2735,27 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) {
ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);
+ // RenderingDevice only.
+ if (GLOBAL_GET("rendering/textures/vram_compression/compress_with_gpu")) {
+ switch (p_mode) {
+ case COMPRESS_BPTC: {
+ // BC7 is unsupported currently.
+ if ((format >= FORMAT_RF && format <= FORMAT_RGBE9995) && _image_compress_bptc_rd_func) {
+ Error result = _image_compress_bptc_rd_func(this, p_channels);
+
+ // If the image was compressed successfully, we return here. If not, we fall back to the default compression scheme.
+ if (result == OK) {
+ return OK;
+ }
+ }
+
+ } break;
+
+ default: {
+ }
+ }
+ }
+
switch (p_mode) {
case COMPRESS_S3TC: {
ERR_FAIL_NULL_V(_image_compress_bc_func, ERR_UNAVAILABLE);
@@ -3115,6 +3137,7 @@ void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr
void (*Image::_image_compress_etc1_func)(Image *) = nullptr;
void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr;
+Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr;
void (*Image::_image_decompress_bc)(Image *) = nullptr;
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
diff --git a/core/io/image.h b/core/io/image.h
index cc285dabe3..8d09a0b40b 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -159,6 +159,8 @@ public:
static void (*_image_compress_etc2_func)(Image *, UsedChannels p_channels);
static void (*_image_compress_astc_func)(Image *, ASTCFormat p_format);
+ static Error (*_image_compress_bptc_rd_func)(Image *, UsedChannels p_channels);
+
static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_bptc)(Image *);
static void (*_image_decompress_etc1)(Image *);
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 0577ca6bca..c9ed4e27d9 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -340,11 +340,10 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
load_task.status = THREAD_LOAD_LOADED;
}
- if (load_task.cond_var) {
+ if (load_task.cond_var && load_task.need_wait) {
load_task.cond_var->notify_all();
- memdelete(load_task.cond_var);
- load_task.cond_var = nullptr;
}
+ load_task.need_wait = false;
bool ignoring = load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE || load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP;
bool replacing = load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE || load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP;
@@ -723,15 +722,21 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
DEV_ASSERT(wtp_task_err == OK);
thread_load_mutex.lock();
}
- } else {
+ } else if (load_task.need_wait) {
// Loading thread is main or user thread.
if (!load_task.cond_var) {
load_task.cond_var = memnew(ConditionVariable);
}
+ load_task.awaiters_count++;
do {
load_task.cond_var->wait(p_thread_load_lock);
DEV_ASSERT(thread_load_tasks.has(p_load_token.local_path) && p_load_token.get_reference_count());
- } while (load_task.cond_var);
+ } while (load_task.need_wait);
+ load_task.awaiters_count--;
+ if (load_task.awaiters_count == 0) {
+ memdelete(load_task.cond_var);
+ load_task.cond_var = nullptr;
+ }
}
} else {
if (loader_is_wtp) {
@@ -1159,11 +1164,10 @@ void ResourceLoader::clear_thread_load_tasks() {
if (thread_load_tasks.size()) {
for (KeyValue<String, ResourceLoader::ThreadLoadTask> &E : thread_load_tasks) {
if (E.value.status == THREAD_LOAD_IN_PROGRESS) {
- if (E.value.cond_var) {
+ if (E.value.cond_var && E.value.need_wait) {
E.value.cond_var->notify_all();
- memdelete(E.value.cond_var);
- E.value.cond_var = nullptr;
}
+ E.value.need_wait = false;
none_running = false;
}
}
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 9d07964105..ec9997891e 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -167,6 +167,8 @@ private:
Thread::ID thread_id = 0; // Used if running on an user thread (e.g., simple non-threaded load).
bool awaited = false; // If it's in the pool, this helps not awaiting from more than one dependent thread.
ConditionVariable *cond_var = nullptr; // In not in the worker pool or already awaiting, this is used as a secondary awaiting mechanism.
+ uint32_t awaiters_count = 0;
+ bool need_wait = true;
LoadToken *load_token = nullptr;
String local_path;
String remapped_path;
diff --git a/core/math/aabb.h b/core/math/aabb.h
index cb358ca7ef..7a5581b5d4 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -85,7 +85,7 @@ struct [[nodiscard]] AABB {
bool intersects_plane(const Plane &p_plane) const;
_FORCE_INLINE_ bool has_point(const Vector3 &p_point) const;
- _FORCE_INLINE_ Vector3 get_support(const Vector3 &p_normal) const;
+ _FORCE_INLINE_ Vector3 get_support(const Vector3 &p_direction) const;
Vector3 get_longest_axis() const;
int get_longest_axis_index() const;
@@ -212,15 +212,18 @@ inline bool AABB::encloses(const AABB &p_aabb) const {
(src_max.z >= dst_max.z));
}
-Vector3 AABB::get_support(const Vector3 &p_normal) const {
- Vector3 half_extents = size * 0.5f;
- Vector3 ofs = position + half_extents;
-
- return Vector3(
- (p_normal.x > 0) ? half_extents.x : -half_extents.x,
- (p_normal.y > 0) ? half_extents.y : -half_extents.y,
- (p_normal.z > 0) ? half_extents.z : -half_extents.z) +
- ofs;
+Vector3 AABB::get_support(const Vector3 &p_direction) const {
+ Vector3 support = position;
+ if (p_direction.x > 0.0f) {
+ support.x += size.x;
+ }
+ if (p_direction.y > 0.0f) {
+ support.y += size.y;
+ }
+ if (p_direction.z > 0.0f) {
+ support.z += size.z;
+ }
+ return support;
}
Vector3 AABB::get_endpoint(int p_point) const {
diff --git a/core/math/rect2.h b/core/math/rect2.h
index 9cb341b689..817923c134 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -285,13 +285,15 @@ struct [[nodiscard]] Rect2 {
return Rect2(position.round(), size.round());
}
- Vector2 get_support(const Vector2 &p_normal) const {
- Vector2 half_extents = size * 0.5f;
- Vector2 ofs = position + half_extents;
- return Vector2(
- (p_normal.x > 0) ? -half_extents.x : half_extents.x,
- (p_normal.y > 0) ? -half_extents.y : half_extents.y) +
- ofs;
+ Vector2 get_support(const Vector2 &p_direction) const {
+ Vector2 support = position;
+ if (p_direction.x > 0.0f) {
+ support.x += size.x;
+ }
+ if (p_direction.y > 0.0f) {
+ support.y += size.y;
+ }
+ return support;
}
_FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const {
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 94285add96..5c793a676f 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -303,6 +303,29 @@ StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) {
return ti->inherits;
}
+bool ClassDB::get_inheritance_chain_nocheck(const StringName &p_class, Vector<StringName> &r_result) {
+ OBJTYPE_RLOCK;
+
+ ClassInfo *start = classes.getptr(p_class);
+ if (!start) {
+ return false;
+ }
+
+ int classes_to_add = 0;
+ for (ClassInfo *ti = start; ti; ti = ti->inherits_ptr) {
+ classes_to_add++;
+ }
+
+ int64_t old_size = r_result.size();
+ r_result.resize(old_size + classes_to_add);
+ StringName *w = r_result.ptrw() + old_size;
+ for (ClassInfo *ti = start; ti; ti = ti->inherits_ptr) {
+ *w++ = ti->name;
+ }
+
+ return true;
+}
+
StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) {
if (classes.has(p_class)) {
return p_class;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 68f3f4550b..d6a95b58e2 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -290,6 +290,7 @@ public:
static void get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
static void get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
static StringName get_parent_class_nocheck(const StringName &p_class);
+ static bool get_inheritance_chain_nocheck(const StringName &p_class, Vector<StringName> &r_result);
static StringName get_parent_class(const StringName &p_class);
static StringName get_compatibility_remapped_class(const StringName &p_class);
static bool class_exists(const StringName &p_class);
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index 32c316e58e..dae0a31fe0 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
void *operator new(size_t p_size, const char *p_description) {
return Memory::alloc_static(p_size, false);
@@ -65,6 +66,38 @@ SafeNumeric<uint64_t> Memory::max_usage;
SafeNumeric<uint64_t> Memory::alloc_count;
+inline bool is_power_of_2(size_t x) { return x && ((x & (x - 1U)) == 0U); }
+
+void *Memory::alloc_aligned_static(size_t p_bytes, size_t p_alignment) {
+ DEV_ASSERT(is_power_of_2(p_alignment));
+
+ void *p1, *p2;
+ if ((p1 = (void *)malloc(p_bytes + p_alignment - 1 + sizeof(uint32_t))) == nullptr) {
+ return nullptr;
+ }
+
+ p2 = (void *)(((uintptr_t)p1 + sizeof(uint32_t) + p_alignment - 1) & ~((p_alignment)-1));
+ *((uint32_t *)p2 - 1) = (uint32_t)((uintptr_t)p2 - (uintptr_t)p1);
+ return p2;
+}
+
+void *Memory::realloc_aligned_static(void *p_memory, size_t p_bytes, size_t p_prev_bytes, size_t p_alignment) {
+ if (p_memory == nullptr) {
+ return alloc_aligned_static(p_bytes, p_alignment);
+ }
+
+ void *ret = alloc_aligned_static(p_bytes, p_alignment);
+ memcpy(ret, p_memory, p_prev_bytes);
+ free_aligned_static(p_memory);
+ return ret;
+}
+
+void Memory::free_aligned_static(void *p_memory) {
+ uint32_t offset = *((uint32_t *)p_memory - 1);
+ void *p = (void *)((uint8_t *)p_memory - offset);
+ free(p);
+}
+
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
#ifdef DEBUG_ENABLED
bool prepad = true;
diff --git a/core/os/memory.h b/core/os/memory.h
index d03e08d785..033e417cb5 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -62,6 +62,30 @@ public:
static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false);
static void free_static(void *p_ptr, bool p_pad_align = false);
+ // ↓ return value of alloc_aligned_static
+ // ┌─────────────────┬─────────┬─────────┬──────────────────┐
+ // │ padding (up to │ uint32_t│ void* │ padding (up to │
+ // │ p_alignment - 1)│ offset │ p_bytes │ p_alignment - 1) │
+ // └─────────────────┴─────────┴─────────┴──────────────────┘
+ //
+ // alloc_aligned_static will allocate p_bytes + p_alignment - 1 + sizeof(uint32_t) and
+ // then offset the pointer until alignment is satisfied.
+ //
+ // This offset is stored before the start of the returned ptr so we can retrieve the original/real
+ // start of the ptr in order to free it.
+ //
+ // The rest is wasted as padding in the beginning and end of the ptr. The sum of padding at
+ // both start and end of the block must add exactly to p_alignment - 1.
+ //
+ // p_alignment MUST be a power of 2.
+ static void *alloc_aligned_static(size_t p_bytes, size_t p_alignment);
+ static void *realloc_aligned_static(void *p_memory, size_t p_bytes, size_t p_prev_bytes, size_t p_alignment);
+ // Pass the ptr returned by alloc_aligned_static to free it.
+ // e.g.
+ // void *data = realloc_aligned_static( bytes, 16 );
+ // free_aligned_static( data );
+ static void free_aligned_static(void *p_memory);
+
static uint64_t get_mem_available();
static uint64_t get_mem_usage();
static uint64_t get_mem_max_usage();
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 5e402937cf..695ad23bf5 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1849,6 +1849,7 @@ static void _register_variant_builtin_methods_math() {
bind_method(Rect2, intersection, sarray("b"), varray());
bind_method(Rect2, merge, sarray("b"), varray());
bind_method(Rect2, expand, sarray("to"), varray());
+ bind_method(Rect2, get_support, sarray("direction"), varray());
bind_method(Rect2, grow, sarray("amount"), varray());
bind_methodv(Rect2, grow_side, &Rect2::grow_side_bind, sarray("side", "amount"), varray());
bind_method(Rect2, grow_individual, sarray("left", "top", "right", "bottom"), varray());
@@ -2185,7 +2186,7 @@ static void _register_variant_builtin_methods_misc() {
bind_method(AABB, merge, sarray("with"), varray());
bind_method(AABB, expand, sarray("to_point"), varray());
bind_method(AABB, grow, sarray("by"), varray());
- bind_method(AABB, get_support, sarray("dir"), varray());
+ bind_method(AABB, get_support, sarray("direction"), varray());
bind_method(AABB, get_longest_axis, sarray(), varray());
bind_method(AABB, get_longest_axis_index, sarray(), varray());
bind_method(AABB, get_longest_axis_size, sarray(), varray());