Revert metadata row for sprites
Store in a separate VAO instead more performant as it uses less VRAM and allows shader lookup co-ords to be passed to fragment shaders without calculation in the fragment shader.
This commit is contained in:
parent
9e9ab3e6f9
commit
b2a4db2028
7 changed files with 21 additions and 29 deletions
|
|
@ -8,7 +8,7 @@ layout(std140) uniform CellRenderData {
|
|||
|
||||
uint default_fg, highlight_fg, highlight_bg, cursor_fg, cursor_bg, url_color, url_style, inverted;
|
||||
|
||||
uint xnum, ynum, sprites_xnum, sprites_ynum, cursor_fg_sprite_idx, cell_height;
|
||||
uint xnum, ynum, sprites_xnum, sprites_ynum, cursor_fg_sprite_idx;
|
||||
float cursor_x, cursor_y, cursor_w, cursor_opacity;
|
||||
|
||||
// must have unique entries with 0 being default_bg and unset being UINT32_MAX
|
||||
|
|
@ -109,9 +109,6 @@ vec3 to_sprite_pos(uvec2 pos, uint idx) {
|
|||
uvec3 c = to_sprite_coords(idx);
|
||||
vec2 s_xpos = vec2(c.x, float(c.x) + 1.0f) * (1.0f / float(sprites_xnum));
|
||||
vec2 s_ypos = vec2(c.y, float(c.y) + 1.0f) * (1.0f / float(sprites_ynum));
|
||||
uint texture_height_px = (cell_height + 1u) * sprites_ynum;
|
||||
float row_height = 1.0f / float(texture_height_px);
|
||||
s_ypos[1] -= row_height; // skip the metadata row
|
||||
return vec3(s_xpos[pos.x], s_ypos[pos.y], c.z);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1125,7 +1125,7 @@ def sprite_map_set_limits(w: int, h: int) -> None:
|
|||
|
||||
|
||||
def set_send_sprite_to_gpu(
|
||||
func: Optional[Callable[[int, int, int, bytes, bytes], None]]
|
||||
func: Optional[Callable[[int, int, int, bytes], None]]
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -130,23 +130,21 @@ python_send_to_gpu(FontGroup *fg, sprite_index idx, pixel *buf) {
|
|||
unsigned int x, y, z;
|
||||
sprite_index_to_pos(idx, fg->sprite_tracker.xnum, fg->sprite_tracker.ynum, &x, &y, &z);
|
||||
const size_t sprite_size = fg->fcm.cell_width * fg->fcm.cell_height;
|
||||
PyObject *ret = PyObject_CallFunction(python_send_to_gpu_impl, "IIIy#y#", x, y, z, buf, sprite_size * sizeof(buf[0]), buf + sprite_size, fg->fcm.cell_width * sizeof(buf[0]));
|
||||
PyObject *ret = PyObject_CallFunction(python_send_to_gpu_impl, "IIIy#", x, y, z, buf, sprite_size * sizeof(buf[0]));
|
||||
if (ret == NULL) PyErr_Print();
|
||||
else Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
current_send_sprite_to_gpu(FontGroup *fg, sprite_index idx, pixel *buf, sprite_index decorations_idx) {
|
||||
pixel *metadata = buf + fg->fcm.cell_width * fg->fcm.cell_height;
|
||||
metadata[0] = decorations_idx;
|
||||
memset(metadata + 1, 0, (fg->fcm.cell_width - 1) * sizeof(metadata[0]));
|
||||
(void)decorations_idx;
|
||||
if (python_send_to_gpu_impl) python_send_to_gpu(fg, idx, buf);
|
||||
else send_sprite_to_gpu((FONTS_DATA_HANDLE)fg, idx, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_canvas_can_fit(FontGroup *fg, unsigned cells, unsigned scale) {
|
||||
#define cs(cells, scale) (sizeof(fg->canvas.buf[0]) * 3u * cells * fg->fcm.cell_width * (fg->fcm.cell_height + 1) * scale * scale)
|
||||
#define cs(cells, scale) (sizeof(fg->canvas.buf[0]) * 3u * cells * fg->fcm.cell_width * fg->fcm.cell_height * scale * scale)
|
||||
size_t size_in_bytes = cs(cells, scale);
|
||||
if (size_in_bytes > fg->canvas.size_in_bytes) {
|
||||
free(fg->canvas.buf);
|
||||
|
|
@ -330,7 +328,7 @@ sprite_tracker_current_layout(FONTS_DATA_HANDLE data, unsigned int *x, unsigned
|
|||
static void
|
||||
sprite_tracker_set_layout(GPUSpriteTracker *sprite_tracker, unsigned int cell_width, unsigned int cell_height) {
|
||||
sprite_tracker->xnum = MIN(MAX(1u, max_texture_size / cell_width), (size_t)UINT16_MAX);
|
||||
sprite_tracker->max_y = MIN(MAX(1u, max_texture_size / (cell_height + 1)), (size_t)UINT16_MAX);
|
||||
sprite_tracker->max_y = MIN(MAX(1u, max_texture_size / cell_height), (size_t)UINT16_MAX);
|
||||
sprite_tracker->ynum = 1;
|
||||
sprite_tracker->x = 0; sprite_tracker->y = 0; sprite_tracker->z = 0;
|
||||
}
|
||||
|
|
@ -820,7 +818,7 @@ apply_scale_to_font_group(FontGroup *fg, RunFont *rf) {
|
|||
|
||||
static pixel*
|
||||
pointer_to_space_for_last_sprite(Canvas *canvas, FontCellMetrics fcm) {
|
||||
return canvas->buf + (canvas->size_in_bytes / sizeof(canvas->buf[0]) - fcm.cell_width * (fcm.cell_height + 1));
|
||||
return canvas->buf + (canvas->size_in_bytes / sizeof(canvas->buf[0]) - fcm.cell_width * fcm.cell_height);
|
||||
}
|
||||
|
||||
static pixel*
|
||||
|
|
|
|||
|
|
@ -1439,7 +1439,7 @@ def test_char(ch: str, sz: int = 48) -> None:
|
|||
from kitty.fast_data_types import concat_cells, set_send_sprite_to_gpu
|
||||
|
||||
from .render import display_bitmap, setup_for_testing
|
||||
with setup_for_testing('monospace', sz) as (_, _, width, height):
|
||||
with setup_for_testing('monospace', sz) as (_, width, height):
|
||||
buf = bytearray(width * height)
|
||||
try:
|
||||
render_box_char(ch, buf, width, height)
|
||||
|
|
@ -1460,7 +1460,7 @@ def test_drawing(sz: int = 48, family: str = 'monospace', start: int = 0x2500, n
|
|||
|
||||
from .render import display_bitmap, setup_for_testing
|
||||
|
||||
with setup_for_testing(family, sz) as (_, _, width, height):
|
||||
with setup_for_testing(family, sz) as (_, width, height):
|
||||
space = bytearray(width * height)
|
||||
|
||||
def join_cells(cells: Iterable[bytes]) -> bytes:
|
||||
|
|
|
|||
|
|
@ -236,16 +236,14 @@ def __init__(self, family: str = 'monospace', size: float = 11.0, dpi: float = 9
|
|||
self.family, self.size, self.dpi = family, size, dpi
|
||||
self.main_face_path = main_face_path
|
||||
|
||||
def __enter__(self) -> tuple[dict[tuple[int, int, int], bytes], dict[tuple[int, int, int], bytes], int, int]:
|
||||
def __enter__(self) -> tuple[dict[tuple[int, int, int], bytes], int, int]:
|
||||
global descriptor_overrides
|
||||
opts = defaults._replace(font_family=parse_font_spec(self.family), font_size=self.size)
|
||||
set_options(opts)
|
||||
sprites = {}
|
||||
sprite_metadata = {}
|
||||
|
||||
def send_to_gpu(x: int, y: int, z: int, data: bytes, metadata: bytes) -> None:
|
||||
def send_to_gpu(x: int, y: int, z: int, data: bytes) -> None:
|
||||
sprites[(x, y, z)] = data
|
||||
sprite_metadata[(x, y, z)] = metadata
|
||||
|
||||
sprite_map_set_limits(self.xnum, self.ynum)
|
||||
set_send_sprite_to_gpu(send_to_gpu)
|
||||
|
|
@ -256,7 +254,7 @@ def send_to_gpu(x: int, y: int, z: int, data: bytes, metadata: bytes) -> None:
|
|||
try:
|
||||
set_font_family(opts)
|
||||
cell_width, cell_height = create_test_font_group(self.size, self.dpi, self.dpi)
|
||||
return sprites, sprite_metadata, cell_width, cell_height
|
||||
return sprites, cell_width, cell_height
|
||||
except Exception:
|
||||
set_send_sprite_to_gpu(None)
|
||||
raise
|
||||
|
|
@ -268,7 +266,7 @@ def __exit__(self, *args: Any) -> None:
|
|||
|
||||
|
||||
def render_string(text: str, family: str = 'monospace', size: float = 11.0, dpi: float = 96.0) -> tuple[int, int, list[bytes]]:
|
||||
with setup_for_testing(family, size, dpi) as (sprites, sprite_metadata, cell_width, cell_height):
|
||||
with setup_for_testing(family, size, dpi) as (sprites, cell_width, cell_height):
|
||||
s = Screen(None, 1, len(text)*2)
|
||||
line = s.line(0)
|
||||
s.draw(text)
|
||||
|
|
@ -288,7 +286,7 @@ def render_string(text: str, family: str = 'monospace', size: float = 11.0, dpi:
|
|||
def shape_string(
|
||||
text: str = "abcd", family: str = 'monospace', size: float = 11.0, dpi: float = 96.0, path: Optional[str] = None
|
||||
) -> list[tuple[int, int, int, tuple[int, ...]]]:
|
||||
with setup_for_testing(family, size, dpi) as (sprites, sprite_metadata, cell_width, cell_height):
|
||||
with setup_for_testing(family, size, dpi) as (sprites, cell_width, cell_height):
|
||||
s = Screen(None, 1, len(text)*2)
|
||||
line = s.line(0)
|
||||
s.draw(text)
|
||||
|
|
|
|||
|
|
@ -118,12 +118,12 @@ realloc_sprite_texture(FONTS_DATA_HANDLE fg) {
|
|||
sprite_tracker_current_layout(fg, &xnum, &ynum, &z);
|
||||
znum = z + 1;
|
||||
SpriteMap *sprite_map = (SpriteMap*)fg->sprite_map;
|
||||
width = xnum * fg->fcm.cell_width; height = ynum * (fg->fcm.cell_height + 1);
|
||||
width = xnum * fg->fcm.cell_width; height = ynum * fg->fcm.cell_height;
|
||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_SRGB8_ALPHA8, width, height, znum);
|
||||
if (sprite_map->texture_id) {
|
||||
// need to re-alloc
|
||||
src_ynum = MAX(1, sprite_map->last_ynum);
|
||||
copy_image_sub_data(sprite_map->texture_id, tex, width, src_ynum * (fg->fcm.cell_height + 1), sprite_map->last_num_of_layers);
|
||||
copy_image_sub_data(sprite_map->texture_id, tex, width, src_ynum * fg->fcm.cell_height, sprite_map->last_num_of_layers);
|
||||
glDeleteTextures(1, &sprite_map->texture_id);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||
|
|
@ -154,8 +154,8 @@ send_sprite_to_gpu(FONTS_DATA_HANDLE fg, sprite_index idx, pixel *buf) {
|
|||
glBindTexture(GL_TEXTURE_2D_ARRAY, sprite_map->texture_id);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
sprite_index_to_pos(idx, xnum, ynum, &x, &y, &z);
|
||||
x *= fg->fcm.cell_width; y *= fg->fcm.cell_height + 1;
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, x, y, z, fg->fcm.cell_width, fg->fcm.cell_height + 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buf);
|
||||
x *= fg->fcm.cell_width; y *= fg->fcm.cell_height;
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, x, y, z, fg->fcm.cell_width, fg->fcm.cell_height, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -299,7 +299,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
|
|||
|
||||
GLuint default_fg, highlight_fg, highlight_bg, cursor_fg, cursor_bg, url_color, url_style, inverted;
|
||||
|
||||
GLuint xnum, ynum, sprites_xnum, sprites_ynum, cursor_fg_sprite_idx, cell_height;
|
||||
GLuint xnum, ynum, sprites_xnum, sprites_ynum, cursor_fg_sprite_idx;
|
||||
GLfloat cursor_x, cursor_y, cursor_w, cursor_opacity;
|
||||
GLuint bg_colors0, bg_colors1, bg_colors2, bg_colors3, bg_colors4, bg_colors5, bg_colors6, bg_colors7;
|
||||
GLfloat bg_opacities0, bg_opacities1, bg_opacities2, bg_opacities3, bg_opacities4, bg_opacities5, bg_opacities6, bg_opacities7;
|
||||
|
|
@ -389,7 +389,6 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
|
|||
unsigned int x, y, z;
|
||||
sprite_tracker_current_layout(os_window->fonts_data, &x, &y, &z);
|
||||
rd->sprites_xnum = x; rd->sprites_ynum = y;
|
||||
rd->cell_height = os_window->fonts_data->fcm.cell_height;
|
||||
rd->inverted = screen_invert_colors(screen) ? 1 : 0;
|
||||
|
||||
#undef COLOR
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ def setUp(self):
|
|||
self.addCleanup(self.rmtree_ignoring_errors, self.tdir)
|
||||
path = self.path_for_font(self.font_name) if self.font_name else ''
|
||||
tc = setup_for_testing(size=self.font_size, dpi=self.dpi, main_face_path=path)
|
||||
self.sprites, self.sprite_metadata, self.cell_width, self.cell_height = tc.__enter__()
|
||||
self.sprites, self.cell_width, self.cell_height = tc.__enter__()
|
||||
self.addCleanup(tc.__exit__)
|
||||
self.assertEqual([k[0] for k in self.sprites], list(range(11)))
|
||||
|
||||
|
|
@ -283,7 +283,7 @@ class Rendering(FontBaseTest):
|
|||
|
||||
def test_sprite_map(self):
|
||||
sprite_map_set_limits(10, 2)
|
||||
sprite_map_set_layout(5, 4) # 4 because of metadata row
|
||||
sprite_map_set_layout(5, 5)
|
||||
self.ae(test_sprite_position_for(0), (0, 0, 0))
|
||||
self.ae(test_sprite_position_for(1), (1, 0, 0))
|
||||
self.ae(test_sprite_position_for(2), (0, 1, 0))
|
||||
|
|
|
|||
Loading…
Reference in a new issue