call resource callbacks in job
This commit is contained in:
parent
fea0346982
commit
892daa5ed2
BIN
res/sprite/tim.ase
(Stored with Git LFS)
BIN
res/sprite/tim.ase
(Stored with Git LFS)
Binary file not shown.
@ -236,13 +236,13 @@ void app_entry_point(struct string args_str)
|
|||||||
i32 worker_count;
|
i32 worker_count;
|
||||||
{
|
{
|
||||||
/* FIXME: Switch this on to utilize all cores. Only decreasing worker count for testing purposes. */
|
/* FIXME: Switch this on to utilize all cores. Only decreasing worker count for testing purposes. */
|
||||||
#if !PROFILING && !RTC || 1
|
#if !PROFILING && !RTC
|
||||||
i32 min_worker_count = min_i32(NUM_APP_DEDICATED_WORKERS + 2, JOB_MIN_WORKERS);
|
|
||||||
i32 max_worker_count = JOB_MAX_WORKERS;
|
i32 max_worker_count = JOB_MAX_WORKERS;
|
||||||
|
i32 min_worker_count = clamp_i32(NUM_APP_DEDICATED_WORKERS + 2, JOB_MIN_WORKERS, max_worker_count);
|
||||||
i32 target_worker_count = (i32)sys_num_logical_processors() * 0.75;
|
i32 target_worker_count = (i32)sys_num_logical_processors() * 0.75;
|
||||||
worker_count = clamp_i32(target_worker_count, min_worker_count, max_worker_count);
|
worker_count = clamp_i32(target_worker_count, min_worker_count, max_worker_count);
|
||||||
#else
|
#else
|
||||||
worker_count = 8;
|
worker_count = 5;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,7 +76,7 @@ void *arena_push_bytes_no_zero(struct arena *arena, u64 size, u64 align)
|
|||||||
|
|
||||||
u64 new_pos = aligned_start_pos + size;
|
u64 new_pos = aligned_start_pos + size;
|
||||||
if (new_pos > arena->committed) {
|
if (new_pos > arena->committed) {
|
||||||
__profscope(_arena_push_bytes_COMMIT);
|
__profscope(Arena commit);
|
||||||
/* Commit new block(s) */
|
/* Commit new block(s) */
|
||||||
u64 blocks_needed = (new_pos - arena->committed + ARENA_BLOCK_SIZE - 1) / ARENA_BLOCK_SIZE;
|
u64 blocks_needed = (new_pos - arena->committed + ARENA_BLOCK_SIZE - 1) / ARENA_BLOCK_SIZE;
|
||||||
u64 commit_bytes = blocks_needed * ARENA_BLOCK_SIZE;
|
u64 commit_bytes = blocks_needed * ARENA_BLOCK_SIZE;
|
||||||
|
|||||||
@ -732,7 +732,7 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
__profscope(assemble_image);
|
__profscope(Build image from cels);
|
||||||
|
|
||||||
/* Assemble image from cels */
|
/* Assemble image from cels */
|
||||||
for (struct cel *cel = cel_head; cel; cel = cel->next) {
|
for (struct cel *cel = cel_head; cel; cel = cel->next) {
|
||||||
|
|||||||
@ -653,7 +653,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
i64 now_ns = sys_time_ns();
|
i64 now_ns = sys_time_ns();
|
||||||
|
|
||||||
{
|
{
|
||||||
__profscope(host_update_read_packets);
|
__profscope(Read host packets);
|
||||||
struct string read_buff = ZI;
|
struct string read_buff = ZI;
|
||||||
read_buff.len = PACKET_DATA_MAX_LEN;
|
read_buff.len = PACKET_DATA_MAX_LEN;
|
||||||
read_buff.text = arena_push_array_no_zero(scratch.arena, u8, read_buff.len);
|
read_buff.text = arena_push_array_no_zero(scratch.arena, u8, read_buff.len);
|
||||||
@ -829,7 +829,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
|
|
||||||
/* Update channels */
|
/* Update channels */
|
||||||
{
|
{
|
||||||
__profscope(host_update_channels);
|
__profscope(Update host channels);
|
||||||
for (u64 i = 0; i < host->num_channels_reserved; ++i) {
|
for (u64 i = 0; i < host->num_channels_reserved; ++i) {
|
||||||
struct host_channel *channel = &host->channels[i];
|
struct host_channel *channel = &host->channels[i];
|
||||||
if (channel->valid) {
|
if (channel->valid) {
|
||||||
@ -903,7 +903,7 @@ void host_update_end(struct host *host)
|
|||||||
/* Process cmds into sendable packets */
|
/* Process cmds into sendable packets */
|
||||||
/* TODO: Unreliable packets don't need to be allocated into unreliable packet queue, should just send them and forget */
|
/* TODO: Unreliable packets don't need to be allocated into unreliable packet queue, should just send them and forget */
|
||||||
{
|
{
|
||||||
__profscope(host_update_process_cmds);
|
__profscope(Process host cmds);
|
||||||
for (struct host_cmd *cmd = host->first_cmd; cmd; cmd = cmd->next) {
|
for (struct host_cmd *cmd = host->first_cmd; cmd; cmd = cmd->next) {
|
||||||
enum host_cmd_kind kind = cmd->kind;
|
enum host_cmd_kind kind = cmd->kind;
|
||||||
struct host_channel_id channel_id = cmd->channel_id;
|
struct host_channel_id channel_id = cmd->channel_id;
|
||||||
@ -1018,7 +1018,7 @@ void host_update_end(struct host *host)
|
|||||||
/* Send packets */
|
/* Send packets */
|
||||||
/* TODO: Aggregate small packets */
|
/* TODO: Aggregate small packets */
|
||||||
{
|
{
|
||||||
__profscope(host_update_send_packets);
|
__profscope(Send host packets);
|
||||||
for (u64 i = 0; i < host->num_channels_reserved; ++i) {
|
for (u64 i = 0; i < host->num_channels_reserved; ++i) {
|
||||||
struct sock *sock = host->sock;
|
struct sock *sock = host->sock;
|
||||||
struct host_channel *channel = &host->channels[i];
|
struct host_channel *channel = &host->channels[i];
|
||||||
|
|||||||
49
src/job.c
49
src/job.c
@ -236,17 +236,27 @@ INTERNAL struct job_handle job_dispatch_ex(struct job_desc desc)
|
|||||||
|
|
||||||
/* Queue job */
|
/* Queue job */
|
||||||
if (job_queue) {
|
if (job_queue) {
|
||||||
__profscope(Queue);
|
__profscope(Queue job);
|
||||||
struct sys_lock lock = sys_mutex_lock_e(G.queued_jobs_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(G.queued_jobs_mutex);
|
||||||
{
|
{
|
||||||
/* Push to queue */
|
/* Push to queue */
|
||||||
{
|
{
|
||||||
|
if (job->prev == job || job->next == job) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (job_queue->last) {
|
if (job_queue->last) {
|
||||||
job_queue->last->next = job;
|
job_queue->last->next = job;
|
||||||
} else {
|
} else {
|
||||||
job_queue->first = job;
|
job_queue->first = job;
|
||||||
}
|
}
|
||||||
|
job->prev = job_queue->last;
|
||||||
job_queue->last = job;
|
job_queue->last = job;
|
||||||
|
|
||||||
|
if (job->prev == job || job->next == job) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++G.queue_submit_gen;
|
++G.queue_submit_gen;
|
||||||
/* Signal workers */
|
/* Signal workers */
|
||||||
@ -272,8 +282,12 @@ INTERNAL struct job_handle job_dispatch_ex(struct job_desc desc)
|
|||||||
while (!stop) {
|
while (!stop) {
|
||||||
/* Remove job from queue */
|
/* Remove job from queue */
|
||||||
if (job_queue && job_id == (job_count - 1)) {
|
if (job_queue && job_id == (job_count - 1)) {
|
||||||
|
__profscope(Dequeue job);
|
||||||
struct sys_lock queue_lock = sys_mutex_lock_e(G.queued_jobs_mutex);
|
struct sys_lock queue_lock = sys_mutex_lock_e(G.queued_jobs_mutex);
|
||||||
{
|
{
|
||||||
|
if (job->prev == job || job->next == job) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
struct worker_job *prev = job->prev;
|
struct worker_job *prev = job->prev;
|
||||||
struct worker_job *next = job->next;
|
struct worker_job *next = job->next;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
@ -286,11 +300,15 @@ INTERNAL struct job_handle job_dispatch_ex(struct job_desc desc)
|
|||||||
} else {
|
} else {
|
||||||
job_queue->last = prev;
|
job_queue->last = prev;
|
||||||
}
|
}
|
||||||
|
if (job->prev == job || job->next == job) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&queue_lock);
|
sys_mutex_unlock(&queue_lock);
|
||||||
}
|
}
|
||||||
/* Run */
|
/* Run */
|
||||||
{
|
{
|
||||||
|
__profscope(Run job);
|
||||||
data.id = job_id;
|
data.id = job_id;
|
||||||
job_func(data);
|
job_func(data);
|
||||||
}
|
}
|
||||||
@ -313,8 +331,12 @@ INTERNAL struct job_handle job_dispatch_ex(struct job_desc desc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (should_release) {
|
if (should_release) {
|
||||||
|
__profscope(Release job);
|
||||||
struct sys_lock fj_lock = sys_mutex_lock_e(G.free_jobs_mutex);
|
struct sys_lock fj_lock = sys_mutex_lock_e(G.free_jobs_mutex);
|
||||||
{
|
{
|
||||||
|
if (job->queue && (job->queue->first == job || job->queue->last == job)) {
|
||||||
|
DEBUGBREAK;
|
||||||
|
}
|
||||||
job->next_free = G.first_free_job;
|
job->next_free = G.first_free_job;
|
||||||
G.first_free_job = job;
|
G.first_free_job = job;
|
||||||
}
|
}
|
||||||
@ -326,7 +348,7 @@ INTERNAL struct job_handle job_dispatch_ex(struct job_desc desc)
|
|||||||
/* Wait for job completion */
|
/* Wait for job completion */
|
||||||
if (wait && !is_done) {
|
if (wait && !is_done) {
|
||||||
__profscope(Wait for job);
|
__profscope(Wait for job);
|
||||||
struct sys_lock lock = sys_mutex_lock_s(job->mutex);
|
struct sys_lock lock = sys_mutex_lock_e(job->mutex);
|
||||||
is_done = atomic_u64_eval(&job->gen) != handle.gen;
|
is_done = atomic_u64_eval(&job->gen) != handle.gen;
|
||||||
while (!is_done) {
|
while (!is_done) {
|
||||||
sys_condition_variable_wait(job->gen_cv, &lock);
|
sys_condition_variable_wait(job->gen_cv, &lock);
|
||||||
@ -411,6 +433,9 @@ void job_wait(struct job_handle handle)
|
|||||||
__profscope(Dequeue job);
|
__profscope(Dequeue job);
|
||||||
struct sys_lock queue_lock = sys_mutex_lock_e(G.queued_jobs_mutex);
|
struct sys_lock queue_lock = sys_mutex_lock_e(G.queued_jobs_mutex);
|
||||||
{
|
{
|
||||||
|
if (job->prev == job || job->next == job) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
struct worker_job *prev = job->prev;
|
struct worker_job *prev = job->prev;
|
||||||
struct worker_job *next = job->next;
|
struct worker_job *next = job->next;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
@ -423,6 +448,9 @@ void job_wait(struct job_handle handle)
|
|||||||
} else {
|
} else {
|
||||||
job_queue->last = prev;
|
job_queue->last = prev;
|
||||||
}
|
}
|
||||||
|
if (job->prev == job || job->next == job) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&queue_lock);
|
sys_mutex_unlock(&queue_lock);
|
||||||
}
|
}
|
||||||
@ -451,6 +479,9 @@ void job_wait(struct job_handle handle)
|
|||||||
__profscope(Release job);
|
__profscope(Release job);
|
||||||
struct sys_lock fj_lock = sys_mutex_lock_e(G.free_jobs_mutex);
|
struct sys_lock fj_lock = sys_mutex_lock_e(G.free_jobs_mutex);
|
||||||
{
|
{
|
||||||
|
if (job->queue && (job->queue->first == job || job->queue->last == job)) {
|
||||||
|
DEBUGBREAK;
|
||||||
|
}
|
||||||
job->next_free = G.first_free_job;
|
job->next_free = G.first_free_job;
|
||||||
G.first_free_job = job;
|
G.first_free_job = job;
|
||||||
}
|
}
|
||||||
@ -462,7 +493,7 @@ void job_wait(struct job_handle handle)
|
|||||||
/* Wait for job completion */
|
/* Wait for job completion */
|
||||||
if (!is_done) {
|
if (!is_done) {
|
||||||
__profscope(Wait for job);
|
__profscope(Wait for job);
|
||||||
struct sys_lock lock = sys_mutex_lock_s(job->mutex);
|
struct sys_lock lock = sys_mutex_lock_e(job->mutex);
|
||||||
is_done = atomic_u64_eval(&job->gen) != handle.gen;
|
is_done = atomic_u64_eval(&job->gen) != handle.gen;
|
||||||
while (!is_done) {
|
while (!is_done) {
|
||||||
sys_condition_variable_wait(job->gen_cv, &lock);
|
sys_condition_variable_wait(job->gen_cv, &lock);
|
||||||
@ -485,7 +516,7 @@ INTERNAL SYS_THREAD_DEF(worker_thread_entry_point, thread_arg)
|
|||||||
struct worker_ctx *ctx = thread_local_var_eval(&tl_worker_ctx);
|
struct worker_ctx *ctx = thread_local_var_eval(&tl_worker_ctx);
|
||||||
ctx->worker_id = worker_id;
|
ctx->worker_id = worker_id;
|
||||||
|
|
||||||
struct worker_job_queues *queues[] = { &G.pinned_queues[worker_id], &G.global_queue };
|
struct worker_job_queue *queues[] = { &G.pinned_queues[worker_id], &G.global_queue };
|
||||||
u64 seen_queue_submit_gen = 0;
|
u64 seen_queue_submit_gen = 0;
|
||||||
|
|
||||||
struct sys_lock queue_lock = sys_mutex_lock_s(G.queued_jobs_mutex);
|
struct sys_lock queue_lock = sys_mutex_lock_s(G.queued_jobs_mutex);
|
||||||
@ -503,7 +534,7 @@ INTERNAL SYS_THREAD_DEF(worker_thread_entry_point, thread_arg)
|
|||||||
queue_lock = sys_mutex_lock_s(G.queued_jobs_mutex);
|
queue_lock = sys_mutex_lock_s(G.queued_jobs_mutex);
|
||||||
{
|
{
|
||||||
seen_queue_submit_gen = G.queue_submit_gen;
|
seen_queue_submit_gen = G.queue_submit_gen;
|
||||||
for (i32 queue_index = 0; queue_index < ARRAY_COUNT(queues); ++queue_index) {
|
for (i32 queue_index = 0; queue_index < (i32)ARRAY_COUNT(queues); ++queue_index) {
|
||||||
struct worker_job_queue *queue = queues[queue_index];
|
struct worker_job_queue *queue = queues[queue_index];
|
||||||
struct worker_job *tmp = queue->first;
|
struct worker_job *tmp = queue->first;
|
||||||
while (!job && tmp) {
|
while (!job && tmp) {
|
||||||
@ -511,8 +542,6 @@ INTERNAL SYS_THREAD_DEF(worker_thread_entry_point, thread_arg)
|
|||||||
{
|
{
|
||||||
i32 tmp_id = tmp->num_dispatched;
|
i32 tmp_id = tmp->num_dispatched;
|
||||||
i32 tmp_count = tmp->count;
|
i32 tmp_count = tmp->count;
|
||||||
i32 tmp_pinned_worker = tmp->pinned_worker_id;
|
|
||||||
b32 tmp_is_pinned_to_worker = tmp_pinned_worker == worker_id;
|
|
||||||
if (tmp_id < tmp_count) {
|
if (tmp_id < tmp_count) {
|
||||||
/* Pick job */
|
/* Pick job */
|
||||||
++tmp->num_workers;
|
++tmp->num_workers;
|
||||||
@ -537,6 +566,9 @@ INTERNAL SYS_THREAD_DEF(worker_thread_entry_point, thread_arg)
|
|||||||
__profscope(Dequeue job);
|
__profscope(Dequeue job);
|
||||||
queue_lock = sys_mutex_lock_e(G.queued_jobs_mutex);
|
queue_lock = sys_mutex_lock_e(G.queued_jobs_mutex);
|
||||||
{
|
{
|
||||||
|
if (job->prev == job || job->next == job) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
struct worker_job *prev = job->prev;
|
struct worker_job *prev = job->prev;
|
||||||
struct worker_job *next = job->next;
|
struct worker_job *next = job->next;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
@ -549,6 +581,9 @@ INTERNAL SYS_THREAD_DEF(worker_thread_entry_point, thread_arg)
|
|||||||
} else {
|
} else {
|
||||||
job_queue->last = prev;
|
job_queue->last = prev;
|
||||||
}
|
}
|
||||||
|
if (job->prev == job || job->next == job) {
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&queue_lock);
|
sys_mutex_unlock(&queue_lock);
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/mixer.c
10
src/mixer.c
@ -291,7 +291,7 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
/* Update & read mixes */
|
/* Update & read mixes */
|
||||||
mixes = arena_push_array_no_zero(scratch.arena, struct mix *, G.track_playing_count);
|
mixes = arena_push_array_no_zero(scratch.arena, struct mix *, G.track_playing_count);
|
||||||
for (struct track *track = G.track_first_playing; track; track = track->next) {
|
for (struct track *track = G.track_first_playing; track; track = track->next) {
|
||||||
__profscope(prepare_track);
|
__profscope(Prepare track);
|
||||||
struct mix *mix = &track->mix;
|
struct mix *mix = &track->mix;
|
||||||
mix->desc = track->desc;
|
mix->desc = track->desc;
|
||||||
mixes[mixes_count++] = mix;
|
mixes[mixes_count++] = mix;
|
||||||
@ -301,7 +301,7 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (u64 mix_index = 0; mix_index < mixes_count; ++mix_index) {
|
for (u64 mix_index = 0; mix_index < mixes_count; ++mix_index) {
|
||||||
__profscope(mix_track);
|
__profscope(Mix track);
|
||||||
struct mix *mix = mixes[mix_index];
|
struct mix *mix = mixes[mix_index];
|
||||||
|
|
||||||
if (mix->source->pcm.count <= 0) {
|
if (mix->source->pcm.count <= 0) {
|
||||||
@ -354,7 +354,7 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
|
|
||||||
/* Transform 16 bit source -> 32 bit stereo at output duration */
|
/* Transform 16 bit source -> 32 bit stereo at output duration */
|
||||||
{
|
{
|
||||||
__profscope(resample);
|
__profscope(Resample);
|
||||||
f32 *out_samples = mix_pcm.samples;
|
f32 *out_samples = mix_pcm.samples;
|
||||||
|
|
||||||
u64 out_frames_count = mix_pcm.count / 2;
|
u64 out_frames_count = mix_pcm.count / 2;
|
||||||
@ -408,7 +408,7 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
if (desc.flags & MIXER_FLAG_SPATIALIZE) {
|
if (desc.flags & MIXER_FLAG_SPATIALIZE) {
|
||||||
__profscope(spatialize);
|
__profscope(Spatialize);
|
||||||
|
|
||||||
/* Algorithm constants */
|
/* Algorithm constants */
|
||||||
const f32 rolloff_height = 1.2f;
|
const f32 rolloff_height = 1.2f;
|
||||||
@ -469,7 +469,7 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
__profscope(update_track_effect_data);
|
__profscope(Update track effect data);
|
||||||
struct sys_lock lock = sys_mutex_lock_e(G.mutex);
|
struct sys_lock lock = sys_mutex_lock_e(G.mutex);
|
||||||
for (u64 i = 0; i < mixes_count; ++i) {
|
for (u64 i = 0; i < mixes_count; ++i) {
|
||||||
struct mix *mix = mixes[i];
|
struct mix *mix = mixes[i];
|
||||||
|
|||||||
@ -1254,7 +1254,7 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep)
|
|||||||
|
|
||||||
f32 remaining_dt = timestep;
|
f32 remaining_dt = timestep;
|
||||||
while (remaining_dt > 0) {
|
while (remaining_dt > 0) {
|
||||||
__profscope(step_part);
|
__profscope(Step part);
|
||||||
++phys_iteration;
|
++phys_iteration;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
struct arena_temp scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
@ -1282,7 +1282,7 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep)
|
|||||||
|
|
||||||
f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS;
|
f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS;
|
||||||
for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) {
|
for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) {
|
||||||
__profscope(substep);
|
__profscope(Substep);
|
||||||
|
|
||||||
/* Warm start */
|
/* Warm start */
|
||||||
#if SIM_PHYSICS_ENABLE_WARM_STARTING
|
#if SIM_PHYSICS_ENABLE_WARM_STARTING
|
||||||
|
|||||||
@ -9,9 +9,12 @@
|
|||||||
|
|
||||||
/* Include tracy client */
|
/* Include tracy client */
|
||||||
#define TRACY_ENABLE
|
#define TRACY_ENABLE
|
||||||
#define TRACY_MANUAL_LIFETIME
|
#if 0
|
||||||
#define TRACY_DELAYED_INIT
|
/* Enable manual lifetime */
|
||||||
#if 1
|
# define TRACY_MANUAL_LIFETIME
|
||||||
|
# define TRACY_DELAYED_INIT
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
/* Disable system tracing (very slow) */
|
/* Disable system tracing (very slow) */
|
||||||
# define TRACY_NO_CALLSTACK
|
# define TRACY_NO_CALLSTACK
|
||||||
# define TRACY_NO_SYSTEM_TRACING
|
# define TRACY_NO_SYSTEM_TRACING
|
||||||
@ -19,7 +22,7 @@
|
|||||||
#include STRINGIZE(TRACY_INCLUDE_PATH)
|
#include STRINGIZE(TRACY_INCLUDE_PATH)
|
||||||
|
|
||||||
#define PROFILING_CAPTURE_FRAME_IMAGE 0
|
#define PROFILING_CAPTURE_FRAME_IMAGE 0
|
||||||
#define PROFILING_LOCKS 0
|
#define PROFILING_LOCKS 1
|
||||||
#define PROFILING_D3D 1
|
#define PROFILING_D3D 1
|
||||||
#define PROFILING_CMD_WSTR L"tracy-profiler.exe -a 127.0.0.1"
|
#define PROFILING_CMD_WSTR L"tracy-profiler.exe -a 127.0.0.1"
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "tar.h"
|
#include "tar.h"
|
||||||
#include "incbin.h"
|
#include "incbin.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "job.h"
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Global data
|
* Global data
|
||||||
@ -218,6 +219,20 @@ INTERNAL SYS_THREAD_DEF(resource_watch_monitor_thread_entry_point, _)
|
|||||||
#define WATCH_DISPATCHER_DELAY_SECONDS 0.050
|
#define WATCH_DISPATCHER_DELAY_SECONDS 0.050
|
||||||
#define WATCH_DISPATCHER_DEDUP_DICT_BINS 128
|
#define WATCH_DISPATCHER_DEDUP_DICT_BINS 128
|
||||||
|
|
||||||
|
struct resource_watch_callback_job_sig {
|
||||||
|
struct string name;
|
||||||
|
resource_watch_callback **callbacks;
|
||||||
|
};
|
||||||
|
|
||||||
|
INTERNAL JOB_DEF(resource_watch_callback_job, job)
|
||||||
|
{
|
||||||
|
__prof;
|
||||||
|
struct resource_watch_callback_job_sig *sig = job.sig;
|
||||||
|
struct string name = sig->name;
|
||||||
|
resource_watch_callback *callback = sig->callbacks[job.id];
|
||||||
|
callback(name);
|
||||||
|
}
|
||||||
|
|
||||||
INTERNAL SYS_THREAD_DEF(resource_watch_dispatcher_thread_entry_point, _)
|
INTERNAL SYS_THREAD_DEF(resource_watch_dispatcher_thread_entry_point, _)
|
||||||
{
|
{
|
||||||
(UNUSED)_;
|
(UNUSED)_;
|
||||||
@ -227,8 +242,10 @@ INTERNAL SYS_THREAD_DEF(resource_watch_dispatcher_thread_entry_point, _)
|
|||||||
while (!atomic_i32_eval(&G.watch_shutdown)) {
|
while (!atomic_i32_eval(&G.watch_shutdown)) {
|
||||||
sys_condition_variable_wait(G.watch_dispatcher_cv, &watch_dispatcher_lock);
|
sys_condition_variable_wait(G.watch_dispatcher_cv, &watch_dispatcher_lock);
|
||||||
if (!atomic_i32_eval(&G.watch_shutdown) && G.watch_dispatcher_info_arena->pos > 0) {
|
if (!atomic_i32_eval(&G.watch_shutdown) && G.watch_dispatcher_info_arena->pos > 0) {
|
||||||
|
__profscope(Dispatch resource watch callbacks);
|
||||||
/* Unlock and sleep a bit so duplicate events pile up */
|
/* Unlock and sleep a bit so duplicate events pile up */
|
||||||
{
|
{
|
||||||
|
__profscope(Delay);
|
||||||
sys_mutex_unlock(&watch_dispatcher_lock);
|
sys_mutex_unlock(&watch_dispatcher_lock);
|
||||||
sys_sleep(WATCH_DISPATCHER_DELAY_SECONDS);
|
sys_sleep(WATCH_DISPATCHER_DELAY_SECONDS);
|
||||||
watch_dispatcher_lock = sys_mutex_lock_e(G.watch_dispatcher_mutex);
|
watch_dispatcher_lock = sys_mutex_lock_e(G.watch_dispatcher_mutex);
|
||||||
@ -241,12 +258,25 @@ INTERNAL SYS_THREAD_DEF(resource_watch_dispatcher_thread_entry_point, _)
|
|||||||
MEMZERO_STRUCT(&G.watch_dispatcher_info_list);
|
MEMZERO_STRUCT(&G.watch_dispatcher_info_list);
|
||||||
arena_reset(G.watch_dispatcher_info_arena);
|
arena_reset(G.watch_dispatcher_info_arena);
|
||||||
|
|
||||||
|
/* Build callbacks array */
|
||||||
|
u64 num_callbacks = 0;
|
||||||
|
resource_watch_callback **callbacks = NULL;
|
||||||
|
struct sys_lock callbacks_lock = sys_mutex_lock_s(G.watch_callbacks_mutex);
|
||||||
|
{
|
||||||
|
num_callbacks = G.num_watch_callbacks;
|
||||||
|
callbacks = arena_push_array_no_zero(temp.arena, resource_watch_callback *, num_callbacks);
|
||||||
|
for (u64 i = 0; i < num_callbacks; ++i) {
|
||||||
|
callbacks[i] = G.watch_callbacks[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sys_mutex_unlock(&callbacks_lock);
|
||||||
|
|
||||||
/* Unlock and run callbacks */
|
/* Unlock and run callbacks */
|
||||||
sys_mutex_unlock(&watch_dispatcher_lock);
|
sys_mutex_unlock(&watch_dispatcher_lock);
|
||||||
{
|
{
|
||||||
__profscope(run_resource_watch_callbacks);
|
|
||||||
struct dict *dedup_dict = dict_init(temp.arena, WATCH_DISPATCHER_DEDUP_DICT_BINS);
|
struct dict *dedup_dict = dict_init(temp.arena, WATCH_DISPATCHER_DEDUP_DICT_BINS);
|
||||||
for (struct sys_watch_info *info = watch_info_list.first; info; info = info->next) {
|
for (struct sys_watch_info *info = watch_info_list.first; info; info = info->next) {
|
||||||
|
__profscope(Dispatch);
|
||||||
/* Do not run callbacks for the same file more than once */
|
/* Do not run callbacks for the same file more than once */
|
||||||
b32 skip = false;
|
b32 skip = false;
|
||||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, info->name);
|
u64 hash = hash_fnv64(HASH_FNV64_BASIS, info->name);
|
||||||
@ -256,12 +286,10 @@ INTERNAL SYS_THREAD_DEF(resource_watch_dispatcher_thread_entry_point, _)
|
|||||||
dict_set(temp.arena, dedup_dict, hash, 1);
|
dict_set(temp.arena, dedup_dict, hash, 1);
|
||||||
}
|
}
|
||||||
if (!skip) {
|
if (!skip) {
|
||||||
struct sys_lock callbacks_lock = sys_mutex_lock_s(G.watch_callbacks_mutex);
|
struct resource_watch_callback_job_sig sig = ZI;
|
||||||
for (u64 i = 0; i < G.num_watch_callbacks; ++i) {
|
sig.name = info->name;
|
||||||
resource_watch_callback *callback = G.watch_callbacks[i];
|
sig.callbacks = callbacks;
|
||||||
callback(info->name);
|
job_dispatch_wait(num_callbacks, resource_watch_callback_job, &sig);
|
||||||
}
|
|
||||||
sys_mutex_unlock(&callbacks_lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -649,7 +649,7 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str
|
|||||||
|
|
||||||
/* Blend entities */
|
/* Blend entities */
|
||||||
{
|
{
|
||||||
__profscope(snapshot_lerp_entities);
|
__profscope(Lerp snapshot entities);
|
||||||
u64 num_entities = min_u64(ss0->num_ents_reserved, ss1->num_ents_reserved);
|
u64 num_entities = min_u64(ss0->num_ents_reserved, ss1->num_ents_reserved);
|
||||||
for (u64 i = 0; i < num_entities; ++i) {
|
for (u64 i = 0; i < num_entities; ++i) {
|
||||||
struct sim_ent *e = &ss->ents[i];
|
struct sim_ent *e = &ss->ents[i];
|
||||||
|
|||||||
89
src/sprite.c
89
src/sprite.c
@ -153,11 +153,10 @@ GLOBAL struct {
|
|||||||
|
|
||||||
/* Evictor thread */
|
/* Evictor thread */
|
||||||
struct atomic_i32 evictor_cycle;
|
struct atomic_i32 evictor_cycle;
|
||||||
b32 evictor_shutdown;
|
b32 evictor_scheduler_shutdown;
|
||||||
struct sys_mutex *evictor_mutex;
|
struct sys_mutex *evictor_scheduler_mutex;
|
||||||
struct sys_condition_variable *evictor_cv;
|
struct sys_condition_variable *evictor_scheduler_shutdown_cv;
|
||||||
|
struct sys_thread *evictor_scheduler_thread;
|
||||||
struct sys_thread *evictor_thread;
|
|
||||||
} G = ZI, DEBUG_ALIAS(G, G_sprite);
|
} G = ZI, DEBUG_ALIAS(G, G_sprite);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -204,7 +203,7 @@ INTERNAL struct image_rgba generate_purple_black_image(struct arena *arena, u32
|
|||||||
|
|
||||||
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown);
|
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown);
|
||||||
INTERNAL JOB_DEF(sprite_load_job, arg);
|
INTERNAL JOB_DEF(sprite_load_job, arg);
|
||||||
INTERNAL SYS_THREAD_DEF(sprite_evictor_thread_entry_point, arg);
|
INTERNAL SYS_THREAD_DEF(sprite_evictor_scheduler_thread_entry_point, arg);
|
||||||
|
|
||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, info);
|
INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, info);
|
||||||
@ -256,10 +255,10 @@ struct sprite_startup_receipt sprite_startup(struct gp_startup_receipt *gp_sr,
|
|||||||
|
|
||||||
G.scopes_arena = arena_alloc(GIGABYTE(64));
|
G.scopes_arena = arena_alloc(GIGABYTE(64));
|
||||||
|
|
||||||
G.evictor_mutex = sys_mutex_alloc();
|
G.evictor_scheduler_mutex = sys_mutex_alloc();
|
||||||
G.evictor_cv = sys_condition_variable_alloc();
|
G.evictor_scheduler_shutdown_cv = sys_condition_variable_alloc();
|
||||||
|
|
||||||
G.evictor_thread = sys_thread_alloc(sprite_evictor_thread_entry_point, NULL, LIT("[P2] Sprite evictor"));
|
G.evictor_scheduler_thread = sys_thread_alloc(sprite_evictor_scheduler_thread_entry_point, NULL, LIT("[P2] Sprite evictor scheduler"));
|
||||||
|
|
||||||
app_register_exit_callback(&sprite_shutdown);
|
app_register_exit_callback(&sprite_shutdown);
|
||||||
resource_register_watch_callback(&sprite_resource_watch_callback);
|
resource_register_watch_callback(&sprite_resource_watch_callback);
|
||||||
@ -272,12 +271,12 @@ INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sprite_shutdown)
|
|||||||
__prof;
|
__prof;
|
||||||
/* Signal evictor shutdown */
|
/* Signal evictor shutdown */
|
||||||
{
|
{
|
||||||
struct sys_lock lock = sys_mutex_lock_e(G.evictor_mutex);
|
struct sys_lock lock = sys_mutex_lock_e(G.evictor_scheduler_mutex);
|
||||||
G.evictor_shutdown = true;
|
G.evictor_scheduler_shutdown = true;
|
||||||
sys_condition_variable_broadcast(G.evictor_cv);
|
sys_condition_variable_broadcast(G.evictor_scheduler_shutdown_cv);
|
||||||
sys_mutex_unlock(&lock);
|
sys_mutex_unlock(&lock);
|
||||||
}
|
}
|
||||||
sys_thread_wait_release(G.evictor_thread);
|
sys_thread_wait_release(G.evictor_scheduler_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -430,7 +429,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
|
|
||||||
/* Init frames */
|
/* Init frames */
|
||||||
{
|
{
|
||||||
__profscope(init_frames);
|
__profscope(Init frames);
|
||||||
sheet.image_size = ase.image_size;
|
sheet.image_size = ase.image_size;
|
||||||
sheet.frame_size = ase.frame_size;
|
sheet.frame_size = ase.frame_size;
|
||||||
sheet.frames = arena_push_array(arena, struct sprite_sheet_frame, ase.num_frames);
|
sheet.frames = arena_push_array(arena, struct sprite_sheet_frame, ase.num_frames);
|
||||||
@ -452,7 +451,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
/* Init spans */
|
/* Init spans */
|
||||||
sheet.spans_count = ase.num_spans;
|
sheet.spans_count = ase.num_spans;
|
||||||
if (ase.num_spans > 0) {
|
if (ase.num_spans > 0) {
|
||||||
__profscope(init_spans);
|
__profscope(Init spans);
|
||||||
sheet.spans = arena_push_array(arena, struct sprite_sheet_span, sheet.spans_count);
|
sheet.spans = arena_push_array(arena, struct sprite_sheet_span, sheet.spans_count);
|
||||||
sheet.spans_dict = dict_init(arena, (u64)(ase.num_spans * SHEET_SPAN_LOOKUP_TABLE_BIN_RATIO));
|
sheet.spans_dict = dict_init(arena, (u64)(ase.num_spans * SHEET_SPAN_LOOKUP_TABLE_BIN_RATIO));
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
@ -470,7 +469,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
|
|
||||||
/* Init slices */
|
/* Init slices */
|
||||||
if (ase.num_slice_keys > 0) {
|
if (ase.num_slice_keys > 0) {
|
||||||
__profscope(init_slices);
|
__profscope(Init slices);
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
struct arena_temp scratch = scratch_begin(arena);
|
||||||
|
|
||||||
struct temp_ase_slice_key_node {
|
struct temp_ase_slice_key_node {
|
||||||
@ -1209,7 +1208,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, name)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Evictor thread
|
* Evictor job
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct evict_node {
|
struct evict_node {
|
||||||
@ -1230,34 +1229,21 @@ INTERNAL SORT_COMPARE_FUNC_DEF(evict_sort, arg_a, arg_b, udata)
|
|||||||
return (b_cycle > a_cycle) - (a_cycle > b_cycle);
|
return (b_cycle > a_cycle) - (a_cycle > b_cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE:
|
INTERNAL JOB_DEF(sprite_evictor_job, _)
|
||||||
* A cache node is safe from eviction as long as:
|
|
||||||
* - Its bin mutex is locked
|
|
||||||
* - Any references are held to the node (its refcount > 0)
|
|
||||||
*
|
|
||||||
* An attempt to evict a cache node will occur when:
|
|
||||||
* - Its refcount = 0 and
|
|
||||||
* - The cache is over its memory budget and the node's last reference is longer ago than the grace period
|
|
||||||
* - Resource reloading is enabled and the node is out of date due to a change to its original resource file
|
|
||||||
*/
|
|
||||||
INTERNAL SYS_THREAD_DEF(sprite_evictor_thread_entry_point, arg)
|
|
||||||
{
|
{
|
||||||
(UNUSED)arg;
|
(UNUSED)_;
|
||||||
|
__prof;
|
||||||
struct sys_lock evictor_lock = sys_mutex_lock_e(G.evictor_mutex);
|
|
||||||
while (!G.evictor_shutdown) {
|
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
struct arena_temp scratch = scratch_begin_no_conflict();
|
||||||
|
{
|
||||||
u64 evict_array_count = 0;
|
u64 evict_array_count = 0;
|
||||||
struct evict_node *evict_array = arena_push_dry(scratch.arena, struct evict_node);
|
struct evict_node *evict_array = arena_push_dry(scratch.arena, struct evict_node);
|
||||||
|
{
|
||||||
if (!G.evictor_shutdown) {
|
|
||||||
i32 cur_cycle = atomic_i32_eval(&G.evictor_cycle);
|
i32 cur_cycle = atomic_i32_eval(&G.evictor_cycle);
|
||||||
|
|
||||||
/* Scan for evictable nodes */
|
/* Scan for evictable nodes */
|
||||||
b32 cache_over_budget_threshold = atomic_u64_eval(&G.cache.memory_usage) > CACHE_MEMORY_BUDGET_THRESHOLD;
|
b32 cache_over_budget_threshold = atomic_u64_eval(&G.cache.memory_usage) > CACHE_MEMORY_BUDGET_THRESHOLD;
|
||||||
if (cache_over_budget_threshold || RESOURCE_RELOADING) {
|
if (cache_over_budget_threshold || RESOURCE_RELOADING) {
|
||||||
__profscope(eviction_scan);
|
__profscope(Evictor scan);
|
||||||
for (u64 i = 0; i < CACHE_BINS_COUNT; ++i) {
|
for (u64 i = 0; i < CACHE_BINS_COUNT; ++i) {
|
||||||
struct cache_bin *bin = &G.cache.bins[i];
|
struct cache_bin *bin = &G.cache.bins[i];
|
||||||
struct sys_lock bin_lock = sys_mutex_lock_s(bin->mutex);
|
struct sys_lock bin_lock = sys_mutex_lock_s(bin->mutex);
|
||||||
@ -1298,14 +1284,14 @@ INTERNAL SYS_THREAD_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
|
|
||||||
/* Sort evict nodes */
|
/* Sort evict nodes */
|
||||||
{
|
{
|
||||||
__profscope(eviction_sort);
|
__profscope(Evictor sort);
|
||||||
merge_sort(evict_array, evict_array_count, sizeof(*evict_array), evict_sort, NULL);
|
merge_sort(evict_array, evict_array_count, sizeof(*evict_array), evict_sort, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove evictable nodes from cache until under budget */
|
/* Remove evictable nodes from cache until under budget */
|
||||||
struct evict_node *first_evicted = NULL;
|
struct evict_node *first_evicted = NULL;
|
||||||
{
|
{
|
||||||
__profscope(eviction_cache_removal);
|
__profscope(Evictor cache removal);
|
||||||
b32 stop_evicting = false;
|
b32 stop_evicting = false;
|
||||||
for (u64 i = 0; i < evict_array_count && !stop_evicting; ++i) {
|
for (u64 i = 0; i < evict_array_count && !stop_evicting; ++i) {
|
||||||
struct evict_node *en = &evict_array[i];
|
struct evict_node *en = &evict_array[i];
|
||||||
@ -1351,7 +1337,7 @@ INTERNAL SYS_THREAD_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
if (first_evicted) {
|
if (first_evicted) {
|
||||||
/* Release evicted node memory */
|
/* Release evicted node memory */
|
||||||
{
|
{
|
||||||
__profscope(eviction_memory_release);
|
__profscope(Evictor memory release);
|
||||||
for (struct evict_node *en = first_evicted; en; en = en->next_evicted) {
|
for (struct evict_node *en = first_evicted; en; en = en->next_evicted) {
|
||||||
struct cache_entry *n = en->cache_entry;
|
struct cache_entry *n = en->cache_entry;
|
||||||
if (n->kind == CACHE_ENTRY_KIND_TEXTURE && n->texture->valid) {
|
if (n->kind == CACHE_ENTRY_KIND_TEXTURE && n->texture->valid) {
|
||||||
@ -1363,7 +1349,7 @@ INTERNAL SYS_THREAD_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
|
|
||||||
/* Add evicted nodes to free list */
|
/* Add evicted nodes to free list */
|
||||||
{
|
{
|
||||||
__profscope(eviction_free_list_append);
|
__profscope(Evictor free list append);
|
||||||
struct sys_lock pool_lock = sys_mutex_lock_e(G.cache.entry_pool_mutex);
|
struct sys_lock pool_lock = sys_mutex_lock_e(G.cache.entry_pool_mutex);
|
||||||
for (struct evict_node *en = first_evicted; en; en = en->next_evicted) {
|
for (struct evict_node *en = first_evicted; en; en = en->next_evicted) {
|
||||||
struct cache_entry *n = en->cache_entry;
|
struct cache_entry *n = en->cache_entry;
|
||||||
@ -1376,9 +1362,28 @@ INTERNAL SYS_THREAD_DEF(sprite_evictor_thread_entry_point, arg)
|
|||||||
}
|
}
|
||||||
atomic_i32_eval_add(&G.evictor_cycle, 1);
|
atomic_i32_eval_add(&G.evictor_cycle, 1);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait */
|
}
|
||||||
sys_condition_variable_wait_time(G.evictor_cv, &evictor_lock, SECONDS_FROM_NS(EVICTOR_CYCLE_INTERVAL_NS));
|
|
||||||
|
/* NOTE:
|
||||||
|
* A cache node is safe from eviction as long as:
|
||||||
|
* - Its bin mutex is locked
|
||||||
|
* - Any references are held to the node (its refcount > 0)
|
||||||
|
*
|
||||||
|
* An attempt to evict a cache node will occur when:
|
||||||
|
* - Its refcount = 0 and
|
||||||
|
* - The cache is over its memory budget and the node's last reference is longer ago than the grace period
|
||||||
|
* - Resource reloading is enabled and the node is out of date due to a change to its original resource file
|
||||||
|
*/
|
||||||
|
INTERNAL SYS_THREAD_DEF(sprite_evictor_scheduler_thread_entry_point, arg)
|
||||||
|
{
|
||||||
|
(UNUSED)arg;
|
||||||
|
|
||||||
|
struct sys_lock evictor_lock = sys_mutex_lock_e(G.evictor_scheduler_mutex);
|
||||||
|
while (!G.evictor_scheduler_shutdown) {
|
||||||
|
job_dispatch_wait(1, sprite_evictor_job, NULL);
|
||||||
|
sys_condition_variable_wait_time(G.evictor_scheduler_shutdown_cv, &evictor_lock, SECONDS_FROM_NS(EVICTOR_CYCLE_INTERVAL_NS));
|
||||||
}
|
}
|
||||||
sys_mutex_unlock(&evictor_lock);
|
sys_mutex_unlock(&evictor_lock);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -282,6 +282,7 @@ struct sys_watch_info {
|
|||||||
struct sys_watch_info_list {
|
struct sys_watch_info_list {
|
||||||
struct sys_watch_info *first;
|
struct sys_watch_info *first;
|
||||||
struct sys_watch_info *last;
|
struct sys_watch_info *last;
|
||||||
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_watch *sys_watch_alloc(struct string path);
|
struct sys_watch *sys_watch_alloc(struct string path);
|
||||||
|
|||||||
@ -418,7 +418,7 @@ struct sys_file sys_file_open_read_wait(struct string path)
|
|||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
while ((handle = CreateFileW(path_wstr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
|
while ((handle = CreateFileW(path_wstr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
|
||||||
if (GetLastError() == ERROR_SHARING_VIOLATION) {
|
if (GetLastError() == ERROR_SHARING_VIOLATION) {
|
||||||
__profscope(file_share_conflict_delay);
|
__profscope(File share conflict delay);
|
||||||
Sleep(delay_ms);
|
Sleep(delay_ms);
|
||||||
if (delay_ms < 1024) {
|
if (delay_ms < 1024) {
|
||||||
delay_ms *= 2;
|
delay_ms *= 2;
|
||||||
@ -800,11 +800,11 @@ struct sys_watch_info_list sys_watch_wait(struct arena *arena, struct sys_watch
|
|||||||
if (list.last) {
|
if (list.last) {
|
||||||
list.last->next = info;
|
list.last->next = info;
|
||||||
info->prev = list.last;
|
info->prev = list.last;
|
||||||
list.last = info;
|
|
||||||
} else {
|
} else {
|
||||||
list.first = info;
|
list.first = info;
|
||||||
list.last = info;
|
|
||||||
}
|
}
|
||||||
|
list.last = info;
|
||||||
|
++list.count;
|
||||||
|
|
||||||
struct string16 name16 = ZI;
|
struct string16 name16 = ZI;
|
||||||
name16.text = res->FileName;
|
name16.text = res->FileName;
|
||||||
@ -856,6 +856,7 @@ struct sys_watch_info_list sys_watch_wait(struct arena *arena, struct sys_watch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (wait_res == WAIT_OBJECT_0 + 1) {
|
} else if (wait_res == WAIT_OBJECT_0 + 1) {
|
||||||
|
ResetEvent(w32_watch->wake_handle);
|
||||||
done = true;
|
done = true;
|
||||||
} else {
|
} else {
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
@ -886,6 +887,7 @@ struct sys_watch_info_list sys_watch_info_copy(struct arena *arena, struct sys_w
|
|||||||
dst_list.first = dst;
|
dst_list.first = dst;
|
||||||
dst_list.last = dst;
|
dst_list.last = dst;
|
||||||
}
|
}
|
||||||
|
dst_list.count = src_list.count;
|
||||||
}
|
}
|
||||||
return dst_list;
|
return dst_list;
|
||||||
}
|
}
|
||||||
@ -1634,6 +1636,7 @@ void sys_mutex_release(struct sys_mutex *mutex)
|
|||||||
|
|
||||||
struct sys_lock sys_mutex_lock_e(struct sys_mutex *mutex)
|
struct sys_lock sys_mutex_lock_e(struct sys_mutex *mutex)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct win32_mutex *m = (struct win32_mutex *)mutex;
|
struct win32_mutex *m = (struct win32_mutex *)mutex;
|
||||||
__proflock_before_exclusive_lock(m->profiling_ctx);
|
__proflock_before_exclusive_lock(m->profiling_ctx);
|
||||||
AcquireSRWLockExclusive((SRWLOCK *)&m->srwlock);
|
AcquireSRWLockExclusive((SRWLOCK *)&m->srwlock);
|
||||||
@ -1650,6 +1653,7 @@ struct sys_lock sys_mutex_lock_e(struct sys_mutex *mutex)
|
|||||||
|
|
||||||
struct sys_lock sys_mutex_lock_s(struct sys_mutex *mutex)
|
struct sys_lock sys_mutex_lock_s(struct sys_mutex *mutex)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct win32_mutex *m = (struct win32_mutex *)mutex;
|
struct win32_mutex *m = (struct win32_mutex *)mutex;
|
||||||
__proflock_before_shared_lock(m->profiling_ctx);
|
__proflock_before_shared_lock(m->profiling_ctx);
|
||||||
AcquireSRWLockShared((SRWLOCK *)&m->srwlock);
|
AcquireSRWLockShared((SRWLOCK *)&m->srwlock);
|
||||||
@ -1664,6 +1668,7 @@ struct sys_lock sys_mutex_lock_s(struct sys_mutex *mutex)
|
|||||||
|
|
||||||
void sys_mutex_unlock(struct sys_lock *lock)
|
void sys_mutex_unlock(struct sys_lock *lock)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct win32_mutex *m = (struct win32_mutex *)lock->mutex;
|
struct win32_mutex *m = (struct win32_mutex *)lock->mutex;
|
||||||
#if RTC
|
#if RTC
|
||||||
atomic_i64_eval_add(&m->count, -1);
|
atomic_i64_eval_add(&m->count, -1);
|
||||||
@ -1743,6 +1748,7 @@ void sys_condition_variable_release(struct sys_condition_variable *sys_cv)
|
|||||||
|
|
||||||
void sys_condition_variable_wait(struct sys_condition_variable *sys_cv, struct sys_lock *lock)
|
void sys_condition_variable_wait(struct sys_condition_variable *sys_cv, struct sys_lock *lock)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct win32_condition_variable *cv = (struct win32_condition_variable *)sys_cv;
|
struct win32_condition_variable *cv = (struct win32_condition_variable *)sys_cv;
|
||||||
struct win32_mutex *m = (struct win32_mutex *)lock->mutex;
|
struct win32_mutex *m = (struct win32_mutex *)lock->mutex;
|
||||||
b32 exclusive = lock->exclusive;
|
b32 exclusive = lock->exclusive;
|
||||||
@ -1780,6 +1786,7 @@ void sys_condition_variable_wait(struct sys_condition_variable *sys_cv, struct s
|
|||||||
|
|
||||||
void sys_condition_variable_wait_time(struct sys_condition_variable *sys_cv, struct sys_lock *lock, f64 seconds)
|
void sys_condition_variable_wait_time(struct sys_condition_variable *sys_cv, struct sys_lock *lock, f64 seconds)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct win32_condition_variable *cv = (struct win32_condition_variable *)sys_cv;
|
struct win32_condition_variable *cv = (struct win32_condition_variable *)sys_cv;
|
||||||
struct win32_mutex *m = (struct win32_mutex *)lock->mutex;
|
struct win32_mutex *m = (struct win32_mutex *)lock->mutex;
|
||||||
b32 exclusive = lock->exclusive;
|
b32 exclusive = lock->exclusive;
|
||||||
@ -1818,6 +1825,7 @@ void sys_condition_variable_wait_time(struct sys_condition_variable *sys_cv, str
|
|||||||
|
|
||||||
void sys_condition_variable_signal(struct sys_condition_variable *sys_cv, u32 count)
|
void sys_condition_variable_signal(struct sys_condition_variable *sys_cv, u32 count)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct win32_condition_variable *cv = (struct win32_condition_variable *)sys_cv;
|
struct win32_condition_variable *cv = (struct win32_condition_variable *)sys_cv;
|
||||||
/* Windows will wake all waiters if many single-wakes occur anyway, so we
|
/* Windows will wake all waiters if many single-wakes occur anyway, so we
|
||||||
* might as well wake all ourselves.
|
* might as well wake all ourselves.
|
||||||
@ -1833,6 +1841,7 @@ void sys_condition_variable_signal(struct sys_condition_variable *sys_cv, u32 co
|
|||||||
|
|
||||||
void sys_condition_variable_broadcast(struct sys_condition_variable *sys_cv)
|
void sys_condition_variable_broadcast(struct sys_condition_variable *sys_cv)
|
||||||
{
|
{
|
||||||
|
__prof;
|
||||||
struct win32_condition_variable *cv = (struct win32_condition_variable *)sys_cv;
|
struct win32_condition_variable *cv = (struct win32_condition_variable *)sys_cv;
|
||||||
WakeAllConditionVariable(&cv->condition_variable);
|
WakeAllConditionVariable(&cv->condition_variable);
|
||||||
}
|
}
|
||||||
@ -2232,7 +2241,7 @@ INTERNAL void win32_precise_sleep_timer(f64 seconds, HANDLE timer)
|
|||||||
|
|
||||||
i64 max_ticks = (i64)scheduler_period_ms * 9500;
|
i64 max_ticks = (i64)scheduler_period_ms * 9500;
|
||||||
while (true) {
|
while (true) {
|
||||||
__profscope(win32_sleep_part);
|
__profscope(Sleep part);
|
||||||
/* Break sleep up into parts that are lower than scheduler period */
|
/* Break sleep up into parts that are lower than scheduler period */
|
||||||
f64 remaining_seconds = (f64)(target_qpc - qpc.QuadPart) / (f64)qpc_per_second;
|
f64 remaining_seconds = (f64)(target_qpc - qpc.QuadPart) / (f64)qpc_per_second;
|
||||||
i64 sleep_ticks = (i64)((remaining_seconds - tolerance) * 10000000);
|
i64 sleep_ticks = (i64)((remaining_seconds - tolerance) * 10000000);
|
||||||
@ -2248,7 +2257,7 @@ INTERNAL void win32_precise_sleep_timer(f64 seconds, HANDLE timer)
|
|||||||
|
|
||||||
/* Spin for any remaining time */
|
/* Spin for any remaining time */
|
||||||
{
|
{
|
||||||
__profscope(sleep_spin);
|
__profscope(Sleep spin);
|
||||||
while (qpc.QuadPart < target_qpc) {
|
while (qpc.QuadPart < target_qpc) {
|
||||||
YieldProcessor();
|
YieldProcessor();
|
||||||
QueryPerformanceCounter(&qpc);
|
QueryPerformanceCounter(&qpc);
|
||||||
@ -2276,18 +2285,14 @@ INTERNAL void win32_precise_sleep_legacy(f64 seconds)
|
|||||||
f64 sleep_ms = (seconds * 1000) - tolerance;
|
f64 sleep_ms = (seconds * 1000) - tolerance;
|
||||||
i32 sleep_slices = (i32)(sleep_ms / scheduler_period_ms);
|
i32 sleep_slices = (i32)(sleep_ms / scheduler_period_ms);
|
||||||
if (sleep_slices > 0) {
|
if (sleep_slices > 0) {
|
||||||
__profscope(win32_sleep);
|
__profscope(Legacy sleep part);
|
||||||
Sleep((DWORD)sleep_slices * scheduler_period_ms);
|
Sleep((DWORD)sleep_slices * scheduler_period_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
__profscope(win32_qpc);
|
|
||||||
QueryPerformanceCounter(&qpc);
|
QueryPerformanceCounter(&qpc);
|
||||||
}
|
|
||||||
|
|
||||||
/* Spin for any remaining time */
|
/* Spin for any remaining time */
|
||||||
{
|
{
|
||||||
__profscope(sleep_spin);
|
__profscope(Legacy sleep spin);
|
||||||
while (qpc.QuadPart < target_qpc) {
|
while (qpc.QuadPart < target_qpc) {
|
||||||
YieldProcessor();
|
YieldProcessor();
|
||||||
QueryPerformanceCounter(&qpc);
|
QueryPerformanceCounter(&qpc);
|
||||||
|
|||||||
@ -63,7 +63,7 @@ volatile void *_thread_local_var_eval(struct thread_local_var_meta *meta)
|
|||||||
{
|
{
|
||||||
u64 id_plus_one = atomic_u64_eval(&meta->id_plus_one);
|
u64 id_plus_one = atomic_u64_eval(&meta->id_plus_one);
|
||||||
if (id_plus_one == 0) {
|
if (id_plus_one == 0) {
|
||||||
__profscope(_thread_local_var_eval__REGISTER);
|
__profscope(Register thread local var);
|
||||||
metas_lock();
|
metas_lock();
|
||||||
{
|
{
|
||||||
id_plus_one = atomic_u64_eval(&meta->id_plus_one); /* Reevaluate now that we've locked */
|
id_plus_one = atomic_u64_eval(&meta->id_plus_one); /* Reevaluate now that we've locked */
|
||||||
@ -89,7 +89,7 @@ volatile void *_thread_local_var_eval(struct thread_local_var_meta *meta)
|
|||||||
|
|
||||||
/* Allocate var for thread if unallocated */
|
/* Allocate var for thread if unallocated */
|
||||||
if (!data) {
|
if (!data) {
|
||||||
__profscope(_thread_local_var_eval__ALLOC);
|
__profscope(Alloc thread local var);
|
||||||
/* Allocate */
|
/* Allocate */
|
||||||
arena_align(t->arena, meta->align);
|
arena_align(t->arena, meta->align);
|
||||||
data = arena_push_array_no_zero(t->arena, u8, meta->size);
|
data = arena_push_array_no_zero(t->arena, u8, meta->size);
|
||||||
|
|||||||
12
src/user.c
12
src/user.c
@ -1162,7 +1162,7 @@ INTERNAL void user_update(void)
|
|||||||
{
|
{
|
||||||
/* Copy valid entities */
|
/* Copy valid entities */
|
||||||
{
|
{
|
||||||
__profscope(copy_sprites_for_sorting);
|
__profscope(Build ents list for sorting);
|
||||||
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
for (u64 ent_index = 0; ent_index < G.ss_blended->num_ents_reserved; ++ent_index) {
|
||||||
struct sim_ent *ent = &G.ss_blended->ents[ent_index];
|
struct sim_ent *ent = &G.ss_blended->ents[ent_index];
|
||||||
if (sim_ent_is_valid_and_active(ent)) {
|
if (sim_ent_is_valid_and_active(ent)) {
|
||||||
@ -1173,7 +1173,7 @@ INTERNAL void user_update(void)
|
|||||||
}
|
}
|
||||||
/* Sort */
|
/* Sort */
|
||||||
{
|
{
|
||||||
__profscope(sort_sprites);
|
__profscope(Sort ents);
|
||||||
merge_sort(sorted, sorted_count, sizeof(*sorted), ent_draw_order_cmp, NULL);
|
merge_sort(sorted, sorted_count, sizeof(*sorted), ent_draw_order_cmp, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1183,7 +1183,7 @@ INTERNAL void user_update(void)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
{
|
{
|
||||||
__profscope(draw_entities);
|
__profscope(Draw entities);
|
||||||
for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) {
|
for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) {
|
||||||
struct sim_ent *ent = sorted[sorted_index];
|
struct sim_ent *ent = sorted[sorted_index];
|
||||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||||
@ -1709,7 +1709,7 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
/* Draw crosshair or show cursor */
|
/* Draw crosshair or show cursor */
|
||||||
if (!G.debug_camera) {
|
if (!G.debug_camera) {
|
||||||
__profscope(draw_crosshair);
|
__profscope(Draw crosshair);
|
||||||
struct v2 crosshair_pos = G.user_cursor;
|
struct v2 crosshair_pos = G.user_cursor;
|
||||||
|
|
||||||
struct sprite_tag crosshair_tag = sprite_tag_from_path(LIT("sprite/crosshair.ase"));
|
struct sprite_tag crosshair_tag = sprite_tag_from_path(LIT("sprite/crosshair.ase"));
|
||||||
@ -1726,7 +1726,7 @@ INTERNAL void user_update(void)
|
|||||||
sys_window_cursor_hide(G.window);
|
sys_window_cursor_hide(G.window);
|
||||||
sys_window_cursor_enable_clip(G.window, cursor_clip);
|
sys_window_cursor_enable_clip(G.window, cursor_clip);
|
||||||
} else {
|
} else {
|
||||||
__profscope(update_window_cursor);
|
__profscope(Update windows cursor);
|
||||||
sys_window_cursor_disable_clip(G.window);
|
sys_window_cursor_disable_clip(G.window);
|
||||||
sys_window_cursor_show(G.window);
|
sys_window_cursor_show(G.window);
|
||||||
}
|
}
|
||||||
@ -2055,7 +2055,7 @@ INTERNAL void user_update(void)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
{
|
{
|
||||||
__profscope(render);
|
__profscope(Render);
|
||||||
|
|
||||||
struct rect user_viewport = RECT_FROM_V2(V2(0, 0), G.user_size);
|
struct rect user_viewport = RECT_FROM_V2(V2(0, 0), G.user_size);
|
||||||
struct v2i32 user_resolution = v2_round_to_int(user_viewport.size);
|
struct v2i32 user_resolution = v2_round_to_int(user_viewport.size);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user