Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structs and fragment-to-light varyings for 3.4 #48075

Merged
merged 7 commits into from
May 18, 2021
3 changes: 3 additions & 0 deletions drivers/gles2/rasterizer_storage_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
184 changes: 161 additions & 23 deletions drivers/gles2/shader_compiler_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand Down Expand Up @@ -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";
Expand All @@ -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) {
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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 ";
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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) {
Expand All @@ -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;

Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand All @@ -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);
}
Expand All @@ -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 += ",";
Expand All @@ -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;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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") {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down
7 changes: 5 additions & 2 deletions drivers/gles2/shader_compiler_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,11 @@ class ShaderCompilerGLES2 {
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;
Expand All @@ -86,6 +88,7 @@ class ShaderCompilerGLES2 {
Set<StringName> used_flag_pointers;
Set<StringName> used_rmode_defines;
Set<StringName> internal_functions;
Set<StringName> fragment_varyings;

DefaultIdentifierActions actions[VS::SHADER_MAX];

Expand Down
3 changes: 3 additions & 0 deletions drivers/gles3/rasterizer_storage_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading