Merge pull request #48075 from lyuma/varying_fragment_to_light_3.4

This commit is contained in:
Rémi Verschelde 2021-05-18 10:53:34 +02:00 committed by GitHub
commit 330ddc37b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 1393 additions and 209 deletions

View file

@ -1574,6 +1574,9 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
pi.name = E->get();
switch (u.type) {
case ShaderLanguage::TYPE_STRUCT: {
pi.type = Variant::ARRAY;
} break;
case ShaderLanguage::TYPE_VOID: {
pi.type = Variant::NIL;
} break;

View file

@ -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;
for (int i = 0; i < p_node->functions.size(); i++) {
@ -243,22 +243,22 @@ void ShaderCompilerGLES2::_dump_function_deps(SL::ShaderNode *p_node, const Stri
r_to_add += "\n";
StringBuffer<128> header;
header += _typestr(fnode->return_type);
header += " ";
header += _mkid(fnode->name);
header += "(";
if (fnode->return_type == SL::TYPE_STRUCT) {
header += _mkid(fnode->return_struct_name) + " " + _mkid(fnode->name) + "(";
} else {
header += _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
}
for (int i = 0; i < fnode->arguments.size(); i++) {
if (i > 0) {
header += ", ";
}
header += _qualstr(fnode->arguments[i].qualifier);
header += _prestr(fnode->arguments[i].precision);
header += _typestr(fnode->arguments[i].type);
header += " ";
header += _mkid(fnode->arguments[i].name);
if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name);
} else {
header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
}
}
header += ")\n";
@ -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;
switch (p_node->type) {
@ -311,6 +311,40 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
StringBuilder vertex_global;
StringBuilder fragment_global;
// structs
for (int i = 0; i < snode->vstructs.size(); i++) {
SL::StructNode *st = snode->vstructs[i].shader_struct;
String struct_code;
struct_code += "struct ";
struct_code += _mkid(snode->vstructs[i].name);
struct_code += " ";
struct_code += "{\n";
for (int j = 0; j < st->members.size(); j++) {
SL::MemberNode *m = st->members[j];
if (m->datatype == SL::TYPE_STRUCT) {
struct_code += _mkid(m->struct_name);
} else {
struct_code += _prestr(m->precision);
struct_code += _typestr(m->datatype);
}
struct_code += " ";
struct_code += m->name;
if (m->array_size > 0) {
struct_code += "[";
struct_code += itos(m->array_size);
struct_code += "]";
}
struct_code += ";\n";
}
struct_code += "}";
struct_code += ";\n";
vertex_global += struct_code;
fragment_global += struct_code;
}
// uniforms
for (Map<StringName, SL::ShaderNode::Uniform>::Element *E = snode->uniforms.front(); E; E = E->next()) {
@ -344,7 +378,14 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
// 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()) {
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;
varying_code += "varying ";
@ -365,13 +406,32 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
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
for (int i = 0; i < snode->vconstants.size(); i++) {
String gcode;
gcode += "const ";
gcode += _prestr(snode->vconstants[i].precision);
gcode += _typestr(snode->vconstants[i].type);
if (snode->vconstants[i].type == SL::TYPE_STRUCT) {
gcode += _mkid(snode->vconstants[i].type_str);
} else {
gcode += _prestr(snode->vconstants[i].precision);
gcode += _typestr(snode->vconstants[i].type);
}
gcode += " " + _mkid(String(snode->vconstants[i].name));
gcode += "=";
gcode += _dump_node_code(snode->vconstants[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
@ -386,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++) {
SL::FunctionNode *fnode = snode->functions[i].function;
function = fnode;
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 = nullptr;
}
Set<StringName> added_vertex;
@ -396,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++) {
SL::FunctionNode *fnode = snode->functions[i].function;
function = fnode;
current_func_name = fnode->name;
if (fnode->name == vertex_name) {
@ -410,13 +474,16 @@ 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);
r_gen_code.light = function_code[light_name];
}
function = nullptr;
}
r_gen_code.vertex_global = vertex_global.as_string();
r_gen_code.fragment_global = fragment_global.as_string();
} break;
case SL::Node::TYPE_STRUCT: {
} break;
case SL::Node::TYPE_FUNCTION: {
} break;
@ -453,8 +520,12 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (var_dec_node->is_const) {
declaration += "const ";
}
declaration += _prestr(var_dec_node->precision);
declaration += _typestr(var_dec_node->datatype);
if (var_dec_node->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(var_dec_node->struct_name);
} else {
declaration += _prestr(var_dec_node->precision);
declaration += _typestr(var_dec_node->datatype);
}
for (int i = 0; i < var_dec_node->declarations.size(); i++) {
if (i > 0) {
@ -476,6 +547,19 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
case SL::Node::TYPE_VARIABLE: {
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)) {
*p_actions.write_flag_pointers[var_node->name] = true;
@ -502,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)) {
code += p_default_actions.renames[var_node->name];
} else if (use_fragment_varying) {
code += "frag_to_light." + _mkid(var_node->name);
} else {
code += _mkid(var_node->name);
}
@ -515,13 +601,36 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
}
}
} break;
case SL::Node::TYPE_ARRAY_CONSTRUCT: {
SL::ArrayConstructNode *arr_con_node = (SL::ArrayConstructNode *)p_node;
int sz = arr_con_node->initializer.size();
if (arr_con_node->datatype == SL::TYPE_STRUCT) {
code += _mkid(arr_con_node->struct_name);
} else {
code += _typestr(arr_con_node->datatype);
}
code += "[";
code += itos(arr_con_node->initializer.size());
code += "]";
code += "(";
for (int i = 0; i < sz; i++) {
code += _dump_node_code(arr_con_node->initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (i != sz - 1) {
code += ", ";
}
}
code += ")";
} break;
case SL::Node::TYPE_ARRAY_DECLARATION: {
SL::ArrayDeclarationNode *arr_dec_node = (SL::ArrayDeclarationNode *)p_node;
StringBuffer<> declaration;
declaration += _prestr(arr_dec_node->precision);
declaration += _typestr(arr_dec_node->datatype);
if (arr_dec_node->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(arr_dec_node->struct_name);
} else {
declaration += _prestr(arr_dec_node->precision);
declaration += _typestr(arr_dec_node->datatype);
}
for (int i = 0; i < arr_dec_node->declarations.size(); i++) {
if (i > 0) {
declaration += ",";
@ -539,6 +648,23 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
} break;
case SL::Node::TYPE_ARRAY: {
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)) {
*p_actions.write_flag_pointers[arr_node->name] = true;
@ -565,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)) {
code += p_default_actions.renames[arr_node->name];
} else if (use_fragment_varying) {
code += "frag_to_light." + _mkid(arr_node->name);
} else {
code += _mkid(arr_node->name);
}
@ -640,12 +768,14 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
} break;
case SL::OP_CALL:
case SL::OP_STRUCT:
case SL::OP_CONSTRUCT: {
ERR_FAIL_COND_V(op_node->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
SL::VariableNode *var_node = (SL::VariableNode *)op_node->arguments[0];
if (op_node->op == SL::OP_CONSTRUCT) {
if (op_node->op == SL::OP_STRUCT) {
code += _mkid(var_node->name);
} else if (op_node->op == SL::OP_CONSTRUCT) {
code += var_node->name;
} else {
if (var_node->name == "texture") {
@ -840,6 +970,11 @@ 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 += ".";
code += member_node->name;
if (member_node->index_expression != nullptr) {
code += "[";
code += _dump_node_code(member_node->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
}
} break;
}
@ -874,8 +1009,11 @@ Error ShaderCompilerGLES2::compile(VS::ShaderMode p_mode, const String &p_code,
used_name_defines.clear();
used_rmode_defines.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;
}

View file

@ -73,9 +73,11 @@ private:
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);
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);
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(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 vertex_name;
StringName fragment_name;
@ -86,6 +88,7 @@ private:
Set<StringName> used_flag_pointers;
Set<StringName> used_rmode_defines;
Set<StringName> internal_functions;
Set<StringName> fragment_varyings;
DefaultIdentifierActions actions[VS::SHADER_MAX];

View file

@ -2355,6 +2355,9 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn
ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[E->get()];
pi.name = E->get();
switch (u.type) {
case ShaderLanguage::TYPE_STRUCT:
pi.type = Variant::ARRAY;
break;
case ShaderLanguage::TYPE_VOID:
pi.type = Variant::NIL;
break;

View file

@ -112,6 +112,8 @@ static int _get_datatype_size(SL::DataType p_type) {
return 16;
case SL::TYPE_SAMPLEREXT:
return 16;
case SL::TYPE_STRUCT:
return 0;
}
ERR_FAIL_V(0);
@ -181,6 +183,8 @@ static int _get_datatype_alignment(SL::DataType p_type) {
return 16;
case SL::TYPE_SAMPLEREXT:
return 16;
case SL::TYPE_STRUCT:
return 0;
}
ERR_FAIL_V(0);
@ -327,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;
for (int i = 0; i < p_node->functions.size(); i++) {
@ -360,12 +364,20 @@ void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const Stri
r_to_add += "\n";
String header;
header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
if (fnode->return_type == SL::TYPE_STRUCT) {
header = _mkid(fnode->return_struct_name) + " " + _mkid(fnode->name) + "(";
} else {
header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
}
for (int i = 0; i < fnode->arguments.size(); i++) {
if (i > 0) {
header += ", ";
}
header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
if (fnode->arguments[i].type == SL::TYPE_STRUCT) {
header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name);
} else {
header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
}
}
header += ")\n";
@ -376,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;
switch (p_node->type) {
@ -399,6 +411,40 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
}
}
// structs
for (int i = 0; i < pnode->vstructs.size(); i++) {
SL::StructNode *st = pnode->vstructs[i].shader_struct;
String struct_code;
struct_code += "struct ";
struct_code += _mkid(pnode->vstructs[i].name);
struct_code += " ";
struct_code += "{\n";
for (int j = 0; j < st->members.size(); j++) {
SL::MemberNode *m = st->members[j];
if (m->datatype == SL::TYPE_STRUCT) {
struct_code += _mkid(m->struct_name);
} else {
struct_code += _prestr(m->precision);
struct_code += _typestr(m->datatype);
}
struct_code += " ";
struct_code += m->name;
if (m->array_size > 0) {
struct_code += "[";
struct_code += itos(m->array_size);
struct_code += "]";
}
struct_code += ";\n";
}
struct_code += "}";
struct_code += ";\n";
r_gen_code.vertex_global += struct_code;
r_gen_code.fragment_global += struct_code;
}
int max_texture_uniforms = 0;
int max_uniforms = 0;
@ -475,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;
}
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()) {
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 interp_mode = _interpstr(E->get().interpolation);
vcode += _prestr(E->get().precision);
@ -491,11 +544,30 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
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++) {
String gcode;
gcode += "const ";
gcode += _prestr(pnode->vconstants[i].precision);
gcode += _typestr(pnode->vconstants[i].type);
if (pnode->vconstants[i].type == SL::TYPE_STRUCT) {
gcode += _mkid(pnode->vconstants[i].type_str);
} else {
gcode += _prestr(pnode->vconstants[i].precision);
gcode += _typestr(pnode->vconstants[i].type);
}
gcode += " " + _mkid(String(pnode->vconstants[i].name));
gcode += "=";
gcode += _dump_node_code(pnode->vconstants[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
@ -509,8 +581,10 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
//code for functions
for (int i = 0; i < pnode->functions.size(); i++) {
SL::FunctionNode *fnode = pnode->functions[i].function;
function = fnode;
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 = nullptr;
}
//place functions in actual code
@ -521,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++) {
SL::FunctionNode *fnode = pnode->functions[i].function;
function = fnode;
current_func_name = fnode->name;
if (fnode->name == vertex_name) {
@ -537,10 +613,14 @@ 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);
r_gen_code.light = function_code[light_name];
}
function = nullptr;
}
//code+=dump_node_code(pnode->body,p_level);
} break;
case SL::Node::TYPE_STRUCT: {
} break;
case SL::Node::TYPE_FUNCTION: {
} break;
case SL::Node::TYPE_BLOCK: {
@ -572,8 +652,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (vdnode->is_const) {
declaration += "const ";
}
declaration += _prestr(vdnode->precision);
declaration += _typestr(vdnode->datatype);
if (vdnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(vdnode->struct_name);
} else {
declaration += _prestr(vdnode->precision);
declaration += _typestr(vdnode->datatype);
}
for (int i = 0; i < vdnode->declarations.size(); i++) {
if (i > 0) {
declaration += ",";
@ -591,6 +675,19 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
} break;
case SL::Node::TYPE_VARIABLE: {
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)) {
*p_actions.write_flag_pointers[vnode->name] = true;
@ -612,6 +709,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
} else if (use_fragment_varying) {
code = "frag_to_light." + _mkid(vnode->name);
} else {
code = _mkid(vnode->name);
}
@ -626,6 +725,26 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
}
} break;
case SL::Node::TYPE_ARRAY_CONSTRUCT: {
SL::ArrayConstructNode *acnode = (SL::ArrayConstructNode *)p_node;
int sz = acnode->initializer.size();
if (acnode->datatype == SL::TYPE_STRUCT) {
code += _mkid(acnode->struct_name);
} else {
code += _typestr(acnode->datatype);
}
code += "[";
code += itos(acnode->initializer.size());
code += "]";
code += "(";
for (int i = 0; i < sz; i++) {
code += _dump_node_code(acnode->initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (i != sz - 1) {
code += ", ";
}
}
code += ")";
} break;
case SL::Node::TYPE_ARRAY_DECLARATION: {
SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node;
@ -633,8 +752,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (adnode->is_const) {
declaration += "const ";
}
declaration += _prestr(adnode->precision);
declaration += _typestr(adnode->datatype);
if (adnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(adnode->struct_name);
} else {
declaration += _prestr(adnode->precision);
declaration += _typestr(adnode->datatype);
}
for (int i = 0; i < adnode->declarations.size(); i++) {
if (i > 0) {
declaration += ",";
@ -648,7 +771,11 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
int sz = adnode->declarations[i].initializer.size();
if (sz > 0) {
declaration += "=";
declaration += _typestr(adnode->datatype);
if (adnode->datatype == SL::TYPE_STRUCT) {
declaration += _mkid(adnode->struct_name);
} else {
declaration += _typestr(adnode->datatype);
}
declaration += "[";
declaration += itos(sz);
declaration += "]";
@ -667,6 +794,23 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
} break;
case SL::Node::TYPE_ARRAY: {
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)) {
*p_actions.write_flag_pointers[anode->name] = true;
@ -688,6 +832,8 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (p_default_actions.renames.has(anode->name)) {
code = p_default_actions.renames[anode->name];
} else if (use_fragment_varying) {
code = "frag_to_light." + _mkid(anode->name);
} else {
code = _mkid(anode->name);
}
@ -695,12 +841,13 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (anode->call_expression != nullptr) {
code += ".";
code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning, false);
}
if (anode->index_expression != nullptr) {
} else if (anode->index_expression != nullptr) {
code += "[";
code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
} else if (anode->assign_expression != nullptr) {
code += "=";
code += _dump_node_code(anode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
}
if (anode->name == time_name) {
@ -747,12 +894,15 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op);
break;
case SL::OP_CALL:
case SL::OP_STRUCT:
case SL::OP_CONSTRUCT: {
ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String());
SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0];
if (onode->op == SL::OP_CONSTRUCT) {
if (onode->op == SL::OP_STRUCT) {
code += _mkid(vnode->name);
} else if (onode->op == SL::OP_CONSTRUCT) {
code += String(vnode->name);
} else {
if (internal_functions.has(vnode->name)) {
@ -861,7 +1011,14 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
case SL::Node::TYPE_MEMBER: {
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;
if (mnode->index_expression != nullptr) {
code += "[";
code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += "]";
} else if (mnode->assign_expression != nullptr) {
code += "=";
code += _dump_node_code(mnode->assign_expression, p_level, r_gen_code, p_actions, p_default_actions, true, false);
}
} break;
}
@ -893,8 +1050,11 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String &p_code,
used_name_defines.clear();
used_rmode_defines.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?
int md = sizeof(float) * 4;

View file

@ -75,9 +75,11 @@ private:
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);
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);
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(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 vertex_name;
StringName fragment_name;
@ -88,6 +90,7 @@ private:
Set<StringName> used_flag_pointers;
Set<StringName> used_rmode_defines;
Set<StringName> internal_functions;
Set<StringName> fragment_varyings;
DefaultIdentifierActions actions[VS::SHADER_MAX];

View file

@ -174,6 +174,8 @@ static String dump_node_code(SL::Node *p_node, int p_level) {
//code+=dump_node_code(pnode->body,p_level);
} break;
case SL::Node::TYPE_STRUCT: {
} break;
case SL::Node::TYPE_FUNCTION: {
} break;
case SL::Node::TYPE_BLOCK: {
@ -212,6 +214,9 @@ static String dump_node_code(SL::Node *p_node, int p_level) {
case SL::Node::TYPE_ARRAY_DECLARATION: {
// FIXME: Implement
} break;
case SL::Node::TYPE_ARRAY_CONSTRUCT: {
// FIXME: Implement
} break;
case SL::Node::TYPE_CONSTANT: {
SL::ConstantNode *cnode = (SL::ConstantNode *)p_node;
return get_constant_text(cnode->datatype, cnode->values);

File diff suppressed because it is too large Load diff

View file

@ -41,6 +41,11 @@
class ShaderLanguage {
public:
struct TkPos {
int char_idx;
int tk_line;
};
enum TokenType {
TK_EMPTY,
TK_IDENTIFIER,
@ -82,6 +87,7 @@ public:
TK_INTERPOLATION_FLAT,
TK_INTERPOLATION_SMOOTH,
TK_CONST,
TK_STRUCT,
TK_PRECISION_LOW,
TK_PRECISION_MID,
TK_PRECISION_HIGH,
@ -201,6 +207,7 @@ public:
TYPE_USAMPLER3D,
TYPE_SAMPLERCUBE,
TYPE_SAMPLEREXT,
TYPE_STRUCT,
};
enum DataPrecision {
@ -256,6 +263,7 @@ public:
OP_POST_DECREMENT,
OP_CALL,
OP_CONSTRUCT,
OP_STRUCT,
OP_INDEX,
OP_MAX
};
@ -300,11 +308,15 @@ public:
TYPE_MEMBER,
TYPE_ARRAY,
TYPE_ARRAY_DECLARATION,
TYPE_ARRAY_CONSTRUCT,
TYPE_STRUCT,
};
Type type;
virtual DataType get_datatype() const { return TYPE_VOID; }
virtual String get_datatype_name() const { return ""; }
Node(Type t) :
next(nullptr),
type(t) {}
@ -325,20 +337,25 @@ public:
DataType return_cache;
DataPrecision return_precision_cache;
Operator op;
StringName struct_name;
Vector<Node *> arguments;
virtual DataType get_datatype() const { return return_cache; }
virtual String get_datatype_name() const { return String(struct_name); }
OperatorNode() :
Node(TYPE_OPERATOR),
return_cache(TYPE_VOID),
return_precision_cache(PRECISION_DEFAULT),
op(OP_EQUAL) {}
op(OP_EQUAL),
struct_name("") {}
};
struct VariableNode : public Node {
DataType datatype_cache;
StringName name;
StringName struct_name;
virtual DataType get_datatype() const { return datatype_cache; }
virtual String get_datatype_name() const { return String(struct_name); }
bool is_const;
VariableNode() :
@ -350,6 +367,7 @@ public:
struct VariableDeclarationNode : public Node {
DataPrecision precision;
DataType datatype;
String struct_name;
bool is_const;
struct Declaration {
@ -369,24 +387,40 @@ public:
struct ArrayNode : public Node {
DataType datatype_cache;
StringName struct_name;
StringName name;
Node *index_expression;
Node *call_expression;
Node *assign_expression;
bool is_const;
virtual DataType get_datatype() const { return datatype_cache; }
virtual String get_datatype_name() const { return String(struct_name); }
ArrayNode() :
Node(TYPE_ARRAY),
datatype_cache(TYPE_VOID),
index_expression(nullptr),
call_expression(nullptr),
assign_expression(nullptr),
is_const(false) {}
};
struct ArrayConstructNode : public Node {
DataType datatype;
String struct_name;
Vector<Node *> initializer;
ArrayConstructNode() :
Node(TYPE_ARRAY_CONSTRUCT),
datatype(TYPE_VOID) {
}
};
struct ArrayDeclarationNode : public Node {
DataPrecision precision;
DataType datatype;
String struct_name;
bool is_const;
struct Declaration {
@ -441,6 +475,7 @@ public:
struct Variable {
DataType type;
StringName struct_name;
DataPrecision precision;
int line; //for completion
int array_size;
@ -472,17 +507,35 @@ public:
struct MemberNode : public Node {
DataType basetype;
StringName base_struct_name;
DataPrecision precision;
DataType datatype;
int array_size;
StringName struct_name;
StringName name;
Node *owner;
Node *index_expression;
Node *assign_expression;
bool has_swizzling_duplicates;
virtual DataType get_datatype() const { return datatype; }
virtual String get_datatype_name() const { return String(struct_name); }
MemberNode() :
Node(TYPE_MEMBER),
basetype(TYPE_VOID),
datatype(TYPE_VOID),
owner(nullptr) {}
array_size(0),
owner(nullptr),
index_expression(nullptr),
assign_expression(nullptr),
has_swizzling_duplicates(false) {}
};
struct StructNode : public Node {
List<MemberNode *> members;
StructNode() :
Node(TYPE_STRUCT) {}
};
struct FunctionNode : public Node {
@ -490,11 +543,13 @@ public:
ArgumentQualifier qualifier;
StringName name;
DataType type;
StringName type_str;
DataPrecision precision;
};
StringName name;
DataType return_type;
StringName return_struct_name;
DataPrecision return_precision;
Vector<Argument> arguments;
BlockNode *body;
@ -512,6 +567,7 @@ public:
struct Constant {
StringName name;
DataType type;
StringName type_str;
DataPrecision precision;
ConstantNode *initializer;
};
@ -523,13 +579,30 @@ public:
bool callable;
};
struct Struct {
StringName name;
StructNode *shader_struct;
};
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;
DataInterpolation interpolation;
DataPrecision precision;
int array_size;
TkPos tkpos;
Varying() :
stage(STAGE_UNKNOWN),
type(TYPE_VOID),
interpolation(INTERPOLATION_FLAT),
precision(PRECISION_DEFAULT),
@ -573,10 +646,12 @@ public:
Map<StringName, Constant> constants;
Map<StringName, Varying> varyings;
Map<StringName, Uniform> uniforms;
Map<StringName, Struct> structs;
Vector<StringName> render_modes;
Vector<Function> functions;
Vector<Constant> vconstants;
Vector<Struct> vstructs;
ShaderNode() :
Node(TYPE_SHADER) {}
@ -603,6 +678,7 @@ public:
COMPLETION_FUNCTION_CALL,
COMPLETION_CALL_ARGUMENTS,
COMPLETION_INDEX,
COMPLETION_STRUCT,
};
struct Token {
@ -673,11 +749,7 @@ private:
int tk_line;
StringName current_function;
struct TkPos {
int char_idx;
int tk_line;
};
bool last_const = false;
TkPos _get_tkpos() {
TkPos tkp;
@ -718,7 +790,7 @@ private:
IDENTIFIER_CONSTANT,
};
bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr);
bool _find_identifier(const BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr);
bool _is_operator_assign(Operator p_op) const;
bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = nullptr);
bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr);
@ -743,6 +815,7 @@ private:
DataType completion_base;
SubClassTag completion_class;
StringName completion_function;
StringName completion_struct;
int completion_argument;
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
@ -750,11 +823,15 @@ private:
static const BuiltinFuncOutArgs builtin_func_out_args[];
Error _validate_datatype(DataType p_type);
bool _compare_datatypes_in_nodes(Node *a, Node *b) const;
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
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 _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_array_constructor(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, DataType p_type, const StringName &p_struct_name, int p_array_size);
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);