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}