Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5575,7 +5575,7 @@ void EditorNode::add_io_error(const String &p_error) {
// the io errors to prevent the io popup to set it's parent to the progress dialog.
if (singleton->progress_dialog->is_visible()) {
singleton->load_errors_queued_to_display = true;
} else {
} else if (!singleton->load_error_dialog->is_inside_tree()) {
EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5);
}
}
Expand All @@ -5588,7 +5588,7 @@ void EditorNode::add_io_warning(const String &p_warning) {
// the io errors to prevent the io popup to set it's parent to the progress dialog.
if (singleton->progress_dialog->is_visible()) {
singleton->load_errors_queued_to_display = true;
} else {
} else if (!singleton->load_error_dialog->is_inside_tree()) {
EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5);
}
}
Expand Down Expand Up @@ -6030,7 +6030,9 @@ void EditorNode::progress_end_task_bg(const String &p_task) {
void EditorNode::_progress_dialog_visibility_changed() {
// Open the io errors after the progress dialog is closed.
if (load_errors_queued_to_display && !progress_dialog->is_visible()) {
EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5);
if (!singleton->load_error_dialog->is_inside_tree()) {
EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5);
}
load_errors_queued_to_display = false;
}
}
Expand Down
15 changes: 12 additions & 3 deletions editor/import/resource_importer_shader_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ static String _include_function(const String &p_path, void *userpointer) {
return file_inc->get_as_utf8_string();
}

static void _add_shader_import_error_if_needed(const String &p_source_file) {
if (!EditorNode::get_singleton()) {
return;
}

if (!ShaderFileEditor::singleton || !ShaderFileEditor::singleton->is_visible_in_tree()) {
EditorNode::add_io_error(vformat(TTR("Error importing GLSL shader file: '%s'. Open the file in the filesystem dock in order to see the reason."), p_source_file));
}
}

Error ResourceImporterShaderFile::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
Error err;
Ref<FileAccess> file = FileAccess::open(p_source_file, FileAccess::READ, &err);
Expand All @@ -102,9 +112,8 @@ Error ResourceImporterShaderFile::import(ResourceUID::ID p_source_id, const Stri
err = shader_file->parse_versions_from_text(file_txt, "", _include_function, &base_path);

if (err != OK) {
if (!ShaderFileEditor::singleton->is_visible_in_tree()) {
callable_mp_static(&EditorNode::add_io_error).call_deferred(vformat(TTR("Error importing GLSL shader file: '%s'. Open the file in the filesystem dock in order to see the reason."), p_source_file));
}
shader_file->print_errors(p_source_file);
callable_mp_static(_add_shader_import_error_if_needed).call_deferred(p_source_file);
}

ResourceSaver::save(shader_file, p_save_path + ".res");
Expand Down
30 changes: 28 additions & 2 deletions servers/rendering/rendering_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10006,6 +10006,12 @@ Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<
Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, source, p_source->get_language(), &error, p_allow_cache);
bytecode->set_stage_bytecode(stage, spirv);
bytecode->set_stage_compile_error(stage, error);

if (!error.is_empty()) {
String message = vformat("Stage '%s' compile error:\n\n%s", String(RD::get_shader_stage_name(stage)), error);
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Error compiling shader.", message, false, ERR_HANDLER_SHADER);
Comment thread
AThousandShips marked this conversation as resolved.
Outdated
bytecode->mark_stage_compile_error_printed(stage);
}
}
}
return bytecode;
Expand All @@ -10020,7 +10026,17 @@ Vector<uint8_t> RenderingDevice::_shader_compile_binary_from_spirv(const Ref<RDS
ShaderStageSPIRVData sd;
sd.shader_stage = stage;
String error = p_spirv->get_stage_compile_error(stage);
ERR_FAIL_COND_V_MSG(!error.is_empty(), Vector<uint8_t>(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
if (!error.is_empty()) {
String message;
if (p_spirv->was_stage_compile_error_printed(stage)) {
message = vformat("Can't create a shader from an errored bytecode. Stage '%s' has compile errors. Check previous shader errors.", String(RD::get_shader_stage_name(stage)));
} else {
message = vformat("Can't create a shader from an errored bytecode. Stage '%s' compile error:\n\n%s", String(RD::get_shader_stage_name(stage)), error);
p_spirv->mark_stage_compile_error_printed(stage);
}
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Can't create a shader from an errored bytecode.", message, false, ERR_HANDLER_SHADER);
return Vector<uint8_t>();
}
sd.spirv = p_spirv->get_stage_bytecode(stage);
if (sd.spirv.is_empty()) {
continue;
Expand All @@ -10040,7 +10056,17 @@ RID RenderingDevice::_shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv
ShaderStageSPIRVData sd;
sd.shader_stage = stage;
String error = p_spirv->get_stage_compile_error(stage);
ERR_FAIL_COND_V_MSG(!error.is_empty(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
if (!error.is_empty()) {
String message;
if (p_spirv->was_stage_compile_error_printed(stage)) {
message = vformat("Can't create a shader from an errored bytecode. Stage '%s' has compile errors. Check previous shader errors.", String(RD::get_shader_stage_name(stage)));
} else {
message = vformat("Can't create a shader from an errored bytecode. Stage '%s' compile error:\n\n%s", String(RD::get_shader_stage_name(stage)), error);
p_spirv->mark_stage_compile_error_printed(stage);
}
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Can't create a shader from an errored bytecode.", message, false, ERR_HANDLER_SHADER);
return RID();
}
sd.spirv = p_spirv->get_stage_bytecode(stage);
if (sd.spirv.is_empty()) {
continue;
Expand Down
3 changes: 2 additions & 1 deletion servers/rendering/rendering_device_binds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String

if (base_error.is_empty()) {
if (stage_found[RD::SHADER_STAGE_COMPUTE] && stages_found > 1) {
ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "When writing compute shaders, [compute] mustbe the only stage present.");
base_error = "When writing compute shaders, [compute] must be the only stage present.";
return ERR_PARSE_ERROR;
}

if (version_texts.is_empty()) {
Expand Down
31 changes: 21 additions & 10 deletions servers/rendering/rendering_device_binds.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,12 @@ class RDShaderSource : public RefCounted {
class RDShaderSPIRV : public Resource {
GDCLASS(RDShaderSPIRV, Resource)

friend class RenderingDevice;
friend class RDShaderFile;

Vector<uint8_t> bytecode[RD::SHADER_STAGE_MAX];
String compile_error[RD::SHADER_STAGE_MAX];
bool compile_error_printed[RD::SHADER_STAGE_MAX] = {};

public:
void set_stage_bytecode(RD::ShaderStage p_stage, const Vector<uint8_t> &p_bytecode) {
Expand Down Expand Up @@ -321,13 +325,25 @@ class RDShaderSPIRV : public Resource {
void set_stage_compile_error(RD::ShaderStage p_stage, const String &p_compile_error) {
ERR_FAIL_INDEX(p_stage, RD::SHADER_STAGE_MAX);
compile_error[p_stage] = p_compile_error;
compile_error_printed[p_stage] = false;
}

String get_stage_compile_error(RD::ShaderStage p_stage) const {
ERR_FAIL_INDEX_V(p_stage, RD::SHADER_STAGE_MAX, String());
return compile_error[p_stage];
}

private:
void mark_stage_compile_error_printed(RD::ShaderStage p_stage) {
ERR_FAIL_INDEX(p_stage, RD::SHADER_STAGE_MAX);
compile_error_printed[p_stage] = true;
}

bool was_stage_compile_error_printed(RD::ShaderStage p_stage) const {
ERR_FAIL_INDEX_V(p_stage, RD::SHADER_STAGE_MAX, false);
return compile_error_printed[p_stage];
}

protected:
static void _bind_methods() {
ClassDB::bind_method(D_METHOD("set_stage_bytecode", "stage", "bytecode"), &RDShaderSPIRV::set_stage_bytecode);
Expand Down Expand Up @@ -409,21 +425,16 @@ class RDShaderFile : public Resource {

void print_errors(const String &p_file) {
if (!base_error.is_empty()) {
ERR_PRINT("Error parsing shader '" + p_file + "':\n\n" + base_error);
String error_message = "Error parsing shader '" + p_file + "':\n\n" + base_error;
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Error parsing shader.", error_message, false, ERR_HANDLER_SHADER);
} else {
for (KeyValue<StringName, Ref<RDShaderSPIRV>> &E : versions) {
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String error = E.value->get_stage_compile_error(RD::ShaderStage(i));
if (!error.is_empty()) {
static const char *stage_str[RD::SHADER_STAGE_MAX] = {
"vertex",
"fragment",
"tesselation_control",
"tesselation_evaluation",
"compute"
};

print_error("Error parsing shader '" + p_file + "', version '" + String(E.key) + "', stage '" + stage_str[i] + "':\n\n" + error);
String error_message = "Error parsing shader '" + p_file + "', version '" + String(E.key) + "', stage '" + RD::get_shader_stage_name(RD::ShaderStage(i)) + "':\n\n" + error;
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Error parsing shader.", error_message, false, ERR_HANDLER_SHADER);
E.value->mark_stage_compile_error_printed(RD::ShaderStage(i));
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions servers/rendering/rendering_device_commons.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,26 @@ class RenderingDeviceCommons : public Object {
SHADER_STAGE_INTERSECTION_BIT = (1 << SHADER_STAGE_INTERSECTION),
};

static const char *get_shader_stage_name(ShaderStage p_stage) {
static constexpr const char *shader_stage_names[SHADER_STAGE_MAX] = {
"vertex",
"fragment",
"tesselation_control",
"tesselation_evaluation",
"compute",
"raygen",
"any_hit",
"closest_hit",
"miss",
"intersection",
};

if (p_stage >= 0 && p_stage < SHADER_STAGE_MAX) {
return shader_stage_names[p_stage];
}
return "unknown";
}

enum ShaderLanguage {
SHADER_LANGUAGE_GLSL,
SHADER_LANGUAGE_HLSL,
Expand Down