summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2021-09-25 16:01:54 -0700
committerVito Caputo <vcaputo@pengaru.com>2021-09-26 18:05:06 -0700
commita59229b6d83057650b320e44ad1f2e74f6fceac7 (patch)
tree2e204f70a800fbf0837eae70be93cc03f317747f
parent6f1584f3d16ed04934da9bb1a7591ae3d4127b9a (diff)
shader: introduce shader_active_uniforms()
The existing shader api only supports caller-provided uniforms and attributes at instantiation time, with no ability to introspect what uniforms are actually actively present in a given shader. This commit adds introspection of the active uniforms for a given shader at creation time, as well as when reloaded, keeping the information around to be accessed via shader_active_uniforms(). The immediate impetus for this is supporting runtime discovery of uniforms present in the shader source, with the intention of exposing these as sequencer tracks for external manipulation.
-rw-r--r--src/pig.c10
-rw-r--r--src/shader.c75
-rw-r--r--src/shader.h7
3 files changed, 80 insertions, 12 deletions
diff --git a/src/pig.c b/src/pig.c
index 6c11c67..6161b8d 100644
--- a/src/pig.c
+++ b/src/pig.c
@@ -72,10 +72,12 @@ static void randomize_color(v3f_t *color)
static void pig_uniforms_func(shader_t *shader, void *uniforms_ctxt, void *render_ctxt, unsigned n_uniforms, const int *uniforms, const m4f_t *model_x, float alpha)
{
- play_t *play = render_ctxt;
- pig_t *pig = uniforms_ctxt;
- unsigned t0, t1;
- float r = randf();
+ play_t *play = render_ctxt;
+ pig_t *pig = uniforms_ctxt;
+ unsigned t0, t1;
+ float r = randf();
+ const shader_uniform_t *active_uniforms;
+ int n_active_uniforms;
if (play_ticks_elapsed(play, PLAY_TICKS_TIMER2, 1000)) {
if (shader_reload_files(shader) < 0)
diff --git a/src/shader.c b/src/shader.c
index 1cadc7f..83df512 100644
--- a/src/shader.c
+++ b/src/shader.c
@@ -22,16 +22,20 @@
#include "glad.h"
#include "macros.h"
+#include "shader.h"
+
typedef struct shader_t {
- unsigned program, refcnt;
- unsigned n_uniforms, n_attributes;
- const char **uniforms, **attributes;
- int *uniform_locations, *attribute_locations;
- const char *vs_path, *fs_path;
- struct timespec vs_mtime, fs_mtime;
-
- int locations[];
+ unsigned program, refcnt;
+ unsigned n_uniforms, n_attributes;
+ const char **uniforms, **attributes;
+ int *uniform_locations, *attribute_locations;
+ const char *vs_path, *fs_path;
+ struct timespec vs_mtime, fs_mtime;
+ shader_uniform_t *active_uniforms;
+ int n_active_uniforms;
+
+ int locations[];
} shader_t;
@@ -81,6 +85,58 @@ unsigned int shader_pair_new_bare(const char *vs_src, const char *fs_src)
return shader;
}
+
+/* query a shader for its active uniforms, returns results in res_uniforms
+ * the returned results are owned by the shader, do not free them, they will be
+ * cleaned up with shader_free() or reallocated by shader_reload_files()
+ */
+void shader_active_uniforms(shader_t *shader, int *res_n_uniforms, const shader_uniform_t **res_uniforms)
+{
+ assert(shader);
+ assert(res_n_uniforms);
+ assert(res_uniforms);
+
+ *res_n_uniforms = shader->n_active_uniforms;
+ *res_uniforms = shader->active_uniforms;
+}
+
+
+static void refresh_active_uniforms(shader_t *shader)
+{
+ int n, maxlen;
+
+ assert(shader);
+
+ if (shader->active_uniforms) {
+ for (int i = 0; i < shader->n_active_uniforms; i++)
+ free(shader->active_uniforms[i].name);
+ free(shader->active_uniforms);
+ shader->active_uniforms = NULL;
+ shader->n_active_uniforms = 0;
+ }
+
+ glGetProgramiv(shader->program, GL_ACTIVE_UNIFORMS, &n);
+ glGetProgramiv(shader->program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen);
+
+ /* FIXME: this is currently written such that allocation failures just cut the
+ * active uniforms short instead of throwing an error, but should probably
+ * be rewritten to fail and report the ENOMEM errors.
+ */
+ shader->active_uniforms = calloc(n, sizeof(shader_uniform_t));
+ if (shader->active_uniforms) {
+ for (int i = 0; i < n; i++) {
+ shader->active_uniforms[i].name = calloc(maxlen, sizeof(char));
+ if (!shader->active_uniforms[i].name)
+ break;
+
+ glGetActiveUniform(shader->program, i, maxlen, /* length */ NULL, /* size */ NULL, &shader->active_uniforms[i].type, shader->active_uniforms[i].name);
+ shader->active_uniforms[i].location = glGetUniformLocation(shader->program, shader->active_uniforms[i].name);
+ shader->n_active_uniforms++;
+ }
+ }
+}
+
+
static void get_locations(shader_t *shader)
{
for (unsigned i = 0; i < shader->n_uniforms; i++)
@@ -90,6 +146,7 @@ static void get_locations(shader_t *shader)
shader->attribute_locations[i] = glGetAttribLocation(shader->program, shader->attributes[i]);
}
+
shader_t * shader_pair_new(const char *vs_src, const char *fs_src, unsigned n_uniforms, const char **uniforms, unsigned n_attributes, const char **attributes)
{
shader_t *shader;
@@ -112,6 +169,7 @@ shader_t * shader_pair_new(const char *vs_src, const char *fs_src, unsigned n_un
shader->attribute_locations = &shader->locations[n_uniforms];
get_locations(shader);
+ refresh_active_uniforms(shader);
return shader;
}
@@ -178,6 +236,7 @@ int shader_reload_files(shader_t *shader)
free(fs_src);
get_locations(shader);
+ refresh_active_uniforms(shader);
return ret;
}
diff --git a/src/shader.h b/src/shader.h
index b52189a..a7df2ec 100644
--- a/src/shader.h
+++ b/src/shader.h
@@ -19,6 +19,12 @@
typedef struct shader_t shader_t;
+typedef struct shader_uniform_t {
+ char *name;
+ GLenum type;
+ int location;
+} shader_uniform_t;
+
unsigned int shader_pair_new_bare(const char *vs_src, const char *fs_src);
shader_t * shader_pair_new(const char *vs_src, const char *fs_src, unsigned n_uniforms, const char **uniforms, unsigned n_attributes, const char **attributes);
shader_t * shader_pair_new_files(const char *vs_path, const char *fs_path, unsigned n_uniforms, const char **uniforms, unsigned n_attributes, const char **attributes);
@@ -26,5 +32,6 @@ void shader_ref(shader_t *shader);
shader_t * shader_free(shader_t *shader);
void shader_use(shader_t *shader, unsigned *res_n_uniforms, int **res_uniform_locations, unsigned *res_n_attributes, int **res_attribute_locations);
int shader_reload_files(shader_t *shader);
+void shader_active_uniforms(shader_t *shader, int *res_n_uniforms, const shader_uniform_t **res_uniforms);
#endif
© 2021 All Rights Reserved