为了实现刚才的 常量获取,也就是从 builtin 变量里面获得 我们需要的 group_id
这是一个 Type::Vec<u32, 3>的类型
我们要完成一系列的操作 代码如下
pub fn init(&mut self) { //初始化 let ty_vec3 = self.get_type(Type::Vec(Rc::new(Type::U32), 3)); let ty_pt = self.builder.type_pointer(None, StorageClass::Input, ty_vec3); let wgid = self.builder.variable(ty_pt, None, StorageClass::Input, None); self.builder.decorate(wgid, Decoration::BuiltIn, vec![rspirv::dr::Operand::BuiltIn(spirv::BuiltIn::WorkgroupId)]); self.builtins.push(wgid); }
pub fn call_native(&mut self, name: &str, args: &Vec<Symbol>, ret: &Symbol)-> Result<()> { match name { "spirv_group"=> { let ty = Type::Vec(Rc::new(Type::U32), 3); let ty_vec3 = self.get_type(ty.clone()); let id = self.builder.load(ty_vec3, None, self.builtins[0], None, None)?; *self.get_mut(ret) = Var{id, ty, cls: StorageClass::Input}; } _=> {} } Ok(()) }
复制代码
我们首先申明了类型 Type::Vec(Rc::new(Type::U32), 3) 然后是这个类型的指针
然后 申明了一个变量 存放这个系统内建的 指针
decorate(wgid, Decoration::BuiltIn, vec![rspirv::dr::Operand::BuiltIn(spirv::BuiltIn::WorkgroupId)])
复制代码
这一行表示这个变量就是我们要的 WorkgroupId
以后我们用 标准库的 OnceCell 能力把这些非常量 但是运行时候进行一次初始化的 类型 跨模块的类型定义 初始化 LazyInit
编译之后我们发现下面的错误
没有生成 spirv 模块 这说明我们所有的 spirv 代码 除了类型和变量申明 装饰申明 以外 都需要处于一个 block 中
所以我们 用一个全局的 block_id 表示 没有就创建一个
block_id : Option<u32>
pub fn gen_block(&mut self, block: &[Statement], break_id: Option<u32>, continue_id: Option<u32>)-> Result<()> { for st in block.into_iter() { if self.block_id.is_none() { self.block_id = Some(self.builder.begin_block(None)?); }
复制代码
每条语句生成之前,先检查 有没有 block 没有就创建一个
函数的最后必须有一条 ret 不然会有没有闭合的 block
所有的 block 都是闭合的 也就是必须要 跳转或者返回 结束
self.frames.push(frame); self.gen_block(&code, None, None)?; if self.block_id.is_some() { self.builder.ret()?; }
复制代码
执行之后 得到下面的 结果
看起来像模像样了,但是必然是有问题的,我们用 spirv-val 检查一下
意思是所有在 main 里面用到的变量 必须在 interface 中申明
好吧 我们设置一个 interface 数组 ,用到的时候 push 进去,最后再导入一下 为了避免重复 我们使用 每次插入之前 找一下
BTW 这种小的数据结构 一次 find 非常快 就没必要用什么 HashSet BTreeSet 之类的了
pub fn add_interface(&mut self, id: u32) { if self.interfaces.iter().find(|i| *i == &id).is_none() { self.interfaces.push(id); } }
复制代码
我们再次执行一下
完美,有了一个没有错误的 spirv Shader 但是 遗憾的是 这个 shader 应该只是读取了 builtin 变量 然后啥都没干
评论