librashader_reflect/back/
spirv.rs

1use crate::back::targets::SPIRV;
2use crate::back::{
3    CompileReflectShader, CompileShader, CompilerBackend, FromCompilation, ShaderCompilerOutput,
4};
5use crate::error::{ShaderCompileError, ShaderReflectError};
6use crate::front::SpirvCompilation;
7use crate::reflect::cross::glsl::GlslReflect;
8use crate::reflect::cross::SpirvCross;
9use crate::reflect::naga::{Naga, NagaLoweringOptions, NagaReflect};
10use crate::reflect::semantics::ShaderSemantics;
11use crate::reflect::{ReflectShader, ShaderReflection};
12use naga::Module;
13
14pub(crate) struct WriteSpirV {
15    // rely on GLSL to provide out reflection but we don't actually need the AST.
16    pub(crate) reflect: GlslReflect,
17    pub(crate) vertex: Vec<u32>,
18    pub(crate) fragment: Vec<u32>,
19}
20
21#[cfg(not(feature = "stable"))]
22impl FromCompilation<SpirvCompilation, SpirvCross> for SPIRV {
23    type Target = SPIRV;
24    type Options = Option<()>;
25    type Context = ();
26    type Output = impl CompileReflectShader<Self::Target, SpirvCompilation, SpirvCross>;
27
28    fn from_compilation(
29        compile: SpirvCompilation,
30    ) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
31        let reflect = GlslReflect::try_from(&compile)?;
32        let vertex = compile.vertex;
33        let fragment = compile.fragment;
34        Ok(CompilerBackend {
35            backend: WriteSpirV {
36                reflect,
37                vertex,
38                fragment,
39            },
40        })
41    }
42}
43
44#[cfg(feature = "stable")]
45impl FromCompilation<SpirvCompilation, SpirvCross> for SPIRV {
46    type Target = SPIRV;
47    type Options = Option<()>;
48    type Context = ();
49    type Output = Box<dyn CompileReflectShader<Self::Target, SpirvCompilation, SpirvCross> + Send>;
50
51    fn from_compilation(
52        compile: SpirvCompilation,
53    ) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
54        let reflect = GlslReflect::try_from(&compile)?;
55        let vertex = compile.vertex;
56        let fragment = compile.fragment;
57        Ok(CompilerBackend {
58            backend: Box::new(WriteSpirV {
59                reflect,
60                vertex,
61                fragment,
62            }),
63        })
64    }
65}
66
67impl ReflectShader for WriteSpirV {
68    fn reflect(
69        &mut self,
70        pass_number: usize,
71        semantics: &ShaderSemantics,
72    ) -> Result<ShaderReflection, ShaderReflectError> {
73        self.reflect.reflect(pass_number, semantics)
74    }
75
76    fn validate(&mut self) -> Result<(), ShaderReflectError> {
77        self.reflect.validate()
78    }
79}
80
81impl CompileShader<SPIRV> for WriteSpirV {
82    type Options = Option<()>;
83    type Context = ();
84
85    fn compile(
86        self,
87        _options: Self::Options,
88    ) -> Result<ShaderCompilerOutput<Vec<u32>, Self::Context>, ShaderCompileError> {
89        Ok(ShaderCompilerOutput {
90            vertex: self.vertex,
91            fragment: self.fragment,
92            context: (),
93        })
94    }
95
96    fn compile_boxed(
97        self: Box<Self>,
98        _options: Self::Options,
99    ) -> Result<ShaderCompilerOutput<Vec<u32>, Self::Context>, ShaderCompileError> {
100        Ok(ShaderCompilerOutput {
101            vertex: self.vertex,
102            fragment: self.fragment,
103            context: (),
104        })
105    }
106}
107
108/// The context for a SPIRV compilation via Naga
109pub struct NagaSpirvContext {
110    pub fragment: Module,
111    pub vertex: Module,
112}
113
114#[cfg(not(feature = "stable"))]
115impl FromCompilation<SpirvCompilation, Naga> for SPIRV {
116    type Target = SPIRV;
117    type Options = NagaSpirvOptions;
118    type Context = NagaSpirvContext;
119    type Output = impl CompileReflectShader<Self::Target, SpirvCompilation, Naga>;
120
121    fn from_compilation(
122        compile: SpirvCompilation,
123    ) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
124        Ok(CompilerBackend {
125            backend: NagaReflect::try_from(&compile)?,
126        })
127    }
128}
129
130#[cfg(feature = "stable")]
131impl FromCompilation<SpirvCompilation, Naga> for SPIRV {
132    type Target = SPIRV;
133    type Options = NagaSpirvOptions;
134    type Context = NagaSpirvContext;
135    type Output = Box<dyn CompileReflectShader<Self::Target, SpirvCompilation, Naga> + Send>;
136
137    fn from_compilation(
138        compile: SpirvCompilation,
139    ) -> Result<CompilerBackend<Self::Output>, ShaderReflectError> {
140        Ok(CompilerBackend {
141            backend: Box::new(NagaReflect::try_from(&compile)?),
142        })
143    }
144}
145
146pub struct NagaSpirvOptions {
147    pub lowering: NagaLoweringOptions,
148    pub version: (u8, u8),
149}