mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-11-04 22:55:51 +00:00
Generate glsl uniforms header from slang code
This commit is contained in:
parent
a7c226d957
commit
9469d268fd
6 changed files with 268 additions and 28 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
|
@ -11,6 +11,7 @@ kitty/rgb.py linguist-generated=true
|
|||
kitty/srgb_gamma.* linguist-generated=true
|
||||
kitty/gl-wrapper.* linguist-generated=true
|
||||
kitty/glfw-wrapper.* linguist-generated=true
|
||||
kitty/glsl-uniforms.h linguist-generated=true
|
||||
kitty/color-names.h linguist-generated=true
|
||||
kitty/parse-graphics-command.h linguist-generated=true
|
||||
kitty/parse-multicell-command.h linguist-generated=true
|
||||
|
|
|
|||
14
kitty/gl.c
14
kitty/gl.c
|
|
@ -299,6 +299,20 @@ get_uniform_information(int program, const char *name, GLenum information_type)
|
|||
return q;
|
||||
}
|
||||
|
||||
ArrayInformation
|
||||
get_uniform_array_information(int program, const char *name) {
|
||||
ArrayInformation ans;
|
||||
const char* names[] = {""};
|
||||
names[0] = name;
|
||||
GLuint pid = program_id(program);
|
||||
GLuint t;
|
||||
glGetUniformIndices(pid, 1, (void*)names, &t);
|
||||
glGetActiveUniformsiv(pid, 1, &t, GL_UNIFORM_ARRAY_STRIDE, &ans.stride);
|
||||
glGetActiveUniformsiv(pid, 1, &t, GL_UNIFORM_OFFSET, &ans.offset);
|
||||
glGetActiveUniformsiv(pid, 1, &t, GL_UNIFORM_SIZE, &ans.size);
|
||||
return ans;
|
||||
}
|
||||
|
||||
GLint
|
||||
attrib_location(int program, const char *name) {
|
||||
GLint ans = glGetAttribLocation(programs[program].id, name);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ typedef struct {
|
|||
} UniformBlock;
|
||||
|
||||
typedef struct {
|
||||
GLint offset, stride, size;
|
||||
GLint offset; // byte offset from start of UBO
|
||||
GLint stride; // element stride in bytes
|
||||
GLint size; // umber of elements
|
||||
} ArrayInformation;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -47,6 +49,7 @@ GLuint block_index(int program, const char *name);
|
|||
GLint block_size(int program, GLuint block_index);
|
||||
GLint get_uniform_location(int program, const char *name);
|
||||
GLint get_uniform_information(int program, const char *name, GLenum information_type);
|
||||
ArrayInformation get_uniform_array_information(int program, const char *name);
|
||||
GLint attrib_location(int program, const char *name);
|
||||
ssize_t create_vao(void);
|
||||
size_t add_buffer_to_vao(ssize_t vao_idx, GLenum usage);
|
||||
|
|
|
|||
164
kitty/glsl-uniforms.h
generated
Normal file
164
kitty/glsl-uniforms.h
generated
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// generated by slang.py DO NOT EDIT
|
||||
#include "gl.h"
|
||||
|
||||
|
||||
typedef struct BgimageUniforms {
|
||||
int background;
|
||||
int image;
|
||||
int positions;
|
||||
int sizes;
|
||||
int tiled;
|
||||
} BgimageUniforms;
|
||||
|
||||
static inline void get_uniform_locations_bgimage(int program, BgimageUniforms *ans) {
|
||||
ans->background = get_uniform_location(program, "background_0");
|
||||
ans->image = get_uniform_location(program, "image_0");
|
||||
ans->positions = get_uniform_location(program, "positions_0");
|
||||
ans->sizes = get_uniform_location(program, "sizes_0");
|
||||
ans->tiled = get_uniform_location(program, "tiled_0");
|
||||
}
|
||||
|
||||
typedef struct BlitUniforms {
|
||||
int dest_rect;
|
||||
int image;
|
||||
int src_rect;
|
||||
} BlitUniforms;
|
||||
|
||||
static inline void get_uniform_locations_blit(int program, BlitUniforms *ans) {
|
||||
ans->dest_rect = get_uniform_location(program, "dest_rect_0");
|
||||
ans->image = get_uniform_location(program, "image_0");
|
||||
ans->src_rect = get_uniform_location(program, "src_rect_0");
|
||||
}
|
||||
|
||||
typedef struct BorderUniforms {
|
||||
int background_opacity;
|
||||
// Vertex Input locations
|
||||
int rect;
|
||||
int rect_color;
|
||||
// Uniform block locations
|
||||
UniformBlock Colors;
|
||||
ArrayInformation colors;
|
||||
UniformBlock GammaLUT;
|
||||
ArrayInformation gamma_lut;
|
||||
} BorderUniforms;
|
||||
|
||||
static inline void get_uniform_locations_border(int program, BorderUniforms *ans) {
|
||||
ans->background_opacity = get_uniform_location(program, "background_opacity_0");
|
||||
ans->rect = 0;
|
||||
ans->rect_color = 1;
|
||||
ans->Colors.index = block_index(program, "block_Colors_0");
|
||||
ans->Colors.size = block_size(program, ans->Colors.index);
|
||||
ans->colors = get_uniform_array_information(program, "block_Colors_0.colors_0[0]");
|
||||
ans->GammaLUT.index = block_index(program, "block_GammaLUT_0");
|
||||
ans->GammaLUT.size = block_size(program, ans->GammaLUT.index);
|
||||
ans->gamma_lut = get_uniform_array_information(program, "block_GammaLUT_0.gamma_lut_0[0]");
|
||||
}
|
||||
|
||||
typedef struct CellUniforms {
|
||||
int draw_bg_bitfield;
|
||||
int sprites;
|
||||
int text_contrast;
|
||||
int text_gamma_adjustment;
|
||||
// Vertex Input locations
|
||||
int colors;
|
||||
int is_selected;
|
||||
int sprite_idx;
|
||||
// Uniform block locations
|
||||
UniformBlock CellRenderData;
|
||||
UniformBlock ColorTable;
|
||||
ArrayInformation color_table;
|
||||
UniformBlock GammaLUT;
|
||||
ArrayInformation gamma_lut;
|
||||
} CellUniforms;
|
||||
|
||||
static inline void get_uniform_locations_cell(int program, CellUniforms *ans) {
|
||||
ans->draw_bg_bitfield = get_uniform_location(program, "draw_bg_bitfield_0");
|
||||
ans->sprites = get_uniform_location(program, "sprites_0");
|
||||
ans->text_contrast = get_uniform_location(program, "text_contrast_0");
|
||||
ans->text_gamma_adjustment = get_uniform_location(program, "text_gamma_adjustment_0");
|
||||
ans->colors = 0;
|
||||
ans->is_selected = 2;
|
||||
ans->sprite_idx = 1;
|
||||
ans->CellRenderData.index = block_index(program, "block_CellRenderData_0");
|
||||
ans->CellRenderData.size = block_size(program, ans->CellRenderData.index);
|
||||
ans->ColorTable.index = block_index(program, "block_ColorTable_0");
|
||||
ans->ColorTable.size = block_size(program, ans->ColorTable.index);
|
||||
ans->color_table = get_uniform_array_information(program, "block_ColorTable_0.color_table_0[0]");
|
||||
ans->GammaLUT.index = block_index(program, "block_GammaLUT_0");
|
||||
ans->GammaLUT.size = block_size(program, ans->GammaLUT.index);
|
||||
ans->gamma_lut = get_uniform_array_information(program, "block_GammaLUT_0.gamma_lut_0[0]");
|
||||
}
|
||||
|
||||
typedef struct GraphicsUniforms {
|
||||
int amask_bg_premult;
|
||||
int amask_fg;
|
||||
int dest_rect;
|
||||
int extra_alpha;
|
||||
int image;
|
||||
int src_rect;
|
||||
} GraphicsUniforms;
|
||||
|
||||
static inline void get_uniform_locations_graphics(int program, GraphicsUniforms *ans) {
|
||||
ans->amask_bg_premult = get_uniform_location(program, "amask_bg_premult_0");
|
||||
ans->amask_fg = get_uniform_location(program, "amask_fg_0");
|
||||
ans->dest_rect = get_uniform_location(program, "dest_rect_0");
|
||||
ans->extra_alpha = get_uniform_location(program, "extra_alpha_0");
|
||||
ans->image = get_uniform_location(program, "image_0");
|
||||
ans->src_rect = get_uniform_location(program, "src_rect_0");
|
||||
}
|
||||
|
||||
typedef struct Rounded_rectUniforms {
|
||||
int background_color;
|
||||
int color;
|
||||
int params;
|
||||
int rect;
|
||||
} Rounded_rectUniforms;
|
||||
|
||||
static inline void get_uniform_locations_rounded_rect(int program, Rounded_rectUniforms *ans) {
|
||||
ans->background_color = get_uniform_location(program, "background_color_0");
|
||||
ans->color = get_uniform_location(program, "color_0");
|
||||
ans->params = get_uniform_location(program, "params_0");
|
||||
ans->rect = get_uniform_location(program, "rect_0");
|
||||
}
|
||||
|
||||
typedef struct ScreenshotUniforms {
|
||||
int dest_rect;
|
||||
int image;
|
||||
int src_rect;
|
||||
int src_size;
|
||||
} ScreenshotUniforms;
|
||||
|
||||
static inline void get_uniform_locations_screenshot(int program, ScreenshotUniforms *ans) {
|
||||
ans->dest_rect = get_uniform_location(program, "dest_rect_0");
|
||||
ans->image = get_uniform_location(program, "image_0");
|
||||
ans->src_rect = get_uniform_location(program, "src_rect_0");
|
||||
ans->src_size = get_uniform_location(program, "src_size_0");
|
||||
}
|
||||
|
||||
typedef struct TintUniforms {
|
||||
int edges;
|
||||
int tint_color;
|
||||
} TintUniforms;
|
||||
|
||||
static inline void get_uniform_locations_tint(int program, TintUniforms *ans) {
|
||||
ans->edges = get_uniform_location(program, "edges_0");
|
||||
ans->tint_color = get_uniform_location(program, "tint_color_0");
|
||||
}
|
||||
|
||||
typedef struct TrailUniforms {
|
||||
int cursor_edge_x;
|
||||
int cursor_edge_y;
|
||||
int trail_color;
|
||||
int trail_opacity;
|
||||
int x_coords;
|
||||
int y_coords;
|
||||
} TrailUniforms;
|
||||
|
||||
static inline void get_uniform_locations_trail(int program, TrailUniforms *ans) {
|
||||
ans->cursor_edge_x = get_uniform_location(program, "cursor_edge_x_0");
|
||||
ans->cursor_edge_y = get_uniform_location(program, "cursor_edge_y_0");
|
||||
ans->trail_color = get_uniform_location(program, "trail_color_0");
|
||||
ans->trail_opacity = get_uniform_location(program, "trail_opacity_0");
|
||||
ans->x_coords = get_uniform_location(program, "x_coords_0");
|
||||
ans->y_coords = get_uniform_location(program, "y_coords_0");
|
||||
}
|
||||
|
|
@ -15,8 +15,17 @@ import utils;
|
|||
#define TAB_BAR_EDGE_LEFT_COLOR 7
|
||||
#define TAB_BAR_EDGE_RIGHT_COLOR 8
|
||||
|
||||
uniform float gamma_lut[256];
|
||||
uniform uint colors[9];
|
||||
struct GammaLUT {
|
||||
uniform float gamma_lut[256];
|
||||
};
|
||||
ConstantBuffer<GammaLUT> glt;
|
||||
#define gamma_lut glt.gamma_lut
|
||||
|
||||
struct Colors {
|
||||
uniform uint colors[9];
|
||||
};
|
||||
ConstantBuffer<Colors> clrs;
|
||||
#define colors clrs.colors
|
||||
|
||||
// Vertex attributes matching GLSL input locations
|
||||
struct VertexInput {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# License: GPLv3 Copyright: 2026, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import glob
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
|
|
@ -430,6 +431,12 @@ class GLSLMetadata:
|
|||
self.input_locations = {}
|
||||
self.uniform_struct_names = {}
|
||||
|
||||
def merge(self, other: 'GLSLMetadata') -> None:
|
||||
self.loose_uniforms.update(other.loose_uniforms)
|
||||
self.uniform_structs.update(other.uniform_structs)
|
||||
self.uniform_struct_names.update(other.uniform_struct_names)
|
||||
self.input_locations.update(other.input_locations)
|
||||
|
||||
def asdict(self) -> dict[str, Any]:
|
||||
return {
|
||||
'loose_uniforms': self.loose_uniforms,
|
||||
|
|
@ -458,7 +465,9 @@ def fixup_opengl_code(glsl_code: str, path: str) -> tuple[str, GLSLMetadata]:
|
|||
uniform_name = name.rpartition('_')[0]
|
||||
if uniform_name in uniform_names:
|
||||
raise KeyError(f'The uniform name {uniform_name} is used with multiple suffixes in {path}')
|
||||
uniform_names[uniform_name] = name.partition('[')[0] # ]
|
||||
if '[' in name:
|
||||
name = name.partition('[')[0] + '[0]'
|
||||
uniform_names[uniform_name] = name
|
||||
return name
|
||||
src_lines = glsl_code.splitlines()
|
||||
|
||||
|
|
@ -540,32 +549,72 @@ def fixup_opengl_code(glsl_code: str, path: str) -> tuple[str, GLSLMetadata]:
|
|||
def fixup_opengl_files(paths: Iterable[str], metadata_map: dict[str, GLSLMetadata]) -> None:
|
||||
' Convert the GLSL output of slangc to something that will work with OpenGL 3.1 '
|
||||
for path in paths:
|
||||
with open(path, 'r+') as f:
|
||||
with open(path, 'r') as f:
|
||||
glsl_code = f.read()
|
||||
try:
|
||||
fixed, metadata = fixup_opengl_code(glsl_code, path)
|
||||
except Exception:
|
||||
os.unlink(path)
|
||||
raise
|
||||
parts = os.path.basename(path).split('.')
|
||||
if len(parts) == 3:
|
||||
name = parts[0]
|
||||
if name in metadata_map:
|
||||
metadata_map[name].loose_uniforms.update(metadata.loose_uniforms)
|
||||
metadata_map[name].uniform_structs.update(metadata.uniform_structs)
|
||||
else:
|
||||
metadata_map[name] = metadata
|
||||
f.seek(0)
|
||||
f.truncate()
|
||||
f.write(fixed)
|
||||
try:
|
||||
fixed, metadata = fixup_opengl_code(glsl_code, path)
|
||||
except Exception:
|
||||
os.unlink(path)
|
||||
raise
|
||||
parts = os.path.basename(path).split('.')
|
||||
write_if_changed(path, fixed)
|
||||
if len(parts) == 3:
|
||||
name = parts[0]
|
||||
if name in metadata_map:
|
||||
metadata_map[name].merge(metadata)
|
||||
else:
|
||||
metadata_map[name] = metadata
|
||||
|
||||
|
||||
def write_glsl_header(metadata_map: dict[str, GLSLMetadata]) -> None:
|
||||
from pprint import pprint
|
||||
for name, m in metadata_map.items():
|
||||
print(name)
|
||||
pprint(m.asdict())
|
||||
print()
|
||||
def write_if_changed(dest: str, text: str) -> None:
|
||||
with suppress(FileNotFoundError), open(dest) as f:
|
||||
existing = f.read()
|
||||
if existing == text:
|
||||
return
|
||||
with open(dest, 'w') as f:
|
||||
f.write(text)
|
||||
|
||||
|
||||
def write_glsl_header(metadata_map: dict[str, GLSLMetadata], dest: str = 'kitty/glsl-uniforms.h') -> None:
|
||||
lines = ['// generated by slang.py DO NOT EDIT', '#include "gl.h"', '']
|
||||
a = lines.append
|
||||
for name in sorted(metadata_map):
|
||||
m = metadata_map[name]
|
||||
struct_name = name.capitalize() + 'Uniforms'
|
||||
a('')
|
||||
a(f'typedef struct {struct_name} {{') # }}
|
||||
for u in sorted(m.loose_uniforms):
|
||||
a(f' int {u};')
|
||||
if m.input_locations:
|
||||
a(' // Vertex Input locations')
|
||||
for u in sorted(m.input_locations):
|
||||
a(f' int {u};')
|
||||
if m.uniform_structs:
|
||||
a(' // Uniform block locations')
|
||||
for u in sorted(m.uniform_structs):
|
||||
a(f' UniformBlock {u};')
|
||||
for v in sorted(m.uniform_structs[u]):
|
||||
vv = m.uniform_structs[u][v]
|
||||
if ']' in vv:
|
||||
a(f' ArrayInformation {v};')
|
||||
|
||||
a(f'}} {struct_name};')
|
||||
a('')
|
||||
a(f'static inline void get_uniform_locations_{name}(int program, {struct_name} *ans) {{') # }}
|
||||
for u in sorted(m.loose_uniforms):
|
||||
a(f' ans->{u} = get_uniform_location(program, "{m.loose_uniforms[u]}");')
|
||||
for u in sorted(m.input_locations):
|
||||
a(f' ans->{u} = {m.input_locations[u]};')
|
||||
for u in sorted(m.uniform_structs):
|
||||
a(f' ans->{u}.index = block_index(program, "{m.uniform_struct_names[u]}");')
|
||||
a(f' ans->{u}.size = block_size(program, ans->{u}.index);')
|
||||
block_name = m.uniform_struct_names[u]
|
||||
for v in sorted(m.uniform_structs[u]):
|
||||
vv = m.uniform_structs[u][v]
|
||||
if ']' in vv:
|
||||
a(f' ans->{v} = get_uniform_array_information(program, "{block_name}.{vv}");')
|
||||
a('}')
|
||||
write_if_changed(dest, '\n'.join(lines))
|
||||
# }}}
|
||||
|
||||
|
||||
|
|
@ -639,7 +688,7 @@ def compile_builtin_shaders(build_dir: str, dest_dir: str, parallel_run: Paralle
|
|||
# Now run all commands
|
||||
parallel_run(chain(spirv_commands, glsl_commands))
|
||||
metadata_map = {}
|
||||
fixup_opengl_files(built_glsl_files, metadata_map=metadata_map)
|
||||
fixup_opengl_files(glob.glob(os.path.join(dest_dir, '*.glsl')), metadata_map=metadata_map)
|
||||
if shutil.which('glslangValidator'):
|
||||
from kitty.shaders.validate_shaders import validation_command_for_file
|
||||
parallel_run((True, f'Validating |{os.path.basename(x)}| ...', validation_command_for_file(x)) for x in built_glsl_files)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue