写点什么

spirv 常量的管理

作者:Miracle
  • 2025-09-24
    四川
  • 本文字数:1897 字

    阅读完需:约 6 分钟

spirv 常量的管理

下面我们开始编译 Assign 指令了

处理 Assign 之前 必须首先处理 Const(0) 我们注意到 SpirvBuilder 是没有常量的 所以我们需要 增加一种类型 常量的类型 然后将 Zeta 中间代码 的常量表导入进来

我们的 Module 是这样的

pub struct Module {    pub consts: Vec<Dynamic>,    pub fns: Vec<(bool, FnDef, Vec<Statement>)>,}
复制代码

中间代码,使用 Symbol::Const(usize) 来访问具体的 常量值


我们使用下面的代码 导入常量 完成类型 ID 的获取 值的存储

        for val in module.consts {            let ty = self.get_type(val.get_type());            if val.is_f64() {                self.consts.push(Const{id: self.builder.constant_bit64(ty, val.as_f64().unwrap().to_bits()), val});            } else if val.is_f32() {                self.consts.push(Const{id: self.builder.constant_bit32(ty, val.as_f32().unwrap().to_bits()), val});            } else if val.is_int() {                if let Dynamic::I64(val) = val {                    self.consts.push(Const{id: self.builder.constant_bit64(ty, val as u64), val: Dynamic::from(val)});                } else {                    self.consts.push(Const{id: self.builder.constant_bit32(ty, val.as_i32().unwrap() as u32), val});                }            } else if val.is_uint() {                if let Dynamic::U64(val) = val {                    self.consts.push(Const{id: self.builder.constant_bit64(ty, val as u64), val: Dynamic::U64(val)});                } else {                    self.consts.push(Const{id: self.builder.constant_bit32(ty, val.as_u32().unwrap()), val});                }            } else {                self.consts.push(Const{ id: 0, val});            }        }
复制代码


然后 我们开始处理索引了 刚才 Assign 时候 左边是 Idx(Var(1), Const(0))

所以我们首先要取出 这个 Var(1) 索引 常量变量为 0 的值

代码是这样的

            Symbol::Idx(obj, idx)=> {                let obj = self.get(obj);                if let Type::Vec(ty, num) = obj.ty {                    if let Some(val) = self.get_const(idx) {                        let ty_id = self.get_type((*ty).clone());                        let id = self.builder.composite_extract(ty_id, None, obj.id, vec![val.val.as_u32().unwrap()]).unwrap();                        Var{id, ty: (*ty).clone(), cls: StorageClass::Function}                    } else {                        panic!("")                    }                } else { panic!("")}
复制代码

当我获取左边的时候 得到这样的结果

这个时候可以简单的把 id 16 赋值给 Var(2) 就行了

我们的代码是这样的

                Statement::Assign(left, right) => {                    if let Symbol::Idx(obj, idx) = right {                    } else {                        let left = self.get(left);                        *self.get_mut(right) = left;                    }                }
复制代码

执行的结果是这样

完美,现在就是另外半边的赋值了

我们看看右半边是什么

实现写入的代码是这样的

                    if let Symbol::Idx(obj, idx) = right {                        let obj = self.get(obj);                        if let Type::Array(ty, num) = obj.ty {                            let idx = self.get(idx);                            let ty_id = self.get_type((*ty).clone());                            let ty_pt = self.builder.type_pointer(None, obj.cls, ty_id);                            let pt = self.builder.access_chain(ty_pt, None, obj.id, vec![idx.id])?;//然后向 ID装入值                            let src = self.get(left);                            self.builder.store(pt, src.id, None, None)?;                        } else if let Type::Vec(ty, num) = obj.ty {                            if let Some(val) = self.get_const(idx) {                                let ty_id = self.get_type((*ty).clone());                            }                        }
复制代码


我们生成 spirv 汇编代码是这样的


完美,那么是时候让这个 shader 在我的显卡上运行起来了


用户头像

Miracle

关注

三十年资深码农 2019-10-25 加入

还未添加个人简介

评论

发布
暂无评论
spirv 常量的管理_Miracle_InfoQ写作社区