Add a shader warning when the uniform buffer limit is exceeded

This commit is contained in:
Yuri Roubinsky 2021-12-22 10:15:12 +03:00
parent 9221c0f8ad
commit fd9c92d4ab
9 changed files with 107 additions and 115 deletions

View File

@ -293,15 +293,20 @@ void ShaderTextEditor::_update_warning_panel() {
} }
warning_count++; warning_count++;
int line = w.get_line();
// First cell. // First cell.
warnings_panel->push_cell(); warnings_panel->push_cell();
warnings_panel->push_meta(w.get_line() - 1);
warnings_panel->push_color(warnings_panel->get_theme_color(SNAME("warning_color"), SNAME("Editor"))); warnings_panel->push_color(warnings_panel->get_theme_color(SNAME("warning_color"), SNAME("Editor")));
warnings_panel->add_text(TTR("Line") + " " + itos(w.get_line())); if (line != -1) {
warnings_panel->add_text(" (" + w.get_name() + "):"); warnings_panel->push_meta(line - 1);
warnings_panel->add_text(TTR("Line") + " " + itos(line));
warnings_panel->add_text(" (" + w.get_name() + "):");
warnings_panel->pop(); // Meta goto.
} else {
warnings_panel->add_text(w.get_name() + ":");
}
warnings_panel->pop(); // Color. warnings_panel->pop(); // Color.
warnings_panel->pop(); // Meta goto.
warnings_panel->pop(); // Cell. warnings_panel->pop(); // Cell.
// Second cell. // Second cell.

View File

@ -350,7 +350,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n"); OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n");
OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n"); OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n");
OS::get_singleton()->print(" --vk-layers Enable Vulkan Validation layers for debugging.\n"); OS::get_singleton()->print(" --vk-layers Enable Vulkan Validation layers for debugging.\n");
#if DEBUG_ENABLED #ifdef DEBUG_ENABLED
OS::get_singleton()->print(" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n"); OS::get_singleton()->print(" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n");
#endif #endif
OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n"); OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");

View File

@ -1591,7 +1591,7 @@ void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout) {
Bus::Effect bfx; Bus::Effect bfx;
bfx.effect = fx; bfx.effect = fx;
bfx.enabled = p_bus_layout->buses[i].effects[j].enabled; bfx.enabled = p_bus_layout->buses[i].effects[j].enabled;
#if DEBUG_ENABLED #ifdef DEBUG_ENABLED
bfx.prof_time = 0; bfx.prof_time = 0;
#endif #endif
bus->effects.push_back(bfx); bus->effects.push_back(bfx);

View File

@ -2655,13 +2655,13 @@ void RendererStorageRD::MaterialData::update_uniform_buffer(const Map<StringName
uint32_t size = 0U; uint32_t size = 0U;
// The following code enforces a 16-byte alignment of uniform arrays. // The following code enforces a 16-byte alignment of uniform arrays.
if (E.value.array_size > 0) { 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); int m = (16 * E.value.array_size);
if ((size % m) != 0U) { if ((size % m) != 0U) {
size += m - (size % m); size += m - (size % m);
} }
} else { } else {
size = ShaderLanguage::get_type_size(E.value.type); size = ShaderLanguage::get_datatype_size(E.value.type);
} }
ERR_CONTINUE(offset + size > p_buffer_size); ERR_CONTINUE(offset + size > p_buffer_size);
#endif #endif

View File

@ -54,81 +54,6 @@ static String _typestr(SL::DataType p_type) {
return 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) { static int _get_datatype_alignment(SL::DataType p_type) {
switch (p_type) { switch (p_type) {
case SL::TYPE_VOID: 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; uniform_defines.write[uniform.order] = ucode;
if (is_buffer_global) { if (is_buffer_global) {
//globals are indices into the global table //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); uniform_alignments.write[uniform.order] = _get_datatype_alignment(ShaderLanguage::TYPE_UINT);
} else { } else {
// The following code enforces a 16-byte alignment of uniform arrays. // The following code enforces a 16-byte alignment of uniform arrays.
if (uniform.array_size > 0) { 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); int m = (16 * uniform.array_size);
if ((size % m) != 0) { if ((size % m) != 0) {
size += m - (size % m); 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_sizes.write[uniform.order] = size;
uniform_alignments.write[uniform.order] = 16; uniform_alignments.write[uniform.order] = 16;
} else { } 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); uniform_alignments.write[uniform.order] = _get_datatype_alignment(uniform.type);
} }
} }

View File

@ -3866,55 +3866,77 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
return pi; return pi;
} }
uint32_t ShaderLanguage::get_type_size(DataType p_type) { uint32_t ShaderLanguage::get_datatype_size(ShaderLanguage::DataType p_type) {
switch (p_type) { switch (p_type) {
case TYPE_VOID: case TYPE_VOID:
return 0; return 0;
case TYPE_BOOL: case TYPE_BOOL:
case TYPE_INT:
case TYPE_UINT:
case TYPE_FLOAT:
return 4; return 4;
case TYPE_BVEC2: case TYPE_BVEC2:
case TYPE_IVEC2:
case TYPE_UVEC2:
case TYPE_VEC2:
return 8; return 8;
case TYPE_BVEC3: case TYPE_BVEC3:
case TYPE_IVEC3:
case TYPE_UVEC3:
case TYPE_VEC3:
return 12; return 12;
case TYPE_BVEC4: case TYPE_BVEC4:
return 16;
case TYPE_INT:
return 4;
case TYPE_IVEC2:
return 8;
case TYPE_IVEC3:
return 12;
case TYPE_IVEC4: case TYPE_IVEC4:
return 16;
case TYPE_UINT:
return 4;
case TYPE_UVEC2:
return 8;
case TYPE_UVEC3:
return 12;
case TYPE_UVEC4: case TYPE_UVEC4:
return 16;
case TYPE_FLOAT:
return 4;
case TYPE_VEC2:
return 8;
case TYPE_VEC3:
return 12;
case TYPE_VEC4: case TYPE_VEC4:
return 16; return 16;
case TYPE_MAT2: case TYPE_MAT2:
return 8; return 32; // 4 * 4 + 4 * 4
case TYPE_MAT3: case TYPE_MAT3:
return 12; return 48; // 4 * 4 + 4 * 4 + 4 * 4
case TYPE_MAT4: case TYPE_MAT4:
return 16; return 64;
case TYPE_SAMPLER2D: case TYPE_SAMPLER2D:
return 16;
case TYPE_ISAMPLER2D: case TYPE_ISAMPLER2D:
return 16;
case TYPE_USAMPLER2D: case TYPE_USAMPLER2D:
return 16;
case TYPE_SAMPLER2DARRAY: case TYPE_SAMPLER2DARRAY:
return 16;
case TYPE_ISAMPLER2DARRAY: case TYPE_ISAMPLER2DARRAY:
return 16;
case TYPE_USAMPLER2DARRAY: case TYPE_USAMPLER2DARRAY:
return 16;
case TYPE_SAMPLER3D: case TYPE_SAMPLER3D:
return 16;
case TYPE_ISAMPLER3D: case TYPE_ISAMPLER3D:
return 16;
case TYPE_USAMPLER3D: case TYPE_USAMPLER3D:
return 16;
case TYPE_SAMPLERCUBE: case TYPE_SAMPLERCUBE:
return 16;
case TYPE_SAMPLERCUBEARRAY: case TYPE_SAMPLERCUBEARRAY:
return 4; //not really, but useful for indices return 16;
case TYPE_STRUCT: case TYPE_STRUCT:
// FIXME: Implement.
return 0;
case ShaderLanguage::TYPE_MAX:
return 0; return 0;
case TYPE_MAX: {
ERR_FAIL_V(0);
};
} }
return 0; ERR_FAIL_V(0);
} }
void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
@ -5309,7 +5331,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
_set_error("Expected expression, found: " + get_token_text(tk)); _set_error("Expected expression, found: " + get_token_text(tk));
return nullptr; return nullptr;
} else { } else {
#if DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) { if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) {
_add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning."); _add_line_warning(ShaderWarning::FORMATTING_ERROR, "Empty statement. Remove ';' to fix this warning.");
} }
@ -6120,7 +6142,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
ERR_FAIL_V(nullptr); //unexpected operator 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) && 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].is_op && !expression[i + 1].is_op) &&
(expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT)) { (expression[i - 1].node->get_datatype() == TYPE_FLOAT && expression[i + 1].node->get_datatype() == TYPE_FLOAT)) {
@ -7571,6 +7593,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
int texture_binding = 0; int texture_binding = 0;
int uniforms = 0; int uniforms = 0;
int instance_index = 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; ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL;
stages = &p_functions; stages = &p_functions;
@ -7971,6 +7997,18 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
uniform2.texture_order = -1; uniform2.texture_order = -1;
if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) { if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) {
uniform2.order = uniforms++; 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
} }
} }
@ -8980,6 +9018,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token(); tk = _get_token();
} }
#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; return OK;
} }
@ -9687,7 +9733,7 @@ ShaderLanguage::ShaderLanguage() {
nodes = nullptr; nodes = nullptr;
completion_class = TAG_GLOBAL; 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_CONSTANT, &used_constants);
warnings_check_map.insert(ShaderWarning::UNUSED_FUNCTION, &used_functions); warnings_check_map.insert(ShaderWarning::UNUSED_FUNCTION, &used_functions);
warnings_check_map.insert(ShaderWarning::UNUSED_STRUCT, &used_structs); warnings_check_map.insert(ShaderWarning::UNUSED_STRUCT, &used_structs);

View File

@ -787,7 +787,7 @@ public:
static bool is_sampler_type(DataType p_type); 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 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 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 void get_keyword_list(List<String> *r_keywords);
static bool is_control_flow_keyword(String p_keyword); static bool is_control_flow_keyword(String p_keyword);
@ -919,11 +919,14 @@ private:
bool check_warnings = false; bool check_warnings = false;
uint32_t warning_flags; uint32_t warning_flags;
void _add_line_warning(ShaderWarning::Code p_code, const StringName &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)); 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 = "") { 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, p_line, p_subject)); 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(); void _check_warning_accums();
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED

View File

@ -63,6 +63,8 @@ String ShaderWarning::get_message() const {
return vformat("The local variable '%s' is declared but never used.", subject); return vformat("The local variable '%s' is declared but never used.", subject);
case FORMATTING_ERROR: case FORMATTING_ERROR:
return subject; 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: default:
break; break;
} }
@ -73,6 +75,10 @@ String ShaderWarning::get_name() const {
return get_name_from_code(code); 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) { String ShaderWarning::get_name_from_code(Code p_code) {
ERR_FAIL_INDEX_V(p_code, WARNING_MAX, String()); 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_VARYING",
"UNUSED_LOCAL_VARIABLE", "UNUSED_LOCAL_VARIABLE",
"FORMATTING_ERROR", "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."); 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_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::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::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) { 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; return (CodeFlags)result;
} }
ShaderWarning::ShaderWarning(Code p_code, int p_line, const StringName &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) { code(p_code), line(p_line), subject(p_subject), extra_args(p_extra_args) {
} }
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED

View File

@ -36,6 +36,7 @@
#include "core/string/string_name.h" #include "core/string/string_name.h"
#include "core/templates/list.h" #include "core/templates/list.h"
#include "core/templates/map.h" #include "core/templates/map.h"
#include "core/variant/variant.h"
class ShaderWarning { class ShaderWarning {
public: public:
@ -48,6 +49,7 @@ public:
UNUSED_VARYING, UNUSED_VARYING,
UNUSED_LOCAL_VARIABLE, UNUSED_LOCAL_VARIABLE,
FORMATTING_ERROR, FORMATTING_ERROR,
DEVICE_LIMIT_EXCEEDED,
WARNING_MAX, WARNING_MAX,
}; };
@ -61,12 +63,14 @@ public:
UNUSED_VARYING_FLAG = 32U, UNUSED_VARYING_FLAG = 32U,
UNUSED_LOCAL_VARIABLE_FLAG = 64U, UNUSED_LOCAL_VARIABLE_FLAG = 64U,
FORMATTING_ERROR_FLAG = 128U, FORMATTING_ERROR_FLAG = 128U,
DEVICE_LIMIT_EXCEEDED_FLAG = 256U,
}; };
private: private:
Code code; Code code;
int line; int line;
StringName subject; StringName subject;
Vector<Variant> extra_args;
public: public:
Code get_code() const; Code get_code() const;
@ -74,12 +78,13 @@ public:
const StringName &get_subject() const; const StringName &get_subject() const;
String get_message() const; String get_message() const;
String get_name() const; String get_name() const;
Vector<Variant> get_extra_args() const;
static String get_name_from_code(Code p_code); static String get_name_from_code(Code p_code);
static Code get_code_from_name(const String &p_name); static Code get_code_from_name(const String &p_name);
static CodeFlags get_flags_from_codemap(const Map<Code, bool> &p_map); 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 #endif // DEBUG_ENABLED