diff --git a/src/net/net.c b/src/net/net.c index f807a97e..ab351996 100644 --- a/src/net/net.c +++ b/src/net/net.c @@ -36,14 +36,14 @@ N_Host *N_AcquireHost(u16 listen_port) host->num_msg_assembler_lookup_bins = N_NumMsgAssemblerLookupBins; host->msg_assembler_lookup_bins = PushStructs(host->arena, N_MsgAssemblerLookupBin, host->num_msg_assembler_lookup_bins); - host->sock = P_AcquireSock(listen_port, Mebi(2), Mebi(2)); + host->sock = PLT_AcquireSock(listen_port, Mebi(2), Mebi(2)); return host; } void N_ReleaseHost(N_Host *host) { - P_ReleaseSock(host->sock); + PLT_ReleaseSock(host->sock); ReleaseBuddyCtx(host->buddy); ReleaseArena(host->rcv_buffer_write->arena); @@ -56,18 +56,18 @@ void N_ReleaseHost(N_Host *host) //////////////////////////////////////////////////////////// //~ Channel -u64 N_HashFromAddress(P_Address address) +u64 N_HashFromAddress(PLT_Address address) { return HashFnv64(Fnv64Basis, StringFromStruct(&address)); } -N_Channel *N_ChannelFromAddress(N_Host *host, P_Address address) +N_Channel *N_ChannelFromAddress(N_Host *host, PLT_Address address) { u64 hash = N_HashFromAddress(address); N_ChannelLookupBin *bin = &host->channel_lookup_bins[hash % host->num_channel_lookup_bins]; for (N_Channel *channel = bin->first; channel; channel = channel->next_address_hash) { - if (channel->address_hash == hash && P_MatchAddress(channel->address, address)) + if (channel->address_hash == hash && PLT_MatchAddress(channel->address, address)) { return channel; } @@ -127,7 +127,7 @@ N_ChannelList N_ChannelsFromId(Arena *arena, N_Host *host, N_ChannelId channel_i return result; } -N_Channel *N_AcquireChannel(N_Host *host, P_Address address) +N_Channel *N_AcquireChannel(N_Host *host, PLT_Address address) { N_ChannelId id = ZI; N_Channel *channel; @@ -498,7 +498,7 @@ N_Cmd *N_PushCmd(N_Host *host) return cmd; } -void N_Connect(N_Host *host, P_Address connect_address) +void N_Connect(N_Host *host, PLT_Address connect_address) { N_Channel *channel = N_ChannelFromAddress(host, connect_address); if (!channel->valid) @@ -550,11 +550,11 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host) N_RcvPacket *first_packet = 0; N_RcvPacket *last_packet = 0; { - P_Sock *sock = host->sock; - P_SockReadResult result = ZI; - while ((result = P_ReadSock(scratch.arena, sock)).valid) + PLT_Sock *sock = host->sock; + PLT_SockReadResult result = ZI; + while ((result = PLT_ReadSock(scratch.arena, sock)).valid) { - P_Address address = result.address; + PLT_Address address = result.address; String data = result.data; if (data.len > 0) { @@ -581,7 +581,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host) for (N_RcvPacket *packet = first_packet; packet; packet = packet->next) { //struct sock *sock = packet->sock; - P_Address address = packet->address; + PLT_Address address = packet->address; BB_Buff bb = BB_BuffFromString(packet->data); BB_Reader br = BB_ReaderFromBuff(&bb); u32 magic = BB_ReadUBits(&br, 32); // TODO: implicitly encode magic into crc32 @@ -634,7 +634,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host) // A foreign host is trying to connect to us if (!channel->valid) { - LogInfoF("Host received conection attempt from %F", FmtString(P_StringFromAddress(scratch.arena, address))); + LogInfoF("Host received conection attempt from %F", FmtString(PLT_StringFromAddress(scratch.arena, address))); // TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? channel = N_AcquireChannel(host, address); } @@ -651,7 +651,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host) // We successfully connected to a foreign host and they are ready to receive messages if (channel->valid && !channel->connected) { - LogInfoF("Host received connection from %F", FmtString(P_StringFromAddress(scratch.arena, address))); + LogInfoF("Host received connection from %F", FmtString(PLT_StringFromAddress(scratch.arena, address))); N_Event *event = N_PushEvent(arena, &events); event->kind = N_EventKind_ChannelOpened; event->channel_id = channel->id; @@ -667,7 +667,7 @@ N_EventList N_BeginUpdate(Arena *arena, N_Host *host) // A foreign host disconnected from us if (channel->valid) { - LogInfoF("Host received disconnection from %F", FmtString(P_StringFromAddress(scratch.arena, address))); + LogInfoF("Host received disconnection from %F", FmtString(PLT_StringFromAddress(scratch.arena, address))); N_Event *event = N_PushEvent(arena, &events); event->kind = N_EventKind_ChannelClosed; event->channel_id = channel->id; @@ -1014,22 +1014,22 @@ void N_EndUpdate(N_Host *host) { for (u64 i = 0; i < host->num_channels_reserved; ++i) { - P_Sock *sock = host->sock; + PLT_Sock *sock = host->sock; N_Channel *channel = &host->channels[i]; u64 total_sent = 0; if (channel->valid) { - P_Address address = channel->address; + PLT_Address address = channel->address; // Send reliable packets to channel for (N_SndPacket *packet = channel->first_reliable_packet; packet; packet = packet->next) { - P_WriteSock(sock, address, STRING(packet->data_len, packet->data)); + PLT_WriteSock(sock, address, STRING(packet->data_len, packet->data)); total_sent += packet->data_len; } // Send unreliable packets to channel for (N_SndPacket *packet = channel->first_unreliable_packet; packet; packet = packet->next) { - P_WriteSock(sock, address, STRING(packet->data_len, packet->data)); + PLT_WriteSock(sock, address, STRING(packet->data_len, packet->data)); total_sent += packet->data_len; } // Release unreliable packets diff --git a/src/net/net.h b/src/net/net.h index e7e3f114..70c7d659 100644 --- a/src/net/net.h +++ b/src/net/net.h @@ -106,8 +106,8 @@ Struct(N_SndPacket) Struct(N_RcvPacket) { - P_Sock *sock; - P_Address address; + PLT_Sock *sock; + PLT_Address address; String data; N_RcvPacket *next; }; @@ -131,7 +131,7 @@ Struct(N_Channel) N_Channel *next_free; - P_Address address; + PLT_Address address; u64 address_hash; N_Channel *next_address_hash; N_Channel *prev_address_hash; @@ -222,7 +222,7 @@ Struct(N_Host) { Arena *arena; - P_Sock *sock; + PLT_Sock *sock; BuddyCtx *buddy; // For storing msg assembler data @@ -274,11 +274,11 @@ void N_ReleaseHost(N_Host *host); #define N_MatchChannelId(a, b) ((a).gen == (b).gen && (a).idx == (b).idx) #define N_IsChannelIdNil(v) ((v).gen == 0 && (v).idx == 0) -u64 N_HashFromAddress(P_Address address); -N_Channel *N_ChannelFromAddress(N_Host *host, P_Address address); +u64 N_HashFromAddress(PLT_Address address); +N_Channel *N_ChannelFromAddress(N_Host *host, PLT_Address address); N_Channel *N_ChannelFromId(N_Host *host, N_ChannelId channel_id); N_ChannelList N_ChannelsFromId(Arena *arena, N_Host *host, N_ChannelId channel_id); -N_Channel *N_AcquireChannel(N_Host *host, P_Address address); +N_Channel *N_AcquireChannel(N_Host *host, PLT_Address address); void N_ReleaseChannel(N_Channel *channel); //////////////////////////////////////////////////////////// @@ -301,7 +301,7 @@ N_SndPacket *N_PushSndPacket(N_Channel *channel, b32 is_reliable); //~ Host command N_Cmd *N_PushCmd(N_Host *host); -void N_Connect(N_Host *host, P_Address connect_address); +void N_Connect(N_Host *host, PLT_Address connect_address); void N_Disconnect(N_Host *host, N_ChannelId channel_id); void N_Write(N_Host *host, N_ChannelId channel_id, String msg, N_WriteFlag flags); diff --git a/src/platform/platform.h b/src/platform/platform.h index 5282db3c..2177ba27 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -1,26 +1,26 @@ //////////////////////////////////////////////////////////// //~ Opaque types -Struct(P_Watch); -Struct(P_Sock); +Struct(PLT_Watch); +Struct(PLT_Sock); //////////////////////////////////////////////////////////// //~ File system types -Struct(P_File) +Struct(PLT_File) { u64 handle; b32 valid; }; -Struct(P_FileTime) +Struct(PLT_FileTime) { DateTime created; DateTime accessed; DateTime modified; }; -Struct(P_FileMap) +Struct(PLT_FileMap) { String mapped_memory; u64 handle; @@ -30,16 +30,16 @@ Struct(P_FileMap) //////////////////////////////////////////////////////////// //~ Address types -Enum(P_AddressFamily) +Enum(PLT_AddressFamily) { - P_AddressFamily_Ipv4, - P_AddressFamily_Ipv6 + PLT_AddressFamily_Ipv4, + PLT_AddressFamily_Ipv6 }; -Struct(P_Address) +Struct(PLT_Address) { b32 valid; - P_AddressFamily family; + PLT_AddressFamily family; // NOTE: ipnb & portnb are stored in network byte order u8 ipnb[16]; u16 portnb; @@ -48,28 +48,28 @@ Struct(P_Address) //////////////////////////////////////////////////////////// //~ Sock types -Struct(P_SockReadResult) +Struct(PLT_SockReadResult) { b32 valid; // Since data.len = 0 can be valid - P_Address address; + PLT_Address address; String data; }; //////////////////////////////////////////////////////////// //~ Message box types -Enum(P_MessageBoxKind) +Enum(PLT_MessageBoxKind) { - P_MessageBoxKind_Ok, - P_MessageBoxKind_Warning, - P_MessageBoxKind_Error, - P_MessageBoxKind_Fatal + PLT_MessageBoxKind_Ok, + PLT_MessageBoxKind_Warning, + PLT_MessageBoxKind_Error, + PLT_MessageBoxKind_Fatal }; //////////////////////////////////////////////////////////// //~ @hookdecl Bootstrap -void P_Bootstrap(void); +void PLT_Bootstrap(void); //////////////////////////////////////////////////////////// //~ @hookdecl File system @@ -77,65 +77,65 @@ void P_Bootstrap(void); // NOTE: File paths use forward slash '/' as delimiter //- File system helpers -String P_GetWritePath(Arena *arena); -b32 P_IsFile(String path); -b32 P_IsDir(String path); -void P_MkDir(String path); +String PLT_GetWritePath(Arena *arena); +b32 PLT_IsFile(String path); +b32 PLT_IsDir(String path); +void PLT_MkDir(String path); //- File creation -P_File P_OpenFileRead(String path); -P_File P_OpenFileReadWait(String path); // Waits until file is not being used by another program -P_File P_OpenFileWrite(String path); -P_File P_OpenFileAppend(String path); -void P_CloseFile(P_File file); +PLT_File PLT_OpenFileRead(String path); +PLT_File PLT_OpenFileReadWait(String path); // Waits until file is not being used by another program +PLT_File PLT_OpenFileWrite(String path); +PLT_File PLT_OpenFileAppend(String path); +void PLT_CloseFile(PLT_File file); //- File data manipulation -String P_ReadFile(Arena *arena, P_File file); -void P_WriteFile(P_File file, String data); +String PLT_ReadFile(Arena *arena, PLT_File file); +void PLT_WriteFile(PLT_File file, String data); //- File info -u64 P_GetFileSize(P_File file); -P_FileTime P_GetFileTime(P_File file); +u64 PLT_GetFileSize(PLT_File file); +PLT_FileTime PLT_GetFileTime(PLT_File file); //////////////////////////////////////////////////////////// //~ @hookdecl File map -P_FileMap P_OpenFileMap(P_File file); -void P_CloseFileMap(P_FileMap map); -String P_GetFileMapData(P_FileMap map); +PLT_FileMap PLT_OpenFileMap(PLT_File file); +void PLT_CloseFileMap(PLT_FileMap map); +String PLT_GetFileMapData(PLT_FileMap map); //////////////////////////////////////////////////////////// //~ @hookdecl Address helpers -P_Address P_AddressFromString(String str); -P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr); -P_Address P_AddressFromPort(u16 port); -String P_StringFromAddress(Arena *arena, P_Address address); -b32 P_MatchAddress(P_Address a, P_Address b); +PLT_Address PLT_AddressFromString(String str); +PLT_Address PLT_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr); +PLT_Address PLT_AddressFromPort(u16 port); +String PLT_StringFromAddress(Arena *arena, PLT_Address address); +b32 PLT_MatchAddress(PLT_Address a, PLT_Address b); //////////////////////////////////////////////////////////// //~ @hookdecl Socket -P_Sock *P_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size); -void P_ReleaseSock(P_Sock *sock); -P_SockReadResult P_ReadSock(Arena *arena, P_Sock *sock); -void P_WriteSock(P_Sock *sock, P_Address address, String data); +PLT_Sock *PLT_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size); +void PLT_ReleaseSock(PLT_Sock *sock); +PLT_SockReadResult PLT_ReadSock(Arena *arena, PLT_Sock *sock); +void PLT_WriteSock(PLT_Sock *sock, PLT_Address address, String data); //////////////////////////////////////////////////////////// //~ @hookdecl Utils -void P_MessageBox(P_MessageBoxKind kind, String message); -void P_SetClipboardText(String str); -String P_GetClipboardText(Arena *arena); +void PLT_MessageBox(PLT_MessageBoxKind kind, String message); +void PLT_SetClipboardText(String str); +String PLT_GetClipboardText(Arena *arena); //////////////////////////////////////////////////////////// //~ @hookdecl Timer -Fence *P_GetTimerFence(void); -i64 P_GetCurrentTimerPeriodNs(void); +Fence *PLT_GetTimerFence(void); +i64 PLT_GetCurrentTimerPeriodNs(void); //////////////////////////////////////////////////////////// //~ @hookdecl Sleep -void P_SleepPrecise(i64 sleep_time_ns); -void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns); +void PLT_SleepPrecise(i64 sleep_time_ns); +void PLT_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns); diff --git a/src/platform/platform.lay b/src/platform/platform.lay index abc53fc8..9a446db4 100644 --- a/src/platform/platform.lay +++ b/src/platform/platform.lay @@ -5,7 +5,7 @@ @IncludeC platform.h -@Bootstrap P_Bootstrap +@Bootstrap PLT_Bootstrap ////////////////////////////// //- Impl diff --git a/src/platform/platform_win32/platform_win32.c b/src/platform/platform_win32/platform_win32.c index 325e09ad..c3bfcca0 100644 --- a/src/platform/platform_win32/platform_win32.c +++ b/src/platform/platform_win32/platform_win32.c @@ -1,25 +1,25 @@ -P_W32_Ctx P_W32 = Zi; +PLT_W32_Ctx PLT_W32 = Zi; //////////////////////////////////////////////////////////// //~ @hookimpl Bootstrap -void P_Bootstrap(void) +void PLT_Bootstrap(void) { //- Init watches pool - P_W32.watches_arena = AcquireArena(Gibi(64)); + PLT_W32.watches_arena = AcquireArena(Gibi(64)); // Init winsock - WSAStartup(MAKEWORD(2, 2), &P_W32.wsa_data); - P_W32.socks_arena = AcquireArena(Gibi(64)); + WSAStartup(MAKEWORD(2, 2), &PLT_W32.wsa_data); + PLT_W32.socks_arena = AcquireArena(Gibi(64)); // Init timer - DispatchWave(Lit("Win32 timer sync"), 1, P_W32_SyncTimerForever, 0); + DispatchWave(Lit("Win32 timer sync"), 1, PLT_W32_SyncTimerForever, 0); } //////////////////////////////////////////////////////////// //~ Time -DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st) +DateTime PLT_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st) { return (DateTime) { @@ -37,7 +37,7 @@ DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st) //////////////////////////////////////////////////////////// //~ File system -String P_W32_StringFromWin32Path(Arena *arena, wchar_t *src) +String PLT_W32_StringFromWin32Path(Arena *arena, wchar_t *src) { String result = Zi; result.text = ArenaNext(arena, u8); @@ -65,10 +65,10 @@ String P_W32_StringFromWin32Path(Arena *arena, wchar_t *src) //////////////////////////////////////////////////////////// //~ Address -P_W32_Address P_W32_Win32AddressFromPlatformAddress(P_Address addr) +PLT_W32_Address PLT_W32_Win32AddressFromPlatformAddress(PLT_Address addr) { - P_W32_Address result = Zi; - if (addr.family == P_AddressFamily_Ipv4) + PLT_W32_Address result = Zi; + if (addr.family == PLT_AddressFamily_Ipv4) { result.family = AF_INET; result.size = sizeof(struct sockaddr_in); @@ -88,7 +88,7 @@ P_W32_Address P_W32_Win32AddressFromPlatformAddress(P_Address addr) } // If supplied address has ip INADDR_ANY (0), convert ip to localhost -P_W32_Address P_W32_ConvertAnyaddrToLocalhost(P_W32_Address addr) +PLT_W32_Address PLT_W32_ConvertAnyaddrToLocalhost(PLT_W32_Address addr) { if (addr.family == AF_INET) { @@ -128,19 +128,19 @@ P_W32_Address P_W32_ConvertAnyaddrToLocalhost(P_W32_Address addr) return addr; } -P_Address P_W32_PlatformAddressFromWin32Address(P_W32_Address ws_addr) +PLT_Address PLT_W32_PlatformAddressFromWin32Address(PLT_W32_Address ws_addr) { - P_Address result = Zi; + PLT_Address result = Zi; if (ws_addr.family == AF_INET) { - result.family = P_AddressFamily_Ipv4; + result.family = PLT_AddressFamily_Ipv4; result.portnb = ws_addr.sin.sin_port; CopyBytes(result.ipnb, &ws_addr.sin.sin_addr, 4); result.valid = 1; } else if (ws_addr.family == AF_INET6) { - result.family = P_AddressFamily_Ipv6; + result.family = PLT_AddressFamily_Ipv6; result.portnb = ws_addr.sin6.sin6_port; CopyBytes(result.ipnb, &ws_addr.sin6.sin6_addr.s6_addr, 16); result.valid = 1; @@ -151,7 +151,7 @@ P_Address P_W32_PlatformAddressFromWin32Address(P_W32_Address ws_addr) //////////////////////////////////////////////////////////// //~ Timer job -void P_W32_SyncTimerForever(WaveLaneCtx *lane) +void PLT_W32_SyncTimerForever(WaveLaneCtx *lane) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); @@ -163,10 +163,10 @@ void P_W32_SyncTimerForever(WaveLaneCtx *lane) } i32 periods_index = 0; - i64 periods[P_W32_NumRollingTimerPeriods] = Zi; + i64 periods[PLT_W32_NumRollingTimerPeriods] = Zi; for (i32 i = 0; i < (i32)countof(periods); ++i) { - periods[i] = P_W32_DefaultTimerPeriodNs; + periods[i] = PLT_W32_DefaultTimerPeriodNs; } i64 last_cycle_ns = 0; @@ -185,7 +185,7 @@ void P_W32_SyncTimerForever(WaveLaneCtx *lane) WaitForSingleObject(timer, INFINITE); } i64 now_ns = TimeNs(); - i64 period_ns = last_cycle_ns == 0 ? P_W32_DefaultTimerPeriodNs : now_ns - last_cycle_ns; + i64 period_ns = last_cycle_ns == 0 ? PLT_W32_DefaultTimerPeriodNs : now_ns - last_cycle_ns; last_cycle_ns = now_ns; // Compute mean period @@ -201,18 +201,18 @@ void P_W32_SyncTimerForever(WaveLaneCtx *lane) periods_sum_ns += (f64)periods[i]; } f64 mean_ns = periods_sum_ns / (f64)countof(periods); - Atomic64Set(&P_W32.average_timer_period_ns.v, RoundF64(mean_ns)); + Atomic64Set(&PLT_W32.average_timer_period_ns.v, RoundF64(mean_ns)); } // Update fence - SetFence(&P_W32.timer_fence, now_ns); + SetFence(&PLT_W32.timer_fence, now_ns); } } //////////////////////////////////////////////////////////// //~ @hookimpl File system -String P_GetWritePath(Arena *arena) +String PLT_GetWritePath(Arena *arena) { u16 *p = 0; // TODO: cache this? @@ -225,13 +225,13 @@ String P_GetWritePath(Arena *arena) String path = Zi; if (result == S_OK) { - path = P_W32_StringFromWin32Path(arena, p); + path = PLT_W32_StringFromWin32Path(arena, p); } CoTaskMemFree(p); return path; } -b32 P_IsFile(String path) +b32 PLT_IsFile(String path) { TempArena scratch = BeginScratchNoConflict(); wchar_t *path_wstr = WstrFromString(scratch.arena, path); @@ -240,7 +240,7 @@ b32 P_IsFile(String path) return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY); } -b32 P_IsDir(String path) +b32 PLT_IsDir(String path) { TempArena scratch = BeginScratchNoConflict(); wchar_t *path_wstr = WstrFromString(scratch.arena, path); @@ -249,7 +249,7 @@ b32 P_IsDir(String path) return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY); } -void P_MkDir(String path) +void PLT_MkDir(String path) { TempArena scratch = BeginScratchNoConflict(); wchar_t *path_wstr = WstrFromString(scratch.arena, path); @@ -292,10 +292,10 @@ void P_MkDir(String path) EndScratch(scratch); } -P_File P_OpenFileRead(String path) +PLT_File PLT_OpenFileRead(String path) { TempArena scratch = BeginScratchNoConflict(); - P_File file = Zi; + PLT_File file = Zi; wchar_t *path_wstr = WstrFromString(scratch.arena, path); HANDLE handle = CreateFileW( @@ -314,10 +314,10 @@ P_File P_OpenFileRead(String path) return file; } -P_File P_OpenFileReadWait(String path) +PLT_File PLT_OpenFileReadWait(String path) { TempArena scratch = BeginScratchNoConflict(); - P_File file = Zi; + PLT_File file = Zi; wchar_t *path_wstr = WstrFromString(scratch.arena, path); i32 delay_ms = 1; @@ -344,10 +344,10 @@ P_File P_OpenFileReadWait(String path) return file; } -P_File P_OpenFileWrite(String path) +PLT_File PLT_OpenFileWrite(String path) { TempArena scratch = BeginScratchNoConflict(); - P_File file = Zi; + PLT_File file = Zi; wchar_t *path_wstr = WstrFromString(scratch.arena, path); HANDLE handle = CreateFileW( @@ -366,10 +366,10 @@ P_File P_OpenFileWrite(String path) return file; } -P_File P_OpenFileAppend(String path) +PLT_File PLT_OpenFileAppend(String path) { TempArena scratch = BeginScratchNoConflict(); - P_File file = Zi; + PLT_File file = Zi; wchar_t *path_wstr = WstrFromString(scratch.arena, path); HANDLE handle = CreateFileW( @@ -388,7 +388,7 @@ P_File P_OpenFileAppend(String path) return file; } -void P_CloseFile(P_File file) +void PLT_CloseFile(PLT_File file) { if (file.handle) { @@ -396,7 +396,7 @@ void P_CloseFile(P_File file) } } -String P_ReadFile(Arena *arena, P_File file) +String PLT_ReadFile(Arena *arena, PLT_File file) { i64 size = 0; GetFileSizeEx((HANDLE)file.handle, (PLARGE_INTEGER)&size); @@ -419,7 +419,7 @@ String P_ReadFile(Arena *arena, P_File file) return result; } -void P_WriteFile(P_File file, String data) +void PLT_WriteFile(PLT_File file, String data) { // TODO: Check what the real data limit is and chunk sequentially based on // that (rather than failing) @@ -444,14 +444,14 @@ void P_WriteFile(P_File file, String data) ); } -u64 P_GetFileSize(P_File file) +u64 PLT_GetFileSize(PLT_File file) { LARGE_INTEGER li_file_size; GetFileSizeEx((HANDLE)file.handle, &li_file_size); return (u64)(li_file_size.QuadPart > 0 ? li_file_size.QuadPart : 0); } -P_FileTime P_GetFileTime(P_File file) +PLT_FileTime PLT_GetFileTime(PLT_File file) { // Get file times FILETIME ft_created; @@ -473,27 +473,27 @@ P_FileTime P_GetFileTime(P_File file) FileTimeToSystemTime(&ft_accessed, &st_accessed); FileTimeToSystemTime(&ft_modified, &st_modified); - return (P_FileTime) + return (PLT_FileTime) { - .created = P_W32_DateTimeFromWin32SystemTime(st_created), - .accessed = P_W32_DateTimeFromWin32SystemTime(st_accessed), - .modified = P_W32_DateTimeFromWin32SystemTime(st_modified) + .created = PLT_W32_DateTimeFromWin32SystemTime(st_created), + .accessed = PLT_W32_DateTimeFromWin32SystemTime(st_accessed), + .modified = PLT_W32_DateTimeFromWin32SystemTime(st_modified) }; } else { - return (P_FileTime) { 0 }; + return (PLT_FileTime) { 0 }; } } //////////////////////////////////////////////////////////// //~ @hookimpl File map -P_FileMap P_OpenFileMap(P_File file) +PLT_FileMap PLT_OpenFileMap(PLT_File file) { - P_FileMap map = Zi; + PLT_FileMap map = Zi; - u64 size = P_GetFileSize(file); + u64 size = PLT_GetFileSize(file); u8 *base_ptr = 0; HANDLE map_handle = 0; @@ -536,7 +536,7 @@ P_FileMap P_OpenFileMap(P_File file) return map; } -void P_CloseFileMap(P_FileMap map) +void PLT_CloseFileMap(PLT_FileMap map) { if (map.mapped_memory.text) { @@ -548,7 +548,7 @@ void P_CloseFileMap(P_FileMap map) } } -String P_GetFileMapData(P_FileMap map) +String PLT_GetFileMapData(PLT_FileMap map) { return map.mapped_memory; } @@ -556,9 +556,9 @@ String P_GetFileMapData(P_FileMap map) //////////////////////////////////////////////////////////// //~ @hookimpl Address helpers -P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr) +PLT_Address PLT_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr) { - P_Address result = Zi; + PLT_Address result = Zi; struct addrinfo hints = Zi; hints.ai_family = AF_UNSPEC; @@ -575,7 +575,7 @@ P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr) { struct sockaddr_in *sockaddr = (struct sockaddr_in *)ai_result->ai_addr; result.valid = 1; - result.family = P_AddressFamily_Ipv4; + result.family = PLT_AddressFamily_Ipv4; result.portnb = sockaddr->sin_port; StaticAssert(sizeof(sockaddr->sin_addr) == 4); CopyBytes(result.ipnb, (void *)&sockaddr->sin_addr, 4); @@ -586,7 +586,7 @@ P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr) // TODO: Enable ipv6 // struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)ai_result->ai_addr; // result.valid = 1; - // result.family = P_AddressFamily_Ipv6; + // result.family = PLT_AddressFamily_Ipv6; // result.portnb = sockaddr->sin6_port; // StaticAssert(sizeof(sockaddr->sin6_addr) == 16); // CopyBytes(result.ipnb, (void *)&sockaddr->sin6_addr, 16); @@ -600,7 +600,7 @@ P_Address P_AddressFromIpPortCstr(char *ip_cstr, char *port_cstr) return result; } -P_Address P_AddressFromString(String str) +PLT_Address PLT_AddressFromString(String str) { // Parse string into ip & port u8 ip_buff[1024]; @@ -691,11 +691,11 @@ P_Address P_AddressFromString(String str) } } - P_Address result = P_AddressFromIpPortCstr(ip_cstr, port_cstr); + PLT_Address result = PLT_AddressFromIpPortCstr(ip_cstr, port_cstr); return result; } -P_Address P_AddressFromPort(u16 port) +PLT_Address PLT_AddressFromPort(u16 port) { u8 port_buff[128]; char *port_cstr = 0; @@ -721,16 +721,16 @@ P_Address P_AddressFromPort(u16 port) } } - P_Address result = P_AddressFromIpPortCstr(0, port_cstr); + PLT_Address result = PLT_AddressFromIpPortCstr(0, port_cstr); return result; } -String P_StringFromAddress(Arena *arena, P_Address address) +String PLT_StringFromAddress(Arena *arena, PLT_Address address) { String result = Zi; - if (address.family == P_AddressFamily_Ipv6) + if (address.family == PLT_AddressFamily_Ipv6) { // TODO } @@ -748,7 +748,7 @@ String P_StringFromAddress(Arena *arena, P_Address address) return result; } -b32 P_MatchAddress(P_Address a, P_Address b) +b32 PLT_MatchAddress(PLT_Address a, PLT_Address b) { return MatchStruct(&a, &b); } @@ -756,26 +756,26 @@ b32 P_MatchAddress(P_Address a, P_Address b) //////////////////////////////////////////////////////////// //~ @hookimpl Socket -P_Sock *P_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size) +PLT_Sock *PLT_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size) { - P_W32_Sock *ws = 0; + PLT_W32_Sock *ws = 0; { - Lock lock = LockE(&P_W32.socks_mutex); - if (P_W32.first_free_sock) + Lock lock = LockE(&PLT_W32.socks_mutex); + if (PLT_W32.first_free_sock) { - ws = P_W32.first_free_sock; - P_W32.first_free_sock = ws->next_free; + ws = PLT_W32.first_free_sock; + PLT_W32.first_free_sock = ws->next_free; } else { - ws = PushStructNoZero(P_W32.socks_arena, P_W32_Sock); + ws = PushStructNoZero(PLT_W32.socks_arena, PLT_W32_Sock); } Unlock(&lock); } ZeroStruct(ws); - P_Address addr = P_AddressFromPort(listen_port); - P_W32_Address bind_address = P_W32_Win32AddressFromPlatformAddress(addr); + PLT_Address addr = PLT_AddressFromPort(listen_port); + PLT_W32_Address bind_address = PLT_W32_Win32AddressFromPlatformAddress(addr); ws->sock = socket(bind_address.family, SOCK_DGRAM, IPPROTO_UDP); { i32 sb = sndbuf_size; @@ -787,39 +787,39 @@ P_Sock *P_AcquireSock(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size) } bind(ws->sock, &bind_address.sa, bind_address.size); - return (P_Sock *)ws; + return (PLT_Sock *)ws; } -void P_ReleaseSock(P_Sock *sock) +void PLT_ReleaseSock(PLT_Sock *sock) { - P_W32_Sock *ws = (P_W32_Sock *)sock; + PLT_W32_Sock *ws = (PLT_W32_Sock *)sock; closesocket(ws->sock); - Lock lock = LockE(&P_W32.socks_mutex); + Lock lock = LockE(&PLT_W32.socks_mutex); { - ws->next_free = P_W32.first_free_sock; - P_W32.first_free_sock = ws; + ws->next_free = PLT_W32.first_free_sock; + PLT_W32.first_free_sock = ws; } Unlock(&lock); } -P_SockReadResult P_ReadSock(Arena *arena, P_Sock *sock) +PLT_SockReadResult PLT_ReadSock(Arena *arena, PLT_Sock *sock) { - P_W32_Sock *ws = (P_W32_Sock *)sock; + PLT_W32_Sock *ws = (PLT_W32_Sock *)sock; u64 read_buff_size = Kibi(64); String read_buff = Zi; read_buff.len = read_buff_size; read_buff.text = PushStructsNoZero(arena, u8, read_buff_size); - P_SockReadResult result = Zi; + PLT_SockReadResult result = Zi; - P_W32_Address ws_addr = Zi; + PLT_W32_Address ws_addr = Zi; ws_addr.size = sizeof(ws_addr.sas); i32 size = recvfrom(ws->sock, (char *)read_buff.text, read_buff.len, 0, &ws_addr.sa, &ws_addr.size); ws_addr.family = ws_addr.sin.sin_family; - result.address = P_W32_PlatformAddressFromWin32Address(ws_addr); + result.address = PLT_W32_PlatformAddressFromWin32Address(ws_addr); if (size >= 0) { AddGstat(SockBytesReceived, size); @@ -845,10 +845,10 @@ P_SockReadResult P_ReadSock(Arena *arena, P_Sock *sock) return result; } -void P_WriteSock(P_Sock *sock, P_Address address, String data) +void PLT_WriteSock(PLT_Sock *sock, PLT_Address address, String data) { - P_W32_Sock *ws = (P_W32_Sock *)sock; - P_W32_Address ws_addr = P_W32_Win32AddressFromPlatformAddress(address); + PLT_W32_Sock *ws = (PLT_W32_Sock *)sock; + PLT_W32_Address ws_addr = PLT_W32_Win32AddressFromPlatformAddress(address); i32 size = sendto(ws->sock, (char *)data.text, data.len, 0, &ws_addr.sa, ws_addr.size); if (size > 0) { @@ -867,7 +867,7 @@ void P_WriteSock(P_Sock *sock, P_Address address, String data) //////////////////////////////////////////////////////////// //~ @hookimpl Utils -void P_MessageBox(P_MessageBoxKind kind, String message) +void PLT_MessageBox(PLT_MessageBoxKind kind, String message) { TempArena scratch = BeginScratchNoConflict(); @@ -877,24 +877,24 @@ void P_MessageBox(P_MessageBoxKind kind, String message) switch (kind) { - case P_MessageBoxKind_Ok: + case PLT_MessageBoxKind_Ok: { mbox_type |= MB_ICONINFORMATION; } break; - case P_MessageBoxKind_Warning: + case PLT_MessageBoxKind_Warning: { title = L"Warning"; mbox_type |= MB_ICONWARNING; } break; - case P_MessageBoxKind_Error: + case PLT_MessageBoxKind_Error: { title = L"Error"; mbox_type |= MB_ICONERROR; } break; - case P_MessageBoxKind_Fatal: + case PLT_MessageBoxKind_Fatal: { title = L"Fatal error"; mbox_type |= MB_ICONSTOP; @@ -907,7 +907,7 @@ void P_MessageBox(P_MessageBoxKind kind, String message) EndScratch(scratch); } -void P_SetClipboardText(String str) +void PLT_SetClipboardText(String str) { if (OpenClipboard(0)) { @@ -929,7 +929,7 @@ void P_SetClipboardText(String str) } } -String P_GetClipboardText(Arena *arena) +String PLT_GetClipboardText(Arena *arena) { String result = Zi; if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(0)) @@ -949,28 +949,28 @@ String P_GetClipboardText(Arena *arena) //////////////////////////////////////////////////////////// //~ @hookimpl Timer -Fence *P_GetTimerFence(void) +Fence *PLT_GetTimerFence(void) { - return &P_W32.timer_fence; + return &PLT_W32.timer_fence; } -i64 P_GetCurrentTimerPeriodNs(void) +i64 PLT_GetCurrentTimerPeriodNs(void) { - return Atomic64Fetch(&P_W32.average_timer_period_ns.v); + return Atomic64Fetch(&PLT_W32.average_timer_period_ns.v); } //////////////////////////////////////////////////////////// //~ @hookimpl Sleep -void P_SleepPrecise(i64 sleep_time_ns) +void PLT_SleepPrecise(i64 sleep_time_ns) { i64 now_ns = TimeNs(); i64 target_ns = now_ns + sleep_time_ns; // Sleep on timer to conserve power { - Fence *timer_fence = P_GetTimerFence(); - i64 timer_period_ns = P_GetCurrentTimerPeriodNs(); + Fence *timer_fence = PLT_GetTimerFence(); + i64 timer_period_ns = PLT_GetCurrentTimerPeriodNs(); i64 timer_tolerance_ns = timer_period_ns * 0.5; i64 target_timer_sleep_ns = target_ns - timer_period_ns - timer_tolerance_ns; YieldOnFence(timer_fence, target_timer_sleep_ns); @@ -985,7 +985,7 @@ void P_SleepPrecise(i64 sleep_time_ns) } } -void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns) +void PLT_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns) { if (last_frame_time_ns != 0 && target_dt_ns > 0) { @@ -994,7 +994,7 @@ void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns) i64 sleep_time_ns = target_dt_ns - last_frame_dt_ns; if (sleep_time_ns > 0) { - P_SleepPrecise(sleep_time_ns); + PLT_SleepPrecise(sleep_time_ns); } } } diff --git a/src/platform/platform_win32/platform_win32.h b/src/platform/platform_win32/platform_win32.h index 9b967c56..41b46dbb 100644 --- a/src/platform/platform_win32/platform_win32.h +++ b/src/platform/platform_win32/platform_win32.h @@ -1,18 +1,18 @@ //////////////////////////////////////////////////////////// //~ Watch types -Struct(P_W32_Watch) +Struct(PLT_W32_Watch) { HANDLE dir_handle; HANDLE wake_handle; - P_W32_Watch *next_free; + PLT_W32_Watch *next_free; u8 results_buff[Kibi(64)]; }; //////////////////////////////////////////////////////////// //~ Address types -Struct(P_W32_Address) +Struct(PLT_W32_Address) { i32 size; i32 family; @@ -28,56 +28,56 @@ Struct(P_W32_Address) //////////////////////////////////////////////////////////// //~ Sock types -Struct(P_W32_Sock) +Struct(PLT_W32_Sock) { SOCKET sock; - P_W32_Sock *next_free; + PLT_W32_Sock *next_free; }; //////////////////////////////////////////////////////////// //~ State types -#define P_W32_NumRollingTimerPeriods 500 -#define P_W32_DefaultTimerPeriodNs 50000000 +#define PLT_W32_NumRollingTimerPeriods 500 +#define PLT_W32_DefaultTimerPeriodNs 50000000 -Struct(P_W32_Ctx) +Struct(PLT_W32_Ctx) { //- Watches pool Mutex watches_mutex; Arena *watches_arena; - P_W32_Watch *watches_first_free; + PLT_W32_Watch *watches_first_free; //- Socket pool WSADATA wsa_data; Arena *socks_arena; Mutex socks_mutex; - P_W32_Sock *first_free_sock; + PLT_W32_Sock *first_free_sock; //- Timer Fence timer_fence; Atomic64Padded average_timer_period_ns; }; -extern P_W32_Ctx P_W32; +extern PLT_W32_Ctx PLT_W32; //////////////////////////////////////////////////////////// //~ Time -DateTime P_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st); +DateTime PLT_W32_DateTimeFromWin32SystemTime(SYSTEMTIME st); //////////////////////////////////////////////////////////// //~ File system -String P_W32_StringFromWin32Path(Arena *arena, wchar_t *src); +String PLT_W32_StringFromWin32Path(Arena *arena, wchar_t *src); //////////////////////////////////////////////////////////// //~ Address -P_W32_Address P_W32_Win32AddressFromPlatformAddress(P_Address addr); -P_W32_Address P_W32_ConvertAnyaddrToLocalhost(P_W32_Address addr); -P_Address P_W32_PlatformAddressFromWin32Address(P_W32_Address ws_addr); +PLT_W32_Address PLT_W32_Win32AddressFromPlatformAddress(PLT_Address addr); +PLT_W32_Address PLT_W32_ConvertAnyaddrToLocalhost(PLT_W32_Address addr); +PLT_Address PLT_W32_PlatformAddressFromWin32Address(PLT_W32_Address ws_addr); //////////////////////////////////////////////////////////// //~ Timer job -void P_W32_SyncTimerForever(WaveLaneCtx *lane); +void PLT_W32_SyncTimerForever(WaveLaneCtx *lane); diff --git a/src/pp/pp.lay b/src/pp/pp.lay index 8efbe07a..e7c3751b 100644 --- a/src/pp/pp.lay +++ b/src/pp/pp.lay @@ -1,7 +1,12 @@ @Layer pp ////////////////////////////// -//- Dependencies +//- Resources -@Dep pp_sim -@Dep pp_vis +@EmbedDir P_Resources pp_res + +////////////////////////////// +//- Impl + +@DefaultDownstream Any pp_vis +@DefaultDownstream Any pp_sim diff --git a/src/pp/pp_vis/pp_vis_res/font/fixedsys.ttf b/src/pp/pp_res/font/fixedsys.ttf similarity index 100% rename from src/pp/pp_vis/pp_vis_res/font/fixedsys.ttf rename to src/pp/pp_res/font/fixedsys.ttf diff --git a/src/pp/pp_vis/pp_vis_res/font/seguisb.ttf b/src/pp/pp_res/font/seguisb.ttf similarity index 100% rename from src/pp/pp_vis/pp_vis_res/font/seguisb.ttf rename to src/pp/pp_res/font/seguisb.ttf diff --git a/src/pp/pp_sim/pp_sim.lay b/src/pp/pp_sim/pp_sim.lay index 1f407f23..dc9fcb65 100644 --- a/src/pp/pp_sim/pp_sim.lay +++ b/src/pp/pp_sim/pp_sim.lay @@ -3,6 +3,7 @@ ////////////////////////////// //- Dependencies +@Dep pp @Dep platform ////////////////////////////// diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 639b0ba9..d82e0cfe 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -1676,7 +1676,7 @@ void S_TickForever(WaveLaneCtx *lane) if (!shutdown) { i64 step_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND; - P_SleepFrame(frame_begin_ns, step_dt_ns); + PLT_SleepFrame(frame_begin_ns, step_dt_ns); } } diff --git a/src/pp/pp_vis/pp_vis.lay b/src/pp/pp_vis/pp_vis.lay index e5a88a3e..83eb70aa 100644 --- a/src/pp/pp_vis/pp_vis.lay +++ b/src/pp/pp_vis/pp_vis.lay @@ -3,6 +3,7 @@ ////////////////////////////// //- Dependencies +@Dep pp @Dep gpu @Dep glyph_cache @Dep platform @@ -13,8 +14,6 @@ ////////////////////////////// //- Resources -@EmbedDir V_Resources pp_vis_res - @ComputeShader V_ClearCellsCS @ComputeShader V_ClearParticlesCS @ComputeShader V_BackdropCS @@ -31,10 +30,8 @@ //- Api @IncludeC pp_vis_shared.cgh -@IncludeG pp_vis_shared.cgh - @IncludeC pp_vis_core.h - +@IncludeG pp_vis_shared.cgh @IncludeG pp_vis_gpu.gh @Bootstrap V_Bootstrap @@ -43,5 +40,4 @@ //- Impl @IncludeC pp_vis_core.c - @IncludeG pp_vis_gpu.g diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 7a1aa2b7..e408d477 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -246,7 +246,7 @@ V_WidgetTheme V_GetWidgetTheme(void) { V_WidgetTheme theme = Zi; - theme.text_font = GC_FontKeyFromResource(ResourceKeyFromStore(&V_Resources, Lit("font/seguisb.ttf"))); + theme.text_font = GC_FontKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("font/seguisb.ttf"))); theme.icon_font = UI_BuiltinIconFont(); // theme.font_size = 14; diff --git a/src/pp_old/pp.c b/src/pp_old/pp.c deleted file mode 100644 index c3a42d09..00000000 --- a/src/pp_old/pp.c +++ /dev/null @@ -1,3092 +0,0 @@ -PP_SharedUserState PP_shared_user_state = ZI; - -//////////////////////////////////////////////////////////// -//~ Startup - -void PP_StartupUser(void) -{ - __prof; - PP_SharedUserState *g = &PP_shared_user_state; - - SetGstat(GSTAT_DEBUG_STEPS, U64Max); - - Arena *perm = PermArena(); - g->real_time_ns = TimeNs(); - - /* TODO: Remove this */ - String connect_address_str = Lit(""); - g->connect_address_str = PushString(perm, connect_address_str); - - /* Initialize average dt to a reasonable value */ - g->average_local_to_user_snapshot_publish_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND; - - /* User blend clients */ - g->user_client_store = PP_AcquireClientStore(); - g->user_unblended_client = PP_AcquireClient(g->user_client_store); - g->user_blended_client = PP_AcquireClient(g->user_client_store); - g->ss_blended = PP_NilSnapshot(); - - /* Local to user client */ - g->local_to_user_client_store = PP_AcquireClientStore(); - g->local_to_user_client = PP_AcquireClient(g->local_to_user_client_store); - - /* Init from swap */ - if (IsSwappedIn()); - { - TempArena scratch = BeginScratchNoConflict(); - String swap_encoded = SwappedStateFromName(scratch.arena, Lit("pp_user")); - - BB_Buff bb = BB_BuffFromString(swap_encoded); - BB_Reader br = BB_ReaderFromBuff(&bb); - - String swap_str = BB_ReadString(scratch.arena, &br); - g->window_restore = BB_ReadString(perm, &br); - - if (swap_str.len == sizeof(PP_SwappedUserState)) - { - PP_SwappedUserState *swap = PushStructNoZero(scratch.arena, PP_SwappedUserState); - CopyBytes(swap, swap_str.text, swap_str.len); - PP_SharedUserState *old = &swap->s; - CopyStructRegion(g, old, AUTO_PERSIST_START, AUTO_PERSIST_END); - } - - EndScratch(scratch); - } - - /* Create job pools */ - JobPoolId user_pool = InitJobPool(1, Lit("User"), JobPoolPriority_Graphics); - JobPoolId sim_pool = InitJobPool(1, Lit("Simulation"), JobPoolPriority_Simulation); - - /* Start jobs */ - g->shutdown_jobs_count += RunJob(PP_UpdateUserOrSleep, .pool = user_pool, .fence = &g->shutdown_jobs_fence); - g->shutdown_jobs_count += RunJob(PP_UpdateSim, .pool = sim_pool, .fence = &g->shutdown_jobs_fence); - OnExit(&PP_ShutdownUser); -} - -//////////////////////////////////////////////////////////// -//~ Shutdown - -ExitFuncDef(PP_ShutdownUser) -{ - __prof; - PP_SharedUserState *g = &PP_shared_user_state; - Atomic32Set(&g->shutdown, 1); - YieldOnFence(&g->shutdown_jobs_fence, g->shutdown_jobs_count); - - /* Swap out */ - if (IsSwappingOut()) - { - TempArena scratch = BeginScratchNoConflict(); - u64 max_size = Mebi(16); - u8 *bytes = PushStructsNoZero(scratch.arena, u8, max_size); - BB_Buff bb = BB_BuffFromString(STRING(max_size, bytes)); - { - BB_Writer bw = BB_WriterFromBuff(&bb); - PP_SwappedUserState *swap = PushStruct(scratch.arena, PP_SwappedUserState); - swap->s = *g; - BB_WriteString(&bw, StringFromStruct(swap)); - BB_WriteString(&bw, g->window_restore); - WriteSwappedState(Lit("pp_user"), STRING(BB_GetNumBytesWritten(&bw), BB_GetWrittenRaw(&bw))); - } - EndScratch(scratch); - } -} - -//////////////////////////////////////////////////////////// -//~ Ui helpers - -//- Ui style -void PP_PushGameUiStyle(void) -{ - // UI_Push(FontSize, 48); - // UI_Push(FontSize, 32); - - // UI_Push(Font, ResourceKeyFromStore(&PP_Resources, Lit("font/roboto-med.ttf"))); - UI_Push(Font, ResourceKeyFromStore(&PP_Resources, Lit("font/fixedsys.ttf"))); - UI_Push(FontSize, 16); - - UI_Push(Rounding, UI_RPIX(0)); - - UI_Push(Border, 1); - // UI_Push(BackgroundColor, Rgba32F(0.3, 0.5, 0.3, 0.3)); - UI_Push(BackgroundColor, Rgba32F(0.3, 0.3, 0.3, 1)); - - UI_Push(BorderColor, Rgba32F(0.6, 0.6, 0.6, 1)); - - UI_Push(Width, UI_FILL(1, 0)); - UI_Push(Height, UI_FILL(1, 0)); - - UI_Push(ChildLayoutAxis, Axis_Y); -} - -//- Draw xform -void PP_DrawDebugXform(Xform xf, u32 color_x, u32 color_y) -{ - PP_SharedUserState *g = &PP_shared_user_state; - f32 thickness = 2.f; - f32 arrowhead_len = 15.f; - - Vec2 pos = MulXformV2(g->world_to_ui_xf, xf.og); - Vec2 x_ray = MulXformBasisV2(g->world_to_ui_xf, RightFromXform(xf)); - Vec2 y_ray = MulXformBasisV2(g->world_to_ui_xf, UpFromXform(xf)); - - f32 ray_scale = 1; - x_ray = MulVec2(x_ray, ray_scale); - y_ray = MulVec2(y_ray, ray_scale); - - /* FIXME: Enable this */ -#if 0 - D_DrawArrowRay(g->render_sig, pos, x_ray, thickness, arrowhead_len, color_x); - D_DrawArrowRay(g->render_sig, pos, y_ray, thickness, arrowhead_len, color_y); -#endif - - //u32 color_quad = Rgba32F(0, 1, 1, 0.3); - //Quad quad = QuadFromRect(RectFromScalar(0, 0, 1, -1)); - //quad = MulXformQuad(xf, ScaleQuad(quad, 0.075f)); - //D_DrawQuad(g->render_sig, quad, color); -} - -//- Draw movement -void PP_DrawDebugMovement(PP_Ent *ent) -{ - PP_SharedUserState *g = &PP_shared_user_state; - f32 thickness = 2.f; - f32 arrow_len = 15.f; - - u32 color_vel = Color_Orange; - - Xform xf = PP_XformFromEnt(ent); - Vec2 velocity = ent->linear_velocity; - - Vec2 pos = MulXformV2(g->world_to_ui_xf, xf.og); - Vec2 vel_ray = MulXformBasisV2(g->world_to_ui_xf, velocity); - - if (Vec2Len(vel_ray) > 0.00001) - { - /* FIXME: Enable this */ - D_DrawArrowRay(g->render_sig, pos, vel_ray, thickness, arrow_len, color_vel); - } -} - -//- Ent debug string -String PP_DebugStringFromEnt(Arena *arena, PP_Ent *ent) -{ - TempArena scratch = BeginScratch(arena); - PP_Snapshot *ss = ent->ss; - - const u8 hex[] = "0123456789abcdef"; - - String result = ZI; - result.text = PushDry(arena, u8); - - //result.len += StringF(arena, "[%F]", FmtUid(ent->key.uid)).len; - { - b32 transmitting = PP_HasProp(ent, PP_Prop_SyncSrc); - b32 receiving = PP_HasProp(ent, PP_Prop_SyncDst); - if (transmitting & receiving) - { - result.len += StringF(arena, " networked (sending & receiving)").len; - } - else if (transmitting) - { - result.len += StringF(arena, " networked (sending)").len; - } - else if (receiving) - { - result.len += StringF(arena, " networked (receiving)").len; - } - else - { - result.len += StringF(arena, " local").len; - } - } - result.len += StringF(arena, "\n").len; - - result.len += StringF(arena, "owner: [%F]\n", FmtUid(ent->owner.uid)).len; - - result.len += StringF(arena, "\n").len; - - { - result.len += StringF(arena, "props: 0x").len; - for (u64 chunk_index = countof(ent->props); chunk_index-- > 0;) - { - u64 chunk = ent->props[chunk_index]; - for (u64 part_index = 8; part_index-- > 0;) - { - if ((chunk_index != (countof(ent->props) - 1)) || ((chunk_index * 64) + (part_index * 8)) <= PP_Prop_COUNT) - { - u8 part = (chunk >> (part_index * 8)) & 0xFF; - StringFromChar(arena, hex[(part >> 4) & 0x0F]); - StringFromChar(arena, hex[(part >> 0) & 0x0F]); - result.len += 2; - } - } - } - result.len += StringF(arena, "\n").len; - } - - if (!PP_EqEntKey(ent->parent, PP_RootEntKey)) - { - result.len += StringF(arena, "parent: [%F]\n", FmtUid(ent->parent.uid)).len; - } - - if (!PP_IsNilEntKey(ent->next) || !PP_IsNilEntKey(ent->prev)) - { - result.len += StringF(arena, "prev: [%F]\n", FmtUid(ent->prev.uid)).len; - result.len += StringF(arena, "next: [%F]\n", FmtUid(ent->next.uid)).len; - } - - result.len += StringF(arena, "\n").len; - - /* Pos */ - Xform xf = PP_XformFromEnt(ent); - Vec2 linear_velocity = ent->linear_velocity; - f32 angular_velocity = ent->angular_velocity; - result.len += StringF(arena, "pos: (%F, %F)\n", FmtFloat(xf.og.x), FmtFloat(xf.og.y)).len; - result.len += StringF(arena, "linear velocity: (%F, %F)\n", FmtFloat(linear_velocity.x), FmtFloat(linear_velocity.y)).len; - result.len += StringF(arena, "angular velocity: %F\n", FmtFloat(angular_velocity)).len; - - /* Test */ - result.len += StringF(arena, "collision dir: (%F, %F)\n", FmtFloat(ent->collision_dir.x), FmtFloat(ent->collision_dir.y)).len; - - /* Children */ - if (!PP_IsNilEntKey(ent->first) || !PP_IsNilEntKey(ent->last)) - { - PP_Ent *child = PP_EntFromKey(ss, ent->first); - if (!PP_EqEntKey(ent->first, ent->last) || !child->valid) - { - result.len += StringF(arena, "first child: [%F]\n", FmtUid(ent->first.uid)).len; - result.len += StringF(arena, "last child: [%F]\n", FmtUid(ent->last.uid)).len; - } - while (child->valid) - { - result.len += StringF(arena, "\n---------------------------------\n").len; - result.len += StringF(arena, "CHILD\n").len; - String child_text = PP_DebugStringFromEnt(scratch.arena, child); - result.len += IndentString(arena, child_text, 4).len; - child = PP_EntFromKey(ss, child->next); - } - } - - EndScratch(scratch); - return result; -} - -//////////////////////////////////////////////////////////// -//~ Render buffers - -//- Gbuffer - -GPU_Resource *PP_AcquireGbuffer(GPU_Format format, Vec2I32 size) -{ - __prof; - GPU_ResourceDesc desc = ZI; - desc.kind = GPU_ResourceKind_Texture2D; - desc.flags = GPU_ResourceFlag_Writable | GPU_ResourceFlag_Renderable; - desc.texture.format = format; - desc.texture.size = VEC3I32(size.x, size.y, 1); - return GPU_AcquireResource(desc); -} - -//////////////////////////////////////////////////////////// -//~ Sort entities - -MergesortCompareFuncDef(PP_EntSortCmp, arg_a, arg_b, _) -{ - PP_Ent *a = *(PP_Ent **)arg_a; - PP_Ent *b = *(PP_Ent **)arg_b; - - i32 result = 0; - - if (result == 0) - { - /* Sort by light */ - b32 a_cmp = PP_HasProp(a, PP_Prop_LightTest); - b32 b_cmp = PP_HasProp(b, PP_Prop_LightTest); - result = (a_cmp > b_cmp) - (a_cmp < b_cmp); - } - if (result == 0) - { - /* Sort by layer */ - i32 a_cmp = a->layer; - i32 b_cmp = b->layer; - result = (a_cmp < b_cmp) - (a_cmp > b_cmp); - } - if (result == 0) - { - /* Sort by sprite */ - u64 a_cmp = a->sprite.hash; - u64 b_cmp = b->sprite.hash; - result = (a_cmp < b_cmp) - (a_cmp > b_cmp); - } - if (result == 0) - { - /* Sort by activation */ - u64 a_cmp = a->activation_tick; - u64 b_cmp = b->activation_tick; - result = (a_cmp < b_cmp) - (a_cmp > b_cmp); - } - - return result; -} - -//////////////////////////////////////////////////////////// -//~ User update - -void PP_UpdateUser(void) -{ - __prof; - PP_SharedUserState *g = &PP_shared_user_state; - TempArena scratch = BeginScratchNoConflict(); - - //- Begin UI frame - UI_FrameFlag ui_frame_flags = 0; - ui_frame_flags |= UI_FrameFlag_Debug * !!g->ui_debug; - ui_frame_flags |= UI_FrameFlag_Vsync * !!VSYNC; - UI_Frame ui_frame = UI_BeginFrame(ui_frame_flags); - WND_Frame window_frame = ui_frame.window_frame; - ControllerEventsArray controller_events = window_frame.controller_events; - - g->real_dt_ns = TimeNs() - g->real_time_ns; - g->real_time_ns += g->real_dt_ns; - - //- Restore window - if (g->user_tick == 0) - { - String restore = g->window_restore; - if (restore.len > 0) - { - WND_PushCmd(window_frame, .kind = WND_CmdKind_Restore, .restore = restore); - } - } - else - { - String src = window_frame.restore; - if (src.len > g->window_restore.len) - { - Arena *perm = PermArena(); - g->window_restore = PushString(perm, src); - } - CopyBytes(g->window_restore.text, src.text, src.len); - g->window_restore.len = src.len; - } - - - g->screen_size = window_frame.draw_size; - g->screen_size.x = MaxI32(g->screen_size.x, 1); - g->screen_size.y = MaxI32(g->screen_size.y, 1); - - //- Init render data buffers - if (!g->material_instances_arena) - { - g->material_instances_tbuff = GPU_AcquireTransientBuffer(GPU_QueueKind_Direct, sizeof(PP_MaterialInstance)); - g->grids_tbuff = GPU_AcquireTransientBuffer(GPU_QueueKind_Direct, sizeof(PP_MaterialGrid)); - g->material_instances_arena = AcquireArena(Gibi(64)); - g->grids_arena = AcquireArena(Gibi(64)); - } - - //- Pull latest local sim snapshot - { - __profn("Pull snapshot"); - Lock lock = LockE(&g->local_to_user_client_mutex); - u64 old_last_tick = g->user_unblended_client->last_tick; - u64 last_tick = g->local_to_user_client->last_tick; - if (last_tick > old_last_tick) - { - PP_Snapshot *src = PP_SnapshotFromTick(g->local_to_user_client, last_tick); - PP_AcquireSnapshot(g->user_unblended_client, src, src->tick); - g->last_local_to_user_snapshot_published_at_ns = g->local_to_user_client_publish_time_ns; - g->average_local_to_user_snapshot_publish_dt_ns -= g->average_local_to_user_snapshot_publish_dt_ns / 50; - g->average_local_to_user_snapshot_publish_dt_ns += g->local_to_user_client_publish_dt_ns / 50; - } - Unlock(&lock); - } - - //- Create user world from blended snapshots - { - __profn("Blend snapshots"); - /* Determine how far along are we between sim ticks (0 = start of tick, 1 = end of tick) */ - f64 tick_progress = 0; - i64 next_tick_expected_ns = g->last_local_to_user_snapshot_published_at_ns + g->average_local_to_user_snapshot_publish_dt_ns; - if (next_tick_expected_ns > g->last_local_to_user_snapshot_published_at_ns) - { - tick_progress = (f64)(g->real_time_ns - g->last_local_to_user_snapshot_published_at_ns) / (f64)(next_tick_expected_ns - g->last_local_to_user_snapshot_published_at_ns); - } - - /* Predict local sim time based on average snapshot publish dt. */ - PP_Snapshot *newest_snapshot = PP_SnapshotFromTick(g->user_unblended_client, g->user_unblended_client->last_tick); - g->local_sim_last_known_time_ns = newest_snapshot->sim_time_ns; - g->local_sim_last_known_tick = newest_snapshot->tick; - if (Atomic32Fetch(&g->user_paused)) - { - g->local_sim_predicted_time_ns = g->local_sim_last_known_tick; - } - else - { - g->local_sim_predicted_time_ns = newest_snapshot->sim_time_ns + (newest_snapshot->sim_dt_ns * tick_progress); - } - - if (USER_INTERP_ENABLED && !Atomic32Fetch(&g->user_paused)) - { - /* Determine render time */ - g->render_time_target_ns = g->local_sim_predicted_time_ns - (USER_INTERP_RATIO * g->average_local_to_user_snapshot_publish_dt_ns); - if (g->average_local_to_user_snapshot_publish_dt_ns > 0) - { - /* Increment render time based on average publish dt */ - f64 sim_publish_timescale = (f64)newest_snapshot->sim_dt_ns / (f64)g->average_local_to_user_snapshot_publish_dt_ns; - g->render_time_ns += g->real_dt_ns * sim_publish_timescale; - } - i64 render_time_target_diff_ns = g->render_time_target_ns - g->render_time_ns; - if (render_time_target_diff_ns > NsFromSeconds(0.010) || render_time_target_diff_ns < NsFromSeconds(-0.005)) - { - /* Snap render time if it gets too out of sync with target render time */ - g->render_time_ns = g->render_time_target_ns; - } - - /* Get two snapshots nearest to render time */ - PP_Snapshot *left_snapshot = PP_NilSnapshot(); - PP_Snapshot *right_snapshot = newest_snapshot; - { - PP_Snapshot *ss = PP_SnapshotFromTick(g->user_unblended_client, g->user_unblended_client->first_tick); - while (ss->valid) - { - u64 next_tick = ss->next_tick; - i64 ss_time_ns = ss->sim_time_ns; - if (ss_time_ns < g->render_time_ns && ss_time_ns > left_snapshot->sim_time_ns) - { - left_snapshot = ss; - } - if (ss_time_ns > g->render_time_ns && ss_time_ns < right_snapshot->sim_time_ns) - { - right_snapshot = ss; - } - ss = PP_SnapshotFromTick(g->user_unblended_client, next_tick); - } - } - - /* Create world from blended snapshots */ - if (left_snapshot->valid && right_snapshot->valid) - { - f64 blend = (f64)(g->render_time_ns - left_snapshot->sim_time_ns) / (f64)(right_snapshot->sim_time_ns - left_snapshot->sim_time_ns); - g->ss_blended = PP_AcquireSnapshotFromLerp(g->user_blended_client, left_snapshot, right_snapshot, blend); - } - else if (left_snapshot->valid) - { - g->ss_blended = PP_AcquireSnapshot(g->user_blended_client, left_snapshot, left_snapshot->tick); - } - else if (right_snapshot->valid) - { - g->ss_blended = PP_AcquireSnapshot(g->user_blended_client, right_snapshot, right_snapshot->tick); - } - - /* Release unneeded unblended snapshots */ - if (left_snapshot->tick > 0) - { - PP_ReleaseSnapshotsInRange(g->user_unblended_client, 0, left_snapshot->tick - 1); - } - } - else - { - /* Interp disabled, just copy latest snapshot */ - g->render_time_target_ns = newest_snapshot->sim_time_ns; - g->render_time_ns = newest_snapshot->sim_time_ns; - g->ss_blended = PP_AcquireSnapshot(g->user_blended_client, newest_snapshot, newest_snapshot->tick); - - /* Release unneeded unblended snapshots */ - if (newest_snapshot->tick > 0) - { - PP_ReleaseSnapshotsInRange(g->user_unblended_client, 0, newest_snapshot->tick - 1); - } - } - - /* Release unneeded blended snapshots */ - if (g->ss_blended->tick > 0) - { - PP_ReleaseSnapshotsInRange(g->user_blended_client, 0, g->ss_blended->tick - 1); - PP_ReleaseSnapshotsInRange(g->user_blended_client, g->ss_blended->tick + 1, U64Max); - } - } - - //- Process controller events into user bind state - { - __profn("Process controller events"); - - /* Reset bind pressed / released states */ - for (u32 i = 0; i < countof(g->bind_states); ++i) - { - g->bind_states[i] = (PP_BindState) { - .is_held = g->bind_states[i].is_held - }; - } - - for (u64 idx = 0; idx < controller_events.count; ++idx) - { - ControllerEvent *event = &controller_events.events[idx]; - if (event->kind == ControllerEventKind_Quit) - { - SignalExit(0); - } - - if (event->kind == ControllerEventKind_ButtonUp) - { - /* Escape quit */ - if (event->button == Btn_Esc) - { - SignalExit(0); - } - } - - /* Update mouse pos */ - if (event->kind == ControllerEventKind_CursorMove) - { - g->screen_cursor = Vec2FromFields(event->cursor_pos); - } - - /* Update bind states */ - if ((event->kind == ControllerEventKind_ButtonDown || event->kind == ControllerEventKind_ButtonUp)) - { - Btn button = event->button; - button = button >= Btn_COUNT ? Btn_None : button; - PP_BindKind bind = g_binds[button]; - if (bind) - { - b32 pressed = event->kind == ControllerEventKind_ButtonDown; -#if 0 - b32 out_of_bounds = button >= Btn_M1 && button <= Btn_M5 && - (g->ui_cursor.x < 0 || - g->ui_cursor.y < 0 || - g->ui_cursor.x > g->ui_size.x || - g->ui_cursor.y > g->ui_size.y); -#else - b32 out_of_bounds = 0; -#endif - g->bind_states[bind].is_held = pressed && !out_of_bounds; - if (pressed) - { - if (!out_of_bounds) - { - ++g->bind_states[bind].num_presses_and_repeats; - if (event->is_repeat) - { - ++g->bind_states[bind].num_repeats; - } - else - { - ++g->bind_states[bind].num_presses; - } - } - } - else - { - ++g->bind_states[bind].num_releases; - } - } - } - } - } - - //- Find local entities - PP_Ent *local_player = PP_EntFromKey(g->ss_blended, g->ss_blended->local_player); - PP_Ent *local_control = PP_EntFromKey(g->ss_blended, local_player->player_control_ent); - PP_Ent *local_camera = PP_EntFromKey(g->ss_blended, local_player->player_camera_ent); - - //- Find hovered entity - PP_Ent *hovered_ent = PP_NilEnt(); - { - Xform mouse_xf = XformFromPos(g->world_cursor); - CLD_Shape mouse_shape = ZI; - mouse_shape.points[0] = VEC2(0, 0); - mouse_shape.count = 1; - mouse_shape.radius = 0.01f; - for (u64 ent_index = 0; ent_index < g->ss_blended->num_ents_reserved; ++ent_index) - { - PP_Ent *ent = &g->ss_blended->ents[ent_index]; - if (!PP_IsValidAndActive(ent)) continue; - - CLD_Shape ent_collider = ent->local_collider; - if (ent_collider.count > 0) - { - /* TODO: Can just use boolean GJK */ - Xform ent_xf = PP_XformFromEnt(ent); - CLD_CollisionData collision_result = CLD_CollisionDataFromShapes(&ent_collider, &mouse_shape, ent_xf, mouse_xf); - if (collision_result.num_points > 0) - { - hovered_ent = PP_EntFromKey(g->ss_blended, ent->top); - break; - } - } - } - } - - //- Update user state from binds - { - if (g->bind_states[PP_BindKind_Fullscreen].num_presses && g->bind_states[PP_BindKind_FullscreenMod].is_held) - { - WND_PushCmd(window_frame, .kind = WND_CmdKind_SetFullscreen, .v = !window_frame.fullscreen); - } - } - - if (g->bind_states[PP_BindKind_DebugDraw].num_presses > 0) - { - g->debug_draw = !g->debug_draw; - } - - if (g->bind_states[PP_BindKind_DebugToggleTopmost].num_presses > 0) - { - WND_PushCmd(window_frame, .kind = WND_CmdKind_SetForcedTop, .v = !window_frame.forced_top); - LogSuccessF("Toggle topmost"); - } - - if (g->bind_states[PP_BindKind_DebugConsole].num_presses > 0) - { - g->debug_console = !g->debug_console; - } - - if (g->bind_states[PP_BindKind_DebugCamera].num_presses > 0) - { - g->debug_camera = !g->debug_camera; - } - - if (g->bind_states[PP_BindKind_DebugUi].num_presses > 0) - { - g->ui_debug = !g->ui_debug; - } - - if (g->bind_states[PP_BindKind_DebugLister].num_presses > 0) - { - g->lister_active = !g->lister_active; - } - - { - if (g->bind_states[PP_BindKind_DebugFollow].num_presses > 0) - { - if (PP_IsNilEntKey(g->debug_following)) - { - g->debug_following = hovered_ent->key; - } - else - { - g->debug_following = PP_NilEntKey; - } - } - if (!PP_IsNilEntKey(g->debug_following)) - { - PP_Ent *follow_ent = PP_EntFromKey(g->ss_blended, g->debug_following); - PP_Ent *follow_camera = PP_NilEnt(); - for (u64 i = 0; i < g->ss_blended->num_ents_reserved; ++i) - { - PP_Ent *ent = &g->ss_blended->ents[i]; - PP_Ent *ent_camera_follow = PP_EntFromKey(g->ss_blended, ent->camera_follow); - if (ent_camera_follow->valid && ent_camera_follow == follow_ent) - { - follow_camera = ent; - break; - } - } - if (follow_camera->valid) - { - local_camera = follow_camera; - } - else - { - g->debug_following = PP_NilEntKey; - } - } - } - - //- Apply shake - for (u64 ent_index = 0; ent_index < g->ss_blended->num_ents_reserved; ++ent_index) - { - PP_Ent *ent = &g->ss_blended->ents[ent_index]; - if (!PP_IsValidAndActive(ent)) continue; - - /* How much time between camera shakes */ - i64 frequency_ns = NsFromSeconds(0.01f); - f32 shake = ent->shake; - if (shake > 0) - { - u64 angle_seed0 = ent->key.uid.lo + (u64)(g->ss_blended->sim_time_ns / frequency_ns); - u64 angle_seed1 = angle_seed0 + 1; - f32 angle0 = RandF64FromSeed(angle_seed0, 0, Tau); - f32 angle1 = RandF64FromSeed(angle_seed1, 0, Tau); - - Vec2 vec0 = Vec2WithLen(Vec2FromAngle(angle0), shake); - /* NOTE: vec1 not completely accurate since shake can change between frames, it's just a prediction */ - Vec2 vec1 = Vec2WithLen(Vec2FromAngle(angle1), shake); - - /* TODO: Cubic interp? */ - f32 blend = (f32)(g->ss_blended->sim_time_ns % frequency_ns) / (f32)frequency_ns; - Vec2 vec = LerpVec2(vec0, vec1, blend); - - Xform xf = PP_XformFromEnt(ent); - xf.og = AddVec2(xf.og, MulVec2(vec, shake)); - PP_SetXform(ent, xf); - } - } - - //- Update ui to screen xform from screen size - if (g->debug_camera) - { - g->ui_size = g->screen_size; - g->ui_to_screen_xf = XformIdentity; - g->ui_to_screen_xf.og = RoundVec2(g->ui_to_screen_xf.og); - } - else - { - /* Determine ui size by camera & window dimensions */ - f32 aspect_ratio = (f32)(DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT); - if (local_camera->valid) - { - Xform quad_xf = MulXform(PP_XformFromEnt(local_camera), local_camera->camera_quad_xform); - Vec2 camera_size = ScaleFromXform(quad_xf); - if (!IsVec2Zero(camera_size)) - { - aspect_ratio = camera_size.x / camera_size.y; - } - } - f32 width = g->screen_size.x; - f32 height = g->screen_size.y; - if (width / height > aspect_ratio) - { - width = height * aspect_ratio; - } - else - { - height = CeilF32(width / aspect_ratio); - } - g->ui_size = VEC2I32(width, height); - - /* Center ui in window */ - f32 x = RoundF32(g->screen_size.x / 2 - width / 2); - f32 y = RoundF32(g->screen_size.y / 2 - height / 2); - g->ui_to_screen_xf = XformFromTrs(TRS(.t = VEC2(x, y))); - g->ui_to_screen_xf.og = RoundVec2(g->ui_to_screen_xf.og); - } - - g->ui_cursor = MulXformV2(InvertXform(g->ui_to_screen_xf), g->screen_cursor); - - UI_Box *pp_root_box = 0; - { - UI_PushCP(UI_BuildRow(UI_NilKey)); - { - UI_BuildSpacer(UI_FILL(1, 0)); - { - UI_SetNext(Width, UI_PIX(g->ui_size.x, 1)); - UI_PushCP(UI_BuildColumn(UI_NilKey)); - { - UI_BuildSpacer(UI_FILL(1, 0)); - { - if (window_frame.forced_top) - { - UI_SetNext(Border, 10); - UI_SetNext(BorderColor, Rgba32F(1, 0, 0, 0.5)); - } - UI_SetNext(ChildLayoutAxis, Axis_Y); - UI_SetNext(Height, UI_PIX(g->ui_size.y, 1)); - pp_root_box = UI_BuildBox(UI_KeyF("pp root")); - } - UI_BuildSpacer(UI_FILL(1, 0)); - } - UI_PopCP(); - } - UI_BuildSpacer(UI_FILL(1, 0)); - } - UI_PopCP(); - } - PP_PushGameUiStyle(); - UI_Push(Parent, pp_root_box); - - //- Update world to ui xform from camera - if (g->debug_camera) - { - g->world_to_ui_xf = XformWithWorldRotation(g->world_to_ui_xf, 0); - - Vec2 world_cursor = InvertXformMulV2(g->world_to_ui_xf, g->ui_cursor); - - /* Pan view */ - if (g->bind_states[PP_BindKind_Pan].is_held) - { - if (!g->debug_camera_panning) - { - g->debug_camera_pan_start = world_cursor; - g->debug_camera_panning = 1; - } - Vec2 offset = NegVec2(SubVec2(g->debug_camera_pan_start, world_cursor)); - g->world_to_ui_xf = TranslateXform(g->world_to_ui_xf, offset); - world_cursor = InvertXformMulV2(g->world_to_ui_xf, g->ui_cursor); - g->debug_camera_pan_start = world_cursor; - } - else - { - g->debug_camera_panning = 0; - } - - /* Zoom view */ - i32 input_zooms = g->bind_states[PP_BindKind_ZoomIn].num_presses - g->bind_states[PP_BindKind_ZoomOut].num_presses; - if (input_zooms != 0) - { - /* Zoom to cursor */ - f32 zoom_rate = 2; - f32 zoom = PowF32(zoom_rate, input_zooms); - g->world_to_ui_xf = TranslateXform(g->world_to_ui_xf, world_cursor); - g->world_to_ui_xf = ScaleXform(g->world_to_ui_xf, VEC2(zoom, zoom)); - g->world_to_ui_xf = TranslateXform(g->world_to_ui_xf, NegVec2(world_cursor)); - } - g->world_to_ui_xf.og = RoundVec2(g->world_to_ui_xf.og); - } - else - { - Xform xf = PP_XformFromEnt(local_camera); - - Vec2 world_center = xf.og; - f32 rot = RotationFromXform(xf); - - /* Scale view into viewport based on camera size */ - Vec2 scale = VEC2(g->ui_size.x, g->ui_size.y); - { - Xform quad_xf = MulXform(xf, local_camera->camera_quad_xform); - Vec2 camera_size = ScaleFromXform(quad_xf); - if (!IsVec2Zero(camera_size)) - { - scale = DivVec2Vec2(scale, camera_size); - } - } - scale.x = MinF32(scale.x, scale.y); - scale.y = scale.x; - - Vec2 ui_center = MulVec2(VEC2(g->ui_size.x, g->ui_size.y), 0.5); - Trs trs = TRS(.t = SubVec2(ui_center, world_center), .r = rot, .s = scale); - Vec2 pivot = world_center; - g->world_to_ui_xf = XformIdentity; - g->world_to_ui_xf = TranslateXform(g->world_to_ui_xf, pivot); - g->world_to_ui_xf = TranslateXform(g->world_to_ui_xf, trs.t); - g->world_to_ui_xf = RotateXform(g->world_to_ui_xf, trs.r); - g->world_to_ui_xf = ScaleXform(g->world_to_ui_xf, trs.s); - g->world_to_ui_xf = TranslateXform(g->world_to_ui_xf, NegVec2(pivot)); - g->world_to_ui_xf.og = RoundVec2(g->world_to_ui_xf.og); - } - - g->world_cursor = InvertXformMulV2(g->world_to_ui_xf, g->ui_cursor); - - //- Update world to render xform from world to ui xform - - b32 effects_disabled = 0; - // b32 effects_disabled = 1; - g->render_size = RoundVec2ToVec2I32(VEC2(RENDER_WIDTH, RENDER_HEIGHT)); - - if (g->debug_camera) - { - g->render_size = g->ui_size; - effects_disabled = 1; - g->world_to_render_xf = g->world_to_ui_xf; - } - else - { - Xform ui_to_world_xf = InvertXform(g->world_to_ui_xf); - Vec2 world_center = MulXformV2(ui_to_world_xf, MulVec2(VEC2(g->ui_size.x, g->ui_size.y), 0.5)); - - Vec2 scale = VEC2(PIXELS_PER_UNIT, PIXELS_PER_UNIT); - - Xform xf = XformIdentity; - - xf = TranslateXform(xf, MulVec2(VEC2(g->render_size.x, g->render_size.y), 0.5)); - - xf = ScaleXform(xf, scale); - xf = TranslateXform(xf, MulVec2(world_center, -1)); - xf.og = RoundVec2(xf.og); - - g->world_to_render_xf = xf; - } - - //- Update render to ui xform - { - Xform world_to_ui_xf = g->world_to_ui_xf; - Xform world_to_render_xf = g->world_to_render_xf; - Xform render_to_world_xf = InvertXform(world_to_render_xf); - Xform render_to_ui_xf = MulXform(world_to_ui_xf, render_to_world_xf); - g->render_to_ui_xf = render_to_ui_xf; - } - - //- Update listener from view - { - Vec2 up = VEC2(0, -1); - Vec2 ui_center = MulVec2(VEC2(g->ui_size.x, g->ui_size.y), 0.5f); - Vec2 listener_pos = InvertXformMulV2(g->world_to_ui_xf, ui_center); - Vec2 listener_dir = NormVec2(InvertXformBasisMulV2(g->world_to_ui_xf, up)); - MIX_UpdateListener(listener_pos, listener_dir); - } - - //- Draw grid - { - f32 thickness = 2; - - Vec2 offset = NegVec2(MulXformV2(g->world_to_render_xf, VEC2(0, 0))); - f32 spacing = ScaleFromXform(g->world_to_render_xf).x; - - Vec2 pos = InvertXformMulV2(g->world_to_render_xf, VEC2(0, 0)); - Vec2 size = InvertXformBasisMulV2(g->world_to_render_xf, VEC2(g->render_size.x, g->render_size.y)); - u32 color0 = Rgb32F(0.17f, 0.17f, 0.17f); - u32 color1 = Rgb32F(0.15f, 0.15f, 0.15f); - - PP_MaterialGrid *grid = PushStruct(g->grids_arena, PP_MaterialGrid); - *grid = PP_DefaultMaterialGrid; - grid->line_thickness = thickness; - grid->line_spacing = spacing; - grid->offset = offset; - grid->bg0_srgb = color0; - grid->bg1_srgb = color1; - grid->line_srgb = Rgb32(0x3f, 0x3f, 0x3f); - grid->x_srgb = Color_Red; - grid->y_srgb = Color_Green; - - PP_MaterialInstance *mat = PushStruct(g->material_instances_arena, PP_MaterialInstance); - *mat = PP_DefaultMaterialInstance; - mat->grid_id = grid - (PP_MaterialGrid *)ArenaBase(g->grids_arena); - mat->xf = XformFromRect(RectFromVec2(pos, size)); - } - - //- Sort drawable entities - PP_Ent **sorted = PushDry(scratch.arena, PP_Ent *); - u64 sorted_count = 0; - { - /* Copy valid entities */ - { - __profn("Build ents list for sorting"); - for (u64 ent_index = 0; ent_index < g->ss_blended->num_ents_reserved; ++ent_index) - { - PP_Ent *ent = &g->ss_blended->ents[ent_index]; - if (PP_IsValidAndActive(ent)) - { - *PushStructNoZero(scratch.arena, PP_Ent *) = ent; - ++sorted_count; - } - } - } - /* Sort */ - { - __profn("Sort ents"); - Mergesort(sorted, sorted_count, sizeof(*sorted), PP_EntSortCmp, 0); - } - } - - //- Draw entities - { - __profn("Draw entities"); - for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) - { - PP_Ent *ent = sorted[sorted_index]; - if (!PP_IsValidAndActive(ent)) continue; - //if (SPR_IsNil(ent->sprite)) continue; - - ResourceKey sprite = ent->sprite; - - PP_Ent *parent = PP_EntFromKey(g->ss_blended, ent->parent); - - Xform xf = PP_XformFromEnt(ent); - UNUSED Xform parent_xf = PP_XformFromEnt(parent); - - b32 skip_debug_draw = !g->debug_camera && ent == local_camera; - skip_debug_draw = skip_debug_draw || PP_HasProp(ent, PP_Prop_MotorJoint); - - b32 skip_debug_draw_transform = PP_HasProp(ent, PP_Prop_Camera); - skip_debug_draw_transform = 1; - - UNUSED Xform sprite_xform = MulXform(xf, ent->sprite_local_xform); - - /* Draw tracer */ - /* TODO: Enable this */ -#if 0 - if (PP_HasProp(ent, PP_Prop_Tracer)) - { - Vec2 velocity = ent->tracer_start_velocity; - - Vec2 a = ent->tracer_start; - Vec2 b = xf.og; - Vec2 c = ent->tracer_gradient_start; - Vec2 d = ent->tracer_gradient_end; - - Vec2 vcd = SubVec2(d, c); - Vec2 vca = SubVec2(a, c); - Vec2 vdb = SubVec2(b, d); - Vec2 vdc = NegVec2(vcd); - - f32 opacity_a = 1; - f32 opacity_b = 1; - if (Vec2LenSq(vcd) != 0) - { - if (DotVec2(velocity, vca) <= 0) - { - a = c; - opacity_a = 0; - } - else - { - opacity_a = DotVec2(vcd, vca) / Vec2LenSq(vcd); - } - opacity_a = ClampF32(opacity_a, 0, 1); - opacity_b = ClampF32(1.f - (DotVec2(vdc, vdb) / Vec2LenSq(vdc)), 0, 1); - } - - f32 thickness = 0.01f; - u32 color_start = Rgba32F(1, 0.5, 0, opacity_a); - u32 color_end = Rgba32F(1, 0.8, 0.4, opacity_b); - - if (opacity_b > 0.99f) - { - D_DrawCircle(g->render_sig, b, thickness / 2, color_end, 20); - } - D_DrawLineGradient(g->render_sig, a, b, thickness, color_start, color_end); - } -#endif - - /* Draw sprite */ - if (!IsResourceNil(sprite)) - { - SPR_Sheet *sheet = SPR_SheetFromResourceAsync(sprite); - SPR_Texture *texture = SPR_TextureFromResourceAsync(sprite); - /* TODO: Fade in placeholder if texture isn't loaded */ - if (sheet->loaded && texture->loaded) - { - b32 is_light = PP_HasProp(ent, PP_Prop_LightTest); - Vec3 emittance = ent->sprite_emittance; - u32 tint = ent->sprite_tint; - SPR_Frame frame = SPR_FrameFromIndex(sheet, ent->animation_frame); - PP_MaterialInstance *mat = PushStruct(g->material_instances_arena, PP_MaterialInstance); - *mat = PP_DefaultMaterialInstance; - mat->xf = sprite_xform; - mat->tex = GPU_Texture2DRidFromResource(texture->gpu_texture); - mat->tint_srgb = tint; - mat->tex_uv0 = frame.clip.p0; - mat->tex_uv1 = frame.clip.p1; - mat->is_light = is_light; - mat->light_emittance_srgb = emittance; - } - } - - /* Draw tiles */ - /* TODO: Something better */ - if (PP_HasProp(ent, PP_Prop_TileChunk)) - { - Vec2I32 chunk_index = ent->tile_chunk_index; - ResourceKey tile_sprite = ResourceKeyFromStore(&PP_Resources, Lit("sprite/tile.ase")); - SPR_Texture *tile_texture = SPR_TextureFromResourceAsync(tile_sprite); - if (tile_texture->loaded) - { - f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT; - for (i32 tile_y = 0; tile_y < SIM_TILES_PER_CHUNK_SQRT; ++tile_y) - { - for (i32 tile_x = 0; tile_x < SIM_TILES_PER_CHUNK_SQRT; ++tile_x) - { - Vec2I32 local_tile_index = VEC2I32(tile_x, tile_y); - PP_TileKind tile = ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)]; - /* FIXME: Enable this */ - //if (tile > -1) - if (tile == PP_TileKind_Wall) - { - Vec2I32 world_tile_index = PP_WorldTileIndexFromLocalTileIndex(chunk_index, local_tile_index); - Vec2 pos = PP_PosFromWorldTileIndex(world_tile_index); - Xform tile_xf = XformFromRect(RectFromVec2(pos, VEC2(tile_size, tile_size))); - PP_MaterialInstance *mat = PushStruct(g->material_instances_arena, PP_MaterialInstance); - *mat = PP_DefaultMaterialInstance; - mat->xf = tile_xf; - mat->tex = GPU_Texture2DRidFromResource(tile_texture->gpu_texture); - mat->is_light = 1; - mat->light_emittance_srgb = VEC3(0, 0, 0); - } - } - } - } - } - - /* Debug draw entity info */ - if (g->debug_draw && !skip_debug_draw) - { - TempArena temp = BeginTempArena(scratch.arena); - - if (PP_HasProp(ent, PP_Prop_Kinematic) || PP_HasProp(ent, PP_Prop_Dynamic)) - { - PP_DrawDebugMovement(ent); - } - - /* Draw xform */ - if (!skip_debug_draw_transform) - { - u32 color_x = Rgba32F(1, 0, 0, 0.5); - u32 color_y = Rgba32F(0, 1, 0, 0.5); - PP_DrawDebugXform(xf, color_x, color_y); - } - - /* Draw AABB */ - /* FIXME: Enable this */ -#if 0 - if (ent->local_collider.count > 0) - { - Aabb aabb = CLD_AabbFromShape(&ent->local_collider, xf); - f32 thickness = 1; - u32 color = Rgba32F(1, 0, 1, 0.5); - Quad quad = QuadFromAabb(aabb); - quad = MulXformQuad(g->world_to_ui_xf, quad); - D_DrawQuadLine(g->render_sig, quad, thickness, color); - } - - /* Draw focus arrow */ - if (ent == local_control || PP_EqEntKey(ent->key, g->debug_following)) - { - SPR_Sheet *sheet = SPR_SheetFromResourceAsync(ent->sprite); - SPR_Slice slice = SPR_SliceFromNameIndex(sheet, Lit("attach.wep"), ent->animation_frame); - Vec2 start = MulXformV2(sprite_xform, slice.center); - start = MulXformV2(g->world_to_ui_xf, start); - Vec2 end = AddVec2(xf.og, ent->control.focus); - end = MulXformV2(g->world_to_ui_xf, end); - D_DrawArrowLine(g->render_sig, start, end, 3, 10, Rgba32F(1, 1, 1, 0.5)); - } -#endif - -#if 0 - /* Draw slices */ - if (!SPR_IsNil(ent->sprite)) - { - SPR_Sheet *sheet = SPR_SheetFromResourceAsync(sprite); - - u32 quad_color = Rgba32F(1, 0, 0.5, 1); - u32 point_color = Rgba32F(1, 0, 0, 1); - u32 ray_color = Rgba32F(1, 0, 0.5, 1); - - for (u64 i = 0; i < sheet->slice_groups_count; ++i) - { - SPR_SheetSliceGroup *group = &sheet->slice_groups[i]; - if (StringEndsWith(group->name, Lit(".ray"))) continue; - - for (u32 j = 0; j < group->per_frame_count; ++j) - { - SPR_Slice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j]; - - Vec2 center = MulXformV2(sprite_xform, slice.center); - center = MulXformV2(g->world_to_ui_xf, center); - - if (!slice.has_ray) - { - Quad quad = QuadFromRect(slice.rect); - quad = MulXformQuad(sprite_xform, quad); - quad = MulXformQuad(g->world_to_ui_xf, quad); - D_DrawQuadLine(g->render_sig, quad, 2, quad_color); - } - - D_DrawCircle(g->render_sig, center, 3, point_color, 20); - - if (slice.has_ray) - { - Vec2 ray = MulXformBasisV2(sprite_xform, slice.dir); - ray = MulXformBasisV2(g->world_to_ui_xf, ray); - ray = Vec2WithLen(ray, 25); - D_DrawArrowRay(g->render_sig, center, ray, 2, 10, ray_color); - } - } - } - } -#endif - - /* Draw weld joint */ -#if 0 - if (PP_HasProp(ent, PP_Prop_WeldJoint)) - { - PP_Ent *e1 = PP_EntFromKey(g->ss_blended, ent->weld_joint_data.e1); - Xform e1_xf = PP_XformFromEnt(e1); - - u32 color = Color_Yellow; - f32 radius = 3; - Vec2 point = MulXformV2(e1_xf, ent->weld_joint_data.point_local_e1); - point = MulXformV2(g->world_to_ui_xf, point); - D_DrawCircle(g->render_sig, point, radius, color, 10); - - DEBUGBREAKABLE; - } -#endif - - /* Draw mouse joint */ - /* FIXME: Enable this */ -#if 0 - if (PP_HasProp(ent, PP_Prop_MouseJoint)) - { - PP_Ent *target = PP_EntFromKey(g->ss_blended, ent->mouse_joint_data.target); - Xform target_xf = PP_XformFromEnt(target); - u32 color = Color_White; - Vec2 point_start = MulXformV2(target_xf, ent->mouse_joint_data.point_local_start); - Vec2 point_end = g->world_cursor; - point_start = MulXformV2(g->world_to_ui_xf, point_start); - point_end = MulXformV2(g->world_to_ui_xf, point_end); - D_DrawArrowLine(g->render_sig, point_start, point_end, 3, 10, color); - D_DrawCircle(g->render_sig, point_start, 4, color, 10); - } -#endif - - /* Draw collider */ - /* FIXME: Enable this */ -#if 0 - if (ent->local_collider.count > 0) - { - CLD_Shape collider = ent->local_collider; - u32 color = Rgba32F(1, 1, 0, 0.5); - f32 thickness = 2; - { - /* Draw collider using support points */ - u32 detail = 32; - Xform collider_draw_xf = MulXform(g->world_to_ui_xf, xf); - D_DrawColliderLine(g->render_sig, collider, collider_draw_xf, thickness, color, detail); - } - { - /* Draw collider shape points */ - for (u32 i = 0; i < collider.count; ++i) - { - Vec2 p = MulXformV2(MulXform(g->world_to_ui_xf, xf), collider.points[i]); - D_DrawCircle(g->render_sig, p, 3, Color_Blue, 10); - } - } - if (collider.count == 1 && collider.radius > 0) - { - /* Draw upwards line for circle */ - Vec2 start = xf.og; - Vec2 end = CLD_SupportPointFromDir(&collider, xf, NegVec2(xf.by)).p; - start = MulXformV2(g->world_to_ui_xf, start); - end = MulXformV2(g->world_to_ui_xf, end); - D_DrawLine(g->render_sig, start, end, thickness, color); - } -#if 0 - /* Draw support point at focus dir */ - { - Vec2 p = collider_support_point(&collider, xf, ent->control.focus); - p = MulXformV2(g->world_to_ui_xf, p); - D_DrawCircle(g->render_sig, p, 3, Color_Red, 10); - } -#endif - } -#endif - - /* Draw contact constraint */ - /* FIXME: Enable this */ -#if 0 - if (PP_HasProp(ent, PP_Prop_ContactConstraint)) - { - ContactConstraint *data = &ent->contact_constraint_data; - PP_Ent *e0 = PP_EntFromKey(g->ss_blended, data->e0); - PP_Ent *e1 = PP_EntFromKey(g->ss_blended, data->e1); - LAX e0; - LAX e1; - -#if IsDeveloperModeEnabled - /* Draw contact points */ - { - f32 radius = 5; - for (u32 i = 0; i < data->num_points; ++i) - { - u32 color = (data->skip_solve || data->wrong_dir) ? Alpha32F(Color_Yellow, 0.3) : Rgba32F(0.8, 0.2, 0.2, 1); - ContactPoint point = data->points[i]; - Vec2 dbg_pt = point.dbg_pt; - - /* Draw point */ - { - D_DrawCircle(g->render_sig, MulXformV2(g->world_to_ui_xf, dbg_pt), radius, color, 10); - } - - /* Draw normal */ - { - f32 len = 0.1f; - f32 arrow_thickness = 2; - f32 arrow_height = 5; - Vec2 start = MulXformV2(g->world_to_ui_xf, dbg_pt); - Vec2 end = MulXformV2(g->world_to_ui_xf, AddVec2(dbg_pt, MulVec2(NormVec2(data->normal), len))); - D_DrawArrowLine(g->render_sig, start, end, arrow_thickness, arrow_height, color); - } -#if 0 - /* Draw contact info */ - { - F_Font *disp_font = F_LoadFontAsync(ResourceKeyFromStore(&PP_Resources, Lit("font/fixedsys.ttf")), 12.0f); - if (disp_font) - { - f32 offset_px = 10; - - String fmt = Lit( - "e0 index: %F\n" - "e1 index: %F\n" - "key: 0x%F\n" - "impulse (n): %F\n" - "impulse (t): %F\n" - "separation: %F\n" - "normal: (%F, %F)\n" - "num contacts: %F" - ); - String text = StringF( - temp.arena, fmt, - FmtUint(e0->key.idx), - FmtUint(e1->key.idx), - FmtHex(point.key), - FmtFloat(point.normal_impulse), - FmtFloat(point.tangent_impulse), - FmtFloatP(point.starting_separation, 6), - FmtFloatP(data->normal.x, 6), FmtFloatP(data->normal.y, 6), - FmtUint(data->num_points) - ); - - draw_text(g->render_sig, disp_font, AddVec2(RoundVec2(MulXformV2(g->world_to_ui_xf, dbg_pt)), VEC2(0, offset_px)), text); - } - } -#endif - } - } -#endif - } -#endif - - /* Draw collision debug */ -#if COLLIDER_DEBUG - if (PP_HasProp(ent, PP_Prop_CollisionDebug)) - { - ContactDebugData *data = &ent->collision_debug_data; - CLD_CollisionData collision_reuslt = data->collision_result; - PP_Ent *e0 = PP_EntFromKey(g->ss_blended, data->e0); - PP_Ent *e1 = PP_EntFromKey(g->ss_blended, data->e1); - CLD_Shape e0_collider = e0->local_collider; - CLD_Shape e1_collider = e1->local_collider; - LAX e0_collider; - LAX e1_collider; - - /* Draw closest points */ -#if 0 - { - f32 radius = 4; - u32 color = Rgba32F(1, 1, 0, 0.5); - Vec2 a = MulXformV2(g->world_to_ui_xf, data->closest0); - Vec2 b = MulXformV2(g->world_to_ui_xf, data->closest1); - D_DrawCircle(g->render_sig, a, radius, color, 10); - D_DrawCircle(g->render_sig, b, radius, color, 10); - } -#endif - - /* Draw clipping */ - { - f32 thickness = 4; - f32 radius = 4; - u32 color_line = Rgba32F(1, 0, 1, 0.75); - u32 color_a = Rgba32F(1, 0, 0, 0.25); - u32 color_b = Rgba32F(0, 1, 0, 0.25); - u32 color_line_clipped = Rgba32F(1, 0, 1, 1); - u32 color_a_clipped = Rgba32F(1, 0, 0, 1); - u32 color_b_clipped = Rgba32F(0, 1, 0, 1); - { - Vec2 a = MulXformV2(g->world_to_ui_xf, collision_reuslt.a0); - Vec2 b = MulXformV2(g->world_to_ui_xf, collision_reuslt.b0); - D_DrawLine(g->render_sig, a, b, thickness, color_line); - D_DrawCircle(g->render_sig, a, radius, color_a, 10); - D_DrawCircle(g->render_sig, b, radius, color_b, 10); - - Vec2 a_clipped = MulXformV2(g->world_to_ui_xf, collision_reuslt.a0_clipped); - Vec2 b_clipped = MulXformV2(g->world_to_ui_xf, collision_reuslt.b0_clipped); - D_DrawLine(g->render_sig, a_clipped, b_clipped, thickness, color_line_clipped); - D_DrawCircle(g->render_sig, a_clipped, radius, color_a_clipped, 10); - D_DrawCircle(g->render_sig, b_clipped, radius, color_b_clipped, 10); - } - { - Vec2 a = MulXformV2(g->world_to_ui_xf, collision_reuslt.a1); - Vec2 b = MulXformV2(g->world_to_ui_xf, collision_reuslt.b1); - D_DrawLine(g->render_sig, a, b, thickness, color_line); - D_DrawCircle(g->render_sig, a, radius, color_a, 10); - D_DrawCircle(g->render_sig, b, radius, color_b, 10); - - Vec2 a_clipped = MulXformV2(g->world_to_ui_xf, collision_reuslt.a1_clipped); - Vec2 b_clipped = MulXformV2(g->world_to_ui_xf, collision_reuslt.b1_clipped); - D_DrawLine(g->render_sig, a_clipped, b_clipped, thickness, color_line_clipped); - D_DrawCircle(g->render_sig, a_clipped, radius, color_a_clipped, 10); - D_DrawCircle(g->render_sig, b_clipped, radius, color_b_clipped, 10); - } - } - -#if COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI - Xform e0_xf = data->xf0; - Xform e1_xf = data->xf1; - -#if 0 - /* Only draw points with large separation */ - b32 should_draw = 0; - for (u32 i = 0; i < data->num_points; ++i) - { - if (data->points[i].starting_separation < -0.1) - { - should_draw = 1; - break; - } - } -#else - b32 should_draw = 1; -#endif - - if (should_draw) - { -#if 0 - /* Test info */ - { - F_Font *disp_font = F_LoadFontAsync(ResourceKeyFromStore(&PP_Resources, Lit("font/fixedsys.ttf")), 12.0f); - if (disp_font) - { - f32 offset_px = 10; - String fmt = Lit( - "e0 pos: (%F, %F)\n" - "e0 rot: %F\n" - "e1 pos: (%F, %F)\n" - "e1 rot: %F\n" - ); - String text = StringF( - temp.arena, fmt, - FmtFloatP(e0_xf.og.x, 24), FmtFloatP(e0_xf.og.y, 24), - FmtFloatP(RotationFromXform(e0_xf), 24), - FmtFloatP(e1_xf.og.x, 24), FmtFloatP(e1_xf.og.y, 24), - FmtFloatP(RotationFromXform(e1_xf), 24) - ); - - draw_text(g->render_sig, disp_font, AddVec2(RoundVec2(MulXformV2(g->world_to_ui_xf, VEC2(0, 0))), VEC2(0, offset_px)), text); - } - } -#endif - - /* Draw CLD_Menkowski */ - { - - u32 color = collision_reuslt.solved ? Rgba32F(0, 0, 0.25, 1) : Rgba32F(0, 0.25, 0.25, 1); - f32 thickness = 2; - u32 detail = 512; - LAX thickness; - - Vec2Array m = CLD_Menkowski(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf, detail); - - for (u64 i = 0; i < m.count; ++i) m.points[i] = MulXformV2(g->world_to_ui_xf, m.points[i]); - D_DrawPolyLine(g->render_sig, m, 1, thickness, color); - //D_DrawPoly(g->render_sig, m, color); - } - - /* Draw CLD_PointCloud */ - { - u32 color = Rgba32F(1, 1, 1, 1); - f32 radius = 2; - - Vec2Array m = CLD_PointCloud(temp.arena, &e0_collider, &e1_collider, e0_xf, e1_xf); - - for (u64 i = 0; i < m.count; ++i) - { - Vec2 p = MulXformV2(g->world_to_ui_xf, m.points[i]); - D_DrawCircle(g->render_sig, p, radius, color, 10); - } - } - - /* Draw prototype */ - { - f32 thickness = 2; - u32 color = Rgba32F(1, 1, 1, 0.25); - - Vec2Array m = { - .points = collision_reuslt.prototype.points, - .count = collision_reuslt.prototype.len - }; - for (u64 i = 0; i < m.count; ++i) m.points[i] = MulXformV2(g->world_to_ui_xf, m.points[i]); - D_DrawPolyLine(g->render_sig, m, 1, thickness, color); - for (u64 i = 0; i < m.count; ++i) D_DrawCircle(g->render_sig, m.points[i], 10, color, 10); - } - - /* Draw simplex */ - { - f32 thickness = 2; - u32 line_color = Color_Yellow; - u32 color_first = Rgba32F(1, 0, 0, 0.75); - u32 color_second = Rgba32F(0, 1, 0, 0.75); - u32 color_third = Rgba32F(0, 0, 1, 0.75); - - CLD_MenkowskiSimplex simplex = collision_reuslt.simplex; - Vec2 simplex_points[] = { simplex.a.p, simplex.b.p, simplex.c.p }; - for (u64 i = 0; i < countof(simplex_points); ++i) simplex_points[i] = MulXformV2(g->world_to_ui_xf, simplex_points[i]); - Vec2Array simplex_array = { .count = simplex.len, .points = simplex_points }; - - if (simplex.len >= 1) - { - u32 color = simplex.len == 1 ? color_first : (simplex.len == 2 ? color_second : color_third); - D_DrawCircle(g->render_sig, simplex_array.points[0], thickness * 3, color, 10); - } - if (simplex.len >= 2) - { - u32 color = simplex.len == 2 ? color_first : color_second; - D_DrawCircle(g->render_sig, simplex_array.points[1], thickness * 3, color, 10); - } - if (simplex.len >= 3) - { - u32 color = color_first; - D_DrawCircle(g->render_sig, simplex_array.points[2], thickness * 3, color, 10); - } - if (simplex.len >= 2) - { - D_DrawPolyLine(g->render_sig, simplex_array, simplex.len > 2, thickness, line_color); - } - } - - /* Draw normal */ - { - u32 color = Color_White; - f32 len = 0.1f; - f32 arrow_thickness = 4; - f32 arrowhead_height = 10; - Vec2 start = MulXformV2(g->world_to_ui_xf, VEC2(0, 0)); - Vec2 end = MulXformV2(g->world_to_ui_xf, MulVec2(NormVec2(collision_reuslt.normal), len)); - D_DrawArrowLine(g->render_sig, start, end, arrow_thickness, arrowhead_height, color); - } - } - #endif - } - #endif - - /* Draw hierarchy */ - /* FIXME: Enable this */ -#if 0 - if (PP_HasProp(parent, PP_Prop_Active) && !parent->is_root) - { - u32 color = Rgba32F(0.6, 0.6, 1, 0.75); - f32 thickness = 2; - f32 arrow_height = 15; - - Vec2 start = MulXformV2(g->world_to_ui_xf, xf.og); - Vec2 end = MulXformV2(g->world_to_ui_xf, parent_xf.og); - D_DrawArrowLine(g->render_sig, start, end, thickness, arrow_height, color); - } - - /* Draw camera rect */ - if (PP_HasProp(ent, PP_Prop_Camera)) - { - u32 color = ent == local_camera ? Rgba32F(1, 1, 1, 0.5) : Rgba32F(0, 0.75, 0, 0.5); - f32 thickness = 3; - - Xform quad_xf = MulXform(xf, ent->camera_quad_xform); - Quad quad = MulXformQuad(quad_xf, CenteredUnitSquareQuad); - quad = MulXformQuad(g->world_to_ui_xf, quad); - - D_DrawQuadLine(g->render_sig, quad, thickness, color); - } -#endif - - EndTempArena(temp); - } - } - } - - /* Draw crosshair or show cursor */ - /* FIXME: Enable this */ - #if 0 - if (!g->debug_camera) - { - __profn("Draw crosshair"); - Vec2 crosshair_pos = g->ui_cursor; - ResourceKey crosshair = ResourceKeyFromStore(PP_Resources, Lit("sprite/crosshair.ase")); - SPR_Texture *t = SPR_TextureFromResourceAsync(crosshair); - Vec2 size = VEC2(t->width, t->height); - Xform xf = XformFromTrs(TRS(.t = crosshair_pos, .s = size)); - D_DrawUiRect(g->render_sig, D_UIRECTPARAMS(.xf = xf, .texture = t->gpu_resource)); - } - #endif - - /* FIXME: Enable this */ - #if 0 - { - __profn("Update window cursor"); - if (g->debug_camera) - { - P_DisableWindoweCursorClip(g->window); - P_ShowWindowCursor(g->window); - } - else - { - SPR_Texture *t = SPR_TextureFromResourceAsync(ResourceKeyFromStore(PP_Resources, Lit("sprite/crosshair.ase"))); - Vec2 size = VEC2(t->width, t->height); - Rect cursor_clip = RectFromVec2(g->ui_screen_offset, g->ui_size); - cursor_clip.pos = AddVec2(cursor_clip.pos, MulVec2(size, 0.5f)); - cursor_clip.pos = AddVec2(cursor_clip.pos, VEC2(1, 1)); - cursor_clip.size = SubVec2(cursor_clip.size, size); - P_HideWindowCursor(g->window); - P_EnableWindoweCursorClip(g->window, cursor_clip); - } - } - #endif - - //- Create user sim cmd - - { - /* Queue player move cmd */ - f32 move_speed = 1.0f; - //if (g->bind_states[PP_BindKind_Walk].is_held) - if (g->bind_states[PP_BindKind_FullscreenMod].is_held) - { - //const f32 walk_ratio = 0.25f; - const f32 walk_ratio = 0.05f; - move_speed *= walk_ratio; - } - - Vec2 input_move_dir = ZI; - { - for (PP_BindKind bind = 0; bind < (i32)countof(g->bind_states); ++bind) - { - PP_BindState state = g->bind_states[bind]; - - if (!state.is_held && state.num_presses <= 0) - { - continue; - } - - switch (bind) - { - default: break; - - /* Movement */ - case PP_BindKind_MoveUp: - { - input_move_dir.y -= 1; - } break; - - case PP_BindKind_MoveDown: - { - input_move_dir.y += 1; - } break; - - case PP_BindKind_MoveLeft: - { - input_move_dir.x -= 1; - } break; - - case PP_BindKind_MoveRight: - { - input_move_dir.x += 1; - } break; - } - } - - input_move_dir = InvertXformBasisMulV2(g->world_to_ui_xf, input_move_dir); /* Make move dir relative to world view */ - input_move_dir = MulVec2(NormVec2(input_move_dir), move_speed); - } - - if (!g->debug_camera) - { - g->focus_send = SubVec2(g->world_cursor, PP_XformFromEnt(local_control).og); - } - Vec2 input_aim_dir = g->focus_send; - - /* Queue player control cmd */ - { - PP_ControlData control = ZI; - control.move = input_move_dir; - control.focus = input_aim_dir; - control.dbg_cursor = g->world_cursor; - - PP_BindState fire_state = g->bind_states[PP_BindKind_Fire]; - PP_BindState fire_alt_state = g->bind_states[PP_BindKind_AltFire]; - PP_BindState drag_state = g->bind_states[PP_BindKind_DebugDrag]; - PP_BindState delete_state = g->bind_states[PP_BindKind_DebugDelete]; - PP_BindState clear_state = g->bind_states[PP_BindKind_DebugClear]; - PP_BindState spawn1_state = g->bind_states[PP_BindKind_DebugSpawn1]; - PP_BindState spawn2_state = g->bind_states[PP_BindKind_DebugSpawn2]; - PP_BindState spawn3_state = g->bind_states[PP_BindKind_DebugSpawn3]; - PP_BindState spawn4_state = g->bind_states[PP_BindKind_DebugSpawn4]; - PP_BindState walls_state = g->bind_states[PP_BindKind_DebugWalls]; - PP_BindState pause_state = g->bind_states[PP_BindKind_DebugPause]; - PP_BindState step_state = g->bind_states[PP_BindKind_DebugStep]; - PP_BindState tile_state = g->bind_states[PP_BindKind_TestTile]; - PP_BindState explode_state = g->bind_states[PP_BindKind_DebugExplode]; - PP_BindState teleport_state = g->bind_states[PP_BindKind_DebugTeleport]; - - if (fire_state.num_presses || fire_state.is_held) - { - control.flags |= PP_ControlFlag_Fire; - } - if (fire_alt_state.num_presses || fire_alt_state.is_held) - { - control.flags |= PP_ControlFlag_AltFire; - } - if (drag_state.num_presses || drag_state.is_held) - { - control.flags |= PP_ControlFlag_Drag; - } - if (delete_state.num_presses || delete_state.is_held) - { - control.flags |= PP_ControlFlag_Delete; - } - if (clear_state.num_presses_and_repeats) - { - control.flags |= PP_ControlFlag_ClearAll; - } - if (spawn1_state.num_presses_and_repeats) - { - control.flags |= PP_ControlFlag_SpawnTest1; - } - if (spawn2_state.num_presses_and_repeats) - { - control.flags |= PP_ControlFlag_SpawnTest2; - } - if (spawn3_state.num_presses_and_repeats) - { - control.flags |= PP_ControlFlag_SpawnTest3; - } - if (spawn4_state.num_presses_and_repeats) - { - control.flags |= PP_ControlFlag_SpawnTest4; - } - if (walls_state.num_presses_and_repeats) - { - control.flags |= PP_ControlFlag_TestWalls; - } - if (tile_state.num_presses || tile_state.is_held) - { - control.flags |= PP_ControlFlag_TestTiles; - } - if (explode_state.num_presses_and_repeats) - { - control.flags |= PP_ControlFlag_TestExplode; - } - if (teleport_state.num_presses_and_repeats || (g->debug_camera && teleport_state.is_held)) - { - control.flags |= PP_ControlFlag_TestTeleport; - } - - if (pause_state.num_presses) - { - Atomic32FetchXor(&g->user_paused, 1); - } - Atomic32FetchAdd(&g->user_paused_steps, step_state.num_presses_and_repeats); - - /* Set user sim control */ - { - Lock lock = LockE(&g->user_sim_cmd_mutex); - - /* Reset flags */ - if (g->user_sim_cmd_gen != g->last_user_sim_cmd_gen) - { - g->user_sim_cmd_control.flags = 0; - g->last_user_sim_cmd_gen = g->user_sim_cmd_gen; - } - - 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_hovered_ent = hovered_ent->key; - Unlock(&lock); - } - } - -#if IsRtcEnabled - /* Gjk steps */ - { - if (g->bind_states[PP_BindKind_ResetDebugSteps].num_presses_and_repeats > 0) - { - SetGstat(GSTAT_DEBUG_STEPS, 0); - } - i32 add_steps = 0; - add_steps += g->bind_states[PP_BindKind_IncrementDebugSteps].num_presses_and_repeats; - add_steps -= g->bind_states[PP_BindKind_DecrementDebugSteps].num_presses_and_repeats; - if (add_steps != 0) - { - AddGstat(GSTAT_DEBUG_STEPS, add_steps); - } - } -#endif - } - - { - /* Update network usage stats */ - i64 stat_now_ns = TimeNs(); - g->net_bytes_read.last_second_end = GetGstat(GSTAT_SOCK_BYTES_RECEIVED); - g->net_bytes_sent.last_second_end = GetGstat(GSTAT_SOCK_BYTES_SENT); - if (stat_now_ns - g->last_second_reset_ns > NsFromSeconds(1)) - { - g->last_second_reset_ns = stat_now_ns; - g->net_bytes_read.last_second = g->net_bytes_read.last_second_end - g->net_bytes_read.last_second_start; - g->net_bytes_sent.last_second = g->net_bytes_sent.last_second_end - g->net_bytes_sent.last_second_start; - g->net_bytes_read.last_second_start = g->net_bytes_read.last_second_end; - g->net_bytes_sent.last_second_start = g->net_bytes_sent.last_second_end; - } - } - - //- Draw ent debug info - /* FIXME: Enable this */ -#if 0 - if (g->debug_draw && hovered_ent->valid) - { - PP_Ent *ent = hovered_ent; - - Vec2 pos = AddVec2(g->ui_cursor, VEC2(15, 15)); - F_Font *font = F_LoadFontAsync(ResourceKeyFromStore(&PP_Resources, Lit("font/fixedsys.ttf")), 12.0f); - if (font) - { - TempArena temp = BeginTempArena(scratch.arena); - - String dbg_text = ZI; - dbg_text.text = PushDry(temp.arena, u8); - dbg_text.len += PP_DebugStringFromEnt(temp.arena, ent).len; - draw_text(g->render_sig, D_TEXTPARAMS(.font = font, .pos = pos, .str = dbg_text)); - - EndTempArena(temp); - } - } -#endif - - ////////////////////////////// - //- Debug draw - - GPU_Stats gpu_stats = GPU_QueryStats(); - - /* Draw console */ - UI_Box *console_box = 0; - { - b32 console_minimized = !g->debug_console; - console_box = PP_BuildDebugConsole(console_minimized); - } - - /* Draw lister */ - if (g->lister_active) - { - UI_PushCP(pp_root_box); - { - UI_Push(Tag, HashF("lister")); - UI_Key titlebar_key = UI_KeyF("lister title bar"); - - u32 base_background_color = 0xff1a1d1e; - u32 base_border_color = 0xff343a3b; - - f32 window_border = 1; - f32 window_width = 300; - u32 window_background_color = base_background_color; - u32 window_border_color = base_border_color; - u32 titlebar_color = 0; - u32 titlebar_border_color = 0; - u32 divider_color = base_border_color; - { - UI_Report rep = UI_ReportFromKey(titlebar_key); - if (rep.m1_held) - { - g->lister_pos = SubVec2(g->ui_cursor, rep.last_m1_offset); - } - { - window_border_color = BlendSrgbU32(window_border_color, Rgb32F(0.5, 0.5, 0.5), rep.hot); - } - } - - UI_Push(BackgroundColor, window_background_color); - UI_Push(BorderColor, window_border_color); - UI_Push(Border, window_border); - // UI_Push(Rounding, UI_RPIX(15)); - UI_Push(Rounding, UI_RPIX(15)); - UI_Push(Width, UI_PIX(window_width, 0)); - UI_Push(Height, UI_FIT(0)); - UI_Push(ChildLayoutAxis, Axis_Y); - UI_Push(FloatingPos, g->lister_pos); - UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_PushCP(UI_BuildBox(UI_KeyF("lister"))); - { - /* Title bar */ - UI_PushCP(0); - { - UI_Push(BackgroundColor, titlebar_color); - UI_Push(BorderColor, titlebar_border_color); - UI_Push(Rounding, UI_RPIX(0)); - UI_Push(ChildLayoutAxis, Axis_X); - UI_Push(Width, UI_FILL(1, 0)); - UI_Push(Height, UI_FNT(2, 1)); - UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable); - UI_PushCP(UI_BuildBox(titlebar_key)); - { - UI_Push(Width, UI_FILL(1, 0)); - UI_Push(BorderColor, 0); - - /* Left title box */ - UI_BuildRow(UI_NilKey); - - /* Title box */ - UI_SetNext(ChildAlignment, UI_Alignment_Center); - UI_SetNext(Width, UI_FIT(1)); - UI_SetNext(Text, Lit("Titleeeeeeeeeeeeeee")); - UI_SetNext(Flags, UI_BoxFlag_DrawText); - UI_BuildBox(UI_NilKey); - - /* Right title box */ - UI_BuildRow(UI_NilKey); - } - UI_PopCP(); - } - UI_PopCP(); - } - - UI_SetNext(Tint, 0); - UI_SetNext(Rounding, 0); - UI_PushCP(UI_BuildRow(UI_NilKey)); - { - f32 padding = window_border; - UI_BuildSpacer(UI_PIX(padding, 1)); - { - UI_SetNext(Tint, 0); - UI_SetNext(Rounding, 0); - UI_SetNext(Width, UI_FILL(1, 0)); - UI_PushCP(UI_BuildColumn(UI_NilKey)); - { - u32 count = 10; - for (u32 i = 0; i < count; ++i) - { - UI_BuildDivider(UI_PIX(1, 1), divider_color); - - UI_Key btn_key = UI_KeyF("btn%F", FmtSint(i)); - UI_Report rep = UI_ReportFromKey(btn_key); - - u32 hovered_color = Rgb32(0x10, 0x3c, 0x4c); - u32 pressed_color = Alpha32F(hovered_color, 0.25); - - f32 hot = rep.hot; - f32 active = rep.active; - f32 hovered = rep.hovered; - - u32 color = 0; - u32 border_color = 0; - color = BlendSrgbU32(color, hovered_color, hot); - color = BlendSrgbU32(color, pressed_color, active * hovered); - border_color = BlendSrgbU32(border_color, Rgb32(0x00, 0x79, 0xa6), hot); - - String button_text = UI_StringF("Button %F", FmtSint(i)); - - UI_SetNext(BorderColor, border_color); - UI_SetNext(BackgroundColor, color); - UI_SetNext(Rounding, UI_RPIX(5)); - UI_SetNext(Width, UI_FILL(1, 0)); - UI_SetNext(Height, UI_FNT(1.5, 1)); - UI_SetNext(Text, button_text); - UI_SetNext(ChildAlignment, UI_Alignment_Center); - UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable); - UI_BuildBox(btn_key); - - if (rep.m1_presses) - { - LogInfoF("%F pressed", FmtString(button_text)); - } - } - UI_BuildSpacer(UI_PIX(padding, 1)); - } - UI_PopCP(); - } - UI_BuildSpacer(UI_PIX(padding, 1)); - } - UI_PopCP(); - - - - UI_PopCP(); - } - UI_PopCP(); - } - - /* Draw debug info */ - if (g->debug_draw) - { - __profn("Draw debug info"); - - UI_BuildSpacer(UI_FILL(1, 0)); - - UI_SetNext(ChildLayoutAxis, Axis_Y); - UI_SetNext(BackgroundColor, 0); - UI_SetNext(BorderColor, 0); - UI_SetNext(Width, UI_FIT(1)); - UI_SetNext(Height, UI_FIT(1)); - UI_SetNext(Tint, 0); - UI_PushCP(UI_BuildBox(UI_KeyF("dbg"))); - { - UI_Push(BackgroundColor, 0); - UI_Push(BorderColor, 0); - - UI_BuildLabelF("Blended world entities: %F/%F", FmtUint(g->ss_blended->num_ents_allocated), FmtUint(g->ss_blended->num_ents_reserved)); - UI_BuildLabelF("Blended world tick: %F", FmtUint(g->ss_blended->tick)); - - UI_BuildLabelF("Blended world time: %F", FmtFloat(SecondsFromNs(g->ss_blended->sim_time_ns))); - UI_BuildSpacer(UI_FNT(1, 0)); - - UI_BuildLabelF("Average local sim publish dt: %F", FmtFloat(SecondsFromNs(g->average_local_to_user_snapshot_publish_dt_ns))); - UI_BuildLabelF("Local sim last known tick: %F", FmtUint(g->local_sim_last_known_tick)); - UI_BuildLabelF("Local sim last known time: %F", FmtFloat(SecondsFromNs(g->local_sim_last_known_time_ns))); - UI_BuildLabelF("Local sim predicted time: %F", FmtFloat(SecondsFromNs(g->local_sim_predicted_time_ns))); - UI_BuildLabelF("Render time target: %F", FmtFloat(SecondsFromNs(g->render_time_target_ns))); - - UI_BuildLabelF("Render time: %F", FmtFloat(SecondsFromNs(g->render_time_ns))); - - UI_BuildLabelF("Local player: [%F]", FmtUid(local_player->key.uid)); - UI_BuildSpacer(UI_FNT(1, 0)); - - Vec2 world_cursor = g->world_cursor; - UI_BuildLabelF("Cursor world: %F, %F", FmtFloat(world_cursor.x), FmtFloat(world_cursor.y)); - - Vec2I32 world_tile_cursor = PP_WorldTileIndexFromPos(world_cursor); - UI_BuildLabelF("Cursor world tile: %F, %F", FmtSint(world_tile_cursor.x), FmtSint(world_tile_cursor.y)); - - Vec2I32 local_tile_cursor = PP_LocalTileIndexFromWorldTileIndex(world_tile_cursor); - UI_BuildLabelF("Cursor local tile: %F, %F", FmtSint(local_tile_cursor.x), FmtSint(local_tile_cursor.y)); - - Vec2I32 tile_chunk_cursor = PP_TileChunkIndexFromWorldTileIndex(world_tile_cursor); - UI_BuildLabelF("Cursor tile chunk: %F, %F", FmtSint(tile_chunk_cursor.x), FmtSint(tile_chunk_cursor.y)); - UI_BuildSpacer(UI_FNT(1, 0)); - - UI_BuildLabelF("Network read: %F mbit/s", FmtFloat((f64)g->net_bytes_read.last_second * 8 / 1000 / 1000)); - - UI_BuildLabelF("Network write: %F mbit/s", FmtFloat((f64)g->net_bytes_sent.last_second * 8 / 1000 / 1000)); - - UI_BuildLabelF("Ping (real): %F ms", FmtFloat(SecondsFromNs(local_player->player_last_rtt_ns) * 1000)); - - UI_BuildLabelF("Ping (average): %F ms", FmtFloat(local_player->player_average_rtt_seconds * 1000)); - UI_BuildSpacer(UI_FNT(1, 0)); - - UI_BuildLabelF("Memory committed: %F MiB", FmtFloat((f64)GetGstat(GSTAT_MEMORY_COMMITTED) / 1024 / 1024)); - - UI_BuildLabelF("Virtual memory reserved: %F TiB", FmtFloat((f64)GetGstat(GSTAT_MEMORY_RESERVED) / 1024 / 1024 / 1024 / 1024)); - - UI_BuildLabelF("Arenas allocated: %F", FmtUint(GetGstat(GSTAT_NUM_ARENAS))); - UI_BuildSpacer(UI_FNT(1, 0)); - - UI_BuildLabelF("GPU dedicated memory usage: %F MiB", FmtFloat((f64)gpu_stats.local_committed / 1024 / 1024)); - UI_BuildLabelF("GPU shared memory usage: %F MiB", FmtFloat((f64)gpu_stats.non_local_committed / 1024 / 1024)); - UI_BuildSpacer(UI_FNT(1, 0)); - - UI_BuildLabelF("GPU resources: %F", FmtUint(gpu_stats.driver_resources_allocated)); - UI_BuildLabelF("GPU descriptors: %F", FmtUint(gpu_stats.driver_descriptors_allocated)); - //UI_BuildLabelF(\n")); - //UI_BuildLabelF(\n")); - -#if IsRtcEnabled - UI_BuildSpacer(UI_FNT(1, 0)); - UI_BuildLabelF("Debug steps: %F", FmtUint(GetGstat(GSTAT_DEBUG_STEPS))); - //UI_BuildLabelF(\n")); -#endif - } - UI_PopCP(); - } - - ////////////////////////////// - //- Render - - Rect ui_viewport = RectFromVec2(VEC2(0, 0), VEC2(g->ui_size.x, g->ui_size.y)); - Rect render_viewport = RectFromVec2(VEC2(0, 0), VEC2(g->render_size.x, g->render_size.y)); - GPU_QueueKind gpu_render_queue = GPU_QueueKind_Direct; - Fence *submit_fence = GPU_FenceFromQueue(gpu_render_queue); - { - __profn("Render"); - - - /* Acquire gbuffers */ - if (g->shade_target && !EqVec2I32(g->render_size, GPU_GetTextureSize2D(g->shade_target))) - { - __profn("Release render resources"); - YieldOnFence(submit_fence, g->gpu_submit_fence_target); - GPU_ReleaseResource(g->albedo, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->emittance, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->emittance_flood_read, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->emittance_flood_target, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->shade_read, GPU_ReleaseFlag_None); - GPU_ReleaseResource(g->shade_target, GPU_ReleaseFlag_None); - g->shade_target = 0; - } - if (!g->shade_target) - { - __profn("Acquire sig resources"); - g->albedo = PP_AcquireGbuffer(GPU_Format_R8G8B8A8_Unorm, g->render_size); - g->emittance = PP_AcquireGbuffer(GPU_Format_R16G16B16A16_Float, g->render_size); - g->emittance_flood_read = PP_AcquireGbuffer(GPU_Format_R16G16_Uint, g->render_size); - g->emittance_flood_target = PP_AcquireGbuffer(GPU_Format_R16G16_Uint, g->render_size); - g->shade_read = PP_AcquireGbuffer(GPU_Format_R16G16B16A16_Float, g->render_size); - g->shade_target = PP_AcquireGbuffer(GPU_Format_R16G16B16A16_Float, g->render_size); - } - - /* Upload transient buffers */ - GPU_Resource *material_instances_buffer = GPU_UploadTransientBufferFromArena(&g->material_instances_tbuff, g->material_instances_arena); - GPU_Resource *grids_buffer = GPU_UploadTransientBufferFromArena(&g->grids_tbuff, g->grids_arena); - u64 material_instances_count = GPU_GetBufferCount(material_instances_buffer); - u64 grids_count = GPU_GetBufferCount(grids_buffer); - - GPU_CommandList *cl = GPU_BeginCommandList(gpu_render_queue); - { - __profn("Run render"); - GPU_ProfN(cl, Lit("Run render")); - Mat4x4 world_to_render_vp_matrix = ProjectMat4x4View(g->world_to_render_xf, render_viewport.width, render_viewport.height); - Mat4x4 ui_vp_matrix = ProjectMat4x4View(XformIdentity, ui_viewport.width, ui_viewport.height); - Mat4x4 blit_vp_matrix = ZI; - { - Xform xf = g->render_to_ui_xf; - xf = ScaleXform(xf, VEC2(g->render_size.x, g->render_size.y)); - xf = TranslateXform(xf, VEC2(0.5, 0.5)); - blit_vp_matrix = ProjectMat4x4View(xf, ui_viewport.width, ui_viewport.height); - } - - //- Prep material pass - { - __profn("Clear gbuffers"); - GPU_ProfN(cl, Lit("Clear gbuffers")); - GPU_TransitionToRenderable(cl, g->albedo, 0); - GPU_TransitionToRenderable(cl, g->emittance, 1); - GPU_ClearRenderable(cl, g->albedo); - GPU_ClearRenderable(cl, g->emittance); - } - - //- Material pass - if (material_instances_count > 0) - { - __profn("Material pass"); - GPU_ProfN(cl, Lit("Material pass")); - - GPU_Viewport viewport = GPU_ViewportFromRect(render_viewport); - GPU_Scissor scissor = GPU_ScissorFromRect(render_viewport); - - PP_MaterialSig sig = ZI; - sig.projection = world_to_render_vp_matrix; - sig.sampler = GPU_SamplerStateRidFromResource(GPU_GetCommonPointSampler()); - sig.instances = GPU_StructuredBufferRidFromResource(material_instances_buffer); - sig.grids = GPU_StructuredBufferRidFromResource(grids_buffer); - GPU_Rasterize( - cl, - &sig, - PP_MaterialVS, PP_MaterialPS, - 2, - viewport, - scissor, - material_instances_count, - GPU_GetCommonQuadIndices(), - GPU_RasterizeMode_TriangleList - ); - } - - //- Prep flood pass - { - GPU_TransitionToReadable(cl, g->emittance); - GPU_TransitionToWritable(cl, g->emittance_flood_read); - GPU_TransitionToWritable(cl, g->emittance_flood_target); - } - - //- Flood pass - if (!effects_disabled) - { - __profn("Flood pass"); - GPU_ProfN(cl, Lit("Flood pass")); - - i32 step_length = -1; - - /* TODO: Remove this */ - u64 max_steps = GetGstat(GSTAT_DEBUG_STEPS); - u64 step = 0; - while (step_length != 0 && step < max_steps) - { - __profn("Flood step"); - GPU_ProfN(cl, Lit("Flood step")); - - GPU_FlushWritable(cl, g->emittance_flood_read); - - PP_FloodSig sig = ZI; - sig.step_len = step_length; - sig.emittance = GPU_Texture2DRidFromResource(g->emittance); - sig.read = GPU_RWTexture2DRidFromResource(g->emittance_flood_read); - sig.target = GPU_RWTexture2DRidFromResource(g->emittance_flood_target); - sig.tex_width = g->render_size.x; - sig.tex_height = g->render_size.y; - GPU_Compute(cl, &sig, PP_FloodCS, (g->render_size.x + 7) / 8, (g->render_size.y + 7) / 8, 1); - - /* Swap buffers */ - GPU_Resource *swp = g->emittance_flood_read; - g->emittance_flood_read = g->emittance_flood_target; - g->emittance_flood_target = swp; - - /* Update step */ - if (step_length == -1) - { - step_length = MaxI32(g->render_size.x, g->render_size.y) / 2; - } - else - { - step_length /= 2; - } - ++step; - } - } - - //- Prep shade pass - { - __profn("Clear shade target"); - GPU_ProfN(cl, Lit("Clear shade target")); - GPU_TransitionToReadable(cl, g->albedo); - GPU_TransitionToReadable(cl, g->emittance); - GPU_TransitionToWritable(cl, g->shade_target); - GPU_FlushWritable(cl, g->emittance_flood_read); - GPU_FlushWritable(cl, g->shade_read); - } - - //- Shade pass - { - __profn("Shade pass"); - GPU_ProfN(cl, Lit("Shade pass")); - Vec3I32 noise_size = GPU_GetTextureSize3D(GPU_GetCommonNoise()); - - u32 shade_flags = PP_ShadeFlag_None | PP_ShadeFlag_ToneMap; - if (effects_disabled) - { - shade_flags |= PP_ShadeFlag_DisableEffects; - } - - PP_ShadeSig sig = ZI; - sig.flags = shade_flags; - sig.tex_width = g->render_size.x; - sig.tex_height = g->render_size.y; - sig.exposure = 2.0; - sig.frame_seed = VEC4U32( - (u32)(RandU64FromState(&g->frame_rand) & 0xFFFFFFFF), - (u32)(RandU64FromState(&g->frame_rand) & 0xFFFFFFFF), - (u32)(RandU64FromState(&g->frame_rand) & 0xFFFFFFFF), - (u32)(RandU64FromState(&g->frame_rand) & 0xFFFFFFFF) - ); - sig.frame_index = g->frame_index; - sig.camera_offset = g->world_to_render_xf.og; - sig.noise = GPU_Texture3DRidFromResource(GPU_GetCommonNoise()); - sig.albedo = GPU_Texture2DRidFromResource(g->albedo); - sig.emittance = GPU_Texture2DRidFromResource(g->emittance); - sig.emittance_flood = GPU_Texture2DRidFromResource(g->emittance_flood_read); - sig.read = GPU_Texture2DRidFromResource(g->shade_read); - sig.target = GPU_RWTexture2DRidFromResource(g->shade_target); - sig.noise_tex_width = noise_size.x; - sig.noise_tex_height = noise_size.y; - sig.noise_tex_depth = noise_size.z; - GPU_Compute(cl, &sig, PP_ShadeCS, (g->render_size.x + 7) / 8, (g->render_size.y + 7) / 8, 1); - - /* Swap */ - GPU_Resource *swp = g->shade_read; - g->shade_read = g->shade_target; - g->shade_target = swp; - } - - //- Transition target to readable before UI pass - GPU_TransitionToReadable(cl, g->shade_read); - GPU_TransitionToReadable(cl, g->shade_target); - } - g->gpu_submit_fence_target = GPU_EndCommandList(cl); - - /* Reset render data */ - GPU_ResetTransientBuffer(&g->material_instances_tbuff, g->gpu_submit_fence_target); - GPU_ResetTransientBuffer(&g->grids_tbuff, g->gpu_submit_fence_target); - ResetArena(g->material_instances_arena); - ResetArena(g->grids_arena); - } - - /* Set root background texture to game texture */ - { - Xform ui_to_render_xf = InvertXform(g->render_to_ui_xf); - Vec2 p0 = MulXformV2(ui_to_render_xf, VEC2(0, 0)); - Vec2 p1 = MulXformV2(ui_to_render_xf, Vec2FromFields(g->ui_size)); - Vec2 uv0 = DivVec2Vec2(p0, Vec2FromFields(g->render_size)); - Vec2 uv1 = DivVec2Vec2(p1, Vec2FromFields(g->render_size)); - UI_SetBackgroundTexture(pp_root_box, g->shade_read, uv0, uv1); - } - - ////////////////////////////// - //- End frame - - g->gpu_submit_fence_target = UI_EndFrame(ui_frame); - - ++g->user_tick; - EndScratch(scratch); -} - -//////////////////////////////////////////////////////////// -//~ User update job - -JobImpl(PP_UpdateUserOrSleep, UNUSED sig, UNUSED key) -{ - PP_SharedUserState *g = &PP_shared_user_state; - i64 time_ns = TimeNs(); - while (!Atomic32Fetch(&g->shutdown)) - { - u32 fps_limit = FPS_LIMIT; - if (fps_limit > 0) - { - __profn("User frame limit"); - P_SleepFrame(time_ns, 1000000000 / fps_limit); - time_ns = TimeNs(); - } - PP_UpdateUser(); - } -} - -//////////////////////////////////////////////////////////// -//~ Generate user input cmds - -void PP_GenerateuserInputCmds(PP_Client *user_input_client, u64 tick) -{ - PP_SharedUserState *g = &PP_shared_user_state; - PP_Snapshot *prev_user_input_ss = PP_SnapshotFromTick(user_input_client, user_input_client->last_tick); - PP_Snapshot *user_input_ss = PP_AcquireSnapshot(user_input_client, prev_user_input_ss, tick); - PP_Ent *user_input_root = PP_EntFromKey(user_input_ss, PP_RootEntKey); - /* Find / create local control cmd ent */ - PP_Ent *control_cmd = PP_FirstWithProp(user_input_ss, PP_Prop_Cmd); - if (!control_cmd->valid) - { - control_cmd = PP_AcquireSyncSrcEnt(user_input_root); - control_cmd->cmd_kind = PP_CmdKind_Control; - control_cmd->predictor = user_input_client->player_id; - PP_EnableProp(control_cmd, PP_Prop_Cmd); - PP_ActivateEnt(control_cmd, user_input_ss->tick); - } - { - Lock lock = LockE(&g->user_sim_cmd_mutex); - /* Update control cmd */ - { - control_cmd->cmd_control = g->user_sim_cmd_control; - control_cmd->cmd_control_hovered_ent = g->user_hovered_ent; - } -#if 0 - /* Create chat cmd */ - if (g->user_sim_cmd_chat.len > 0) - { - PP_Ent *chat_cmd = PP_AcquireSyncSrcEnt(user_input_root); - chat_cmd->cmd_kind = PP_CmdKind_Chat; - //chat_cmd->chat_msg = ZI - } -#endif - ++g->user_sim_cmd_gen; - Unlock(&lock); - } -} - -//////////////////////////////////////////////////////////// -//~ Sim update - -JobImpl(PP_UpdateSim, UNUSED sig, UNUSED key) -{ - PP_SharedUserState *g = &PP_shared_user_state; - #if 0 - struct host_listen_address local_listen_addr = host_listen_address_from_local_name(Lit("LOCAL_SIM")); - struct host_listen_address net_listen_addr = host_listen_address_from_net_port(12345); - //N_Host *host = N_AcquireHost(); - /* TODO: Host system should allocate & copy string stored in local_listen_addr */ - //host_listen(host, local_listen_addr); - //host_listen(host, net_listen_addr); - #endif - - b32 is_master = 0; - N_Host *host; - if (g->connect_address_str.len > 0) - { - host = N_AcquireHost(0); - P_Address addr = P_AddressFromString(g->connect_address_str); - N_Connect(host, addr); - } - else - { - host = N_AcquireHost(12345); - is_master = 1; - } - - BB_Buff msg_writer_bb = BB_AcquireBuff(Gibi(64)); - BB_Buff snapshot_writer_bb = BB_AcquireBuff(Gibi(64)); - PP_Accel accel = PP_AcquireAccel(); - - PP_ClientStore *store = PP_AcquireClientStore(); - PP_Client *user_input_client = PP_AcquireClient(store); /* Stores snapshots containing commands to be published to local client */ - PP_Client *local_client = PP_AcquireClient(store); /* Stores snapshots produced locally */ - PP_Client *publish_client = PP_AcquireClient(store); /* Stores versions of local snapshots that will be published to remote sims */ - - PP_Client *master_client = PP_NilClient(); /* Stores snapshots received from master */ - PP_Client *master_blended_client = PP_NilClient(); /* Stores interpolated master snapshots */ - b32 initialized_from_master = 0; - - - - - - #if 0 - if (IsSwappedIn()) - { - TempArena scratch = BeginScratchNoConflict(); - String encoded = SwappedStateFromName(scratch.arena, Lit("pp_snapshot")); - - BB_Buff bb = BB_BuffFromString(encoded); - BB_Reader br = BB_ReaderFromBuff(&bb); - - u64 tick = BB_ReadIBits(&br, 64); - if (tick > 0) - { - PP_EntKey player_id = { .uid = BB_ReadUid(&br) }; - local_client->player_id = player_id; - user_input_client->player_id = player_id; - PP_Snapshot *ss = PP_AcquireSnapshot(local_client, PP_NilSnapshot(), tick); - PP_DecodeSnapshot(&br, ss); - } - - EndScratch(scratch); - } - #endif - - - - - - - - - - - i64 master_blend_time_ns = 0; - i64 average_master_receive_dt_ns = 0; - i64 last_tick_from_master_received_at_ns = 0; - - - - - - - - - - - - - - - - i64 last_publish_to_user_ns = 0; - i64 real_time_ns = 0; - i64 real_dt_ns = 0; - i64 step_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND; - f64 compute_timescale = 1.0; - while (!Atomic32Fetch(&g->shutdown)) - { - TempArena scratch = BeginScratchNoConflict(); - { - __profn("Sim sleep"); - P_SleepFrame(real_time_ns, step_dt_ns * compute_timescale); - } - { - __profn("Sim update"); - - real_dt_ns = TimeNs() - real_time_ns; - real_time_ns += real_dt_ns; - - N_EventList host_events = N_BeginUpdate(scratch.arena, host); - - /* Read net messages */ - PP_DecodeQueue queue = ZI; - { - for (N_Event *event = host_events.first; event; event = event->next) - { - N_ChannelId channel_id = event->channel_id; - PP_Client *client = PP_ClientFromChannelId(store, channel_id); - switch (event->kind) - { - case N_EventKind_ChannelOpened: - { - if (!client->valid) - { - if (is_master) - { - /* Create remote client */ - client = PP_AcquireClient(store); - PP_SetClientChannelId(client, channel_id); - } - else - { - /* Create master client */ - if (!master_client->valid) - { - client = PP_AcquireClient(store); - PP_SetClientChannelId(client, channel_id); - master_client = client; - master_blended_client = PP_AcquireClient(store); - } - else - { - /* We already have a master client */ - Assert(0); - } - } - } - } break; - - case N_EventKind_Msg: - { - if (client->valid) - { - BB_Buff msg_bb = BB_BuffFromString(event->msg); - BB_Reader msg_br = BB_ReaderFromBuff(&msg_bb); - - u64 ack = BB_ReadUV(&msg_br); - u64 double_ack = BB_ReadUV(&msg_br); - if (ack > client->ack) - { - client->ack = ack; - } - if (double_ack > client->double_ack) - { - client->double_ack = double_ack; - } - - /* Read & queue incoming snapshots for decoding */ - u64 tmp_encoded_len = BB_ReadUV(&msg_br); - while (tmp_encoded_len > 0) - { - u8 *tmp_encoded_bytes = BB_ReadBytesRaw(&msg_br, tmp_encoded_len); - if (!tmp_encoded_bytes) break; - - BB_Buff decoder_bb = BB_BuffFromString(STRING(tmp_encoded_len, tmp_encoded_bytes)); - BB_Reader decoder_br = BB_ReaderFromBuff(&decoder_bb); - u64 base_tick = BB_ReadUV(&decoder_br); - u64 tick = BB_ReadUV(&decoder_br); - - String tmp_encoded = ZI; - tmp_encoded.len = BB_NumBytesRemaining(&decoder_br); - tmp_encoded.text = BB_ReadBytesRaw(&decoder_br, tmp_encoded.len); - if (!tmp_encoded.text) tmp_encoded.len = 0; - - PP_Snapshot *base_ss = PP_SnapshotFromTick(client, base_tick); - if (base_ss->tick == base_tick) - { - if (is_master) - { - /* Queue incoming slave client snapshot for decoding */ - //b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0; - b32 should_decode = tick > client->highest_received_tick; - if (should_decode) - { - PP_DecodeQueueNode *node = PushStruct(scratch.arena, PP_DecodeQueueNode); - node->client = client; - node->tick = tick; - node->base_tick = base_tick; - node->tmp_encoded = tmp_encoded; - if (queue.last) - { - queue.last->next = node; - } - else - { - queue.first = node; - } - queue.last = node; - if (tick > client->highest_received_tick) - { - client->highest_received_tick = tick; - } - } - } - else - { - /* Decode incoming master client snapshots for decoding (only the newest one) */ - b32 should_decode = client == master_client && tick > client->highest_received_tick; - if (should_decode) - { - PP_DecodeQueueNode *node = queue.first ? queue.first : PushStruct(scratch.arena, PP_DecodeQueueNode); - node->client = client; - node->tick = tick; - node->base_tick = base_tick; - node->tmp_encoded = tmp_encoded; - queue.first = node; - queue.last = node; - if (tick > client->highest_received_tick) - { - client->highest_received_tick = tick; - if (average_master_receive_dt_ns == 0) - { - average_master_receive_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND; - } - else - { - average_master_receive_dt_ns -= average_master_receive_dt_ns / 50; - average_master_receive_dt_ns += (real_time_ns - last_tick_from_master_received_at_ns) / 50; - } - last_tick_from_master_received_at_ns = real_time_ns; - } - } - } - } - else - { - /* We do not have the tick that the incoming delta is based from */ - Assert(0); - } - - tmp_encoded_len = BB_ReadUV(&msg_br); - } - } - } break; - - default: break; - } - } - } - - /* Decode incoming snapshots */ - for (PP_DecodeQueueNode *n = queue.first; n; n = n->next) - { - PP_Client *client = n->client; - u64 base_tick = n->base_tick; - u64 tick = n->tick; - PP_Snapshot *base_ss = PP_SnapshotFromTick(client, base_tick); - if (base_ss->tick == base_tick) - { - BB_Buff bb = BB_BuffFromString(n->tmp_encoded); - BB_Reader br = BB_ReaderFromBuff(&bb); - - /* Acquire & decode snapshot */ - PP_Snapshot *ss = PP_AcquireSnapshot(client, base_ss, tick); - PP_DecodeSnapshot(&br, ss); - - /* Assume all incoming ents want to be sync srcs */ - for (u64 i = 0; i < ss->num_ents_reserved; ++i) - { - PP_Ent *ent = &ss->ents[i]; - if (ent->valid && PP_HasProp(ent, PP_Prop_SyncDst)) - { - PP_DisableProp(ent, PP_Prop_SyncDst); - PP_EnableProp(ent, PP_Prop_SyncSrc); - } - } - } - else - { - // We do not have the tick that the incoming delta is based from. - // This decode should never have been queued in the first place. - Assert(0); - } - } - - if (!is_master && !initialized_from_master) - { - if (master_client->valid && master_client->last_tick > 0) - { - initialized_from_master = 1; - } - else - { - goto skip_step; - } - } - - b32 should_step = !Atomic32Fetch(&g->user_paused); - if (Atomic32Fetch(&g->user_paused_steps) > 0) - { - should_step = 1; - Atomic32FetchAdd(&g->user_paused_steps, -1); - } - - if (!should_step) - { - goto skip_step; - } - - /* Update networked clients */ - u64 oldest_client_ack = 0; - for (u64 i = 0; i < store->num_clients_reserved; ++i) - { - PP_Client *client = &store->clients[i]; - if (client->valid && client != local_client && client != publish_client && client != user_input_client && client != master_client) - { - client->last_rtt_ns = N_GetChannelLastRttNs(host, client->channel_id); - /* Release unneeded received snapshots */ - /* TDOO: Cap how many client snapshots we're willing to retain */ - if (client->double_ack > 0) - { - u64 keep_tick = MinU64(client->double_ack, local_client->last_tick); - if (keep_tick > 0) - { - PP_ReleaseSnapshotsInRange(client, 0, keep_tick - 1); - } - } - if (client->ack < oldest_client_ack || oldest_client_ack == 0) - { - oldest_client_ack = client->ack; - } - } - } - - /* Release unneeded published snapshots */ - { - u64 keep_tick = oldest_client_ack; - if (keep_tick == 0 && publish_client->last_tick > 0) - { - keep_tick = publish_client->last_tick - 1; - } - if (keep_tick > 0) - { - --keep_tick; - } - PP_ReleaseSnapshotsInRange(publish_client, 0, keep_tick); - } - - /* Release old local snapshots */ - { - u64 keep_range = 50; - if (local_client->last_tick > keep_range) - { - u64 keep_tick = local_client->last_tick - keep_range; - PP_ReleaseSnapshotsInRange(local_client, 0, keep_tick); - } - } - - /* Release unneeded user input snapshots */ - PP_ReleaseSnapshotsInRange(user_input_client, 0, local_client->first_tick - 1); - - - - - - - - - - if (is_master) - { - /* Step master */ - u64 prev_tick = local_client->last_tick; - u64 next_tick = prev_tick + 1; - PP_SimStepCtx ctx = ZI; - ctx.is_master = is_master; - ctx.sim_dt_ns = step_dt_ns; - ctx.accel = &accel; - ctx.user_input_client = user_input_client; - ctx.master_client = master_client; - ctx.publish_client = publish_client; - PP_Snapshot *prev_world = PP_SnapshotFromTick(local_client, prev_tick); - ctx.world = PP_AcquireSnapshot(local_client, prev_world, next_tick); - PP_GenerateuserInputCmds(user_input_client, next_tick); - PP_StepSim(&ctx); - } - else if (master_client->valid) - { - /* Step client */ - - /* TODO: Eventually determine master tick based on a delay to allow for jitter and also interpolation so we can lower snapshot publish frequency */ - - - b32 master_ss_is_blended = 0; - PP_Snapshot *master_ss = PP_NilSnapshot(); - { - /* How along are we between master sim ticks (0 = start of tick, 1 = end of tick) */ - f64 tick_progress = 0; - i64 next_tick_expected_ns = last_tick_from_master_received_at_ns + average_master_receive_dt_ns; - if (next_tick_expected_ns > last_tick_from_master_received_at_ns) - { - tick_progress = (f64)(real_time_ns - last_tick_from_master_received_at_ns) / (f64)(next_tick_expected_ns - last_tick_from_master_received_at_ns); - } - - /* Predict master sim time based on average snapshot publish dt. */ - PP_Snapshot *newest_snapshot = PP_SnapshotFromTick(master_client, master_client->last_tick); - i64 master_sim_predicted_time_ns = newest_snapshot->sim_time_ns + (newest_snapshot->sim_dt_ns * tick_progress); - - /* Determine blend time */ - i64 master_blend_time_target_ns = master_sim_predicted_time_ns - (SIM_CLIENT_INTERP_RATIO * average_master_receive_dt_ns); - if (average_master_receive_dt_ns > 0) - { - master_blend_time_ns += real_dt_ns; - } - - i64 blend_time_target_diff_ns = master_blend_time_target_ns - master_blend_time_ns; - if (blend_time_target_diff_ns > NsFromSeconds(0.100) || blend_time_target_diff_ns < NsFromSeconds(-0.100)) - { - /* Snap blend time if it gets too far from target blend time */ - master_blend_time_ns = master_blend_time_target_ns; - } - u64 master_blend_tick = master_blend_time_ns / newest_snapshot->sim_dt_ns; - - /* Get snapshot nearest to master blend time */ - /* TODO: Blend */ - PP_Snapshot *left_snapshot = PP_NilSnapshot(); - PP_Snapshot *right_snapshot = newest_snapshot; - { - PP_Snapshot *ss = PP_SnapshotFromTick(master_client, master_client->first_tick); - while (ss->valid) - { - u64 next_tick = ss->next_tick; - i64 ss_time_ns = ss->sim_time_ns; - if (ss_time_ns < master_blend_time_ns && ss_time_ns > left_snapshot->sim_time_ns) - { - left_snapshot = ss; - } - if (ss_time_ns > master_blend_time_ns && ss_time_ns < right_snapshot->sim_time_ns) - { - right_snapshot = ss; - } - ss = PP_SnapshotFromTick(master_client, next_tick); - } - } - - /* Create world from blended master snapshots */ - f64 blend = 0; - if (left_snapshot->valid && right_snapshot->valid && right_snapshot->tick > left_snapshot->tick) - { - blend = (f64)(master_blend_tick - left_snapshot->tick) / (f64)(right_snapshot->tick - left_snapshot->tick); - f64 epsilon = 0.001; - if (blend < epsilon) - { - master_ss_is_blended = 0; - master_ss = left_snapshot; - } - else if (blend > 1 - epsilon) - { - master_ss_is_blended = 0; - master_ss = right_snapshot; - } - else - { - master_ss_is_blended = 1; - master_ss = PP_AcquireSnapshotFromLerp(master_blended_client, left_snapshot, right_snapshot, blend); - - /* Release unneeded blended master snapshots */ - if (master_ss->tick > 0) - { - PP_ReleaseSnapshotsInRange(master_blended_client, 0, master_ss->tick - 1); - PP_ReleaseSnapshotsInRange(master_blended_client, master_ss->tick + 1, U64Max); - } - } - } - else - { - master_ss_is_blended = 0; - master_ss = left_snapshot->valid ? left_snapshot : right_snapshot; - } - - /* Release unneeded master snapshots */ - u64 keep_master_tick = MinU64(left_snapshot->tick, master_client->double_ack); - if (keep_master_tick > 0) - { - PP_ReleaseSnapshotsInRange(master_client, 0, keep_master_tick - 1); - } - -#if 0 - DEBUGBREAKABLE; - LogDebugF("*************************************************"); - LogDebugF("local_client->last_tick: %F", FmtUint(local_client->last_tick)); - LogDebugF("master_sim_predicted_time_ns: %F", FmtSint(master_sim_predicted_time_ns)); - LogDebugF("tick_progress: %F", FmtFloat(tick_progress)); - LogDebugF("sim_publish_timescale: %F", FmtFloat(sim_publish_timescale)); - LogDebugF("last_tick_from_master_received_at_ns: %F", FmtSint(last_tick_from_master_received_at_ns)); - LogDebugF("average_master_receive_dt_ns: %F", FmtSint(average_master_receive_dt_ns)); - LogDebugF("next_tick_expected_ns: %F", FmtSint(next_tick_expected_ns)); - LogDebugF("master_blend_time_target_ns: %F", FmtSint(master_blend_time_target_ns)); - LogDebugF("blend_time_target_diff_ns: %F", FmtSint(blend_time_target_diff_ns)); - LogDebugF("master_blend_time_ns: %F", FmtSint(master_blend_time_ns)); - LogDebugF("left_snapshot->tick: %F", FmtUint(left_snapshot->tick)); - LogDebugF("right_snapshot->tick: %F", FmtUint(right_snapshot->tick)); - LogDebugF("master_ss->tick: %F", FmtUint(master_ss->tick)); -#endif - } - - if (master_ss->valid) - { - PP_Ent *master_player = PP_FirstWithProp(master_ss, PP_Prop_IsMaster); - - /* Update ent key from master */ - { - user_input_client->player_id = master_ss->local_player; - local_client->player_id = master_ss->local_player; - } - - /* Check for misprediction */ - u64 mispredicted_tick = 0; - if (!master_ss_is_blended) - { - /* TODO: Actually check for misprediction rather than triggering mispredict any time a new master snapshot is received */ - mispredicted_tick = master_ss->tick; - } - - u64 step_base_tick = local_client->last_tick; - u64 step_end_tick = step_base_tick + 1; - if (mispredicted_tick > 0) - { - step_base_tick = mispredicted_tick; - if (step_end_tick <= step_base_tick) - { - step_end_tick = step_base_tick + 1; - } - } - - // We want to simulate the ahead of the server to predict client input. - // How many ticks ahead we want to simulate is a balance between added latency and the server not receiving our inputs on time. - // We can take the server's ack minus the server's tick to determine how many cmds of ours the server has buffered. - // - // If this buffer gets too low (because we are lagging behind or the connection is unstable), meaning the server is not getting our input on time: - // - Shorten local compute rate to increase the rate at which we predict ahead & produce cmds, until the server's ack indicates a buffer size within desired range. - // - // If this buffer gets too large (because the client predicts too far ahead), meaning unneeded latency is being introduced: - // - Dilate local compute rate to decrease the rate at which we predict ahead & produce cmds until the server's ack indicates a buffer size within desired range. - { - i64 cmds_ahead_on_master = (i64)master_client->ack - (i64)master_client->last_tick; - if (cmds_ahead_on_master < -3 || cmds_ahead_on_master > 10) - { - /* Cmds are too far from master time, snap step end tick */ - i64 rtt_ns = master_client->last_rtt_ns; - f64 rtt_tick_ratio = (f64)(rtt_ns + (step_dt_ns - 1)) / (f64)step_dt_ns; - i64 num_predict_ticks = RoundF64ToI64(rtt_tick_ratio) + 5; - step_end_tick = master_client->last_tick + num_predict_ticks; - compute_timescale = 1.1; - } - else if (cmds_ahead_on_master > 2) - { - /* Slow down simulation to dial back how far ahead we are predicting and bring local sim time closer to master sim time */ - compute_timescale = 1.1; - } - else if (cmds_ahead_on_master < 1) - { - /* Speed up simulation rate predict more ticks and give master more inputs to work with */ - compute_timescale = 0.9; - } - else - { - /* Server's cmd buffer is in a healthy range */ - compute_timescale = 1; - } - } - - /* Sync master with local base tick */ - PP_Snapshot *base_ss = PP_SnapshotFromTick(local_client, step_base_tick); - if (mispredicted_tick) - { - if (base_ss->valid) - { - PP_SyncSnapshotEnts(base_ss, master_ss, master_player->key, 0); - } - else - { - base_ss = PP_AcquireSnapshot(local_client, master_ss, step_base_tick); - } - } - - /* Release any existing ticks that are about to be simulated */ - PP_ReleaseSnapshotsInRange(local_client, step_base_tick + 1, U64Max); - - /* Step */ - PP_GenerateuserInputCmds(user_input_client, step_end_tick); - { - PP_SimStepCtx ctx = ZI; - ctx.is_master = is_master; - ctx.sim_dt_ns = step_dt_ns; - ctx.accel = &accel; - ctx.user_input_client = user_input_client; - ctx.master_client = master_client; - ctx.publish_client = publish_client; - - u64 step_tick = step_base_tick + 1; - PP_Snapshot *prev_ss = base_ss; - while (step_tick <= step_end_tick) - { - ctx.world = PP_AcquireSnapshot(local_client, prev_ss, step_tick); - if (!mispredicted_tick && step_tick == step_end_tick) - { - PP_SyncSnapshotEnts(ctx.world, master_ss, master_player->key, PP_SyncFlag_NoSyncPredictables); - } - PP_StepSim(&ctx); - prev_ss = ctx.world; - ++step_tick; - } - } - } - } - - /* Publish snapshot to remote clients */ - for (u64 i = 0; i < store->num_clients_reserved; ++i) - { - PP_Client *client = &store->clients[i]; - if (client->valid && client != user_input_client && client != local_client && client != publish_client) - { - BB_Writer msg_bw = BB_WriterFromBuff(&msg_writer_bb); - - BB_WriteUV(&msg_bw, client->highest_received_tick); /* ack */ - BB_WriteUV(&msg_bw, client->ack); /* double ack */ - - PP_Snapshot *base_ss = PP_SnapshotFromTick(publish_client, client->ack); - PP_Snapshot *publish_ss; - if (client == master_client) - { - /* If sending to master, start sending all snapshots since last ack */ - publish_ss = PP_SnapshotFromClosestTickGte(publish_client, base_ss->tick + 1); - } - else - { - /* If sending to slave, only send latest snapshot */ - publish_ss = PP_SnapshotFromTick(publish_client, publish_client->last_tick); - } - - while (publish_ss->valid) - { - BB_Writer snapshot_bw = BB_WriterFromBuff(&snapshot_writer_bb); - String tmp_snapshot_encoded = ZI; - { - BB_WriteUV(&snapshot_bw, base_ss->tick); - BB_WriteUV(&snapshot_bw, publish_ss->tick); - PP_EncodeSnapshot(&snapshot_bw, client, base_ss, publish_ss); - tmp_snapshot_encoded.len = BB_GetNumBytesWritten(&snapshot_bw); - tmp_snapshot_encoded.text = BB_GetWrittenRaw(&snapshot_bw); - } - BB_WriteUV(&msg_bw, tmp_snapshot_encoded.len); - BB_WriteBytes(&msg_bw, tmp_snapshot_encoded); - publish_ss = PP_SnapshotFromTick(publish_client, publish_ss->tick + 1); - } - BB_WriteUV(&msg_bw, 0); - - String encoded = ZI; - encoded.len = BB_GetNumBytesWritten(&msg_bw); - encoded.text = BB_GetWrittenRaw(&msg_bw); - N_Write(host, client->channel_id, encoded, 0); - } - } - - /* Copy local snapshot to user client */ - { - PP_Snapshot *local_ss = PP_SnapshotFromTick(local_client, local_client->last_tick); - if (local_ss->valid) - { - /* TODO: Double buffer */ - Lock lock = LockE(&g->local_to_user_client_mutex); - PP_AcquireSnapshot(g->local_to_user_client, local_ss, local_ss->tick); - i64 publish_ns = TimeNs(); - if (last_publish_to_user_ns == 0) - { - last_publish_to_user_ns = publish_ns - g->average_local_to_user_snapshot_publish_dt_ns; - } - g->local_to_user_client_publish_dt_ns = publish_ns - last_publish_to_user_ns; - g->local_to_user_client_publish_time_ns = publish_ns; - last_publish_to_user_ns = publish_ns; - PP_ReleaseSnapshotsInRange(g->local_to_user_client, 0, local_ss->tick - 1); - Unlock(&lock); - } - } - - skip_step: - - /* Send host messages */ - N_EndUpdate(host); - __profframe("Local sim"); - - EndScratch(scratch); - } - } - -#if 0 - if (IsSwappingOut()) - { - TempArena scratch = BeginScratchNoConflict(); - u64 max_size = Mebi(64); - u8 *bytes = PushStructsNoZero(scratch.arena, u8, max_size); - BB_Buff bb = BB_BuffFromString(STRING(max_size, bytes)); - { - BB_Writer bw = BB_WriterFromBuff(&bb); - - u64 tick = local_client->last_tick; - PP_Snapshot *ss = PP_SnapshotFromTick(local_client, tick); - BB_WriteUBits(&bw, tick, 64); - BB_WriteUid(&bw, local_client->player_id.uid); - PP_EncodeSnapshot(&bw, local_client, PP_NilSnapshot(), ss); - WriteSwappedState(Lit("pp_snapshot"), STRING(BB_GetNumBytesWritten(&bw), BB_GetWrittenRaw(&bw))); - } - EndScratch(scratch); - } -#endif - -#if 0 - PP_ReleaseClientStore(store); - PP_ReleaseAccel(&accel); - BB_ReleaseBuff(&snapshot_writer_bb); - BB_ReleaseBuff(&msg_writer_bb); - N_ReleaseHost(host); -#endif -} diff --git a/src/pp_old/pp.h b/src/pp_old/pp.h deleted file mode 100644 index d53f0402..00000000 --- a/src/pp_old/pp.h +++ /dev/null @@ -1,336 +0,0 @@ -//////////////////////////////////////////////////////////// -//~ Binds - -//- Bind kinds -Enum(PP_BindKind) -{ - PP_BindKind_None, - - PP_BindKind_MoveUp, - PP_BindKind_MoveDown, - PP_BindKind_MoveLeft, - PP_BindKind_MoveRight, - PP_BindKind_Walk, - PP_BindKind_Fire, - PP_BindKind_AltFire, - - PP_BindKind_TestTile, - PP_BindKind_DebugClear, - PP_BindKind_DebugSpawn1, - PP_BindKind_DebugSpawn2, - PP_BindKind_DebugSpawn3, - PP_BindKind_DebugSpawn4, - PP_BindKind_DebugWalls, - PP_BindKind_DebugFollow, - PP_BindKind_DebugDraw, - PP_BindKind_DebugConsole, - PP_BindKind_DebugCamera, - PP_BindKind_DebugLister, - PP_BindKind_DebugPause, - PP_BindKind_DebugStep, - PP_BindKind_DebugDrag, - PP_BindKind_DebugDelete, - PP_BindKind_DebugTeleport, - PP_BindKind_DebugExplode, - PP_BindKind_DebugToggleTopmost, - PP_BindKind_DebugUi, - PP_BindKind_FullscreenMod, - PP_BindKind_Fullscreen, - PP_BindKind_ZoomIn, - PP_BindKind_ZoomOut, - PP_BindKind_Pan, - -#if IsRtcEnabled - /* Debug */ - - PP_BindKind_ResetDebugSteps, - PP_BindKind_IncrementDebugSteps, - PP_BindKind_DecrementDebugSteps, -#endif - - PP_BindKind_COUNT -}; - -//- Test bindings - -/* TODO: Remove this */ -Global Readonly PP_BindKind g_binds[Btn_COUNT] = { - [Btn_W] = PP_BindKind_MoveUp, - [Btn_S] = PP_BindKind_MoveDown, - [Btn_A] = PP_BindKind_MoveLeft, - [Btn_D] = PP_BindKind_MoveRight, - [Btn_M1] = PP_BindKind_Fire, - [Btn_M2] = PP_BindKind_AltFire, -#if 0 - [Btn_Alt] = PP_BindKind_Walk, -#endif - - /* Testing */ - [Btn_Z] = PP_BindKind_TestTile, - [Btn_M5] = PP_BindKind_DebugDrag, - [Btn_M4] = PP_BindKind_DebugDelete, - [Btn_F] = PP_BindKind_DebugExplode, - [Btn_T] = PP_BindKind_DebugTeleport, - [Btn_C] = PP_BindKind_DebugClear, - [Btn_1] = PP_BindKind_DebugSpawn1, - [Btn_2] = PP_BindKind_DebugSpawn2, - [Btn_3] = PP_BindKind_DebugSpawn3, - [Btn_4] = PP_BindKind_DebugSpawn4, - [Btn_G] = PP_BindKind_DebugWalls, - [Btn_N] = PP_BindKind_DebugStep, - [Btn_Q] = PP_BindKind_DebugFollow, - [Btn_F1] = PP_BindKind_DebugPause, - [Btn_F2] = PP_BindKind_DebugCamera, - [Btn_F3] = PP_BindKind_DebugDraw, - [Btn_Tab] = PP_BindKind_DebugLister, - [Btn_F4] = PP_BindKind_DebugToggleTopmost, - [Btn_F5] = PP_BindKind_DebugUi, - [Btn_GraveAccent] = PP_BindKind_DebugConsole, - [Btn_Alt] = PP_BindKind_FullscreenMod, - [Btn_Enter] = PP_BindKind_Fullscreen, - [Btn_MWheelUp] = PP_BindKind_ZoomIn, - [Btn_MWheelDown] = PP_BindKind_ZoomOut, - [Btn_M3] = PP_BindKind_Pan, - -#if IsRtcEnabled - [Btn_ForwardSlash] = PP_BindKind_ResetDebugSteps, - [Btn_Comma] = PP_BindKind_DecrementDebugSteps, - [Btn_Period] = PP_BindKind_IncrementDebugSteps -#endif -}; - -//////////////////////////////////////////////////////////// -//~ Stats - -Struct(PP_SecondsStat) -{ - u64 last_second_start; - u64 last_second_end; - u64 last_second; -}; - -//////////////////////////////////////////////////////////// -//~ Console log - -Struct(PP_ConsoleLog) -{ - String msg; - i32 level; - i32 color_index; - DateTime datetime; - PP_ConsoleLog *prev; - PP_ConsoleLog *next; -}; - -//////////////////////////////////////////////////////////// -//~ Sim decode queue - -Struct(PP_DecodeQueueNode) -{ - PP_Client *client; - u64 tick; - u64 base_tick; - String tmp_encoded; - PP_DecodeQueueNode *next; -}; - -Struct(PP_DecodeQueue) -{ - PP_DecodeQueueNode *first; - PP_DecodeQueueNode *last; -}; - -//////////////////////////////////////////////////////////// -//~ State types - -Struct(PP_BindState) -{ - b32 is_held; /* Is this bind held down this frame */ - u32 num_presses; /* How many times was this bind's pressed since last frame */ - u32 num_repeats; /* How many times was this bind's key repeated since last frame */ - u32 num_presses_and_repeats; /* Same as `num_presses` but includes key repeats as well */ - u32 num_releases; /* How many times was this bind released since last frame */ -}; - -Struct(PP_SharedUserState) -{ - Atomic32 shutdown; - - Fence shutdown_jobs_fence; - u64 shutdown_jobs_count; - - Arena *arena; - String connect_address_str; - - PP_ClientStore *user_client_store; - PP_Client *user_unblended_client; /* Contains snapshots received from local sim */ - PP_Client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */ - PP_Snapshot *ss_blended; /* Points to blended snapshot contained in blended client */ - - u64 user_tick; - u64 window_os_gen; - - //- Usage stats - i64 last_second_reset_ns; - PP_SecondsStat net_bytes_read; - PP_SecondsStat net_bytes_sent; - - //- Renderer gbuffers - GPU_Resource *albedo; - GPU_Resource *emittance; - GPU_Resource *emittance_flood_read; - GPU_Resource *emittance_flood_target; - GPU_Resource *shade_read; - GPU_Resource *shade_target; - - //- Renderer transient buffers - GPU_TransientBuffer material_instances_tbuff; - GPU_TransientBuffer grids_tbuff; - Arena *material_instances_arena; - Arena *grids_arena; - - //- Renderer state - RandState frame_rand; - u64 frame_index; - i64 gpu_submit_fence_target; - - //- Bind state - PP_BindState bind_states[PP_BindKind_COUNT]; - - //- Window -> user - Mutex sys_window_events_mutex; - Arena *sys_window_events_arena; - - //- User -> sim - Mutex user_sim_cmd_mutex; - PP_ControlData user_sim_cmd_control; - PP_EntKey user_hovered_ent; - u64 last_user_sim_cmd_gen; - u64 user_sim_cmd_gen; - - Atomic32 user_paused; - Atomic32 user_paused_steps; - - //- Sim -> user - Mutex local_to_user_client_mutex; - PP_ClientStore *local_to_user_client_store; - PP_Client *local_to_user_client; - i64 local_to_user_client_publish_dt_ns; - i64 local_to_user_client_publish_time_ns; - - //- Local sim -> user rolling window of publish time deltas - i64 last_local_to_user_snapshot_published_at_ns; - i64 average_local_to_user_snapshot_publish_dt_ns; - - i64 local_sim_predicted_time_ns; /* Calculated from +