From 99b6c3eeb9f2a90397a74b222221d7298ac5c756 Mon Sep 17 00:00:00 2001 From: Jarcode Date: Thu, 30 Nov 2017 18:24:10 -0800 Subject: [PATCH] various changes --- render.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- shaders/rc.glsl | 25 ++++++++++++++++++++----- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/render.c b/render.c index ba8155d..32ca415 100644 --- a/render.c +++ b/render.c @@ -359,11 +359,44 @@ struct gl_data { #ifdef GLAD_DEBUG +struct err_msg { + GLenum code; + const char* msg; + const char* cname; +}; + +#define CODE(c) .code = c, .cname = #c + +static const struct err_msg err_lookup[] = { + { CODE(GL_INVALID_ENUM), .msg = "Invalid enum parameter" }, + { CODE(GL_INVALID_VALUE), .msg = "Invalid value parameter" }, + { CODE(GL_INVALID_OPERATION), .msg = "Invalid operation" }, + { CODE(GL_STACK_OVERFLOW), .msg = "Stack overflow" }, + { CODE(GL_STACK_UNDERFLOW), .msg = "Stack underflow" }, + { CODE(GL_OUT_OF_MEMORY), .msg = "Out of memory" }, + { CODE(GL_INVALID_FRAMEBUFFER_OPERATION), .msg = "Out of memory" }, + #ifdef GL_CONTEXT_LOSS + { CODE(GL_CONTEXT_LOSS), .msg = "Context loss (graphics device or driver reset?)" } + #endif +}; + +#undef CODE + static void glad_debugcb(const char* name, void *funcptr, int len_args, ...) { GLenum err = glad_glGetError(); if (err != GL_NO_ERROR) { - fprintf(stderr, "glGetError(): %d in %s\n", err, name); + const char* cname = "?", * msg = "Unknown error code"; + size_t t; + for (t = 0; t < sizeof(err_lookup) / sizeof(struct err_msg); ++t) { + if (err_lookup[t].code == err) { + cname = err_lookup[t].cname; + msg = err_lookup[t].msg; + break; + } + } + fprintf(stderr, "glGetError(): %d (%s) in %s: '%s'\n", + (int) err, cname, name, msg); abort(); } } @@ -910,16 +943,16 @@ struct renderer* rd_new(int x, int y, int w, int h, const char* data) { gl->audio_tex_r = create_1d_tex(); gl->audio_tex_l = create_1d_tex(); - + if (gl->interpolate) { size_t isz = (r->bufsize_request / gl->bufscale) * sizeof(float); float* ibuf = malloc(isz * 4); + memset(ibuf, 0, isz * 4); gl->interpolate_buf[0] = &ibuf[isz * 0]; gl->interpolate_buf[1] = &ibuf[isz * 1]; gl->interpolate_buf[2] = &ibuf[isz * 2]; gl->interpolate_buf[3] = &ibuf[isz * 3]; } - { gl->t_data = malloc(sizeof(void*) * t_count); @@ -955,6 +988,11 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi if (!r->alive) return; + /* Force disable interpolation if the update rate is close to or higher than the frame rate */ + float uratio = (gl->ur / gl->fr); /* update : framerate ratio */ + bool old_interpolate = gl->interpolate; + // gl->interpolate = uratio <= 0.9F ? old_interpolate : false; + /* Perform buffer scaling */ size_t nsz = gl->bufscale > 1 ? (bsz / gl->bufscale) : 0; float nlb[nsz], nrb[nsz]; @@ -992,7 +1030,7 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi ilbe = gl->interpolate_buf[IB_END_LEFT ][t], irbs = gl->interpolate_buf[IB_START_RIGHT][t], irbe = gl->interpolate_buf[IB_END_RIGHT ][t], - mod = (gl->ur / gl->fr) * gl->kcounter; /* modifier for this frame */ + mod = uratio * gl->kcounter; /* modifier for this frame */ if (mod > 1.0F) mod = 1.0F; ilb[t] = ilbs + ((ilbe - ilbs) * mod); irb[t] = irbs + ((irbe - irbs) * mod); @@ -1146,6 +1184,9 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi gl->fcounter = 0; /* reset frame counter */ gl->ucounter = 0; /* reset update counter */ } + + /* Restore interpolation settings */ + gl->interpolate = old_interpolate; } void rd_destroy(struct renderer* r) { diff --git a/shaders/rc.glsl b/shaders/rc.glsl index daa2c9c..6fab13a 100644 --- a/shaders/rc.glsl +++ b/shaders/rc.glsl @@ -35,9 +35,13 @@ high refresh rates. This feature itself, however, will effect performance as it - will have to interpolate data every frame on the CPU. + will have to interpolate data every frame on the CPU. It will + automatically (and temporarily) disable itself if the update + rate is close to, or higher than the framerate: - This will delay data output by two update frames, so it can + if (update_rate / frame_rate > 0.9) disable_interpolation; + + This will delay data output by one update frame, so it can desync audio with visual effects on low UPS configs. */ #request setinterpolate true @@ -64,11 +68,22 @@ The following settings (@22050 Hz) produce the listed rates: Sample UPS Description - - 2048 -> 43.0 (low accuracy, cheap), use with ~60 FPS - - 1024 -> 86.1 (high accuracy, expensive), use with 120+ FPS + - 2048 -> 43.0 (low accuracy, cheap), use with < 60 FPS + - 1024 -> 86.1 (high accuracy, expensive), use with >= 60 FPS - 512 -> 172.3 (extreme accuracy, very expensive), use only for graphing accurate spectrum data with - custom modules. */ + custom modules. + + If the framerate drops below the update rate, the update rate + will be locked to the framerate (to prevent wasting CPU time). + This behaviour means you can use a 1024 sample size on a 60Hz + monitor with vsync enabled to get 60FPS and 60UPS. + + For high refresh rate monitors (120+ Hz), it's recommended to + also stick with the 1024 sample size and use interpolation to + smooth the data, as accuracy beyond this setting is mostly + meaningless for visual purposes. +*/ #request setsamplesize 1024 /* Audio buffer size to be used for processing and shaders.