@@ -77,113 +77,132 @@ class ConvertUBOToPushConstantPass : public spvtools::opt::Pass
7777 {
7878 bool modified = false ;
7979
80- // Find the ID that matches the block name by searching OpName instructions
81- // This could be either a variable ID or a type ID (struct type)
82- uint32_t named_id = 0 ;
80+ // Collect all IDs that match the block name by searching OpName instructions.
81+ // Multiple OpName instructions may have the same name, so we need to check all of them
82+ // to find the one that refers to a UniformBuffer (Uniform storage class + Block decoration).
83+ std::vector<uint32_t > candidate_ids;
8384 for (auto & debug_inst : context ()->module ()->debugs2 ())
8485 {
8586 if (debug_inst.opcode () == spv::Op::OpName &&
8687 debug_inst.GetOperand (1 ).AsString () == m_BlockName)
8788 {
88- named_id = debug_inst.GetOperand (0 ).AsId ();
89- break ;
89+ candidate_ids.push_back (debug_inst.GetOperand (0 ).AsId ());
9090 }
9191 }
9292
93- if (named_id == 0 )
93+ if (candidate_ids. empty () )
9494 {
9595 // Block name not found
9696 return Status::SuccessWithoutChange;
9797 }
9898
99- // Check if the named_id is a variable or a type
99+ // Try each candidate ID to find a UniformBuffer
100100 spvtools::opt::Instruction* target_var = nullptr ;
101- spvtools::opt::Instruction* named_inst = get_def_use_mgr ()->GetDef (named_id);
102-
103- if (named_inst == nullptr )
104- {
105- return Status::SuccessWithoutChange;
106- }
107-
108- if (named_inst->opcode () == spv::Op::OpVariable)
101+ for (uint32_t named_id : candidate_ids)
109102 {
110- // The name refers directly to a variable
111- target_var = named_inst;
112- }
113- else if (named_inst->opcode () == spv::Op::OpTypeStruct)
114- {
115- // The name refers to a struct type, we need to find the variable
116- // that uses a pointer to this struct type with Uniform storage class
117- uint32_t struct_type_id = named_id;
103+ spvtools::opt::Instruction* named_inst = get_def_use_mgr ()->GetDef (named_id);
104+ if (named_inst == nullptr )
105+ {
106+ continue ;
107+ }
118108
119- // Search for a variable that points to this struct type with Uniform storage class
120- for (auto & inst : context ()->types_values ())
109+ if (named_inst->opcode () == spv::Op::OpVariable)
121110 {
122- if (inst.opcode () != spv::Op::OpVariable)
111+ // The name refers directly to a variable - check if it's a UniformBuffer
112+ spvtools::opt::Instruction* var_inst = named_inst;
113+
114+ // Get the pointer type of the variable
115+ spvtools::opt::Instruction* ptr_type_inst = get_def_use_mgr ()->GetDef (var_inst->type_id ());
116+ if (ptr_type_inst == nullptr || ptr_type_inst->opcode () != spv::Op::OpTypePointer)
123117 {
124118 continue ;
125119 }
126120
127- // Get the pointer type of this variable
128- spvtools::opt::Instruction* ptr_type = get_def_use_mgr ()->GetDef (inst.type_id ());
129- if (ptr_type == nullptr || ptr_type->opcode () != spv::Op::OpTypePointer)
121+ // Check if the storage class is Uniform
122+ spv::StorageClass storage_class =
123+ static_cast <spv::StorageClass>(ptr_type_inst->GetSingleWordInOperand (0 ));
124+ if (storage_class != spv::StorageClass::Uniform)
130125 {
131126 continue ;
132127 }
133128
134- // Check storage class is Uniform
135- spv::StorageClass sc = static_cast <spv::StorageClass>(
136- ptr_type->GetSingleWordInOperand (0 ));
137- if (sc != spv::StorageClass::Uniform)
129+ // Get the pointee type ID and verify it has Block decoration
130+ uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand (1 );
131+ if (HasBlockDecoration (pointee_type_id))
138132 {
139- continue ;
133+ // Found a UniformBuffer!
134+ target_var = var_inst;
135+ break ;
136+ }
137+ }
138+ else if (named_inst->opcode () == spv::Op::OpTypeStruct)
139+ {
140+ // The name refers to a struct type, we need to find the variable
141+ // that uses a pointer to this struct type with Uniform storage class
142+ uint32_t struct_type_id = named_id;
143+
144+ // Search for a variable that points to this struct type with Uniform storage class
145+ for (auto & inst : context ()->types_values ())
146+ {
147+ if (inst.opcode () != spv::Op::OpVariable)
148+ {
149+ continue ;
150+ }
151+
152+ // Get the pointer type of this variable
153+ spvtools::opt::Instruction* ptr_type = get_def_use_mgr ()->GetDef (inst.type_id ());
154+ if (ptr_type == nullptr || ptr_type->opcode () != spv::Op::OpTypePointer)
155+ {
156+ continue ;
157+ }
158+
159+ // Check storage class is Uniform
160+ spv::StorageClass sc = static_cast <spv::StorageClass>(
161+ ptr_type->GetSingleWordInOperand (0 ));
162+ if (sc != spv::StorageClass::Uniform)
163+ {
164+ continue ;
165+ }
166+
167+ // Check if the pointee type is our struct type
168+ uint32_t pointee_type_id = ptr_type->GetSingleWordInOperand (1 );
169+ if (pointee_type_id == struct_type_id)
170+ {
171+ // Verify it has Block decoration
172+ if (HasBlockDecoration (pointee_type_id))
173+ {
174+ // Found a UniformBuffer!
175+ target_var = &inst;
176+ break ;
177+ }
178+ }
140179 }
141180
142- // Check if the pointee type is our struct type
143- uint32_t pointee_type_id = ptr_type->GetSingleWordInOperand (1 );
144- if (pointee_type_id == struct_type_id)
181+ if (target_var != nullptr )
145182 {
146- target_var = &inst;
147183 break ;
148184 }
149185 }
150186 }
151187
152188 if (target_var == nullptr )
153189 {
154- // Variable not found
190+ // No UniformBuffer found with the given block name
155191 return Status::SuccessWithoutChange;
156192 }
157193
158194 uint32_t target_var_id = target_var->result_id ();
159195
160- // Get the pointer type of the variable
196+ // Get the pointer type of the variable (we already verified it above, but get it again for consistency)
161197 spvtools::opt::Instruction* ptr_type_inst = get_def_use_mgr ()->GetDef (target_var->type_id ());
162198 if (ptr_type_inst == nullptr || ptr_type_inst->opcode () != spv::Op::OpTypePointer)
163199 {
164200 return Status::SuccessWithoutChange;
165201 }
166202
167- // Check if the storage class is Uniform
168- spv::StorageClass storage_class =
169- static_cast <spv::StorageClass>(ptr_type_inst->GetSingleWordInOperand (0 ));
170- if (storage_class != spv::StorageClass::Uniform)
171- {
172- // Not a uniform buffer, nothing to do
173- return Status::SuccessWithoutChange;
174- }
175-
176203 // Get the pointee type ID
177204 uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand (1 );
178205
179- // Verify that the pointee type has the Block decoration, which is required for UBOs.
180- // This ensures we don't accidentally convert a non-UBO uniform variable.
181- if (!HasBlockDecoration (pointee_type_id))
182- {
183- // The struct type doesn't have Block decoration, not a valid UBO
184- return Status::SuccessWithoutChange;
185- }
186-
187206 // Create or find a pointer type with PushConstant storage class
188207 spvtools::opt::analysis::TypeManager* type_mgr = context ()->get_type_mgr ();
189208 uint32_t new_ptr_type_id =
0 commit comments