wine-detection. gpu debug/validation command line args

This commit is contained in:
jacob 2026-02-26 23:05:36 -06:00
parent 3061bba8e0
commit 58543ac517
11 changed files with 337 additions and 138 deletions

View File

@ -791,6 +791,7 @@ Inline u64 MixU64s(u64 seed_a, u64 seed_b)
b32 Panic(String msg);
Callstack CaptureCallstack(u64 skip_frames);
b32 IsRunningInDebugger(void);
b32 IsRunningInWine(void);
i64 TimeNs(void);
void TrueRand(String buffer);
CpuTopologyInfo GetCpuTopologyInfo(void);

View File

@ -102,6 +102,11 @@ b32 IsRunningInDebugger(void)
return IsDebuggerPresent();
}
b32 IsRunningInWine(void)
{
return W32.wine_version.len > 0;
}
i64 TimeNs(void)
{
LARGE_INTEGER qpc;
@ -445,10 +450,12 @@ i32 W32_Main(void)
// Get raw args from command line
Arena *perm = PermArena();
String cmdline_str = Zi;
{
StringList args_list = Zi;
{
LPCWSTR cmdline_wstr = GetCommandLineW();
wchar_t *cmdline_wstr = GetCommandLineW();
cmdline_str = StringFromWstrNoLimit(perm, cmdline_wstr);
i32 argc = 0;
LPWSTR *argv = CommandLineToArgvW(cmdline_wstr, &argc);
for (i32 i = 0; i < argc; ++i)
@ -461,6 +468,24 @@ i32 W32_Main(void)
W32.raw_command_line = args_list;
}
// Detect wine
{
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
if (ntdll)
{
typedef char *W32_WineVersionFunc(void);
W32_WineVersionFunc *wine_version_func = (W32_WineVersionFunc *)GetProcAddress(ntdll, "wine_get_version");
if (wine_version_func)
{
char *wine_version_cstr = wine_version_func();
if (wine_version_cstr)
{
W32.wine_version = PushString(perm, StringFromCstrNoLimit(wine_version_cstr));
}
}
}
}
//////////////////////////////
//- Bootstrap
@ -541,7 +566,11 @@ i32 W32_Main(void)
// Bootstrap log system
W32_BootstrapLogs();
LogInfoF("Main thread ID: %F", FmtUint(ThreadId()));
LogInfoF("Command line: [%F]", FmtString(cmdline_str));
if (W32.wine_version.len > 0)
{
LogInfoF("Wine version: \"%F\"", FmtString(W32.wine_version));
}
if (appdir_error.len > 0)
{
LogError(appdir_error);

View File

@ -65,6 +65,7 @@ Struct(W32_Ctx)
{
SYSTEM_INFO info;
u32 main_thread_id;
String wine_version;
Atomic32 shutdown;
Atomic32 exit_code;

View File

@ -4,7 +4,7 @@
#define SIM_PHYSICS_SUBSTEPS 4
#define SIM_TICKS_PER_SECOND 32
#define SIM_TICKS_PER_SECOND 64
#define SIM_TICK_INTERVAL_NS (NsFromSeconds(1) / SIM_TICKS_PER_SECOND)
// Like USER_INTERP_RATIO, but applies to snapshots received by the local sim from the
// master sim (how far back in time should the client render the server's state)
@ -12,8 +12,6 @@
#define GPU_NAMES IsRtcEnabled
#define GPU_DEBUG 0
#define GPU_DEBUG_VALIDATION 0
#define GPU_SHADER_PRINT 1
#define GPU_SHADER_PRINT_BUFFER_SIZE Kibi(64);

View File

@ -10,9 +10,25 @@ void G_Bootstrap(void)
Arena *perm = PermArena();
// NOTE: Nsight seems to have trouble attaching when independent devices are enabled
G_D12.independent_devices_enabled = !CommandlineArgFromName(Lit("no-independent-d3d12-device")).exists;
LogInfoF("D3D12 independent devices enabled: %F", FmtSint(G_D12.independent_devices_enabled));
G_D12.independent_devices_enabled = !CommandlineArgFromName(Lit("no-d3d12-independent-devices")).exists;
G_D12.validation_layer_enabled = CommandlineArgFromName(Lit("gpu-debug-validation")).exists;
G_D12.debug_layer_enabled = G_D12.validation_layer_enabled || CommandlineArgFromName(Lit("gpu-debug")).exists;
if (G_D12.independent_devices_enabled && IsRunningInWine())
{
LogInfoF("Wine detected, disabling D3D12 independent devices");
G_D12.independent_devices_enabled = 0;
}
LogInfoF("D3D12 independent devices enabled: %F", FmtSint(G_D12.independent_devices_enabled));
LogInfoF("D3D12 debug layer enabled: %F", FmtSint(G_D12.debug_layer_enabled));
LogInfoF("D3D12 validation layer enabled: %F", FmtSint(G_D12.validation_layer_enabled));
//////////////////////////////
//- Initialize independent device factory with Agility SDK
if (G_D12.independent_devices_enabled)
{
//////////////////////////////
//- Extract agility SDK
@ -59,17 +75,18 @@ void G_Bootstrap(void)
//////////////////////////////
//- Create device factory
if (G_D12.independent_devices_enabled)
{
D3D12GetInterface(&CLSID_D3D12SDKConfiguration, &IID_ID3D12SDKConfiguration1, (void **)&G_D12.sdk_config);
D3D12GetInterface(&CLSID_D3D12SDKConfiguration, &IID_ID3D12SDKConfiguration1, (void **)&G_D12.independent.sdk_config);
// Create device factory
char *sdk_dir_path_cstr = CstrFromString(scratch.arena, PathFromString(scratch.arena, sdk_dir_path, '\\'));
HRESULT hr = ID3D12SDKConfiguration1_CreateDeviceFactory(
G_D12.sdk_config,
G_D12.independent.sdk_config,
sdk_ver_num,
sdk_dir_path_cstr,
&IID_ID3D12DeviceFactory,
(void **)&G_D12.device_factory
(void **)&G_D12.independent.device_factory
);
if (FAILED(hr))
{
@ -77,17 +94,18 @@ void G_Bootstrap(void)
}
// Enable debug layer
if (GPU_DEBUG)
if (G_D12.debug_layer_enabled)
{
ID3D12Debug1 *debug = 0;
ID3D12DeviceFactory_GetConfigurationInterface(G_D12.device_factory, &CLSID_D3D12Debug, &IID_ID3D12Debug1, (void **)&debug);
ID3D12DeviceFactory_GetConfigurationInterface(G_D12.independent.device_factory, &CLSID_D3D12Debug, &IID_ID3D12Debug1, (void **)&debug);
ID3D12Debug1_EnableDebugLayer(debug);
if (GPU_DEBUG_VALIDATION)
if (G_D12.validation_layer_enabled)
{
ID3D12Debug1_SetEnableGPUBasedValidation(debug, 1);
}
}
}
}
//////////////////////////////
//- Initialize device
@ -98,7 +116,7 @@ void G_Bootstrap(void)
// Create dxgi factory
{
u32 dxgi_factory_flags = 0;
if (GPU_DEBUG)
if (G_D12.debug_layer_enabled)
{
dxgi_factory_flags |= DXGI_CREATE_FACTORY_DEBUG;
}
@ -133,7 +151,7 @@ void G_Bootstrap(void)
{
if (G_D12.independent_devices_enabled)
{
hr = ID3D12DeviceFactory_CreateDevice(G_D12.device_factory, (IUnknown *)adapter, D3D_FEATURE_LEVEL_12_0, &IID_ID3D12Device10, (void **)&device);
hr = ID3D12DeviceFactory_CreateDevice(G_D12.independent.device_factory, (IUnknown *)adapter, D3D_FEATURE_LEVEL_12_0, &IID_ID3D12Device10, (void **)&device);
}
else
{
@ -237,17 +255,8 @@ void G_Bootstrap(void)
G_D12.device = device;
}
// Retrieve device configuration
{
hr = ID3D12Device_QueryInterface(G_D12.device, &IID_ID3D12DeviceConfiguration, (void **)&G_D12.device_config);
if (FAILED(hr))
{
Panic(Lit("Failed to query ID3D12DeviceConfiguration interface"));
}
}
// Enable debug layer breaks
if (GPU_DEBUG)
if (G_D12.debug_layer_enabled)
{
// Enable D3D12 Debug break
{
@ -275,11 +284,17 @@ void G_Bootstrap(void)
}
}
// Log device configuration
// Retrieve device configuration
if (G_D12.independent_devices_enabled)
{
hr = ID3D12Device_QueryInterface(G_D12.device, &IID_ID3D12DeviceConfiguration, (void **)&G_D12.independent.device_config);
if (FAILED(hr))
{
Panic(Lit("Failed to query ID3D12DeviceConfiguration interface"));
}
D3D12_DEVICE_CONFIGURATION_DESC desc = Zi;
ID3D12DeviceConfiguration_GetDesc(G_D12.device_config, &desc);
ID3D12DeviceConfiguration_GetDesc(G_D12.independent.device_config, &desc);
StringList flags_list = Zi;
{
if (desc.Flags & D3D12_DEVICE_FLAG_DEBUG_LAYER_ENABLED) PushStringToList(scratch.arena, &flags_list, Lit("D3D12_DEVICE_FLAG_DEBUG_LAYER_ENABLED"));
@ -439,7 +454,7 @@ void G_Bootstrap(void)
desc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED | D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED;
if (G_D12.independent_devices_enabled)
{
hr = ID3D12DeviceConfiguration_SerializeVersionedRootSignature(G_D12.device_config, &desc, &blob, 0);
hr = ID3D12DeviceConfiguration_SerializeVersionedRootSignature(G_D12.independent.device_config, &desc, &blob, 0);
}
else
{
@ -1111,7 +1126,6 @@ i64 G_D12_CommitRawCommandList(G_D12_RawCommandList *cl)
{
completion_target = ++queue->commit_fence_target;
cl->commit_fence_target = completion_target;
ID3D12CommandQueue_Signal(queue->d3d_queue, queue->commit_fence, completion_target);
// Append

View File

@ -442,8 +442,10 @@ Struct(G_D12_AsyncCtx)
Struct(G_D12_Ctx)
{
b32 independent_devices_enabled;
IsolatedAtomic64 resource_creation_gen;
b32 independent_devices_enabled;
b32 debug_layer_enabled;
b32 validation_layer_enabled;
// Stats
Atomic64 arenas_count;
@ -476,10 +478,15 @@ Struct(G_D12_Ctx)
Mutex free_swapchains_mutex;
G_D12_Swapchain *first_free_swapchain;
// Device
// Independent device (only valid when independent_devices_enabled = 1)
struct
{
ID3D12SDKConfiguration1 *sdk_config;
ID3D12DeviceConfiguration *device_config;
ID3D12DeviceFactory *device_factory;
} independent;
// Device
IDXGIFactory6 *dxgi_factory;
IDXGIAdapter3 *dxgi_adapter;
ID3D12Device10 *device;

View File

@ -2067,6 +2067,10 @@ P_Frame *P_PushFrame(P_World *world, P_Frame *src_frame, i64 tick)
frame->world = world;
frame->tick = tick;
frame->time_ns = src_frame->time_ns;
frame->assembled_at_ns = src_frame->assembled_at_ns;
frame->base_time_ns = src_frame->base_time_ns;
frame->base_predict_from = src_frame->base_predict_from;
frame->base_predict_to = src_frame->base_predict_to;
frame->first_ent = &P_NilEnt;
frame->last_ent = &P_NilEnt;
@ -2412,8 +2416,8 @@ void P_StepFrame(P_Frame *frame)
{
if (Vec2Len(guy->v) > 0.001)
{
// f32 damp_force = TweakFloat("Guy damp force", 50, 0, 100);
f32 damp_force = TweakFloat("Guy damp force", 0, 0, 100);
f32 damp_force = TweakFloat("Guy damp force", 50, 0, 100);
// f32 damp_force = TweakFloat("Guy damp force", 0, 0, 100);
Vec2 damp = MulVec2(NegVec2(guy->v), damp_force * sim_dt);
guy->v = AddVec2(guy->v, damp);
}

View File

@ -369,6 +369,14 @@ Struct(P_Frame)
u64 fragments_count;
u64 received_fragments_count;
u64 received_fragment_bits[(P_MaxFrameSnapshotFragments + 63) / 64];
i64 assembled_at_ns;
//////////////////////////////
//- Prediction state
i64 base_time_ns;
i64 base_predict_from;
i64 base_predict_to;
};
Struct(P_FrameBin)

View File

@ -102,7 +102,7 @@ void S_TickForever(WaveLaneCtx *lane)
// TODO: Keep old frames around for player snapshot deltas
P_ClearFrames(world, I64Min, prev_world_frame->tick - 1);
i64 time_ns = TimeNs();
i64 begin_time_ns = TimeNs();
//////////////////////////////
//- Swap
@ -417,21 +417,27 @@ void S_TickForever(WaveLaneCtx *lane)
//- Apply bot controls
{
b32 bot_movement_enabled = TweakBool("Bot movement enabled", 1);
f32 move_bias = TweakFloat("Bot movement bias", 1, -1, 1);
f32 move_frequency = TweakFloat("Bot movement frequency", 0, 0, 10);
f32 turn_frequency = TweakFloat("Bot turn frequency", 0, 0, 10);
// b32 bot_movement_enabled = TweakBool("Bot movement enabled", 1);
for (P_Ent *bot = P_FirstEnt(world_frame); !P_IsEntNil(bot); bot = P_NextEnt(bot))
{
if (bot->is_bot)
{
if (bot_movement_enabled)
{
i64 alive_time_ns = time_ns - bot->created_at_ns;
i64 frequency_ns = NsFromSeconds(0.1);
bot->control.move.y = SinF32((f64)alive_time_ns / (f64)frequency_ns);
}
else
{
ZeroStruct(&bot->control.move);
}
i64 alive_time_ns = world_frame->time_ns - bot->created_at_ns;
f64 alive_time = SecondsFromNs(alive_time_ns);
// i64 frequency_ns = NsFromSeconds(0.1);
// bot->control.move.y = SinF32((f64)alive_time_ns / (f64)frequency_ns);
f32 move_t = alive_time * move_frequency * Tau;
f32 look_t = alive_time * turn_frequency * Tau;
bot->control.move.y = SinF32(move_t);
bot->control.move.y += move_bias;
bot->control.look = MulVec2(VEC2(CosF32(look_t), SinF32(look_t)), 3);
DEBUGBREAKABLE;
}
}
}
@ -988,7 +994,7 @@ void S_TickForever(WaveLaneCtx *lane)
if (!shutdown)
{
i64 step_dt_ns = SIM_TICK_INTERVAL_NS;
PLT_SleepFrame(time_ns, step_dt_ns);
PLT_SleepFrame(begin_time_ns, step_dt_ns);
}
}

View File

@ -364,7 +364,7 @@ void V_TickForever(WaveLaneCtx *lane)
P_World *sim_world = P_AcquireWorld();
i64 cur_predict_world_seq = 0;
P_World *predict_worlds[2] = Zi;
P_World *predict_worlds[V_MaxInterpRatio] = Zi;
for (i64 predict_world_idx = 0; predict_world_idx < countof(predict_worlds); ++predict_world_idx)
{
predict_worlds[predict_world_idx] = P_AcquireWorld();
@ -388,8 +388,9 @@ void V_TickForever(WaveLaneCtx *lane)
f64 most_recent_rtt = 0;
// i64 smoothed_rtt_ns = 0;
f64 smoothed_rtt = 0.0;
// f64 smoothed_rtt = 0.300;
f64 smoothed_rtt = 1.00;
// f64 smoothed_rtt = 1.00;
// f64 smoothed_rtt = 2;
f32 smooth_remote_buffered_ticks = 0;
@ -576,6 +577,8 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Begin frame
i64 prev_frame_ack = ack;
V.cur_frame_tick += 1;
V_Frame *prev_frame = V_PrevFrame();
V_Frame *frame = V_CurrentFrame();
@ -1016,11 +1019,10 @@ void V_TickForever(WaveLaneCtx *lane)
Vec2 look_pos = frame->look;
look_pos = RotateVec2(look_pos, InvertRot(rot));
P_Ent *player = P_EntFromKey(frame->local_world->last_frame, V.player_key);
P_Ent *guy = P_EntFromKey(frame->local_world->last_frame, player->guy);
Vec2 guy_center = P_WorldShapeFromEnt(guy).centroid;
P_Ent *follow = P_EntFromKey(frame->local_world->last_frame, V.follow_key);
Vec2 follow_center = P_WorldShapeFromEnt(follow).centroid;
Vec2 screen_center = MulVec2(frame->screen_dims, 0.5);
target_camera_pos = guy_center;
target_camera_pos = follow_center;
target_camera_pos = AddVec2(target_camera_pos, MulVec2Vec2(look_pos, look_ratio));
target_camera_zoom = 1;
}
@ -1028,6 +1030,12 @@ void V_TickForever(WaveLaneCtx *lane)
target_camera_pos.y = ClampF32(target_camera_pos.y, -world_pitch / 2, world_pitch / 2);
target_camera_zoom = ClampF32(target_camera_zoom, min_zoom, max_zoom);
if (IsNan(target_camera_pos.x) || IsNan(target_camera_pos.y) || IsNan(target_camera_zoom))
{
target_camera_pos = VEC2(0, 0);
target_camera_zoom = 1;
}
// Interpolate camera
{
if (prev_frame->tick == 0)
@ -1302,6 +1310,7 @@ void V_TickForever(WaveLaneCtx *lane)
ack = dst_tick;
ack_dt_ns = ack_received_at_ns - frame->time_ns;
ack_received_at_ns = frame->time_ns;
dst_frame->assembled_at_ns = frame->time_ns;
}
}
}
@ -1569,6 +1578,8 @@ void V_TickForever(WaveLaneCtx *lane)
}
}
P_Frame *ack_frame = P_FrameFromTick(sim_world, ack);
//////////////////////////////
//- Predict
@ -1608,7 +1619,7 @@ void V_TickForever(WaveLaneCtx *lane)
i64 max_predict_ticks = SIM_TICKS_PER_SECOND;
last_predict_tick = predict_to;
first_predict_tick = ack;
first_predict_tick = MaxI64(first_predict_tick, last_predict_tick - max_predict_ticks);
// first_predict_tick = MaxI64(first_predict_tick, last_predict_tick - max_predict_ticks);
}
@ -1629,12 +1640,23 @@ void V_TickForever(WaveLaneCtx *lane)
if (ack != prev_frame_ack)
{
ack_frame->base_time_ns = ack_frame->time_ns;
ack_frame->base_predict_from = ack_frame->tick;
ack_frame->base_predict_to = predict_to;
cur_predict_world_seq += 1;
}
// Predict
P_World *predict_world = predict_worlds[cur_predict_world_seq % countof(predict_worlds)];
P_World *prev_predict_world = predict_worlds[MaxI64(cur_predict_world_seq - 1, 0) % countof(predict_worlds)];
P_Frame *predict_frame = predict_world->last_frame;
{
if (predict_world->tiles_hash != sim_world->tiles_hash)
@ -1645,7 +1667,8 @@ void V_TickForever(WaveLaneCtx *lane)
predict_world->seed = sim_world->seed;
// P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - 1, prev_frame->blend_from_tick - 1));
P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - 2, prev_frame->blend_from_tick - 1));
// P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - 2, prev_frame->blend_from_tick - 1));
// P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - V_MaxInterpRatio, prev_frame->blend_from_tick - 1));
predict_frame = P_PushFrame(predict_world, P_FrameFromTick(sim_world, first_predict_tick), first_predict_tick);
for (i64 predict_tick = first_predict_tick + 1; predict_tick <= last_predict_tick; ++predict_tick)
@ -1866,8 +1889,8 @@ void V_TickForever(WaveLaneCtx *lane)
frame->local_world->seed = predict_world->seed;
P_ClearFrames(frame->local_world, I64Min, I64Max);
i64 target_blend_dt_ns = frame->dt_ns + frame->dt_ns * dilation_factor;
// i64 target_blend_dt_ns = frame->dt_ns;
// i64 target_blend_dt_ns = frame->dt_ns + frame->dt_ns * dilation_factor;
i64 target_blend_dt_ns = frame->dt_ns;
i64 blend_dt_ns = frame->dt_ns;
V.target_blend_time_ns += target_blend_dt_ns;
@ -1876,14 +1899,16 @@ void V_TickForever(WaveLaneCtx *lane)
// How many ticks back in time should the user thread blend between?
// <Delay> = <USER_INTERP_RATIO> * <Tick interval>
// E.g: At 1.5, the world will render 75ms back in time if the sim runs at 50tps
f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, 5);
if (predict_to != prev_frame_predict_to)
f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
if (ack != prev_frame_ack)
{
i64 delay_ns = SIM_TICK_INTERVAL_NS * interp_ratio;
V.target_blend_time_ns = predict_world->last_frame->time_ns - delay_ns;
V.target_blend_time_ns = ack_frame->time_ns - delay_ns;
}
f64 blend_to_target_lerp_rate = 0.05;
// f64 blend_to_target_lerp_rate = 0.05;
f64 blend_to_target_lerp_rate = 1;
// f64 blend_to_target_lerp_rate = 1;
V.blend_time_ns = LerpI64(V.blend_time_ns, V.target_blend_time_ns, blend_to_target_lerp_rate);
if (AbsI64(V.blend_time_ns - V.target_blend_time_ns) > (SIM_TICK_INTERVAL_NS * interp_ratio * 2))
{
@ -1891,24 +1916,107 @@ void V_TickForever(WaveLaneCtx *lane)
V.blend_time_ns = V.target_blend_time_ns;
}
if (TweakBool("Interpolation enabled", 1))
if (TweakBool("Interpolation enabled", 0))
{
P_Frame *left_predict_frame = &P_NilFrame;
P_Frame *right_predict_frame = &P_NilFrame;
for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
// for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
// {
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
// {
// right_predict_frame = tmp;
// left_predict_frame = tmp->prev;
// break;
// }
// }
{
if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
for (
i64 predict_world_seq = cur_predict_world_seq;
predict_world_seq > MaxI64(0, cur_predict_world_seq - countof(predict_worlds));
--predict_world_seq
)
{
right_predict_frame = tmp;
left_predict_frame = tmp->prev;
i64 tmp_right_predict_world_idx = predict_world_seq % countof(predict_worlds);
i64 tmp_left_predict_world_idx = (predict_world_seq - 1) % countof(predict_worlds);
P_World *tmp_right_world = predict_worlds[tmp_right_predict_world_idx];
P_World *tmp_left_world = predict_worlds[tmp_left_predict_world_idx];
// P_Frame *tmp_right = P_FrameFromTick(tmp_right_world, tmp_right_world->last_frame->base_predict_to);
// P_Frame *tmp_left = P_FrameFromTick(tmp_left_world, tmp_left_world->last_frame->base_predict_to);
// P_Frame *tmp_right = tmp_right_world->last_frame;
// P_Frame *tmp_left = tmp_left_world->last_frame;
P_Frame *tmp_right = P_FrameFromTick(tmp_right_world, tmp_right_world->last_frame->base_predict_from);
P_Frame *tmp_left = P_FrameFromTick(tmp_left_world, tmp_left_world->last_frame->base_predict_from);
// P_Frame *tmp_right = tmp_right_world->last_frame;
// P_Frame *tmp_left = tmp_left_world->last_frame;
if (tmp_right->base_time_ns >= V.blend_time_ns && tmp_left->base_time_ns <= V.blend_time_ns)
{
right_predict_frame = tmp_right;
left_predict_frame = tmp_left;
break;
}
}
// for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
// {
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
// {
// right_predict_frame = tmp;
// break;
// }
// }
// for (P_Frame *tmp = prev_predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
// {
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
// {
// left_predict_frame = tmp->prev;
// break;
// }
// }
}
// for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
// {
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
// {
// right_predict_frame = tmp;
// break;
// }
// }
// for (P_Frame *tmp = prev_predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
// {
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
// {
// left_predict_frame = tmp->prev;
// break;
// }
// }
if (P_IsFrameNil(left_predict_frame) || P_IsFrameNil(right_predict_frame))
{
LogDebugF("Missing blend");
right_predict_frame = predict_world->last_frame;
left_predict_frame = right_predict_frame->prev;
// left_predict_frame = right_predict_frame->prev;
left_predict_frame = right_predict_frame;
}
frame->blend_from_tick = left_predict_frame->tick;
@ -1916,6 +2024,9 @@ void V_TickForever(WaveLaneCtx *lane)
local_frame = P_PushFrame(frame->local_world, left_predict_frame, left_predict_frame->tick);
{
P_Frame *left_sim_frame = left_predict_frame;
P_Frame *right_sim_frame = right_predict_frame;
// P_Frame *left_sim_frame = predict_world->first_frame;
// P_Frame *right_sim_frame = left_sim_frame->next;
@ -1926,12 +2037,17 @@ void V_TickForever(WaveLaneCtx *lane)
// P_Frame *right_sim_frame = P_FrameFromTick(sim_world, ack - 1);
// P_Frame *left_sim_frame = right_sim_frame->prev;
P_Frame *right_sim_frame = P_FrameFromTick(sim_world, right_predict_frame->src_tick);
P_Frame *left_sim_frame = right_sim_frame->prev;
// P_Frame *right_sim_frame = P_FrameFromTick(sim_world, right_predict_frame->src_tick);
// P_Frame *left_sim_frame = right_sim_frame->prev;
f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->base_time_ns) / (f64)(right_predict_frame->base_time_ns - left_predict_frame->base_time_ns);
if (IsInf(blend_t))
{
blend_t = 1;
}
f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->time_ns) / (f64)(right_predict_frame->time_ns - left_predict_frame->time_ns);
LogDebugF("blend_t: %F", FmtFloat(blend_t));
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
{
@ -2103,6 +2219,12 @@ void V_TickForever(WaveLaneCtx *lane)
P_Ent *local_player = P_EntFromKey(frame->local_world->last_frame, V.player_key);
P_Ent *local_guy = P_EntFromKey(frame->local_world->last_frame, local_player->guy);
P_Ent *local_follow = P_EntFromKey(frame->local_world->last_frame, V.follow_key);
if (P_IsEntNil(local_follow))
{
local_follow = local_guy;
V.follow_key = local_guy->key;
}
//////////////////////////////
//- Compute crosshair position
@ -2111,7 +2233,8 @@ void V_TickForever(WaveLaneCtx *lane)
if (!P_IsEntNil(local_guy))
{
P_Ent *ent = local_guy;
// P_Ent *ent = local_guy;
P_Ent *ent = local_follow;
P_Anim anim = P_AnimFromEnt(local_frame, ent);
SPR_Sprite body = SPR_SpriteFromSheet(anim.sheet, anim.span, anim.frame_seq);
@ -2311,11 +2434,17 @@ void V_TickForever(WaveLaneCtx *lane)
}
}
if (frame->held_buttons[Button_V])
{
if (frame->held_buttons[Button_Shift])
{
V.follow_key = local_guy->key;
}
else if (!P_IsEntNil(hovered_ent))
{
V.follow_key = hovered_ent->key;
}
}
//////////////////////////////
//- Draw entities
@ -2725,9 +2854,9 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Push test emitter
// if (frame->held_buttons[Button_F])
if (frame->held_buttons[Button_F])
// if (frame->held_buttons[Button_F] && !prev_frame->held_buttons[Button_F])
if (0)
// if (0)
{
{
V_Emitter emitter = Zi;
@ -2787,9 +2916,9 @@ void V_TickForever(WaveLaneCtx *lane)
//////////////////////////////
//- Push test explosion
// if (frame->held_buttons[Button_G])
if (frame->held_buttons[Button_G])
// if (frame->held_buttons[Button_G] && !prev_frame->held_buttons[Button_G])
if (0)
// if (0)
{
// Fire
{
@ -5313,7 +5442,6 @@ void V_TickForever(WaveLaneCtx *lane)
G_DumbMemoryLayoutSync(cl, screen_target, G_Layout_DirectQueue_General);
}
//////////////////////////////
//- Set UI box texture

View File

@ -218,6 +218,8 @@ Enum(V_DrawFlag)
////////////////////////////////////////////////////////////
//~ State types
#define V_MaxInterpRatio 4
Struct(V_Frame)
{
Arena *arena;
@ -255,6 +257,7 @@ Struct(V_Frame)
Struct(V_Ctx)
{
P_EntKey player_key;
P_EntKey follow_key;
i64 panels_count;
i64 windows_count;