Rust着色器编译库shaderc的使用,shaderc提供高性能GLSL/HLSL到SPIR-V的跨平台编译功能
Rust着色器编译库shaderc的使用,shaderc提供高性能GLSL/HLSL到SPIR-V的跨平台编译功能
shaderc-rs是Google shaderc库的Rust绑定,提供高性能的GLSL/HLSL到SPIR-V的跨平台编译功能。
使用
首先在Cargo.toml中添加依赖:
[dependencies]
shaderc = "0.9"
然后在crate根中添加:
extern crate shaderc;
示例
以下是编译着色器为SPIR-V二进制模块和汇编文本的示例:
use shaderc;
let source = "#version 310 es\n void EP() {}";
let mut compiler = shaderc::Compiler::new().unwrap();
let mut options = shaderc::CompileOptions::new().unwrap();
options.add_macro_definition("EP", Some("main"));
let binary_result = compiler.compile_into_spirv(
source, shaderc::ShaderKind::Vertex,
"shader.glsl", "main", Some(&options)).unwrap();
assert_eq!(Some(&0x07230203), binary_result.as_binary().first());
let text_result = compiler.compile_into_spirv_assembly(
source, shaderc::ShaderKind::Vertex,
"shader.glsl", "main", Some(&options)).unwrap();
assert!(text_result.as_text().starts_with("; SPIR-V\n"));
完整示例
以下是一个更完整的示例,展示如何使用shaderc编译GLSL着色器:
use shaderc;
fn main() {
// GLSL顶点着色器源代码
let vertex_shader_source = r#"
#version 450
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;
layout(location = 0) out vec3 fragColor;
void main() {
gl_Position = vec4(position, 1.0);
fragColor = color;
}
"#;
// 创建编译器实例
let compiler = shaderc::Compiler::new().expect("Failed to create shader compiler");
// 创建编译选项
let mut compile_options = shaderc::CompileOptions::new().unwrap();
compile_options.set_optimization_level(shaderc::OptimizationLevel::Performance);
// 编译顶点着色器为SPIR-V
let vertex_spirv = compiler.compile_into_spirv(
vertex_shader_source,
shaderc::ShaderKind::Vertex,
"vertex_shader.glsl", // 文件名,用于错误报告
"main", // 入口函数名
Some(&compile_options)
).expect("Failed to compile vertex shader");
// 输出编译结果
println!("Vertex shader SPIR-V size: {} bytes", vertex_spirv.as_binary().len());
println!("Vertex shader compilation warnings: {}", vertex_spirv.get_warning_messages());
// 也可以编译为SPIR-V汇编文本
let vertex_asm = compiler.compile_into_spirv_assembly(
vertex_shader_source,
shaderc::ShaderKind::Vertex,
"vertex_shader.glsl",
"main",
Some(&compile_options)
).expect("Failed to compile vertex shader to assembly");
println!("Vertex shader assembly:\n{}", vertex_asm.as_text());
}
设置
shaderc-rs需要C++ shaderc库,可以通过以下方式获取:
- 从Vulkan SDK中获取
- 通过Linux包管理器安装
- 从shaderc项目下载预编译版本
- 从源代码构建
构建脚本会按以下顺序尝试获取原生shaderc库:
- 如果指定了
--features build-from-source
,则从源代码构建 - 如果设置了
SHADERC_LIB_DIR
环境变量,则搜索该路径 - 如果设置了
VULKAN_SDK
环境变量,则搜索$VULKAN_SDK/lib
- 如果可用,使用
pkg-config
查找库路径 - 在Linux上,如果没有设置
SHADERC_LIB_DIR
,还会搜索系统库路径 - 如果以上步骤都找不到原生库,则从源代码构建
从源代码构建
要从源代码构建shaderc,需要以下工具:
- CMake
- Git
- Python 3
- C++11编译器
在Windows上还需要Ninja构建系统。
1 回复
Rust着色器编译库shaderc使用指南
shaderc
是Rust中一个高性能的着色器编译库,提供了将GLSL和HLSL编译为SPIR-V字节码的功能。它是Google的Shaderc项目的Rust绑定,支持跨平台使用。
主要特性
- 支持GLSL和HLSL到SPIR-V的编译
- 跨平台支持(Windows/Linux/macOS)
- 包含预编译的shaderc库,无需额外安装
- 支持着色器优化
- 提供详细的编译错误信息
安装
在Cargo.toml中添加依赖:
[dependencies]
shaderc = "0.7"
基本使用方法
1. 编译GLSL着色器
use shaderc;
fn compile_glsl_to_spirv() -> Result<Vec<u32>, shaderc::Error> {
let source = r#"
#version 450
layout(location = 0) in vec3 position;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = vec4(position, 1.0);
}
"#;
let mut compiler = shaderc::Compiler::new().unwrap();
let options = shaderc::CompileOptions::new().unwrap();
let binary_result = compiler.compile_into_spirv(
source,
shaderc::ShaderKind::Fragment,
"shader.glsl",
"main",
Some(&options),
)?;
Ok(binary_result.as_binary().to_vec())
}
2. 编译HLSL着色器
fn compile_hlsl_to_spirv() -> Result<Vec<u32>, shaderc::Error> {
let source = r#"
struct PSInput {
float4 position : SV_POSITION;
float4 color : COLOR;
};
float4 PSMain(PSInput input) : SV_TARGET {
return input.color;
}
"#;
let mut compiler = shaderc::Compiler::new().unwrap();
let mut options = shaderc::CompileOptions::new().unwrap();
options.set_source_language(shaderc::SourceLanguage::HLSL);
let binary_result = compiler.compile_into_spirv(
source,
shaderc::ShaderKind::Fragment,
"shader.hlsl",
"PSMain",
Some(&options),
)?;
Ok(binary_result.as_binary().to_vec())
}
高级功能
1. 设置优化级别
let mut options = shaderc::CompileOptions::new().unwrap();
options.set_optimization_level(shaderc::OptimizationLevel::Performance);
2. 添加宏定义
options.add_macro_definition("USE_TEXTURE", Some("1"));
3. 包含目录设置
options.set_include_callback(|requested_source, _, _, _| {
match requested_source {
"common.glsl" => Ok(shaderc::ResolvedInclude {
resolved_name: "common.glsl".to_string(),
content: "#define PI 3.14159265359".to_string(),
}),
_ => Err("File not found".to_string()),
}
});
4. 获取编译警告和错误
match compiler.compile_into_spirv(source, kind, filename, entry, Some(&options)) {
Ok(result) => {
if !result.get_num_warnings() == 0 {
println!("Compilation warnings: {}", result.get_warning_messages());
}
Ok(result.as_binary().to_vec())
}
Err(e) => {
eprintln!("Shader compilation failed: {}", e);
Err(e)
}
}
使用场景示例
Vulkan应用程序中的着色器加载
use vulkano::shader::ShaderModule;
fn load_shader(device: Arc<Device>) -> Arc<ShaderModule> {
let spirv = compile_glsl_to_spirv().unwrap();
unsafe {
ShaderModule::from_words(device, &spirv).unwrap()
}
}
完整示例代码
下面是一个完整的Vulkan应用程序中使用shaderc编译和加载着色器的示例:
use shaderc;
use vulkano::{
device::{Device, DeviceExtensions},
instance::{Instance, InstanceExtensions},
shader::ShaderModule,
Version,
};
use std::sync::Arc;
fn main() {
// 1. 初始化Vulkan实例
let instance = Instance::new(
None,
Version::V1_1,
&InstanceExtensions::none(),
None,
).unwrap();
// 2. 编译GLSL着色器
let vert_shader = compile_vertex_shader().unwrap();
let frag_shader = compile_fragment_shader().unwrap();
// 3. 创建逻辑设备
let physical = instance.enumerate_physical_devices().unwrap().next().unwrap();
let queue_family = physical.queue_families().next().unwrap();
let (device, mut queues) = Device::new(
physical,
physical.supported_features(),
&DeviceExtensions::none(),
[(queue_family, 0.5)].iter().cloned(),
).unwrap();
// 4. 加载着色器模块
let vert_shader_module = unsafe {
ShaderModule::from_words(device.clone(), &vert_shader).unwrap()
};
let frag_shader_module = unsafe {
ShaderModule::from_words(device.clone(), &frag_shader).unwrap()
};
println!("Shader modules loaded successfully!");
}
// 编译顶点着色器
fn compile_vertex_shader() -> Result<Vec<u32>, shaderc::Error> {
let source = r#"
#version 450
layout(location = 0) in vec2 position;
layout(location = 1) in vec3 color;
layout(location = 0) out vec3 v_color;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
v_color = color;
}
"#;
let mut compiler = shaderc::Compiler::new().unwrap();
let mut options = shaderc::CompileOptions::new().unwrap();
options.set_optimization_level(shaderc::OptimizationLevel::Performance);
compiler.compile_into_spirv(
source,
shaderc::ShaderKind::Vertex,
"vert.glsl",
"main",
Some(&options),
).map(|res| res.as_binary().to_vec())
}
// 编译片段着色器
fn compile_fragment_shader() -> Result<Vec<u32>, shaderc::Error> {
let source = r#"
#version 450
layout(location = 0) in vec3 v_color;
layout(location = 0) out vec4 f_color;
void main() {
f_color = vec4(v_color, 1.0);
}
"#;
let mut compiler = shaderc::Compiler::new().unwrap();
let mut options = shaderc::CompileOptions::new().unwrap();
options.set_optimization_level(shaderc::OptimizationLevel::Performance);
compiler.compile_into_spirv(
source,
shaderc::ShaderKind::Fragment,
"frag.glsl",
"main",
Some(&options),
).map(|res| res.as_binary().to_vec())
}
注意事项
shaderc
会链接预编译的库,在Windows上可能需要Visual C++运行时- 对于复杂的着色器项目,考虑使用
include_str!
宏来管理着色器代码文件 - 发布构建时可以考虑缓存编译后的SPIR-V字节码以提高加载速度
shaderc
为Rust开发者提供了强大的着色器编译能力,特别适合需要跨平台着色器支持的图形应用程序开发。