spirv_cross2/reflect/
names.rs

1use crate::error;
2use crate::handle::{Handle, Id};
3use crate::Compiler;
4
5use crate::string::CompilerStr;
6use spirv_cross_sys as sys;
7use spirv_cross_sys::{SpvId, TypeId, VariableId};
8
9impl<T> Compiler<T> {
10    /// Gets the identifier (`OpName`) of an ID.
11    pub fn name<I: Id>(&self, handle: Handle<I>) -> error::Result<Option<CompilerStr>> {
12        let id = self.yield_id(handle)?;
13        unsafe {
14            let name = sys::spvc_compiler_get_name(self.ptr.as_ptr(), SpvId(id.id()));
15            let name = CompilerStr::from_ptr(name, self.ctx.drop_guard());
16            if name.is_empty() {
17                Ok(None)
18            } else {
19                Ok(Some(name))
20            }
21        }
22    }
23
24    /// Overrides the identifier OpName of an ID.
25    ///
26    /// Identifiers beginning with underscores or identifiers which contain double underscores
27    /// are reserved by the implementation.
28    pub fn set_name<'str, I: Id>(
29        &mut self,
30        handle: Handle<I>,
31        string: impl Into<CompilerStr<'str>>,
32    ) -> error::Result<()> {
33        let id = self.yield_id(handle)?;
34        let string = string.into();
35
36        unsafe {
37            let cstring = string.into_cstring_ptr()?;
38
39            sys::spvc_compiler_set_name(self.ptr.as_ptr(), SpvId(id.id()), cstring.as_ptr());
40
41            // Sanity drop to show that the lifetime of the cstring is only up until
42            // we have returned. AFAIK, SPIRV-Cross will do a string copy.
43            // If it does not, then we'll have to keep this string alive for a while.
44            drop(cstring);
45            Ok(())
46        }
47    }
48
49    /// Given a struct type ID, obtain the identifier for member number "index".
50    pub fn member_name(
51        &self,
52        struct_type: Handle<TypeId>,
53        index: u32,
54    ) -> error::Result<Option<CompilerStr>> {
55        let struct_type_id = self.yield_id(struct_type)?;
56        let index = index;
57
58        unsafe {
59            let name = sys::spvc_compiler_get_member_name(self.ptr.as_ptr(), struct_type_id, index);
60            let name = CompilerStr::from_ptr(name, self.ctx.drop_guard());
61            if name.is_empty() {
62                Ok(None)
63            } else {
64                Ok(Some(name))
65            }
66        }
67    }
68
69    /// Sets the member identifier for the given struct member.
70    pub fn set_member_name<'str>(
71        &mut self,
72        struct_type: Handle<TypeId>,
73        index: u32,
74        string: impl Into<CompilerStr<'str>>,
75    ) -> error::Result<()> {
76        let struct_type_id = self.yield_id(struct_type)?;
77        let index = index;
78        let string = string.into();
79
80        unsafe {
81            let cstring = string.into_cstring_ptr()?;
82
83            sys::spvc_compiler_set_member_name(
84                self.ptr.as_ptr(),
85                struct_type_id,
86                index,
87                cstring.as_ptr(),
88            );
89
90            // Sanity drop to show that the lifetime of the cstring is only up until
91            // we have returned. AFAIK, SPIRV-Cross will do a string copy.
92            // If it does not, then we'll have to keep this string alive for a while.
93            drop(cstring);
94            Ok(())
95        }
96    }
97}
98
99impl<T> Compiler<T> {
100    /// When declaring buffer blocks in GLSL, the name declared in the GLSL source
101    /// might not be the same as the name declared in the SPIR-V module due to naming conflicts.
102    /// In this case, SPIRV-Cross needs to find a fallback-name, and it might only
103    /// be possible to know this name after compiling to GLSL.
104    ///
105    /// This is particularly important for HLSL input and UAVs which tends to reuse the same block type
106    /// for multiple distinct blocks. For these cases it is not possible to modify the name of the type itself
107    /// because it might be unique. Instead, you can use this interface to check after compilation which
108    /// name was actually used if your input SPIR-V tends to have this problem.
109    ///
110    /// For other names like remapped names for variables, etc., it's generally enough to query the name of the variables
111    /// after compiling, block names are an exception to this rule.
112    /// `handle` should be a handle to a variable with a Block-like type.
113    ///
114    /// This also applies to HLSL cbuffers.
115    pub fn remapped_declared_block_name(
116        &self,
117        handle: impl Into<Handle<VariableId>>,
118    ) -> error::Result<Option<CompilerStr<'static>>> {
119        let handle = handle.into();
120        let handle = self.yield_id(handle)?;
121        unsafe {
122            let name =
123                sys::spvc_compiler_get_remapped_declared_block_name(self.ptr.as_ptr(), handle);
124
125            // SAFETY: 'ctx is sound here
126            // https://github.com/KhronosGroup/SPIRV-Cross/blob/main/spirv_cross_c.cpp#L2773
127            let name = CompilerStr::from_ptr(name, self.ctx.drop_guard());
128            if name.is_empty() {
129                Ok(None)
130            } else {
131                Ok(Some(name))
132            }
133        }
134    }
135}