mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 21:51:22 +00:00 
			
		
		
		
	Added support for constants in shader case and array size declaration
				
					
				
			This commit is contained in:
		
							parent
							
								
									9e49dbda2a
								
							
						
					
					
						commit
						fe4c8e387b
					
				
					 3 changed files with 119 additions and 28 deletions
				
			
		|  | @ -920,7 +920,7 @@ void ShaderLanguage::clear() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) { | ||||
| bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) { | ||||
| 	if (p_function_info.built_ins.has(p_identifier)) { | ||||
| 		if (r_data_type) { | ||||
| 			*r_data_type = p_function_info.built_ins[p_identifier].type; | ||||
|  | @ -968,6 +968,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea | |||
| 			if (r_struct_name) { | ||||
| 				*r_struct_name = p_block->variables[p_identifier].struct_name; | ||||
| 			} | ||||
| 			if (r_constant_value) { | ||||
| 				*r_constant_value = p_block->variables[p_identifier].value; | ||||
| 			} | ||||
| 
 | ||||
| 			return true; | ||||
| 		} | ||||
|  | @ -1028,6 +1031,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea | |||
| 	} | ||||
| 
 | ||||
| 	if (shader->constants.has(p_identifier)) { | ||||
| 		if (r_is_const) { | ||||
| 			*r_is_const = true; | ||||
| 		} | ||||
| 		if (r_data_type) { | ||||
| 			*r_data_type = shader->constants[p_identifier].type; | ||||
| 		} | ||||
|  | @ -1040,6 +1046,11 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea | |||
| 		if (r_struct_name) { | ||||
| 			*r_struct_name = shader->constants[p_identifier].type_str; | ||||
| 		} | ||||
| 		if (r_constant_value) { | ||||
| 			if (shader->constants[p_identifier].initializer && shader->constants[p_identifier].initializer->values.size() == 1) { | ||||
| 				*r_constant_value = shader->constants[p_identifier].initializer->values[0]; | ||||
| 			} | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -5010,17 +5021,53 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun | |||
| 					decl.name = name; | ||||
| 					decl.size = 0U; | ||||
| 
 | ||||
| 					pos = _get_tkpos(); | ||||
| 					tk = _get_token(); | ||||
| 
 | ||||
| 					if (tk.type == TK_BRACKET_CLOSE) { | ||||
| 						unknown_size = true; | ||||
| 					} else { | ||||
| 						if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { | ||||
| 							_set_tkpos(pos); | ||||
| 							Node *n = _parse_and_reduce_expression(p_block, p_function_info); | ||||
| 							if (n) { | ||||
| 								if (n->type == Node::TYPE_VARIABLE) { | ||||
| 									VariableNode *vn = static_cast<VariableNode *>(n); | ||||
| 									if (vn) { | ||||
| 										ConstantNode::Value v; | ||||
| 										DataType data_type; | ||||
| 
 | ||||
| 										_find_identifier(p_block, false, p_function_info, vn->name, &data_type, nullptr, &is_const, nullptr, nullptr, &v); | ||||
| 
 | ||||
| 										if (is_const) { | ||||
| 											if (data_type == TYPE_INT) { | ||||
| 												int32_t value = v.sint; | ||||
| 												if (value > 0) { | ||||
| 													node->size_expression = n; | ||||
| 													decl.size = (uint32_t)value; | ||||
| 												} | ||||
| 											} else if (data_type == TYPE_UINT) { | ||||
| 												uint32_t value = v.uint; | ||||
| 												if (value > 0U) { | ||||
| 													node->size_expression = n; | ||||
| 													decl.size = value; | ||||
| 												} | ||||
| 											} | ||||
| 										} | ||||
| 									} | ||||
| 								} else if (n->type == Node::TYPE_OPERATOR) { | ||||
| 									_set_error("Array size expressions are not yet implemented."); | ||||
| 									return ERR_PARSE_ERROR; | ||||
| 								} | ||||
| 							} | ||||
| 						} else if (((int)tk.constant) > 0) { | ||||
| 							decl.size = (uint32_t)tk.constant; | ||||
| 						} | ||||
| 
 | ||||
| 						if (decl.size == 0U) { | ||||
| 							_set_error("Expected integer constant > 0 or ']'"); | ||||
| 							return ERR_PARSE_ERROR; | ||||
| 						} | ||||
| 
 | ||||
| 						decl.size = ((uint32_t)tk.constant); | ||||
| 						tk = _get_token(); | ||||
| 
 | ||||
| 						if (tk.type != TK_BRACKET_CLOSE) { | ||||
|  | @ -5218,7 +5265,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun | |||
| 							_set_error("Expected array initialization"); | ||||
| 							return ERR_PARSE_ERROR; | ||||
| 						} | ||||
| 						if (is_const) { | ||||
| 						if (node->is_const) { | ||||
| 							_set_error("Expected initialization of constant"); | ||||
| 							return ERR_PARSE_ERROR; | ||||
| 						} | ||||
|  | @ -5252,6 +5299,13 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun | |||
| 					} | ||||
| 					decl.initializer = n; | ||||
| 
 | ||||
| 					if (n->type == Node::TYPE_CONSTANT) { | ||||
| 						ConstantNode *const_node = static_cast<ConstantNode *>(n); | ||||
| 						if (const_node && const_node->values.size() == 1) { | ||||
| 							var.value = const_node->values[0]; | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) { | ||||
| 						_set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'"); | ||||
| 						return ERR_PARSE_ERROR; | ||||
|  | @ -5420,18 +5474,29 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun | |||
| 						ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i]; | ||||
| 						if (flow) { | ||||
| 							if (flow->flow_op == FLOW_OP_CASE) { | ||||
| 								ConstantNode *n2 = static_cast<ConstantNode *>(flow->expressions[0]); | ||||
| 								if (!n2) { | ||||
| 									return ERR_PARSE_ERROR; | ||||
| 								if (flow->expressions[0]->type == Node::TYPE_CONSTANT) { | ||||
| 									ConstantNode *cn = static_cast<ConstantNode *>(flow->expressions[0]); | ||||
| 									if (!cn || cn->values.empty()) { | ||||
| 										return ERR_PARSE_ERROR; | ||||
| 									} | ||||
| 									if (constants.has(cn->values[0].sint)) { | ||||
| 										_set_error("Duplicated case label: '" + itos(cn->values[0].sint) + "'"); | ||||
| 										return ERR_PARSE_ERROR; | ||||
| 									} | ||||
| 									constants.insert(cn->values[0].sint); | ||||
| 								} else if (flow->expressions[0]->type == Node::TYPE_VARIABLE) { | ||||
| 									VariableNode *vn = static_cast<VariableNode *>(flow->expressions[0]); | ||||
| 									if (!vn) { | ||||
| 										return ERR_PARSE_ERROR; | ||||
| 									} | ||||
| 									ConstantNode::Value v; | ||||
| 									_find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, nullptr, nullptr, nullptr, &v); | ||||
| 									if (constants.has(v.sint)) { | ||||
| 										_set_error("Duplicated case label: '" + itos(v.sint) + "'"); | ||||
| 										return ERR_PARSE_ERROR; | ||||
| 									} | ||||
| 									constants.insert(v.sint); | ||||
| 								} | ||||
| 								if (n2->values.empty()) { | ||||
| 									return ERR_PARSE_ERROR; | ||||
| 								} | ||||
| 								if (constants.has(n2->values[0].sint)) { | ||||
| 									_set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'"); | ||||
| 									return ERR_PARSE_ERROR; | ||||
| 								} | ||||
| 								constants.insert(n2->values[0].sint); | ||||
| 							} else if (flow->flow_op == FLOW_OP_DEFAULT) { | ||||
| 								continue; | ||||
| 							} else { | ||||
|  | @ -5467,12 +5532,38 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun | |||
| 				tk = _get_token(); | ||||
| 			} | ||||
| 
 | ||||
| 			if (tk.type != TK_INT_CONSTANT) { | ||||
| 				_set_error("Expected integer constant"); | ||||
| 				return ERR_PARSE_ERROR; | ||||
| 			} | ||||
| 			Node *n = nullptr; | ||||
| 
 | ||||
| 			int constant = (int)tk.constant * sign; | ||||
| 			if (tk.type != TK_INT_CONSTANT) { | ||||
| 				bool correct_constant_expression = false; | ||||
| 				DataType data_type; | ||||
| 
 | ||||
| 				if (tk.type == TK_IDENTIFIER) { | ||||
| 					bool is_const; | ||||
| 					_find_identifier(p_block, false, p_function_info, tk.text, &data_type, nullptr, &is_const); | ||||
| 					if (is_const) { | ||||
| 						if (data_type == TYPE_INT) { | ||||
| 							correct_constant_expression = true; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				if (!correct_constant_expression) { | ||||
| 					_set_error("Expected integer constant"); | ||||
| 					return ERR_PARSE_ERROR; | ||||
| 				} | ||||
| 
 | ||||
| 				VariableNode *vn = alloc_node<VariableNode>(); | ||||
| 				vn->name = tk.text; | ||||
| 				n = vn; | ||||
| 			} else { | ||||
| 				ConstantNode::Value v; | ||||
| 				v.sint = (int)tk.constant * sign; | ||||
| 
 | ||||
| 				ConstantNode *cn = alloc_node<ConstantNode>(); | ||||
| 				cn->values.push_back(v); | ||||
| 				cn->datatype = TYPE_INT; | ||||
| 				n = cn; | ||||
| 			} | ||||
| 
 | ||||
| 			tk = _get_token(); | ||||
| 
 | ||||
|  | @ -5484,12 +5575,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun | |||
| 			ControlFlowNode *cf = alloc_node<ControlFlowNode>(); | ||||
| 			cf->flow_op = FLOW_OP_CASE; | ||||
| 
 | ||||
| 			ConstantNode *n = alloc_node<ConstantNode>(); | ||||
| 			ConstantNode::Value v; | ||||
| 			v.sint = constant; | ||||
| 			n->values.push_back(v); | ||||
| 			n->datatype = TYPE_INT; | ||||
| 
 | ||||
| 			BlockNode *case_block = alloc_node<BlockNode>(); | ||||
| 			case_block->block_type = BlockNode::BLOCK_TYPE_CASE; | ||||
| 			case_block->parent_block = p_block; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Yuri Roubinsky
						Yuri Roubinsky