Skip to main content

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
57        unsafe {
58            let name = sys::spvc_compiler_get_member_name(self.ptr.as_ptr(), struct_type_id, index);
59            let name = CompilerStr::from_ptr(name, self.ctx.drop_guard());
60            if name.is_empty() {
61                Ok(None)
62            } else {
63                Ok(Some(name))
64            }
65        }
66    }
67
68    /// Sets the member identifier for the given struct member.
69    pub fn set_member_name<'str>(
70        &mut self,
71        struct_type: Handle<TypeId>,
72        index: u32,
73        string: impl Into<CompilerStr<'str>>,
74    ) -> error::Result<()> {
75        let struct_type_id = self.yield_id(struct_type)?;
76        let string = string.into();
77
78        unsafe {
79            let cstring = string.into_cstring_ptr()?;
80
81            sys::spvc_compiler_set_member_name(
82                self.ptr.as_ptr(),
83                struct_type_id,
84                index,
85                cstring.as_ptr(),
86            );
87
88            // Sanity drop to show that the lifetime of the cstring is only up until
89            // we have returned. AFAIK, SPIRV-Cross will do a string copy.
90            // If it does not, then we'll have to keep this string alive for a while.
91            drop(cstring);
92            Ok(())
93        }
94    }
95}
96
97impl<T> Compiler<T> {
98    /// When declaring buffer blocks in GLSL, the name declared in the GLSL source
99    /// might not be the same as the name declared in the SPIR-V module due to naming conflicts.
100    /// In this case, SPIRV-Cross needs to find a fallback-name, and it might only
101    /// be possible to know this name after compiling to GLSL.
102    ///
103    /// This is particularly important for HLSL input and UAVs which tends to reuse the same block type
104    /// for multiple distinct blocks. For these cases it is not possible to modify the name of the type itself
105    /// because it might be unique. Instead, you can use this interface to check after compilation which
106    /// name was actually used if your input SPIR-V tends to have this problem.
107    ///
108    /// For other names like remapped names for variables, etc., it's generally enough to query the name of the variables
109    /// after compiling, block names are an exception to this rule.
110    /// `handle` should be a handle to a variable with a Block-like type.
111    ///
112    /// This also applies to HLSL cbuffers.
113    pub fn remapped_declared_block_name(
114        &self,
115        handle: impl Into<Handle<VariableId>>,
116    ) -> error::Result<Option<CompilerStr<'static>>> {
117        let handle = handle.into();
118        let handle = self.yield_id(handle)?;
119        unsafe {
120            let name =
121                sys::spvc_compiler_get_remapped_declared_block_name(self.ptr.as_ptr(), handle);
122
123            // SAFETY: 'ctx is sound here
124            // https://github.com/KhronosGroup/SPIRV-Cross/blob/main/spirv_cross_c.cpp#L2773
125            let name = CompilerStr::from_ptr(name, self.ctx.drop_guard());
126            if name.is_empty() {
127                Ok(None)
128            } else {
129                Ok(Some(name))
130            }
131        }
132    }
133}