diff options
Diffstat (limited to 'servers/rendering')
-rw-r--r-- | servers/rendering/renderer_rd/renderer_storage_rd.cpp | 15 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/shader_compiler_rd.cpp | 81 | ||||
-rw-r--r-- | servers/rendering/shader_language.cpp | 324 | ||||
-rw-r--r-- | servers/rendering/shader_language.h | 77 | ||||
-rw-r--r-- | servers/rendering/shader_types.cpp | 110 | ||||
-rw-r--r-- | servers/rendering/shader_types.h | 4 | ||||
-rw-r--r-- | servers/rendering/shader_warnings.cpp | 12 | ||||
-rw-r--r-- | servers/rendering/shader_warnings.h | 7 |
8 files changed, 353 insertions, 277 deletions
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 321d86ffda..5e9b66ed1f 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -2655,13 +2655,13 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName uint32_t size = 0U; // The following code enforces a 16-byte alignment of uniform arrays. if (E.value.array_size > 0) { - size = ShaderLanguage::get_type_size(E.value.type) * E.value.array_size; + size = ShaderLanguage::get_datatype_size(E.value.type) * E.value.array_size; int m = (16 * E.value.array_size); if ((size % m) != 0U) { size += m - (size % m); } } else { - size = ShaderLanguage::get_type_size(E.value.type); + size = ShaderLanguage::get_datatype_size(E.value.type); } ERR_CONTINUE(offset + size > p_buffer_size); #endif @@ -2818,12 +2818,15 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NONE: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); - } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: { + rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: { + rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + } break; default: { rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); } break; @@ -9234,7 +9237,7 @@ void RendererStorageRD::_update_global_variables() { for (uint32_t i = 0; i < total_regions; i++) { if (global_variables.buffer_dirty_regions[i]) { - RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, global_variables.buffer_values); + RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]); global_variables.buffer_dirty_regions[i] = false; } diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index 794c999d1d..9d1d535eba 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -54,81 +54,6 @@ static String _typestr(SL::DataType p_type) { return type; } -static int _get_datatype_size(SL::DataType p_type) { - switch (p_type) { - case SL::TYPE_VOID: - return 0; - case SL::TYPE_BOOL: - return 4; - case SL::TYPE_BVEC2: - return 8; - case SL::TYPE_BVEC3: - return 12; - case SL::TYPE_BVEC4: - return 16; - case SL::TYPE_INT: - return 4; - case SL::TYPE_IVEC2: - return 8; - case SL::TYPE_IVEC3: - return 12; - case SL::TYPE_IVEC4: - return 16; - case SL::TYPE_UINT: - return 4; - case SL::TYPE_UVEC2: - return 8; - case SL::TYPE_UVEC3: - return 12; - case SL::TYPE_UVEC4: - return 16; - case SL::TYPE_FLOAT: - return 4; - case SL::TYPE_VEC2: - return 8; - case SL::TYPE_VEC3: - return 12; - case SL::TYPE_VEC4: - return 16; - case SL::TYPE_MAT2: - return 32; // 4 * 4 + 4 * 4 - case SL::TYPE_MAT3: - return 48; // 4 * 4 + 4 * 4 + 4 * 4 - case SL::TYPE_MAT4: - return 64; - case SL::TYPE_SAMPLER2D: - return 16; - case SL::TYPE_ISAMPLER2D: - return 16; - case SL::TYPE_USAMPLER2D: - return 16; - case SL::TYPE_SAMPLER2DARRAY: - return 16; - case SL::TYPE_ISAMPLER2DARRAY: - return 16; - case SL::TYPE_USAMPLER2DARRAY: - return 16; - case SL::TYPE_SAMPLER3D: - return 16; - case SL::TYPE_ISAMPLER3D: - return 16; - case SL::TYPE_USAMPLER3D: - return 16; - case SL::TYPE_SAMPLERCUBE: - return 16; - case SL::TYPE_SAMPLERCUBEARRAY: - return 16; - case SL::TYPE_STRUCT: - return 0; - - case SL::TYPE_MAX: { - ERR_FAIL_V(0); - }; - } - - ERR_FAIL_V(0); -} - static int _get_datatype_alignment(SL::DataType p_type) { switch (p_type) { case SL::TYPE_VOID: @@ -658,12 +583,12 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge uniform_defines.write[uniform.order] = ucode; if (is_buffer_global) { //globals are indices into the global table - uniform_sizes.write[uniform.order] = _get_datatype_size(ShaderLanguage::TYPE_UINT); + uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(ShaderLanguage::TYPE_UINT); uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT); } else { // The following code enforces a 16-byte alignment of uniform arrays. if (uniform.array_size > 0) { - int size = _get_datatype_size(uniform.type) * uniform.array_size; + int size = ShaderLanguage::get_datatype_size(uniform.type) * uniform.array_size; int m = (16 * uniform.array_size); if ((size % m) != 0) { size += m - (size % m); @@ -671,7 +596,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge uniform_sizes.write[uniform.order] = size; uniform_alignments.write[uniform.order] = 16; } else { - uniform_sizes.write[uniform.order] = _get_datatype_size(uniform.type); + uniform_sizes.write[uniform.order] = ShaderLanguage::get_datatype_size(uniform.type); uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type); } } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 0127fcf813..4ac9d8db64 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -690,7 +690,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { } if (!str.is_valid_int()) { if (uint_suffix_found) { - return _make_token(TK_ERROR, "Invalid (usigned integer) numeric constant"); + return _make_token(TK_ERROR, "Invalid (unsigned integer) numeric constant"); } else { return _make_token(TK_ERROR, "Invalid (integer) numeric constant"); } @@ -977,8 +977,6 @@ void ShaderLanguage::clear() { completion_base = TYPE_VOID; completion_base_array = false; - unknown_varying_usages.clear(); - #ifdef DEBUG_ENABLED used_constants.clear(); used_varyings.clear(); @@ -3868,55 +3866,77 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform return pi; } -uint32_t ShaderLanguage::get_type_size(DataType p_type) { +uint32_t ShaderLanguage::get_datatype_size(ShaderLanguage::DataType p_type) { switch (p_type) { case TYPE_VOID: return 0; case TYPE_BOOL: - case TYPE_INT: - case TYPE_UINT: - case TYPE_FLOAT: return 4; case TYPE_BVEC2: - case TYPE_IVEC2: - case TYPE_UVEC2: - case TYPE_VEC2: return 8; case TYPE_BVEC3: - case TYPE_IVEC3: - case TYPE_UVEC3: - case TYPE_VEC3: return 12; case TYPE_BVEC4: + return 16; + case TYPE_INT: + return 4; + case TYPE_IVEC2: + return 8; + case TYPE_IVEC3: + return 12; case TYPE_IVEC4: + return 16; + case TYPE_UINT: + return 4; + case TYPE_UVEC2: + return 8; + case TYPE_UVEC3: + return 12; case TYPE_UVEC4: + return 16; + case TYPE_FLOAT: + return 4; + case TYPE_VEC2: + return 8; + case TYPE_VEC3: + return 12; case TYPE_VEC4: return 16; case TYPE_MAT2: - return 8; + return 32; // 4 * 4 + 4 * 4 case TYPE_MAT3: - return 12; + return 48; // 4 * 4 + 4 * 4 + 4 * 4 case TYPE_MAT4: - return 16; + return 64; case TYPE_SAMPLER2D: + return 16; case TYPE_ISAMPLER2D: + return 16; case TYPE_USAMPLER2D: + return 16; case TYPE_SAMPLER2DARRAY: + return 16; case TYPE_ISAMPLER2DARRAY: + return 16; case TYPE_USAMPLER2DARRAY: + return 16; case TYPE_SAMPLER3D: + return 16; case TYPE_ISAMPLER3D: + return 16; case TYPE_USAMPLER3D: + return 16; case TYPE_SAMPLERCUBE: + return 16; case TYPE_SAMPLERCUBEARRAY: - return 4; //not really, but useful for indices + return 16; case TYPE_STRUCT: - // FIXME: Implement. - return 0; - case ShaderLanguage::TYPE_MAX: return 0; + case TYPE_MAX: { + ERR_FAIL_V(0); + }; } - return 0; + ERR_FAIL_V(0); } void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { @@ -4122,43 +4142,6 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St return true; } -bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) { - switch (p_varying.stage) { - case ShaderNode::Varying::STAGE_UNKNOWN: - VaryingUsage usage; - usage.var = &p_varying; - usage.line = tk_line; - unknown_varying_usages.push_back(usage); - break; - case ShaderNode::Varying::STAGE_VERTEX: - if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) { - p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT; - } - break; - case ShaderNode::Varying::STAGE_FRAGMENT: - if (current_function == varying_function_names.light) { - p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT; - } - break; - default: - break; - } - return true; -} - -bool ShaderLanguage::_check_varying_usages(int *r_error_line, String *r_error_message) const { - for (const List<ShaderLanguage::VaryingUsage>::Element *E = unknown_varying_usages.front(); E; E = E->next()) { - ShaderNode::Varying::Stage stage = E->get().var->stage; - if (stage != ShaderNode::Varying::STAGE_UNKNOWN && stage != ShaderNode::Varying::STAGE_VERTEX && stage != ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT) { - *r_error_line = E->get().line; - *r_error_message = RTR("Fragment-stage varying could not been accessed in custom function!"); - return false; - } - } - - return true; -} - bool ShaderLanguage::_check_node_constness(const Node *p_node) const { switch (p_node->type) { case Node::TYPE_OPERATOR: { @@ -4991,55 +4974,104 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons for (int i = 0; i < call_function->arguments.size(); i++) { int argidx = i + 1; if (argidx < func->arguments.size()) { - if (call_function->arguments[i].is_const || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) { - bool error = false; - Node *n = func->arguments[argidx]; - if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) { - if (!call_function->arguments[i].is_const) { + bool error = false; + Node *n = func->arguments[argidx]; + ArgumentQualifier arg_qual = call_function->arguments[i].qualifier; + bool is_out_arg = arg_qual != ArgumentQualifier::ARGUMENT_QUALIFIER_IN; + + if (n->type == Node::TYPE_VARIABLE || n->type == Node::TYPE_ARRAY) { + StringName varname; + + if (n->type == Node::TYPE_VARIABLE) { + VariableNode *vn = static_cast<VariableNode *>(n); + varname = vn->name; + } else { // TYPE_ARRAY + ArrayNode *an = static_cast<ArrayNode *>(n); + varname = an->name; + } + + if (shader->varyings.has(varname)) { + switch (shader->varyings[varname].stage) { + case ShaderNode::Varying::STAGE_UNKNOWN: { + _set_error(vformat("Varying '%s' must be assigned in the vertex or fragment function first!", varname)); + return nullptr; + } + case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT: + [[fallthrough]]; + case ShaderNode::Varying::STAGE_VERTEX: + if (is_out_arg && current_function != varying_function_names.vertex) { // inout/out + error = true; + } + break; + case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT: + [[fallthrough]]; + case ShaderNode::Varying::STAGE_FRAGMENT: + if (!is_out_arg) { + if (current_function != varying_function_names.fragment && current_function != varying_function_names.light) { + error = true; + } + } else if (current_function != varying_function_names.fragment) { // inout/out + error = true; + } + break; + default: + break; + } + + if (error) { + _set_error(vformat("Varying '%s' cannot be passed for the '%s' parameter in that context!", varname, _get_qualifier_str(arg_qual))); + return nullptr; + } + } + } + + bool is_const_arg = call_function->arguments[i].is_const; + + if (is_const_arg || is_out_arg) { + StringName varname; + + if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR || n->type == Node::TYPE_ARRAY_CONSTRUCT) { + if (!is_const_arg) { error = true; } } else if (n->type == Node::TYPE_ARRAY) { ArrayNode *an = static_cast<ArrayNode *>(n); - if (an->call_expression != nullptr || an->is_const) { + if (!is_const_arg && (an->call_expression != nullptr || an->is_const)) { error = true; } + varname = an->name; } else if (n->type == Node::TYPE_VARIABLE) { VariableNode *vn = static_cast<VariableNode *>(n); - if (vn->is_const) { + if (vn->is_const && !is_const_arg) { error = true; - } else { - StringName varname = vn->name; - if (shader->constants.has(varname)) { - error = true; - } else if (shader->uniforms.has(varname)) { - error = true; - } else { - if (shader->varyings.has(varname)) { - _set_error(vformat("Varyings cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier))); - return nullptr; - } - if (p_function_info.built_ins.has(varname)) { - BuiltInInfo info = p_function_info.built_ins[varname]; - if (info.constant) { - error = true; - } - } - } } + varname = vn->name; } else if (n->type == Node::TYPE_MEMBER) { MemberNode *mn = static_cast<MemberNode *>(n); - if (mn->basetype_const) { + if (mn->basetype_const && is_out_arg) { + error = true; + } + } + if (!error && varname != StringName()) { + if (shader->constants.has(varname)) { error = true; + } else if (shader->uniforms.has(varname)) { + error = true; + } else if (p_function_info.built_ins.has(varname)) { + BuiltInInfo info = p_function_info.built_ins[varname]; + if (info.constant) { + error = true; + } } } + if (error) { - _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier))); + _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(arg_qual))); return nullptr; } } if (is_sampler_type(call_function->arguments[i].type)) { //let's see where our argument comes from - Node *n = func->arguments[argidx]; ERR_CONTINUE(n->type != Node::TYPE_VARIABLE); //bug? this should always be a variable VariableNode *vn = static_cast<VariableNode *>(n); StringName varname = vn->name; @@ -5143,9 +5175,21 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } } else { - if (!_validate_varying_using(shader->varyings[identifier], &error)) { - _set_error(error); - return nullptr; + ShaderNode::Varying &var = shader->varyings[identifier]; + + switch (var.stage) { + case ShaderNode::Varying::STAGE_VERTEX: + if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) { + var.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT; + } + break; + case ShaderNode::Varying::STAGE_FRAGMENT: + if (current_function == varying_function_names.light) { + var.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT; + } + break; + default: + break; } } } @@ -5287,7 +5331,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Expected expression, found: " + get_token_text(tk)); return nullptr; } else { -#if DEBUG_ENABLED +#ifdef DEBUG_ENABLED if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning."); } @@ -6098,7 +6142,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons ERR_FAIL_V(nullptr); //unexpected operator } -#if DEBUG_ENABLED +#ifdef DEBUG_ENABLED if (check_warnings && HAS_WARNING(ShaderWarning::FLOAT_COMPARISON_FLAG) && (op == OP_EQUAL || op == OP_NOT_EQUAL) && (!expression[i - 1].is_op && !expression[i + 1].is_op) && (expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT)) { @@ -7510,7 +7554,7 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) { return OK; } -Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types) { +Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types) { Token tk = _get_token(); TkPos prev_pos; @@ -7549,11 +7593,17 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int texture_binding = 0; int uniforms = 0; int instance_index = 0; +#ifdef DEBUG_ENABLED + int uniform_buffer_size = 0; + int max_uniform_buffer_size = RenderingDevice::get_singleton()->limit_get(RenderingDevice::LIMIT_MAX_UNIFORM_BUFFER_SIZE); +#endif // DEBUG_ENABLED ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL; stages = &p_functions; const FunctionInfo &constants = p_functions.has("constants") ? p_functions["constants"] : FunctionInfo(); + Map<String, String> defined_modes; + while (tk.type != TK_EOF) { switch (tk.type) { case TK_RENDER_MODE: { @@ -7566,13 +7616,40 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (p_render_modes.find(mode) == -1) { - _set_error("Invalid render mode: '" + String(mode) + "'"); + const String smode = String(mode); + + if (shader->render_modes.find(mode) != -1) { + _set_error(vformat("Duplicated render mode: '%s'.", smode)); return ERR_PARSE_ERROR; } - if (shader->render_modes.find(mode) != -1) { - _set_error("Duplicate render mode: '" + String(mode) + "'"); + bool found = false; + + for (int i = 0; i < p_render_modes.size(); i++) { + const ModeInfo &info = p_render_modes[i]; + const String name = String(info.name); + + if (smode.begins_with(name)) { + if (!info.options.is_empty()) { + if (info.options.find(smode.substr(name.length() + 1)) != -1) { + found = true; + + if (defined_modes.has(name)) { + _set_error(vformat("Redefinition of render mode: '%s'. The %s mode has already been set to '%s'.", smode, name, defined_modes[name])); + return ERR_PARSE_ERROR; + } + defined_modes.insert(name, smode); + break; + } + } else { + found = true; + break; + } + } + } + + if (!found) { + _set_error(vformat("Invalid render mode: '%s'.", smode)); return ERR_PARSE_ERROR; } @@ -7920,6 +7997,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct uniform2.texture_order = -1; if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) { uniform2.order = uniforms++; +#ifdef DEBUG_ENABLED + if (uniform2.array_size > 0) { + int size = get_datatype_size(uniform2.type) * uniform2.array_size; + int m = (16 * uniform2.array_size); + if ((size % m) != 0U) { + size += m - (size % m); + } + uniform_buffer_size += size; + } else { + uniform_buffer_size += get_datatype_size(uniform2.type); + } +#endif // DEBUG_ENABLED } } @@ -8929,14 +9018,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } - int error_line; - String error_message; - if (!_check_varying_usages(&error_line, &error_message)) { - _set_tkpos({ 0, error_line }); - _set_error(error_message); - return ERR_PARSE_ERROR; +#ifdef DEBUG_ENABLED + if (HAS_WARNING(ShaderWarning::DEVICE_LIMIT_EXCEEDED) && (uniform_buffer_size > max_uniform_buffer_size)) { + Vector<Variant> args; + args.push_back(uniform_buffer_size); + args.push_back(max_uniform_buffer_size); + _add_global_warning(ShaderWarning::DEVICE_LIMIT_EXCEEDED, "uniform buffer", args); } - +#endif // DEBUG_ENABLED return OK; } @@ -9159,8 +9248,31 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } break; case COMPLETION_RENDER_MODE: { for (int i = 0; i < p_info.render_modes.size(); i++) { - ScriptCodeCompletionOption option(p_info.render_modes[i], ScriptCodeCompletionOption::KIND_ENUM); - r_options->push_back(option); + const ModeInfo &info = p_info.render_modes[i]; + + if (!info.options.is_empty()) { + bool found = false; + + for (int j = 0; j < info.options.size(); j++) { + if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) { + found = true; + } + } + + if (!found) { + for (int j = 0; j < info.options.size(); j++) { + ScriptCodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptCodeCompletionOption::KIND_ENUM); + r_options->push_back(option); + } + } + } else { + const String name = String(info.name); + + if (!shader->render_modes.has(name)) { + ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_ENUM); + r_options->push_back(option); + } + } } return OK; @@ -9621,7 +9733,7 @@ ShaderLanguage::ShaderLanguage() { nodes = nullptr; completion_class = TAG_GLOBAL; -#if DEBUG_ENABLED +#ifdef DEBUG_ENABLED warnings_check_map.insert(ShaderWarning::UNUSED_CONSTANT, &used_constants); warnings_check_map.insert(ShaderWarning::UNUSED_FUNCTION, &used_functions); warnings_check_map.insert(ShaderWarning::UNUSED_STRUCT, &used_structs); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 8502a250b6..bf3c601aea 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -787,7 +787,7 @@ public: static bool is_sampler_type(DataType p_type); static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, int p_array_size, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE); static PropertyInfo uniform_to_property_info(const ShaderNode::Uniform &p_uniform); - static uint32_t get_type_size(DataType p_type); + static uint32_t get_datatype_size(DataType p_type); static void get_keyword_list(List<String> *r_keywords); static bool is_control_flow_keyword(String p_keyword); @@ -819,6 +819,57 @@ public: DataType return_type = TYPE_VOID; }; + struct ModeInfo { + StringName name; + Vector<StringName> options; + + ModeInfo() {} + + ModeInfo(const StringName &p_name) : + name(p_name) { + } + + ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2) : + name(p_name) { + options.push_back(p_arg1); + options.push_back(p_arg2); + } + + ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3) : + name(p_name) { + options.push_back(p_arg1); + options.push_back(p_arg2); + options.push_back(p_arg3); + } + + ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4) : + name(p_name) { + options.push_back(p_arg1); + options.push_back(p_arg2); + options.push_back(p_arg3); + options.push_back(p_arg4); + } + + ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4, const StringName &p_arg5) : + name(p_name) { + options.push_back(p_arg1); + options.push_back(p_arg2); + options.push_back(p_arg3); + options.push_back(p_arg4); + options.push_back(p_arg5); + } + + ModeInfo(const StringName &p_name, const StringName &p_arg1, const StringName &p_arg2, const StringName &p_arg3, const StringName &p_arg4, const StringName &p_arg5, const StringName &p_arg6) : + name(p_name) { + options.push_back(p_arg1); + options.push_back(p_arg2); + options.push_back(p_arg3); + options.push_back(p_arg4); + options.push_back(p_arg5); + options.push_back(p_arg6); + } + }; + struct FunctionInfo { Map<StringName, BuiltInInfo> built_ins; Map<StringName, StageFunctionInfo> stage_functions; @@ -868,11 +919,14 @@ private: bool check_warnings = false; uint32_t warning_flags; - void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "") { - warnings.push_back(ShaderWarning(p_code, tk_line, p_subject)); + void _add_line_warning(ShaderWarning::Code p_code, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) { + warnings.push_back(ShaderWarning(p_code, tk_line, p_subject, p_extra_args)); } - void _add_warning(ShaderWarning::Code p_code, int p_line, const StringName &p_subject = "") { - warnings.push_back(ShaderWarning(p_code, p_line, p_subject)); + void _add_global_warning(ShaderWarning::Code p_code, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) { + warnings.push_back(ShaderWarning(p_code, -1, p_subject, p_extra_args)); + } + void _add_warning(ShaderWarning::Code p_code, int p_line, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()) { + warnings.push_back(ShaderWarning(p_code, p_line, p_subject, p_extra_args)); } void _check_warning_accums(); #endif // DEBUG_ENABLED @@ -887,14 +941,6 @@ private: VaryingFunctionNames varying_function_names; - struct VaryingUsage { - ShaderNode::Varying *var; - int line; - }; - List<VaryingUsage> unknown_varying_usages; - - bool _check_varying_usages(int *r_error_line, String *r_error_message) const; - TkPos _get_tkpos() { TkPos tkp; tkp.char_idx = char_idx; @@ -996,7 +1042,6 @@ private: bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat); bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin); bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message); - bool _validate_varying_using(ShaderNode::Varying &p_varying, String *r_message); bool _check_node_constness(const Node *p_node) const; Node *_parse_array_size(BlockNode *p_block, const FunctionInfo &p_function_info, int &r_array_size); @@ -1013,7 +1058,7 @@ private: String _get_shader_type_list(const Set<String> &p_shader_types) const; String _get_qualifier_str(ArgumentQualifier p_qualifier) const; - Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types); + Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const Set<String> &p_shader_types); Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op); Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op); @@ -1037,7 +1082,7 @@ public: struct ShaderCompileInfo { Map<StringName, FunctionInfo> functions; - Vector<StringName> render_modes; + Vector<ModeInfo> render_modes; VaryingFunctionNames varying_function_names = VaryingFunctionNames(); Set<String> shader_types; GlobalVariableGetTypeFunc global_variable_type_func = nullptr; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 359196e096..91ba8301e2 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -35,7 +35,7 @@ const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions( return shader_modes[p_mode].functions; } -const Vector<StringName> &ShaderTypes::get_modes(RS::ShaderMode p_mode) const { +const Vector<ShaderLanguage::ModeInfo> &ShaderTypes::get_modes(RS::ShaderMode p_mode) const { return shader_modes[p_mode].modes; } @@ -190,53 +190,29 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["light"].can_discard = true; shader_modes[RS::SHADER_SPATIAL].functions["light"].main_function = true; - //order used puts first enum mode (default) first - shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mix"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_add"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_sub"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mul"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_always"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_never"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_prepass_alpha"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_test_disabled"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("sss_mode_skin"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_back"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_front"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_disabled"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("unshaded"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("wireframe"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_burley"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_toon"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_schlick_ggx"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_blinn"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_phong"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_toon"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_disabled"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("skip_vertex_transform"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("world_vertex_coords"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("ensure_correct_normals"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadows_disabled"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("vertex_lighting"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("particle_trails"); - - shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage"); - shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage_and_one"); + // spatial render modes + { + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "blend", "mix", "add", "sub", "mul" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_draw", "opaque", "always", "never" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_prepass_alpha" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "depth_test_disabled" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "sss_mode_skin" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "cull", "back", "front", "disabled" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "unshaded" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "wireframe" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "diffuse", "lambert", "lambert_wrap", "burley", "toon" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "specular", "schlick_ggx", "blinn", "phong", "toon", "disabled" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "skip_vertex_transform" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "world_vertex_coords" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ensure_correct_normals" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "shadows_disabled" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "ambient_light_disabled" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "shadow_to_opacity" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "vertex_lighting" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "particle_trails" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "alpha_to_coverage" }); + shader_modes[RS::SHADER_SPATIAL].modes.push_back({ "alpha_to_coverage_and_one" }); + } /************ CANVAS ITEM **************************/ @@ -319,17 +295,13 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true; shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].main_function = true; - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform"); - - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mix"); - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_add"); - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_sub"); - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mul"); - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_premul_alpha"); - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_disabled"); - - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("unshaded"); - shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("light_only"); + // canvasitem render modes + { + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "skip_vertex_transform" }); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "blend", "mix", "add", "sub", "mul", "premul_alpha", "disabled" }); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "unshaded" }); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back({ "light_only" }); + } /************ PARTICLES **************************/ @@ -392,10 +364,13 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_PARTICLES].functions["process"].stage_functions["emit_subparticle"] = emit_vertex_func; } - shader_modes[RS::SHADER_PARTICLES].modes.push_back("collision_use_scale"); - shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_force"); - shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_velocity"); - shader_modes[RS::SHADER_PARTICLES].modes.push_back("keep_data"); + // particles render modes + { + shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "collision_use_scale" }); + shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "disable_force" }); + shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "disable_velocity" }); + shader_modes[RS::SHADER_PARTICLES].modes.push_back({ "keep_data" }); + } /************ SKY **************************/ @@ -439,9 +414,12 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["FOG"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_SKY].functions["sky"].main_function = true; - shader_modes[RS::SHADER_SKY].modes.push_back("use_half_res_pass"); - shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass"); - shader_modes[RS::SHADER_SKY].modes.push_back("disable_fog"); + // sky render modes + { + shader_modes[RS::SHADER_SKY].modes.push_back({ "use_half_res_pass" }); + shader_modes[RS::SHADER_SKY].modes.push_back({ "use_quarter_res_pass" }); + shader_modes[RS::SHADER_SKY].modes.push_back({ "disable_fog" }); + } /************ FOG **************************/ diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h index 75a310a1b1..347c0ec7df 100644 --- a/servers/rendering/shader_types.h +++ b/servers/rendering/shader_types.h @@ -38,7 +38,7 @@ class ShaderTypes { struct Type { Map<StringName, ShaderLanguage::FunctionInfo> functions; - Vector<StringName> modes; + Vector<ShaderLanguage::ModeInfo> modes; }; Map<RS::ShaderMode, Type> shader_modes; @@ -52,7 +52,7 @@ public: static ShaderTypes *get_singleton() { return singleton; } const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode) const; - const Vector<StringName> &get_modes(RS::ShaderMode p_mode) const; + const Vector<ShaderLanguage::ModeInfo> &get_modes(RS::ShaderMode p_mode) const; const Set<String> &get_types() const; const List<String> &get_types_list() const; diff --git a/servers/rendering/shader_warnings.cpp b/servers/rendering/shader_warnings.cpp index bffae484a8..a6ec07dba4 100644 --- a/servers/rendering/shader_warnings.cpp +++ b/servers/rendering/shader_warnings.cpp @@ -63,6 +63,8 @@ String ShaderWarning::get_message() const { return vformat("The local variable '%s' is declared but never used.", subject); case FORMATTING_ERROR: return subject; + case DEVICE_LIMIT_EXCEEDED: + return vformat("The total size of the %s for this shader on this device has been exceeded (%s/%s). The shader may not work correctly.", subject, (int)extra_args[0], (int)extra_args[1]); default: break; } @@ -73,6 +75,10 @@ String ShaderWarning::get_name() const { return get_name_from_code(code); } +Vector<Variant> ShaderWarning::get_extra_args() const { + return extra_args; +} + String ShaderWarning::get_name_from_code(Code p_code) { ERR_FAIL_INDEX_V(p_code, WARNING_MAX, String()); @@ -85,6 +91,7 @@ String ShaderWarning::get_name_from_code(Code p_code) { "UNUSED_VARYING", "UNUSED_LOCAL_VARIABLE", "FORMATTING_ERROR", + "DEVICE_LIMIT_EXCEEDED", }; static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names."); @@ -114,6 +121,7 @@ static void init_code_to_flags_map() { code_to_flags_map->insert(ShaderWarning::UNUSED_VARYING, ShaderWarning::UNUSED_VARYING_FLAG); code_to_flags_map->insert(ShaderWarning::UNUSED_LOCAL_VARIABLE, ShaderWarning::UNUSED_LOCAL_VARIABLE_FLAG); code_to_flags_map->insert(ShaderWarning::FORMATTING_ERROR, ShaderWarning::FORMATTING_ERROR_FLAG); + code_to_flags_map->insert(ShaderWarning::DEVICE_LIMIT_EXCEEDED, ShaderWarning::DEVICE_LIMIT_EXCEEDED_FLAG); } ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, bool> &p_map) { @@ -132,8 +140,8 @@ ShaderWarning::CodeFlags ShaderWarning::get_flags_from_codemap(const Map<Code, b return (CodeFlags)result; } -ShaderWarning::ShaderWarning(Code p_code, int p_line, const StringName &p_subject) : - code(p_code), line(p_line), subject(p_subject) { +ShaderWarning::ShaderWarning(Code p_code, int p_line, const StringName &p_subject, const Vector<Variant> &p_extra_args) : + code(p_code), line(p_line), subject(p_subject), extra_args(p_extra_args) { } #endif // DEBUG_ENABLED diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h index 18915fffd8..2d0ba7b5b2 100644 --- a/servers/rendering/shader_warnings.h +++ b/servers/rendering/shader_warnings.h @@ -36,6 +36,7 @@ #include "core/string/string_name.h" #include "core/templates/list.h" #include "core/templates/map.h" +#include "core/variant/variant.h" class ShaderWarning { public: @@ -48,6 +49,7 @@ public: UNUSED_VARYING, UNUSED_LOCAL_VARIABLE, FORMATTING_ERROR, + DEVICE_LIMIT_EXCEEDED, WARNING_MAX, }; @@ -61,12 +63,14 @@ public: UNUSED_VARYING_FLAG = 32U, UNUSED_LOCAL_VARIABLE_FLAG = 64U, FORMATTING_ERROR_FLAG = 128U, + DEVICE_LIMIT_EXCEEDED_FLAG = 256U, }; private: Code code; int line; StringName subject; + Vector<Variant> extra_args; public: Code get_code() const; @@ -74,12 +78,13 @@ public: const StringName &get_subject() const; String get_message() const; String get_name() const; + Vector<Variant> get_extra_args() const; static String get_name_from_code(Code p_code); static Code get_code_from_name(const String &p_name); static CodeFlags get_flags_from_codemap(const Map<Code, bool> &p_map); - ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = ""); + ShaderWarning(Code p_code = WARNING_MAX, int p_line = -1, const StringName &p_subject = "", const Vector<Variant> &p_extra_args = Vector<Variant>()); }; #endif // DEBUG_ENABLED |