Added constant support to shaders
Co-authored-by: DavidSichma <sichmada@gmail.com>
This commit is contained in:
parent
7310c84367
commit
c2d4abf62e
4 changed files with 133 additions and 6 deletions
|
@ -361,6 +361,21 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
fragment_global += final_code;
|
fragment_global += final_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constants
|
||||||
|
|
||||||
|
for (Map<StringName, SL::ShaderNode::Constant>::Element *E = snode->constants.front(); E; E = E->next()) {
|
||||||
|
String gcode;
|
||||||
|
gcode += "const ";
|
||||||
|
gcode += _prestr(E->get().precision);
|
||||||
|
gcode += _typestr(E->get().type);
|
||||||
|
gcode += " " + _mkid(E->key());
|
||||||
|
gcode += "=";
|
||||||
|
gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
|
gcode += ";\n";
|
||||||
|
vertex_global += gcode;
|
||||||
|
fragment_global += gcode;
|
||||||
|
}
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
|
|
||||||
Map<StringName, String> function_code;
|
Map<StringName, String> function_code;
|
||||||
|
|
|
@ -472,6 +472,19 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
r_gen_code.fragment_global += interp_mode + "in " + vcode;
|
r_gen_code.fragment_global += interp_mode + "in " + vcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Map<StringName, SL::ShaderNode::Constant>::Element *E = pnode->constants.front(); E; E = E->next()) {
|
||||||
|
String gcode;
|
||||||
|
gcode += "const ";
|
||||||
|
gcode += _prestr(E->get().precision);
|
||||||
|
gcode += _typestr(E->get().type);
|
||||||
|
gcode += " " + _mkid(E->key());
|
||||||
|
gcode += "=";
|
||||||
|
gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
|
gcode += ";\n";
|
||||||
|
r_gen_code.vertex_global += gcode;
|
||||||
|
r_gen_code.fragment_global += gcode;
|
||||||
|
}
|
||||||
|
|
||||||
Map<StringName, String> function_code;
|
Map<StringName, String> function_code;
|
||||||
|
|
||||||
//code for functions
|
//code for functions
|
||||||
|
|
|
@ -132,6 +132,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
|
||||||
"TYPE_SAMPLERCUBE",
|
"TYPE_SAMPLERCUBE",
|
||||||
"INTERPOLATION_FLAT",
|
"INTERPOLATION_FLAT",
|
||||||
"INTERPOLATION_SMOOTH",
|
"INTERPOLATION_SMOOTH",
|
||||||
|
"CONST",
|
||||||
"PRECISION_LOW",
|
"PRECISION_LOW",
|
||||||
"PRECISION_MID",
|
"PRECISION_MID",
|
||||||
"PRECISION_HIGH",
|
"PRECISION_HIGH",
|
||||||
|
@ -271,6 +272,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
|
||||||
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
|
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
|
||||||
{ TK_INTERPOLATION_FLAT, "flat" },
|
{ TK_INTERPOLATION_FLAT, "flat" },
|
||||||
{ TK_INTERPOLATION_SMOOTH, "smooth" },
|
{ TK_INTERPOLATION_SMOOTH, "smooth" },
|
||||||
|
{ TK_CONST, "const" },
|
||||||
{ TK_PRECISION_LOW, "lowp" },
|
{ TK_PRECISION_LOW, "lowp" },
|
||||||
{ TK_PRECISION_MID, "mediump" },
|
{ TK_PRECISION_MID, "mediump" },
|
||||||
{ TK_PRECISION_HIGH, "highp" },
|
{ TK_PRECISION_HIGH, "highp" },
|
||||||
|
@ -920,6 +922,16 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Map<String
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shader->constants.has(p_identifier)) {
|
||||||
|
if (r_data_type) {
|
||||||
|
*r_data_type = shader->constants[p_identifier].type;
|
||||||
|
}
|
||||||
|
if (r_type) {
|
||||||
|
*r_type = IDENTIFIER_CONSTANT;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < shader->functions.size(); i++) {
|
for (int i = 0; i < shader->functions.size(); i++) {
|
||||||
|
|
||||||
if (!shader->functions[i].callable)
|
if (!shader->functions[i].callable)
|
||||||
|
@ -2699,6 +2711,12 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shader->constants.has(var->name)) {
|
||||||
|
if (r_message)
|
||||||
|
*r_message = RTR("Constants cannot be modified.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) {
|
if (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3993,7 +4011,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//nothng else, so expression
|
//nothing else, so expression
|
||||||
_set_tkpos(pos); //rollback
|
_set_tkpos(pos); //rollback
|
||||||
Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types);
|
Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types);
|
||||||
if (!expr)
|
if (!expr)
|
||||||
|
@ -4322,24 +4340,30 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
//function
|
//function or constant variable
|
||||||
|
|
||||||
|
bool is_constant = false;
|
||||||
DataPrecision precision = PRECISION_DEFAULT;
|
DataPrecision precision = PRECISION_DEFAULT;
|
||||||
DataType type;
|
DataType type;
|
||||||
StringName name;
|
StringName name;
|
||||||
|
|
||||||
|
if (tk.type == TK_CONST) {
|
||||||
|
is_constant = true;
|
||||||
|
tk = _get_token();
|
||||||
|
}
|
||||||
|
|
||||||
if (is_token_precision(tk.type)) {
|
if (is_token_precision(tk.type)) {
|
||||||
precision = get_token_precision(tk.type);
|
precision = get_token_precision(tk.type);
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_token_datatype(tk.type)) {
|
if (!is_token_datatype(tk.type)) {
|
||||||
_set_error("Expected function, uniform or varying ");
|
_set_error("Expected constant, function, uniform or varying ");
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_token_variable_datatype(tk.type)) {
|
if (!is_token_variable_datatype(tk.type)) {
|
||||||
_set_error("Invalid data type for function return (samplers not allowed)");
|
_set_error("Invalid data type for constants or function return (samplers not allowed)");
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4359,10 +4383,75 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
|
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
if (tk.type != TK_PARENTHESIS_OPEN) {
|
if (tk.type != TK_PARENTHESIS_OPEN) {
|
||||||
_set_error("Expected '(' after identifier");
|
if (type == TYPE_VOID) {
|
||||||
|
_set_error("Expected '(' after function identifier");
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//variable
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ShaderNode::Constant constant;
|
||||||
|
constant.type = type;
|
||||||
|
constant.precision = precision;
|
||||||
|
constant.initializer = NULL;
|
||||||
|
|
||||||
|
if (tk.type == TK_OP_ASSIGN) {
|
||||||
|
|
||||||
|
if (!is_constant) {
|
||||||
|
_set_error("Expected 'const' keyword before constant definition");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//variable created with assignment! must parse an expression
|
||||||
|
Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>());
|
||||||
|
if (!expr)
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
|
||||||
|
if (expr->type != Node::TYPE_CONSTANT) {
|
||||||
|
_set_error("Expected constant expression after '='");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
constant.initializer = static_cast<ConstantNode *>(expr);
|
||||||
|
|
||||||
|
if (type != expr->get_datatype()) {
|
||||||
|
_set_error("Invalid assignment of '" + get_datatype_name(expr->get_datatype()) + "' to '" + get_datatype_name(type) + "'");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
tk = _get_token();
|
||||||
|
} else {
|
||||||
|
_set_error("Expected initialization of constant");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->constants[name] = constant;
|
||||||
|
if (tk.type == TK_COMMA) {
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_IDENTIFIER) {
|
||||||
|
_set_error("Expected identifier after type");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = tk.text;
|
||||||
|
if (_find_identifier(NULL, Map<StringName, BuiltInInfo>(), name)) {
|
||||||
|
_set_error("Redefinition of '" + String(name) + "'");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
|
||||||
|
} else if (tk.type == TK_SEMICOLON) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
_set_error("Expected ',' or ';' after constant");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Map<StringName, BuiltInInfo> builtin_types;
|
Map<StringName, BuiltInInfo> builtin_types;
|
||||||
if (p_functions.has(name)) {
|
if (p_functions.has(name)) {
|
||||||
builtin_types = p_functions[name].built_ins;
|
builtin_types = p_functions[name].built_ins;
|
||||||
|
|
|
@ -80,6 +80,7 @@ public:
|
||||||
TK_TYPE_SAMPLERCUBE,
|
TK_TYPE_SAMPLERCUBE,
|
||||||
TK_INTERPOLATION_FLAT,
|
TK_INTERPOLATION_FLAT,
|
||||||
TK_INTERPOLATION_SMOOTH,
|
TK_INTERPOLATION_SMOOTH,
|
||||||
|
TK_CONST,
|
||||||
TK_PRECISION_LOW,
|
TK_PRECISION_LOW,
|
||||||
TK_PRECISION_MID,
|
TK_PRECISION_MID,
|
||||||
TK_PRECISION_HIGH,
|
TK_PRECISION_HIGH,
|
||||||
|
@ -440,6 +441,13 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShaderNode : public Node {
|
struct ShaderNode : public Node {
|
||||||
|
|
||||||
|
struct Constant {
|
||||||
|
DataType type;
|
||||||
|
DataPrecision precision;
|
||||||
|
ConstantNode *initializer;
|
||||||
|
};
|
||||||
|
|
||||||
struct Function {
|
struct Function {
|
||||||
StringName name;
|
StringName name;
|
||||||
FunctionNode *function;
|
FunctionNode *function;
|
||||||
|
@ -492,6 +500,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Map<StringName, Constant> constants;
|
||||||
Map<StringName, Varying> varyings;
|
Map<StringName, Varying> varyings;
|
||||||
Map<StringName, Uniform> uniforms;
|
Map<StringName, Uniform> uniforms;
|
||||||
Vector<StringName> render_modes;
|
Vector<StringName> render_modes;
|
||||||
|
@ -632,6 +641,7 @@ private:
|
||||||
IDENTIFIER_FUNCTION_ARGUMENT,
|
IDENTIFIER_FUNCTION_ARGUMENT,
|
||||||
IDENTIFIER_LOCAL_VAR,
|
IDENTIFIER_LOCAL_VAR,
|
||||||
IDENTIFIER_BUILTIN_VAR,
|
IDENTIFIER_BUILTIN_VAR,
|
||||||
|
IDENTIFIER_CONSTANT,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL);
|
bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL);
|
||||||
|
|
Loading…
Reference in a new issue