diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/config/engine.cpp | 4 | ||||
-rw-r--r-- | core/config/engine.h | 2 | ||||
-rw-r--r-- | core/core_bind.cpp | 1 | ||||
-rw-r--r-- | core/core_bind.h | 1 | ||||
-rw-r--r-- | core/io/image.cpp | 23 | ||||
-rw-r--r-- | core/io/image.h | 2 | ||||
-rw-r--r-- | core/io/resource_loader.cpp | 20 | ||||
-rw-r--r-- | core/io/resource_loader.h | 2 | ||||
-rw-r--r-- | core/math/aabb.h | 23 | ||||
-rw-r--r-- | core/math/rect2.h | 16 | ||||
-rw-r--r-- | core/object/class_db.cpp | 23 | ||||
-rw-r--r-- | core/object/class_db.h | 1 | ||||
-rw-r--r-- | core/os/memory.cpp | 33 | ||||
-rw-r--r-- | core/os/memory.h | 24 | ||||
-rw-r--r-- | core/variant/variant_call.cpp | 3 |
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()); |