diff options
Diffstat (limited to 'servers')
22 files changed, 504 insertions, 148 deletions
diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 4e7db7d0a5..ff6d769a86 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -44,40 +44,49 @@ DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[Displa int DisplayServer::server_create_count = 1; -void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { +int DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } -void DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) { +int DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) { WARN_PRINT("Global menus not supported by this display server."); + return -1; } int DisplayServer::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const { @@ -159,6 +168,11 @@ Ref<Texture2D> DisplayServer::global_menu_get_item_icon(const String &p_menu_roo return Ref<Texture2D>(); } +int DisplayServer::global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return 0; +} + void DisplayServer::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) { WARN_PRINT("Global menus not supported by this display server."); } @@ -207,6 +221,10 @@ void DisplayServer::global_menu_set_item_icon(const String &p_menu_root, int p_i WARN_PRINT("Global menus not supported by this display server."); } +void DisplayServer::global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level) { + WARN_PRINT("Global menus not supported by this display server."); +} + int DisplayServer::global_menu_get_item_count(const String &p_menu_root) const { WARN_PRINT("Global menus not supported by this display server."); return 0; @@ -535,6 +553,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("global_menu_get_item_state", "menu_root", "idx"), &DisplayServer::global_menu_get_item_state); ClassDB::bind_method(D_METHOD("global_menu_get_item_max_states", "menu_root", "idx"), &DisplayServer::global_menu_get_item_max_states); ClassDB::bind_method(D_METHOD("global_menu_get_item_icon", "menu_root", "idx"), &DisplayServer::global_menu_get_item_icon); + ClassDB::bind_method(D_METHOD("global_menu_get_item_indentation_level", "menu_root", "idx"), &DisplayServer::global_menu_get_item_indentation_level); ClassDB::bind_method(D_METHOD("global_menu_set_item_checked", "menu_root", "idx", "checked"), &DisplayServer::global_menu_set_item_checked); ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable); @@ -549,6 +568,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("global_menu_set_item_state", "menu_root", "idx", "state"), &DisplayServer::global_menu_set_item_state); ClassDB::bind_method(D_METHOD("global_menu_set_item_max_states", "menu_root", "idx", "max_states"), &DisplayServer::global_menu_set_item_max_states); ClassDB::bind_method(D_METHOD("global_menu_set_item_icon", "menu_root", "idx", "icon"), &DisplayServer::global_menu_set_item_icon); + ClassDB::bind_method(D_METHOD("global_menu_set_item_indentation_level", "menu_root", "idx", "level"), &DisplayServer::global_menu_set_item_indentation_level); ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu_root", "idx"), &DisplayServer::global_menu_remove_item); ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear); diff --git a/servers/display_server.h b/servers/display_server.h index 8632b53f7b..a5c42617af 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -127,15 +127,15 @@ public: virtual bool has_feature(Feature p_feature) const = 0; virtual String get_name() const = 0; - virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1); - virtual void global_menu_add_separator(const String &p_menu_root, int p_index = -1); + virtual int global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1); + virtual int global_menu_add_separator(const String &p_menu_root, int p_index = -1); virtual int global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const; virtual int global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const; @@ -153,6 +153,7 @@ public: virtual int global_menu_get_item_state(const String &p_menu_root, int p_idx) const; virtual int global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const; virtual Ref<Texture2D> global_menu_get_item_icon(const String &p_menu_root, int p_idx) const; + virtual int global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const; virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked); virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable); @@ -167,6 +168,7 @@ public: virtual void global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state); virtual void global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states); virtual void global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon); + virtual void global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level); virtual int global_menu_get_item_count(const String &p_menu_root) const; diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 126bb08c94..27b49014d8 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -204,7 +204,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer2D::map_create); ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer2D::map_set_active); - ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer2D::map_is_active); + ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer2D::map_is_active); ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer2D::map_set_cell_size); ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin); diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 115eda7b30..206698f97c 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -41,7 +41,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer3D::map_create); ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer3D::map_set_active); - ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer3D::map_is_active); + ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer3D::map_is_active); ClassDB::bind_method(D_METHOD("map_set_up", "map", "up"), &NavigationServer3D::map_set_up); ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer3D::map_get_up); ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer3D::map_set_cell_size); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 6433a39863..d3601274b5 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -114,12 +114,16 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) { for (int i = 0; i < gen_code.defines.size(); i++) { print_line(gen_code.defines[i]); } + + HashMap<String, String>::Iterator el = gen_code.code.begin(); + while (el) { + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; + } + print_line("\n**uniforms:\n" + gen_code.uniforms); - // print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - // print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); + print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]); + print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]); #endif scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 556db086b2..0911ee595f 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -150,6 +150,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { depth_draw = DepthDraw(depth_drawi); depth_test = DepthTest(depth_testi); cull_mode = Cull(cull_modei); + uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; #if 0 print_line("**compiling shader:"); @@ -158,11 +159,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - RBMap<String, String>::Element *el = gen_code.code.front(); + HashMap<String, String>::Iterator el = gen_code.code.begin(); while (el) { - print_line("\n**code " + el->key() + ":\n" + el->value()); - - el = el->next(); + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; } print_line("\n**uniforms:\n" + gen_code.uniforms); @@ -396,7 +396,11 @@ void SceneShaderForwardClustered::ShaderData::get_shader_uniform_list(List<Prope HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + // Don't expose any of these. continue; } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index fa9ebde1b2..d6b526fa4a 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -174,6 +174,7 @@ public: bool uses_time = false; bool writes_modelview_or_projection = false; bool uses_world_coordinates = false; + bool uses_screen_texture_mipmaps = false; Cull cull_mode = CULL_DISABLED; uint64_t last_pass = 0; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 01b54607bc..85c9e1db2a 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -158,11 +158,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - RBMap<String, String>::Element * el = gen_code.code.front(); + HashMap<String, String>::Iterator el = gen_code.code.begin(); while (el) { - print_line("\n**code " + el->key() + ":\n" + el->value()); - - el = el->next(); + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; } print_line("\n**uniforms:\n" + gen_code.uniforms); @@ -353,7 +352,10 @@ void SceneShaderForwardMobile::ShaderData::get_shader_uniform_list(List<Property HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { continue; } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index c1b08ee4c9..38a2340d40 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1361,6 +1361,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p Item *ci = p_item_list; Rect2 back_buffer_rect; bool backbuffer_copy = false; + bool backbuffer_gen_mipmaps = false; Item *canvas_group_owner = nullptr; @@ -1389,6 +1390,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (!material_screen_texture_found) { backbuffer_copy = true; back_buffer_rect = Rect2(); + backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps; } } @@ -1474,9 +1476,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); item_count = 0; - texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true); + texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps); backbuffer_copy = false; + backbuffer_gen_mipmaps = false; material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies } @@ -1980,6 +1983,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { ubo_size = 0; uniforms.clear(); uses_screen_texture = false; + uses_screen_texture_mipmaps = false; uses_sdf = false; uses_time = false; @@ -1990,7 +1994,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { ShaderCompiler::GeneratedCode gen_code; int blend_mode = BLEND_MODE_MIX; - uses_screen_texture = false; ShaderCompiler::IdentifierActions actions; actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX; @@ -2015,6 +2018,8 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code); ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); + uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + if (version.is_null()) { version = canvas_singleton->shader.canvas_shader.version_create(); } @@ -2025,12 +2030,16 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { for (int i = 0; i < gen_code.defines.size(); i++) { print_line(gen_code.defines[i]); } + + HashMap<String, String>::Iterator el = gen_code.code.begin(); + while (el) { + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; + } + print_line("\n**uniforms:\n" + gen_code.uniforms); - print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); + print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]); + print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]); #endif canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines); ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version)); @@ -2175,7 +2184,11 @@ void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_list(List<Prop HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + // Don't expose any of these. continue; } if (E.value.texture_order >= 0) { diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 5eb4cee4c6..bcbbbaa1a0 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -174,6 +174,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_screen_texture = false; + bool uses_screen_texture_mipmaps = false; bool uses_sdf = false; bool uses_time = false; diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl index 0438671dd2..0b43af7738 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl @@ -30,7 +30,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh; #ifdef MODE_GEN_BLUR_SIZE float get_depth_at_pos(vec2 uv) { - float depth = textureLod(source_depth, uv, 0.0).x; + float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0; if (params.orthogonal) { depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; } else { diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl index a3b3938ee9..a06cacfabe 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl @@ -52,7 +52,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight; #ifdef MODE_GEN_BLUR_SIZE float get_depth_at_pos(vec2 uv) { - float depth = textureLod(source_depth, uv, 0.0).x; + float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0; if (params.orthogonal) { depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; } else { diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 41dd1ccc40..fa8406e7a1 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -941,6 +941,12 @@ void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringNa continue; //instance uniforms don't appear in the buffer } + if (E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + continue; + } + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { //this is a global variable, get the index to it GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key); @@ -1052,6 +1058,12 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va Vector<RID> textures; + if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE || + p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE || + p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + continue; + } + if (p_texture_uniforms[i].global) { uses_global_textures = true; @@ -1307,7 +1319,7 @@ bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap< update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true); } - if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) { + if (p_ubo_size == 0 && (p_texture_uniforms.size() == 0)) { // This material does not require an uniform set, so don't create it. return false; } diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index dc3f35f942..1516e5e4fd 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -327,8 +327,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0); - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); - s->vertex_buffer_size = p_surface.vertex_data.size(); + if (p_surface.vertex_data.size()) { + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage); + s->vertex_buffer_size = p_surface.vertex_data.size(); + } if (p_surface.attribute_data.size()) { s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data); @@ -345,7 +347,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) } if (p_surface.index_count) { - bool is_index_16 = p_surface.vertex_count <= 65536; + bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0; s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); s->index_count = p_surface.index_count; @@ -364,6 +366,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) } } + ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both"); + s->aabb = p_surface.aabb; s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. @@ -377,7 +381,11 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(s->vertex_buffer); + if (s->vertex_buffer.is_valid()) { + u.append_id(s->vertex_buffer); + } else { + u.append_id(default_rd_storage_buffer); + } uniforms.push_back(u); } { @@ -416,7 +424,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) mesh->bone_aabbs.resize(p_surface.bone_aabbs.size()); } for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { - mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); + const AABB &bone = p_surface.bone_aabbs[i]; + if (!bone.has_no_volume()) { + mesh->bone_aabbs.write[i].merge_with(bone); + } } mesh->aabb.merge_with(p_surface.aabb); } @@ -467,6 +478,7 @@ void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, i ERR_FAIL_COND(!mesh); ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); ERR_FAIL_COND(p_data.size() == 0); + ERR_FAIL_COND(mesh->surfaces[p_surface]->vertex_buffer.is_null()); uint64_t data_size = p_data.size(); const uint8_t *r = p_data.ptr(); @@ -524,7 +536,9 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const { RS::SurfaceData sd; sd.format = s.format; - sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + if (s.vertex_buffer.is_valid()) { + sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + } if (s.attribute_buffer.is_valid()) { sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer); } @@ -702,7 +716,9 @@ void MeshStorage::mesh_clear(RID p_mesh) { ERR_FAIL_COND(!mesh); for (uint32_t i = 0; i < mesh->surface_count; i++) { Mesh::Surface &s = *mesh->surfaces[i]; - RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions + if (s.vertex_buffer.is_valid()) { + RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions + } if (s.attribute_buffer.is_valid()) { RD::get_singleton()->free(s.attribute_buffer); } @@ -848,7 +864,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3 } MeshInstance::Surface s; - if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) { + if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) { //surface warrants transform s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true); diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index c2cf08812c..f14350305a 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -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,6 +542,13 @@ 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)) { // Texture layouts are different for OpenGL GLSL and Vulkan GLSL if (!RS::get_singleton()->is_low_end()) { @@ -892,12 +904,39 @@ 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) { @@ -1155,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; @@ -1404,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(); diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h index 06f42e9f0f..1ad43daf5f 100644 --- a/servers/rendering/shader_compiler.h +++ b/servers/rendering/shader_compiler.h @@ -80,6 +80,7 @@ public: bool uses_global_textures; bool uses_fragment_time; bool uses_vertex_time; + bool uses_screen_texture_mipmaps; }; struct DefaultIdentifierActions { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 81e4d5e217..cab92e6e20 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -200,6 +200,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "HINT_ANISOTROPY_TEXTURE", "HINT_RANGE", "HINT_INSTANCE_INDEX", + "HINT_SCREEN_TEXTURE", + "HINT_NORMAL_ROUGHNESS_TEXTURE", + "HINT_DEPTH_TEXTURE", "FILTER_NEAREST", "FILTER_LINEAR", "FILTER_NEAREST_MIPMAP", @@ -363,6 +366,10 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_ROUGHNESS_A, "hint_roughness_a", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal", CF_UNSPECIFIED, {}, {} }, { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_SCREEN_TEXTURE, "hint_screen_texture", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_NORMAL_ROUGHNESS_TEXTURE, "hint_normal_roughness_texture", CF_UNSPECIFIED, {}, {} }, + { TK_HINT_DEPTH_TEXTURE, "hint_depth_texture", CF_UNSPECIFIED, {}, {} }, + { TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} }, { TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} }, { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} }, @@ -1096,6 +1103,15 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) { case ShaderNode::Uniform::HINT_ANISOTROPY: { result = "hint_anisotropy"; } break; + case ShaderNode::Uniform::HINT_SCREEN_TEXTURE: { + result = "hint_screen_texture"; + } break; + case ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE: { + result = "hint_normal_roughness_texture"; + } break; + case ShaderNode::Uniform::HINT_DEPTH_TEXTURE: { + result = "hint_depth_texture"; + } break; default: break; } @@ -8605,6 +8621,15 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } } break; + case TK_HINT_SCREEN_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE; + } break; + case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE; + } break; + case TK_HINT_DEPTH_TEXTURE: { + new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE; + } break; case TK_FILTER_NEAREST: { new_filter = FILTER_NEAREST; } break; @@ -8629,6 +8654,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f case TK_REPEAT_ENABLE: { new_repeat = REPEAT_ENABLE; } break; + default: break; } @@ -8653,9 +8679,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f if (new_filter != FILTER_DEFAULT) { if (uniform.filter != FILTER_DEFAULT) { if (uniform.filter == new_filter) { - _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_filter_name(new_filter))); + _set_error(vformat(RTR("Duplicated filter mode: '%s'."), get_texture_filter_name(new_filter))); } else { - _set_error(vformat(RTR("Redefinition of hint: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter))); + _set_error(vformat(RTR("Redefinition of filter mode: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter))); } return ERR_PARSE_ERROR; } else { @@ -8666,9 +8692,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f if (new_repeat != REPEAT_DEFAULT) { if (uniform.repeat != REPEAT_DEFAULT) { if (uniform.repeat == new_repeat) { - _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_repeat_name(new_repeat))); + _set_error(vformat(RTR("Duplicated repeat mode: '%s'."), get_texture_repeat_name(new_repeat))); } else { - _set_error(vformat(RTR("Redefinition of hint: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat))); + _set_error(vformat(RTR("Redefinition of repeat mode: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat))); } return ERR_PARSE_ERROR; } else { @@ -10309,6 +10335,9 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ options.push_back("hint_roughness_gray"); options.push_back("hint_roughness_normal"); options.push_back("hint_roughness_r"); + options.push_back("hint_screen_texture"); + options.push_back("hint_normal_roughness_texture"); + options.push_back("hint_depth_texture"); options.push_back("source_color"); options.push_back("repeat_enable"); options.push_back("repeat_disable"); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index bfec6e1df6..75b713d167 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -176,6 +176,9 @@ public: TK_HINT_SOURCE_COLOR, TK_HINT_RANGE, TK_HINT_INSTANCE_INDEX, + TK_HINT_SCREEN_TEXTURE, + TK_HINT_NORMAL_ROUGHNESS_TEXTURE, + TK_HINT_DEPTH_TEXTURE, TK_FILTER_NEAREST, TK_FILTER_LINEAR, TK_FILTER_NEAREST_MIPMAP, @@ -667,6 +670,9 @@ public: HINT_DEFAULT_WHITE, HINT_DEFAULT_TRANSPARENT, HINT_ANISOTROPY, + HINT_SCREEN_TEXTURE, + HINT_NORMAL_ROUGHNESS_TEXTURE, + HINT_DEPTH_TEXTURE, HINT_MAX }; diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp index d118c73c4a..3766477070 100644 --- a/servers/rendering/shader_preprocessor.cpp +++ b/servers/rendering/shader_preprocessor.cpp @@ -349,6 +349,8 @@ void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) { process_ifdef(p_tokenizer); } else if (directive == "ifndef") { process_ifndef(p_tokenizer); + } else if (directive == "elif") { + process_elif(p_tokenizer); } else if (directive == "else") { process_else(p_tokenizer); } else if (directive == "endif") { @@ -415,10 +417,67 @@ void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) { } } +void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + + if (state->current_branch == nullptr || state->current_branch->else_defined) { + set_error(RTR("Unmatched elif."), line); + return; + } + if (state->previous_region != nullptr) { + state->previous_region->to_line = line - 1; + } + + String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges(); + if (body.is_empty()) { + set_error(RTR("Missing condition."), line); + return; + } + + Error error = expand_condition(body, line, body); + if (error != OK) { + return; + } + + error = expand_macros(body, line, body); + if (error != OK) { + return; + } + + Expression expression; + Vector<String> names; + error = expression.parse(body, names); + if (error != OK) { + set_error(expression.get_error_text(), line); + return; + } + + Variant v = expression.execute(Array(), nullptr, false); + if (v.get_type() == Variant::NIL) { + set_error(RTR("Condition evaluation error."), line); + return; + } + + bool skip = false; + for (int i = 0; i < state->current_branch->conditions.size(); i++) { + if (state->current_branch->conditions[i]) { + skip = true; + break; + } + } + + bool success = !skip && v.booleanize(); + start_branch_condition(p_tokenizer, success, true); + + if (state->save_regions) { + add_region(line + 1, success, state->previous_region->parent); + } +} + void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { const int line = p_tokenizer->get_line(); - if (state->skip_stack_else.is_empty()) { + if (state->current_branch == nullptr || state->current_branch->else_defined) { set_error(RTR("Unmatched else."), line); return; } @@ -428,17 +487,14 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { p_tokenizer->advance('\n'); - bool skip = state->skip_stack_else[state->skip_stack_else.size() - 1]; - state->skip_stack_else.remove_at(state->skip_stack_else.size() - 1); - - Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_filename]; - int index = vec.size() - 1; - if (index >= 0) { - SkippedCondition *cond = vec[index]; - if (cond->end_line == -1) { - cond->end_line = p_tokenizer->get_line(); + bool skip = false; + for (int i = 0; i < state->current_branch->conditions.size(); i++) { + if (state->current_branch->conditions[i]) { + skip = true; + break; } } + state->current_branch->else_defined = true; if (state->save_regions) { add_region(line + 1, !skip, state->previous_region->parent); @@ -462,16 +518,10 @@ void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) { state->previous_region = state->previous_region->parent; } - Vector<SkippedCondition *> vec = state->skipped_conditions[state->current_filename]; - int index = vec.size() - 1; - if (index >= 0) { - SkippedCondition *cond = vec[index]; - if (cond->end_line == -1) { - cond->end_line = p_tokenizer->get_line(); - } - } - p_tokenizer->advance('\n'); + + state->current_branch = state->current_branch->parent; + state->branches.pop_back(); } void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { @@ -483,7 +533,12 @@ void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) { return; } - Error error = expand_macros(body, line, body); + Error error = expand_condition(body, line, body); + if (error != OK) { + return; + } + + error = expand_macros(body, line, body); if (error != OK) { return; } @@ -703,24 +758,19 @@ void ShaderPreprocessor::add_region(int p_line, bool p_enabled, Region *p_parent state->previous_region = &state->regions[region.file].push_back(region)->get(); } -void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success) { - state->condition_depth++; - - if (p_success) { - state->skip_stack_else.push_back(true); +void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue) { + if (!p_continue) { + state->condition_depth++; + state->current_branch = &state->branches.push_back(Branch(p_success, state->current_branch))->get(); } else { - SkippedCondition *cond = memnew(SkippedCondition()); - cond->start_line = p_tokenizer->get_line(); - state->skipped_conditions[state->current_filename].push_back(cond); - + state->current_branch->conditions.push_back(p_success); + } + if (!p_success) { Vector<String> ends; + ends.push_back("elif"); ends.push_back("else"); ends.push_back("endif"); - if (next_directive(p_tokenizer, ends) == "else") { - state->skip_stack_else.push_back(false); - } else { - state->skip_stack_else.push_back(true); - } + next_directive(p_tokenizer, ends); } } @@ -737,47 +787,173 @@ void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) { add_to_output(line); } -Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) { - Vector<Pair<String, Define *>> active_defines; - active_defines.resize(state->defines.size()); - int index = 0; - for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) { - active_defines.set(index++, Pair<String, Define *>(E->key(), E->get())); +Error ShaderPreprocessor::expand_condition(const String &p_string, int p_line, String &r_expanded) { + // Checks bracket count to be even + check the cursor position. + { + int bracket_start_count = 0; + int bracket_end_count = 0; + + for (int i = 0; i < p_string.size(); i++) { + switch (p_string[i]) { + case CURSOR: + state->completion_type = COMPLETION_TYPE_CONDITION; + break; + case '(': + bracket_start_count++; + break; + case ')': + bracket_end_count++; + break; + } + } + if (bracket_start_count > bracket_end_count) { + _set_expected_error(")", p_line); + return FAILED; + } + if (bracket_end_count > bracket_start_count) { + _set_expected_error("(", p_line); + return FAILED; + } } - return expand_macros(p_string, p_line, active_defines, r_expanded); + String result = p_string; + + int index = 0; + int index_start = 0; + int index_end = 0; + + while (find_match(result, "defined", index, index_start)) { + bool open_bracket = false; + bool found_word = false; + bool word_completed = false; + + LocalVector<char32_t> text; + int post_bracket_index = -1; + int size = result.size(); + + for (int i = (index_start - 1); i < size; i++) { + char32_t c = result[i]; + if (c == 0) { + if (found_word) { + word_completed = true; + } + break; + } + char32_t cs[] = { c, '\0' }; + String s = String(cs); + bool is_space = is_char_space(c); + + if (word_completed) { + if (c == ')') { + continue; + } + if (c == '|' || c == '&') { + if (open_bracket) { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + break; + } else if (!is_space) { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + } else if (is_space) { + if (found_word && !open_bracket) { + index_end = i; + word_completed = true; + } + } else if (c == '(') { + if (open_bracket) { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + open_bracket = true; + } else if (c == ')') { + if (open_bracket) { + if (!found_word) { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + open_bracket = false; + post_bracket_index = i + 1; + } else { + index_end = i; + } + word_completed = true; + } else if (is_char_word(c)) { + text.push_back(c); + found_word = true; + } else { + _set_unexpected_token_error(s, p_line); + return FAILED; + } + } + + if (word_completed) { + if (open_bracket) { + _set_expected_error(")", p_line); + return FAILED; + } + if (post_bracket_index != -1) { + index_end = post_bracket_index; + } + + String body = state->defines.has(vector_to_string(text)) ? "true" : "false"; + String temp = result; + + result = result.substr(0, index) + body; + index_start = result.length(); + if (index_end > 0) { + result += temp.substr(index_end); + } + } else { + set_error(RTR("Invalid macro name."), p_line); + return FAILED; + } + } + r_expanded = result; + return OK; } -Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_expanded) { - r_expanded = p_string; - // When expanding macros we must only evaluate them once. - // Later we continue expanding but with the already - // evaluated macros removed. - for (int i = 0; i < p_defines.size(); i++) { - Pair<String, Define *> define_pair = p_defines[i]; - - Error error = expand_macros_once(r_expanded, p_line, define_pair, r_expanded); - if (error != OK) { - return error; +Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) { + String iterative = p_string; + int pass_count = 0; + bool expanded = true; + + while (expanded) { + expanded = false; + + // As long as we find something to expand, keep going. + for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) { + if (expand_macros_once(iterative, p_line, E, iterative)) { + expanded = true; + } } - // Remove expanded macro and recursively replace remaining. - p_defines.remove_at(i); - return expand_macros(r_expanded, p_line, p_defines, r_expanded); + pass_count++; + if (pass_count > 50) { + set_error(RTR("Macro expansion limit exceeded."), p_line); + break; + } } + r_expanded = iterative; + + if (!state->error.is_empty()) { + return FAILED; + } return OK; } -Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded) { +bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded) { String result = p_line; - const String &key = p_define_pair.first; - const Define *define = p_define_pair.second; + const String &key = p_define_pair->key(); + const Define *define = p_define_pair->value(); int index_start = 0; int index = 0; - while (find_match(result, key, index, index_start)) { + if (find_match(result, key, index, index_start)) { String body = define->body; if (define->arguments.size() > 0) { // Complex macro with arguments. @@ -785,14 +961,14 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu int args_end = p_line.find(")", args_start); if (args_start == -1 || args_end == -1) { set_error(RTR("Missing macro argument parenthesis."), p_line_number); - return FAILED; + return false; } String values = result.substr(args_start + 1, args_end - (args_start + 1)); Vector<String> args = values.split(","); if (args.size() != define->arguments.size()) { set_error(RTR("Invalid macro argument count."), p_line_number); - return FAILED; + return false; } // Insert macro arguments into the body. @@ -814,11 +990,13 @@ Error ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_nu // Manually reset index_start to where the body value of the define finishes. // This ensures we don't skip another instance of this macro in the string. index_start = index + body.length() + 1; - break; } + + r_expanded = result; + return true; } - r_expanded = result; - return OK; + + return false; } bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) { @@ -909,12 +1087,6 @@ void ShaderPreprocessor::clear() { memdelete(E->get()); } - for (const RBMap<String, Vector<SkippedCondition *>>::Element *E = state->skipped_conditions.front(); E; E = E->next()) { - for (SkippedCondition *condition : E->get()) { - memdelete(condition); - } - } - memdelete(state); } state_owner = false; @@ -1030,7 +1202,7 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen switch (pp_state.completion_type) { case COMPLETION_TYPE_DIRECTIVE: { List<String> options; - get_keyword_list(&options, true); + get_keyword_list(&options, true, true); for (const String &E : options) { ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); @@ -1049,6 +1221,11 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen } } break; + case COMPLETION_TYPE_CONDITION: { + ScriptLanguage::CodeCompletionOption option("defined", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_completion_options->push_back(option); + + } break; case COMPLETION_TYPE_INCLUDE_PATH: { if (p_include_completion_func && r_completion_options) { p_include_completion_func(r_completion_options); @@ -1062,8 +1239,12 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen return err; } -void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords) { +void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords) { r_keywords->push_back("define"); + if (!p_ignore_context_keywords) { + r_keywords->push_back("defined"); + } + r_keywords->push_back("elif"); if (p_include_shader_keywords) { r_keywords->push_back("else"); } diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h index 41b574298d..b4e7c7199f 100644 --- a/servers/rendering/shader_preprocessor.h +++ b/servers/rendering/shader_preprocessor.h @@ -50,6 +50,7 @@ public: COMPLETION_TYPE_DIRECTIVE, COMPLETION_TYPE_PRAGMA_DIRECTIVE, COMPLETION_TYPE_PRAGMA, + COMPLETION_TYPE_CONDITION, COMPLETION_TYPE_INCLUDE_PATH, }; @@ -130,14 +131,23 @@ private: String body; }; - struct SkippedCondition { - int start_line = -1; - int end_line = -1; + struct Branch { + Vector<bool> conditions; + Branch *parent = nullptr; + bool else_defined = false; + + Branch() {} + + Branch(bool p_condition, Branch *p_parent) : + parent(p_parent) { + conditions.push_back(p_condition); + } }; struct State { RBMap<String, Define *> defines; - Vector<bool> skip_stack_else; + List<Branch> branches; + Branch *current_branch = nullptr; int condition_depth = 0; RBSet<String> includes; List<uint64_t> cyclic_include_hashes; // Holds code hash of includes. @@ -149,7 +159,6 @@ private: bool save_regions = false; RBMap<String, List<Region>> regions; Region *previous_region = nullptr; - RBMap<String, Vector<SkippedCondition *>> skipped_conditions; bool disabled = false; CompletionType completion_type = COMPLETION_TYPE_NONE; HashSet<Ref<ShaderInclude>> shader_includes; @@ -167,8 +176,17 @@ private: static String vector_to_string(const LocalVector<char32_t> &p_v, int p_start = 0, int p_end = -1); static String tokens_to_string(const LocalVector<Token> &p_tokens); + void _set_expected_error(const String &p_what, int p_line) { + set_error(vformat(RTR("Expected a '%s'."), p_what), p_line); + } + + void _set_unexpected_token_error(const String &p_what, int p_line) { + set_error(vformat(RTR("Unexpected token '%s'."), p_what), p_line); + } + void process_directive(Tokenizer *p_tokenizer); void process_define(Tokenizer *p_tokenizer); + void process_elif(Tokenizer *p_tokenizer); void process_else(Tokenizer *p_tokenizer); void process_endif(Tokenizer *p_tokenizer); void process_if(Tokenizer *p_tokenizer); @@ -179,12 +197,12 @@ private: void process_undef(Tokenizer *p_tokenizer); void add_region(int p_line, bool p_enabled, Region *p_parent_region); - void start_branch_condition(Tokenizer *p_tokenizer, bool p_success); + void start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue = false); + Error expand_condition(const String &p_string, int p_line, String &r_result); void expand_output_macros(int p_start, int p_line); Error expand_macros(const String &p_string, int p_line, String &r_result); - Error expand_macros(const String &p_string, int p_line, Vector<Pair<String, Define *>> p_defines, String &r_result); - Error expand_macros_once(const String &p_line, int p_line_number, Pair<String, Define *> p_define_pair, String &r_expanded); + bool expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded); bool find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start); String next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives); @@ -202,7 +220,7 @@ public: Error preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, List<Region> *r_regions = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr); - static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords); + static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords = false); static void get_pragma_list(List<String> *r_pragmas); ShaderPreprocessor(); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a54d4f0384..dcdc56d948 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -627,7 +627,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint const int *src = indices.ptr(); for (int i = 0; i < p_index_array_len; i++) { - if (p_vertex_array_len < (1 << 16)) { + if (p_vertex_array_len < (1 << 16) && p_vertex_array_len > 0) { uint16_t v = src[i]; memcpy(&iw[i * 2], &v, 2); @@ -836,9 +836,8 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i break; } /* determine whether using 16 or 32 bits indices */ - if (p_vertex_len >= (1 << 16)) { + if (p_vertex_len >= (1 << 16) || p_vertex_len == 0) { elem_size = 4; - } else { elem_size = 2; } @@ -909,8 +908,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa } } - ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // Mandatory - if (p_blend_shapes.size()) { // Validate format for morphs. for (int i = 0; i < p_blend_shapes.size(); i++) { @@ -944,6 +941,12 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa uint32_t mask = (1 << ARRAY_MAX) - 1; format |= (~mask) & p_compress_format; // Make the full format. + if ((format & RS::ARRAY_FORMAT_VERTEX) == 0 && !(format & RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) { + ERR_PRINT("Mesh created without vertex array. This mesh will not be visible with the default shader. If using an empty vertex array is intentional, create the mesh with the ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY flag to silence this error."); + // Set the flag here after warning to suppress errors down the pipeline. + format |= RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY; + } + int vertex_array_size = vertex_element_size * array_len; int attrib_array_size = attrib_element_size * array_len; int skin_array_size = skin_element_size * array_len; @@ -1378,7 +1381,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p Vector<uint8_t> attrib_data = p_data.attribute_data; Vector<uint8_t> skin_data = p_data.skin_data; - ERR_FAIL_COND_V(vertex_data.size() == 0, Array()); + ERR_FAIL_COND_V(vertex_data.size() == 0 && (p_data.format & RS::ARRAY_FORMAT_VERTEX), Array()); int vertex_len = p_data.vertex_count; Vector<uint8_t> index_data = p_data.index_data; diff --git a/servers/rendering_server.h b/servers/rendering_server.h index a2fe9caf19..d04c62bfd2 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -244,7 +244,7 @@ public: enum ArrayFormat { /* ARRAY FORMAT FLAGS */ - ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // Mandatory + ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL, ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT, ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR, @@ -262,17 +262,19 @@ public: ARRAY_FORMAT_CUSTOM_BASE = (ARRAY_INDEX + 1), ARRAY_FORMAT_CUSTOM_BITS = 3, + ARRAY_FORMAT_CUSTOM_MASK = 0x7, ARRAY_FORMAT_CUSTOM0_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + 0), ARRAY_FORMAT_CUSTOM1_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS), ARRAY_FORMAT_CUSTOM2_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 2), ARRAY_FORMAT_CUSTOM3_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 3), - ARRAY_FORMAT_CUSTOM_MASK = 0x7, ARRAY_COMPRESS_FLAGS_BASE = (ARRAY_INDEX + 1 + 12), ARRAY_FLAG_USE_2D_VERTICES = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 0), ARRAY_FLAG_USE_DYNAMIC_UPDATE = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 1), ARRAY_FLAG_USE_8_BONE_WEIGHTS = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 2), + + ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY = 1 << (ARRAY_INDEX + 1 + 15), }; enum PrimitiveType { |