Permalink
Browse files

Add an option for using EXT_bindable_uniform to update shader uniforms

  • Loading branch information...
1 parent 40b71b3 commit 6af24593a30f6087395b4d1f8de1336a46e4f25b @JasonGreen committed Apr 21, 2011
Showing with 156 additions and 17 deletions.
  1. +10 −0 perftest.c
  2. +2 −0 perftest.h
  3. +144 −17 perftest_ogl.c
View
@@ -24,6 +24,8 @@ int gLastFPSDrawFrameCount;
int gFPSFramesToSkip = 100; /* Skip the first 100 frames when averaging FPS (TODO: make configurable?) */
int gIgnoreKeyboard = 0;
int gUseGLSL = 0; /* Default to ARB_vp/fp */
+int gUseBindableUniform = 0;
+int gHaveBindableUniform = 0;
int gUseVAO = 0;
int gResetVertexPointers = 0;
int gResetConstants = 0;
@@ -311,6 +313,7 @@ static void displayHelp()
printf(" -use_d3d9=[0,1] 1 = Use D3D9 engine (Windows only)\n");
printf(" -use_multithreaded_gl=[0,1] 1 = Use MultiThreaded GL (Mac only) (M)\n");
printf(" -use_glsl=[0,1] 1 = Use GLSL, 0 = Use ARB_vp/fp (G)\n");
+ printf(" -use_bindable_uniform=[0,1] 1 = Use EXT_bindable_uniform with GLSL (B)\n");
printf(" -use_vao=[0,1] 1 = Use VAO, 0 = Use general vertex attrib calls (V)\n");
printf(" -reset_constants=[0,1] 1 = Reset constants before each draw call (C)\n");
printf(" -reset_vertex_pointers=[0,1] 1 = Reset vertex pointers before each draw call (P)\n");
@@ -351,13 +354,19 @@ int handleKeyPress(unsigned char key)
/* Some commands are only handled when using OpenGL */
switch(key) {
+ case 'b':
+ case 'B':
+ if (!gUseD3D9 && gHaveBindableUniform && gUseGLSL)
+ TOGGLE_OPTION(gUseBindableUniform);
+ break;
case 'c':
case 'C':
TOGGLE_OPTION(gResetConstants)
case 'g':
case 'G':
if (!gUseD3D9)
TOGGLE_OPTION(gUseGLSL)
+ break;
case 'm':
case 'M':
#ifdef __APPLE__
@@ -409,6 +418,7 @@ static void parseCommandLineOptions(int argc, char** argv)
parseIntArgument(argv[i], "use_d3d9", &gUseD3D9);
parseIntArgument(argv[i], "use_multithreaded_gl", &gUseMultiThreadedGL);
parseIntArgument(argv[i], "use_glsl", &gUseGLSL);
+ parseIntArgument(argv[i], "use_bindable_uniform", &gUseBindableUniform);
parseIntArgument(argv[i], "use_vao", &gUseVAO);
parseIntArgument(argv[i], "reset_constants", &gResetConstants);
parseIntArgument(argv[i], "reset_vertex_pointers", &gResetVertexPointers);
View
@@ -66,6 +66,8 @@ extern float gRotation;
/* config options */
extern int gIgnoreKeyboard;
extern int gUseGLSL;
+extern int gHaveBindableUniform;
+extern int gUseBindableUniform;
extern int gHaveVAO;
extern int gUseVAO;
extern int gResetVertexPointers;
View
@@ -27,6 +27,22 @@ PFNGLGENBUFFERSARBPROC p_glGenBuffers = NULL;
PFNGLBUFFERSUBDATAARBPROC p_glBufferSubData = NULL;
PFNGLBUFFERDATAARBPROC p_glBufferData = NULL;
+/* EXT_bindable_uniform */
+typedef void (APIENTRY * PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);
+typedef GLint (APIENTRY * PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);
+typedef GLint * (APIENTRY * PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);
+PFNGLUNIFORMBUFFEREXTPROC p_glUniformBufferEXT = NULL;
+PFNGLGETUNIFORMBUFFERSIZEEXTPROC p_glGetUniformBufferSizeEXT = NULL;
+PFNGLGETUNIFORMOFFSETEXTPROC p_glGetUniformOffsetEXT = NULL;
+#ifndef GL_EXT_bindable_uniform
+#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#define GL_UNIFORM_BUFFER_EXT 0x8DEE
+#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF
+#endif
+
/* ARB_multitexture prototypes */
typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
PFNGLACTIVETEXTUREARBPROC p_glActiveTexture = NULL;
@@ -117,6 +133,7 @@ int gWindowID = 0;
int gHaveGPUProgramParameters = 0;
GLuint gVBO;
GLuint gEBO;
+GLuint gBindableBuffer = 0;
GLuint gVAO;
GLuint gVAO2;
GLuint gFBO;
@@ -125,6 +142,7 @@ GLuint gFBOColorTexture1;
GLuint gFBODepthTexture;
GLuint gDummyTex;
GLuint gShader;
+GLuint gShaderBindable;
GLuint gPostShader;
GLuint gVertexProgram;
GLuint gFragmentProgram;
@@ -134,6 +152,8 @@ GLuint gPositionLoc = -1;
GLuint gQuadPositionLoc = -1;
GLuint gProjMatrixLoc = -1;
GLuint gMvMatrixLoc = -1;
+GLuint gProjMatrixBindableLoc = -1;
+GLuint gMvMatrixBindableLoc = -1;
GLuint gWindowWidth;
GLuint gWindowHeight;
GLuint gWindowHasBeenResized = 0;
@@ -142,6 +162,17 @@ GLuint gWindowHasBeenResized = 0;
/* Shader source */
/******************************************************************************/
+const GLchar* basicVertexShaderSourceBindable =
+ "#extension GL_EXT_bindable_uniform : enable\n"
+ "attribute vec4 inPosition;\n"
+ "uniform mat4 inProjectionMatrix;\n"
+ "bindable uniform mat4 inModelViewMatrix;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = inProjectionMatrix * inModelViewMatrix* inPosition;\n"
+ " gl_Position.z = 0.0;\n"
+ "}\n";
+
const GLchar* basicVertexShaderSource =
"attribute vec4 inPosition;\n"
"uniform mat4 inProjectionMatrix;\n"
@@ -384,12 +415,53 @@ static void createDummyTex()
/******************************************************************************/
+static void utilGetMatrixLocations(GLuint prog,
+ GLuint *projMatrix,
+ GLuint *mvMatrix)
+{
+ *projMatrix = p_glGetUniformLocation(prog, "inProjectionMatrix");
+ *mvMatrix = p_glGetUniformLocation(prog, "inModelViewMatrix");
+}
+
+static void utilCreateBindableUniformBuffer()
+{
+ GLuint bufSize;
+
+ p_glGenBuffers(1, &gBindableBuffer);
+ if (!gBindableBuffer) {
+ fprintf(stderr, "Unable to create bindable uniform VBO\n");
+ gHaveBindableUniform = 0;
+ gUseBindableUniform = 0;
+ return;
+ }
+ p_glBindBuffer(GL_UNIFORM_BUFFER_EXT, gBindableBuffer);
+ p_glBufferData(GL_UNIFORM_BUFFER_EXT,
+ sizeof(gModelViewMatrixf),
+ NULL,
+ GL_STATIC_DRAW);
+
+ /* Sanity size check */
+ bufSize = p_glGetUniformBufferSizeEXT(gShaderBindable, gMvMatrixBindableLoc);
+ if (bufSize != sizeof(gModelViewMatrixf)) {
+ fprintf(stderr, "bufSize (%d) != matrix size (%zd)\n",
+ bufSize,
+ sizeof(gModelViewMatrixf));
+ gHaveBindableUniform = 0;
+ gUseBindableUniform = 0;
+ return;
+ }
+ /* Bind the buffer to the bindable modelview matrix */
+ p_glUniformBufferEXT(gShaderBindable, gMvMatrixBindableLoc, gBindableBuffer);
+ p_glBufferSubData(GL_UNIFORM_BUFFER_EXT, 0, sizeof(gModelViewMatrixf), gModelViewMatrixf);
+}
+
static void createShaders()
{
GLint status;
/* The basic shader for the geometry */
gShader = p_glCreateProgram();
+ GLuint vertexShaderBindable = 0;
GLuint vertexShader= utilCompileShader(GL_VERTEX_SHADER,
basicVertexShaderSource);
GLuint fragmentShader = utilCompileShader(GL_FRAGMENT_SHADER,
@@ -405,6 +477,30 @@ static void createShaders()
printf("program link error\n");
utilPrintInfoLog(0, gShader);
}
+ utilGetMatrixLocations(gShader, &gProjMatrixLoc, &gMvMatrixLoc);
+
+ /* Vertex shader that uses EXT_bindable_uniform */
+ if (gHaveBindableUniform) {
+ gShaderBindable = p_glCreateProgram();
+ vertexShaderBindable = utilCompileShader(GL_VERTEX_SHADER,
+ basicVertexShaderSourceBindable);
+
+ /* Use the same fragment shader */
+ p_glAttachShader(gShaderBindable, vertexShaderBindable);
+ p_glAttachShader(gShaderBindable, fragmentShader);
+
+ p_glLinkProgram(gShaderBindable);
+
+ p_glGetProgramiv(gShaderBindable, GL_LINK_STATUS, &status);
+ if (!status) {
+ printf("program link error from bindable shader\n");
+ utilPrintInfoLog(0, gShaderBindable);
+ }
+ utilGetMatrixLocations(gShaderBindable,
+ &gProjMatrixBindableLoc,
+ &gMvMatrixBindableLoc);
+ utilCreateBindableUniformBuffer();
+ }
/* The post processing shader */
gPostShader = p_glCreateProgram();
@@ -567,10 +663,23 @@ static void createVertexBuffers()
/******************************************************************************/
-static inline void update_modelview_constants(const float* params)
+/* Updates the modelview matrix with the given float params. mtxLoc is only
+ * used in the GLSL case and is the handle to the matrix uniform */
+static inline void update_modelview_constants(const float* params, GLuint mtxLoc)
{
- if (gUseGLSL)
- p_glUniformMatrix4fv(gMvMatrixLoc, 1, GL_FALSE, params);
+ if (gUseGLSL) {
+ if (gUseBindableUniform) {
+ /* TODO: Add other update mechanisms here for profiling:
+ * - glUniform4fv() (would need to rework the shader a bit)
+ * - glBufferSubData()
+ * - APPLE_flush_buffer_range
+ * - ARB_flush_buffer_range
+ */
+ p_glUniformMatrix4fv(mtxLoc, 1, GL_FALSE, params);
+ } else {
+ p_glUniformMatrix4fv(mtxLoc, 1, GL_FALSE, params);
+ }
+ }
else {
if (gHaveGPUProgramParameters)
p_glProgramLocalParameters4fvEXT(GL_VERTEX_PROGRAM_ARB, 4, 4, params);
@@ -585,22 +694,29 @@ static inline void update_modelview_constants(const float* params)
static void drawScene()
{
int i;
+ GLuint mvMtxLoc = 0;
if (gUseGLSL) {
- p_glUseProgram(gShader);
+ GLuint prog;
+ GLuint projMtxLoc;
+
+ if (gUseBindableUniform) {
+ prog = gShaderBindable;
+ projMtxLoc = gProjMatrixBindableLoc;
+ mvMtxLoc = gMvMatrixBindableLoc;
+ } else {
+ prog = gShader;
+ projMtxLoc = gProjMatrixLoc;
+ mvMtxLoc = gMvMatrixLoc;
+ }
+
+ /* Enable GLSL and disable any ARB programs */
+ p_glUseProgram(prog);
glDisable(GL_VERTEX_PROGRAM_ARB);
- p_glBindProgramARB(GL_VERTEX_PROGRAM_ARB, gVertexProgram);
glDisable(GL_FRAGMENT_PROGRAM_ARB);
- p_glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, gFragmentProgram);
/* Upload new projection matrix */
- if (gProjMatrixLoc == -1)
- gProjMatrixLoc = p_glGetUniformLocation(gShader, "inProjectionMatrix");
- p_glUniformMatrix4fv(gProjMatrixLoc, 1, GL_FALSE, gProjectionMatrixf);
-
- /* Grab modelview uniform pointer if needed */
- if (gMvMatrixLoc == -1)
- gMvMatrixLoc = p_glGetUniformLocation(gShader, "inModelViewMatrix");
+ p_glUniformMatrix4fv(projMtxLoc, 1, GL_FALSE, gProjectionMatrixf);
} else {
p_glUseProgram(0);
@@ -628,15 +744,15 @@ static void drawScene()
p_glBindVertexArray(gVAO);
if (gResetConstants || i == 0)
- update_modelview_constants(gModelViewMatrixf);
+ update_modelview_constants(gModelViewMatrixf, mvMtxLoc);
glDrawElements(GL_TRIANGLES, NUM_INDICES*3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
if (gResetVertexPointers)
p_glBindVertexArray(gVAO2);
if (gResetConstants || i == 0)
- update_modelview_constants(gModelViewMatrixf2);
+ update_modelview_constants(gModelViewMatrixf2, mvMtxLoc);
glDrawElements(GL_TRIANGLES, NUM_INDICES*3, GL_UNSIGNED_SHORT,BUFFER_OFFSET(0));
}
@@ -656,15 +772,15 @@ static void drawScene()
p_glVertexAttribPointer(gPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
if (gResetConstants || i == 0)
- update_modelview_constants(gModelViewMatrixf);
+ update_modelview_constants(gModelViewMatrixf, mvMtxLoc);
glDrawElements(GL_TRIANGLES, NUM_INDICES*3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
if (gResetVertexPointers)
p_glVertexAttribPointer(gPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(36));
if (gResetConstants || i == 0)
- update_modelview_constants(gModelViewMatrixf2);
+ update_modelview_constants(gModelViewMatrixf2, mvMtxLoc);
glDrawElements(GL_TRIANGLES, NUM_INDICES*3, GL_UNSIGNED_SHORT,BUFFER_OFFSET(0));
}
@@ -884,6 +1000,17 @@ static void checkGLExtensions()
killProcess(1);
}
+ /* Grab bindable uniform pointers */
+ if (glutExtensionSupported("GL_EXT_bindable_uniform")) {
+ gHaveBindableUniform = 1;
+ GET_PROC_ADDRESS(p_glUniformBufferEXT, glUniformBufferEXT);
+ GET_PROC_ADDRESS(p_glGetUniformBufferSizeEXT, glGetUniformBufferSizeEXT);
+ GET_PROC_ADDRESS(p_glGetUniformOffsetEXT, glGetUniformOffsetEXT);
+ } else {
+ gHaveBindableUniform = 0;
+ gUseBindableUniform = 0;
+ }
+
/* Grab VAO extension pointers */
if (glutExtensionSupported("GL_ARB_vertex_array_object")) {
GET_PROC_ADDRESS(p_glGenVertexArrays, glGenVertexArrays);

0 comments on commit 6af2459

Please sign in to comment.