Code to get uniform locations

This commit is contained in:
Kovid Goyal
2017-09-11 08:40:01 +05:30
parent 8ce2794a8a
commit d2b3052918
2 changed files with 57 additions and 22 deletions

View File

@@ -105,9 +105,21 @@ glew_init(PyObject UNUSED *self) {
// }}} // }}}
// Programs {{{ // Programs {{{
enum Program { CELL_PROGRAM, CURSOR_PROGRAM, BORDERS_PROGRAM, NUM_PROGRAMS }; enum ProgramNames { CELL_PROGRAM, CURSOR_PROGRAM, BORDERS_PROGRAM, NUM_PROGRAMS };
static GLuint program_ids[NUM_PROGRAMS] = {0}; typedef struct {
char name[256];
GLint size;
GLenum type;
} Uniform;
typedef struct {
GLuint id;
Uniform uniforms[256];
GLint num_of_uniforms;
} Program;
static Program programs[NUM_PROGRAMS] = {{0}};
static inline GLuint static inline GLuint
compile_shader(GLenum shader_type, const char *source) { compile_shader(GLenum shader_type, const char *source) {
@@ -130,14 +142,37 @@ compile_shader(GLenum shader_type, const char *source) {
return shader_id; return shader_id;
} }
static inline bool
init_uniforms(int program) {
Program *p = programs + program;
glGetProgramiv(p->id, GL_ACTIVE_UNIFORMS, &(p->num_of_uniforms));
if (set_error_from_gl()) return false;
for (GLint i = 0; i < p->num_of_uniforms; i++) {
Uniform *u = p->uniforms + i;
glGetActiveUniform(p->id, (GLuint)i, sizeof(u->name)/sizeof(u->name[0]), NULL, &(u->size), &(u->type), u->name);
if (set_error_from_gl()) return false;
}
return true;
}
static inline GLint static inline GLint
get_attrib_location(int program, const char *name) { uniform_location(int program, const char *name) {
return glGetAttribLocation(program_ids[program], name); for (GLint i = 0; i < programs[program].num_of_uniforms; i++) {
if (strncmp(programs[program].uniforms[i].name, name, sizeof(programs[program].uniforms[i].name)) == 0) return i;
}
return -1;
}
static inline GLint
attrib_location(int program, const char *name) {
return glGetAttribLocation(programs[program].id, name);
} }
static void static void
bind_program(int program) { bind_program(int program) {
glUseProgram(program_ids[program]); glUseProgram(programs[program].id);
} }
static void static void
@@ -244,12 +279,12 @@ add_attribute_to_vao(int p, ssize_t vao_idx, const char *name, GLint size, GLenu
VAO *vao = vaos + vao_idx; VAO *vao = vaos + vao_idx;
static char err[256] = {0}; static char err[256] = {0};
if (!vao->num_buffers) { set_local_error("You must create a buffer for this attribute first"); return false; } if (!vao->num_buffers) { set_local_error("You must create a buffer for this attribute first"); return false; }
GLint attrib_location = get_attrib_location(p, name); GLint aloc = attrib_location(p, name);
if (set_error_from_gl()) return false; if (set_error_from_gl()) return false;
if (attrib_location == -1) { snprintf(err, sizeof(err)/sizeof(err[0]), "No attribute named: %s found in this program", name); set_local_error(err); return false; } if (aloc == -1) { snprintf(err, sizeof(err)/sizeof(err[0]), "No attribute named: %s found in this program", name); set_local_error(err); return false; }
ssize_t buf = vao->buffers[vao->num_buffers - 1]; ssize_t buf = vao->buffers[vao->num_buffers - 1];
if (!bind_buffer(buf)) return false; if (!bind_buffer(buf)) return false;
glEnableVertexAttribArray(attrib_location); glEnableVertexAttribArray(aloc);
if (set_error_from_gl()) return false; if (set_error_from_gl()) return false;
switch(data_type) { switch(data_type) {
case GL_BYTE: case GL_BYTE:
@@ -258,15 +293,15 @@ add_attribute_to_vao(int p, ssize_t vao_idx, const char *name, GLint size, GLenu
case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT:
case GL_INT: case GL_INT:
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
glVertexAttribIPointer(attrib_location, size, data_type, stride, offset); glVertexAttribIPointer(aloc, size, data_type, stride, offset);
break; break;
default: default:
glVertexAttribPointer(attrib_location, size, data_type, GL_FALSE, stride, offset); glVertexAttribPointer(aloc, size, data_type, GL_FALSE, stride, offset);
break; break;
} }
if (set_error_from_gl()) return false; if (set_error_from_gl()) return false;
if (divisor) { if (divisor) {
glVertexAttribDivisor(attrib_location, divisor); glVertexAttribDivisor(aloc, divisor);
if (set_error_from_gl()) return false; if (set_error_from_gl()) return false;
} }
unbind_buffer(buf); unbind_buffer(buf);
@@ -317,33 +352,34 @@ compile_program(PyObject UNUSED *self, PyObject *args) {
GLuint vertex_shader_id = 0, fragment_shader_id = 0; GLuint vertex_shader_id = 0, fragment_shader_id = 0;
if (!PyArg_ParseTuple(args, "iss", &which, &vertex_shader, &fragment_shader)) return NULL; if (!PyArg_ParseTuple(args, "iss", &which, &vertex_shader, &fragment_shader)) return NULL;
if (which < CELL_PROGRAM || which >= NUM_PROGRAMS) { PyErr_Format(PyExc_ValueError, "Unknown program: %d", which); return NULL; } if (which < CELL_PROGRAM || which >= NUM_PROGRAMS) { PyErr_Format(PyExc_ValueError, "Unknown program: %d", which); return NULL; }
if (program_ids[which] != 0) { PyErr_SetString(PyExc_ValueError, "program already compiled"); return NULL; } if (programs[which].id != 0) { PyErr_SetString(PyExc_ValueError, "program already compiled"); return NULL; }
program_ids[which] = glCreateProgram(); programs[which].id = glCreateProgram();
if (program_ids[which] == 0) { set_error_from_gl(); return NULL; } if (programs[which].id == 0) { set_error_from_gl(); return NULL; }
vertex_shader_id = compile_shader(GL_VERTEX_SHADER, vertex_shader); vertex_shader_id = compile_shader(GL_VERTEX_SHADER, vertex_shader);
if (vertex_shader_id == 0) goto end; if (vertex_shader_id == 0) goto end;
fragment_shader_id = compile_shader(GL_FRAGMENT_SHADER, fragment_shader); fragment_shader_id = compile_shader(GL_FRAGMENT_SHADER, fragment_shader);
if (vertex_shader_id == 0) goto end; if (vertex_shader_id == 0) goto end;
glAttachShader(program_ids[which], vertex_shader_id); glAttachShader(programs[which].id, vertex_shader_id);
if (set_error_from_gl()) goto end; if (set_error_from_gl()) goto end;
glAttachShader(program_ids[which], fragment_shader_id); glAttachShader(programs[which].id, fragment_shader_id);
glLinkProgram(program_ids[which]); glLinkProgram(programs[which].id);
GLint ret = GL_FALSE; GLint ret = GL_FALSE;
glGetProgramiv(program_ids[which], GL_LINK_STATUS, &ret); glGetProgramiv(programs[which].id, GL_LINK_STATUS, &ret);
if (ret != GL_TRUE) { if (ret != GL_TRUE) {
GLsizei len; GLsizei len;
glGetProgramInfoLog(program_ids[which], sizeof(glbuf), &len, glbuf); glGetProgramInfoLog(programs[which].id, sizeof(glbuf), &len, glbuf);
fprintf(stderr, "Failed to compile GLSL shader!\n%s", glbuf); fprintf(stderr, "Failed to compile GLSL shader!\n%s", glbuf);
PyErr_SetString(PyExc_ValueError, "Failed to compile shader"); PyErr_SetString(PyExc_ValueError, "Failed to compile shader");
goto end; goto end;
} }
if (!init_uniforms(which)) goto end;
end: end:
if (vertex_shader_id != 0) glDeleteShader(vertex_shader_id); if (vertex_shader_id != 0) glDeleteShader(vertex_shader_id);
if (fragment_shader_id != 0) glDeleteShader(fragment_shader_id); if (fragment_shader_id != 0) glDeleteShader(fragment_shader_id);
translate_error(); translate_error();
if (PyErr_Occurred()) { glDeleteProgram(program_ids[which]); program_ids[which] = 0; return NULL;} if (PyErr_Occurred()) { glDeleteProgram(programs[which].id); programs[which].id = 0; return NULL;}
return Py_BuildValue("I", program_ids[which]); return Py_BuildValue("I", programs[which].id);
Py_RETURN_NONE; Py_RETURN_NONE;
} }

View File

@@ -35,7 +35,6 @@ UBO = namedtuple('UBO', 'size index offsets buf_id')
BASE = os.path.dirname(os.path.abspath(__file__)) BASE = os.path.dirname(os.path.abspath(__file__))
@lru_cache()
def load_shaders(name): def load_shaders(name):
vert = open(os.path.join(BASE, '{}_vertex.glsl'.format(name))).read().replace('GLSL_VERSION', str(GLSL_VERSION), 1) vert = open(os.path.join(BASE, '{}_vertex.glsl'.format(name))).read().replace('GLSL_VERSION', str(GLSL_VERSION), 1)
frag = open(os.path.join(BASE, '{}_fragment.glsl'.format(name))).read().replace('GLSL_VERSION', str(GLSL_VERSION), 1) frag = open(os.path.join(BASE, '{}_fragment.glsl'.format(name))).read().replace('GLSL_VERSION', str(GLSL_VERSION), 1)