- Removed legacy push constant structures and functions for better clarity and maintainability. - Introduced new `text_push_constants_t` structure for text rendering with optimized layout. - Implemented dual stage push constant analysis to support separate layouts for vertex and fragment shaders. - Added functions to generate push constant structures and fill functions based on shader reflection. - Enhanced static checks for push constant layouts to ensure compatibility and correctness. - Updated templates to accommodate new dual stage push constant generation. - Added support detection for procedural vertex shaders based on push constant layout.
GLSL Shader Compilation Tools
GLSL着色器编译和C++绑定生成工具集。
📁 模块结构
tools/
├── __init__.py # 包初始化,导出公共接口
├── main.py # 主入口文件 (~200行)
├── constants.py # SPIR-V常量定义 (~80行)
├── types.py # 数据类型定义 (~210行)
├── spirv_parser.py # SPIR-V二进制解析 (~430行)
├── type_mapping.py # 类型映射和布局计算 (~220行)
├── code_generator.py # C++代码生成 (~250行)
├── compiler.py # ShaderCompiler类 (~130行)
└── utils.py # 工具函数 (~150行)
总计: 原来的1520行代码被拆分为8个模块,每个模块80-430行。
🔧 模块说明
1. constants.py
定义所有SPIR-V规范相关的常量:
- SPIR-V魔数和操作码
- 装饰值(Decoration)
- 执行模型和存储类
- 着色器文件扩展名映射
2. types.py
定义所有数据类和枚举:
ToolError: 错误类型StorageClass,BaseType: 枚举类型TypeInfo系列: SPIR-V类型信息(Scalar, Vector, Matrix, Array, Struct, Pointer)SPIRVReflection: 完整的反射信息ShaderMetadata: 着色器元数据CompilationResult: 编译结果
3. spirv_parser.py
SPIR-V二进制解析功能:
parse_spirv_words(): 解析二进制为字数组parse_spirv_instructions(): 解析指令流parse_spirv_type_system(): 提取类型系统resolve_all_types(): 解析类型引用extract_buffers(): 提取buffer信息
4. type_mapping.py
SPIR-V到C++类型映射:
spirv_type_to_cpp(): 类型转换calculate_std430_alignment(): 计算对齐calculate_std430_size(): 计算大小align_up(): 对齐辅助函数
5. code_generator.py
C++代码生成:
generate_buffer_structures(): 生成结构体定义spirv_to_cpp_array(): 生成SPIR-V数组generate_header(): 生成完整头文件vk_descriptor_type_to_cpp(): Vulkan类型转换vk_shader_stage_to_cpp(): 着色器阶段转换
6. compiler.py
着色器编译器:
ShaderCompiler: 主编译器类compile_shader(): 编译单个着色器_find_glslc(): 查找glslc编译器_build_glslc_command(): 构建编译命令
7. utils.py
工具函数:
discover_shaders(): 发现着色器文件group_shader_files(): 分组着色器load_shader_metadata(): 加载元数据read_directory_list(): 读取目录列表
8. main.py
主入口:
parse_args(): 参数解析process_shader_group(): 处理着色器组main(): 主函数
📊 依赖关系
Level 0: constants.py (无依赖)
↓
Level 1: types.py (依赖constants)
↓
Level 2: spirv_parser.py, type_mapping.py, utils.py (依赖types)
↓
Level 3: code_generator.py (依赖type_mapping)
compiler.py (依赖spirv_parser)
↓
Level 4: main.py (依赖所有模块)
🚀 使用方法
命令行使用
# 基本用法
python -m tools.main -l path/to/shader_list.txt
# 启用详细日志
python -m tools.main -l shader_list.txt -d
# 指定输出目录
python -m tools.main -l shader_list.txt -o build/shaders
# 干运行(仅发现文件,不编译)
python -m tools.main -l shader_list.txt --dry-run
Python API使用
from tools import ShaderCompiler, discover_shaders, group_shader_files
from pathlib import Path
# 发现着色器
shader_dirs = [Path("src/render/shaders")]
shaders = discover_shaders(shader_dirs)
# 编译着色器
compiler = ShaderCompiler(verbose=True)
metadata = load_shader_metadata(shaders[0])
result = compiler.compile_shader(shaders[0], metadata, "comp")
print(f"Entry point: {result.entry_point}")
print(f"Bindings: {result.bindings}")
✨ 新结构的优势
- 模块化: 每个模块职责单一,易于理解和维护
- 可测试性: 独立模块便于单元测试
- 可复用性: 各模块可以独立导入使用
- 可扩展性: 添加新功能时只需修改相关模块
- 减少复杂度: 从单个1520行文件拆分为8个小文件
🔄 从旧版本迁移
旧版本的 tools/main.py 已被重构,但功能完全保持兼容:
# 旧用法(仍然有效)
python tools/main.py -l shader_list.txt
# 新用法(推荐)
python -m tools.main -l shader_list.txt
📝 开发指南
添加新的SPIR-V操作码
在 constants.py 中添加:
OP_NEW_OPCODE = 123
添加新的类型映射
在 type_mapping.py 中扩展 spirv_type_to_cpp() 函数。
自定义代码生成
修改 code_generator.py 中的生成函数。
🎯 Buffer 数据设置便捷功能
工具会自动为着色器中定义的 buffer 生成便捷的数据管理接口。
功能概览
生成三层抽象接口:
- 基础辅助函数 -
create_*_buffer(),upload_*(),download_*() - 类型安全包装器 -
typed_buffer<T>和类型别名 - 自动化管理器 -
*_buffer_manager类
配置选项
在 ShaderMetadata 中配置:
metadata = ShaderMetadata(
# ... 其他字段 ...
generate_buffer_helpers=True, # 生成基础辅助函数
generate_typed_buffers=True, # 生成类型安全包装器
generate_buffer_manager=True, # 生成管理器类
)
使用示例
// 方式 1: 基础辅助函数
auto buffer = create_positions_buffer(rm, 1000).value();
upload_positions(device, buffer, data);
// 方式 2: 类型安全包装器
auto typed_buf = create_positions_typed(device, rm, 1000).value();
typed_buf.upload(data);
typed_buf.download(output);
// 方式 3: 自动化管理器(推荐)
auto mgr = particle_buffer_manager::create(device, rm, 1000).value();
mgr.initialize(positions, velocities);
mgr.bind_to_descriptor_set(pipeline, descriptor_set);
详细文档
🐛 故障排除
找不到glslc编译器
确保已安装Vulkan SDK并且glslc在PATH中。
导入错误
确保从项目根目录运行,并且tools目录包含 __init__.py。
编译失败
使用 -d 标志启用详细日志查看完整错误信息。
🎨 模板系统
从v2.0开始,代码生成器使用Jinja2模板引擎而非字符串拼接。
优势
- ✅ 可维护性:模板和逻辑分离,C++代码结构清晰
- ✅ 可扩展性:添加新功能只需创建模板
- ✅ 可读性:支持语法高亮,易于理解
- ✅ 性能:模板编译缓存,性能优异
模板目录结构
tools/templates/
├── base/ # 基础模板(头文件、结构体)
├── buffer_helpers/ # Buffer辅助函数
├── typed_buffer/ # 类型安全buffer
└── buffer_manager/ # Buffer管理器
详细文档
自定义模板
from tools.template_loader import get_renderer
renderer = get_renderer()
result = renderer.render('my_template.jinja2', {
'my_var': 'value',
})
测试
python tools/test_template_refactor.py