Skip to content

Commit 71e51c8

Browse files
committed
Convert 3.x shaders
1 parent 555d250 commit 71e51c8

11 files changed

Lines changed: 4824 additions & 9 deletions

File tree

editor/shader/text_shader_editor.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@
4747
#include "servers/rendering/shader_preprocessor.h"
4848
#include "servers/rendering/shader_types.h"
4949

50+
#ifndef DISABLE_DEPRECATED
51+
#include "servers/rendering/shader_converter.h"
52+
#endif
53+
5054
/*** SHADER SYNTAX HIGHLIGHTER ****/
5155

5256
Dictionary GDShaderSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_line) {
@@ -760,6 +764,28 @@ void TextShaderEditor::_menu_option(int p_option) {
760764
case EDIT_COMPLETE: {
761765
code_editor->get_text_editor()->request_code_completion();
762766
} break;
767+
#ifndef DISABLE_DEPRECATED
768+
case EDIT_CONVERT: {
769+
if (shader.is_null()) {
770+
return;
771+
}
772+
String code = code_editor->get_text_editor()->get_text();
773+
if (code.is_empty()) {
774+
return;
775+
}
776+
ShaderDeprecatedConverter converter;
777+
if (!converter.is_code_deprecated(code)) {
778+
if (converter.get_error_text() != String()) {
779+
shader_convert_error_dialog->set_text(vformat(RTR("Line %d: %s"), converter.get_error_line(), converter.get_error_text()));
780+
shader_convert_error_dialog->popup_centered();
781+
ERR_PRINT("Shader conversion failed: " + converter.get_error_text());
782+
}
783+
confirm_convert_shader->popup_centered();
784+
return;
785+
}
786+
_convert_shader();
787+
} break;
788+
#endif
763789
case SEARCH_FIND: {
764790
code_editor->get_find_replace_bar()->popup_search();
765791
} break;
@@ -828,6 +854,43 @@ void TextShaderEditor::_notification(int p_what) {
828854
} break;
829855
}
830856
}
857+
#ifndef DISABLE_DEPRECATED
858+
void TextShaderEditor::_convert_shader() {
859+
if (shader.is_null()) {
860+
return;
861+
}
862+
String code = code_editor->get_text_editor()->get_text();
863+
if (code.is_empty()) {
864+
return;
865+
}
866+
ShaderDeprecatedConverter converter;
867+
if (!converter.convert_code(code)) {
868+
String err_text = converter.get_error_text();
869+
if (err_text.is_empty()) {
870+
err_text = TTR("Unknown error occurred while converting the shader.");
871+
} else if (converter.get_error_line() > 0) {
872+
err_text = vformat("%s (line %d)", err_text, converter.get_error_line());
873+
}
874+
875+
shader_convert_error_dialog->set_text(err_text);
876+
shader_convert_error_dialog->popup_centered();
877+
ERR_PRINT("Shader conversion failed: " + err_text);
878+
return;
879+
}
880+
String new_code = converter.emit_code();
881+
882+
#ifdef DEBUG_ENABLED
883+
print_line(converter.get_report());
884+
#endif
885+
if (new_code == code) {
886+
return;
887+
}
888+
// Ensure undoable.
889+
code_editor->get_text_editor()->set_text(new_code);
890+
code_editor->get_text_editor()->tag_saved_version();
891+
code_editor->_validate_script();
892+
}
893+
#endif
831894

832895
void TextShaderEditor::_apply_editor_settings() {
833896
code_editor->update_editor_settings();
@@ -1254,6 +1317,11 @@ TextShaderEditor::TextShaderEditor() {
12541317
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE);
12551318
edit_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &TextShaderEditor::_menu_option));
12561319

1320+
#ifndef DISABLE_DEPRECATED
1321+
edit_menu->get_popup()->add_separator();
1322+
edit_menu->get_popup()->add_item(TTR("Convert 3.x Shader"), EDIT_CONVERT);
1323+
#endif
1324+
12571325
search_menu = memnew(MenuButton);
12581326
search_menu->set_flat(false);
12591327
search_menu->set_theme_type_variation("FlatMenuButton");
@@ -1345,6 +1413,20 @@ TextShaderEditor::TextShaderEditor() {
13451413

13461414
add_child(disk_changed);
13471415

1416+
#ifndef DISABLE_DEPRECATED
1417+
shader_convert_error_dialog = memnew(AcceptDialog);
1418+
shader_convert_error_dialog->set_title(TTR("Error converting shader"));
1419+
shader_convert_error_dialog->set_hide_on_ok(true);
1420+
add_child(shader_convert_error_dialog);
1421+
1422+
confirm_convert_shader = memnew(ConfirmationDialog);
1423+
confirm_convert_shader->set_title(TTR("Confirm Convert 3.x Shader"));
1424+
confirm_convert_shader->set_text(TTR("This shader does not appear to be a 3.x shader.\nAre you sure you want to convert it?"));
1425+
confirm_convert_shader->get_ok_button()->set_text(TTR("Convert"));
1426+
confirm_convert_shader->get_cancel_button()->set_text(TTR("Cancel"));
1427+
confirm_convert_shader->connect(SceneStringName(confirmed), callable_mp(this, &TextShaderEditor::_convert_shader));
1428+
add_child(confirm_convert_shader);
13481429
_apply_editor_settings();
1430+
#endif
13491431
code_editor->show_toggle_files_button(); // TODO: Disabled for now, because it doesn't work properly.
13501432
}

editor/shader/text_shader_editor.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class TextShaderEditor : public ShaderEditor {
123123
EDIT_TOGGLE_WORD_WRAP,
124124
EDIT_TOGGLE_COMMENT,
125125
EDIT_COMPLETE,
126+
EDIT_CONVERT,
126127
SEARCH_FIND,
127128
SEARCH_FIND_NEXT,
128129
SEARCH_FIND_PREV,
@@ -149,13 +150,21 @@ class TextShaderEditor : public ShaderEditor {
149150
ConfirmationDialog *disk_changed = nullptr;
150151

151152
ShaderTextEditor *code_editor = nullptr;
153+
#ifndef DISABLE_DEPRECATED
154+
AcceptDialog *shader_convert_error_dialog = nullptr;
155+
ConfirmationDialog *confirm_convert_shader = nullptr;
156+
#endif
157+
152158
bool compilation_success = true;
153159

154160
void _menu_option(int p_option);
155161
void _prepare_edit_menu();
156162
mutable Ref<Shader> shader;
157163
mutable Ref<ShaderInclude> shader_inc;
158164

165+
#ifndef DISABLE_DEPRECATED
166+
void _convert_shader();
167+
#endif
159168
void _apply_editor_settings();
160169
void _project_settings_changed();
161170

scene/resources/shader.cpp

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
#include "scene/main/scene_tree.h"
3939
#include "scene/resources/texture.h"
4040
#include "servers/rendering/rendering_server.h"
41+
#include "servers/rendering/rendering_server_globals.h"
4142
#include "servers/rendering/shader_language.h"
4243
#include "servers/rendering/shader_preprocessor.h"
44+
#include "servers/rendering/shader_types.h"
4345

4446
#ifdef TOOLS_ENABLED
4547
#include "editor/doc/editor_help.h"
@@ -50,6 +52,12 @@
5052
#endif
5153
#endif
5254

55+
#ifndef DISABLE_DEPRECATED
56+
#include "servers/rendering/shader_converter.h"
57+
#endif
58+
59+
#define _LOAD_COMPAT_META_PROPERTY "_load_compat"
60+
5361
Shader::Mode Shader::get_mode() const {
5462
return mode;
5563
}
@@ -85,13 +93,57 @@ void Shader::set_include_path(const String &p_path) {
8593
include_path = p_path;
8694
}
8795

96+
#ifndef DISABLE_DEPRECATED
97+
ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_name) {
98+
RenderingServerEnums::GlobalShaderParameterType gvt = RenderingServerGlobals::material_storage->global_shader_parameter_get_type(p_name);
99+
return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
100+
}
101+
#endif
102+
88103
void Shader::set_code(const String &p_code) {
89104
for (const Ref<ShaderInclude> &E : include_dependencies) {
90105
E->disconnect_changed(callable_mp(this, &Shader::_dependency_changed));
91106
}
92107

93108
code = p_code;
94109
preprocessed_code = p_code;
110+
#ifndef DISABLE_DEPRECATED
111+
if (get_meta(_LOAD_COMPAT_META_PROPERTY, false)) {
112+
// check if the Shader code compiles; if not, it's probably an old shader.
113+
114+
ShaderLanguage sl;
115+
ShaderLanguage::ShaderCompileInfo info;
116+
String mode_string = ShaderLanguage::get_shader_type(p_code);
117+
118+
RenderingServerEnums::ShaderMode new_mode;
119+
if (mode_string == "canvas_item") {
120+
new_mode = RenderingServerEnums::SHADER_CANVAS_ITEM;
121+
} else if (mode_string == "particles") {
122+
new_mode = RenderingServerEnums::SHADER_PARTICLES;
123+
} else if (mode_string == "spatial") {
124+
new_mode = RenderingServerEnums::SHADER_SPATIAL;
125+
} else {
126+
new_mode = RenderingServerEnums::SHADER_MAX;
127+
}
128+
if (new_mode != RenderingServerEnums::SHADER_MAX) {
129+
info.functions = ShaderTypes::get_singleton()->get_functions(new_mode);
130+
info.render_modes = ShaderTypes::get_singleton()->get_modes(new_mode);
131+
info.shader_types = ShaderTypes::get_singleton()->get_types();
132+
info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
133+
Error err = sl.compile(p_code, info);
134+
if (err) {
135+
ShaderDeprecatedConverter sdc;
136+
if (sdc.is_code_deprecated(p_code)) {
137+
ERR_FAIL_COND_MSG(!sdc.convert_code(p_code), vformat("Shader conversion failed (line %d): %s", sdc.get_error_line(), sdc.get_error_text()));
138+
code = sdc.emit_code();
139+
preprocessed_code = code;
140+
} else if (sdc.get_error_text() != "") { // Preprocessing failed.
141+
WARN_PRINT(vformat("Shader conversion failed (line %d): %s", sdc.get_error_line(), sdc.get_error_text()));
142+
} // If the code is reported as not deprecated, let it fall through to the compile step after this if block so that we get the full compile error.
143+
}
144+
}
145+
}
146+
#endif
95147

96148
{
97149
String path = get_path();
@@ -103,7 +155,7 @@ void Shader::set_code(const String &p_code) {
103155
// 2) Server does not do interaction with Resource filetypes, this is a scene level feature.
104156
HashSet<Ref<ShaderInclude>> new_include_dependencies;
105157
ShaderPreprocessor preprocessor;
106-
Error result = preprocessor.preprocess(p_code, path, preprocessed_code, nullptr, nullptr, nullptr, &new_include_dependencies);
158+
Error result = preprocessor.preprocess(code, path, preprocessed_code, nullptr, nullptr, nullptr, &new_include_dependencies);
107159
if (result == OK) {
108160
// This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower)
109161
include_dependencies = new_include_dependencies;
@@ -274,6 +326,20 @@ Array Shader::_get_shader_uniform_list(bool p_get_groups) {
274326
return ret;
275327
}
276328

329+
void Shader::_start_load(const StringName &p_res_format_type, int p_res_format_version) {
330+
#ifndef DISABLE_DEPRECATED
331+
if ((p_res_format_type == "binary" && p_res_format_version == 3) || (p_res_format_type == "text" && p_res_format_version == 2)) {
332+
set_meta(_LOAD_COMPAT_META_PROPERTY, true);
333+
}
334+
#endif
335+
}
336+
337+
void Shader::_finish_load(const StringName &p_res_format_type, int p_res_format_version) {
338+
#ifndef DISABLE_DEPRECATED
339+
set_meta(_LOAD_COMPAT_META_PROPERTY, Variant());
340+
#endif
341+
}
342+
277343
void Shader::_bind_methods() {
278344
ClassDB::bind_method(D_METHOD("get_mode"), &Shader::get_mode);
279345

@@ -329,9 +395,22 @@ Ref<Resource> ResourceFormatLoaderShader::load(const String &p_path, const Strin
329395
Ref<Shader> shader;
330396
shader.instantiate();
331397

398+
#ifndef DISABLE_DEPRECATED
399+
bool is_deprecated = p_path.get_extension().to_lower() == "shader";
400+
if (is_deprecated) {
401+
shader->set_meta(_LOAD_COMPAT_META_PROPERTY, true);
402+
}
403+
#endif
404+
332405
shader->set_include_path(p_path);
333406
shader->set_code(str);
334407

408+
#ifndef DISABLE_DEPRECATED
409+
if (is_deprecated) {
410+
shader->set_meta(_LOAD_COMPAT_META_PROPERTY, Variant());
411+
}
412+
#endif
413+
335414
if (r_error) {
336415
*r_error = OK;
337416
}
@@ -340,6 +419,9 @@ Ref<Resource> ResourceFormatLoaderShader::load(const String &p_path, const Strin
340419
}
341420

342421
void ResourceFormatLoaderShader::get_recognized_extensions(List<String> *p_extensions) const {
422+
#ifndef DISABLE_DEPRECATED
423+
p_extensions->push_back("shader");
424+
#endif
343425
p_extensions->push_back("gdshader");
344426
}
345427

@@ -351,6 +433,11 @@ String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const
351433
if (p_path.has_extension("gdshader")) {
352434
return "Shader";
353435
}
436+
#ifndef DISABLE_DEPRECATED
437+
if (p_path.has_extension("shader")) {
438+
return "Shader";
439+
}
440+
#endif
354441
return "";
355442
}
356443

scene/resources/shader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ class Shader : public Resource {
101101

102102
virtual RID get_rid() const override;
103103

104+
virtual void _start_load(const StringName &p_res_format_type, int p_res_format_version) override;
105+
virtual void _finish_load(const StringName &p_res_format_type, int p_res_format_version) override;
106+
104107
Shader();
105108
~Shader();
106109
};

0 commit comments

Comments
 (0)