diff --git a/.natvis b/.natvis index 3fd140af..4eb7585c 100644 --- a/.natvis +++ b/.natvis @@ -42,8 +42,8 @@ - - 0x{*((u64 *)this + 1), xb}{*(u64 *)this, xb} + + 0x{hi, xb}{lo, xb} diff --git a/src/app.h b/src/app.h index 14ab5dbe..e85439f6 100644 --- a/src/app.h +++ b/src/app.h @@ -9,6 +9,7 @@ struct app_statistics { struct atomic_u64 sock_bytes_received; struct atomic_u64 memory_committed; struct atomic_u64 memory_reserved; + struct atomic_u64 num_arenas; }; INLINE struct app_statistics *app_statistics(void) diff --git a/src/arena.c b/src/arena.c index d0bc2e9c..0919c432 100644 --- a/src/arena.c +++ b/src/arena.c @@ -43,6 +43,8 @@ struct arena arena_alloc(u64 reserve) /* Arena should be 64k aligned */ ASSERT(((u64)arena.base & 0xFFFF) == 0); + atomic_u64_inc_eval(&app_statistics()->num_arenas); + return arena; } @@ -53,6 +55,7 @@ void arena_release(struct arena *arena) __proffree(arena->base); atomic_u64_eval_add_i64(&app_statistics()->memory_committed, -((i64)arena->committed)); atomic_u64_eval_add_i64(&app_statistics()->memory_reserved, -((i64)arena->reserved)); + atomic_u64_dec_eval(&app_statistics()->num_arenas); sys_memory_release(arena->base); } diff --git a/src/bitbuff.c b/src/bitbuff.c index 5693a1c5..97cd5399 100644 --- a/src/bitbuff.c +++ b/src/bitbuff.c @@ -20,7 +20,7 @@ enum dbg_magic { DBG_MAGIC_IV = 0x981f, DBG_MAGIC_F32 = 0x56F9, DBG_MAGIC_F64 = 0x7053, - DBG_MAGIC_U128 = 0xA24E, + DBG_MAGIC_UID = 0xA24E, DBG_MAGIC_STRING = 0x7866, }; @@ -330,11 +330,11 @@ void bw_write_f64(struct bitbuff_writer *bw, f64 value) bw_write_ubits(bw, *(u64 *)&value, 64); } -void bw_write_u128(struct bitbuff_writer *bw, u128 value) +void bw_write_uid(struct bitbuff_writer *bw, struct uid value) { - _dbg_write_magic(bw, DBG_MAGIC_U128, 128); - bw_write_ubits(bw, U128_HI(value), 64); - bw_write_ubits(bw, U128_LO(value), 64); + _dbg_write_magic(bw, DBG_MAGIC_UID, 128); + bw_write_ubits(bw, value.hi, 64); + bw_write_ubits(bw, value.lo, 64); } void bw_write_string(struct bitbuff_writer *bw, struct string s) @@ -577,12 +577,12 @@ f64 br_read_f64(struct bitbuff_reader *br) return *(f64 *)&ubits; } -u128 br_read_u128(struct bitbuff_reader *br) +struct uid br_read_uid(struct bitbuff_reader *br) { - _dbg_read_magic(br, DBG_MAGIC_U128, 128); + _dbg_read_magic(br, DBG_MAGIC_UID, 128); u64 hi = br_read_ubits(br, 64); u64 lo = br_read_ubits(br, 64); - return U128(hi, lo); + return UID(hi, lo); } struct string br_read_string(struct arena *arena, struct bitbuff_reader *br) diff --git a/src/bitbuff.h b/src/bitbuff.h index ea76e0a2..85bff67a 100644 --- a/src/bitbuff.h +++ b/src/bitbuff.h @@ -57,7 +57,7 @@ void bw_write_iv(struct bitbuff_writer *bw, i64 value); void bw_write_f32(struct bitbuff_writer *bw, f32 value); void bw_write_f64(struct bitbuff_writer *bw, f64 value); -void bw_write_u128(struct bitbuff_writer *bw, u128 value); +void bw_write_uid(struct bitbuff_writer *bw, struct uid value); void bw_write_string(struct bitbuff_writer *bw, struct string s); @@ -99,7 +99,7 @@ i64 br_read_iv(struct bitbuff_reader *br); f32 br_read_f32(struct bitbuff_reader *br); f64 br_read_f64(struct bitbuff_reader *br); -u128 br_read_u128(struct bitbuff_reader *br); +struct uid br_read_uid(struct bitbuff_reader *br); struct string br_read_string(struct arena *arena, struct bitbuff_reader *br); diff --git a/src/common.h b/src/common.h index b66eb0a8..8d6952f6 100644 --- a/src/common.h +++ b/src/common.h @@ -391,14 +391,14 @@ INLINE u128 u128_mul(u128 a, u128 b) { return a * b; } #elif COMPILER_MSVC #if LANGUAGE_CPP -# define U128(hi64, lo64) { (hi64), (lo64) } +# define U128(hi64, lo64) { .hi = (hi64), .lo = (lo64) } #else # define U128(hi64, lo64) ((u128) { .hi = (hi64), .lo = (lo64) }) #endif #define U128_HI(a) ((a).hi) #define U128_LO(a) ((a).lo) -typedef struct { u64 hi; u64 lo; } u128; +typedef struct { u64 lo; u64 hi; } u128; INLINE b32 u128_eq(u128 a, u128 b) { return a.hi == b.hi && a.lo == b.lo; } INLINE b32 u128_lt(u128 a, u128 b) { return ((((a.hi > b.hi) - (a.hi < b.hi)) << 1) + ((a.lo > b.lo) - (a.lo < b.lo))) < 0; } @@ -407,6 +407,8 @@ INLINE u128 u128_xor_u8(u128 a, u8 b) { return U128(a.hi, a.lo ^ b); } /* https://www.codeproject.com/Tips/784635/UInt-Bit-Operations */ +/* TODO: Use msvc intrinsics & ensure results are identical to clang */ + INLINE u128 u128_mul(u128 a, u128 b) { u64 a1 = (a.lo & 0xffffffff); @@ -485,6 +487,19 @@ struct string32 { u32 *text; }; +#define UID(hi, lo) (struct uid) { .v = U128((hi), (lo)) } +#define UID0 (struct uid) { 0 } +struct uid { + union { + u128 v; + struct { + u64 lo; + u64 hi; + }; + }; +}; +INLINE b32 uid_eq(struct uid a, struct uid b) { return u128_eq(a.v, b.v); } + struct image_rgba { u32 width; u32 height; @@ -501,10 +516,6 @@ struct sim_ent_handle { u64 gen; }; -struct sim_netid { - u128 v; -}; - struct sim_client_handle { u32 idx; u32 gen; diff --git a/src/rng.c b/src/rng.c index 0fcce607..e9f52ed5 100644 --- a/src/rng.c +++ b/src/rng.c @@ -78,6 +78,13 @@ u128 rng_rand_u128(void) return v; } +struct uid rng_rand_uid(void) +{ + u128 v = 0; + sys_rand(STRING_FROM_STRUCT(&v)); + return (struct uid) { .v = v }; +} + f32 rng_rand_f32(f32 range_start, f32 range_end) { return ((f32)rng_rand_u32() / (f32)U32_MAX) * (range_end - range_start) + range_start; diff --git a/src/rng.h b/src/rng.h index 6bfc84f0..20d2922b 100644 --- a/src/rng.h +++ b/src/rng.h @@ -11,6 +11,7 @@ struct rng_startup_receipt rng_startup(struct resource_startup_receipt *resource u32 rng_rand_u32(void); u64 rng_rand_u64(void); u128 rng_rand_u128(void); +struct uid rng_rand_uid(void); f32 rng_rand_f32(f32 range_start, f32 range_end); f64 rng_rand_f64(f64 range_start, f64 range_end); diff --git a/src/sim.c b/src/sim.c index 74ba8b58..80c37769 100644 --- a/src/sim.c +++ b/src/sim.c @@ -25,7 +25,7 @@ #define CLIENT_LOOKUP_BUCKETS 127 #define TICK_LOOKUP_BUCKETS 127 -#define NETID_LOOKUP_BUCKETS 1024 +#define UID_LOOKUP_BUCKETS 4096 /* ========================== * * Startup @@ -305,18 +305,18 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn ss->sim_dt_ns = src->sim_dt_ns; ss->sim_time_ns = src->sim_time_ns; ss->continuity_gen = src->continuity_gen; - ss->local_client_netid = src->local_client_netid; + ss->local_client_ent_uid = src->local_client_ent_uid; ss->phys_iteration = src->phys_iteration; - /* Copy netid lookup buckets */ - ss->num_netid_buckets = src->num_netid_buckets > 0 ? src->num_netid_buckets : NETID_LOOKUP_BUCKETS; - ss->netid_buckets = arena_push_array(&ss->arena, struct sim_ent_bucket, ss->num_netid_buckets); - if (src->num_netid_buckets > 0) { - for (u64 i = 0; i < src->num_netid_buckets; ++i) { - ss->netid_buckets[i] = src->netid_buckets[i]; + /* Copy uid lookup buckets */ + ss->num_uid_buckets = src->num_uid_buckets > 0 ? src->num_uid_buckets : UID_LOOKUP_BUCKETS; + ss->uid_buckets = arena_push_array(&ss->arena, struct sim_ent_bucket, ss->num_uid_buckets); + if (src->num_uid_buckets > 0) { + for (u64 i = 0; i < src->num_uid_buckets; ++i) { + ss->uid_buckets[i] = src->uid_buckets[i]; } } else { - MEMZERO(ss->netid_buckets, sizeof(*ss->netid_buckets) * ss->num_netid_buckets); + MEMZERO(ss->uid_buckets, sizeof(*ss->uid_buckets) * ss->num_uid_buckets); } /* Copy entities */ @@ -586,7 +586,7 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, bw_write_uv(bw, ss1->continuity_gen); bw_write_uv(bw, ss1->phys_iteration); - bw_write_u128(bw, receiver->client_ent_netid.v); + bw_write_uid(bw, receiver->ent_uid); /* Ents */ if (ss1->num_ents_allocated == ss0->num_ents_allocated) { @@ -625,7 +625,7 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss) ss->continuity_gen = br_read_uv(br); ss->phys_iteration = br_read_uv(br); - ss->local_client_netid.v = br_read_u128(br); + ss->local_client_ent_uid = br_read_uid(br); /* Ents */ if (br_read_bit(br)) { diff --git a/src/sim.h b/src/sim.h index 6b4796ab..858cb1f7 100644 --- a/src/sim.h +++ b/src/sim.h @@ -79,8 +79,8 @@ struct sim_client { struct sim_client_handle next_in_bucket; struct sim_client_handle prev_in_bucket; - /* The client entity's net id in the master sim (if relevant) */ - struct sim_netid client_ent_netid; + /* The client entity's uid in the master sim (if relevant) */ + struct uid ent_uid; /* This is the highest confirmed tick of ours that we know this client has received */ u64 ack; @@ -171,11 +171,11 @@ struct sim_snapshot { /* The last physics iteration (used for tracking contact lifetime) */ u64 phys_iteration; - struct sim_netid local_client_netid; /* The netid of the receiver's client ent */ + struct uid local_client_ent_uid; /* The uid of the receiver's client ent */ - /* Net id lookup */ - struct sim_ent_bucket *netid_buckets; - u64 num_netid_buckets; + /* Uid lookup */ + struct sim_ent_bucket *uid_buckets; + u64 num_uid_buckets; /* Entities */ struct arena ents_arena; @@ -211,15 +211,11 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1); void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss); -/* ========================== * - * Net id - * ========================== */ -#define SIM_NETID_NIL (struct sim_netid) { U128(0, 0) } -INLINE b32 sim_netid_eq(struct sim_netid a, struct sim_netid b) -{ - return u128_eq(a.v, b.v); -} + + + + #endif diff --git a/src/sim_ent.c b/src/sim_ent.c index b32d5900..1038dcd6 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -39,35 +39,38 @@ struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent) struct sim_snapshot *ss = parent->ss; struct sim_ent *e = sim_ent_alloc_raw(ss); sim_ent_link_parent(e, parent); + + sim_ent_set_uid(e, rng_rand_uid()); + return e; } -/* Allocates a new entity with a random netid to be synced to clients */ +/* Allocates a new entity with a random uid to be synced to clients */ struct sim_ent *sim_ent_alloc_net_src(struct sim_ent *parent) { struct sim_snapshot *ss = parent->ss; struct sim_ent *e = sim_ent_alloc_raw(ss); sim_ent_link_parent(e, parent); + sim_ent_set_uid(e, rng_rand_uid()); + sim_ent_enable_prop(e, SIM_ENT_PROP_NET_SRC); - struct sim_netid netid = ZI; - netid.v = rng_rand_u128(); e->net_src_client = ss->client->handle; - sim_ent_set_netid(e, netid); return e; } -/* Allocates a new entity that will sync with incoming net src ents containing netid, and coming from the specified client */ -struct sim_ent *sim_ent_alloc_net_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct sim_netid netid) +/* Allocates a new entity that will sync with incoming net src ents containing uid, and coming from the specified client */ +struct sim_ent *sim_ent_alloc_net_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct uid uid) { struct sim_snapshot *ss = parent->ss; struct sim_ent *e = sim_ent_alloc_raw(ss); sim_ent_link_parent(e, parent); + sim_ent_set_uid(e, uid); + sim_ent_enable_prop(e, SIM_ENT_PROP_NET_DST); e->net_src_client = client_handle; - sim_ent_set_netid(e, netid); return e; } @@ -83,8 +86,8 @@ void sim_ent_release_raw(struct sim_ent *ent) } } - /* Release netid */ - sim_ent_set_netid(ent, SIM_NETID_NIL); + /* Release uid */ + sim_ent_set_uid(ent, UID0); /* Release */ ++ent->handle.gen; @@ -103,38 +106,38 @@ void sim_ent_release(struct sim_ent *ent) } /* ========================== * - * Net id + * Uid * ========================== */ -INLINE u64 hash_from_netid(struct sim_netid netid) +INLINE u64 hash_from_uid(struct uid uid) { - /* Just use lower 64 bits of netid since it's already randomnized */ - return U128_LO(netid.v); + /* Just use lower 64 bits of uid since it's already randomnized */ + return uid.lo; } -struct sim_netid sim_ent_get_netid(struct sim_ent *ent) +struct uid sim_ent_get_uid(struct sim_ent *ent) { - return ent->_netid; + return ent->_uid; } -void sim_ent_set_netid(struct sim_ent *ent, struct sim_netid netid) +void sim_ent_set_uid(struct sim_ent *ent, struct uid uid) { struct sim_snapshot *ss = ent->ss; - struct sim_ent_bucket *buckets = ss->netid_buckets; - u64 num_netid_buckets = ss->num_netid_buckets; + struct sim_ent_bucket *buckets = ss->uid_buckets; + u64 num_uid_buckets = ss->num_uid_buckets; - struct sim_netid old_netid = ent->_netid; + struct uid old_uid = ent->_uid; /* Release old from lookup */ - if (!sim_netid_eq(old_netid, SIM_NETID_NIL)) { - u64 hash = hash_from_netid(old_netid); - struct sim_ent_bucket *bucket = &buckets[hash % num_netid_buckets]; + if (!uid_eq(old_uid, UID0)) { + u64 hash = hash_from_uid(old_uid); + struct sim_ent_bucket *bucket = &buckets[hash % num_uid_buckets]; struct sim_ent *prev = sim_ent_nil(); struct sim_ent *next = sim_ent_nil(); struct sim_ent *e = sim_ent_from_handle(ss, bucket->first); while (e->valid) { - next = sim_ent_from_handle(ss, e->next_in_netid_bucket); - if (sim_netid_eq(e->_netid, old_netid)) { + next = sim_ent_from_handle(ss, e->next_in_uid_bucket); + if (uid_eq(e->_uid, old_uid)) { break; } prev = e; @@ -142,44 +145,44 @@ void sim_ent_set_netid(struct sim_ent *ent, struct sim_netid netid) } if (e->valid) { if (prev->valid) { - prev->next_in_netid_bucket = next->handle; + prev->next_in_uid_bucket = next->handle; } else { bucket->first = next->handle; } if (next->valid) { - next->prev_in_netid_bucket = prev->handle; + next->prev_in_uid_bucket = prev->handle; } else { bucket->last = prev->handle; } } } - /* Insert new netid into lookup */ - if (!sim_netid_eq(netid, SIM_NETID_NIL)) { - u64 hash = hash_from_netid(netid); - struct sim_ent_bucket *bucket = &buckets[hash % num_netid_buckets]; + /* Insert new uid into lookup */ + if (!uid_eq(uid, UID0)) { + u64 hash = hash_from_uid(uid); + struct sim_ent_bucket *bucket = &buckets[hash % num_uid_buckets]; struct sim_ent *last = sim_ent_from_handle(ss, bucket->last); if (last->valid) { - last->next_in_netid_bucket = ent->handle; + last->next_in_uid_bucket = ent->handle; } else { bucket->first = ent->handle; } - ent->prev_in_netid_bucket = last->handle; + ent->prev_in_uid_bucket = last->handle; bucket->last = ent->handle; } - ent->_netid = netid; + ent->_uid = uid; } -struct sim_ent *sim_ent_from_netid(struct sim_snapshot *ss, struct sim_netid netid) +struct sim_ent *sim_ent_from_uid(struct sim_snapshot *ss, struct uid uid) { struct sim_ent *res = sim_ent_nil(); - u64 num_buckets = ss->num_netid_buckets; - if (num_buckets > 0 && !sim_netid_eq(netid, SIM_NETID_NIL)) { - u64 hash = hash_from_netid(netid); - struct sim_ent_bucket *bucket = &ss->netid_buckets[hash % num_buckets]; - for (struct sim_ent *e = sim_ent_from_handle(ss, bucket->first); e->valid; e = sim_ent_from_handle(ss, e->next_in_netid_bucket)) { - if (sim_netid_eq(e->_netid, netid)) { + u64 num_buckets = ss->num_uid_buckets; + if (num_buckets > 0 && !uid_eq(uid, UID0)) { + u64 hash = hash_from_uid(uid); + struct sim_ent_bucket *bucket = &ss->uid_buckets[hash % num_buckets]; + for (struct sim_ent *e = sim_ent_from_handle(ss, bucket->first); e->valid; e = sim_ent_from_handle(ss, e->next_in_uid_bucket)) { + if (uid_eq(e->_uid, uid)) { res = e; break; } @@ -496,7 +499,7 @@ void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_en /* FIXME: Things like xforms need to be retreived manually rather than memcopied. - * This will also be true for things like ent handles once netids are implemented. */ + * This will also be true for things like ent handles once uids are implemented. */ /* TODO: Granular delta encoding */ @@ -527,7 +530,7 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e) { struct sim_snapshot *ss = e->ss; - struct sim_netid old_netid = sim_ent_get_netid(e); + struct uid old_uid = sim_ent_get_uid(e); u64 pos = 0; while (pos < sizeof(*e)) { @@ -540,10 +543,10 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e) pos += 8; } - struct sim_netid new_netid = sim_ent_get_netid(e); - e->_netid = old_netid; - if (!sim_netid_eq(old_netid, new_netid)) { - sim_ent_set_netid(e, new_netid); + struct uid new_uid = sim_ent_get_uid(e); + e->_uid = old_uid; + if (!uid_eq(old_uid, new_uid)) { + sim_ent_set_uid(e, new_uid); } e->ss = ss; diff --git a/src/sim_ent.h b/src/sim_ent.h index 57ab85cc..11c15bb3 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -62,10 +62,17 @@ struct sim_ent { /* ====================================================================== */ /* Metadata */ - b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */ - struct sim_ent_handle handle; struct sim_snapshot *ss; + b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */ + + struct sim_ent_handle handle; + + /* The unique ID of the entity determined at allocation time. + * Mainly used for networking. + * Use uid getter to access. */ + struct uid _uid; + u64 props[(SIM_ENT_PROP_COUNT + 63) / 64]; u64 continuity_gen; @@ -85,8 +92,8 @@ struct sim_ent { struct sim_ent_handle first; struct sim_ent_handle last; - struct sim_ent_handle next_in_netid_bucket; - struct sim_ent_handle prev_in_netid_bucket; + struct sim_ent_handle next_in_uid_bucket; + struct sim_ent_handle prev_in_uid_bucket; struct sim_ent_handle next_free; @@ -99,10 +106,6 @@ struct sim_ent { /* Handle of the client that owns the src ent of this dst ent */ struct sim_client_handle net_src_client; - /* The (unique) networked ID of the entity. - * Use net getter to access. */ - struct sim_netid _netid; - /* ====================================================================== */ /* Position */ @@ -132,7 +135,7 @@ struct sim_ent { struct sim_ent_handle cmd_client; struct sim_control cmd_control; - struct sim_netid cmd_hovered_ent_netid; + struct uid cmd_hovered_ent_uid; /* ====================================================================== */ /* Client */ @@ -396,16 +399,16 @@ INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent) struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss); struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent); struct sim_ent *sim_ent_alloc_net_src(struct sim_ent *parent); -struct sim_ent *sim_ent_alloc_net_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct sim_netid netid); +struct sim_ent *sim_ent_alloc_net_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct uid uid); void sim_ent_release_raw(struct sim_ent *ent); void sim_ent_release(struct sim_ent *ent); -/* Net id */ +/* Uid */ -struct sim_netid sim_ent_get_netid(struct sim_ent *ent); -void sim_ent_set_netid(struct sim_ent *ent, struct sim_netid netid); -struct sim_ent *sim_ent_from_netid(struct sim_snapshot *ss, struct sim_netid netid); +struct uid sim_ent_get_uid(struct sim_ent *ent); +void sim_ent_set_uid(struct sim_ent *ent, struct uid uid); +struct sim_ent *sim_ent_from_uid(struct sim_snapshot *ss, struct uid uid); /* Query */ struct sim_ent *sim_ent_from_handle(struct sim_snapshot *ss, struct sim_ent_handle handle); diff --git a/src/sim_step.c b/src/sim_step.c index 71a1b915..2657e1a4 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -168,8 +168,9 @@ void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel) /* Reset ent space handles */ for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(ent)) continue; - MEMZERO_STRUCT(&ent->space_handle); + if (ent->valid) { + MEMZERO_STRUCT(&ent->space_handle); + } } /* NOTE: Not rebuilding space since it'll happen during phys step */ @@ -177,10 +178,11 @@ void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel) /* Rebuild lookup tables */ for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *ent = &ss->ents[sim_ent_index]; - if (!sim_ent_is_valid_and_active(ent)) continue; - if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) { - struct sim_lookup_key contact_lookup_key = sim_lookup_key_from_two_handles(ent->contact_constraint_data.e0, ent->contact_constraint_data.e1); - sim_lookup_set(&accel->contact_lookup, contact_lookup_key, ent->handle); + if (sim_ent_is_valid_and_active(ent)) { + if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) { + struct sim_lookup_key contact_lookup_key = sim_lookup_key_from_two_handles(ent->contact_constraint_data.e0, ent->contact_constraint_data.e1); + sim_lookup_set(&accel->contact_lookup, contact_lookup_key, ent->handle); + } } } } @@ -667,7 +669,7 @@ void sim_step(struct sim_step_ctx *ctx) } /* Dereference hovered ent */ - client_ent->client_hovered_ent = sim_ent_from_netid(world, cmd_ent->cmd_hovered_ent_netid)->handle; + client_ent->client_hovered_ent = sim_ent_from_uid(world, cmd_ent->cmd_hovered_ent_uid)->handle; u32 flags = control->flags; if (flags & SIM_CONTROL_FLAG_DRAG) { diff --git a/src/string.c b/src/string.c index 585b1880..a0ac41be 100644 --- a/src/string.c +++ b/src/string.c @@ -463,15 +463,15 @@ struct string string_formatv(struct arena *arena, struct string fmt, va_list arg } break; case FMT_TYPE_UINT: { - parsed_str = string_from_uint(arena, arg.value.uint, 10, 0); + parsed_str = string_from_uint(arena, arg.value.uint, 10, arg.zfill); } break; case FMT_TYPE_SINT: { - parsed_str = string_from_int(arena, arg.value.sint, 10, 0); + parsed_str = string_from_int(arena, arg.value.sint, 10, arg.zfill); } break; case FMT_TYPE_HEX: { - parsed_str = string_from_uint(arena, arg.value.sint, 16, 0); + parsed_str = string_from_uint(arena, arg.value.sint, 16, arg.zfill); } break; case FMT_TYPE_PTR: { @@ -479,7 +479,7 @@ struct string string_formatv(struct arena *arena, struct string fmt, va_list arg } break; case FMT_TYPE_FLOAT: { - parsed_str = string_from_float(arena, arg.value.f.val, arg.value.f.precision); + parsed_str = string_from_float(arena, arg.value.f, arg.precision); } break; case FMT_TYPE_HANDLE: { diff --git a/src/string.h b/src/string.h index b7d07646..fea5c357 100644 --- a/src/string.h +++ b/src/string.h @@ -58,16 +58,15 @@ enum fmt_type { struct fmt_arg { enum fmt_type type; + u32 precision; + u32 zfill; union { u8 c; struct string string; u64 uint; i64 sint; void *ptr; - struct { - f64 val; - u32 precision; - } f; + f64 f; struct { u64 h64[2]; } handle; @@ -79,11 +78,12 @@ struct fmt_arg { #define FMT_CHAR(v) (struct fmt_arg) {.type = FMT_TYPE_CHAR, .value.c = (v)} #define FMT_STR(v) (struct fmt_arg) {.type = FMT_TYPE_STR, .value.string = (v)} #define FMT_UINT(v) (struct fmt_arg) {.type = FMT_TYPE_UINT, .value.uint = (v)} +#define FMT_UINT_Z(v, z) (struct fmt_arg) {.type = FMT_TYPE_UINT, .value.uint = (v), .zfill = (z)} #define FMT_SINT(v) (struct fmt_arg) {.type = FMT_TYPE_SINT, .value.sint = (v)} #define FMT_HEX(v) (struct fmt_arg) {.type = FMT_TYPE_HEX, .value.uint = (v)} #define FMT_PTR(v) (struct fmt_arg) {.type = FMT_TYPE_PTR, .value.ptr = (v)} #define FMT_FLOAT(v) FMT_FLOAT_P(v, DEFAULT_FMT_PRECISION) -#define FMT_FLOAT_P(v, p) (struct fmt_arg) {.type = FMT_TYPE_FLOAT, .value.f.val = (v), .value.f.precision = p} +#define FMT_FLOAT_P(v, p) (struct fmt_arg) {.type = FMT_TYPE_FLOAT, .value.f = (v), .precision = (p)} #define FMT_HANDLE(v) (struct fmt_arg) {.type = FMT_TYPE_HANDLE, .value.handle.h64[0] = (v).idx, .value.handle.h64[1] = (v).gen} #define string_format(arena, fmt, ...) _string_format((arena), (fmt), __VA_ARGS__, FMT_END) diff --git a/src/user.c b/src/user.c index d141f9e0..c0b7a8af 100644 --- a/src/user.c +++ b/src/user.c @@ -86,7 +86,7 @@ GLOBAL struct { /* User -> local sim */ struct sys_mutex user_sim_cmd_mutex; struct sim_control user_sim_cmd_control; - struct sim_netid user_sim_cmd_hovered_ent_netid; + struct uid user_sim_cmd_hovered_ent_uid; u64 last_user_sim_cmd_gen; u64 user_sim_cmd_gen; @@ -348,16 +348,17 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e struct string res = ZI; res.text = arena_dry_push(arena, u8); + res.len += string_format(arena, LIT("<%F>"), FMT_HANDLE(ent->handle)).len; + + /* TODO: String fmt function */ + struct uid uid = sim_ent_get_uid(ent); + res.len += string_copy(arena, LIT(" [")).len; + res.len += string_from_uint(arena, (U128_HI(uid.v) >> 36) & 0xFFFFFFF, 16, 7).len; + res.len += string_copy(arena, LIT("]\n")).len; + { res.len += string_copy(arena, LIT("net: ")).len; - struct sim_netid netid = sim_ent_get_netid(ent); - if (!sim_netid_eq(netid, SIM_NETID_NIL)) { - res.len += string_copy(arena, LIT(" [")).len; - res.len += string_from_uint(arena, (U128_HI(netid.v) >> 36) & 0xFFFFFFF, 16, 7).len; - res.len += string_copy(arena, LIT("]")).len; - } - b32 transmitting = sim_ent_has_prop(ent, SIM_ENT_PROP_NET_SRC); b32 receiving = sim_ent_has_prop(ent, SIM_ENT_PROP_NET_DST); if (transmitting & receiving) { @@ -405,7 +406,7 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e res.len += string_format(arena, LIT("last child: <%F>\n"), FMT_HANDLE(ent->last)).len; } while (child->valid) { - res.len += string_format(arena, LIT("\nCHILD <%F>\n"), FMT_HANDLE(child->handle)).len; + res.len += string_copy(arena, LIT("\nCHILD\n")).len; struct string child_text = get_ent_debug_text(scratch.arena, child); res.len += string_indent(arena, child_text, 4).len; child = sim_ent_from_handle(ss, child->next); @@ -698,7 +699,7 @@ INTERNAL void user_update(void) * Find local entities * ========================== */ - struct sim_ent *local_client_ent = sim_ent_from_netid(G.ss_blended, G.ss_blended->local_client_netid); + struct sim_ent *local_client_ent = sim_ent_from_uid(G.ss_blended, G.ss_blended->local_client_ent_uid); struct sim_ent *local_player = sim_ent_from_handle(G.ss_blended, local_client_ent->client_control_ent); struct sim_ent *local_camera = sim_ent_from_handle(G.ss_blended, local_client_ent->client_camera_ent); @@ -1530,7 +1531,7 @@ INTERNAL void user_update(void) u32 old_flags = G.user_sim_cmd_control.flags; G.user_sim_cmd_control = control; G.user_sim_cmd_control.flags |= old_flags; - G.user_sim_cmd_hovered_ent_netid = sim_ent_get_netid(hovered_ent); + G.user_sim_cmd_hovered_ent_uid = sim_ent_get_uid(hovered_ent); sys_mutex_unlock(&lock); } } @@ -1575,7 +1576,6 @@ INTERNAL void user_update(void) struct string dbg_text = ZI; dbg_text.text = arena_dry_push(temp.arena, u8); - dbg_text.len += string_format(temp.arena, LIT("ENT <%F>\n"), FMT_HANDLE(ent->handle)).len; dbg_text.len += get_ent_debug_text(temp.arena, ent).len; draw_text(G.ui_cmd_buffer, font, pos, dbg_text); @@ -1640,6 +1640,9 @@ INTERNAL void user_update(void) draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Virtual memory usage: %F TiB"), FMT_FLOAT_P((f64)atomic_u64_eval(&app_statistics()->memory_reserved) / 1024 / 1024 / 1024 / 1024, 3))); pos.y += spacing; + + draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Arenas allocated: %F"), FMT_UINT(atomic_u64_eval(&app_statistics()->num_arenas)))); + pos.y += spacing; pos.y += spacing; #if 0 @@ -1841,8 +1844,8 @@ INTERNAL struct sim_ent_handle _translate(struct sim_snapshot *local_ss, struct struct sim_ent_handle local_handle = SIM_ENT_NIL_HANDLE; struct sim_ent *remote_ent = sim_ent_from_handle(remote_ss, remote_ent_handle); if (remote_ent->valid) { - struct sim_netid netid = sim_ent_get_netid(remote_ent); - struct sim_ent *local_ent = sim_ent_from_netid(local_ss, netid); + struct uid uid = sim_ent_get_uid(remote_ent); + struct sim_ent *local_ent = sim_ent_from_uid(local_ss, uid); local_handle = local_ent->handle; } return local_handle; @@ -1864,15 +1867,15 @@ INTERNAL void sim_ent_sync_remote(struct sim_ent *local, struct sim_ent *remote) local->ss = old.ss; local->handle = old.handle; local->net_src_client = remote_client_handle; - local->_netid = old._netid; + local->_uid = old._uid; local->parent = old.parent; local->prev = old.prev; local->next = old.next; local->first = old.first; local->last = old.last; local->top = old.top; - local->next_in_netid_bucket = old.next_in_netid_bucket; - local->prev_in_netid_bucket = old.prev_in_netid_bucket; + local->next_in_uid_bucket = old.next_in_uid_bucket; + local->prev_in_uid_bucket = old.prev_in_uid_bucket; local->next_free = old.next_free; /* Translate remote handles */ @@ -1891,6 +1894,7 @@ INTERNAL void sim_ent_sync_remote(struct sim_ent *local, struct sim_ent *remote) } +/* Walks a local & remote ent tree and allocates net dst ents from remote src ents */ INTERNAL void sim_ent_alloc_any_missing_net_dst(struct sim_ent *local_parent, struct sim_ent *remote) { __prof; @@ -1899,10 +1903,10 @@ INTERNAL void sim_ent_alloc_any_missing_net_dst(struct sim_ent *local_parent, st struct sim_snapshot *remote_ss = remote->ss; struct sim_client_handle remote_client_handle = remote_ss->client->handle; - struct sim_netid netid = sim_ent_get_netid(remote); - struct sim_ent *local_ent = sim_ent_from_netid(local_ss, netid); + struct uid uid = sim_ent_get_uid(remote); + struct sim_ent *local_ent = sim_ent_from_uid(local_ss, uid); if (!local_ent->valid) { - local_ent = sim_ent_alloc_net_dst(local_parent, remote_client_handle, netid); + local_ent = sim_ent_alloc_net_dst(local_parent, remote_client_handle, uid); } for (struct sim_ent *remote_child = sim_ent_from_handle(remote_ss, remote->first); remote_child->valid; remote_child = sim_ent_from_handle(remote_ss, remote_child->next)) { sim_ent_alloc_any_missing_net_dst(local_ent, remote_child); @@ -1911,7 +1915,7 @@ INTERNAL void sim_ent_alloc_any_missing_net_dst(struct sim_ent *local_parent, st } -INTERNAL void sim_snapshot_sync_remote_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss) +INTERNAL void sim_snapshot_sync_net_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss) { __prof; @@ -1929,8 +1933,8 @@ INTERNAL void sim_snapshot_sync_remote_ents(struct sim_snapshot *local_ss, struc for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) { struct sim_ent *local_ent = &local_ss->ents[i]; if (local_ent->valid && sim_ent_has_prop(local_ent, SIM_ENT_PROP_NET_DST) && sim_client_handle_eq(local_ent->net_src_client, remote_client_handle)) { - struct sim_netid netid = sim_ent_get_netid(local_ent); - struct sim_ent *remote_ent = sim_ent_from_netid(remote_ss, netid); + struct uid uid = sim_ent_get_uid(local_ent); + struct sim_ent *remote_ent = sim_ent_from_uid(remote_ss, uid); if (remote_ent->valid) { /* Copy all ent data from remote */ sim_ent_sync_remote(local_ent, remote_ent); @@ -2178,7 +2182,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) { struct sys_lock lock = sys_mutex_lock_e(&G.user_sim_cmd_mutex); control_cmd_ent->cmd_control = G.user_sim_cmd_control; - control_cmd_ent->cmd_hovered_ent_netid = G.user_sim_cmd_hovered_ent_netid; + control_cmd_ent->cmd_hovered_ent_uid = G.user_sim_cmd_hovered_ent_uid; ++G.user_sim_cmd_gen; sys_mutex_unlock(&lock); } @@ -2199,16 +2203,16 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) if (client->valid) { /* Create client ent if necessary */ if (is_master && client != publish_client && client != local_client && client != master_client) { - struct sim_ent *client_ent = sim_ent_from_netid(local_ss, client->client_ent_netid); + struct sim_ent *client_ent = sim_ent_from_uid(local_ss, client->ent_uid); if (!client_ent->valid) { /* FIXME: Client ent never released upon disconnect */ client_ent = sim_ent_alloc_net_src(local_root); client_ent->client_handle = client->handle; sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT); sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE); - client->client_ent_netid = sim_ent_get_netid(client_ent); + client->ent_uid = sim_ent_get_uid(client_ent); if (client == user_input_client) { - local_ss->local_client_netid = sim_ent_get_netid(client_ent); + local_ss->local_client_ent_uid = sim_ent_get_uid(client_ent); } } } @@ -2218,9 +2222,9 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) if (client != publish_client && client != local_client) { struct sim_snapshot *client_ss = sim_snapshot_from_tick(client, step_tick); if (client_ss->valid) { - sim_snapshot_sync_remote_ents(local_ss, client_ss); + sim_snapshot_sync_net_ents(local_ss, client_ss); if (!is_master && client == master_client) { - local_ss->local_client_netid = client_ss->local_client_netid; + local_ss->local_client_ent_uid = client_ss->local_client_ent_uid; } } } @@ -2234,7 +2238,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) struct sim_ent *ent = &local_ss->ents[i]; if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_NET_DST)) { struct sim_client *src_client = sim_client_from_handle(store, ent->net_src_client); - struct sim_ent *client_ent = sim_ent_from_netid(local_ss, src_client->client_ent_netid); + struct sim_ent *client_ent = sim_ent_from_uid(local_ss, src_client->ent_uid); ent->cmd_client = client_ent->handle; } } @@ -2368,7 +2372,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) } else { pub_ss = sim_snapshot_alloc(publish_client, sim_snapshot_from_tick(publish_client, publish_client->last_tick), local_ss->tick + 5); } - sim_snapshot_sync_remote_ents(pub_ss, local_ss); + sim_snapshot_sync_net_ents(pub_ss, local_ss); } #endif @@ -2438,7 +2442,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg) /* TODO: Double buffer */ struct sys_lock lock = sys_mutex_lock_e(&G.local_to_user_client_mutex); struct sim_snapshot *copy_ss = sim_snapshot_alloc(G.local_to_user_client, local_ss, local_ss->tick); - copy_ss->local_client_netid = local_ss->local_client_netid; + copy_ss->local_client_ent_uid = local_ss->local_client_ent_uid; i64 publish_ns = sys_time_ns(); copy_ss->publish_dt_ns = publish_ns - last_publish_ns; copy_ss->publish_time_ns = publish_ns;