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}