Dont send the color table to the GPU on every frame

This commit is contained in:
Kovid Goyal 2017-08-30 10:20:26 +05:30
parent d7b433f6b7
commit d12573a67d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 43 additions and 6 deletions

View File

@ -4,7 +4,9 @@ uniform vec4 steps; // xstart, ystart, dx, dy
uniform vec2 sprite_layout; // dx, dy
uniform ivec2 color_indices; // which color to use as fg and which as bg
uniform uvec4 default_colors; // The default colors
uniform uint color_table[256]; // The color table
uniform ColorTable {
uint color_table[256]; // The color table
};
in uvec3 sprite_coords;
in uvec3 colors;
in float is_selected;

View File

@ -16,8 +16,8 @@ from .constants import (
from .fast_data_types import (
CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE, DATA_CELL_SIZE, GL_BLEND,
GL_FLOAT, GL_LINE_LOOP, GL_TRIANGLE_FAN, GL_UNSIGNED_INT, glDisable,
glDrawArrays, glDrawArraysInstanced, glEnable, glUniform1i, glUniform1uiv,
glUniform2f, glUniform2i, glUniform2ui, glUniform4f, glUniform4ui
glDrawArrays, glDrawArraysInstanced, glEnable, glUniform1i, glUniform2f,
glUniform2i, glUniform2ui, glUniform4f, glUniform4ui
)
from .rgb import to_color
from .shaders import ShaderProgram, load_shaders
@ -35,6 +35,21 @@ class DynamicColor(Enum):
class CellProgram(ShaderProgram):
def __init__(self, *args):
ShaderProgram.__init__(self, *args)
self.color_table_buf = None
def send_color_table(self, color_profile):
if color_profile.ubo is None:
color_profile.ubo = self.init_uniform_block('ColorTable', 'color_table')
ubo = color_profile.ubo
if self.color_table_buf is None:
self.color_table_buf = (GLuint * (ubo.size // sizeof(GLuint)))()
offset = ubo.offsets['color_table'] // sizeof(GLuint)
stride = ubo.size // (256 * sizeof(GLuint))
color_profile.copy_color_table(addressof(self.color_table_buf), offset, stride)
self.send_uniform_buffer_data(ubo, self.color_table_buf)
def create_sprite_map(self):
with self.array_object_creator() as add_attribute:
stride = DATA_CELL_SIZE * sizeof(GLuint)
@ -124,15 +139,17 @@ def calculate_gl_geometry(window_geometry, viewport_width, viewport_height, cell
def render_cells(vao_id, sg, cell_program, sprites, color_profile, invert_colors=False):
if color_profile.dirty:
cell_program.send_color_table(color_profile)
color_profile.dirty = False
ul = cell_program.uniform_location
glUniform2ui(ul('dimensions'), sg.xnum, sg.ynum)
glUniform4ui(ul('default_colors'), color_profile.default_fg, color_profile.default_bg, color_profile.highlight_fg, color_profile.highlight_bg)
glUniform1uiv(ul('color_table'), 256, color_profile.color_table_address())
glUniform2i(ul('color_indices'), 1 if invert_colors else 0, 0 if invert_colors else 1)
glUniform4f(ul('steps'), sg.xstart, sg.ystart, sg.dx, sg.dy)
glUniform1i(ul('sprites'), sprites.sampler_num)
glUniform2f(ul('sprite_layout'), *(sprites.layout))
with cell_program.bound_vertex_array(vao_id):
with cell_program.bound_vertex_array(vao_id), cell_program.bound_uniform_buffer(color_profile.ubo):
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, sg.xnum * sg.ynum)

View File

@ -61,6 +61,7 @@ new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) {
memcpy(self->color_table, FG_BG_256, sizeof(FG_BG_256));
memcpy(self->orig_color_table, FG_BG_256, sizeof(FG_BG_256));
self->dirty = Py_True; Py_INCREF(Py_True);
self->ubo = Py_None; Py_INCREF(Py_None);
}
return (PyObject*) self;
}
@ -68,6 +69,7 @@ new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) {
static void
dealloc(ColorProfile* self) {
Py_DECREF(self->dirty);
Py_DECREF(self->ubo);
Py_TYPE(self)->tp_free((PyObject*)self);
}
@ -162,6 +164,20 @@ set_configured_colors(ColorProfile *self, PyObject *args) {
Py_RETURN_NONE;
}
static PyObject*
copy_color_table(ColorProfile *self, PyObject *args) {
#define copy_color_table_doc "copy_color_table(address, offset, stride) -> copy the color table into the memory at address, using the specified offset and stride."
unsigned int offset, stride, i;
PyObject *ptr;
if (!PyArg_ParseTuple(args, "OII", &ptr, &offset, &stride)) return NULL;
color_type *buf = (color_type*)PyLong_AsVoidPtr(ptr);
stride = MAX(1, stride);
for (i = 0, buf = buf + offset; i < sizeof(self->color_table)/sizeof(self->color_table[0]); i++, buf += stride) {
*buf = self->color_table[i];
}
Py_RETURN_NONE;
}
static PyObject*
color_table_address(ColorProfile *self) {
#define color_table_address_doc "Pointer address to start of color table"
@ -193,6 +209,7 @@ static PyGetSetDef getsetters[] = {
static PyMemberDef members[] = {
{"dirty", T_OBJECT_EX, offsetof(ColorProfile, dirty), 0, "dirty"},
{"ubo", T_OBJECT_EX, offsetof(ColorProfile, ubo), 0, "ubo"},
{NULL}
};
@ -204,6 +221,7 @@ static PyMethodDef methods[] = {
METHOD(reset_color, METH_O)
METHOD(set_color, METH_VARARGS)
METHOD(set_configured_colors, METH_VARARGS)
METHOD(copy_color_table, METH_VARARGS)
{NULL} /* Sentinel */
};

View File

@ -184,7 +184,7 @@ typedef struct {
typedef struct {
PyObject_HEAD
PyObject *dirty;
PyObject *dirty, *ubo;
uint32_t color_table[256];
uint32_t orig_color_table[256];
DynamicColor configured, overridden;