Skip to content

Commit

Permalink
lib: Replace various bools with a single enum
Browse files Browse the repository at this point in the history
Renderer state management is still generally a mess, I want to delete
most of that code by restructuring things, but this is a nice start.
  • Loading branch information
vkoskiv committed Nov 2, 2024
1 parent 94269a7 commit 5d7d695
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 39 deletions.
7 changes: 4 additions & 3 deletions src/lib/api/c-ray.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,11 @@ bool cr_renderer_set_str_pref(struct cr_renderer *ext, enum cr_renderer_param p,
void cr_renderer_stop(struct cr_renderer *ext) {
if (!ext) return;
struct renderer *r = (struct renderer *)ext;
r->state.render_aborted = true;
while (r->prefs.iterative && !r->state.exit_done) {
r->state.s = r_exiting;
// TODO: use pthread_cond instead of silly busy-waiting loops like this
do {
timer_sleep_ms(10);
}
} while (r->prefs.iterative && r->state.s == r_exiting);
}

void cr_renderer_toggle_pause(struct cr_renderer *ext) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/datatypes/tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct render_tile *tile_next_interactive(struct renderer *r, struct tile_set *s
}
if (!tile) {
// FIXME: shared state to indicate pause instead of accessing worker state
if (r->state.render_aborted || r->state.workers.items[0].paused) {
if (r->state.s != r_rendering || r->state.workers.items[0].paused) {
mutex_release(set->tile_mutex);
return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/protocol/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ void *client_connection_thread(void *arg) {
}

// And just wait for commands.
while (r->state.rendering && !state->thread_complete) {
while (r->state.s == r_rendering && !state->thread_complete) {
cJSON *request = readJSON(client->socket);
if (containsStats(request)) {
cJSON *array = cJSON_GetObjectItem(request, "tiles");
Expand Down
18 changes: 9 additions & 9 deletions src/lib/protocol/worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,19 @@ static void *workerThread(void *arg) {
thread->completedSamples = 1;

struct texture *tileBuffer = NULL;
while (thread->current && r->state.rendering) {
while (thread->current && r->state.s == r_rendering) {
if (!tileBuffer || tileBuffer->width != thread->current->width || tileBuffer->height != thread->current->height) {
tex_destroy(tileBuffer);
tileBuffer = tex_new(float_p, thread->current->width, thread->current->height, 3);
}
long totalUsec = 0;
long samples = 0;

while (thread->completedSamples < r->prefs.sampleCount+1 && r->state.rendering) {
while (thread->completedSamples < r->prefs.sampleCount+1 && r->state.s == r_rendering) {
timer_start(&timer);
for (int y = thread->current->end.y - 1; y > thread->current->begin.y - 1; --y) {
for (int x = thread->current->begin.x; x < thread->current->end.x; ++x) {
if (r->state.render_aborted || !g_running) goto bail;
if (r->state.s != r_rendering || !g_running) goto bail;
uint32_t pixIdx = (uint32_t)(y * cam->width + x);
initSampler(sampler, SAMPLING_STRATEGY, thread->completedSamples - 1, r->prefs.sampleCount, pixIdx);

Expand Down Expand Up @@ -207,8 +207,7 @@ static void *workerThread(void *arg) {
#define active_msec 16

static cJSON *startRender(int connectionSocket, size_t thread_limit) {
g_worker_renderer->state.rendering = true;
g_worker_renderer->state.render_aborted = false;
g_worker_renderer->state.s = r_rendering;
logr(info, "Starting network render job\n");

size_t threadCount = thread_limit ? thread_limit : g_worker_renderer->prefs.threads;
Expand Down Expand Up @@ -268,7 +267,7 @@ static cJSON *startRender(int connectionSocket, size_t thread_limit) {
}

int pauser = 0;
while (g_worker_renderer->state.rendering) {
while (g_worker_renderer->state.s == r_rendering) {
// Send stats about 4x/s
if (pauser == 256 / active_msec) {
cJSON *stats = newAction("stats");
Expand All @@ -288,7 +287,7 @@ static cJSON *startRender(int connectionSocket, size_t thread_limit) {
if (!sendJSON(connectionSocket, stats, NULL)) {
logr(debug, "Connection lost, bailing out.\n");
// Setting this flag also kills the threads.
g_worker_renderer->state.rendering = false;
g_worker_renderer->state.s = r_exiting;
}
mutex_release(g_worker_socket_mutex);
pauser = 0;
Expand All @@ -299,12 +298,13 @@ static cJSON *startRender(int connectionSocket, size_t thread_limit) {
for (size_t t = 0; t < threadCount; ++t) {
if (workerThreadStates[t].threadComplete) inactive++;
}
if (g_worker_renderer->state.render_aborted || inactive == threadCount)
g_worker_renderer->state.rendering = false;
if (inactive == threadCount) break;

timer_sleep_ms(active_msec);
}

g_worker_renderer->state.s = r_exiting;

//Make sure workder threads are terminated before continuing (This blocks)
for (size_t t = 0; t < threadCount; ++t) {
thread_wait(&worker_threads[t]);
Expand Down
40 changes: 19 additions & 21 deletions src/lib/renderer/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

static bool g_aborted = false;

// FIXME: c-ray is a library now, so just setting upa global handler like this
// is a bit ugly.
void sigHandler(int sig) {
if (sig == 2) { //SIGINT
logr(plain, "\n");
Expand Down Expand Up @@ -226,8 +228,7 @@ void renderer_render(struct renderer *r) {

logr(info, "Pathtracing%s...\n", r->prefs.iterative ? " iteratively" : "");

r->state.rendering = true;
r->state.render_aborted = false;
r->state.s = r_rendering;

if (r->state.clients.count) logr(info, "Using %lu render worker%s totaling %lu thread%s.\n", r->state.clients.count, PLURAL(r->state.clients.count), r->state.clients.count, PLURAL(r->state.clients.count));

Expand Down Expand Up @@ -267,32 +268,29 @@ void renderer_render(struct renderer *r) {
}

//Start main thread loop to handle renderer feedback and state management
while (r->state.rendering) {
if (g_aborted) {
r->state.render_aborted = true;
while (r->state.s == r_rendering) {
size_t inactive = 0;
for (size_t w = 0; w < r->state.workers.count; ++w) {
if (r->state.workers.items[w].thread_complete) inactive++;
}
if (g_aborted || inactive == r->state.workers.count) break;

struct callback status = r->state.callbacks[cr_cb_status_update];
if (status.fn) {
update_cb_info(r, &set, &cb_info);
status.fn(&cb_info, status.user_data);
}

size_t inactive = 0;
for (size_t w = 0; w < r->state.workers.count; ++w) {
if (r->state.workers.items[w].thread_complete) inactive++;
}
if (r->state.render_aborted || inactive == r->state.workers.count)
r->state.rendering = false;
timer_sleep_ms(r->state.workers.items[0].paused ? paused_msec : active_msec);
}

r->state.s = r_exiting;
r->state.current_set = NULL;

//Make sure render threads are terminated before continuing (This blocks)
for (size_t w = 0; w < r->state.workers.count; ++w) {
for (size_t w = 0; w < r->state.workers.count; ++w)
thread_wait(&r->state.workers.items[w].thread);
}

struct callback stop = r->state.callbacks[cr_cb_on_stop];
if (stop.fn) {
update_cb_info(r, &set, &cb_info);
Expand All @@ -301,7 +299,7 @@ void renderer_render(struct renderer *r) {
if (info_tiles) free(info_tiles);
tile_set_free(&set);
logr(info, "Renderer exiting\n");
r->state.exit_done = true;
r->state.s = r_idle;
}

// An interactive render thread that progressively
Expand All @@ -322,13 +320,13 @@ void *render_thread_interactive(void *arg) {

struct timeval timer = {0};

while (tile && r->state.rendering) {
while (tile && r->state.s == r_rendering) {
long total_us = 0;

timer_start(&timer);
for (int y = tile->end.y - 1; y > tile->begin.y - 1; --y) {
for (int x = tile->begin.x; x < tile->end.x; ++x) {
if (r->state.render_aborted) goto exit;
if (r->state.s != r_rendering) goto exit;
uint32_t pixIdx = (uint32_t)(y * (*buf)->width + x);
//FIXME: This does not converge to the same result as with regular renderThread.
//I assume that's because we'd have to init the sampler differently when we render all
Expand Down Expand Up @@ -362,7 +360,7 @@ void *render_thread_interactive(void *arg) {
threadState->currentTile = NULL;
tile = tile_next_interactive(r, threadState->tiles);
//Pause rendering when bool is set
while (threadState->paused && !r->state.render_aborted) {
while (threadState->paused && r->state.s == r_rendering) {
threadState->in_pause_loop = true;
timer_sleep_ms(100);
}
Expand Down Expand Up @@ -401,14 +399,14 @@ void *render_thread(void *arg) {
struct timeval timer = { 0 };
size_t samples = 1;

while (tile && r->state.rendering) {
while (tile && r->state.s == r_rendering) {
long total_us = 0;

while (samples < r->prefs.sampleCount + 1 && r->state.rendering) {
while (samples < r->prefs.sampleCount + 1 && r->state.s == r_rendering) {
timer_start(&timer);
for (int y = tile->end.y - 1; y > tile->begin.y - 1; --y) {
for (int x = tile->begin.x; x < tile->end.x; ++x) {
if (r->state.render_aborted) goto exit;
if (r->state.s != r_rendering) goto exit;
uint32_t pixIdx = (uint32_t)(y * (*buf)->width + x);
initSampler(sampler, SAMPLING_STRATEGY, samples - 1, r->prefs.sampleCount, pixIdx);

Expand Down Expand Up @@ -436,7 +434,7 @@ void *render_thread(void *arg) {
samples++;
tile->completed_samples++;
//Pause rendering when bool is set
while (threadState->paused && !r->state.render_aborted) {
while (threadState->paused && r->state.s == r_rendering) {
timer_sleep_ms(100);
}
threadState->avg_per_sample_us = total_us / samples;
Expand Down
12 changes: 8 additions & 4 deletions src/lib/renderer/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@ struct callback {
void *user_data;
};

enum renderer_state {
r_idle = 0,
r_rendering,
r_restarting,
r_exiting,
};

/// Renderer state data
struct state {
size_t finishedPasses; // For interactive mode
bool rendering;
// TODO: Rename to request_abort, and use an enum for actual state
bool render_aborted; //SDL listens for X key pressed, which sets this
bool exit_done;
enum renderer_state s;
struct worker_arr workers;
struct render_client_arr clients;
struct callback callbacks[5];
Expand Down

0 comments on commit 5d7d695

Please sign in to comment.