From e86a60e6c7475819f99bb042793a7ad568368e2f Mon Sep 17 00:00:00 2001 From: aura Date: Sun, 26 Jul 2026 02:09:41 +0200 Subject: better prop system + profiler trace --- CMakeLists.txt | 6 +++++- src/game/object.h | 33 ++++++++++++++++++++++++++------- src/game/player.h | 2 ++ src/game/world/world.h | 1 + src/util/mem.h | 6 ++++++ src/util/profiler.h | 18 ++++++++++++++++-- 6 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 src/util/mem.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 215cb40..f93450e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,10 +2,14 @@ cmake_minimum_required(VERSION 3.10) project(videogame) set(CMAKE_CXX_COMPILER "clang++") -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) file(GLOB_RECURSE SRC_FILES ./src/*.cpp ./src/game/*.cpp ./src/util/config/*.cpp) +if(CMAKE_VERSION VERSION_GREATER "3.10") + set(OpenGL_GL_PREFERENCE GLVND) +endif() + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if(UNIX) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build) diff --git a/src/game/object.h b/src/game/object.h index 80ade03..3f0592c 100644 --- a/src/game/object.h +++ b/src/game/object.h @@ -5,6 +5,7 @@ typedef void ( *OBJECT_DEINIT_FN )( struct OBJECT* obj ); inline const char* obj_classid_to_name( U32 classid ); +inline LIST* obj_proplist( U32 classid ); enum ObjectClass_t { OBJCLASS_NONE = 0, @@ -12,6 +13,7 @@ enum ObjectClass_t { OBJCLASS_TRIGGER, OBJCLASS_PLAYER, OBJCLASS_BASENPC, + OBJCLASS_LAST }; static const char* OBJCLASS_NAMES[] = { @@ -22,14 +24,16 @@ static const char* OBJCLASS_NAMES[] = { "base_npc", }; + // todo: come up with a good way to make these static struct OBJECT_PROP { - OBJECT_PROP( const char* name, void* value, U32 size, LIST* list, void* parent ) { + OBJECT_PROP( const char* name, U32 size, U32 classid, U32 offset ) { this->name = name; this->size = size; this->hash = fnv1a( name ); - this->offset = (U32)( (U8*)value - (U8*)parent ); - list->push( this ); + this->offset = offset; + LIST* l = obj_proplist( classid ); + l->push( this ); } const char* name; @@ -38,20 +42,36 @@ struct OBJECT_PROP { U32 size; }; + +inline LIST* obj_proplist( U32 classid ) { + static struct LIST prop_lists[OBJCLASS_LAST]; + + if( classid >= OBJCLASS_LAST ) { + dlog( "obj_classid_to_name() : invalid classid passed (%d)", classid ); + return 0; + } + + return &prop_lists[classid]; +} + #define OBJVAR( type, name ) \ type name; \ - OBJECT_PROP __##name##_props{ #name, (void*)&name, sizeof(type), &this->props, this } + constexpr static U32 __##name##_offset() { OBJ_SELF_TYPE t; return (U32)( (U64)&t.name - (U64)&t ); } \ + static inline OBJECT_PROP __##name##_props{ #name, sizeof(type), OBJ_SELF_TYPE::CLASSID, (U32)( __##name##_offset() ) } #define OBJVARV( type, name, val ) \ type name{ type( val ) }; \ - OBJECT_PROP __##name##_props{ #name, (void*)&name, sizeof(type), &this->props, this } + constexpr static U32 __##name##_offset() { OBJ_SELF_TYPE t; return (U32)( (U64)&t.name - (U64)&t ); } \ + static inline OBJECT_PROP __##name##_props{ #name, sizeof(type), OBJ_SELF_TYPE::CLASSID, (U32)( __##name##_offset() ) } #define OBJVAR_STR( name, len ) \ char name##[len]; \ - OBJECT_PROP __##name##_props{ #name, (void*)name, len, &this->props, this } + constexpr static U32 __##name##_offset() { OBJ_SELF_TYPE t; return (U32)( (U64)&t.name - (U64)&t ); } \ + static inline OBJECT_PROP __##name##_props{ #name, sizeof(type), OBJ_SELF_TYPE::CLASSID, (U32)( __##name##_offset() ) } struct OBJECT { static const U32 CLASSID = OBJCLASS_NONE; + using OBJ_SELF_TYPE = OBJECT; U32 classid; U8 keeponlevel{}; @@ -59,7 +79,6 @@ struct OBJECT { OBJECT* parent; LIST children{}; - LIST props{}; OBJECT_DEINIT_FN deinit_fn{}; OBJVAR( VEC3, pos ); diff --git a/src/game/player.h b/src/game/player.h index 27b423d..a2967bd 100644 --- a/src/game/player.h +++ b/src/game/player.h @@ -31,6 +31,8 @@ struct PLAYER_INPUT { struct PLAYER : OBJECT { static const U32 CLASSID = OBJCLASS_PLAYER; + using OBJ_SELF_TYPE = PLAYER; + OBJVAR( U32, health ); OBJVARV( F32, fov, 72.f ); OBJVARV( F32, eyeoffset, 40.f ); diff --git a/src/game/world/world.h b/src/game/world/world.h index 229f235..11af15e 100644 --- a/src/game/world/world.h +++ b/src/game/world/world.h @@ -3,6 +3,7 @@ struct WORLD : OBJECT { static const U32 CLASSID = OBJCLASS_WORLD; + using OBJ_SELF_TYPE = WORLD; struct WORLD_MAP* map; }; diff --git a/src/util/mem.h b/src/util/mem.h new file mode 100644 index 0000000..852e844 --- /dev/null +++ b/src/util/mem.h @@ -0,0 +1,6 @@ +#include "typedef.h" + +[[maybe_unused, clang::noinline]] +static void* __cur_retaddr() { + return __builtin_extract_return_addr( __builtin_return_address(0) ); +} diff --git a/src/util/profiler.h b/src/util/profiler.h index 7caac96..334ad62 100644 --- a/src/util/profiler.h +++ b/src/util/profiler.h @@ -4,6 +4,7 @@ #include "allocator.h" #include "time.h" #include "thread.h" +#include "mem.h" #include "fnv.h" static THREAD_MUTEX __profiler_intern_mutex; @@ -13,7 +14,7 @@ static THREAD_MUTEX __profiler_intern_mutex; #endif #define PROFILE( x ) \ - PROFILER_LIST_ENTRY* __profiler_intern_id = __profiler_intern_start( x ); \ + PROFILER_LIST_ENTRY* __profiler_intern_id = __profiler_intern_start( x, (U64)__cur_retaddr() ); \ defer( { __profiler_intern_end( __profiler_intern_id ); } ) #define _profiled PROFILE( __func__ ); @@ -24,6 +25,7 @@ struct PROFILER_LIST_ENTRY { const char* name; U64 duration; U64 start; + U64 ptr; FNV1A hash; PROFILER_LIST_ENTRY* parent; @@ -76,7 +78,7 @@ inline void __profiler_intern_new_frame( PROFILER_LIST_ENTRY* entry ) { } } -inline PROFILER_LIST_ENTRY* __profiler_intern_start( const char* name ) { +inline PROFILER_LIST_ENTRY* __profiler_intern_start( const char* name, U64 ptr ) { PROFILER_LIST_ENTRY e; FNV1A fnv = fnv1a( name ); U64 tick = u_tick(); @@ -100,6 +102,7 @@ inline PROFILER_LIST_ENTRY* __profiler_intern_start( const char* name ) { e.children = {}; e.parent = gprof.current; e.hash = fnv; + e.ptr = ptr; if( gprof.current ) ep = gprof.current->children.push( e ); @@ -124,14 +127,25 @@ inline void __profiler_intern_init() { thread_mutex_init( &__profiler_intern_mutex ); } +inline void __profiler_intern_trace() { + thread_mutex_lock( &__profiler_intern_mutex ); + PROFILER_LIST_ENTRY* entry = gprof.current; + dlog( "======== [ profiler trace ] ==========\n" ); + while( entry ) { + dlog( "%s [0x%llx]\n", entry->name, entry->ptr ); + } +} + extern void __profiler_intern_draw_overlay( struct GL_FONT* font ); #define profiler_init() __profiler_intern_init() #define profiler_draw_tree( font ) __profiler_intern_draw_overlay( font ) +#define profiler_trace() __profiler_intern_trace() #else #define PROFILE( x ) #define _profiled +#define profiler_trace() #define profiler_init() #define profiler_draw_tree( x ) #endif -- cgit v1.2.3