API for Uniform Block Objects

This commit is contained in:
Kovid Goyal
2017-08-30 09:20:35 +05:30
parent b1168f6c6c
commit d7b433f6b7
2 changed files with 98 additions and 9 deletions

View File

@@ -425,6 +425,16 @@ GetUniformLocation(PyObject UNUSED *self, PyObject *args) {
return PyLong_FromLong((long) ans); return PyLong_FromLong((long) ans);
} }
static PyObject*
GetUniformBlockIndex(PyObject UNUSED *self, PyObject *args) {
char *name;
unsigned int program_id;
if(!PyArg_ParseTuple(args, "Is", &program_id, &name)) return NULL;
GLuint ans = glGetUniformBlockIndex(program_id, name);
if (ans == GL_INVALID_INDEX) { PyErr_SetString(PyExc_ValueError, "No such uniform block is active"); return NULL; }
return PyLong_FromUnsignedLong((unsigned long) ans);
}
static PyObject* static PyObject*
GetAttribLocation(PyObject UNUSED *self, PyObject *args) { GetAttribLocation(PyObject UNUSED *self, PyObject *args) {
char *name; char *name;
@@ -435,6 +445,44 @@ GetAttribLocation(PyObject UNUSED *self, PyObject *args) {
return PyLong_FromLong((long) ans); return PyLong_FromLong((long) ans);
} }
static PyObject*
get_uniform_block_size(PyObject UNUSED *self, PyObject *args) {
unsigned int program_id, block_index;
if(!PyArg_ParseTuple(args, "II", &program_id, &block_index)) return NULL;
GLint ans;
glGetActiveUniformBlockiv(program_id, block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &ans);
CHECK_ERROR;
return PyLong_FromLong((long) ans);
}
static PyObject*
get_uniform_block_offsets(PyObject UNUSED *self, PyObject *args) {
unsigned int program_id;
PyObject *pynames;
if(!PyArg_ParseTuple(args, "IO", &program_id, &pynames)) return NULL;
if (!PySequence_Check(pynames)) { PyErr_SetString(PyExc_TypeError, "names must be a sequence"); return NULL; }
GLsizei count = PySequence_Size(pynames);
char **names = PyMem_Calloc(count, sizeof(char*));
GLuint *indices = PyMem_Calloc(count, sizeof(GLuint));
GLint *offsets = PyMem_Calloc(count, sizeof(GLint));
PyObject *ans = PyTuple_New(count);
if (ans == NULL || indices == NULL || names == NULL) return PyErr_NoMemory();
for (GLsizei i = 0; i < count; i++) {
PyObject *t = PySequence_ITEM(pynames, i);
names[i] = PyUnicode_AsUTF8(t);
Py_CLEAR(t);
}
glGetUniformIndices(program_id, count, (const GLchar * const*)names, indices);
glGetActiveUniformsiv(program_id, count, indices, GL_UNIFORM_OFFSET, offsets);
for (GLsizei i = 0; i < count; i++) PyTuple_SET_ITEM(ans, i, PyLong_FromLong(offsets[i]));
PyMem_Free(names); PyMem_Free(indices); PyMem_Free(offsets);
if (_enable_error_checking) {
SET_GL_ERR;
if (PyErr_Occurred()) { Py_CLEAR(ans); return NULL; }
}
return ans;
}
static PyObject* static PyObject*
UseProgram(PyObject UNUSED *self, PyObject *val) { UseProgram(PyObject UNUSED *self, PyObject *val) {
unsigned long program_id = PyLong_AsUnsignedLong(val); unsigned long program_id = PyLong_AsUnsignedLong(val);
@@ -620,6 +668,15 @@ BindBuffer(PyObject UNUSED *self, PyObject *args) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject*
BindBufferBase(PyObject UNUSED *self, PyObject *args) {
int tgt; unsigned int index, buf_id;
if (!PyArg_ParseTuple(args, "iII", &tgt, &index, &buf_id)) return NULL;
glBindBufferBase(tgt, index, buf_id);
CHECK_ERROR;
Py_RETURN_NONE;
}
static PyObject* static PyObject*
TexBuffer(PyObject UNUSED *self, PyObject *args) { TexBuffer(PyObject UNUSED *self, PyObject *args) {
int tgt, fmt; unsigned int buf_id; int tgt, fmt; unsigned int buf_id;
@@ -777,7 +834,7 @@ int add_module_gl_constants(PyObject *module) {
GLC(GL_R8); GLC(GL_RED); GLC(GL_UNSIGNED_BYTE); GLC(GL_R32UI); GLC(GL_RGB32UI); GLC(GL_RGBA); GLC(GL_R8); GLC(GL_RED); GLC(GL_UNSIGNED_BYTE); GLC(GL_R32UI); GLC(GL_RGB32UI); GLC(GL_RGBA);
GLC(GL_TEXTURE_BUFFER); GLC(GL_STATIC_DRAW); GLC(GL_STREAM_DRAW); GLC(GL_TEXTURE_BUFFER); GLC(GL_STATIC_DRAW); GLC(GL_STREAM_DRAW);
GLC(GL_SRC_ALPHA); GLC(GL_ONE_MINUS_SRC_ALPHA); GLC(GL_SRC_ALPHA); GLC(GL_ONE_MINUS_SRC_ALPHA);
GLC(GL_BLEND); GLC(GL_FLOAT); GLC(GL_UNSIGNED_INT); GLC(GL_ARRAY_BUFFER); GLC(GL_BLEND); GLC(GL_FLOAT); GLC(GL_UNSIGNED_INT); GLC(GL_ARRAY_BUFFER); GLC(GL_UNIFORM_BUFFER);
return 1; return 1;
} }
@@ -788,6 +845,8 @@ int add_module_gl_constants(PyObject *module) {
{"replace_or_create_buffer", (PyCFunction)replace_or_create_buffer, METH_VARARGS, NULL}, \ {"replace_or_create_buffer", (PyCFunction)replace_or_create_buffer, METH_VARARGS, NULL}, \
{"glewInit", (PyCFunction)_glewInit, METH_NOARGS, NULL}, \ {"glewInit", (PyCFunction)_glewInit, METH_NOARGS, NULL}, \
{"check_for_extensions", (PyCFunction)check_for_extensions, METH_NOARGS, NULL}, \ {"check_for_extensions", (PyCFunction)check_for_extensions, METH_NOARGS, NULL}, \
{"get_uniform_block_size", (PyCFunction)get_uniform_block_size, METH_VARARGS, NULL}, \
{"get_uniform_block_offsets", (PyCFunction)get_uniform_block_offsets, METH_VARARGS, NULL}, \
METH(Viewport, METH_VARARGS) \ METH(Viewport, METH_VARARGS) \
METH(CheckError, METH_NOARGS) \ METH(CheckError, METH_NOARGS) \
METH(ClearColor, METH_VARARGS) \ METH(ClearColor, METH_VARARGS) \
@@ -802,6 +861,7 @@ int add_module_gl_constants(PyObject *module) {
METH(Uniform4f, METH_VARARGS) \ METH(Uniform4f, METH_VARARGS) \
METH(Uniform3fv, METH_VARARGS) \ METH(Uniform3fv, METH_VARARGS) \
METH(GetUniformLocation, METH_VARARGS) \ METH(GetUniformLocation, METH_VARARGS) \
METH(GetUniformBlockIndex, METH_VARARGS) \
METH(GetAttribLocation, METH_VARARGS) \ METH(GetAttribLocation, METH_VARARGS) \
METH(ShaderSource, METH_VARARGS) \ METH(ShaderSource, METH_VARARGS) \
METH(CompileShader, METH_O) \ METH(CompileShader, METH_O) \
@@ -837,6 +897,7 @@ int add_module_gl_constants(PyObject *module) {
METH(TexParameteri, METH_VARARGS) \ METH(TexParameteri, METH_VARARGS) \
METH(PixelStorei, METH_VARARGS) \ METH(PixelStorei, METH_VARARGS) \
METH(BindBuffer, METH_VARARGS) \ METH(BindBuffer, METH_VARARGS) \
METH(BindBufferBase, METH_VARARGS) \
METH(TexBuffer, METH_VARARGS) \ METH(TexBuffer, METH_VARARGS) \
METH(TexStorage3D, METH_VARARGS) \ METH(TexStorage3D, METH_VARARGS) \
METH(CopyImageSubData, METH_VARARGS) \ METH(CopyImageSubData, METH_VARARGS) \

View File

@@ -4,6 +4,7 @@
import os import os
import sys import sys
from collections import namedtuple
from contextlib import contextmanager from contextlib import contextmanager
from ctypes import addressof, sizeof from ctypes import addressof, sizeof
from functools import lru_cache from functools import lru_cache
@@ -15,17 +16,19 @@ from .fast_data_types import (
GL_MAX_TEXTURE_SIZE, GL_NEAREST, GL_R8, GL_RED, GL_STREAM_DRAW, GL_MAX_TEXTURE_SIZE, GL_NEAREST, GL_R8, GL_RED, GL_STREAM_DRAW,
GL_TEXTURE0, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_TEXTURE0, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER,
GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_TRUE, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_TRUE,
GL_UNPACK_ALIGNMENT, GL_UNSIGNED_BYTE, GL_VERTEX_SHADER, ITALIC, SpriteMap, GL_UNIFORM_BUFFER, GL_UNPACK_ALIGNMENT, GL_UNSIGNED_BYTE, GL_VERTEX_SHADER,
copy_image_sub_data, glActiveTexture, glAttachShader, glBindBuffer, ITALIC, SpriteMap, copy_image_sub_data, get_uniform_block_offsets,
glBindTexture, glBindVertexArray, glCompileShader, glCopyImageSubData, get_uniform_block_size, glActiveTexture, glAttachShader, glBindBuffer,
glCreateProgram, glCreateShader, glDeleteBuffer, glDeleteProgram, glBindBufferBase, glBindTexture, glBindVertexArray, glCompileShader,
glDeleteShader, glDeleteTexture, glDeleteVertexArray, glCopyImageSubData, glCreateProgram, glCreateShader, glDeleteBuffer,
glDeleteProgram, glDeleteShader, glDeleteTexture, glDeleteVertexArray,
glEnableVertexAttribArray, glGenBuffers, glGenTextures, glGenVertexArrays, glEnableVertexAttribArray, glGenBuffers, glGenTextures, glGenVertexArrays,
glGetAttribLocation, glGetBufferSubData, glGetIntegerv, glGetAttribLocation, glGetBufferSubData, glGetIntegerv,
glGetProgramInfoLog, glGetProgramiv, glGetShaderInfoLog, glGetShaderiv, glGetProgramInfoLog, glGetProgramiv, glGetShaderInfoLog, glGetShaderiv,
glGetUniformLocation, glLinkProgram, glPixelStorei, glShaderSource, glGetUniformBlockIndex, glGetUniformLocation, glLinkProgram, glPixelStorei,
glTexParameteri, glTexStorage3D, glTexSubImage3D, glUseProgram, glShaderSource, glTexParameteri, glTexStorage3D, glTexSubImage3D,
glVertexAttribDivisor, glVertexAttribPointer, replace_or_create_buffer glUseProgram, glVertexAttribDivisor, glVertexAttribPointer,
replace_or_create_buffer
) )
from .fonts.render import render_cell from .fonts.render import render_cell
from .utils import safe_print from .utils import safe_print
@@ -34,6 +37,7 @@ GL_VERSION = (3, 3)
VERSION = GL_VERSION[0] * 100 + GL_VERSION[1] * 10 VERSION = GL_VERSION[0] * 100 + GL_VERSION[1] * 10
ITALIC_MASK = 1 << ITALIC ITALIC_MASK = 1 << ITALIC
BOLD_MASK = 1 << BOLD BOLD_MASK = 1 << BOLD
UBO = namedtuple('UBO', 'size index offsets buf_id')
BASE = os.path.dirname(os.path.abspath(__file__)) BASE = os.path.dirname(os.path.abspath(__file__))
@@ -327,6 +331,30 @@ class ShaderProgram: # {{{
' Return the id for the uniform variable `name` or -1 if not found. ' ' Return the id for the uniform variable `name` or -1 if not found. '
return glGetUniformLocation(self.program_id, name) return glGetUniformLocation(self.program_id, name)
@lru_cache(maxsize=2**6)
def uniform_block_index(self, name: str) -> int:
' Return the block index for the specified uniform block raises ValueError if not found. '
return glGetUniformBlockIndex(self.program_id, name)
def uniform_block_size(self, block_index):
return get_uniform_block_size(self.program_id, block_index)
def init_uniform_block(self, name, *variables):
idx = self.uniform_block_index(name)
size = self.uniform_block_size(idx)
offsets = get_uniform_block_offsets(self.program_id, variables)
offsets = dict(zip(variables, offsets))
buf_id = buffer_manager.create(GL_UNIFORM_BUFFER)
return UBO(size=size, index=idx, offsets=offsets, buf_id=buf_id)
def send_uniform_buffer_data(self, ubo, data, usage=GL_STREAM_DRAW):
buffer_manager.set_data(ubo.buf_id, data, usage=usage)
@contextmanager
def bound_uniform_buffer(self, ubo):
glBindBufferBase(GL_UNIFORM_BUFFER, ubo.index, ubo.buf_id)
yield
@lru_cache(maxsize=2**6) @lru_cache(maxsize=2**6)
def attribute_location(self, name: str) -> int: def attribute_location(self, name: str) -> int:
' Return the id for the attribute variable `name` or -1 if not found. ' ' Return the id for the attribute variable `name` or -1 if not found. '