You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-17 14:11:06 +00:00
Add optimizing AT_LIGHT_PASS builtin to canvas shaders
This one allows for complex shaders paired with a simple lighting shader to skip code that would otherwise be pointlessly (and wastefully) run during the light pass. You can use `if (AT_LIGHT_PASS) , negated or not, and that will be converted to a preprocessed #if when the shader is compiled. Depending on your game (number of items and lights), this can be a *significant* performance gain, or at least avoids relying on the driver's optimizing abilities.
This commit is contained in:
@@ -502,16 +502,31 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node, int p_level, bool p
|
|||||||
SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node;
|
SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node;
|
||||||
if (cfnode->flow_op == SL::FLOW_OP_IF) {
|
if (cfnode->flow_op == SL::FLOW_OP_IF) {
|
||||||
|
|
||||||
code += "if (" + dump_node_code(cfnode->statements[0], p_level) + ") {" ENDL;
|
// Help lazy drivers
|
||||||
code += dump_node_code(cfnode->statements[1], p_level + 1);
|
if (!_is_condition_preprocessable(cfnode->statements[0])) {
|
||||||
if (cfnode->statements.size() == 3) {
|
|
||||||
|
|
||||||
code += "} else {" ENDL;
|
code += "if (" + dump_node_code(cfnode->statements[0], p_level) + ") {" ENDL;
|
||||||
code += dump_node_code(cfnode->statements[2], p_level + 1);
|
code += dump_node_code(cfnode->statements[1], p_level + 1);
|
||||||
|
if (cfnode->statements.size() == 3) {
|
||||||
|
|
||||||
|
code += "} else {" ENDL;
|
||||||
|
code += dump_node_code(cfnode->statements[2], p_level + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
code += "}" ENDL;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
code += "#if (" + dump_node_code(cfnode->statements[0], p_level) + ")" ENDL;
|
||||||
|
code += dump_node_code(cfnode->statements[1], p_level);
|
||||||
|
if (cfnode->statements.size() == 3) {
|
||||||
|
|
||||||
|
code += "#else" ENDL;
|
||||||
|
code += dump_node_code(cfnode->statements[2], p_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
code += "#endif" ENDL;
|
||||||
}
|
}
|
||||||
|
|
||||||
code += "}" ENDL;
|
|
||||||
|
|
||||||
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
|
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
|
||||||
|
|
||||||
if (cfnode->statements.size()) {
|
if (cfnode->statements.size()) {
|
||||||
@@ -649,6 +664,33 @@ String ShaderCompilerGLES2::replace_string(const StringName &p_string) {
|
|||||||
return "_" + p_string.operator String();
|
return "_" + p_string.operator String();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShaderCompilerGLES2::_is_condition_preprocessable(ShaderLanguage::Node *p_condition) const {
|
||||||
|
|
||||||
|
// Check if this is a "(!)variable" expression
|
||||||
|
|
||||||
|
SL::Node *maybe_variable;
|
||||||
|
if (p_condition->type == SL::Node::TYPE_OPERATOR) {
|
||||||
|
SL::OperatorNode *op = (SL::OperatorNode *)p_condition;
|
||||||
|
if (op->op != SL::OP_NOT)
|
||||||
|
return false;
|
||||||
|
maybe_variable = op->arguments[0];
|
||||||
|
} else {
|
||||||
|
maybe_variable = p_condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maybe_variable->type != SL::Node::TYPE_VARIABLE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SL::VariableNode *variable = (SL::VariableNode *)maybe_variable;
|
||||||
|
// Hardcoding since it's currently the only;
|
||||||
|
// if more were added, they would be better characterized
|
||||||
|
// in the various ShaderLanguage::BuiltinsDef
|
||||||
|
if (variable->name != String("AT_LIGHT_PASS"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Error ShaderCompilerGLES2::compile(const String &p_code, ShaderLanguage::ShaderType p_type, String &r_code_line, String &r_globals_line, Flags &r_flags, Map<StringName, ShaderLanguage::Uniform> *r_uniforms) {
|
Error ShaderCompilerGLES2::compile(const String &p_code, ShaderLanguage::ShaderType p_type, String &r_code_line, String &r_globals_line, Flags &r_flags, Map<StringName, ShaderLanguage::Uniform> *r_uniforms) {
|
||||||
|
|
||||||
uses_texscreen = false;
|
uses_texscreen = false;
|
||||||
@@ -873,6 +915,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
|
|||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["PROJECTION_MATRIX"] = "projection_matrix";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["PROJECTION_MATRIX"] = "projection_matrix";
|
||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["EXTRA_MATRIX"] = "extra_matrix";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["EXTRA_MATRIX"] = "extra_matrix";
|
||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["TIME"] = "time";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["TIME"] = "time";
|
||||||
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["AT_LIGHT_PASS"] = "at_light_pass";
|
||||||
|
|
||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["POSITION"] = "(gl_FragCoord.xy)";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["POSITION"] = "(gl_FragCoord.xy)";
|
||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["NORMAL"] = "normal";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["NORMAL"] = "normal";
|
||||||
@@ -888,6 +931,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
|
|||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["SCREEN_UV"] = "screen_uv";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["SCREEN_UV"] = "screen_uv";
|
||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["POINT_COORD"] = "gl_PointCoord";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["POINT_COORD"] = "gl_PointCoord";
|
||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["TIME"] = "time";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["TIME"] = "time";
|
||||||
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["AT_LIGHT_PASS"] = "at_light_pass";
|
||||||
|
|
||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["POSITION"] = "(gl_FragCoord.xy)";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["POSITION"] = "(gl_FragCoord.xy)";
|
||||||
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["NORMAL"] = "normal";
|
mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["NORMAL"] = "normal";
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ private:
|
|||||||
Error compile_node(ShaderLanguage::ProgramNode *p_program);
|
Error compile_node(ShaderLanguage::ProgramNode *p_program);
|
||||||
static Error create_glsl_120_code(void *p_str, ShaderLanguage::ProgramNode *p_program);
|
static Error create_glsl_120_code(void *p_str, ShaderLanguage::ProgramNode *p_program);
|
||||||
|
|
||||||
|
bool _is_condition_preprocessable(ShaderLanguage::Node *p_condition) const;
|
||||||
|
|
||||||
bool uses_light;
|
bool uses_light;
|
||||||
bool uses_texscreen;
|
bool uses_texscreen;
|
||||||
bool uses_texpos;
|
bool uses_texpos;
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ uniform vec2 normal_flip;
|
|||||||
varying highp vec2 pos;
|
varying highp vec2 pos;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define at_light_pass 1
|
||||||
|
#else
|
||||||
|
#define at_light_pass 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_VAR1_INTERP)
|
#if defined(ENABLE_VAR1_INTERP)
|
||||||
@@ -176,6 +179,9 @@ uniform float shadow_esm_multiplier;
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define at_light_pass 1
|
||||||
|
#else
|
||||||
|
#define at_light_pass 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_TEXPIXEL_SIZE)
|
#if defined(USE_TEXPIXEL_SIZE)
|
||||||
|
|||||||
@@ -1124,6 +1124,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[] = {
|
|||||||
{ "PROJECTION_MATRIX", TYPE_MAT4 },
|
{ "PROJECTION_MATRIX", TYPE_MAT4 },
|
||||||
{ "EXTRA_MATRIX", TYPE_MAT4 },
|
{ "EXTRA_MATRIX", TYPE_MAT4 },
|
||||||
{ "TIME", TYPE_FLOAT },
|
{ "TIME", TYPE_FLOAT },
|
||||||
|
{ "AT_LIGHT_PASS", TYPE_BOOL },
|
||||||
{ NULL, TYPE_VOID },
|
{ NULL, TYPE_VOID },
|
||||||
};
|
};
|
||||||
const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[] = {
|
const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[] = {
|
||||||
@@ -1145,6 +1146,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[] =
|
|||||||
// { "SCREEN_POS", TYPE_VEC2},
|
// { "SCREEN_POS", TYPE_VEC2},
|
||||||
// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
|
// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
|
||||||
{ "TIME", TYPE_FLOAT },
|
{ "TIME", TYPE_FLOAT },
|
||||||
|
{ "AT_LIGHT_PASS", TYPE_BOOL },
|
||||||
{ NULL, TYPE_VOID }
|
{ NULL, TYPE_VOID }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user