mirror of
https://github.com/godotengine/godot.git
synced 2025-11-01 14:11:15 +00:00
Backport dd0874e "Allow passing varying from fragment to light shader function" to 3.4
This commit is contained in:
parent
0c028ad96e
commit
fba6b62054
6 changed files with 262 additions and 33 deletions
|
|
@ -210,7 +210,7 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderCompilerGLES2::_dump_function_deps(SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added) {
|
void ShaderCompilerGLES2::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added) {
|
||||||
int fidx = -1;
|
int fidx = -1;
|
||||||
|
|
||||||
for (int i = 0; i < p_node->functions.size(); i++) {
|
for (int i = 0; i < p_node->functions.size(); i++) {
|
||||||
|
|
@ -269,7 +269,7 @@ void ShaderCompilerGLES2::_dump_function_deps(SL::ShaderNode *p_node, const Stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
|
String ShaderCompilerGLES2::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
|
||||||
StringBuilder code;
|
StringBuilder code;
|
||||||
|
|
||||||
switch (p_node->type) {
|
switch (p_node->type) {
|
||||||
|
|
@ -378,7 +378,14 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
|
|
||||||
// varyings
|
// varyings
|
||||||
|
|
||||||
|
List<Pair<StringName, SL::ShaderNode::Varying>> var_frag_to_light;
|
||||||
|
|
||||||
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = snode->varyings.front(); E; E = E->next()) {
|
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = snode->varyings.front(); E; E = E->next()) {
|
||||||
|
if (E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT || E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
|
||||||
|
var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(E->key(), E->get()));
|
||||||
|
fragment_varyings.insert(E->key());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
StringBuffer<> varying_code;
|
StringBuffer<> varying_code;
|
||||||
|
|
||||||
varying_code += "varying ";
|
varying_code += "varying ";
|
||||||
|
|
@ -399,6 +406,21 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
fragment_global += final_code;
|
fragment_global += final_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (var_frag_to_light.size() > 0) {
|
||||||
|
String gcode = "\n\nstruct {\n";
|
||||||
|
for (List<Pair<StringName, SL::ShaderNode::Varying>>::Element *E = var_frag_to_light.front(); E; E = E->next()) {
|
||||||
|
gcode += "\t" + _prestr(E->get().second.precision) + _typestr(E->get().second.type) + " " + _mkid(E->get().first);
|
||||||
|
if (E->get().second.array_size > 0) {
|
||||||
|
gcode += "[";
|
||||||
|
gcode += itos(E->get().second.array_size);
|
||||||
|
gcode += "]";
|
||||||
|
}
|
||||||
|
gcode += ";\n";
|
||||||
|
}
|
||||||
|
gcode += "} frag_to_light;\n";
|
||||||
|
r_gen_code.fragment_global += gcode;
|
||||||
|
}
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
|
|
||||||
for (int i = 0; i < snode->vconstants.size(); i++) {
|
for (int i = 0; i < snode->vconstants.size(); i++) {
|
||||||
|
|
@ -424,8 +446,10 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
|
|
||||||
for (int i = 0; i < snode->functions.size(); i++) {
|
for (int i = 0; i < snode->functions.size(); i++) {
|
||||||
SL::FunctionNode *fnode = snode->functions[i].function;
|
SL::FunctionNode *fnode = snode->functions[i].function;
|
||||||
|
function = fnode;
|
||||||
current_func_name = fnode->name;
|
current_func_name = fnode->name;
|
||||||
function_code[fnode->name] = _dump_node_code(fnode->body, 1, r_gen_code, p_actions, p_default_actions, p_assigning);
|
function_code[fnode->name] = _dump_node_code(fnode->body, 1, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
|
function = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<StringName> added_vertex;
|
Set<StringName> added_vertex;
|
||||||
|
|
@ -434,6 +458,8 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
for (int i = 0; i < snode->functions.size(); i++) {
|
for (int i = 0; i < snode->functions.size(); i++) {
|
||||||
SL::FunctionNode *fnode = snode->functions[i].function;
|
SL::FunctionNode *fnode = snode->functions[i].function;
|
||||||
|
|
||||||
|
function = fnode;
|
||||||
|
|
||||||
current_func_name = fnode->name;
|
current_func_name = fnode->name;
|
||||||
|
|
||||||
if (fnode->name == vertex_name) {
|
if (fnode->name == vertex_name) {
|
||||||
|
|
@ -448,6 +474,8 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
_dump_function_deps(snode, fnode->name, function_code, fragment_global, added_fragment);
|
_dump_function_deps(snode, fnode->name, function_code, fragment_global, added_fragment);
|
||||||
r_gen_code.light = function_code[light_name];
|
r_gen_code.light = function_code[light_name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
r_gen_code.vertex_global = vertex_global.as_string();
|
r_gen_code.vertex_global = vertex_global.as_string();
|
||||||
|
|
@ -519,6 +547,19 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
|
|
||||||
case SL::Node::TYPE_VARIABLE: {
|
case SL::Node::TYPE_VARIABLE: {
|
||||||
SL::VariableNode *var_node = (SL::VariableNode *)p_node;
|
SL::VariableNode *var_node = (SL::VariableNode *)p_node;
|
||||||
|
bool use_fragment_varying = false;
|
||||||
|
|
||||||
|
if (current_func_name != vertex_name) {
|
||||||
|
if (p_assigning) {
|
||||||
|
if (shader->varyings.has(var_node->name)) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fragment_varyings.has(var_node->name)) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p_assigning && p_actions.write_flag_pointers.has(var_node->name)) {
|
if (p_assigning && p_actions.write_flag_pointers.has(var_node->name)) {
|
||||||
*p_actions.write_flag_pointers[var_node->name] = true;
|
*p_actions.write_flag_pointers[var_node->name] = true;
|
||||||
|
|
@ -545,6 +586,8 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
|
|
||||||
if (p_default_actions.renames.has(var_node->name)) {
|
if (p_default_actions.renames.has(var_node->name)) {
|
||||||
code += p_default_actions.renames[var_node->name];
|
code += p_default_actions.renames[var_node->name];
|
||||||
|
} else if (use_fragment_varying) {
|
||||||
|
code += "frag_to_light." + _mkid(var_node->name);
|
||||||
} else {
|
} else {
|
||||||
code += _mkid(var_node->name);
|
code += _mkid(var_node->name);
|
||||||
}
|
}
|
||||||
|
|
@ -605,6 +648,23 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
} break;
|
} break;
|
||||||
case SL::Node::TYPE_ARRAY: {
|
case SL::Node::TYPE_ARRAY: {
|
||||||
SL::ArrayNode *arr_node = (SL::ArrayNode *)p_node;
|
SL::ArrayNode *arr_node = (SL::ArrayNode *)p_node;
|
||||||
|
bool use_fragment_varying = false;
|
||||||
|
|
||||||
|
if (current_func_name != vertex_name) {
|
||||||
|
if (arr_node->assign_expression != nullptr) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
} else {
|
||||||
|
if (p_assigning) {
|
||||||
|
if (shader->varyings.has(arr_node->name)) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fragment_varyings.has(arr_node->name)) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p_assigning && p_actions.write_flag_pointers.has(arr_node->name)) {
|
if (p_assigning && p_actions.write_flag_pointers.has(arr_node->name)) {
|
||||||
*p_actions.write_flag_pointers[arr_node->name] = true;
|
*p_actions.write_flag_pointers[arr_node->name] = true;
|
||||||
|
|
@ -631,6 +691,8 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
|
|
||||||
if (p_default_actions.renames.has(arr_node->name)) {
|
if (p_default_actions.renames.has(arr_node->name)) {
|
||||||
code += p_default_actions.renames[arr_node->name];
|
code += p_default_actions.renames[arr_node->name];
|
||||||
|
} else if (use_fragment_varying) {
|
||||||
|
code += "frag_to_light." + _mkid(arr_node->name);
|
||||||
} else {
|
} else {
|
||||||
code += _mkid(arr_node->name);
|
code += _mkid(arr_node->name);
|
||||||
}
|
}
|
||||||
|
|
@ -908,7 +970,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
code += _dump_node_code(member_node->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
code += _dump_node_code(member_node->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
code += ".";
|
code += ".";
|
||||||
code += member_node->name;
|
code += member_node->name;
|
||||||
if (member_node->index_expression != NULL) {
|
if (member_node->index_expression != nullptr) {
|
||||||
code += "[";
|
code += "[";
|
||||||
code += _dump_node_code(member_node->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
code += _dump_node_code(member_node->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
code += "]";
|
code += "]";
|
||||||
|
|
@ -947,8 +1009,11 @@ Error ShaderCompilerGLES2::compile(VS::ShaderMode p_mode, const String &p_code,
|
||||||
used_name_defines.clear();
|
used_name_defines.clear();
|
||||||
used_rmode_defines.clear();
|
used_rmode_defines.clear();
|
||||||
used_flag_pointers.clear();
|
used_flag_pointers.clear();
|
||||||
|
fragment_varyings.clear();
|
||||||
|
|
||||||
_dump_node_code(parser.get_shader(), 1, r_gen_code, *p_actions, actions[p_mode], false);
|
shader = parser.get_shader();
|
||||||
|
function = nullptr;
|
||||||
|
_dump_node_code(shader, 1, r_gen_code, *p_actions, actions[p_mode], false);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,11 @@ private:
|
||||||
Map<StringName, String> usage_defines;
|
Map<StringName, String> usage_defines;
|
||||||
};
|
};
|
||||||
|
|
||||||
void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added);
|
void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, StringBuilder &r_to_add, Set<StringName> &r_added);
|
||||||
String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope = true);
|
String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope = true);
|
||||||
|
|
||||||
|
const ShaderLanguage::ShaderNode *shader;
|
||||||
|
const ShaderLanguage::FunctionNode *function;
|
||||||
StringName current_func_name;
|
StringName current_func_name;
|
||||||
StringName vertex_name;
|
StringName vertex_name;
|
||||||
StringName fragment_name;
|
StringName fragment_name;
|
||||||
|
|
@ -86,6 +88,7 @@ private:
|
||||||
Set<StringName> used_flag_pointers;
|
Set<StringName> used_flag_pointers;
|
||||||
Set<StringName> used_rmode_defines;
|
Set<StringName> used_rmode_defines;
|
||||||
Set<StringName> internal_functions;
|
Set<StringName> internal_functions;
|
||||||
|
Set<StringName> fragment_varyings;
|
||||||
|
|
||||||
DefaultIdentifierActions actions[VS::SHADER_MAX];
|
DefaultIdentifierActions actions[VS::SHADER_MAX];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) {
|
void ShaderCompilerGLES3::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added) {
|
||||||
int fidx = -1;
|
int fidx = -1;
|
||||||
|
|
||||||
for (int i = 0; i < p_node->functions.size(); i++) {
|
for (int i = 0; i < p_node->functions.size(); i++) {
|
||||||
|
|
@ -388,7 +388,7 @@ void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const Stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
|
String ShaderCompilerGLES3::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope) {
|
||||||
String code;
|
String code;
|
||||||
|
|
||||||
switch (p_node->type) {
|
switch (p_node->type) {
|
||||||
|
|
@ -521,7 +521,14 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
r_gen_code.uniform_total_size += r_gen_code.uniform_total_size % 16;
|
r_gen_code.uniform_total_size += r_gen_code.uniform_total_size % 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Pair<StringName, SL::ShaderNode::Varying>> var_frag_to_light;
|
||||||
|
|
||||||
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) {
|
for (Map<StringName, SL::ShaderNode::Varying>::Element *E = pnode->varyings.front(); E; E = E->next()) {
|
||||||
|
if (E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT || E->get().stage == SL::ShaderNode::Varying::STAGE_FRAGMENT) {
|
||||||
|
var_frag_to_light.push_back(Pair<StringName, SL::ShaderNode::Varying>(E->key(), E->get()));
|
||||||
|
fragment_varyings.insert(E->key());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String vcode;
|
String vcode;
|
||||||
String interp_mode = _interpstr(E->get().interpolation);
|
String interp_mode = _interpstr(E->get().interpolation);
|
||||||
vcode += _prestr(E->get().precision);
|
vcode += _prestr(E->get().precision);
|
||||||
|
|
@ -537,6 +544,21 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (var_frag_to_light.size() > 0) {
|
||||||
|
String gcode = "\n\nstruct {\n";
|
||||||
|
for (List<Pair<StringName, SL::ShaderNode::Varying>>::Element *E = var_frag_to_light.front(); E; E = E->next()) {
|
||||||
|
gcode += "\t" + _prestr(E->get().second.precision) + _typestr(E->get().second.type) + " " + _mkid(E->get().first);
|
||||||
|
if (E->get().second.array_size > 0) {
|
||||||
|
gcode += "[";
|
||||||
|
gcode += itos(E->get().second.array_size);
|
||||||
|
gcode += "]";
|
||||||
|
}
|
||||||
|
gcode += ";\n";
|
||||||
|
}
|
||||||
|
gcode += "} frag_to_light;\n";
|
||||||
|
r_gen_code.fragment_global += gcode;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < pnode->vconstants.size(); i++) {
|
for (int i = 0; i < pnode->vconstants.size(); i++) {
|
||||||
String gcode;
|
String gcode;
|
||||||
gcode += "const ";
|
gcode += "const ";
|
||||||
|
|
@ -559,8 +581,10 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
//code for functions
|
//code for functions
|
||||||
for (int i = 0; i < pnode->functions.size(); i++) {
|
for (int i = 0; i < pnode->functions.size(); i++) {
|
||||||
SL::FunctionNode *fnode = pnode->functions[i].function;
|
SL::FunctionNode *fnode = pnode->functions[i].function;
|
||||||
|
function = fnode;
|
||||||
current_func_name = fnode->name;
|
current_func_name = fnode->name;
|
||||||
function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
|
function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
|
function = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//place functions in actual code
|
//place functions in actual code
|
||||||
|
|
@ -571,6 +595,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
for (int i = 0; i < pnode->functions.size(); i++) {
|
for (int i = 0; i < pnode->functions.size(); i++) {
|
||||||
SL::FunctionNode *fnode = pnode->functions[i].function;
|
SL::FunctionNode *fnode = pnode->functions[i].function;
|
||||||
|
|
||||||
|
function = fnode;
|
||||||
|
|
||||||
current_func_name = fnode->name;
|
current_func_name = fnode->name;
|
||||||
|
|
||||||
if (fnode->name == vertex_name) {
|
if (fnode->name == vertex_name) {
|
||||||
|
|
@ -587,6 +613,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
_dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment);
|
_dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment);
|
||||||
r_gen_code.light = function_code[light_name];
|
r_gen_code.light = function_code[light_name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//code+=dump_node_code(pnode->body,p_level);
|
//code+=dump_node_code(pnode->body,p_level);
|
||||||
|
|
@ -647,6 +675,19 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
} break;
|
} break;
|
||||||
case SL::Node::TYPE_VARIABLE: {
|
case SL::Node::TYPE_VARIABLE: {
|
||||||
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
|
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
|
||||||
|
bool use_fragment_varying = false;
|
||||||
|
|
||||||
|
if (current_func_name != vertex_name) {
|
||||||
|
if (p_assigning) {
|
||||||
|
if (shader->varyings.has(vnode->name)) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fragment_varyings.has(vnode->name)) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) {
|
if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) {
|
||||||
*p_actions.write_flag_pointers[vnode->name] = true;
|
*p_actions.write_flag_pointers[vnode->name] = true;
|
||||||
|
|
@ -668,6 +709,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
|
|
||||||
if (p_default_actions.renames.has(vnode->name)) {
|
if (p_default_actions.renames.has(vnode->name)) {
|
||||||
code = p_default_actions.renames[vnode->name];
|
code = p_default_actions.renames[vnode->name];
|
||||||
|
} else if (use_fragment_varying) {
|
||||||
|
code = "frag_to_light." + _mkid(vnode->name);
|
||||||
} else {
|
} else {
|
||||||
code = _mkid(vnode->name);
|
code = _mkid(vnode->name);
|
||||||
}
|
}
|
||||||
|
|
@ -751,6 +794,23 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
} break;
|
} break;
|
||||||
case SL::Node::TYPE_ARRAY: {
|
case SL::Node::TYPE_ARRAY: {
|
||||||
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
|
SL::ArrayNode *anode = (SL::ArrayNode *)p_node;
|
||||||
|
bool use_fragment_varying = false;
|
||||||
|
|
||||||
|
if (current_func_name != vertex_name) {
|
||||||
|
if (anode->assign_expression != nullptr) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
} else {
|
||||||
|
if (p_assigning) {
|
||||||
|
if (shader->varyings.has(anode->name)) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fragment_varyings.has(anode->name)) {
|
||||||
|
use_fragment_varying = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) {
|
if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) {
|
||||||
*p_actions.write_flag_pointers[anode->name] = true;
|
*p_actions.write_flag_pointers[anode->name] = true;
|
||||||
|
|
@ -772,6 +832,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
|
|
||||||
if (p_default_actions.renames.has(anode->name)) {
|
if (p_default_actions.renames.has(anode->name)) {
|
||||||
code = p_default_actions.renames[anode->name];
|
code = p_default_actions.renames[anode->name];
|
||||||
|
} else if (use_fragment_varying) {
|
||||||
|
code = "frag_to_light." + _mkid(anode->name);
|
||||||
} else {
|
} else {
|
||||||
code = _mkid(anode->name);
|
code = _mkid(anode->name);
|
||||||
}
|
}
|
||||||
|
|
@ -783,7 +845,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
code += "[";
|
code += "[";
|
||||||
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
code += "]";
|
code += "]";
|
||||||
} else if (anode->assign_expression != NULL) {
|
} else if (anode->assign_expression != nullptr) {
|
||||||
code += "=";
|
code += "=";
|
||||||
code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
|
code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
|
||||||
}
|
}
|
||||||
|
|
@ -949,7 +1011,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
||||||
case SL::Node::TYPE_MEMBER: {
|
case SL::Node::TYPE_MEMBER: {
|
||||||
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
|
SL::MemberNode *mnode = (SL::MemberNode *)p_node;
|
||||||
code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name;
|
code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name;
|
||||||
if (mnode->index_expression != NULL) {
|
if (mnode->index_expression != nullptr) {
|
||||||
code += "[";
|
code += "[";
|
||||||
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||||
code += "]";
|
code += "]";
|
||||||
|
|
@ -988,8 +1050,11 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String &p_code,
|
||||||
used_name_defines.clear();
|
used_name_defines.clear();
|
||||||
used_rmode_defines.clear();
|
used_rmode_defines.clear();
|
||||||
used_flag_pointers.clear();
|
used_flag_pointers.clear();
|
||||||
|
fragment_varyings.clear();
|
||||||
|
|
||||||
_dump_node_code(parser.get_shader(), 1, r_gen_code, *p_actions, actions[p_mode], false);
|
shader = parser.get_shader();
|
||||||
|
function = nullptr;
|
||||||
|
_dump_node_code(shader, 1, r_gen_code, *p_actions, actions[p_mode], false);
|
||||||
|
|
||||||
if (r_gen_code.uniform_total_size) { //uniforms used?
|
if (r_gen_code.uniform_total_size) { //uniforms used?
|
||||||
int md = sizeof(float) * 4;
|
int md = sizeof(float) * 4;
|
||||||
|
|
|
||||||
|
|
@ -75,9 +75,11 @@ private:
|
||||||
Map<StringName, String> usage_defines;
|
Map<StringName, String> usage_defines;
|
||||||
};
|
};
|
||||||
|
|
||||||
void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added);
|
void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added);
|
||||||
String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope = true);
|
String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning, bool p_use_scope = true);
|
||||||
|
|
||||||
|
const ShaderLanguage::ShaderNode *shader;
|
||||||
|
const ShaderLanguage::FunctionNode *function;
|
||||||
StringName current_func_name;
|
StringName current_func_name;
|
||||||
StringName vertex_name;
|
StringName vertex_name;
|
||||||
StringName fragment_name;
|
StringName fragment_name;
|
||||||
|
|
@ -88,6 +90,7 @@ private:
|
||||||
Set<StringName> used_flag_pointers;
|
Set<StringName> used_flag_pointers;
|
||||||
Set<StringName> used_rmode_defines;
|
Set<StringName> used_rmode_defines;
|
||||||
Set<StringName> internal_functions;
|
Set<StringName> internal_functions;
|
||||||
|
Set<StringName> fragment_varyings;
|
||||||
|
|
||||||
DefaultIdentifierActions actions[VS::SHADER_MAX];
|
DefaultIdentifierActions actions[VS::SHADER_MAX];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2761,6 +2761,72 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) {
|
||||||
|
if (current_function == String("light")) {
|
||||||
|
*r_message = RTR("Varying may not be assigned in the 'light' function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (p_varying.stage) {
|
||||||
|
case ShaderNode::Varying::STAGE_UNKNOWN: // first assign
|
||||||
|
if (current_function == String("vertex")) {
|
||||||
|
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX;
|
||||||
|
} else if (current_function == String("fragment")) {
|
||||||
|
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ShaderNode::Varying::STAGE_VERTEX:
|
||||||
|
if (current_function == String("fragment")) {
|
||||||
|
*r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ShaderNode::Varying::STAGE_FRAGMENT:
|
||||||
|
if (current_function == String("vertex")) {
|
||||||
|
*r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
|
||||||
|
switch (p_varying.stage) {
|
||||||
|
case ShaderNode::Varying::STAGE_UNKNOWN:
|
||||||
|
*r_message = RTR("Varying must be assigned before using!");
|
||||||
|
return false;
|
||||||
|
case ShaderNode::Varying::STAGE_VERTEX:
|
||||||
|
if (current_function == String("fragment")) {
|
||||||
|
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT;
|
||||||
|
} else if (current_function == String("light")) {
|
||||||
|
p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ShaderNode::Varying::STAGE_FRAGMENT:
|
||||||
|
if (current_function == String("light")) {
|
||||||
|
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT:
|
||||||
|
if (current_function == String("light")) {
|
||||||
|
*r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT:
|
||||||
|
if (current_function == String("fragment")) {
|
||||||
|
*r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) {
|
bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) {
|
||||||
if (p_node->type == Node::TYPE_OPERATOR) {
|
if (p_node->type == Node::TYPE_OPERATOR) {
|
||||||
OperatorNode *op = static_cast<OperatorNode *>(p_node);
|
OperatorNode *op = static_cast<OperatorNode *>(p_node);
|
||||||
|
|
@ -2793,13 +2859,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader->varyings.has(var->name) && current_function != String("vertex")) {
|
|
||||||
if (r_message) {
|
|
||||||
*r_message = RTR("Varyings can only be assigned in vertex function.");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shader->constants.has(var->name) || var->is_const) {
|
if (shader->constants.has(var->name) || var->is_const) {
|
||||||
if (r_message) {
|
if (r_message) {
|
||||||
*r_message = RTR("Constants cannot be modified.");
|
*r_message = RTR("Constants cannot be modified.");
|
||||||
|
|
@ -2820,13 +2879,6 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader->varyings.has(arr->name) && current_function != String("vertex")) {
|
|
||||||
if (r_message) {
|
|
||||||
*r_message = RTR("Varyings can only be assigned in vertex function.");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3419,6 +3471,23 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
last_const = is_const;
|
last_const = is_const;
|
||||||
|
if (ident_type == IDENTIFIER_VARYING) {
|
||||||
|
TkPos prev_pos = _get_tkpos();
|
||||||
|
Token next_token = _get_token();
|
||||||
|
_set_tkpos(prev_pos);
|
||||||
|
String error;
|
||||||
|
if (next_token.type == TK_OP_ASSIGN) {
|
||||||
|
if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
|
||||||
|
_set_error(error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!_validate_varying_using(shader->varyings[identifier], &error)) {
|
||||||
|
_set_error(error);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ident_type == IDENTIFIER_FUNCTION) {
|
if (ident_type == IDENTIFIER_FUNCTION) {
|
||||||
_set_error("Can't use function as identifier: " + String(identifier));
|
_set_error("Can't use function as identifier: " + String(identifier));
|
||||||
|
|
@ -5695,6 +5764,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TkPos name_pos = _get_tkpos();
|
||||||
name = tk.text;
|
name = tk.text;
|
||||||
|
|
||||||
if (_find_identifier(nullptr, Map<StringName, BuiltInInfo>(), name)) {
|
if (_find_identifier(nullptr, Map<StringName, BuiltInInfo>(), name)) {
|
||||||
|
|
@ -5867,11 +5937,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
_set_error("Expected ';'");
|
_set_error("Expected ';'");
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
} else {
|
} else { // varying
|
||||||
ShaderNode::Varying varying;
|
ShaderNode::Varying varying;
|
||||||
varying.type = type;
|
varying.type = type;
|
||||||
varying.precision = precision;
|
varying.precision = precision;
|
||||||
varying.interpolation = interpolation;
|
varying.interpolation = interpolation;
|
||||||
|
varying.tkpos = name_pos;
|
||||||
|
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
|
if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) {
|
||||||
|
|
@ -6238,6 +6309,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
|
||||||
|
if (E->get().stage == ShaderNode::Varying::STAGE_VERTEX || E->get().stage == ShaderNode::Varying::STAGE_FRAGMENT) {
|
||||||
|
_set_tkpos(E->get().tkpos);
|
||||||
|
_set_error(RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'"));
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,11 @@
|
||||||
|
|
||||||
class ShaderLanguage {
|
class ShaderLanguage {
|
||||||
public:
|
public:
|
||||||
|
struct TkPos {
|
||||||
|
int char_idx;
|
||||||
|
int tk_line;
|
||||||
|
};
|
||||||
|
|
||||||
enum TokenType {
|
enum TokenType {
|
||||||
TK_EMPTY,
|
TK_EMPTY,
|
||||||
TK_IDENTIFIER,
|
TK_IDENTIFIER,
|
||||||
|
|
@ -580,12 +585,24 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Varying {
|
struct Varying {
|
||||||
|
enum Stage {
|
||||||
|
STAGE_UNKNOWN,
|
||||||
|
STAGE_VERTEX, // transition stage to STAGE_VERTEX_TO_FRAGMENT or STAGE_VERTEX_TO_LIGHT, emits error if they are not used
|
||||||
|
STAGE_FRAGMENT, // transition stage to STAGE_FRAGMENT_TO_LIGHT, emits error if it's not used
|
||||||
|
STAGE_VERTEX_TO_FRAGMENT,
|
||||||
|
STAGE_VERTEX_TO_LIGHT,
|
||||||
|
STAGE_FRAGMENT_TO_LIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
Stage stage;
|
||||||
DataType type;
|
DataType type;
|
||||||
DataInterpolation interpolation;
|
DataInterpolation interpolation;
|
||||||
DataPrecision precision;
|
DataPrecision precision;
|
||||||
int array_size;
|
int array_size;
|
||||||
|
TkPos tkpos;
|
||||||
|
|
||||||
Varying() :
|
Varying() :
|
||||||
|
stage(STAGE_UNKNOWN),
|
||||||
type(TYPE_VOID),
|
type(TYPE_VOID),
|
||||||
interpolation(INTERPOLATION_FLAT),
|
interpolation(INTERPOLATION_FLAT),
|
||||||
precision(PRECISION_DEFAULT),
|
precision(PRECISION_DEFAULT),
|
||||||
|
|
@ -734,11 +751,6 @@ private:
|
||||||
StringName current_function;
|
StringName current_function;
|
||||||
bool last_const = false;
|
bool last_const = false;
|
||||||
|
|
||||||
struct TkPos {
|
|
||||||
int char_idx;
|
|
||||||
int tk_line;
|
|
||||||
};
|
|
||||||
|
|
||||||
TkPos _get_tkpos() {
|
TkPos _get_tkpos() {
|
||||||
TkPos tkp;
|
TkPos tkp;
|
||||||
tkp.char_idx = char_idx;
|
tkp.char_idx = char_idx;
|
||||||
|
|
@ -815,6 +827,8 @@ private:
|
||||||
|
|
||||||
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
|
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
|
||||||
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = nullptr);
|
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = nullptr);
|
||||||
|
bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message);
|
||||||
|
bool _validate_varying_using(ShaderNode::Varying &p_varying, String *r_message);
|
||||||
|
|
||||||
Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
|
Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
|
||||||
Node *_parse_array_constructor(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, DataType p_type, const StringName &p_struct_name, int p_array_size);
|
Node *_parse_array_constructor(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, DataType p_type, const StringName &p_struct_name, int p_array_size);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue