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        &mut 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(
62        &mut self,
63        op: GLOp,
64        result_type: Word,
65        args: impl AsRef<[SpirvValue]>,
66    ) -> SpirvValue {
67        let args = args.as_ref();
68        let glsl = self.ext_inst.borrow_mut().import_glsl(self);
69        self.emit()
70            .ext_inst(
71                result_type,
72                None,
73                glsl,
74                op as u32,
75                args.iter().map(|a| Operand::IdRef(a.def(self))),
76            )
77            .unwrap()
78            .with_type(result_type)
79    }
80}