summaryrefslogtreecommitdiff
path: root/servers/rendering/shader_compiler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/shader_compiler.cpp')
-rw-r--r--servers/rendering/shader_compiler.cpp185
1 files changed, 148 insertions, 37 deletions
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 812d636a0b..fc644fcae6 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -32,8 +32,8 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
+#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_types.h"
-#include "servers/rendering_server.h"
#define SL ShaderLanguage
@@ -48,8 +48,8 @@ static String _mktab(int p_level) {
static String _typestr(SL::DataType p_type) {
String type = ShaderLanguage::get_datatype_name(p_type);
- if (ShaderLanguage::is_sampler_type(p_type)) {
- type = type.replace("sampler", "texture"); //we use textures instead of samplers
+ if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) {
+ type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL
}
return type;
}
@@ -289,7 +289,7 @@ String ShaderCompiler::_get_sampler_name(ShaderLanguage::TextureFilter p_filter,
return actions.sampler_array_name + "[" + itos(p_filter + (p_repeat == ShaderLanguage::REPEAT_ENABLE ? ShaderLanguage::FILTER_DEFAULT : 0)) + "]";
}
-void ShaderCompiler::_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) {
+void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const HashMap<StringName, String> &p_func_code, String &r_to_add, HashSet<StringName> &added) {
int fidx = -1;
for (int i = 0; i < p_node->functions.size(); i++) {
@@ -303,8 +303,8 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str
Vector<StringName> uses_functions;
- for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) {
- uses_functions.push_back(E->get());
+ for (const StringName &E : p_node->functions[fidx].uses_function) {
+ uses_functions.push_back(E);
}
uses_functions.sort_custom<StringName::AlphCompare>(); //ensure order is deterministic so the same shader is always produced
@@ -370,19 +370,19 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str
}
}
-static String _get_global_variable_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
+static String _get_global_shader_uniform_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
switch (p_type) {
case ShaderLanguage::TYPE_BOOL: {
- return "(" + p_buffer + "[" + p_index + "].x != 0.0)";
+ return "bool(floatBitsToUint(" + p_buffer + "[" + p_index + "].x))";
}
case ShaderLanguage::TYPE_BVEC2: {
- return "(notEqual(" + p_buffer + "[" + p_index + "].xy, vec2(0.0)))";
+ return "bvec2(floatBitsToUint(" + p_buffer + "[" + p_index + "].xy))";
}
case ShaderLanguage::TYPE_BVEC3: {
- return "(notEqual(" + p_buffer + "[" + p_index + "].xyz, vec3(0.0)))";
+ return "bvec3(floatBitsToUint(" + p_buffer + "[" + p_index + "].xyz))";
}
case ShaderLanguage::TYPE_BVEC4: {
- return "(notEqual(" + p_buffer + "[" + p_index + "].xyzw, vec4(0.0)))";
+ return "bvec4(floatBitsToUint(" + p_buffer + "[" + p_index + "].xyzw))";
}
case ShaderLanguage::TYPE_INT: {
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].x)";
@@ -498,6 +498,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
if (SL::is_sampler_type(E.value.type)) {
+ if (E.value.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
max_texture_uniforms++;
} else {
if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
@@ -537,8 +542,19 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
p_actions.uniforms->insert(uniform_name, uniform);
continue; // Instances are indexed directly, don't need index uniforms.
}
+
+ if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
+
if (SL::is_sampler_type(uniform.type)) {
- ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") uniform ";
+ // Texture layouts are different for OpenGL GLSL and Vulkan GLSL
+ if (!RS::get_singleton()->is_low_end()) {
+ ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") ";
+ }
+ ucode += "uniform ";
}
bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
@@ -567,6 +583,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
texture.name = uniform_name;
texture.hint = uniform.hint;
texture.type = uniform.type;
+ texture.use_color = uniform.use_color;
texture.filter = uniform.filter;
texture.repeat = uniform.repeat;
texture.global = uniform.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL;
@@ -681,9 +698,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
vcode += ";\n";
-
- r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode;
- r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode;
+ // GLSL ES 3.0 does not allow layout qualifiers for varyings
+ if (!RS::get_singleton()->is_low_end()) {
+ r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") ";
+ r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") ";
+ }
+ r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode;
+ r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode;
index += inc;
}
@@ -727,7 +748,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
}
- Map<StringName, String> function_code;
+ HashMap<StringName, String> function_code;
//code for functions
for (int i = 0; i < pnode->functions.size(); i++) {
@@ -740,7 +761,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
//place functions in actual code
- Set<StringName> added_funcs_per_stage[STAGE_MAX];
+ HashSet<StringName> added_funcs_per_stage[STAGE_MAX];
for (int i = 0; i < pnode->functions.size(); i++) {
SL::FunctionNode *fnode = pnode->functions[i].function;
@@ -883,22 +904,49 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
+ if (vnode->name == "SCREEN_TEXTURE") {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
} else {
if (shader->uniforms.has(vnode->name)) {
//its a uniform!
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
if (u.texture_order >= 0) {
- code = _mkid(vnode->name); //texture, use as is
+ StringName name = vnode->name;
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+ name = "SCREEN_TEXTURE";
+ if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+ name = "NORMAL_ROUGHNESS_TEXTURE";
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ name = "DEPTH_TEXTURE";
+ } else {
+ name = _mkid(vnode->name); //texture, use as is
+ }
+
+ if (p_default_actions.renames.has(name)) {
+ code = p_default_actions.renames[name];
+ } else {
+ code = name;
+ }
+
+ if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) {
+ *p_actions.usage_flag_pointers[name] = true;
+ used_flag_pointers.insert(name);
+ }
+
} else {
//a scalar or vector
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is
//global variable, this means the code points to an index to the global table
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
code = actions.base_uniform_string + _mkid(vnode->name);
@@ -994,11 +1042,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
code = actions.base_uniform_string + _mkid(anode->name); //texture, use as is
//global variable, this means the code points to an index to the global table
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
code = actions.base_uniform_string + _mkid(anode->name);
@@ -1125,8 +1173,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code += ", ";
}
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (is_texture_func && i == 1) {
- //need to map from texture to sampler in order to sample
+ if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
+ //need to map from texture to sampler in order to sample when using Vulkan GLSL
StringName texture_uniform;
bool correct_texture_uniform = false;
@@ -1146,6 +1194,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
if (correct_texture_uniform) {
+ //TODO Needs to detect screen_texture hint as well
is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
String sampler_name;
@@ -1190,7 +1239,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
code += ")";
if (is_screen_texture && actions.apply_luminance_multiplier) {
- code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))";
+ code = "(" + code + " / vec4(vec3(sc_luminance_multiplier), 1.0))";
}
} break;
case SL::OP_INDEX: {
@@ -1299,9 +1348,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
return code;
}
-ShaderLanguage::DataType ShaderCompiler::_get_variable_type(const StringName &p_type) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_type);
- return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
+ShaderLanguage::DataType ShaderCompiler::_get_global_shader_uniform_type(const StringName &p_name) {
+ RS::GlobalShaderParameterType gvt = RSG::material_storage->global_shader_parameter_get_type(p_name);
+ return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
}
Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
@@ -1309,23 +1358,81 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
info.shader_types = ShaderTypes::get_singleton()->get_types();
- info.global_variable_type_func = _get_variable_type;
+ info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
Error err = parser.compile(p_code, info);
if (err != OK) {
- Vector<String> shader = p_code.split("\n");
- for (int i = 0; i < shader.size(); i++) {
- if (i + 1 == parser.get_error_line()) {
- // Mark the error line to be visible without having to look at
- // the trace at the end.
- print_line(vformat("E%4d-> %s", i + 1, shader[i]));
+ Vector<ShaderLanguage::FilePosition> include_positions = parser.get_include_positions();
+
+ String current;
+ HashMap<String, Vector<String>> includes;
+ includes[""] = Vector<String>();
+ Vector<String> include_stack;
+ Vector<String> shader_lines = p_code.split("\n");
+
+ // Reconstruct the files.
+ for (int i = 0; i < shader_lines.size(); i++) {
+ String l = shader_lines[i];
+ if (l.begins_with("@@>")) {
+ String inc_path = l.replace_first("@@>", "");
+
+ l = "#include \"" + inc_path + "\"";
+ includes[current].append("#include \"" + inc_path + "\""); // Restore the include directive
+ include_stack.push_back(current);
+ current = inc_path;
+ includes[inc_path] = Vector<String>();
+
+ } else if (l.begins_with("@@<")) {
+ if (include_stack.size()) {
+ current = include_stack[include_stack.size() - 1];
+ include_stack.resize(include_stack.size() - 1);
+ }
+ } else {
+ includes[current].push_back(l);
+ }
+ }
+
+ // Print the files.
+ for (const KeyValue<String, Vector<String>> &E : includes) {
+ if (E.key.is_empty()) {
+ if (p_path == "") {
+ print_line("--Main Shader--");
+ } else {
+ print_line("--" + p_path + "--");
+ }
} else {
- print_line(vformat("%5d | %s", i + 1, shader[i]));
+ print_line("--" + E.key + "--");
}
+ int err_line = -1;
+ for (int i = 0; i < include_positions.size(); i++) {
+ if (include_positions[i].file == E.key) {
+ err_line = include_positions[i].line;
+ }
+ }
+ const Vector<String> &V = E.value;
+ for (int i = 0; i < V.size(); i++) {
+ if (i == err_line - 1) {
+ // Mark the error line to be visible without having to look at
+ // the trace at the end.
+ print_line(vformat("E%4d-> %s", i + 1, V[i]));
+ } else {
+ print_line(vformat("%5d | %s", i + 1, V[i]));
+ }
+ }
+ }
+
+ String file;
+ int line;
+ if (include_positions.size() > 1) {
+ file = include_positions[include_positions.size() - 1].file;
+ line = include_positions[include_positions.size() - 1].line;
+ } else {
+ file = p_path;
+ line = parser.get_error_line();
}
- _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
+ _err_print_error(nullptr, file.utf8().get_data(), line, parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
return err;
}
@@ -1337,6 +1444,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
r_gen_code.uses_fragment_time = false;
r_gen_code.uses_vertex_time = false;
r_gen_code.uses_global_textures = false;
+ r_gen_code.uses_screen_texture_mipmaps = false;
used_name_defines.clear();
used_rmode_defines.clear();
@@ -1367,8 +1475,11 @@ void ShaderCompiler::initialize(DefaultIdentifierActions p_actions) {
texture_functions.insert("textureLod");
texture_functions.insert("textureProjLod");
texture_functions.insert("textureGrad");
+ texture_functions.insert("textureProjGrad");
texture_functions.insert("textureGather");
texture_functions.insert("textureSize");
+ texture_functions.insert("textureQueryLod");
+ texture_functions.insert("textureQueryLevels");
texture_functions.insert("texelFetch");
}