rustc_codegen_spirv/builder/
ext_inst.rs

1use super::Builder;
2use crate::builder_spirv::{SpirvValue, SpirvValueExt};
3use crate::custom_insts;
4use rspirv::dr::Operand;
5use rspirv::spirv::{GLOp, Word};
6
7const GLSL_STD_450: &str = "GLSL.std.450";
8
9/// Manager for OpExtInst/OpExtImport instructions
10#[derive(Default)]
11pub struct ExtInst {
12    /// See `crate::custom_insts` for more details on what this entails.
13    custom: Option<Word>,
14
15    glsl: Option<Word>,
16}
17
18impl ExtInst {
19    pub fn import_custom(&mut self, bx: &Builder<'_, '_>) -> Word {
20        if let Some(id) = self.custom {
21            id
22        } else {
23            let id = bx
24                .emit_global()
25                .ext_inst_import(custom_insts::CUSTOM_EXT_INST_SET.clone());
26            self.custom = Some(id);
27            id
28        }
29    }
30
31    pub fn import_glsl(&mut self, bx: &Builder<'_, '_>) -> Word {
32        if let Some(id) = self.glsl {
33            id
34        } else {
35            let id = bx.emit_global().ext_inst_import(GLSL_STD_450);
36            self.glsl = Some(id);
37            id
38        }
39    }
40}
41
42impl<'a, 'tcx> Builder<'a, 'tcx> {
43    pub fn custom_inst(
44        &self,
45        result_type: Word,
46        inst: custom_insts::CustomInst<Operand>,
47    ) -> SpirvValue {
48        let custom_ext_inst_set = self.ext_inst.borrow_mut().import_custom(self);
49        self.emit()
50            .ext_inst(
51                result_type,
52                None,
53                custom_ext_inst_set,
54                inst.op() as u32,
55                inst.into_operands(),
56            )
57            .unwrap()
58            .with_type(result_type)
59    }
60
61    pub fn gl_op(&self, op: GLOp, result_type: Word, args: impl AsRef<[SpirvValue]>) -> SpirvValue {
62        let args = args.as_ref();
63        let glsl = self.ext_inst.borrow_mut().import_glsl(self);
64        self.emit()
65            .ext_inst(
66                result_type,
67                None,
68                glsl,
69                op as u32,
70                args.iter().map(|a| Operand::IdRef(a.def(self))),
71            )
72            .unwrap()
73            .with_type(result_type)
74    }
75}