simple in-game debug console
This commit is contained in:
parent
716a26e42c
commit
d48706d1f7
@ -268,8 +268,7 @@ void app_entry_point(struct string args_str)
|
||||
struct string logfile_path = string_cat(temp.arena, logfile_dir, logfile_name);
|
||||
sys_mkdir(logfile_dir);
|
||||
|
||||
struct log_startup_receipt log_sr = log_startup(logfile_path);
|
||||
(UNUSED)log_sr;
|
||||
log_startup(logfile_path);
|
||||
logf_info("Start of logs");
|
||||
arena_temp_end(temp);
|
||||
}
|
||||
|
||||
15
src/draw.c
15
src/draw.c
@ -372,14 +372,12 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
|
||||
u64 num_line_glyphs = 0;
|
||||
struct drawable_glyph *line_glyphs = arena_dry_push(scratch.arena, struct drawable_glyph);
|
||||
|
||||
b32 submit_line = false;
|
||||
b32 line_done = false;
|
||||
while (!line_done) {
|
||||
string_done = !string_codepoint_iter_next(&iter);
|
||||
if (string_done) {
|
||||
line_done = true;
|
||||
} else {
|
||||
submit_line = true;
|
||||
u32 codepoint = iter.codepoint;
|
||||
if (codepoint == '\n') {
|
||||
line_done = true;
|
||||
@ -411,7 +409,6 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
|
||||
}
|
||||
|
||||
/* Line ended */
|
||||
if (submit_line) {
|
||||
/* TODO: Only create nodes for non-empty lines. Embed line number in the node. */
|
||||
struct drawable_line *node = arena_push(scratch.arena, struct drawable_line);
|
||||
node->line_width = line_width;
|
||||
@ -428,7 +425,6 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
|
||||
widest_line = max_f32(widest_line, line_width);
|
||||
++num_lines;
|
||||
}
|
||||
}
|
||||
string_codepoint_iter_end(&iter);
|
||||
}
|
||||
|
||||
@ -453,12 +449,7 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
|
||||
|
||||
/* Offset bounds Y */
|
||||
switch (params.offset_y) {
|
||||
case DRAW_TEXT_OFFSET_Y_TOP:
|
||||
{
|
||||
if (first_line) {
|
||||
bounds.y -= first_line_top_offset;
|
||||
}
|
||||
} break;
|
||||
case DRAW_TEXT_OFFSET_Y_TOP: break;
|
||||
case DRAW_TEXT_OFFSET_Y_CENTER:
|
||||
{
|
||||
bounds.y -= bounds.height / 2.f;
|
||||
@ -466,7 +457,7 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
|
||||
case DRAW_TEXT_OFFSET_Y_BOTTOM:
|
||||
{
|
||||
if (last_line) {
|
||||
bounds.y -= bounds.height - first_line_top_offset - last_line_bottom_offset;
|
||||
bounds.y -= bounds.height + last_line_bottom_offset;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
@ -475,7 +466,7 @@ struct rect draw_text(struct gpu_cmd_buffer *cmdbuff, struct draw_text_params pa
|
||||
u64 line_number = 0;
|
||||
for (struct drawable_line *line = first_line; line; line = line->next) {
|
||||
struct v2 draw_pos = bounds.pos;
|
||||
draw_pos.y += line_number * line_spacing;
|
||||
draw_pos.y += line_number * line_spacing - first_line_top_offset;
|
||||
|
||||
/* Alignment */
|
||||
switch (params.alignment) {
|
||||
|
||||
@ -156,8 +156,7 @@ INTERNAL WORK_TASK_FUNC_DEF(font_load_asset_task, vparams)
|
||||
|
||||
font_task_params_release(params);
|
||||
|
||||
f64 elapsed = SECONDS_FROM_NS(sys_time_ns() - start_ns);
|
||||
logf_info("Finished loading font \"%F\" (point size %F) in %F seconds", FMT_STR(path), FMT_FLOAT((f64)point_size), FMT_FLOAT(elapsed));
|
||||
logf_success("Finished loading font \"%F\" (point size %F) in %F seconds", FMT_STR(path), FMT_FLOAT((f64)point_size), FMT_FLOAT(SECONDS_FROM_NS(sys_time_ns() - start_ns)));
|
||||
asset_cache_mark_ready(asset, font);
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
@ -638,6 +638,7 @@ INTERNAL struct string shader_alloc(struct arena *arena, struct dx11_shader *sha
|
||||
__prof;
|
||||
struct temp_arena scratch = scratch_begin(arena);
|
||||
struct string error_str = ZI;
|
||||
i64 start_ns = sys_time_ns();
|
||||
|
||||
struct string shader_name = string_from_cstr_no_limit(shader_desc->name_cstr);
|
||||
|
||||
@ -666,10 +667,12 @@ INTERNAL struct string shader_alloc(struct arena *arena, struct dx11_shader *sha
|
||||
logf_info("Compiling shader \"%F\"", FMT_STR(shader_name));
|
||||
/* Compile shader */
|
||||
/* TODO: pre-compile shaders w/ FXC? */
|
||||
HRESULT hr = D3DCompile(shader_src.text, shader_src.len, NULL, NULL, (ID3DInclude *)&include_handler, "vs_main", "vs_5_0", flags, 0, &vs_blob, &error_blob);
|
||||
struct string friendly_name = string_cat(scratch.arena, LIT("res/"), shader_name);
|
||||
char *friendly_name_cstr = cstr_from_string(scratch.arena, friendly_name);
|
||||
HRESULT hr = D3DCompile(shader_src.text, shader_src.len, friendly_name_cstr, NULL, (ID3DInclude *)&include_handler, "vs_main", "vs_5_0", flags, 0, &vs_blob, &error_blob);
|
||||
if (SUCCEEDED(hr)) {
|
||||
ID3D11Device_CreateVertexShader(G.dev, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob), NULL, &shader->vs);
|
||||
hr = D3DCompile(shader_src.text, shader_src.len, NULL, NULL, (ID3DInclude *)&include_handler, "ps_main", "ps_5_0", flags, 0, &ps_blob, &error_blob);
|
||||
hr = D3DCompile(shader_src.text, shader_src.len, friendly_name_cstr, NULL, (ID3DInclude *)&include_handler, "ps_main", "ps_5_0", flags, 0, &ps_blob, &error_blob);
|
||||
if (SUCCEEDED(hr)) {
|
||||
ID3D11Device_CreatePixelShader(G.dev, ID3D10Blob_GetBufferPointer(ps_blob), ID3D10Blob_GetBufferSize(ps_blob), NULL, &shader->ps);
|
||||
success = true;
|
||||
@ -688,9 +691,19 @@ INTERNAL struct string shader_alloc(struct arena *arena, struct dx11_shader *sha
|
||||
}
|
||||
|
||||
/* Create device layout */
|
||||
ID3D11Device_CreateInputLayout(G.dev, shader_desc->input_layout_desc, elem_count, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob), &shader->input_layout);
|
||||
HRESULT hr = ID3D11Device_CreateInputLayout(G.dev, shader_desc->input_layout_desc, elem_count, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob), &shader->input_layout);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
success = false;
|
||||
error_str = LIT("Failed to create input layout");
|
||||
}
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success || error_blob) {
|
||||
if (error_str.len <= 0) {
|
||||
error_str = LIT("Unknown error");
|
||||
}
|
||||
if (error_blob) {
|
||||
u64 error_blob_cstr_len = ID3D10Blob_GetBufferSize(error_blob);
|
||||
char *error_blob_cstr = (char *)ID3D10Blob_GetBufferPointer(error_blob);
|
||||
@ -709,6 +722,10 @@ INTERNAL struct string shader_alloc(struct arena *arena, struct dx11_shader *sha
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
logf_success("Finished compiling shader \"%F\" in %F seconds", FMT_STR(shader_name), FMT_FLOAT(SECONDS_FROM_NS(sys_time_ns() - start_ns)));
|
||||
}
|
||||
|
||||
if (vs_blob) {
|
||||
ID3D10Blob_Release(vs_blob);
|
||||
}
|
||||
@ -759,7 +776,7 @@ INTERNAL void reload_shader(struct dx11_shader *old_shader, struct dx11_shader_d
|
||||
*old_shader = new_shader;
|
||||
} else {
|
||||
error_msg = string_format(scratch.arena,
|
||||
LIT("Failed to compile shader \"%F\":\n\n%F"),
|
||||
LIT("Failed to compile shader \"%F\": %F"),
|
||||
FMT_STR(name),
|
||||
FMT_STR(comp_error));
|
||||
shader_release(&new_shader);
|
||||
@ -785,7 +802,7 @@ INTERNAL void reload_shader(struct dx11_shader *old_shader, struct dx11_shader_d
|
||||
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(shader_resource_watch_callback, name)
|
||||
{
|
||||
if (shader_set_dirty(name)) {
|
||||
logf_info("Shader source file \"%F\" has changed", FMT_STR(name));
|
||||
logf_debug("Shader source file \"%F\" has changed", FMT_STR(name));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
95
src/log.c
95
src/log.c
@ -1,12 +1,12 @@
|
||||
#include "log.h"
|
||||
#include "scratch.h"
|
||||
#include "log.h"
|
||||
#include "string.h"
|
||||
#include "atomic.h"
|
||||
|
||||
struct log_event_callback {
|
||||
log_event_callback_func *func;
|
||||
i32 level;
|
||||
struct log_event_callback *next;
|
||||
i32 level;
|
||||
};
|
||||
|
||||
/* ========================== *
|
||||
@ -15,9 +15,12 @@ struct log_event_callback {
|
||||
|
||||
GLOBAL struct {
|
||||
struct atomic_i32 initialized;
|
||||
struct sys_mutex mutex;
|
||||
struct arena arena;
|
||||
log_event_callback_func *callbacks_head;
|
||||
|
||||
struct sys_mutex callbacks_mutex;
|
||||
struct arena callbacks_arena;
|
||||
struct log_event_callback *first_callback;
|
||||
struct log_event_callback *last_callback;
|
||||
|
||||
struct sys_file file;
|
||||
b32 file_valid;
|
||||
} G = ZI, DEBUG_ALIAS(G, G_log);
|
||||
@ -25,27 +28,32 @@ GLOBAL struct {
|
||||
GLOBAL READONLY struct log_level_settings g_log_level_settings[LOG_LEVEL_COUNT] = {
|
||||
[LOG_LEVEL_CRITICAL] = {
|
||||
LIT_NOCAST("CRITICAL"),
|
||||
0xFFFF00FF
|
||||
COLOR_PURPLE
|
||||
},
|
||||
|
||||
[LOG_LEVEL_ERROR] = {
|
||||
LIT_NOCAST("ERROR"),
|
||||
0xFFFF0000
|
||||
COLOR_RED
|
||||
},
|
||||
|
||||
[LOG_LEVEL_WARNING] = {
|
||||
LIT_NOCAST("WARNING"),
|
||||
0xFFFFFF00
|
||||
COLOR_YELLOW
|
||||
},
|
||||
|
||||
[LOG_LEVEL_SUCCESS] = {
|
||||
LIT_NOCAST("SUCCESS"),
|
||||
COLOR_GREEN
|
||||
},
|
||||
|
||||
[LOG_LEVEL_INFO] = {
|
||||
LIT_NOCAST("INFO"),
|
||||
0xFFFFFFFF
|
||||
COLOR_WHITE
|
||||
},
|
||||
|
||||
[LOG_LEVEL_DEBUG] = {
|
||||
LIT_NOCAST("DEBUG"),
|
||||
0xFF30D5C8
|
||||
COLOR_BLUE
|
||||
}
|
||||
};
|
||||
|
||||
@ -53,10 +61,10 @@ GLOBAL READONLY struct log_level_settings g_log_level_settings[LOG_LEVEL_COUNT]
|
||||
* Startup
|
||||
* ========================== */
|
||||
|
||||
struct log_startup_receipt log_startup(struct string logfile_path)
|
||||
void log_startup(struct string logfile_path)
|
||||
{
|
||||
G.mutex = sys_mutex_alloc();
|
||||
G.arena = arena_alloc(GIGABYTE(64));
|
||||
G.callbacks_arena = arena_alloc(MEGABYTE(8));
|
||||
G.callbacks_mutex = sys_mutex_alloc();
|
||||
if (logfile_path.len > 0) {
|
||||
/* Create / wipe log file */
|
||||
sys_file_close(sys_file_open_write(logfile_path));
|
||||
@ -67,22 +75,28 @@ struct log_startup_receipt log_startup(struct string logfile_path)
|
||||
}
|
||||
}
|
||||
atomic_i32_eval_exchange(&G.initialized, 1);
|
||||
return (struct log_startup_receipt) { 0 };
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Callback
|
||||
* ========================== */
|
||||
|
||||
void log_register_callback(log_event_callback_func *func)
|
||||
void log_register_callback(log_event_callback_func *func, i32 level)
|
||||
{
|
||||
/* TODO */
|
||||
(UNUSED)func;
|
||||
#if 0
|
||||
if (!atomic_i32_eval(&G.initialized)) { return; }
|
||||
struct sys_lock lock = sys_mutex_lock_e(&G.mutex);
|
||||
struct sys_lock lock = sys_mutex_lock_e(&G.callbacks_mutex);
|
||||
{
|
||||
struct log_event_callback *callback = arena_push(&G.callbacks_arena, struct log_event_callback);
|
||||
callback->func = func;
|
||||
callback->level = level;
|
||||
if (G.last_callback) {
|
||||
G.last_callback->next = callback;
|
||||
} else {
|
||||
G.first_callback = callback;
|
||||
}
|
||||
G.last_callback = callback;
|
||||
}
|
||||
sys_mutex_unlock(&lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -130,7 +144,9 @@ void _log(i32 level, struct string msg)
|
||||
|
||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||
|
||||
struct sys_datetime lt = sys_local_time();
|
||||
struct sys_datetime datetime = sys_local_time();
|
||||
i64 time_ns = sys_time_ns();
|
||||
|
||||
u32 tid = sys_thread_id();
|
||||
|
||||
struct log_level_settings settings = g_log_level_settings[level];
|
||||
@ -142,10 +158,10 @@ void _log(i32 level, struct string msg)
|
||||
LIT("[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F"),
|
||||
|
||||
/* Time */
|
||||
FMT_UINT_Z(lt.hour, 2),
|
||||
FMT_UINT_Z(lt.minute, 2),
|
||||
FMT_UINT_Z(lt.second, 2),
|
||||
FMT_UINT_Z(lt.milliseconds, 3),
|
||||
FMT_UINT_Z(datetime.hour, 2),
|
||||
FMT_UINT_Z(datetime.minute, 2),
|
||||
FMT_UINT_Z(datetime.second, 2),
|
||||
FMT_UINT_Z(datetime.milliseconds, 3),
|
||||
|
||||
/* TID */
|
||||
FMT_UINT_Z(tid, 5),
|
||||
@ -166,10 +182,10 @@ void _log(i32 level, struct string msg)
|
||||
LIT("[%F:%F:%F.%F] |%F| [%F] %F"),
|
||||
|
||||
/* Time */
|
||||
FMT_UINT_Z(lt.hour, 2),
|
||||
FMT_UINT_Z(lt.minute, 2),
|
||||
FMT_UINT_Z(lt.second, 2),
|
||||
FMT_UINT_Z(lt.milliseconds, 3),
|
||||
FMT_UINT_Z(datetime.hour, 2),
|
||||
FMT_UINT_Z(datetime.minute, 2),
|
||||
FMT_UINT_Z(datetime.second, 2),
|
||||
FMT_UINT_Z(datetime.milliseconds, 3),
|
||||
|
||||
/* TID */
|
||||
FMT_UINT_Z(tid, 5),
|
||||
@ -185,6 +201,27 @@ void _log(i32 level, struct string msg)
|
||||
__profmsg((char *)msg.text, msg.len, settings.color);
|
||||
append_to_logfile(msg_formatted);
|
||||
|
||||
|
||||
/* Run callbacks */
|
||||
struct log_event event = ZI;
|
||||
event.level = level;
|
||||
event.msg = msg;
|
||||
event.datetime = datetime;
|
||||
event.time_ns = time_ns;
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
event.file = file;
|
||||
event.line = line;
|
||||
#endif
|
||||
{
|
||||
struct sys_lock lock = sys_mutex_lock_s(&G.callbacks_mutex);
|
||||
for (struct log_event_callback *callback = G.first_callback; callback; callback = callback->next) {
|
||||
if (level <= callback->level) {
|
||||
callback->func(event);
|
||||
}
|
||||
}
|
||||
sys_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
|
||||
51
src/log.h
51
src/log.h
@ -2,6 +2,7 @@
|
||||
#define LOG_H
|
||||
|
||||
#include "string.h"
|
||||
#include "sys.h"
|
||||
|
||||
#define LOG_LEVEL(l) (l <= LOG_LEVEL_COMPTIME)
|
||||
|
||||
@ -23,9 +24,10 @@
|
||||
#define LOG_LEVEL_CRITICAL 0
|
||||
#define LOG_LEVEL_ERROR 1
|
||||
#define LOG_LEVEL_WARNING 2
|
||||
#define LOG_LEVEL_INFO 3
|
||||
#define LOG_LEVEL_DEBUG 4
|
||||
#define LOG_LEVEL_COUNT 5
|
||||
#define LOG_LEVEL_SUCCESS 3
|
||||
#define LOG_LEVEL_INFO 4
|
||||
#define LOG_LEVEL_DEBUG 5
|
||||
#define LOG_LEVEL_COUNT 6
|
||||
|
||||
/* ========================== *
|
||||
* Callback interface
|
||||
@ -37,18 +39,22 @@ struct log_level_settings {
|
||||
};
|
||||
|
||||
struct log_event {
|
||||
/* Msg lifetime is only as long as callback duration */
|
||||
struct string msg;
|
||||
i32 level;
|
||||
struct string msg; /* Lifetime is only as long as the callback function call receiving the event */
|
||||
struct log_level_settings settings;
|
||||
|
||||
struct sys_datetime datetime;
|
||||
i64 time_ns;
|
||||
|
||||
/* These will be nulled if LOG_INCLUDE_SOURCE_LOCATION is disabled */
|
||||
struct string file;
|
||||
i32 line;
|
||||
};
|
||||
|
||||
typedef void (log_event_callback_func)(struct log_event);
|
||||
#define LOG_EVENT_CALLBACK_FUNC_DEF(name, log_event_arg) void name(struct log_event log_event_arg)
|
||||
typedef LOG_EVENT_CALLBACK_FUNC_DEF(log_event_callback_func, log_event);
|
||||
|
||||
void log_register_callback(log_event_callback_func *func);
|
||||
void log_register_callback(log_event_callback_func *func, i32 level);
|
||||
|
||||
/* ========================== *
|
||||
* Logging macros
|
||||
@ -95,20 +101,19 @@ void log_register_callback(log_event_callback_func *func);
|
||||
# define logf_warning(fmt_lit, ...)
|
||||
#endif
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_DEBUG)
|
||||
#if LOG_LEVEL(LOG_LEVEL_SUCCESS)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_debug(msg) _log(LOG_LEVEL_DEBUG, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_debug(fmt_lit, ...) _logf(LOG_LEVEL_DEBUG, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# define log_success(msg) _log(LOG_LEVEL_SUCCESS, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_success(fmt_lit, ...) _logf(LOG_LEVEL_SUCCESS, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
# define log_debug(msg) _log(LOG_LEVEL_DEBUG, msg)
|
||||
# define logf_debug(fmt_lit, ...) _logf(LOG_LEVEL_DEBUG, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# define log_success(msg) _log(LOG_LEVEL_SUCCESS, msg)
|
||||
# define logf_success(fmt_lit, ...) _logf(LOG_LEVEL_SUCCESS, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define log_debug(msg)
|
||||
# define logf_debug(fmt_lit, ...)
|
||||
# define log_success(msg)
|
||||
# define logf_success(fmt_lit, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_INFO)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_info(msg) _log(LOG_LEVEL_INFO, LIT(__FILE__), __LINE__, msg)
|
||||
@ -122,12 +127,24 @@ void log_register_callback(log_event_callback_func *func);
|
||||
# define logf_info(fmt_lit, ...)
|
||||
#endif
|
||||
|
||||
#if LOG_LEVEL(LOG_LEVEL_DEBUG)
|
||||
# if LOG_INCLUDE_SOURCE_LOCATION
|
||||
# define log_debug(msg) _log(LOG_LEVEL_DEBUG, LIT(__FILE__), __LINE__, msg)
|
||||
# define logf_debug(fmt_lit, ...) _logf(LOG_LEVEL_DEBUG, LIT(__FILE__), __LINE__, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# else
|
||||
# define log_debug(msg) _log(LOG_LEVEL_DEBUG, msg)
|
||||
# define logf_debug(fmt_lit, ...) _logf(LOG_LEVEL_DEBUG, LIT(fmt_lit) , ## __VA_ARGS__, FMT_END)
|
||||
# endif
|
||||
#else
|
||||
# define log_debug(msg)
|
||||
# define logf_debug(fmt_lit, ...)
|
||||
#endif
|
||||
|
||||
/* ========================== *
|
||||
* Function declarations
|
||||
* ========================== */
|
||||
|
||||
struct log_startup_receipt { i32 _; };
|
||||
struct log_startup_receipt log_startup(struct string logfile_path);
|
||||
void log_startup(struct string logfile_path);
|
||||
|
||||
void _log_panic(struct string msg);
|
||||
|
||||
|
||||
@ -997,7 +997,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
test_clear_level(ctx);
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_SPAWN1_TEST) {
|
||||
logf_info("Spawn test 1");
|
||||
logf_debug("Spawn test 1");
|
||||
u32 count = 1;
|
||||
f32 spread = 0;
|
||||
for (u32 j = 0; j < count; ++j) {
|
||||
@ -1007,7 +1007,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_SPAWN2_TEST) {
|
||||
logf_info("Spawn test 2");
|
||||
logf_debug("Spawn test 2");
|
||||
u32 count = 1;
|
||||
f32 spread = 0;
|
||||
for (u32 j = 0; j < count; ++j) {
|
||||
@ -1017,7 +1017,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
}
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_SPAWN3_TEST) {
|
||||
logf_info("Spawn test 3");
|
||||
logf_debug("Spawn test 3");
|
||||
u32 count = 1;
|
||||
f32 spread = 0;
|
||||
for (u32 j = 0; j < count; ++j) {
|
||||
@ -1030,7 +1030,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
test_generate_walls(world);
|
||||
}
|
||||
if (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) {
|
||||
logf_info("Explosion test");
|
||||
logf_debug("Explosion test");
|
||||
test_spawn_explosion(root, player->player_cursor_pos, 100, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,8 +134,7 @@ INTERNAL WORK_TASK_FUNC_DEF(sound_load_asset_task, vparams)
|
||||
sound->pcm.samples = samples;
|
||||
MEMCPY(sound->pcm.samples, decoded.pcm.samples, decoded.pcm.count * sizeof(*decoded.pcm.samples));
|
||||
|
||||
f64 elapsed = SECONDS_FROM_NS(sys_time_ns() - start_ns);
|
||||
logf_info("Finished loading sound \"%F\" in %F seconds", FMT_STR(path), FMT_FLOAT(elapsed));
|
||||
logf_success("Finished loading sound \"%F\" in %F seconds", FMT_STR(path), FMT_FLOAT(SECONDS_FROM_NS(sys_time_ns() - start_ns)));
|
||||
asset_cache_mark_ready(asset, sound);
|
||||
} else {
|
||||
logf_error("Error loading sound \"%F\": %F", FMT_STR(path), FMT_STR(error_msg));
|
||||
|
||||
20
src/sprite.c
20
src/sprite.c
@ -351,6 +351,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
||||
struct string path = tag.path;
|
||||
|
||||
logf_info("Loading sprite texture [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||
b32 success = false;
|
||||
i64 start_ns = sys_time_ns();
|
||||
|
||||
ASSERT(string_ends_with(path, LIT(".ase")));
|
||||
@ -388,18 +389,20 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
||||
e->texture->loaded = true;
|
||||
/* TODO: Query gpu for more accurate texture size in VRAM */
|
||||
memory_size += (decoded.image.width * decoded.image.height) * sizeof(*decoded.image.pixels);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
arena_set_readonly(&e->arena);
|
||||
e->memory_usage = e->arena.committed + memory_size;
|
||||
atomic_u64_eval_add_u64(&G.cache.memory_usage, e->memory_usage);
|
||||
|
||||
f64 elapsed = SECONDS_FROM_NS(sys_time_ns() - start_ns);
|
||||
logf_info("Finished loading sprite texture [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||
if (success) {
|
||||
logf_success("Finished loading sprite texture [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||
FMT_HEX(e->hash.v),
|
||||
FMT_STR(path),
|
||||
FMT_FLOAT(elapsed),
|
||||
FMT_FLOAT(SECONDS_FROM_NS(sys_time_ns() - start_ns)),
|
||||
FMT_UINT(e->memory_usage));
|
||||
}
|
||||
|
||||
atomic_i32_eval_exchange(&e->state, CACHE_ENTRY_STATE_LOADED);
|
||||
|
||||
@ -676,6 +679,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
||||
struct string path = tag.path;
|
||||
|
||||
logf_info("Loading sprite sheet [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||
b32 success = false;
|
||||
i64 start_ns = sys_time_ns();
|
||||
|
||||
ASSERT(e->kind == CACHE_ENTRY_KIND_SHEET);
|
||||
@ -705,19 +709,21 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
||||
*e->sheet = init_sheet_from_ase_result(&e->arena, decoded);
|
||||
e->sheet->loaded = true;
|
||||
e->sheet->valid = true;
|
||||
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
arena_set_readonly(&e->arena);
|
||||
e->memory_usage = e->arena.committed;
|
||||
atomic_u64_eval_add_u64(&G.cache.memory_usage, e->memory_usage);
|
||||
|
||||
f64 elapsed = SECONDS_FROM_NS(sys_time_ns() - start_ns);
|
||||
logf_info("Finished loading sprite sheet [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||
if (success) {
|
||||
logf_success("Finished loading sprite sheet [%F] \"%F\" in %F seconds (cache size: %F bytes).",
|
||||
FMT_HEX(e->hash.v),
|
||||
FMT_STR(path),
|
||||
FMT_FLOAT(elapsed),
|
||||
FMT_FLOAT(SECONDS_FROM_NS(sys_time_ns() - start_ns)),
|
||||
FMT_UINT(e->memory_usage));
|
||||
|
||||
}
|
||||
|
||||
atomic_i32_eval_exchange(&e->state, CACHE_ENTRY_STATE_LOADED);
|
||||
|
||||
|
||||
@ -683,9 +683,6 @@ struct win32_watch {
|
||||
HANDLE dir_handle;
|
||||
HANDLE wake_handle;
|
||||
struct win32_watch *next_free;
|
||||
|
||||
u64 dir_path_len;
|
||||
u8 dir_path_text[1024];
|
||||
u8 results_buff[KILOBYTE(64)];
|
||||
};
|
||||
|
||||
@ -708,23 +705,6 @@ struct sys_watch sys_watch_alloc(struct string dir_path)
|
||||
}
|
||||
MEMZERO_STRUCT(w32_watch);
|
||||
|
||||
if (dir_path.len > 0 && dir_path.len < (ARRAY_COUNT(w32_watch->dir_path_text) - 1)) {
|
||||
u64 dir_path_len = dir_path.len;
|
||||
MEMCPY(w32_watch->dir_path_text, dir_path.text, dir_path_len);
|
||||
for (u64 i = 0; i < dir_path_len; ++i) {
|
||||
if (w32_watch->dir_path_text[i] == '\\') {
|
||||
w32_watch->dir_path_text[i] = '/';
|
||||
}
|
||||
}
|
||||
if (w32_watch->dir_path_text[dir_path_len - 1] != '/') {
|
||||
w32_watch->dir_path_text[dir_path_len] = '/';
|
||||
++dir_path_len;
|
||||
}
|
||||
w32_watch->dir_path_len = dir_path_len;
|
||||
} else {
|
||||
sys_panic(string_format(scratch.arena, LIT("Directory path too \"%F\" has invalid length"), FMT_STR(dir_path)));
|
||||
}
|
||||
|
||||
wchar_t *dir_path_wstr = wstr_from_string(scratch.arena, dir_path);
|
||||
w32_watch->dir_handle = CreateFileW(
|
||||
dir_path_wstr,
|
||||
@ -812,8 +792,7 @@ struct sys_watch_info_list sys_watch_wait(struct arena *arena, struct sys_watch
|
||||
name16.text = res->FileName;
|
||||
name16.len = res->FileNameLength / sizeof(wchar_t);
|
||||
|
||||
info->name = string_copy(arena, STRING(w32_watch->dir_path_len, w32_watch->dir_path_text));
|
||||
info->name.len += string_from_string16(arena, name16).len;
|
||||
info->name = string_from_string16(arena, name16);
|
||||
for (u64 i = 0; i < info->name.len; ++i) {
|
||||
if (info->name.text[i] == '\\') {
|
||||
info->name.text[i] = '/';
|
||||
|
||||
150
src/user.c
150
src/user.c
@ -37,6 +37,17 @@ struct second_stat {
|
||||
u64 last_second;
|
||||
};
|
||||
|
||||
struct console_log {
|
||||
struct string msg;
|
||||
i32 level;
|
||||
i32 index;
|
||||
struct sys_datetime datetime;
|
||||
i64 time_ns;
|
||||
struct rect bounds;
|
||||
struct console_log *prev;
|
||||
struct console_log *next;
|
||||
};
|
||||
|
||||
GLOBAL struct {
|
||||
struct atomic_i32 user_thread_shutdown;
|
||||
struct sys_thread user_thread;
|
||||
@ -74,13 +85,20 @@ GLOBAL struct {
|
||||
|
||||
struct bind_state bind_states[USER_BIND_KIND_COUNT];
|
||||
|
||||
/* Debug camera */
|
||||
struct sim_ent_id debug_following;
|
||||
b32 debug_camera;
|
||||
b32 debug_camera_panning;
|
||||
struct v2 debug_camera_pan_start;
|
||||
|
||||
b32 debug_draw;
|
||||
|
||||
/* Debug console */
|
||||
struct sys_mutex console_logs_mutex;
|
||||
struct arena console_logs_arena;
|
||||
struct console_log *first_console_log;
|
||||
struct console_log *last_console_log;
|
||||
f32 console_logs_height;
|
||||
|
||||
/* Window -> user */
|
||||
struct sys_mutex sys_events_mutex;
|
||||
struct arena sys_events_arena;
|
||||
@ -178,6 +196,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
|
||||
* ========================== */
|
||||
|
||||
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(user_shutdown);
|
||||
INTERNAL LOG_EVENT_CALLBACK_FUNC_DEF(debug_console_log_callback, log);
|
||||
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_thread_entry_point, arg);
|
||||
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg);
|
||||
INTERNAL SYS_WINDOW_EVENT_CALLBACK_FUNC_DEF(window_event_callback, event);
|
||||
@ -239,12 +258,17 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
||||
G.final_cmd_buffer = gpu_cmd_buffer_alloc();
|
||||
G.backbuffer_cmd_buffer = gpu_cmd_buffer_alloc();
|
||||
|
||||
//log_register_callback(debug_console_log_callback, LOG_LEVEL_SUCCESS);
|
||||
log_register_callback(debug_console_log_callback, LOG_LEVEL_INFO);
|
||||
G.console_logs_mutex = sys_mutex_alloc();
|
||||
G.console_logs_arena = arena_alloc(GIGABYTE(64));
|
||||
|
||||
G.window = window;
|
||||
sys_window_register_event_callback(G.window, &window_event_callback);
|
||||
|
||||
G.local_sim_thread = sys_thread_alloc(&user_local_sim_thread_entry_point, G.local_sim_ctx, LIT("[P8] Local sim thread"));
|
||||
|
||||
G.debug_draw = true;
|
||||
//G.debug_draw = true;
|
||||
|
||||
G.user_thread = sys_thread_alloc(&user_thread_entry_point, NULL, LIT("[P9] User thread"));
|
||||
app_register_exit_callback(&user_shutdown);
|
||||
@ -435,6 +459,106 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
|
||||
return res;
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Debug console
|
||||
* ========================== */
|
||||
|
||||
INTERNAL LOG_EVENT_CALLBACK_FUNC_DEF(debug_console_log_callback, log)
|
||||
{
|
||||
struct sys_lock lock = sys_mutex_lock_e(&G.console_logs_mutex);
|
||||
{
|
||||
struct console_log *clog = arena_push(&G.console_logs_arena, struct console_log);
|
||||
clog->level = log.level;
|
||||
clog->msg = string_copy(&G.console_logs_arena, log.msg);
|
||||
clog->datetime = log.datetime;
|
||||
clog->time_ns = log.time_ns;
|
||||
|
||||
if (G.last_console_log) {
|
||||
G.last_console_log->next = clog;
|
||||
clog->prev = G.last_console_log;
|
||||
clog->index = G.last_console_log->index + 1;
|
||||
} else {
|
||||
G.first_console_log = clog;
|
||||
}
|
||||
G.last_console_log = clog;
|
||||
}
|
||||
sys_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
INTERNAL void draw_debug_console(b32 minimized)
|
||||
{
|
||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||
|
||||
struct v2 desired_start_pos = V2(10, 400);
|
||||
i64 fade_time_ns = NS_FROM_SECONDS(10);
|
||||
f32 fade_curve = 0.5;
|
||||
f32 spacing = 0;
|
||||
f32 bg_margin = 5;
|
||||
u32 info_colors[2] = { RGB_F(0.4, 0.4, 0.4), RGB_F(0.5, 0.5, 0.5) };
|
||||
u32 success_colors[2] = { RGB_F(0.1, 0.3, 0.1), RGB_F(0.2, 0.4, 0.2) };
|
||||
u32 warning_colors[2] = { RGB_F(0.4, 0.4, 0.1), RGB_F(0.5, 0.5, 0.2) };
|
||||
u32 error_colors[2] = { RGB_F(0.4, 0.1, 0.1), RGB_F(0.5, 0.2, 0.2) };
|
||||
|
||||
struct v2 draw_pos = desired_start_pos;
|
||||
f32 bounds_top = F32_INFINITY;
|
||||
f32 bounds_bottom = -F32_INFINITY;
|
||||
|
||||
if (G.console_logs_height < desired_start_pos.y) {
|
||||
draw_pos.y = G.console_logs_height;
|
||||
}
|
||||
G.console_logs_height = 0;
|
||||
|
||||
i64 now_ns = sys_time_ns();
|
||||
struct font *font = font_load_async(LIT("fonts/fixedsys.ttf"), 12.0f);
|
||||
if (font) {
|
||||
struct sys_lock lock = sys_mutex_lock_e(&G.console_logs_mutex);
|
||||
{
|
||||
for (struct console_log *log = G.last_console_log; log; log = log->prev) {
|
||||
f32 opacity = 0.75;
|
||||
if (minimized) {
|
||||
f32 lin = 1.0 - clamp_f64((f64)(now_ns - log->time_ns) / (f64)fade_time_ns, 0, 1);
|
||||
opacity *= math_pow(lin, fade_curve);
|
||||
}
|
||||
if (draw_pos.y > -desired_start_pos.y && opacity > 0) {
|
||||
/* Draw background */
|
||||
u32 color_index = log->index & 1; /* Alternate colors for greater distinction between logs */
|
||||
u32 color = info_colors[color_index];
|
||||
switch (log->level) {
|
||||
default: break;
|
||||
case LOG_LEVEL_ERROR: color = error_colors[color_index]; break;
|
||||
case LOG_LEVEL_WARNING: color = warning_colors[color_index]; break;
|
||||
case LOG_LEVEL_SUCCESS: color = success_colors[color_index]; break;
|
||||
}
|
||||
draw_quad(G.ui_cmd_buffer, quad_from_rect(log->bounds), ALPHA_F(color, opacity));
|
||||
|
||||
/* Draw text */
|
||||
struct string text = log->msg;
|
||||
struct draw_text_params params = DRAW_TEXT_PARAMS(.font = font, .pos = draw_pos, .offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM, .color = ALPHA_F(COLOR_WHITE, opacity), .str = text);
|
||||
struct rect bounds = draw_text(G.ui_cmd_buffer, params);
|
||||
|
||||
struct rect draw_bounds = bounds;
|
||||
draw_bounds.x -= bg_margin;
|
||||
draw_bounds.y -= bg_margin;
|
||||
draw_bounds.width += bg_margin * 2.f;
|
||||
draw_bounds.height += bg_margin * 2.f;
|
||||
draw_pos.y -= draw_bounds.height + spacing;
|
||||
log->bounds = draw_bounds;
|
||||
|
||||
bounds_top = min_f32(bounds_top, draw_bounds.y);
|
||||
bounds_bottom = max_f32(bounds_bottom, draw_bounds.y + draw_bounds.height);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
sys_mutex_unlock(&lock);
|
||||
}
|
||||
if (bounds_top < F32_INFINITY && bounds_bottom > -F32_INFINITY) {
|
||||
G.console_logs_height = bounds_bottom - bounds_top;
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Sort entities
|
||||
* ========================== */
|
||||
@ -1880,9 +2004,16 @@ INTERNAL void user_update(void)
|
||||
draw_text(G.ui_cmd_buffer, DRAW_TEXT_PARAMS(.font = font, .pos = pos, .str = text, .offset_y = DRAW_TEXT_OFFSET_Y_BOTTOM, .color = COLOR_WHITE));
|
||||
arena_temp_end(temp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if DEVELOPER
|
||||
draw_debug_console(!G.debug_draw);
|
||||
#else
|
||||
if (G.debug_draw) {
|
||||
draw_debug_console(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========================== *
|
||||
* Render
|
||||
* ========================== */
|
||||
@ -2601,19 +2732,6 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Publish snapshot to remote clients */
|
||||
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
|
||||
struct sim_client *client = &store->clients[i];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user