commit a5db2ccfe67eafd2190706e6017c57b22b05716e
parent e9877da533f6161b1d7f679fc70012ceb329431a
Author: Brian Swetland <swetland@frotz.net>
Date:   Sun,  1 Sep 2013 02:25:46 -0700
shaders: auto-bind uniform blocks and samplers
Uniform blocks named "block[0-3]" are bound to bind points 0..3
Sampler uniforms named "sampler[0-3]" are bound to texture units 0..3
Diffstat:
2 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/common/app.h b/common/app.h
@@ -83,9 +83,11 @@ struct GeometryShader {
 
 struct Program {
 	unsigned id;
-	Program() : id(0) {};
+	unsigned bound;
+	Program() : id(0), bound(0) {};
 	~Program() { if (id) { glDeleteProgram(id); } };
-	void use(void) { glUseProgram(id); }
+	void use(void) { glUseProgram(id); if (!bound) bind(); }
+	void bind(void);
 	int link(VertexShader *vs, PixelShader *ps);
 	int link(VertexShader *vs, GeometryShader *gs, PixelShader *ps);
 	int load(const char *vsfn, const char *psfn);
diff --git a/common/shaders.cc b/common/shaders.cc
@@ -53,6 +53,13 @@ int Program::link(VertexShader *vs, PixelShader *ps) {
 	return link(vs, NULL, ps);
 }
 
+static const char *_blocknames[] = {
+	"block0", "block1", "block2", "block3",
+};
+static const char *_samplernames[] = {
+	"sampler0", "sampler1", "sampler2", "sampler3",
+};
+
 int Program::link(VertexShader *vs, GeometryShader *gs, PixelShader *ps) {
 	unsigned n;
 	int r;
@@ -71,7 +78,29 @@ int Program::link(VertexShader *vs, GeometryShader *gs, PixelShader *ps) {
 	if (id)
 		glDeleteProgram(id);
 	id = n;
-	return 0;
+
+	/* bind uniform block indices to bindpoints based on their name */
+	for (n = 0; n < sizeof(_blocknames) / sizeof(_blocknames[0]); n++) {
+		r = glGetUniformBlockIndex(id, _blocknames[n]);
+		if (r != GL_INVALID_INDEX) {
+			fprintf(stderr,"found %s @ %d\n", _blocknames[n], r);
+			glUniformBlockBinding(id, r, n);
+		}
+	}
+}
+
+/* defer final link steps until the first time glUseProgram() is called, */
+void Program::bind() {
+	unsigned n;
+	int r;
+	for (n = 0; n < sizeof(_samplernames) / sizeof(_samplernames[0]); n++) {
+		r = glGetUniformLocation(id, _samplernames[n]);
+		if (r != -1) {
+			fprintf(stderr,"found %s @ %d\n", _samplernames[0], r);
+			glUniform1i(r, n);
+		}
+	}
+	bound = 1;
 }
 
 int Program::load(const char *vsfn, const char *gsfn, const char *psfn) {