Added '@' include specifier, #define workaround, closes #74, closes #75

This commit is contained in:
Jarcode
2018-10-26 21:40:31 -07:00
parent 93df114308
commit f4ad41df32
13 changed files with 106 additions and 54 deletions

View File

@@ -4,7 +4,7 @@ obj = $(src:.c=.o)
# Build type parameter
ifeq ($(BUILD),debug)
CFLAGS_BUILD = -O0 -ggdb -Wall
CFLAGS_BUILD = -O0 -ggdb -Wall -DGLAVA_DEBUG
GLAD_GEN = c-debug
STRIP_CMD = $(info Skipping `strip` for debug builds)
else

View File

@@ -21,6 +21,7 @@
#define REQUEST 3
#define INCLUDE 4
#define COLOR 5
#define DEFINE 6
struct sbuf {
char* buf;
@@ -131,6 +132,22 @@ static struct schar directive(struct glsl_ext* ext, char** args,
size_t args_sz, int state,
size_t line, const char* f) {
switch (state) {
case DEFINE: {
/* Workaround for re-defining macros in GLSL. By default this is generally an error in most
compilers/drivers, but we would prefer to override (non-function) definitions instead.
Due to how this directive is parsed, the macro itself is still emitted afterwards. */
if (args_sz == 0) {
parse_error_s(line, f, "No arguments provided to #define directive!");
}
size_t bsz = (strlen(args[0]) * 3) + 64;
struct schar ret = { .buf = malloc(bsz) };
int r = snprintf(ret.buf, bsz, "#ifdef %1$s\n#undef %1$s\n#endif\n", args[0]);
if (r < 0) abort();
ret.sz = r;
free_after(ext, ret.buf);
return ret;
}
case INCLUDE: {
if (args_sz == 0) {
parse_error_s(line, f, "No arguments provided to #include directive!");
@@ -143,6 +160,15 @@ static struct schar directive(struct glsl_ext* ext, char** args,
target = &target[1];
ext->cd = ext->cfd;
}
/* Handle `@` default specifier */
if (tsz && target[0] == '@') {
if (!ext->dd) {
parse_error_s(line, f, "encountered '@' path specifier while no default "
"directory is available in the current context");
}
target = &target[1];
ext->cd = ext->dd;
}
char path[strlen(ext->cd) + tsz + 2];
snprintf(path, sizeof(path) / sizeof(char), "%s/%s", ext->cd, target);
@@ -169,6 +195,7 @@ static struct schar directive(struct glsl_ext* ext, char** args,
.source_len = st.st_size,
.cd = ext->cd,
.cfd = ext->cfd,
.dd = ext->dd,
.handlers = ext->handlers
};
@@ -258,14 +285,8 @@ static struct schar directive(struct glsl_ext* ext, char** args,
parse_error(line, f, "unknown request type '%s'", request);
}
}
struct schar ret = {
.buf = NULL,
.sz = 0
};
return ret;
}
default: return (struct schar) { .buf = NULL, .sz = 0 };
}
}
@@ -405,28 +426,34 @@ void ext_process(struct glsl_ext* ext, const char* f) {
else goto copy; /* copy character if it ended the sequence */
}
}
/* emit contents from start of macro to current index and resume regular parsing*/
#define skip_macro() \
do { \
n_append(&sbuf, t - macro_start_idx, &ext->source[macro_start_idx]); \
state = at == '\n' ? LINE_START : GLSL; \
goto copy; \
} while (0)
case MACRO: { /* processing start of macro */
switch (at) {
case '\n':
case ' ':
case '\t':
case '\0': {
/* end parsing directive */
if (!strncmp("#request", &ext->source[macro_start_idx], t - macro_start_idx)
|| !strncmp("#REQUEST", &ext->source[macro_start_idx], t - macro_start_idx)) {
state = REQUEST;
goto prepare_arg_parse;
} else if (!strncmp("#include", &ext->source[macro_start_idx],
t - macro_start_idx)
|| !strncmp("#INCLUDE", &ext->source[macro_start_idx],
t - macro_start_idx)) {
state = INCLUDE;
goto prepare_arg_parse;
} else {
n_append(&sbuf, t - macro_start_idx, &ext->source[macro_start_idx]);
state = at == '\n' ? LINE_START : GLSL;
goto copy;
}
case '\0': { /* end parsing directive */
#define DIRECTIVE_CMP(lower, upper) \
(!strncmp("#" lower, &ext->source[macro_start_idx], t - macro_start_idx) \
|| !strncmp("#" upper, &ext->source[macro_start_idx], t - macro_start_idx))
#define DIRECTIVE_CASE(lower, upper) \
do { if (state == MACRO && DIRECTIVE_CMP(#lower, #upper)) { state = upper; goto prepare_arg_parse; } } while (0)
DIRECTIVE_CASE(request, REQUEST);
DIRECTIVE_CASE(include, INCLUDE);
DIRECTIVE_CASE(define, DEFINE);
/* no match */
if (state == MACRO) skip_macro();
#undef DIRECTIVE_CMP
#undef DIRECTIVE_CASE
prepare_arg_parse:
{
arg_start_idx = t + 1;
@@ -443,17 +470,18 @@ void ext_process(struct glsl_ext* ext, const char* f) {
parse_error(line, f, "Unexpected character '%c' while parsing GLSL directive", at);
}
}
/* scope-violating macro to copy the result of the currently parsed argument */
#define copy_arg(end) \
do { if (end - arg_start_idx > 0) { \
++args_sz; \
args = realloc(args, sizeof(char*) * args_sz); \
args[args_sz - 1] = malloc((end - arg_start_idx) + 1); \
memcpy(args[args_sz - 1], &ext->source[arg_start_idx], end - arg_start_idx); \
args[args_sz - 1][end - arg_start_idx] = '\0'; \
} } while (0)
/* scope-violating macro to copy the result of the currently parsed argument */
#define copy_arg(end) \
do { if (end - arg_start_idx > 0) { \
++args_sz; \
args = realloc(args, sizeof(char*) * args_sz); \
args[args_sz - 1] = malloc((end - arg_start_idx) + 1); \
memcpy(args[args_sz - 1], &ext->source[arg_start_idx], end - arg_start_idx); \
args[args_sz - 1][end - arg_start_idx] = '\0'; \
} } while (0)
case REQUEST:
case INCLUDE: {
case INCLUDE:
case DEFINE: {
switch (at) {
case ' ':
case '\t':
@@ -466,7 +494,7 @@ void ext_process(struct glsl_ext* ext, const char* f) {
arg_start_idx = t + 1;
} else arg_start = false;
if (at == '\n') {
if (at == '\n' || state == DEFINE) {
/* end directive */
size_t a;
struct schar r = directive(ext, args, args_sz, state, line, f);
@@ -479,10 +507,15 @@ void ext_process(struct glsl_ext* ext, const char* f) {
n_append(&sbuf, r.sz, r.buf);
append(&sbuf, "\n");
}
state = LINE_START;
if (state == DEFINE) skip_macro();
else state = LINE_START;
}
break;
case '(':
if (state != DEFINE || args_sz != 0) goto arg; /* only handle first arg of #define */
skip_macro(); /* ignore macro functions */
case '"':
if (state == DEFINE) goto arg; /* do not handle quoting for #define */
if (quoted) {
/* end arg */
copy_arg(t);
@@ -494,12 +527,14 @@ void ext_process(struct glsl_ext* ext, const char* f) {
quoted = true;
} else arg_start = false;
break;
default:
arg_start = false;
default: {
arg: arg_start = false;
}
}
continue;
}
#undef copy_arg
}
copy:
if (at != '\0')

View File

@@ -27,6 +27,7 @@ struct glsl_ext {
size_t source_len; /* IN: raw source len */
const char* cd; /* IN: current directory */
const char* cfd; /* IN: config directory, if NULL it is assumed to cd */
const char* dd; /* IN: default directory */
void** destruct; /* internal */
size_t destruct_sz; /* internal */

View File

@@ -135,6 +135,7 @@ static GLuint shaderload(const char* rpath,
GLenum type,
const char* shader,
const char* config,
const char* defaults,
struct request_handler* handlers,
int shader_version,
bool raw,
@@ -181,6 +182,7 @@ static GLuint shaderload(const char* rpath,
.source_len = raw ? 0 : st.st_size,
.cd = shader,
.cfd = config,
.dd = defaults,
.handlers = handlers,
.processed = (char*) (raw ? shader : NULL),
.p_len = raw ? s_len : 0
@@ -216,10 +218,14 @@ static GLuint shaderload(const char* rpath,
if (ret == GL_FALSE) {
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &ilen);
if (ilen) {
GLchar buf[ilen];
glGetShaderInfoLog(s, ilen, NULL, buf);
GLchar ebuf[ilen];
glGetShaderInfoLog(s, ilen, NULL, ebuf);
fprintf(stderr, "Shader compilation failed for '%s':\n", path);
fwrite(buf, sizeof(GLchar), ilen - 1, stderr);
fwrite(ebuf, sizeof(GLchar), ilen - 1, stderr);
#ifdef GLAVA_DEBUG
fprintf(stderr, "Processed shader source for '%s':\n", path);
fwrite(buf, sizeof(GLchar), sl, stderr);
#endif
return 0;
} else {
fprintf(stderr, "Shader compilation failed for '%s', but no info was available\n", path);
@@ -276,11 +282,11 @@ static GLuint shaderlink_f(GLuint* arr) {
}
/* load shaders */
#define shaderbuild(gl, shader_path, c, r, v, ...) \
shaderbuild_f(gl, shader_path, c, r, v, (const char*[]) {__VA_ARGS__, 0})
#define shaderbuild(gl, shader_path, c, d, r, v, ...) \
shaderbuild_f(gl, shader_path, c, d, r, v, (const char*[]) {__VA_ARGS__, 0})
static GLuint shaderbuild_f(struct gl_data* gl,
const char* shader_path,
const char* config,
const char* config, const char* defaults,
struct request_handler* handlers,
int shader_version,
const char** arr) {
@@ -296,7 +302,7 @@ static GLuint shaderbuild_f(struct gl_data* gl,
if (path[t] == '.') {
if (!strcmp(path + t + 1, "frag") || !strcmp(path + t + 1, "glsl")) {
if (!(shaders[i] = shaderload(path, GL_FRAGMENT_SHADER,
shader_path, config, handlers,
shader_path, config, defaults, handlers,
shader_version, false, gl))) {
return 0;
}
@@ -317,7 +323,7 @@ static GLuint shaderbuild_f(struct gl_data* gl,
}
}
/* load builtin vertex shader */
shaders[sz] = shaderload(NULL, GL_VERTEX_SHADER, VERTEX_SHADER_SRC, NULL, handlers, shader_version, true, gl);
shaders[sz] = shaderload(NULL, GL_VERTEX_SHADER, VERTEX_SHADER_SRC, NULL, NULL, handlers, shader_version, true, gl);
fflush(stdout);
return shaderlink_f(shaders);
}
@@ -1054,9 +1060,11 @@ struct renderer* rd_new(const char** paths, const char* entry,
directories will be populated with symlinks to the installed modules. */
const char* data;
const char* dd; /* defaults dir (system) */
const char* env = gl->wcb->get_environment();
size_t d_len, e_len;
for (const char** i = paths; (data = *i) != NULL; ++i) dd = data;
for (const char** i = paths; (data = *i) != NULL; ++i) {
d_len = strlen(data);
e_len = env ? strlen(env) : 0;
@@ -1237,7 +1245,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
};
current = s;
GLuint id = shaderbuild(gl, shaders, data, handlers, shader_version, d->d_name);
GLuint id = shaderbuild(gl, shaders, data, dd, handlers, shader_version, d->d_name);
if (!id) {
abort();
}
@@ -1298,7 +1306,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
char util[usz]; /* module pack path to use */
snprintf(util, usz, "%s/%s", data, util_folder);
loading_smooth_pass = true;
if (!(gl->sm_prog = shaderbuild(gl, util, data, handlers, shader_version, "smooth_pass.frag")))
if (!(gl->sm_prog = shaderbuild(gl, util, data, dd, handlers, shader_version, "smooth_pass.frag")))
abort();
loading_smooth_pass = false;
}
@@ -1475,9 +1483,9 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
"}" "\n";
if (!setup) {
bg_prog = shaderlink(shaderload(NULL, GL_VERTEX_SHADER, VERTEX_SHADER_SRC,
NULL, NULL, 330, true, gl),
NULL, NULL, NULL, 330, true, gl),
shaderload(NULL, GL_FRAGMENT_SHADER, frag_shader,
NULL, NULL, 330, true, gl));
NULL, NULL, NULL, 330, true, gl));
bg_utex = glGetUniformLocation(bg_prog, "tex");
bg_screen = glGetUniformLocation(bg_prog, "screen");
glBindFragDataLocation(bg_prog, 1, "fragment");

View File

@@ -6,6 +6,7 @@ uniform ivec2 screen;
#request uniform "audio_sz" audio_sz
uniform int audio_sz;
#include "@bars.glsl"
#include ":bars.glsl"
#request uniform "audio_l" audio_l

View File

@@ -7,6 +7,7 @@ uniform ivec2 screen;
uniform int audio_sz;
#include ":util/smooth.glsl"
#include "@circle.glsl"
#include ":circle.glsl"
#request uniform "audio_l" audio_l

View File

@@ -6,6 +6,7 @@ uniform sampler2D tex; /* screen texture */
out vec4 fragment; /* output */
#include "@circle.glsl"
#include ":circle.glsl"
void main() {

View File

@@ -21,7 +21,7 @@
/* 1 to invert (vertically), 0 otherwise */
#define INVERT 0
/* Gravity step, overrude frin `smooth_parameters.glsl` */
/* Gravity step, overrude from `smooth_parameters.glsl` */
#request setgravitystep 2.4
/* Smoothing factor, override from `smooth_parameters.glsl` */

View File

@@ -40,6 +40,7 @@ uniform int audio_sz;
*/
#include ":util/smooth.glsl"
#include "@graph.glsl"
#include ":graph.glsl"
#request uniform "audio_l" audio_l

View File

@@ -8,6 +8,7 @@ uniform ivec2 screen; /* screen dimensions */
out vec4 fragment; /* output */
#include "@graph.glsl"
#include ":graph.glsl"
void main() {

View File

@@ -7,6 +7,7 @@ uniform ivec2 screen;
uniform int audio_sz;
#include ":util/smooth.glsl"
#include "@radial.glsl"
#include ":radial.glsl"
#request uniform "audio_l" audio_l

View File

@@ -11,6 +11,7 @@ uniform sampler1D audio_l;
out vec4 fragment;
#include "@wave.glsl"
#include ":wave.glsl"
#define index(offset) ((texture(audio_l, (gl_FragCoord.x + offset) / screen.x).r - 0.5) * AMPLIFY) + 0.5F

View File

@@ -8,6 +8,7 @@ uniform ivec2 screen; /* screen dimensions */
out vec4 fragment; /* output */
#include "@wave.glsl"
#include ":wave.glsl"
void main() {