sort profiler tracks by wave/lane priority
This commit is contained in:
parent
f17bdc9d76
commit
ee4579bd2d
@ -4,7 +4,7 @@
|
||||
void BootstrapAsync(void)
|
||||
{
|
||||
// TODO: Dynamic lane counts
|
||||
DispatchWave(Lit("Async"), 4, AsyncWorkerEntryPoint, 0);
|
||||
DispatchWave(Lit("Async"), 4, AsyncWorkerEntryPoint, 0, PROFILER_PRIORITY_ASYNC);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
@ -7,13 +7,13 @@
|
||||
#if IsCpu
|
||||
#include "base_memory.h"
|
||||
#include "base_arena.h"
|
||||
#include "base_math.h"
|
||||
#include "base_wave.h"
|
||||
#include "base_prof.h"
|
||||
#include "base_futex.h"
|
||||
#include "base_sync.h"
|
||||
#include "base_time.h"
|
||||
#include "base_uid.h"
|
||||
#include "base_math.h"
|
||||
#include "base_wave.h"
|
||||
#include "base_string.h"
|
||||
#include "base_cmdline.h"
|
||||
#include "base_log.h"
|
||||
|
||||
@ -11,6 +11,7 @@ void BeginProfZone(char *name_cstr_lit)
|
||||
track = PushStruct(perm, ProfTrack);
|
||||
Base_tl.prof.thread_track = track;
|
||||
}
|
||||
track->lane = CurrentLaneCtx();
|
||||
LockTicketMutex(&Base.prof.register_track_tm);
|
||||
{
|
||||
u64 track_idx = Atomic32Fetch(&Base.prof.tracks_count);
|
||||
|
||||
@ -21,6 +21,7 @@ Struct(ProfSample)
|
||||
Struct(ProfTrack)
|
||||
{
|
||||
u64 id;
|
||||
WaveLaneCtx *lane;
|
||||
Atomic64 top_sample_seq;
|
||||
ProfSample samples_ring[ProfSamplesRingCap];
|
||||
};
|
||||
|
||||
@ -20,6 +20,7 @@ Struct(BaseThreadLocalCtx)
|
||||
{
|
||||
ThreadLocalArenaCtx arenas;
|
||||
ThreadLocalProfCtx prof;
|
||||
ThreadLocalWaveLaneCtx wave;
|
||||
};
|
||||
|
||||
extern ThreadLocal BaseThreadLocalCtx Base_tl;
|
||||
|
||||
@ -108,7 +108,7 @@ void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Task helpers
|
||||
//~ Lane helpers
|
||||
|
||||
i32 WaveLaneIdxFromTaskIdx(WaveLaneCtx *lane, u64 task_idx)
|
||||
{
|
||||
|
||||
@ -6,8 +6,11 @@
|
||||
|
||||
AlignedStruct(WaveCtx, IsolationSize)
|
||||
{
|
||||
i32 lanes_count;
|
||||
String name;
|
||||
void *udata;
|
||||
i32 lanes_count;
|
||||
i32 profiler_priority;
|
||||
|
||||
|
||||
// Sync barrier
|
||||
IsolatedAtomic64 sync_gen;
|
||||
@ -30,6 +33,11 @@ AlignedStruct(WaveLaneCtx, IsolationSize)
|
||||
|
||||
typedef void WaveLaneEntryFunc(WaveLaneCtx *lane);
|
||||
|
||||
Struct(ThreadLocalWaveLaneCtx)
|
||||
{
|
||||
WaveLaneCtx *lane;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Wave sync ops
|
||||
|
||||
@ -48,15 +56,17 @@ void WaveSyncBroadcastEx_(WaveLaneCtx *lane, u32 broadcast_lane_idx, void *broad
|
||||
void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Task helpers
|
||||
//~ Lane helers
|
||||
|
||||
i32 WaveLaneIdxFromTaskIdx(WaveLaneCtx *lane, u64 task_idx);
|
||||
RngU64 WaveIdxRangeFromCount(WaveLaneCtx *lane, u64 tasks_count);
|
||||
|
||||
#define CurrentLaneCtx() (Base_tl.wave.lane)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ @hookdecl Dispatch
|
||||
|
||||
void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *udata);
|
||||
void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *udata, i32 profiler_priority);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ @hookdecl Thread
|
||||
|
||||
@ -641,9 +641,14 @@ i32 W32_Main(void)
|
||||
GetSystemInfo(&W32.info);
|
||||
|
||||
// Init main thread
|
||||
W32_InitCurrentThread(Lit("Main"));
|
||||
WaveCtx wave = Zi;
|
||||
WaveLaneCtx lane = Zi;
|
||||
wave.name = Lit("Main");
|
||||
wave.lanes_count = 1;
|
||||
lane.wave = &wave;
|
||||
lane.default_spin_count = DefaultWaveLaneSpinCount;
|
||||
W32_InitCurrentThread(&lane);
|
||||
W32.main_thread_id = GetCurrentThreadId();
|
||||
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
||||
|
||||
// Setup logging memory
|
||||
W32.logs_arena = AcquireArena(Gibi(64));
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Thread
|
||||
|
||||
void W32_InitCurrentThread(String name)
|
||||
String W32_InitCurrentThread(WaveLaneCtx *lane)
|
||||
{
|
||||
// Init thread arenas
|
||||
// Init thread state
|
||||
{
|
||||
Base_tl.arenas.perm = AcquireArena(Gibi(64));
|
||||
for (i32 i = 0; i < (i32)countof(Base_tl.arenas.scratch); ++i)
|
||||
@ -12,20 +12,30 @@ void W32_InitCurrentThread(String name)
|
||||
}
|
||||
}
|
||||
Arena *perm = PermArena();
|
||||
Base_tl.wave.lane = lane;
|
||||
|
||||
|
||||
// Set thread name
|
||||
wchar_t *thread_name_wstr = WstrFromString(perm, name);
|
||||
WaveCtx *wave = lane->wave;
|
||||
String thread_name = wave->name;
|
||||
if (wave->lanes_count > 1)
|
||||
{
|
||||
thread_name = StringF(perm, "%F:%F", FmtString(wave->name), FmtUint(lane->idx));
|
||||
}
|
||||
wchar_t *thread_name_wstr = WstrFromString(perm, thread_name);
|
||||
SetThreadDescription(GetCurrentThread(), thread_name_wstr);
|
||||
|
||||
// Initialize COM
|
||||
CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
|
||||
return thread_name;
|
||||
}
|
||||
|
||||
DWORD WINAPI W32_ThreadProc(LPVOID thread_args_vp)
|
||||
{
|
||||
W32_ThreadArgs *thread_args = (W32_ThreadArgs *)thread_args_vp;
|
||||
W32_InitCurrentThread(thread_args->name);
|
||||
LogInfoF("New thread \"%F\" created with ID %F", FmtString(thread_args->name), FmtUint(ThreadId()));
|
||||
String thread_name = W32_InitCurrentThread(thread_args->lane);
|
||||
LogInfoF("New thread \"%F\" created with ID %F", FmtString(thread_name), FmtUint(ThreadId()));
|
||||
thread_args->entry(thread_args->lane);
|
||||
return 0;
|
||||
}
|
||||
@ -33,12 +43,12 @@ DWORD WINAPI W32_ThreadProc(LPVOID thread_args_vp)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ @hookimpl Dispatch
|
||||
|
||||
void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *udata)
|
||||
void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *udata, i32 profiler_priority)
|
||||
{
|
||||
Arena *perm = PermArena();
|
||||
PERSIST Atomic64 num_threads_allocated = Zi;
|
||||
|
||||
// Catch high lane count to prevent OS crash
|
||||
// Catch high lane count to prevent windows BSOD
|
||||
i64 old_num_threads_allocated = Atomic64FetchAdd(&num_threads_allocated, num_lanes);
|
||||
i64 new_num_threads_allocated = old_num_threads_allocated + num_lanes;
|
||||
if (new_num_threads_allocated > MaxThreads)
|
||||
@ -55,8 +65,10 @@ void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *ud
|
||||
}
|
||||
|
||||
WaveCtx *wave_ctx = PushStruct(perm, WaveCtx);
|
||||
wave_ctx->name = PushString(perm, name);
|
||||
wave_ctx->lanes_count = num_lanes;
|
||||
wave_ctx->udata = udata;
|
||||
wave_ctx->profiler_priority = profiler_priority;
|
||||
|
||||
for (u32 lane_idx = 0; lane_idx < num_lanes; ++lane_idx)
|
||||
{
|
||||
@ -65,21 +77,10 @@ void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *ud
|
||||
lane_ctx->wave = wave_ctx;
|
||||
lane_ctx->default_spin_count = DefaultWaveLaneSpinCount;
|
||||
|
||||
String thread_name = Zi;
|
||||
if (num_lanes > 1)
|
||||
{
|
||||
thread_name = StringF(perm, "%F:%F", FmtString(name), FmtUint(lane_idx));
|
||||
}
|
||||
else
|
||||
{
|
||||
thread_name = PushString(perm, name);
|
||||
}
|
||||
|
||||
W32_ThreadArgs *thread_args = PushStruct(perm, W32_ThreadArgs);
|
||||
thread_args->lane = lane_ctx;
|
||||
thread_args->udata = udata;
|
||||
thread_args->entry = entry;
|
||||
thread_args->name = thread_name;
|
||||
|
||||
HANDLE handle = CreateThread(0, Mebi(4), W32_ThreadProc, thread_args, 0, 0);
|
||||
if (!handle)
|
||||
|
||||
@ -6,12 +6,11 @@ Struct(W32_ThreadArgs)
|
||||
void *udata;
|
||||
WaveLaneCtx *lane;
|
||||
WaveLaneEntryFunc *entry;
|
||||
String name;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Thread
|
||||
|
||||
void W32_InitCurrentThread(String name);
|
||||
String W32_InitCurrentThread(WaveLaneCtx *lane);
|
||||
|
||||
DWORD WINAPI W32_ThreadProc(LPVOID thread_args_vp);
|
||||
|
||||
@ -27,6 +27,11 @@
|
||||
#define PROFILING_ENABLED 1
|
||||
|
||||
|
||||
#define PROFILER_PRIORITY_ASYNC 10
|
||||
#define PROFILER_PRIORITY_SIM 20
|
||||
#define PROFILER_PRIORITY_VIS 30
|
||||
|
||||
|
||||
|
||||
// TODO: Move these to user-configurable settings
|
||||
|
||||
|
||||
@ -611,7 +611,7 @@ void G_Bootstrap(void)
|
||||
|
||||
OnAsyncTick(G_D12_TickAsync);
|
||||
|
||||
DispatchWave(Lit("Gpu collection worker"), 1, G_D12_CollectionWorkerEntryPoint, 0);
|
||||
DispatchWave(Lit("Gpu collection worker"), 1, G_D12_CollectionWorkerEntryPoint, 0, 0);
|
||||
|
||||
EndScratch(scratch);
|
||||
}
|
||||
|
||||
@ -1453,5 +1453,5 @@ void BootstrapLayers(void)
|
||||
{
|
||||
OS_Bootstrap();
|
||||
i32 meta_lanes_count = 32;
|
||||
DispatchWave(Lit("Meta"), MaxI32(meta_lanes_count, 1), M_BuildEntryPoint, 0);
|
||||
DispatchWave(Lit("Meta"), MaxI32(meta_lanes_count, 1), M_BuildEntryPoint, 0, 0);
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ void NET_Bootstrap(void)
|
||||
NET_W32.iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
|
||||
|
||||
// Start worker
|
||||
DispatchWave(Lit("Net"), 1, NET_W32_TickForever, 0);
|
||||
DispatchWave(Lit("Net"), 1, NET_W32_TickForever, 0, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
@ -9,7 +9,7 @@ void PLT_Bootstrap(void)
|
||||
PLT_W32.watches_arena = AcquireArena(Gibi(64));
|
||||
|
||||
// Init timer
|
||||
DispatchWave(Lit("Win32 timer sync"), 1, PLT_W32_SyncTimerForever, 0);
|
||||
DispatchWave(Lit("Win32 timer sync"), 1, PLT_W32_SyncTimerForever, 0, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
@ -15,7 +15,7 @@ void S_Bootstrap(void)
|
||||
S.client_bins_count = Kibi(4);
|
||||
S.client_bins = PushStructsNoZero(perm, S_ClientBin, S.client_bins_count);
|
||||
|
||||
DispatchWave(Lit("Sim"), 1, S_TickForever, 0);
|
||||
DispatchWave(Lit("Sim"), 1, S_TickForever, 0, PROFILER_PRIORITY_SIM);
|
||||
OnExit(S_Shutdown);
|
||||
}
|
||||
|
||||
@ -682,7 +682,7 @@ void S_TickForever(WaveLaneCtx *lane)
|
||||
bot->is_player = 1;
|
||||
bot->is_bot = 1;
|
||||
{
|
||||
String bot_name = P_PresetPlayerNames[bots_count % countof(P_PresetPlayerNames)];
|
||||
String bot_name = P_PresetBotNames[bots_count % countof(P_PresetBotNames)];
|
||||
P_SetEntString(bot, bot_name);
|
||||
}
|
||||
bots_count += 1;
|
||||
|
||||
@ -49,32 +49,32 @@ PERSIST Readonly String P_PresetHumanNames[] = {
|
||||
CompLit("Buck"),
|
||||
};
|
||||
|
||||
// Taken from a random GMOD server
|
||||
PERSIST Readonly String P_PresetPlayerNames[] = {
|
||||
CompLit("Tidunbly"),
|
||||
CompLit("lowayo"),
|
||||
CompLit("_Runne_"),
|
||||
CompLit("lionberg"),
|
||||
CompLit("charlie main"),
|
||||
CompLit("Fr0stie"),
|
||||
CompLit("Mr. Bones"),
|
||||
CompLit("Legs"),
|
||||
CompLit("Poy"),
|
||||
CompLit("frezh"),
|
||||
CompLit("Kirep"),
|
||||
CompLit("Cyan Crayon"),
|
||||
CompLit("THE WIFE"),
|
||||
CompLit("Panda"),
|
||||
CompLit("KARMA"),
|
||||
CompLit("adoti"),
|
||||
CompLit("yoyota"),
|
||||
CompLit("TaurusJ3"),
|
||||
CompLit("dub"),
|
||||
CompLit("Siepter"),
|
||||
CompLit("Zunix"),
|
||||
CompLit("Lumby"),
|
||||
CompLit("Talids"),
|
||||
CompLit("Train"),
|
||||
CompLit("Kaitsedd"),
|
||||
CompLit("jiyu"),
|
||||
// Names taken from some random GMOD server
|
||||
PERSIST Readonly String P_PresetBotNames[] = {
|
||||
CompLit("[Bot] Tidunbly"),
|
||||
CompLit("[Bot] lowayo"),
|
||||
CompLit("[Bot] _Runne_"),
|
||||
CompLit("[Bot] lionberg"),
|
||||
CompLit("[Bot] charlie main"),
|
||||
CompLit("[Bot] Fr0stie"),
|
||||
CompLit("[Bot] Mr. Bones"),
|
||||
CompLit("[Bot] Legs"),
|
||||
CompLit("[Bot] Poy"),
|
||||
CompLit("[Bot] frezh"),
|
||||
CompLit("[Bot] Kirep"),
|
||||
CompLit("[Bot] Cyan Crayon"),
|
||||
CompLit("[Bot] THE WIFE"),
|
||||
CompLit("[Bot] Panda"),
|
||||
CompLit("[Bot] KARMA"),
|
||||
CompLit("[Bot] adoti"),
|
||||
CompLit("[Bot] yoyota"),
|
||||
CompLit("[Bot] TaurusJ3"),
|
||||
CompLit("[Bot] dub"),
|
||||
CompLit("[Bot] Siepter"),
|
||||
CompLit("[Bot] Zunix"),
|
||||
CompLit("[Bot] Lumby"),
|
||||
CompLit("[Bot] Talids"),
|
||||
CompLit("[Bot] Train"),
|
||||
CompLit("[Bot] Kaitsedd"),
|
||||
CompLit("[Bot] jiyu"),
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -234,7 +234,7 @@ Struct(V_Palette)
|
||||
{
|
||||
Vec2 pos;
|
||||
UI_Key key;
|
||||
b32 is_showing;
|
||||
b32 should_show;
|
||||
f32 show;
|
||||
|
||||
f32 scroll;
|
||||
@ -250,6 +250,7 @@ Struct(V_Palette)
|
||||
f32 caret_start_px;
|
||||
f32 caret_end_px;
|
||||
f32 text_scroll_px;
|
||||
f32 text_scroll_view_width_px;
|
||||
|
||||
V_TextboxState search_state;
|
||||
};
|
||||
@ -287,6 +288,7 @@ Struct(V_ZoneTrack)
|
||||
{
|
||||
V_ZoneTrack *next;
|
||||
V_Zone *root_zone;
|
||||
WaveLaneCtx *lane;
|
||||
u64 id;
|
||||
|
||||
ProfTrack *prof_track;
|
||||
@ -432,6 +434,7 @@ Struct(V_Frame)
|
||||
f64 blend_sim_tick;
|
||||
f64 blend_predict_tick;
|
||||
|
||||
b32 is_resizing;
|
||||
b32 held_buttons[Button_COUNT]; // User input state captured for gameplay
|
||||
b32 real_held_buttons[Button_COUNT]; // Actual state of user input regardless of keyboard / mouse focus
|
||||
V_Palette palette;
|
||||
|
||||
@ -826,8 +826,6 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
//- Update mouse capture tree
|
||||
top_hot_box = top_active_box ? top_active_box : top_hovered_box;
|
||||
|
||||
//- Update box feedback
|
||||
@ -866,55 +864,12 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
|
||||
f32 target_exists = feedback->exists_absolute ? upper_target : lower_target;
|
||||
f64 target_misc = box->desc.misc;
|
||||
|
||||
// f32 delta_active_rate = box->desc.active_rate * frame->dt;
|
||||
// f32 delta_hot_rate = box->desc.hot_rate * frame->dt;
|
||||
// f32 delta_hovered_rate = box->desc.hovered_rate * frame->dt;
|
||||
// f32 delta_exists_rate = box->desc.exists_rate * frame->dt;
|
||||
// f32 delta_misc_rate = box->desc.misc_rate * frame->dt;
|
||||
// // delta_active_rate = IsNan(delta_active_rate) ? 1 : delta_active_rate;
|
||||
// // delta_hot_rate = IsNan(delta_hot_rate) ? 1 : delta_hot_rate;
|
||||
// // delta_hovered_rate = IsNan(delta_hovered_rate) ? 1 : delta_hovered_rate;
|
||||
// // delta_exists_rate = IsNan(delta_exists_rate) ? 1 : delta_exists_rate;
|
||||
// // delta_misc_rate = IsNan(delta_misc_rate) ? 1 : delta_misc_rate;
|
||||
|
||||
// feedback->active_smooth = SaturateF32(LerpF32(feedback->active_smooth, target_active, delta_active_rate));
|
||||
// feedback->hot_smooth = SaturateF32(LerpF32(feedback->hot_smooth, target_hot, delta_hot_rate));
|
||||
// feedback->hovered_smooth = SaturateF32(LerpF32(feedback->hovered_smooth, target_hovered, delta_hovered_rate));
|
||||
// feedback->exists_smooth = SaturateF32(LerpF32(feedback->exists_smooth, target_exists, delta_exists_rate));
|
||||
// feedback->misc_smooth = SaturateF64(LerpF64(feedback->misc_smooth, target_misc, delta_misc_rate));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
feedback->active_smooth = SaturateF32(LerpF32(feedback->active_smooth, target_active, box->desc.active_rate * frame->dt));
|
||||
feedback->hot_smooth = SaturateF32(LerpF32(feedback->hot_smooth, target_hot, box->desc.hot_rate * frame->dt));
|
||||
feedback->hovered_smooth = SaturateF32(LerpF32(feedback->hovered_smooth, target_hovered, box->desc.hovered_rate * frame->dt));
|
||||
feedback->exists_smooth = SaturateF32(LerpF32(feedback->exists_smooth, target_exists, box->desc.exists_rate * frame->dt));
|
||||
feedback->misc_smooth = SaturateF64(LerpF64(feedback->misc_smooth, target_misc, box->desc.misc_rate * frame->dt));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// f32 active_blend_rate = (15 * frame->dt);
|
||||
// f32 hot_blend_rate = (15 * frame->dt);
|
||||
// f32 hovered_blend_rate = (15 * frame->dt);
|
||||
// f32 exists_blend_rate = (30 * frame->dt);
|
||||
// // f64 misc_blend_rate = (30 * frame->dt);
|
||||
// f64 misc_blend_rate = 1;
|
||||
|
||||
// feedback->active_smooth = SaturateF32(LerpF32(feedback->active_smooth, target_active, active_blend_rate));
|
||||
// feedback->hot_smooth = SaturateF32(LerpF32(feedback->hot_smooth, target_hot, hot_blend_rate));
|
||||
// feedback->hovered_smooth = SaturateF32(LerpF32(feedback->hovered_smooth, target_hovered, hovered_blend_rate));
|
||||
// feedback->exists_smooth = SaturateF32(LerpF32(feedback->exists_smooth, target_exists, exists_blend_rate));
|
||||
// feedback->misc_smooth = SaturateF32(LerpF32(feedback->misc_smooth, target_misc, misc_blend_rate));
|
||||
|
||||
|
||||
|
||||
feedback->misc_smooth = LerpF64(feedback->misc_smooth, target_misc, SaturateF64(box->desc.misc_rate * frame->dt));
|
||||
|
||||
feedback->screen_rect = box->screen_rect;
|
||||
feedback->screen_anchor = box->screen_anchor;
|
||||
|
||||
@ -314,7 +314,7 @@ Struct(UI_BoxDesc)
|
||||
f32 hot_rate;
|
||||
f32 hovered_rate;
|
||||
f32 exists_rate;
|
||||
f32 misc_rate;
|
||||
f64 misc_rate;
|
||||
Vec2 dims_rate;
|
||||
};
|
||||
|
||||
|
||||
@ -111,7 +111,7 @@ void WND_Bootstrap(void)
|
||||
//////////////////////////////
|
||||
//- Dispatch msg processor
|
||||
|
||||
DispatchWave(Lit("Win32 msg loop"), 1, WND_W32_ProcessMessagesForever, 0);
|
||||
DispatchWave(Lit("Win32 msg loop"), 1, WND_W32_ProcessMessagesForever, 0, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
Loading…
Reference in New Issue
Block a user