Rust的DirectX编译器封装库mach-dxcompiler-rs,实现高性能GPU着色器编译与跨平台图形开发
mach-dxcompiler-rs
该库允许将来自mach-dxcompiler的预构建二进制文件静态链接到Rust项目中。mach-dxcompiler存储库是微软DirectXShaderCompiler的一个分支,用Zig替换了CMake构建系统。这使得可以静态构建项目并将其链接到现有应用程序中——但核心逻辑仍然来自原始的DXC库。
使用方法
该crate的构建脚本需要curl.exe
和tar.exe
命令行工具,Windows 10和11应该默认安装了这些工具。
首先,将crate添加到项目中:cargo add mach-dxcompiler-rs
接下来,使用DxcCreateInstance
函数创建DXC COM对象。创建后,这些对象可以与常规的COM Windows API一起使用。
use windows::Win32::Graphics::Direct3D::Dxc;
let mut dxcompiler = std::ptr::null_mut();
mach_dxcompiler_rs::DxcCreateInstance(&Dxc::CLSID_DxcCompiler, &Dxc::IDxcCompiler3::IID, &mut dxcompiler);
// ... 使用着色器编译器 ...
Visual Studio 要求
对于MSVC用户,请确保你的Visual Studio版本至少为17.11或更高。这是为了与本项目使用的构建工具和库兼容。
完整示例
下面是一个完整的示例,展示如何使用mach-dxcompiler-rs编译HLSL着色器:
use windows::{
core::Interface,
Win32::Graphics::Direct3D::Dxc::{self, IDxcBlob, IDxcCompiler3, IDxcUtils},
};
fn compile_shader() -> windows::core::Result<()> {
// 创建编译器实例
let mut compiler: Option<IDxcCompiler3> = None;
unsafe {
mach_dxcompiler_rs::DxcCreateInstance(
&Dxc::CLSID_DxcCompiler,
&IDxcCompiler3::IID,
&mut compiler as *mut _ as *mut *mut _,
)
}?;
// 创建实用工具实例
let mut utils: Option<IDxcUtils> = None;
unsafe {
mach_dxcompiler_rs::DxcCreateInstance(
&Dxc::CLSID_DxcUtils,
&IDxcUtils::IID,
&mut utils as *mut _ as *mut *mut _,
)
}?;
let utils = utils.unwrap();
// HLSL源代码
let shader_source = r"
struct PSInput {
float4 position : SV_POSITION;
float4 color : COLOR;
};
float4 PSMain(PSInput input) : SV_TARGET {
return input.color;
}
";
// 将源代码转换为Blob
let mut source_blob: Option<IDxcBlob> = None;
unsafe {
utils.CreateBlobFromPinned(
shader_source.as_ptr() as *const _,
shader_source.len() as u32,
Dxc::DXC_CP_UTF8,
&mut source_blob,
)
}?;
let source_blob = source_blob.unwrap();
// 编译参数
let args = [
"-T".as_ptr() as *const i8, // 着色器目标
"ps_6_0".as_ptr() as *const i8,
"-E".as_ptr() as *const i8, // 入口点
"PSMain".as_ptr() as *const i8,
];
// 编译着色器
let mut result: Option<IDxcBlob> = None;
unsafe {
compiler.unwrap().Compile(
&source_blob,
std::ptr::null(),
std::ptr::null(),
args.as_ptr(),
args.len() as u32,
std::ptr::null_mut(),
0,
std::ptr::null_mut(),
&mut result,
)
}?;
if let Some(blob) = result {
// 获取编译后的二进制数据
let buffer = unsafe { std::slice::from_raw_parts(blob.GetBufferPointer() as *const u8, blob.GetBufferSize() as usize) };
println!("Shader compiled successfully! Size: {} bytes", buffer.len());
}
Ok(())
}
fn main() {
if let Err(e) = compile_shader() {
eprintln!("Failed to compile shader: {}", e);
}
}
这个示例展示了如何:
- 创建DXC编译器实例
- 创建实用工具实例
- 将HLSL源代码转换为Blob
- 设置编译参数
- 编译着色器并获取结果
注意:实际使用中你可能需要添加更多的错误处理和功能,如包含文件、定义宏等。
Rust的DirectX编译器封装库mach-dxcompiler-rs
介绍
mach-dxcompiler-rs是Rust语言对微软DirectX Shader Compiler(DXC)的封装库,它提供了高性能的GPU着色器编译能力,支持跨平台图形开发。这个库是Mach引擎生态系统的一部分,旨在为Rust开发者提供现代化的着色器编译工具链。
主要特性:
- 封装了微软的DXC编译器(原HLSL编译器)
- 支持HLSL和SPIR-V着色器编译
- 跨平台支持(Windows/Linux/macOS)
- 提供类型安全的Rust接口
- 支持着色器模型6.0+的高级特性
- 可集成到各种图形API后端(Vulkan、Direct3D 12等)
完整示例
下面是一个完整的使用mach-dxcompiler-rs编译HLSL着色器并集成到wgpu图形管线的示例:
use mach_dxcompiler::*;
use wgpu;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 初始化wgpu
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::VULKAN,
..Default::default()
});
let adapter = instance.request_adapter(&wgpu::RequestAdapterOptions::default()).await.unwrap();
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor::default(), None).await.unwrap();
// 2. 定义HLSL顶点和片段着色器
let vertex_shader = r#"
struct VertexInput {
float3 position : POSITION;
float3 normal : NORMAL;
};
struct VertexOutput {
float4 position : SV_POSITION;
float3 normal : NORMAL;
};
[shader("vertex")]
VertexOutput vs_main(VertexInput input) {
VertexOutput output;
output.position = float4(input.position, 1.0);
output.normal = input.normal;
return output;
}
"#;
let fragment_shader = r#"
struct FragmentInput {
float4 position : SV_POSITION;
float3 normal : NORMAL;
};
[shader("fragment")]
float4 ps_main(FragmentInput input) : SV_TARGET {
return float4(input.normal * 0.5 + 0.5, 1.0);
}
"#;
// 3. 使用mach-dxcompiler编译着色器
let dxcompiler = DxCompiler::new()?;
// 编译顶点着色器为SPIR-V
let vs_result = dxcompiler.compile(
vertex_shader,
&CompileOptions {
entry_point: "vs_main".to_string(),
target_profile: "vs_6_0".to_string(),
output_format: OutputFormat::SpirV,
optimization_level: OptimizationLevel::Level3,
..Default::default()
},
)?;
// 编译片段着色器为SPIR-V
let fs_result = dxcompiler.compile(
fragment_shader,
&CompileOptions {
entry_point: "ps_main".to_string(),
target_profile: "ps_6_0".to_string(),
output_format: OutputFormat::SpirV,
optimization_level: OptimizationLevel::Level3,
..Default::default()
},
)?;
// 4. 创建wgpu着色器模块
let vs_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("Vertex Shader"),
source: wgpu::ShaderSource::SpirV(vs_result.data.into()),
});
let fs_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("Fragment Shader"),
source: wgpu::ShaderSource::SpirV(fs_result.data.into()),
});
// 5. 创建渲染管线
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[],
push_constant_ranges: &[],
});
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &vs_module,
entry_point: "vs_main",
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
module: &fs_module,
entry_point: "ps_main",
targets: &[Some(wgpu::ColorTargetState {
format: wgpu::TextureFormat::Rgba8Unorm,
blend: Some(wgpu::BlendState::REPLACE),
write_mask: wgpu::ColorWrites::ALL,
})],
}),
primitive: wgpu::PrimitiveState::default(),
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
multiview: None,
});
println!("渲染管线创建成功!");
Ok(())
}
示例说明
-
初始化wgpu:创建wgpu实例和设备,准备图形渲染环境。
-
定义HLSL着色器:定义了顶点和片段着色器的HLSL源代码,包含基本的顶点变换和法线显示逻辑。
-
编译着色器:
- 使用
DxCompiler::new()
初始化DXC编译器 - 使用
compile()
方法将HLSL编译为SPIR-V - 为顶点和片段着色器分别设置编译选项(入口点、目标profile等)
- 使用
-
创建wgpu着色器模块:将编译后的SPIR-V字节码转换为wgpu可用的着色器模块。
-
创建渲染管线:使用编译好的着色器创建完整的渲染管线。
跨平台注意事项
- Windows:需要安装DirectX SDK或Windows SDK
- Linux/macOS:需要从源码构建DXC或使用预构建版本
- 运行时需要
dxcompiler.dll
/libdxcompiler.so
/libdxcompiler.dylib
在库路径中