diff options
147 files changed, 971 insertions, 5768 deletions
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index 15a7be9c4f..7b144e6e43 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -76,9 +76,9 @@ jobs: path: bin/* retention-days: 14 - linux-editor-sanitizers-mono: + linux-editor-sanitizers: runs-on: "ubuntu-20.04" - name: Editor w/ Mono and sanitizers (target=debug, tools=yes, tests=yes, use_asan=yes, use_ubsan=yes) + name: Editor and sanitizers (target=debug, tools=yes, tests=yes, use_asan=yes, use_ubsan=yes) steps: - uses: actions/checkout@v2 @@ -94,7 +94,8 @@ jobs: - name: Configure dependencies run: | sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \ - libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm + libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm \ + xvfb wget unzip # Upload cache on completion and check it out now - name: Load .scons_cache directory @@ -126,17 +127,47 @@ jobs: scons --version # We should always be explicit with our flags usage here since it's gonna be sure to always set those flags + # [Workaround] SwiftShader doesn't support tesselation, so we skip Godot check about it - name: Compilation env: SCONS_CACHE: ${{github.workspace}}/.scons_cache/ run: | - scons tools=yes tests=yes target=debug module_mono_enabled=yes mono_glue=no use_asan=yes use_ubsan=yes + sed -i "s|ERR_FAIL_COND_V(p_rasterization_state.patch_control_points|//ERR_FAIL_COND_V(p_rasterization_state.patch_control_points|" drivers/vulkan/rendering_device_vulkan.cpp + scons tools=yes tests=yes target=debug debug_symbols=no use_asan=yes use_ubsan=yes ls -l bin/ # Execute unit tests for the editor - name: Unit Tests run: | - ./bin/godot.linuxbsd.tools.64s.mono --test + ./bin/godot.linuxbsd.tools.64s --test + + # Download, unzip and setup SwiftShader library [d4550ab8d3f] + - name: Download SwiftShader + run: | + wget https://github.com/qarmin/gtk_library_store/releases/download/3.24.0/swiftshader.zip + unzip swiftshader.zip + rm swiftshader.zip + curr="$(pwd)/libvk_swiftshader.so" + sed -i "s|PATH_TO_CHANGE|$curr|" vk_swiftshader_icd.json + + # Download and extract zip archive with project, folder is renamed to be able to easy change used project + - name: Download test project + run: | + wget https://github.com/qarmin/RegressionTestProject/archive/4.0.zip + unzip 4.0.zip + mv "RegressionTestProject-4.0" "test_project" + + # Editor is quite complicated piece of software, so it is easy to introduce bug here + - name: Open and close editor + run: | + VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run bin/godot.linuxbsd.tools.64s --audio-driver Dummy -e -q --path test_project 2>&1 | tee sanitizers_log.txt || true + misc/scripts/check_ci_log.py sanitizers_log.txt + + # Run test project + - name: Run project + run: | + VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run bin/godot.linuxbsd.tools.64s 40 --audio-driver Dummy --path test_project 2>&1 | tee sanitizers_log.txt || true + misc/scripts/check_ci_log.py sanitizers_log.txt linux-template-mono: runs-on: "ubuntu-20.04" diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 343adbe592..955108f455 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -36,6 +36,7 @@ #include "core/string/print_string.h" #include "core/templates/list.h" #include "core/templates/map.h" +#include "core/templates/set.h" // Godot's packed file magic header ("GDPC" in ASCII). #define PACK_HEADER_MAGIC 0x43504447 diff --git a/core/templates/map.h b/core/templates/map.h index 51a237472d..7dfee13d2c 100644 --- a/core/templates/map.h +++ b/core/templates/map.h @@ -32,7 +32,7 @@ #define MAP_H #include "core/error/error_macros.h" -#include "core/templates/set.h" +#include "core/os/memory.h" // based on the very nice implementation of rb-trees by: // https://web.archive.org/web/20120507164830/http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html diff --git a/doc/classes/CapsuleMesh.xml b/doc/classes/CapsuleMesh.xml index fab11d44cc..031abd0112 100644 --- a/doc/classes/CapsuleMesh.xml +++ b/doc/classes/CapsuleMesh.xml @@ -12,7 +12,8 @@ </methods> <members> <member name="mid_height" type="float" setter="set_mid_height" getter="get_mid_height" default="1.0"> - Height of the capsule mesh from the center point. + Height of the middle cylindrical part of the capsule (without the hemispherical ends). + [b]Note:[/b] The capsule's total height is equal to [member mid_height] + 2 * [member radius]. </member> <member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments" default="64"> Number of radial segments on the capsule mesh. diff --git a/doc/classes/MeshInstance3D.xml b/doc/classes/MeshInstance3D.xml index 82cd392cd3..e1a6cf44a7 100644 --- a/doc/classes/MeshInstance3D.xml +++ b/doc/classes/MeshInstance3D.xml @@ -43,7 +43,7 @@ Returns the [Material] that will be used by the [Mesh] when drawing. This can return the [member GeometryInstance3D.material_override], the surface override [Material] defined in this [MeshInstance3D], or the surface [Material] defined in the [Mesh]. For example, if [member GeometryInstance3D.material_override] is used, all surfaces will return the override material. </description> </method> - <method name="get_surface_material" qualifiers="const"> + <method name="get_surface_override_material" qualifiers="const"> <return type="Material"> </return> <argument index="0" name="surface" type="int"> @@ -52,14 +52,14 @@ Returns the override [Material] for the specified surface of the [Mesh] resource. </description> </method> - <method name="get_surface_material_count" qualifiers="const"> + <method name="get_surface_override_material_count" qualifiers="const"> <return type="int"> </return> <description> - Returns the number of surface materials. + Returns the number of surface override materials. This is equivalent to [method Mesh.get_surface_count]. </description> </method> - <method name="set_surface_material"> + <method name="set_surface_override_material"> <return type="void"> </return> <argument index="0" name="surface" type="int"> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index f82301bcf4..d6eaa1b88b 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1317,7 +1317,7 @@ Sets the scenario that the instance is in. The scenario is the 3D world that the objects will be displayed in. </description> </method> - <method name="instance_set_surface_material"> + <method name="instance_set_surface_override_material"> <return type="void"> </return> <argument index="0" name="instance" type="RID"> @@ -1327,7 +1327,7 @@ <argument index="2" name="material" type="RID"> </argument> <description> - Sets the material of a specific surface. Equivalent to [method MeshInstance3D.set_surface_material]. + Sets the override material of a specific surface. Equivalent to [method MeshInstance3D.set_surface_override_material]. </description> </method> <method name="instance_set_transform"> diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index ac8bef817b..6ed2cb9d9c 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -142,7 +142,7 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) bool found = text_editor->search(text, p_flags, p_from_line, p_from_col, line, col); if (found) { - if (!preserve_cursor) { + if (!preserve_cursor && !is_selection_only()) { text_editor->unfold_line(line); text_editor->cursor_set_line(line, false); text_editor->cursor_set_column(col + text.length(), false); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 9041b815ca..4bb56beaeb 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1241,7 +1241,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m if (mesh.is_valid()) { mesh_node->set_mesh(mesh); for (int i = 0; i < mesh->get_surface_count(); i++) { - mesh_node->set_surface_material(i, src_mesh_node->get_surface_material(i)); + mesh_node->set_surface_override_material(i, src_mesh_node->get_surface_material(i)); } } } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index b678197037..f1c9cb120d 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -804,11 +804,15 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append) { bool still_selected = true; - if (p_append) { + if (p_append && !editor_selection->get_selected_node_list().is_empty()) { if (editor_selection->is_selected(item)) { // Already in the selection, remove it from the selected nodes editor_selection->remove_node(item); still_selected = false; + + if (editor_selection->get_selected_node_list().size() == 1) { + editor->push_item(editor_selection->get_selected_node_list()[0]); + } } else { // Add the item to the selection editor_selection->add_node(item); @@ -2589,6 +2593,9 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { } _find_canvas_items_in_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems); + if (selitems.size() == 1 && editor_selection->get_selected_node_list().is_empty()) { + editor->push_item(selitems[0]); + } for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) { editor_selection->add_node(E->get()); } diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp index f8932cd534..6f1f243444 100644 --- a/editor/plugins/mesh_library_editor_plugin.cpp +++ b/editor/plugins/mesh_library_editor_plugin.cpp @@ -93,7 +93,7 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, mesh = mesh->duplicate(); for (int j = 0; j < mesh->get_surface_count(); ++j) { - Ref<Material> mat = mi->get_surface_material(j); + Ref<Material> mat = mi->get_surface_override_material(j); if (mat.is_valid()) { mesh->surface_set_material(j, mat); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 8f8a4b3054..ed3b746678 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -205,7 +205,7 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCo ShaderLanguage sl; String calltip; - sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip); + sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip); get_text_editor()->set_code_hint(calltip); } @@ -219,7 +219,7 @@ void ShaderTextEditor::_validate_script() { ShaderLanguage sl; - Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type); + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type); if (err != OK) { String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index b2fa9c540e..e5b8dfd464 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -3398,7 +3398,7 @@ void VisualShaderEditor::_update_preview() { ShaderLanguage sl; - Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type); + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type); for (int i = 0; i < preview_text->get_line_count(); i++) { preview_text->set_line_as_marked(i, false); diff --git a/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json b/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json index 6bf2edb02d..c4f8f71d0e 100644 --- a/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json +++ b/misc/dist/osx_template.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json @@ -2,6 +2,6 @@ "file_format_version" : "1.0.0", "ICD": { "library_path": "../../../Frameworks/libMoltenVK.dylib", - "api_version" : "1.0.0" + "api_version" : "1.1.0" } } diff --git a/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json b/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json index 6bf2edb02d..c4f8f71d0e 100644 --- a/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json +++ b/misc/dist/osx_tools.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json @@ -2,6 +2,6 @@ "file_format_version" : "1.0.0", "ICD": { "library_path": "../../../Frameworks/libMoltenVK.dylib", - "api_version" : "1.0.0" + "api_version" : "1.1.0" } } diff --git a/misc/scripts/check_ci_log.py b/misc/scripts/check_ci_log.py new file mode 100755 index 0000000000..f2cdf95c7b --- /dev/null +++ b/misc/scripts/check_ci_log.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys + +if len(sys.argv) < 2: + print("ERROR: You must run program with file name as argument.") + sys.exit(1) + +fname = sys.argv[1] + +fileread = open(fname.strip(), "r") +file_contents = fileread.read() + +# If find "ERROR: AddressSanitizer:", then happens invalid read or write +# This is critical bug, so we need to fix this as fast as possible + +if file_contents.find("ERROR: AddressSanitizer:") != -1: + print("FATAL ERROR: An incorrectly used memory was found.") + sys.exit(1) + +# There is also possible, that program crashed with or without backtrace. + +if ( + file_contents.find("Program crashed with signal") != -1 + or file_contents.find("Dumping the backtrace") != -1 + or file_contents.find("Segmentation fault (core dumped)") != -1 +): + print("FATAL ERROR: Godot has been crashed.") + sys.exit(1) + +# Finding memory leaks in Godot is quite difficult, because we need to take into +# account leaks also in external libraries. They are usually provided without +# debugging symbols, so the leak report from it usually has only 2/3 lines, +# so searching for 5 element - "#4 0x" - should correctly detect the vast +# majority of memory leaks + +if file_contents.find("ERROR: LeakSanitizer:") != -1: + if file_contents.find("#4 0x") != -1: + print("ERROR: Memory leak was found") + sys.exit(1) + +# It may happen that Godot detects leaking nodes/resources and removes them, so +# this possibility should also be handled as a potential error, even if +# LeakSanitizer doesn't report anything + +if file_contents.find("ObjectDB instances leaked at exit") != -1: + print("ERROR: Memory leak was found") + sys.exit(1) + +# In test project may be put several assert functions which will control if +# project is executed with right parameters etc. which normally will not stop +# execution of project + +if file_contents.find("Assertion failed") != -1: + print("ERROR: Assertion failed in project, check exectution log for more info") + sys.exit(1) + +# For now Godot leaks a lot of rendering stuff so for now we just show info +# about it and this needs to be reenabled after fixing this memory leaks. + +if file_contents.find("were leaked") != -1 or file_contents.find("were never freed") != -1: + print("WARNING: Memory leak was found") + +sys.exit(0) diff --git a/modules/etcpak/SCsub b/modules/etcpak/SCsub index 821c6801b4..2d3b69be75 100644 --- a/modules/etcpak/SCsub +++ b/modules/etcpak/SCsub @@ -11,31 +11,15 @@ thirdparty_obj = [] thirdparty_dir = "#thirdparty/etcpak/" thirdparty_sources = [ - "Bitmap.cpp", - "BitmapDownsampled.cpp", - "BlockData.cpp", - "ColorSpace.cpp", - "DataProvider.cpp", - "Debug.cpp", "Dither.cpp", - "Error.cpp", - "mmap.cpp", "ProcessDxtc.cpp", "ProcessRGB.cpp", - "System.cpp", "Tables.cpp", - "TaskDispatch.cpp", - "Timing.cpp", - "lz4/lz4.c", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] env_etcpak.Prepend(CPPPATH=[thirdparty_dir]) -# Also requires libpng headers -if env["builtin_libpng"]: - env_etcpak.Prepend(CPPPATH=["#thirdparty/libpng"]) - env_thirdparty = env_etcpak.Clone() env_thirdparty.disable_warnings() env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources) diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index b553dcede3..af2bfc33a7 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -391,7 +391,7 @@ void GDScriptByteCodeGenerator::write_type_test(const Address &p_target, const A } void GDScriptByteCodeGenerator::write_type_test_builtin(const Address &p_target, const Address &p_source, Variant::Type p_type) { - append(GDScriptFunction::OPCODE_IS_BUILTIN, 3); + append(GDScriptFunction::OPCODE_IS_BUILTIN, 2); append(p_source); append(p_target); append(p_type); diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 695154e9a9..ca8bb8fcae 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -811,6 +811,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper VariableNode *variable = alloc_node<VariableNode>(); variable->identifier = parse_identifier(); + variable->export_info.name = variable->identifier->name; if (match(GDScriptTokenizer::Token::COLON)) { if (check(GDScriptTokenizer::Token::NEWLINE)) { @@ -860,8 +861,6 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper end_statement("variable declaration"); - variable->export_info.name = variable->identifier->name; - return variable; } diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 0b70175a24..027a054b70 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -3293,6 +3293,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } img->decompress(); img->convert(Image::FORMAT_RGBA8); + img->convert_ra_rgba8_to_rg(); for (int32_t y = 0; y < img->get_height(); y++) { for (int32_t x = 0; x < img->get_width(); x++) { Color c = img->get_pixel(x, y); @@ -4958,8 +4959,8 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_instance(Ref<GLTFState> state, MeshIns if (godot_array_mesh.is_valid()) { surface_name = godot_array_mesh->surface_get_name(surface_i); } - if (p_mesh_instance->get_surface_material(surface_i).is_valid()) { - mat = p_mesh_instance->get_surface_material(surface_i); + if (p_mesh_instance->get_surface_override_material(surface_i).is_valid()) { + mat = p_mesh_instance->get_surface_override_material(surface_i); } if (p_mesh_instance->get_material_override().is_valid()) { mat = p_mesh_instance->get_material_override(); diff --git a/modules/lightmapper_rd/lm_blendseams.glsl b/modules/lightmapper_rd/lm_blendseams.glsl index e47e5fcc51..374c48082e 100644 --- a/modules/lightmapper_rd/lm_blendseams.glsl +++ b/modules/lightmapper_rd/lm_blendseams.glsl @@ -7,7 +7,7 @@ triangles = "#define MODE_TRIANGLES"; #version 450 -VERSION_DEFINES +#VERSION_DEFINES #include "lm_common_inc.glsl" @@ -74,7 +74,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES #include "lm_common_inc.glsl" diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl index eb9d817f99..3dd96893fb 100644 --- a/modules/lightmapper_rd/lm_compute.glsl +++ b/modules/lightmapper_rd/lm_compute.glsl @@ -10,7 +10,7 @@ light_probes = "#define MODE_LIGHT_PROBES"; #version 450 -VERSION_DEFINES +#VERSION_DEFINES // One 2D local group focusing in one layer at a time, though all // in parallel (no barriers) makes more sense than a 3D local group diff --git a/modules/lightmapper_rd/lm_raster.glsl b/modules/lightmapper_rd/lm_raster.glsl index 6c2904192b..55ca193cc1 100644 --- a/modules/lightmapper_rd/lm_raster.glsl +++ b/modules/lightmapper_rd/lm_raster.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #include "lm_common_inc.glsl" @@ -56,7 +56,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES #include "lm_common_inc.glsl" diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 7e3bdfe3b4..f3502b2220 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -1819,7 +1819,7 @@ public: p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST; } - String tmp_export_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport.apk"); + String tmp_export_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport." + uitos(OS::get_singleton()->get_unix_time()) + ".apk"); #define CLEANUP_AND_RETURN(m_err) \ { \ @@ -1836,6 +1836,7 @@ public: List<String> args; int rv; + String output; bool remove_prev = p_preset->get("one_click_deploy/clear_previous_install"); String version_name = p_preset->get("version/name"); @@ -1853,7 +1854,9 @@ public: args.push_back("uninstall"); args.push_back(get_package_name(package_name)); - err = OS::get_singleton()->execute(adb, args, nullptr, &rv); + output.clear(); + err = OS::get_singleton()->execute(adb, args, &output, &rv, true); + print_verbose(output); } print_line("Installing to device (please wait...): " + devices[p_device].name); @@ -1868,7 +1871,9 @@ public: args.push_back("-r"); args.push_back(tmp_export_path); - err = OS::get_singleton()->execute(adb, args, nullptr, &rv); + output.clear(); + err = OS::get_singleton()->execute(adb, args, &output, &rv, true); + print_verbose(output); if (err || rv != 0) { EditorNode::add_io_error("Could not install to device."); CLEANUP_AND_RETURN(ERR_CANT_CREATE); @@ -1885,7 +1890,9 @@ public: args.push_back(devices[p_device].id); args.push_back("reverse"); args.push_back("--remove-all"); - OS::get_singleton()->execute(adb, args, nullptr, &rv); + output.clear(); + OS::get_singleton()->execute(adb, args, &output, &rv, true); + print_verbose(output); if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) { int dbg_port = EditorSettings::get_singleton()->get("network/debug/remote_port"); @@ -1896,7 +1903,9 @@ public: args.push_back("tcp:" + itos(dbg_port)); args.push_back("tcp:" + itos(dbg_port)); - OS::get_singleton()->execute(adb, args, nullptr, &rv); + output.clear(); + OS::get_singleton()->execute(adb, args, &output, &rv, true); + print_verbose(output); print_line("Reverse result: " + itos(rv)); } @@ -1910,7 +1919,9 @@ public: args.push_back("tcp:" + itos(fs_port)); args.push_back("tcp:" + itos(fs_port)); - err = OS::get_singleton()->execute(adb, args, nullptr, &rv); + output.clear(); + err = OS::get_singleton()->execute(adb, args, &output, &rv, true); + print_verbose(output); print_line("Reverse result2: " + itos(rv)); } } else { @@ -1938,7 +1949,9 @@ public: args.push_back("-n"); args.push_back(get_package_name(package_name) + "/com.godot.game.GodotApp"); - err = OS::get_singleton()->execute(adb, args, nullptr, &rv); + output.clear(); + err = OS::get_singleton()->execute(adb, args, &output, &rv, true); + print_verbose(output); if (err || rv != 0) { EditorNode::add_io_error("Could not execute on device."); CLEANUP_AND_RETURN(ERR_CANT_CREATE); @@ -2335,6 +2348,7 @@ public: return ERR_FILE_CANT_OPEN; } + String output; List<String> args; args.push_back("sign"); args.push_back("--verbose"); @@ -2350,7 +2364,9 @@ public: print_verbose("Signing debug binary using: " + String("\n") + apksigner + " " + join_list(args, String(" "))); } int retval; - OS::get_singleton()->execute(apksigner, args, nullptr, &retval); + output.clear(); + OS::get_singleton()->execute(apksigner, args, &output, &retval, true); + print_verbose(output); if (retval) { EditorNode::add_io_error("'apksigner' returned with error #" + itos(retval)); return ERR_CANT_CREATE; @@ -2368,7 +2384,9 @@ public: print_verbose("Verifying signed build using: " + String("\n") + apksigner + " " + join_list(args, String(" "))); } - OS::get_singleton()->execute(apksigner, args, nullptr, &retval); + output.clear(); + OS::get_singleton()->execute(apksigner, args, &output, &retval, true); + print_verbose(output); if (retval) { EditorNode::add_io_error("'apksigner' verification of " + export_label + " failed."); return ERR_CANT_CREATE; @@ -2673,7 +2691,7 @@ public: FileAccess *dst_f = nullptr; io2.opaque = &dst_f; - String tmp_unaligned_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned.apk"); + String tmp_unaligned_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned." + uitos(OS::get_singleton()->get_unix_time()) + ".apk"); #define CLEANUP_AND_RETURN(m_err) \ { \ diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index c0ae4007d2..ad9a19e2af 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -239,5 +239,5 @@ ext.shouldSign = { -> } ext.shouldNotStrip = { -> - return isAndroidStudio() + return isAndroidStudio() || project.hasProperty("doNotStrip") } diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index ec02b0fc7a..81570d9d86 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -122,16 +122,17 @@ task zipCustomBuild(type: Zip) { destinationDir(file(binDir)) } -/** - * Master task used to coordinate the tasks defined above to generate the set of Godot templates. - */ -task generateGodotTemplates(type: GradleBuild) { +def templateExcludedBuildTask() { // We exclude these gradle tasks so we can run the scons command manually. + def excludedTasks = [] for (String buildType : supportedTargets) { - startParameter.excludedTaskNames += ":lib:" + getSconsTaskName(buildType) + excludedTasks += ":lib:" + getSconsTaskName(buildType) } + return excludedTasks +} - tasks = [] +def templateBuildTasks() { + def tasks = [] // Only build the apks and aar files for which we have native shared libraries. for (String target : supportedTargets) { @@ -152,6 +153,29 @@ task generateGodotTemplates(type: GradleBuild) { } } + return tasks +} + +/** + * Master task used to coordinate the tasks defined above to generate the set of Godot templates. + */ +task generateGodotTemplates(type: GradleBuild) { + startParameter.excludedTaskNames = templateExcludedBuildTask() + tasks = templateBuildTasks() + + finalizedBy 'zipCustomBuild' +} + +/** + * Generates the same output as generateGodotTemplates but with dev symbols + */ +task generateDevTemplate (type: GradleBuild) { + // add parameter to set symbols to true + startParameter.projectProperties += [doNotStrip: true] + + startParameter.excludedTaskNames = templateExcludedBuildTask() + tasks = templateBuildTasks() + finalizedBy 'zipCustomBuild' } diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties index 2dc069ad2f..6b3b62a9da 100644 --- a/platform/android/java/gradle.properties +++ b/platform/android/java/gradle.properties @@ -12,7 +12,7 @@ android.useAndroidX=true # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m +org.gradle.jvmargs=-Xmx4536m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 6b527c6fb5..ebcb4c2a80 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -67,10 +67,10 @@ def get_opts(): BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True), BoolVariable("use_coverage", "Test Godot coverage", False), BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False), - BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN))", False), - BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN))", False), - BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN))", False), - BoolVariable("use_msan", "Use LLVM/GCC compiler memory sanitizer (MSAN))", False), + BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN)", False), + BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN)", False), + BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False), + BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False), BoolVariable("pulseaudio", "Detect and use PulseAudio", True), BoolVariable("udev", "Use udev for gamepad connection callbacks", True), BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True), @@ -147,11 +147,23 @@ def configure(env): env.extra_suffix += "s" if env["use_ubsan"]: - env.Append(CCFLAGS=["-fsanitize=undefined"]) + env.Append( + CCFLAGS=[ + "-fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin" + ] + ) env.Append(LINKFLAGS=["-fsanitize=undefined"]) + if env["use_llvm"]: + env.Append( + CCFLAGS=[ + "-fsanitize=nullability-return,nullability-arg,function,nullability-assign,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation" + ] + ) + else: + env.Append(CCFLAGS=["-fsanitize=bounds-strict"]) if env["use_asan"]: - env.Append(CCFLAGS=["-fsanitize=address"]) + env.Append(CCFLAGS=["-fsanitize=address,pointer-subtract,pointer-compare"]) env.Append(LINKFLAGS=["-fsanitize=address"]) if env["use_lsan"]: @@ -162,8 +174,10 @@ def configure(env): env.Append(CCFLAGS=["-fsanitize=thread"]) env.Append(LINKFLAGS=["-fsanitize=thread"]) - if env["use_msan"]: + if env["use_msan"] and env["use_llvm"]: env.Append(CCFLAGS=["-fsanitize=memory"]) + env.Append(CCFLAGS=["-fsanitize-memory-track-origins"]) + env.Append(CCFLAGS=["-fsanitize-recover=memory"]) env.Append(LINKFLAGS=["-fsanitize=memory"]) if env["use_lto"]: diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 5b320da82f..afdafe75e5 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -34,9 +34,9 @@ def get_opts(): BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True), BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False), BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False), - BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN))", False), - BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN))", False), - BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN))", False), + BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN)", False), + BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN)", False), + BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False), ] @@ -136,11 +136,23 @@ def configure(env): env.extra_suffix += "s" if env["use_ubsan"]: - env.Append(CCFLAGS=["-fsanitize=undefined"]) + env.Append( + CCFLAGS=[ + "-fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin" + ] + ) env.Append(LINKFLAGS=["-fsanitize=undefined"]) + if env["use_llvm"]: + env.Append( + CCFLAGS=[ + "-fsanitize=nullability-return,nullability-arg,function,nullability-assign,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation" + ] + ) + else: + env.Append(CCFLAGS=["-fsanitize=bounds-strict"]) if env["use_asan"]: - env.Append(CCFLAGS=["-fsanitize=address"]) + env.Append(CCFLAGS=["-fsanitize=address,pointer-subtract,pointer-compare"]) env.Append(LINKFLAGS=["-fsanitize=address"]) if env["use_lsan"]: diff --git a/platform/server/detect.py b/platform/server/detect.py index 16ddbe1768..4a4109db4a 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -35,11 +35,11 @@ def get_opts(): BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True), BoolVariable("use_coverage", "Test Godot coverage", False), BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False), - BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN))", False), - BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN))", False), - BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN))", False), + BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN)", False), + BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN)", False), + BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False), + BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False), BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True), - BoolVariable("use_msan", "Use LLVM/GCC compiler memory sanitizer (MSAN))", False), BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False), BoolVariable("execinfo", "Use libexecinfo on systems where glibc is not available", False), ] @@ -104,11 +104,23 @@ def configure(env): env.extra_suffix += "s" if env["use_ubsan"]: - env.Append(CCFLAGS=["-fsanitize=undefined"]) + env.Append( + CCFLAGS=[ + "-fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin" + ] + ) env.Append(LINKFLAGS=["-fsanitize=undefined"]) + if env["use_llvm"]: + env.Append( + CCFLAGS=[ + "-fsanitize=nullability-return,nullability-arg,function,nullability-assign,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation" + ] + ) + else: + env.Append(CCFLAGS=["-fsanitize=bounds-strict"]) if env["use_asan"]: - env.Append(CCFLAGS=["-fsanitize=address"]) + env.Append(CCFLAGS=["-fsanitize=address,pointer-subtract,pointer-compare"]) env.Append(LINKFLAGS=["-fsanitize=address"]) if env["use_lsan"]: @@ -119,8 +131,10 @@ def configure(env): env.Append(CCFLAGS=["-fsanitize=thread"]) env.Append(LINKFLAGS=["-fsanitize=thread"]) - if env["use_msan"]: + if env["use_msan"] and env["use_llvm"]: env.Append(CCFLAGS=["-fsanitize=memory"]) + env.Append(CCFLAGS=["-fsanitize-memory-track-origins"]) + env.Append(CCFLAGS=["-fsanitize-recover=memory"]) env.Append(LINKFLAGS=["-fsanitize=memory"]) if env["use_lto"]: diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 95ffbe48c1..2e1b77dfe5 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -259,7 +259,7 @@ void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> if (all_override.is_valid()) { mf.overrides.push_back(all_override); } else { - mf.overrides.push_back(mi->get_surface_material(i)); + mf.overrides.push_back(mi->get_surface_override_material(i)); } } diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 0da53d0101..4d7fc29f15 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -343,7 +343,7 @@ void GIProbe::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { pm.local_xform = xf; pm.mesh = mesh; for (int i = 0; i < mesh->get_surface_count(); i++) { - pm.instance_materials.push_back(mi->get_surface_material(i)); + pm.instance_materials.push_back(mi->get_surface_override_material(i)); } pm.override_material = mi->get_material_override(); plot_meshes.push_back(pm); diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index b997c64b29..7623ede0fc 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -51,13 +51,13 @@ bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) { return true; } - if (p_name.operator String().begins_with("material/")) { + if (p_name.operator String().begins_with("surface_material_override/")) { int idx = p_name.operator String().get_slicec('/', 1).to_int(); - if (idx >= materials.size() || idx < 0) { + if (idx >= surface_override_materials.size() || idx < 0) { return false; } - set_surface_material(idx, p_value); + set_surface_override_material(idx, p_value); return true; } @@ -75,12 +75,12 @@ bool MeshInstance3D::_get(const StringName &p_name, Variant &r_ret) const { return true; } - if (p_name.operator String().begins_with("material/")) { + if (p_name.operator String().begins_with("surface_material_override/")) { int idx = p_name.operator String().get_slicec('/', 1).to_int(); - if (idx >= materials.size() || idx < 0) { + if (idx >= surface_override_materials.size() || idx < 0) { return false; } - r_ret = materials[idx]; + r_ret = surface_override_materials[idx]; return true; } return false; @@ -100,7 +100,7 @@ void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const { if (mesh.is_valid()) { for (int i = 0; i < mesh->get_surface_count(); i++) { - p_list->push_back(PropertyInfo(Variant::OBJECT, "material/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_material_override/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE)); } } } @@ -126,7 +126,7 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) { } mesh->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &MeshInstance3D::_mesh_changed)); - materials.resize(mesh->get_surface_count()); + surface_override_materials.resize(mesh->get_surface_count()); set_base(mesh->get_rid()); } else { @@ -277,26 +277,26 @@ void MeshInstance3D::_notification(int p_what) { } } -int MeshInstance3D::get_surface_material_count() const { - return materials.size(); +int MeshInstance3D::get_surface_override_material_count() const { + return surface_override_materials.size(); } -void MeshInstance3D::set_surface_material(int p_surface, const Ref<Material> &p_material) { - ERR_FAIL_INDEX(p_surface, materials.size()); +void MeshInstance3D::set_surface_override_material(int p_surface, const Ref<Material> &p_material) { + ERR_FAIL_INDEX(p_surface, surface_override_materials.size()); - materials.write[p_surface] = p_material; + surface_override_materials.write[p_surface] = p_material; - if (materials[p_surface].is_valid()) { - RS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, materials[p_surface]->get_rid()); + if (surface_override_materials[p_surface].is_valid()) { + RS::get_singleton()->instance_set_surface_override_material(get_instance(), p_surface, surface_override_materials[p_surface]->get_rid()); } else { - RS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, RID()); + RS::get_singleton()->instance_set_surface_override_material(get_instance(), p_surface, RID()); } } -Ref<Material> MeshInstance3D::get_surface_material(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, materials.size(), Ref<Material>()); +Ref<Material> MeshInstance3D::get_surface_override_material(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surface_override_materials.size(), Ref<Material>()); - return materials[p_surface]; + return surface_override_materials[p_surface]; } Ref<Material> MeshInstance3D::get_active_material(int p_surface) const { @@ -305,7 +305,7 @@ Ref<Material> MeshInstance3D::get_active_material(int p_surface) const { return material_override; } - Ref<Material> surface_material = get_surface_material(p_surface); + Ref<Material> surface_material = get_surface_override_material(p_surface); if (surface_material.is_valid()) { return surface_material; } @@ -320,7 +320,7 @@ Ref<Material> MeshInstance3D::get_active_material(int p_surface) const { void MeshInstance3D::_mesh_changed() { ERR_FAIL_COND(mesh.is_null()); - materials.resize(mesh->get_surface_count()); + surface_override_materials.resize(mesh->get_surface_count()); } void MeshInstance3D::create_debug_tangents() { @@ -408,9 +408,9 @@ void MeshInstance3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_skin", "skin"), &MeshInstance3D::set_skin); ClassDB::bind_method(D_METHOD("get_skin"), &MeshInstance3D::get_skin); - ClassDB::bind_method(D_METHOD("get_surface_material_count"), &MeshInstance3D::get_surface_material_count); - ClassDB::bind_method(D_METHOD("set_surface_material", "surface", "material"), &MeshInstance3D::set_surface_material); - ClassDB::bind_method(D_METHOD("get_surface_material", "surface"), &MeshInstance3D::get_surface_material); + ClassDB::bind_method(D_METHOD("get_surface_override_material_count"), &MeshInstance3D::get_surface_override_material_count); + ClassDB::bind_method(D_METHOD("set_surface_override_material", "surface", "material"), &MeshInstance3D::set_surface_override_material); + ClassDB::bind_method(D_METHOD("get_surface_override_material", "surface"), &MeshInstance3D::get_surface_override_material); ClassDB::bind_method(D_METHOD("get_active_material", "surface"), &MeshInstance3D::get_active_material); ClassDB::bind_method(D_METHOD("create_trimesh_collision"), &MeshInstance3D::create_trimesh_collision); diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h index eb300784b1..8aec227337 100644 --- a/scene/3d/mesh_instance_3d.h +++ b/scene/3d/mesh_instance_3d.h @@ -52,7 +52,7 @@ protected: }; Map<StringName, BlendShapeTrack> blend_shape_tracks; - Vector<Ref<Material>> materials; + Vector<Ref<Material>> surface_override_materials; void _mesh_changed(); void _resolve_skeleton_path(); @@ -75,9 +75,9 @@ public: void set_skeleton_path(const NodePath &p_skeleton); NodePath get_skeleton_path(); - int get_surface_material_count() const; - void set_surface_material(int p_surface, const Ref<Material> &p_material); - Ref<Material> get_surface_material(int p_surface) const; + int get_surface_override_material_count() const; + void set_surface_override_material(int p_surface, const Ref<Material> &p_material); + Ref<Material> get_surface_override_material(int p_surface) const; Ref<Material> get_active_material(int p_surface) const; Node *create_trimesh_collision_node(); diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp index 6cde6a9b17..898f94ccc1 100644 --- a/scene/3d/skeleton_ik_3d.cpp +++ b/scene/3d/skeleton_ik_3d.cpp @@ -270,7 +270,6 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove return; // Skip solving } - // This line below is part of the problem - removing it fixes the issue with BoneAttachment nodes... p_task->skeleton->set_bone_global_pose_override(p_task->chain.chain_root.bone, Transform(), 0.0, true); if (p_task->chain.middle_chain_item) { @@ -567,6 +566,9 @@ void SkeletonIK3D::start(bool p_one_time) { void SkeletonIK3D::stop() { set_process_internal(false); + if (skeleton) { + skeleton->clear_bones_global_pose_override(); + } } Transform SkeletonIK3D::_get_target_transform() { diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 08e25b589e..98ac6aa65e 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -452,7 +452,7 @@ void SoftBody3D::become_mesh_owner() { mesh_owner = true; Vector<Ref<Material>> copy_materials; - copy_materials.append_array(materials); + copy_materials.append_array(surface_override_materials); ERR_FAIL_COND(!mesh->get_surface_count()); @@ -472,7 +472,7 @@ void SoftBody3D::become_mesh_owner() { set_mesh(soft_mesh); for (int i = copy_materials.size() - 1; 0 <= i; --i) { - set_surface_material(i, copy_materials[i]); + set_surface_override_material(i, copy_materials[i]); } } } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index f54ab004c6..4f508423b3 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1973,7 +1973,7 @@ void TextEdit::backspace_at_cursor() { } } - cursor_set_line(prev_line, true, true); + cursor_set_line(prev_line, false, true); cursor_set_column(prev_column); } @@ -2207,7 +2207,7 @@ void TextEdit::_new_line(bool p_split_current_line, bool p_above) { if (!p_split_current_line) { if (p_above) { if (cursor.line > 0) { - cursor_set_line(cursor.line - 1); + cursor_set_line(cursor.line - 1, false); cursor_set_column(text[cursor.line].length()); } else { cursor_set_column(0); @@ -2223,7 +2223,7 @@ void TextEdit::_new_line(bool p_split_current_line, bool p_above) { if (first_line) { cursor_set_line(0); } else if (brace_indent) { - cursor_set_line(cursor.line - 1); + cursor_set_line(cursor.line - 1, false); cursor_set_column(text[cursor.line].length()); } end_complex_operation(); @@ -2573,7 +2573,7 @@ void TextEdit::_backspace(bool p_word, bool p_all_to_left) { _remove_text(line, column, cursor.line, cursor.column); - cursor_set_line(line); + cursor_set_line(line, false); cursor_set_column(column); } else { // One character. @@ -2640,7 +2640,7 @@ void TextEdit::_delete_selection() { selection.active = false; update(); _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - cursor_set_line(selection.from_line, true, false); + cursor_set_line(selection.from_line, false, false); cursor_set_column(selection.from_column); update(); } @@ -3261,7 +3261,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { accept_event(); return; } - if (k->is_action("ui_accept", true) || k->is_action("ui_text_completion_accept", true)) { + if (k->is_action("ui_text_completion_accept", true)) { _confirm_completion(); accept_event(); return; @@ -3851,7 +3851,7 @@ void TextEdit::_insert_text_at_cursor(const String &p_text) { int new_column, new_line; _insert_text(cursor.line, cursor.column, p_text, &new_line, &new_column); _update_scrollbars(); - cursor_set_line(new_line); + cursor_set_line(new_line, false); cursor_set_column(new_column); update(); @@ -4425,7 +4425,7 @@ int TextEdit::get_column_x_offset_for_line(int p_char, int p_line) const { void TextEdit::insert_text_at_cursor(const String &p_text) { if (selection.active) { - cursor_set_line(selection.from_line); + cursor_set_line(selection.from_line, false); cursor_set_column(selection.from_column); _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); @@ -5042,7 +5042,7 @@ void TextEdit::cut() { DisplayServer::get_singleton()->clipboard_set(clipboard); _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - cursor_set_line(selection.from_line); // Set afterwards else it causes the view to be offset. + cursor_set_line(selection.from_line, false); // Set afterwards else it causes the view to be offset. cursor_set_column(selection.from_column); selection.active = false; @@ -5078,7 +5078,7 @@ void TextEdit::paste() { selection.active = false; selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE; _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - cursor_set_line(selection.from_line); + cursor_set_line(selection.from_line, false); cursor_set_column(selection.from_column); } else if (!cut_copy_line.is_empty() && cut_copy_line == clipboard) { @@ -5817,11 +5817,11 @@ void TextEdit::undo() { _update_scrollbars(); if (undo_stack_pos->get().type == TextOperation::TYPE_REMOVE) { - cursor_set_line(undo_stack_pos->get().to_line); + cursor_set_line(undo_stack_pos->get().to_line, false); cursor_set_column(undo_stack_pos->get().to_column); _cancel_code_hint(); } else { - cursor_set_line(undo_stack_pos->get().from_line); + cursor_set_line(undo_stack_pos->get().from_line, false); cursor_set_column(undo_stack_pos->get().from_column); } update(); @@ -5856,7 +5856,7 @@ void TextEdit::redo() { } _update_scrollbars(); - cursor_set_line(undo_stack_pos->get().to_line); + cursor_set_line(undo_stack_pos->get().to_line, false); cursor_set_column(undo_stack_pos->get().to_column); undo_stack_pos = undo_stack_pos->next(); update(); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 195ce070a7..6a65173176 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -289,7 +289,7 @@ void ParticlesMaterial::_update_shader() { code += "}\n"; code += "\n"; - code += "void compute() {\n"; + code += "void process() {\n"; code += " uint base_number = NUMBER;\n"; code += " uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);\n"; code += " float angle_rand = rand_from_seed(alt_seed);\n"; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index b2efecb1cb..f50ee9c4c8 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -194,7 +194,7 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() { code += "uniform float sun_angle_max = 1.74;\n"; code += "uniform float sun_curve : hint_range(0, 1) = 0.05;\n\n"; code += "const float PI = 3.1415926535897932384626433833;\n\n"; - code += "void fragment() {\n"; + code += "void sky() {\n"; code += "\tfloat v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));\n"; code += "\tfloat c = (1.0 - v_angle / (PI * 0.5));\n"; code += "\tvec3 sky = mix(sky_horizon_color.rgb, sky_top_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / sky_curve), 0.0, 1.0));\n"; @@ -301,7 +301,7 @@ PanoramaSkyMaterial::PanoramaSkyMaterial() { String code = "shader_type sky;\n\n"; code += "uniform sampler2D source_panorama : filter_linear;\n"; - code += "void fragment() {\n"; + code += "void sky() {\n"; code += "\tCOLOR = texture(source_panorama, SKY_COORDS).rgb;\n"; code += "}"; @@ -521,7 +521,7 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() { code += "\treturn fract(p.x * p.y * p.z * (p.x + p.y + p.z));\n"; code += "}\n\n"; - code += "void fragment() {\n"; + code += "void sky() {\n"; code += "\tif (LIGHT0_ENABLED) {\n"; code += "\t\tfloat zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );\n"; code += "\t\tfloat sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;\n"; diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 892802c103..7575ccd5c3 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -190,10 +190,6 @@ SceneStringNames::SceneStringNames() { _default = StaticCString::create("default"); - for (int i = 0; i < MAX_MATERIALS; i++) { - mesh_materials[i] = "material/" + itos(i); - } - _window_group = StaticCString::create("_window_group"); _window_input = StaticCString::create("_window_input"); window_input = StaticCString::create("window_input"); diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 655e49c6f9..a5b489eddc 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -216,10 +216,6 @@ public: StringName use_in_baked_light; StringName use_dynamic_gi; #endif - enum { - MAX_MATERIALS = 32 - }; - StringName mesh_materials[MAX_MATERIALS]; }; #endif // SCENE_STRING_NAMES_H diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index d0636047b7..0a91931354 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -658,8 +658,6 @@ Body2DSW::Body2DSW() : omit_force_integration = false; applied_torque = 0; island_step = 0; - island_next = nullptr; - island_list_next = nullptr; _set_static(false); first_time_kinematic = false; linear_damp = -1; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 60d55ab8bd..7ea4ac697c 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -125,8 +125,6 @@ class Body2DSW : public CollisionObject2DSW { ForceIntegrationCallback *fi_callback; uint64_t island_step; - Body2DSW *island_next; - Body2DSW *island_list_next; _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const Area2DSW *p_area); @@ -175,12 +173,6 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ Body2DSW *get_island_next() const { return island_next; } - _FORCE_INLINE_ void set_island_next(Body2DSW *p_next) { island_next = p_next; } - - _FORCE_INLINE_ Body2DSW *get_island_list_next() const { return island_list_next; } - _FORCE_INLINE_ void set_island_list_next(Body2DSW *p_next) { island_list_next = p_next; } - _FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_list.push_back({ p_constraint, p_pos }); } _FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_list.erase({ p_constraint, p_pos }); } const List<Pair<Constraint2DSW *, int>> &get_constraint_list() const { return constraint_list; } diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp index 6cfe6908d1..35447c5389 100644 --- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp +++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp @@ -35,6 +35,12 @@ #define LARGE_ELEMENT_FI 1.01239812 void BroadPhase2DHashGrid::_pair_attempt(Element *p_elem, Element *p_with) { + if (p_elem->owner == p_with->owner) { + return; + } + if (!_test_collision_mask(p_elem->collision_mask, p_elem->collision_layer, p_with->collision_mask, p_with->collision_layer)) { + return; + } Map<Element *, PairData *>::Element *E = p_elem->paired.find(p_with); ERR_FAIL_COND(p_elem->_static && p_with->_static); @@ -49,6 +55,12 @@ void BroadPhase2DHashGrid::_pair_attempt(Element *p_elem, Element *p_with) { } void BroadPhase2DHashGrid::_unpair_attempt(Element *p_elem, Element *p_with) { + if (p_elem->owner == p_with->owner) { + return; + } + if (!_test_collision_mask(p_elem->collision_mask, p_elem->collision_layer, p_with->collision_mask, p_with->collision_layer)) { + return; + } Map<Element *, PairData *>::Element *E = p_elem->paired.find(p_with); ERR_FAIL_COND(!E); //this should really be paired.. @@ -74,24 +86,22 @@ void BroadPhase2DHashGrid::_check_motion(Element *p_elem) { bool physical_collision = p_elem->aabb.intersects(E->key()->aabb); bool logical_collision = p_elem->owner->test_collision_mask(E->key()->owner); - if (physical_collision) { - if (!E->get()->colliding || (logical_collision && !E->get()->ud && pair_callback)) { + if (physical_collision && logical_collision) { + if (!E->get()->colliding && pair_callback) { E->get()->ud = pair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, pair_userdata); - } else if (E->get()->colliding && !logical_collision && E->get()->ud && unpair_callback) { - unpair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, E->get()->ud, unpair_userdata); - E->get()->ud = nullptr; } E->get()->colliding = true; - } else { // No physcial_collision + } else { // No collision if (E->get()->colliding && unpair_callback) { unpair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, E->get()->ud, unpair_userdata); + E->get()->ud = nullptr; } E->get()->colliding = false; } } } -void BroadPhase2DHashGrid::_enter_grid(Element *p_elem, const Rect2 &p_rect, bool p_static) { +void BroadPhase2DHashGrid::_enter_grid(Element *p_elem, const Rect2 &p_rect, bool p_static, bool p_force_enter) { Vector2 sz = (p_rect.size / cell_size * LARGE_ELEMENT_FI); //use magic number to avoid floating point issues if (sz.width * sz.height > large_object_min_surface) { //large object, do not use grid, must check against all elements @@ -99,9 +109,6 @@ void BroadPhase2DHashGrid::_enter_grid(Element *p_elem, const Rect2 &p_rect, boo if (E->key() == p_elem->self) { continue; // do not pair against itself } - if (E->get().owner == p_elem->owner) { - continue; - } if (E->get()._static && p_static) { continue; } @@ -133,7 +140,7 @@ void BroadPhase2DHashGrid::_enter_grid(Element *p_elem, const Rect2 &p_rect, boo pb = pb->next; } - bool entered = false; + bool entered = p_force_enter; if (!pb) { //does not exist, create! @@ -155,17 +162,11 @@ void BroadPhase2DHashGrid::_enter_grid(Element *p_elem, const Rect2 &p_rect, boo if (entered) { for (Map<Element *, RC>::Element *E = pb->object_set.front(); E; E = E->next()) { - if (E->key()->owner == p_elem->owner) { - continue; - } _pair_attempt(p_elem, E->key()); } if (!p_static) { for (Map<Element *, RC>::Element *E = pb->static_object_set.front(); E; E = E->next()) { - if (E->key()->owner == p_elem->owner) { - continue; - } _pair_attempt(p_elem, E->key()); } } @@ -179,18 +180,14 @@ void BroadPhase2DHashGrid::_enter_grid(Element *p_elem, const Rect2 &p_rect, boo if (E->key() == p_elem) { continue; // do not pair against itself } - if (E->key()->owner == p_elem->owner) { - continue; - } if (E->key()->_static && p_static) { continue; } - _pair_attempt(E->key(), p_elem); } } -void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool p_static) { +void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool p_static, bool p_force_exit) { Vector2 sz = (p_rect.size / cell_size * LARGE_ELEMENT_FI); if (sz.width * sz.height > large_object_min_surface) { //unpair all elements, instead of checking all, just check what is already paired, so we at least save from checking static vs static @@ -229,7 +226,7 @@ void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool ERR_CONTINUE(!pb); //should exist!! - bool exited = false; + bool exited = p_force_exit; if (p_static) { if (pb->static_object_set[p_elem].dec() == 0) { @@ -245,17 +242,11 @@ void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool if (exited) { for (Map<Element *, RC>::Element *E = pb->object_set.front(); E; E = E->next()) { - if (E->key()->owner == p_elem->owner) { - continue; - } _unpair_attempt(p_elem, E->key()); } if (!p_static) { for (Map<Element *, RC>::Element *E = pb->static_object_set.front(); E; E = E->next()) { - if (E->key()->owner == p_elem->owner) { - continue; - } _unpair_attempt(p_elem, E->key()); } } @@ -288,9 +279,6 @@ void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool if (E->key() == p_elem) { continue; // do not pair against itself } - if (E->key()->owner == p_elem->owner) { - continue; - } if (E->key()->_static && p_static) { continue; } @@ -306,6 +294,8 @@ BroadPhase2DHashGrid::ID BroadPhase2DHashGrid::create(CollisionObject2DSW *p_obj Element e; e.owner = p_object; e._static = false; + e.collision_mask = p_object->get_collision_mask(); + e.collision_layer = p_object->get_collision_layer(); e.subindex = p_subindex; e.self = current; e.pass = 0; @@ -319,13 +309,26 @@ void BroadPhase2DHashGrid::move(ID p_id, const Rect2 &p_aabb) { ERR_FAIL_COND(!E); Element &e = E->get(); + bool layer_changed = e.collision_mask != e.owner->get_collision_mask() || e.collision_layer != e.owner->get_collision_layer(); - if (p_aabb != e.aabb) { + if (p_aabb != e.aabb || layer_changed) { + uint32_t old_mask = e.collision_mask; + uint32_t old_layer = e.collision_layer; if (p_aabb != Rect2()) { - _enter_grid(&e, p_aabb, e._static); + e.collision_mask = e.owner->get_collision_mask(); + e.collision_layer = e.owner->get_collision_layer(); + + _enter_grid(&e, p_aabb, e._static, layer_changed); } if (e.aabb != Rect2()) { - _exit_grid(&e, e.aabb, e._static); + // Need _exit_grid to remove from cells based on the old layer values. + e.collision_mask = old_mask; + e.collision_layer = old_layer; + + _exit_grid(&e, e.aabb, e._static, layer_changed); + + e.collision_mask = e.owner->get_collision_mask(); + e.collision_layer = e.owner->get_collision_layer(); } e.aabb = p_aabb; } @@ -344,13 +347,13 @@ void BroadPhase2DHashGrid::set_static(ID p_id, bool p_static) { } if (e.aabb != Rect2()) { - _exit_grid(&e, e.aabb, e._static); + _exit_grid(&e, e.aabb, e._static, false); } e._static = p_static; if (e.aabb != Rect2()) { - _enter_grid(&e, e.aabb, e._static); + _enter_grid(&e, e.aabb, e._static, false); _check_motion(&e); } } @@ -362,7 +365,7 @@ void BroadPhase2DHashGrid::remove(ID p_id) { Element &e = E->get(); if (e.aabb != Rect2()) { - _exit_grid(&e, e.aabb, e._static); + _exit_grid(&e, e.aabb, e._static, false); } element_map.erase(p_id); diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.h b/servers/physics_2d/broad_phase_2d_hash_grid.h index eb7c8879ac..bb7c03b989 100644 --- a/servers/physics_2d/broad_phase_2d_hash_grid.h +++ b/servers/physics_2d/broad_phase_2d_hash_grid.h @@ -51,6 +51,9 @@ class BroadPhase2DHashGrid : public BroadPhase2DSW { CollisionObject2DSW *owner; bool _static; Rect2 aabb; + // Owner's collision_mask/layer, used to detect changes in layers. + uint32_t collision_mask; + uint32_t collision_layer; int subindex; uint64_t pass; Map<Element *, PairData *> paired; @@ -115,8 +118,12 @@ class BroadPhase2DHashGrid : public BroadPhase2DSW { UnpairCallback unpair_callback; void *unpair_userdata; - void _enter_grid(Element *p_elem, const Rect2 &p_rect, bool p_static); - void _exit_grid(Element *p_elem, const Rect2 &p_rect, bool p_static); + static _FORCE_INLINE_ bool _test_collision_mask(uint32_t p_mask1, uint32_t p_layer1, uint32_t p_mask2, uint32_t p_layer2) { + return p_mask1 & p_layer2 || p_mask2 & p_layer1; + } + + void _enter_grid(Element *p_elem, const Rect2 &p_rect, bool p_static, bool p_force_enter); + void _exit_grid(Element *p_elem, const Rect2 &p_rect, bool p_static, bool p_force_exit); template <bool use_aabb, bool use_segment> _FORCE_INLINE_ void _cull(const Point2i p_cell, const Rect2 &p_aabb, const Point2 &p_from, const Point2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices, int &index); diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h index 49ae4dd848..b724deb48e 100644 --- a/servers/physics_2d/constraint_2d_sw.h +++ b/servers/physics_2d/constraint_2d_sw.h @@ -37,8 +37,6 @@ class Constraint2DSW { Body2DSW **_body_ptr; int _body_count; uint64_t island_step; - Constraint2DSW *island_next; - Constraint2DSW *island_list_next; bool disabled_collisions_between_bodies; RID self; @@ -58,12 +56,6 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ Constraint2DSW *get_island_next() const { return island_next; } - _FORCE_INLINE_ void set_island_next(Constraint2DSW *p_next) { island_next = p_next; } - - _FORCE_INLINE_ Constraint2DSW *get_island_list_next() const { return island_list_next; } - _FORCE_INLINE_ void set_island_list_next(Constraint2DSW *p_next) { island_list_next = p_next; } - _FORCE_INLINE_ Body2DSW **get_body_ptr() const { return _body_ptr; } _FORCE_INLINE_ int get_body_count() const { return _body_count; } diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp index 6613d19729..406d750776 100644 --- a/servers/physics_2d/step_2d_sw.cpp +++ b/servers/physics_2d/step_2d_sw.cpp @@ -31,19 +31,23 @@ #include "step_2d_sw.h" #include "core/os/os.h" -void Step2DSW::_populate_island(Body2DSW *p_body, Body2DSW **p_island, Constraint2DSW **p_constraint_island) { +#define BODY_ISLAND_COUNT_RESERVE 128 +#define BODY_ISLAND_SIZE_RESERVE 512 +#define ISLAND_COUNT_RESERVE 128 +#define ISLAND_SIZE_RESERVE 512 + +void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_body_island, LocalVector<Constraint2DSW *> &p_constraint_island) { p_body->set_island_step(_step); - p_body->set_island_next(*p_island); - *p_island = p_body; + p_body_island.push_back(p_body); - for (const List<Pair<Constraint2DSW *, int>>::Element *E = p_body->get_constraint_list().front(); E; E = E->next()) { + // Faster with reversed iterations. + for (const List<Pair<Constraint2DSW *, int>>::Element *E = p_body->get_constraint_list().back(); E; E = E->prev()) { Constraint2DSW *c = (Constraint2DSW *)E->get().first; if (c->get_island_step() == _step) { continue; //already processed } c->set_island_step(_step); - c->set_island_next(*p_constraint_island); - *p_constraint_island = c; + p_constraint_island.push_back(c); for (int i = 0; i < c->get_body_count(); i++) { if (i == E->get().second) { @@ -53,78 +57,62 @@ void Step2DSW::_populate_island(Body2DSW *p_body, Body2DSW **p_island, Constrain if (b->get_island_step() == _step || b->get_mode() == PhysicsServer2D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) { continue; //no go } - _populate_island(c->get_body_ptr()[i], p_island, p_constraint_island); + _populate_island(c->get_body_ptr()[i], p_body_island, p_constraint_island); } } } -bool Step2DSW::_setup_island(Constraint2DSW *p_island, real_t p_delta) { - Constraint2DSW *ci = p_island; - Constraint2DSW *prev_ci = nullptr; - bool removed_root = false; - while (ci) { - bool process = ci->setup(p_delta); - - if (!process) { - //remove from island if process fails - if (prev_ci) { - prev_ci->set_island_next(ci->get_island_next()); - } else { - removed_root = true; - prev_ci = ci; - } - } else { - prev_ci = ci; +void Step2DSW::_setup_island(LocalVector<Constraint2DSW *> &p_constraint_island, real_t p_delta) { + uint32_t constraint_count = p_constraint_island.size(); + uint32_t valid_constraint_count = 0; + for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) { + Constraint2DSW *constraint = p_constraint_island[constraint_index]; + if (p_constraint_island[constraint_index]->setup(p_delta)) { + // Keep this constraint for solving. + p_constraint_island[valid_constraint_count++] = constraint; } - ci = ci->get_island_next(); } - - return removed_root; + p_constraint_island.resize(valid_constraint_count); } -void Step2DSW::_solve_island(Constraint2DSW *p_island, int p_iterations, real_t p_delta) { +void Step2DSW::_solve_island(LocalVector<Constraint2DSW *> &p_constraint_island, int p_iterations, real_t p_delta) { for (int i = 0; i < p_iterations; i++) { - Constraint2DSW *ci = p_island; - while (ci) { - ci->solve(p_delta); - ci = ci->get_island_next(); + uint32_t constraint_count = p_constraint_island.size(); + for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) { + p_constraint_island[constraint_index]->solve(p_delta); } } } -void Step2DSW::_check_suspend(Body2DSW *p_island, real_t p_delta) { +void Step2DSW::_check_suspend(const LocalVector<Body2DSW *> &p_body_island, real_t p_delta) { bool can_sleep = true; - Body2DSW *b = p_island; - while (b) { - if (b->get_mode() == PhysicsServer2D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) { - b = b->get_island_next(); - continue; //ignore for static + uint32_t body_count = p_body_island.size(); + for (uint32_t body_index = 0; body_index < body_count; ++body_index) { + Body2DSW *body = p_body_island[body_index]; + + if (body->get_mode() == PhysicsServer2D::BODY_MODE_STATIC || body->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) { + continue; // Ignore for static. } - if (!b->sleep_test(p_delta)) { + if (!body->sleep_test(p_delta)) { can_sleep = false; } - - b = b->get_island_next(); } - //put all to sleep or wake up everyoen + // Put all to sleep or wake up everyone. + for (uint32_t body_index = 0; body_index < body_count; ++body_index) { + Body2DSW *body = p_body_island[body_index]; - b = p_island; - while (b) { - if (b->get_mode() == PhysicsServer2D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) { - b = b->get_island_next(); - continue; //ignore for static + if (body->get_mode() == PhysicsServer2D::BODY_MODE_STATIC || body->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) { + continue; // Ignore for static. } - bool active = b->is_active(); + bool active = body->is_active(); if (active == can_sleep) { - b->set_active(!can_sleep); + body->set_active(!can_sleep); } - - b = b->get_island_next(); } } @@ -159,33 +147,43 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { /* GENERATE CONSTRAINT ISLANDS */ - Body2DSW *island_list = nullptr; - Constraint2DSW *constraint_island_list = nullptr; b = body_list->first(); - int island_count = 0; + uint32_t body_island_count = 0; + uint32_t island_count = 0; while (b) { Body2DSW *body = b->self(); if (body->get_island_step() != _step) { - Body2DSW *island = nullptr; - Constraint2DSW *constraint_island = nullptr; - _populate_island(body, &island, &constraint_island); + ++body_island_count; + if (body_islands.size() < body_island_count) { + body_islands.resize(body_island_count); + } + LocalVector<Body2DSW *> &body_island = body_islands[body_island_count - 1]; + body_island.clear(); + body_island.reserve(BODY_ISLAND_SIZE_RESERVE); - island->set_island_list_next(island_list); - island_list = island; + ++island_count; + if (constraint_islands.size() < island_count) { + constraint_islands.resize(island_count); + } + LocalVector<Constraint2DSW *> &constraint_island = constraint_islands[island_count - 1]; + constraint_island.clear(); + constraint_island.reserve(ISLAND_SIZE_RESERVE); - if (constraint_island) { - constraint_island->set_island_list_next(constraint_island_list); - constraint_island_list = constraint_island; - island_count++; + _populate_island(body, body_island, constraint_island); + + body_islands.push_back(body_island); + + if (constraint_island.is_empty()) { + --island_count; } } b = b->next(); } - p_space->set_island_count(island_count); + p_space->set_island_count((int)island_count); const SelfList<Area2DSW>::List &aml = p_space->get_moved_area_list(); @@ -196,9 +194,13 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { continue; } c->set_island_step(_step); - c->set_island_next(nullptr); - c->set_island_list_next(constraint_island_list); - constraint_island_list = c; + ++island_count; + if (constraint_islands.size() < island_count) { + constraint_islands.resize(island_count); + } + LocalVector<Constraint2DSW *> &constraint_island = constraint_islands[island_count - 1]; + constraint_island.clear(); + constraint_island.push_back(c); } p_space->area_remove_from_moved_list((SelfList<Area2DSW> *)aml.first()); //faster to remove here } @@ -211,39 +213,8 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { /* SETUP CONSTRAINT ISLANDS */ - { - Constraint2DSW *ci = constraint_island_list; - Constraint2DSW *prev_ci = nullptr; - while (ci) { - if (_setup_island(ci, p_delta)) { - //removed the root from the island graph because it is not to be processed - - Constraint2DSW *next = ci->get_island_next(); - - if (next) { - //root from list being deleted no longer exists, replace by next - next->set_island_list_next(ci->get_island_list_next()); - if (prev_ci) { - prev_ci->set_island_list_next(next); - } else { - constraint_island_list = next; - } - prev_ci = next; - } else { - //list is empty, just skip - if (prev_ci) { - prev_ci->set_island_list_next(ci->get_island_list_next()); - - } else { - constraint_island_list = ci->get_island_list_next(); - } - } - } else { - prev_ci = ci; - } - - ci = ci->get_island_list_next(); - } + for (uint32_t island_index = 0; island_index < island_count; ++island_index) { + _setup_island(constraint_islands[island_index], p_delta); } { //profile @@ -254,13 +225,8 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { /* SOLVE CONSTRAINT ISLANDS */ - { - Constraint2DSW *ci = constraint_island_list; - while (ci) { - //iterating each island separatedly improves cache efficiency - _solve_island(ci, p_iterations, p_delta); - ci = ci->get_island_list_next(); - } + for (uint32_t island_index = 0; island_index < island_count; ++island_index) { + _solve_island(constraint_islands[island_index], p_iterations, p_delta); } { //profile @@ -280,12 +246,8 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { /* SLEEP / WAKE UP ISLANDS */ - { - Body2DSW *bi = island_list; - while (bi) { - _check_suspend(bi, p_delta); - bi = bi->get_island_list_next(); - } + for (uint32_t island_index = 0; island_index < body_island_count; ++island_index) { + _check_suspend(body_islands[island_index], p_delta); } { //profile @@ -301,4 +263,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { Step2DSW::Step2DSW() { _step = 1; + + body_islands.reserve(BODY_ISLAND_COUNT_RESERVE); + constraint_islands.reserve(ISLAND_COUNT_RESERVE); } diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/step_2d_sw.h index 83b9130608..5af4a36f52 100644 --- a/servers/physics_2d/step_2d_sw.h +++ b/servers/physics_2d/step_2d_sw.h @@ -33,13 +33,18 @@ #include "space_2d_sw.h" +#include "core/templates/local_vector.h" + class Step2DSW { uint64_t _step; - void _populate_island(Body2DSW *p_body, Body2DSW **p_island, Constraint2DSW **p_constraint_island); - bool _setup_island(Constraint2DSW *p_island, real_t p_delta); - void _solve_island(Constraint2DSW *p_island, int p_iterations, real_t p_delta); - void _check_suspend(Body2DSW *p_island, real_t p_delta); + LocalVector<LocalVector<Body2DSW *>> body_islands; + LocalVector<LocalVector<Constraint2DSW *>> constraint_islands; + + void _populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_body_island, LocalVector<Constraint2DSW *> &p_constraint_island); + void _setup_island(LocalVector<Constraint2DSW *> &p_constraint_island, real_t p_delta); + void _solve_island(LocalVector<Constraint2DSW *> &p_constraint_island, int p_iterations, real_t p_delta); + void _check_suspend(const LocalVector<Body2DSW *> &p_body_island, real_t p_delta); public: void step(Space2DSW *p_space, real_t p_delta, int p_iterations); diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp index 64ba0cb09d..cc414b7f30 100644 --- a/servers/physics_3d/body_3d_sw.cpp +++ b/servers/physics_3d/body_3d_sw.cpp @@ -761,8 +761,6 @@ Body3DSW::Body3DSW() : omit_force_integration = false; //applied_torque=0; island_step = 0; - island_next = nullptr; - island_list_next = nullptr; first_time_kinematic = false; first_integration = false; _set_static(false); diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h index e87ff2364b..5790f43019 100644 --- a/servers/physics_3d/body_3d_sw.h +++ b/servers/physics_3d/body_3d_sw.h @@ -135,8 +135,6 @@ class Body3DSW : public CollisionObject3DSW { ForceIntegrationCallback *fi_callback; uint64_t island_step; - Body3DSW *island_next; - Body3DSW *island_list_next; _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const Area3DSW *p_area); @@ -189,12 +187,6 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ Body3DSW *get_island_next() const { return island_next; } - _FORCE_INLINE_ void set_island_next(Body3DSW *p_next) { island_next = p_next; } - - _FORCE_INLINE_ Body3DSW *get_island_list_next() const { return island_list_next; } - _FORCE_INLINE_ void set_island_list_next(Body3DSW *p_next) { island_list_next = p_next; } - _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraint_map.erase(p_constraint); } const Map<Constraint3DSW *, int> &get_constraint_map() const { return constraint_map; } diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp index ef4dca7dcf..28c854466f 100644 --- a/servers/physics_3d/body_pair_3d_sw.cpp +++ b/servers/physics_3d/body_pair_3d_sw.cpp @@ -281,6 +281,8 @@ bool BodyPair3DSW::setup(real_t p_step) { real_t inv_dt = 1.0 / p_step; + bool do_process = false; + for (int i = 0; i < contact_count; i++) { Contact &c = contacts[i]; c.active = false; @@ -323,6 +325,7 @@ bool BodyPair3DSW::setup(real_t p_step) { } c.active = true; + do_process = true; // Precompute normal mass, tangent mass, and bias. Vector3 inertia_A = A->get_inv_inertia_tensor().xform(c.rA.cross(c.normal)); @@ -350,7 +353,7 @@ bool BodyPair3DSW::setup(real_t p_step) { } } - return true; + return do_process; } void BodyPair3DSW::solve(real_t p_step) { @@ -594,6 +597,8 @@ bool BodySoftBodyPair3DSW::setup(real_t p_step) { real_t inv_dt = 1.0 / p_step; + bool do_process = false; + uint32_t contact_count = contacts.size(); for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) { Contact &c = contacts[contact_index]; @@ -614,6 +619,7 @@ bool BodySoftBodyPair3DSW::setup(real_t p_step) { } c.active = true; + do_process = true; #ifdef DEBUG_ENABLED @@ -661,7 +667,7 @@ bool BodySoftBodyPair3DSW::setup(real_t p_step) { } } - return true; + return do_process; } void BodySoftBodyPair3DSW::solve(real_t p_step) { diff --git a/servers/physics_3d/constraint_3d_sw.h b/servers/physics_3d/constraint_3d_sw.h index 2571335c43..16a31e167d 100644 --- a/servers/physics_3d/constraint_3d_sw.h +++ b/servers/physics_3d/constraint_3d_sw.h @@ -37,8 +37,6 @@ class Constraint3DSW { Body3DSW **_body_ptr; int _body_count; uint64_t island_step; - Constraint3DSW *island_next; - Constraint3DSW *island_list_next; int priority; bool disabled_collisions_between_bodies; @@ -60,12 +58,6 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ Constraint3DSW *get_island_next() const { return island_next; } - _FORCE_INLINE_ void set_island_next(Constraint3DSW *p_next) { island_next = p_next; } - - _FORCE_INLINE_ Constraint3DSW *get_island_list_next() const { return island_list_next; } - _FORCE_INLINE_ void set_island_list_next(Constraint3DSW *p_next) { island_list_next = p_next; } - _FORCE_INLINE_ Body3DSW **get_body_ptr() const { return _body_ptr; } _FORCE_INLINE_ int get_body_count() const { return _body_count; } diff --git a/servers/physics_3d/step_3d_sw.cpp b/servers/physics_3d/step_3d_sw.cpp index 2133a38670..06f3227eab 100644 --- a/servers/physics_3d/step_3d_sw.cpp +++ b/servers/physics_3d/step_3d_sw.cpp @@ -33,19 +33,23 @@ #include "core/os/os.h" -void Step3DSW::_populate_island(Body3DSW *p_body, Body3DSW **p_island, Constraint3DSW **p_constraint_island) { +#define BODY_ISLAND_COUNT_RESERVE 128 +#define BODY_ISLAND_SIZE_RESERVE 512 +#define ISLAND_COUNT_RESERVE 128 +#define ISLAND_SIZE_RESERVE 512 + +void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island) { p_body->set_island_step(_step); - p_body->set_island_next(*p_island); - *p_island = p_body; + p_body_island.push_back(p_body); - for (Map<Constraint3DSW *, int>::Element *E = p_body->get_constraint_map().front(); E; E = E->next()) { + // Faster with reversed iterations. + for (Map<Constraint3DSW *, int>::Element *E = p_body->get_constraint_map().back(); E; E = E->prev()) { Constraint3DSW *c = (Constraint3DSW *)E->key(); if (c->get_island_step() == _step) { continue; //already processed } c->set_island_step(_step); - c->set_island_next(*p_constraint_island); - *p_constraint_island = c; + p_constraint_island.push_back(c); for (int i = 0; i < c->get_body_count(); i++) { if (i == E->get()) { @@ -55,87 +59,79 @@ void Step3DSW::_populate_island(Body3DSW *p_body, Body3DSW **p_island, Constrain if (b->get_island_step() == _step || b->get_mode() == PhysicsServer3D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) { continue; //no go } - _populate_island(c->get_body_ptr()[i], p_island, p_constraint_island); + _populate_island(c->get_body_ptr()[i], p_body_island, p_constraint_island); } } } -void Step3DSW::_setup_island(Constraint3DSW *p_island, real_t p_delta) { - Constraint3DSW *ci = p_island; - while (ci) { - ci->setup(p_delta); - //todo remove from island if process fails - ci = ci->get_island_next(); +void Step3DSW::_setup_island(LocalVector<Constraint3DSW *> &p_constraint_island, real_t p_delta) { + uint32_t constraint_count = p_constraint_island.size(); + uint32_t valid_constraint_count = 0; + for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) { + Constraint3DSW *constraint = p_constraint_island[constraint_index]; + if (p_constraint_island[constraint_index]->setup(p_delta)) { + // Keep this constraint for solving. + p_constraint_island[valid_constraint_count++] = constraint; + } } + p_constraint_island.resize(valid_constraint_count); } -void Step3DSW::_solve_island(Constraint3DSW *p_island, int p_iterations, real_t p_delta) { - int at_priority = 1; +void Step3DSW::_solve_island(LocalVector<Constraint3DSW *> &p_constraint_island, int p_iterations, real_t p_delta) { + int current_priority = 1; - while (p_island) { + uint32_t constraint_count = p_constraint_island.size(); + while (constraint_count > 0) { for (int i = 0; i < p_iterations; i++) { - Constraint3DSW *ci = p_island; - while (ci) { - ci->solve(p_delta); - ci = ci->get_island_next(); + // Go through all iterations. + for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) { + p_constraint_island[constraint_index]->solve(p_delta); } } - at_priority++; - - { - Constraint3DSW *ci = p_island; - Constraint3DSW *prev = nullptr; - while (ci) { - if (ci->get_priority() < at_priority) { - if (prev) { - prev->set_island_next(ci->get_island_next()); //remove - } else { - p_island = ci->get_island_next(); - } - } else { - prev = ci; - } - - ci = ci->get_island_next(); + // Check priority to keep only higher priority constraints. + uint32_t priority_constraint_count = 0; + ++current_priority; + for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) { + Constraint3DSW *constraint = p_constraint_island[constraint_index]; + if (constraint->get_priority() >= current_priority) { + // Keep this constraint for the next iteration. + p_constraint_island[priority_constraint_count++] = constraint; } } + constraint_count = priority_constraint_count; } } -void Step3DSW::_check_suspend(Body3DSW *p_island, real_t p_delta) { +void Step3DSW::_check_suspend(const LocalVector<Body3DSW *> &p_body_island, real_t p_delta) { bool can_sleep = true; - Body3DSW *b = p_island; - while (b) { - if (b->get_mode() == PhysicsServer3D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) { - b = b->get_island_next(); - continue; //ignore for static + uint32_t body_count = p_body_island.size(); + for (uint32_t body_index = 0; body_index < body_count; ++body_index) { + Body3DSW *body = p_body_island[body_index]; + + if (body->get_mode() == PhysicsServer3D::BODY_MODE_STATIC || body->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) { + continue; // Ignore for static. } - if (!b->sleep_test(p_delta)) { + if (!body->sleep_test(p_delta)) { can_sleep = false; } - - b = b->get_island_next(); } - //put all to sleep or wake up everyoen + // Put all to sleep or wake up everyone. + for (uint32_t body_index = 0; body_index < body_count; ++body_index) { + Body3DSW *body = p_body_island[body_index]; - b = p_island; - while (b) { - if (b->get_mode() == PhysicsServer3D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) { - b = b->get_island_next(); - continue; //ignore for static + if (body->get_mode() == PhysicsServer3D::BODY_MODE_STATIC || body->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) { + continue; // Ignore for static. } - bool active = b->is_active(); + bool active = body->is_active(); if (active == can_sleep) { - b->set_active(!can_sleep); + body->set_active(!can_sleep); } - - b = b->get_island_next(); } } @@ -181,33 +177,43 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { /* GENERATE CONSTRAINT ISLANDS */ - Body3DSW *island_list = nullptr; - Constraint3DSW *constraint_island_list = nullptr; b = body_list->first(); - int island_count = 0; + uint32_t body_island_count = 0; + uint32_t island_count = 0; while (b) { Body3DSW *body = b->self(); if (body->get_island_step() != _step) { - Body3DSW *island = nullptr; - Constraint3DSW *constraint_island = nullptr; - _populate_island(body, &island, &constraint_island); + ++body_island_count; + if (body_islands.size() < body_island_count) { + body_islands.resize(body_island_count); + } + LocalVector<Body3DSW *> &body_island = body_islands[body_island_count - 1]; + body_island.clear(); + body_island.reserve(BODY_ISLAND_SIZE_RESERVE); - island->set_island_list_next(island_list); - island_list = island; + ++island_count; + if (constraint_islands.size() < island_count) { + constraint_islands.resize(island_count); + } + LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1]; + constraint_island.clear(); + constraint_island.reserve(ISLAND_SIZE_RESERVE); - if (constraint_island) { - constraint_island->set_island_list_next(constraint_island_list); - constraint_island_list = constraint_island; - island_count++; + _populate_island(body, body_island, constraint_island); + + body_islands.push_back(body_island); + + if (constraint_island.is_empty()) { + --island_count; } } b = b->next(); } - p_space->set_island_count(island_count); + p_space->set_island_count((int)island_count); const SelfList<Area3DSW>::List &aml = p_space->get_moved_area_list(); @@ -218,9 +224,13 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { continue; } c->set_island_step(_step); - c->set_island_next(nullptr); - c->set_island_list_next(constraint_island_list); - constraint_island_list = c; + ++island_count; + if (constraint_islands.size() < island_count) { + constraint_islands.resize(island_count); + } + LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1]; + constraint_island.clear(); + constraint_island.push_back(c); } p_space->area_remove_from_moved_list((SelfList<Area3DSW> *)aml.first()); //faster to remove here } @@ -233,9 +243,13 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { continue; } c->set_island_step(_step); - c->set_island_next(nullptr); - c->set_island_list_next(constraint_island_list); - constraint_island_list = c; + ++island_count; + if (constraint_islands.size() < island_count) { + constraint_islands.resize(island_count); + } + LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1]; + constraint_island.clear(); + constraint_island.push_back(c); } sb = sb->next(); } @@ -248,12 +262,8 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { /* SETUP CONSTRAINT ISLANDS */ - { - Constraint3DSW *ci = constraint_island_list; - while (ci) { - _setup_island(ci, p_delta); - ci = ci->get_island_list_next(); - } + for (uint32_t island_index = 0; island_index < island_count; ++island_index) { + _setup_island(constraint_islands[island_index], p_delta); } { //profile @@ -264,13 +274,10 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { /* SOLVE CONSTRAINT ISLANDS */ - { - Constraint3DSW *ci = constraint_island_list; - while (ci) { - //iterating each island separatedly improves cache efficiency - _solve_island(ci, p_iterations, p_delta); - ci = ci->get_island_list_next(); - } + for (uint32_t island_index = 0; island_index < island_count; ++island_index) { + // Warning: _solve_island modifies the constraint islands for optimization purpose, + // their content is not reliable after these calls and shouldn't be used anymore. + _solve_island(constraint_islands[island_index], p_iterations, p_delta); } { //profile @@ -290,12 +297,8 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { /* SLEEP / WAKE UP ISLANDS */ - { - Body3DSW *bi = island_list; - while (bi) { - _check_suspend(bi, p_delta); - bi = bi->get_island_list_next(); - } + for (uint32_t island_index = 0; island_index < body_island_count; ++island_index) { + _check_suspend(body_islands[island_index], p_delta); } /* UPDATE SOFT BODY CONSTRAINTS */ @@ -319,4 +322,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { Step3DSW::Step3DSW() { _step = 1; + + body_islands.reserve(BODY_ISLAND_COUNT_RESERVE); + constraint_islands.reserve(ISLAND_COUNT_RESERVE); } diff --git a/servers/physics_3d/step_3d_sw.h b/servers/physics_3d/step_3d_sw.h index 55c48ec0eb..f406c35c3a 100644 --- a/servers/physics_3d/step_3d_sw.h +++ b/servers/physics_3d/step_3d_sw.h @@ -33,13 +33,18 @@ #include "space_3d_sw.h" +#include "core/templates/local_vector.h" + class Step3DSW { uint64_t _step; - void _populate_island(Body3DSW *p_body, Body3DSW **p_island, Constraint3DSW **p_constraint_island); - void _setup_island(Constraint3DSW *p_island, real_t p_delta); - void _solve_island(Constraint3DSW *p_island, int p_iterations, real_t p_delta); - void _check_suspend(Body3DSW *p_island, real_t p_delta); + LocalVector<LocalVector<Body3DSW *>> body_islands; + LocalVector<LocalVector<Constraint3DSW *>> constraint_islands; + + void _populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island); + void _setup_island(LocalVector<Constraint3DSW *> &p_constraint_island, real_t p_delta); + void _solve_island(LocalVector<Constraint3DSW *> &p_constraint_island, int p_iterations, real_t p_delta); + void _check_suspend(const LocalVector<Body3DSW *> &p_body_island, real_t p_delta); public: void step(Space3DSW *p_space, real_t p_delta, int p_iterations); 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 45f6384b5e..15982b4b29 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 @@ -77,6 +77,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { int depth_drawi = DEPTH_DRAW_OPAQUE; ShaderCompilerRD::IdentifierActions actions; + actions.entry_point_stages["vertex"] = ShaderCompilerRD::STAGE_VERTEX; + actions.entry_point_stages["fragment"] = ShaderCompilerRD::STAGE_FRAGMENT; + actions.entry_point_stages["light"] = ShaderCompilerRD::STAGE_FRAGMENT; actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD); actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX); @@ -148,7 +151,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { print_line("\n**fragment_code:\n" + gen_code.fragment); print_line("\n**light_code:\n" + gen_code.light); #endif - shader_singleton->shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); + shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines); ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version)); ubo_size = gen_code.uniform_total_size; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 7d6e2fa8e4..3c76c91a67 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2012,6 +2012,9 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { uses_screen_texture = false; ShaderCompilerRD::IdentifierActions actions; + actions.entry_point_stages["vertex"] = ShaderCompilerRD::STAGE_VERTEX; + actions.entry_point_stages["fragment"] = ShaderCompilerRD::STAGE_FRAGMENT; + actions.entry_point_stages["light"] = ShaderCompilerRD::STAGE_FRAGMENT; actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD); actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX); @@ -2048,7 +2051,7 @@ void RendererCanvasRenderRD::ShaderData::set_code(const String &p_code) { print_line("\n**fragment_code:\n" + gen_code.fragment); print_line("\n**light_code:\n" + gen_code.light); #endif - canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); + canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines); ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version)); ubo_size = gen_code.uniform_total_size; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 769335ac16..54c6e81110 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -50,6 +50,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { ShaderCompilerRD::GeneratedCode gen_code; ShaderCompilerRD::IdentifierActions actions; + actions.entry_point_stages["sky"] = ShaderCompilerRD::STAGE_FRAGMENT; uses_time = false; uses_half_res = false; @@ -110,7 +111,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) { print_line("\n**light_code:\n" + gen_code.light); #endif - scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); + scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines); ERR_FAIL_COND(!scene_singleton->sky.sky_shader.shader.version_is_valid(version)); ubo_size = gen_code.uniform_total_size; @@ -759,7 +760,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { sky_shader.default_shader = storage->shader_allocate(); storage->shader_initialize(sky_shader.default_shader); - storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = vec3(0.0); } \n"); + storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void sky() { COLOR = vec3(0.0); } \n"); sky_shader.default_material = storage->material_allocate(); storage->material_initialize(sky_shader.default_material); @@ -840,7 +841,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { sky_scene_state.fog_shader = storage->shader_allocate(); storage->shader_initialize(sky_scene_state.fog_shader); - storage->shader_set_code(sky_scene_state.fog_shader, "shader_type sky; uniform vec4 clear_color; void fragment() { COLOR = clear_color.rgb; } \n"); + storage->shader_set_code(sky_scene_state.fog_shader, "shader_type sky; uniform vec4 clear_color; void sky() { COLOR = clear_color.rgb; } \n"); sky_scene_state.fog_material = storage->material_allocate(); storage->material_initialize(sky_scene_state.fog_material); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index b984f850a0..92df9cc702 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -4781,6 +4781,7 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) { ShaderCompilerRD::GeneratedCode gen_code; ShaderCompilerRD::IdentifierActions actions; + actions.entry_point_stages["process"] = ShaderCompilerRD::STAGE_COMPUTE; /* uses_time = false; @@ -4801,7 +4802,7 @@ void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) { version = base_singleton->particles_shader.shader.version_create(); } - base_singleton->particles_shader.shader.version_set_compute_code(version, gen_code.uniforms, gen_code.compute_global, gen_code.compute, gen_code.defines); + base_singleton->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_COMPUTE], gen_code.defines); ERR_FAIL_COND(!base_singleton->particles_shader.shader.version_is_valid(version)); ubo_size = gen_code.uniform_total_size; @@ -8824,7 +8825,6 @@ RendererStorageRD::RendererStorageRD() { sdf_versions.push_back(""); //one only giprobe_sdf_shader.initialize(sdf_versions); giprobe_sdf_shader_version = giprobe_sdf_shader.version_create(); - giprobe_sdf_shader.version_set_compute_code(giprobe_sdf_shader_version, "", "", "", Vector<String>()); giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0); giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader); } @@ -8913,7 +8913,7 @@ RendererStorageRD::RendererStorageRD() { // default material and shader for particles shader particles_shader.default_shader = shader_allocate(); shader_initialize(particles_shader.default_shader); - shader_set_code(particles_shader.default_shader, "shader_type particles; void compute() { COLOR = vec4(1.0); } \n"); + shader_set_code(particles_shader.default_shader, "shader_type particles; void process() { COLOR = vec4(1.0); } \n"); particles_shader.default_material = material_allocate(); material_initialize(particles_shader.default_material); material_set_shader(particles_shader.default_material, particles_shader.default_shader); diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index 8135d388e1..24ac85bb35 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -535,9 +535,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge struct_code += "}"; struct_code += ";\n"; - r_gen_code.vertex_global += struct_code; - r_gen_code.fragment_global += struct_code; - r_gen_code.compute_global += struct_code; + for (int j = 0; j < STAGE_MAX; j++) { + r_gen_code.stage_globals[j] += struct_code; + } } int max_texture_uniforms = 0; @@ -590,9 +590,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge ucode += " " + _mkid(E->key()); ucode += ";\n"; if (SL::is_sampler_type(E->get().type)) { - r_gen_code.vertex_global += ucode; - r_gen_code.fragment_global += ucode; - r_gen_code.compute_global += ucode; + for (int j = 0; j < STAGE_MAX; j++) { + r_gen_code.stage_globals[j] += ucode; + } GeneratedCode::Texture texture; texture.name = E->key(); @@ -608,7 +608,6 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge r_gen_code.texture_uniforms.write[E->get().texture_order] = texture; } else { if (!uses_uniforms) { - r_gen_code.defines.push_back(String("#define USE_MATERIAL_UNIFORMS\n")); uses_uniforms = true; } uniform_defines.write[E->get().order] = ucode; @@ -707,9 +706,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge vcode += "]"; } vcode += ";\n"; - r_gen_code.vertex_global += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode; - r_gen_code.fragment_global += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode; - r_gen_code.compute_global += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode; + + r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode; + r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode; + index++; } @@ -725,7 +725,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge gcode += ";\n"; } gcode += "} frag_to_light;\n"; - r_gen_code.fragment_global += gcode; + r_gen_code.stage_globals[STAGE_FRAGMENT] += gcode; } for (int i = 0; i < pnode->vconstants.size(); i++) { @@ -747,9 +747,9 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge gcode += "="; gcode += _dump_node_code(cnode.initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); gcode += ";\n"; - r_gen_code.vertex_global += gcode; - r_gen_code.fragment_global += gcode; - r_gen_code.compute_global += gcode; + for (int j = 0; j < STAGE_MAX; j++) { + r_gen_code.stage_globals[j] += gcode; + } } Map<StringName, String> function_code; @@ -765,9 +765,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge //place functions in actual code - Set<StringName> added_vtx; - Set<StringName> added_fragment; //share for light - Set<StringName> added_compute; //share for light + Set<StringName> added_funcs_per_stage[STAGE_MAX]; for (int i = 0; i < pnode->functions.size(); i++) { SL::FunctionNode *fnode = pnode->functions[i].function; @@ -776,24 +774,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge current_func_name = fnode->name; - if (fnode->name == vertex_name) { - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.vertex_global, added_vtx); - r_gen_code.vertex = function_code[vertex_name]; - } - - if (fnode->name == fragment_name) { - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); - r_gen_code.fragment = function_code[fragment_name]; - } - - if (fnode->name == light_name) { - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); - r_gen_code.light = function_code[light_name]; - } - - if (fnode->name == compute_name) { - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.compute_global, added_compute); - r_gen_code.compute = function_code[compute_name]; + if (p_actions.entry_point_stages.has(fnode->name)) { + Stage stage = p_actions.entry_point_stages[fnode->name]; + _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.stage_globals[stage], added_funcs_per_stage[stage]); + r_gen_code.code[fnode->name] = function_code[fnode->name]; } function = nullptr; @@ -858,7 +842,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge SL::VariableNode *vnode = (SL::VariableNode *)p_node; bool use_fragment_varying = false; - if (current_func_name != vertex_name) { + if (!(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) { if (p_assigning) { if (shader->varyings.has(vnode->name)) { use_fragment_varying = true; @@ -921,10 +905,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } if (vnode->name == time_name) { - if (current_func_name == vertex_name) { + if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX) { r_gen_code.uses_vertex_time = true; } - if (current_func_name == fragment_name || current_func_name == light_name) { + if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_FRAGMENT) { r_gen_code.uses_fragment_time = true; } } @@ -1003,7 +987,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge SL::ArrayNode *anode = (SL::ArrayNode *)p_node; bool use_fragment_varying = false; - if (current_func_name != vertex_name) { + if (!(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) { if (anode->assign_expression != nullptr) { use_fragment_varying = true; } else { @@ -1059,10 +1043,10 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } if (anode->name == time_name) { - if (current_func_name == vertex_name) { + if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX) { r_gen_code.uses_vertex_time = true; } - if (current_func_name == fragment_name || current_func_name == light_name) { + if (p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_FRAGMENT) { r_gen_code.uses_fragment_time = true; } } @@ -1309,7 +1293,7 @@ ShaderLanguage::DataType ShaderCompilerRD::_get_variable_type(const StringName & } Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { - Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types(), _get_variable_type); + Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderLanguage::VaryingFunctionNames(), ShaderTypes::get_singleton()->get_types(), _get_variable_type); if (err != OK) { Vector<String> shader = p_code.split("\n"); @@ -1322,13 +1306,10 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide } r_gen_code.defines.clear(); - r_gen_code.vertex = String(); - r_gen_code.vertex_global = String(); - r_gen_code.fragment = String(); - r_gen_code.fragment_global = String(); - r_gen_code.compute = String(); - r_gen_code.compute_global = String(); - r_gen_code.light = String(); + r_gen_code.code.clear(); + for (int i = 0; i < STAGE_MAX; i++) { + r_gen_code.stage_globals[i] = String(); + } r_gen_code.uses_fragment_time = false; r_gen_code.uses_vertex_time = false; r_gen_code.uses_global_textures = false; @@ -1348,10 +1329,6 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) { actions = p_actions; - vertex_name = "vertex"; - fragment_name = "fragment"; - compute_name = "compute"; - light_name = "light"; time_name = "TIME"; List<String> func_list; diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.h b/servers/rendering/renderer_rd/shader_compiler_rd.h index 6575829e73..2da127ffa3 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.h +++ b/servers/rendering/renderer_rd/shader_compiler_rd.h @@ -38,7 +38,16 @@ class ShaderCompilerRD { public: + enum Stage { + STAGE_VERTEX, + STAGE_FRAGMENT, + STAGE_COMPUTE, + STAGE_MAX + }; + struct IdentifierActions { + Map<StringName, Stage> entry_point_stages; + Map<StringName, Pair<int *, int>> render_mode_values; Map<StringName, bool *> render_mode_flags; Map<StringName, bool *> usage_flag_pointers; @@ -63,13 +72,9 @@ public: Vector<uint32_t> uniform_offsets; uint32_t uniform_total_size; String uniforms; - String vertex_global; - String vertex; - String fragment_global; - String fragment; - String light; - String compute_global; - String compute; + String stage_globals[STAGE_MAX]; + + Map<String, String> code; bool uses_global_textures; bool uses_fragment_time; @@ -103,10 +108,6 @@ private: const ShaderLanguage::ShaderNode *shader; const ShaderLanguage::FunctionNode *function; StringName current_func_name; - StringName vertex_name; - StringName fragment_name; - StringName light_name; - StringName compute_name; StringName time_name; Set<StringName> texture_functions; diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index e4a39ff813..c48a2ef48c 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -30,146 +30,83 @@ #include "shader_rd.h" -#include "core/string/string_builder.h" #include "renderer_compositor_rd.h" #include "servers/rendering/rendering_device.h" -void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name) { - name = p_name; - //split vertex and shader code (thank you, shader compiler programmers from you know what company). - if (p_vertex_code) { - String defines_tag = "\nVERSION_DEFINES"; - String globals_tag = "\nVERTEX_SHADER_GLOBALS"; - String material_tag = "\nMATERIAL_UNIFORMS"; - String code_tag = "\nVERTEX_SHADER_CODE"; - String code = p_vertex_code; - - int cpos = code.find(defines_tag); - if (cpos != -1) { - vertex_codev = code.substr(0, cpos).ascii(); - code = code.substr(cpos + defines_tag.length(), code.length()); - } - - cpos = code.find(material_tag); - - if (cpos == -1) { - vertex_code0 = code.ascii(); - } else { - vertex_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + material_tag.length(), code.length()); - - cpos = code.find(globals_tag); - - if (cpos == -1) { - vertex_code1 = code.ascii(); - } else { - vertex_code1 = code.substr(0, cpos).ascii(); - String code2 = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code2.find(code_tag); - if (cpos == -1) { - vertex_code2 = code2.ascii(); - } else { - vertex_code2 = code2.substr(0, cpos).ascii(); - vertex_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii(); +void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) { + Vector<String> lines = String(p_code).split("\n"); + + String text; + + for (int i = 0; i < lines.size(); i++) { + String l = lines[i]; + bool push_chunk = false; + + StageTemplate::Chunk chunk; + + if (l.begins_with("#VERSION_DEFINES")) { + chunk.type = StageTemplate::Chunk::TYPE_VERSION_DEFINES; + push_chunk = true; + } else if (l.begins_with("#GLOBALS")) { + switch (p_stage_type) { + case STAGE_TYPE_VERTEX: + chunk.type = StageTemplate::Chunk::TYPE_VERTEX_GLOBALS; + break; + case STAGE_TYPE_FRAGMENT: + chunk.type = StageTemplate::Chunk::TYPE_FRAGMENT_GLOBALS; + break; + case STAGE_TYPE_COMPUTE: + chunk.type = StageTemplate::Chunk::TYPE_COMPUTE_GLOBALS; + break; + default: { } } - } - } - if (p_fragment_code) { - String defines_tag = "\nVERSION_DEFINES"; - String globals_tag = "\nFRAGMENT_SHADER_GLOBALS"; - String material_tag = "\nMATERIAL_UNIFORMS"; - String code_tag = "\nFRAGMENT_SHADER_CODE"; - String light_code_tag = "\nLIGHT_SHADER_CODE"; - String code = p_fragment_code; - - int cpos = code.find(defines_tag); - if (cpos != -1) { - fragment_codev = code.substr(0, cpos).ascii(); - code = code.substr(cpos + defines_tag.length(), code.length()); + push_chunk = true; + } else if (l.begins_with("#MATERIAL_UNIFORMS")) { + chunk.type = StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS; + push_chunk = true; + } else if (l.begins_with("#CODE")) { + chunk.type = StageTemplate::Chunk::TYPE_CODE; + push_chunk = true; + chunk.code = l.replace_first("#CODE", String()).replace(":", "").strip_edges().to_upper(); + } else { + text += l + "\n"; } - cpos = code.find(material_tag); - if (cpos == -1) { - fragment_code0 = code.ascii(); - } else { - fragment_code0 = code.substr(0, cpos).ascii(); - //print_line("CODE0:\n"+String(fragment_code0.get_data())); - code = code.substr(cpos + material_tag.length(), code.length()); - cpos = code.find(globals_tag); - - if (cpos == -1) { - fragment_code1 = code.ascii(); - } else { - fragment_code1 = code.substr(0, cpos).ascii(); - //print_line("CODE1:\n"+String(fragment_code1.get_data())); - - String code2 = code.substr(cpos + globals_tag.length(), code.length()); - cpos = code2.find(light_code_tag); - - if (cpos == -1) { - fragment_code2 = code2.ascii(); - } else { - fragment_code2 = code2.substr(0, cpos).ascii(); - //print_line("CODE2:\n"+String(fragment_code2.get_data())); - - String code3 = code2.substr(cpos + light_code_tag.length(), code2.length()); - - cpos = code3.find(code_tag); - if (cpos == -1) { - fragment_code3 = code3.ascii(); - } else { - fragment_code3 = code3.substr(0, cpos).ascii(); - //print_line("CODE3:\n"+String(fragment_code3.get_data())); - fragment_code4 = code3.substr(cpos + code_tag.length(), code3.length()).ascii(); - //print_line("CODE4:\n"+String(fragment_code4.get_data())); - } - } + if (push_chunk) { + if (text != String()) { + StageTemplate::Chunk text_chunk; + text_chunk.type = StageTemplate::Chunk::TYPE_TEXT; + text_chunk.text = text.utf8(); + stage_templates[p_stage_type].chunks.push_back(text_chunk); + text = String(); } + stage_templates[p_stage_type].chunks.push_back(chunk); } } + if (text != String()) { + StageTemplate::Chunk text_chunk; + text_chunk.type = StageTemplate::Chunk::TYPE_TEXT; + text_chunk.text = text.utf8(); + stage_templates[p_stage_type].chunks.push_back(text_chunk); + text = String(); + } +} + +void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name) { + name = p_name; if (p_compute_code) { + _add_stage(p_compute_code, STAGE_TYPE_COMPUTE); is_compute = true; - - String defines_tag = "\nVERSION_DEFINES"; - String globals_tag = "\nCOMPUTE_SHADER_GLOBALS"; - String material_tag = "\nMATERIAL_UNIFORMS"; - String code_tag = "\nCOMPUTE_SHADER_CODE"; - String code = p_compute_code; - - int cpos = code.find(defines_tag); - if (cpos != -1) { - compute_codev = code.substr(0, cpos).ascii(); - code = code.substr(cpos + defines_tag.length(), code.length()); + } else { + is_compute = false; + if (p_vertex_code) { + _add_stage(p_vertex_code, STAGE_TYPE_VERTEX); } - - cpos = code.find(material_tag); - - if (cpos == -1) { - compute_code0 = code.ascii(); - } else { - compute_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + material_tag.length(), code.length()); - - cpos = code.find(globals_tag); - - if (cpos == -1) { - compute_code1 = code.ascii(); - } else { - compute_code1 = code.substr(0, cpos).ascii(); - String code2 = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code2.find(code_tag); - if (cpos == -1) { - compute_code2 = code2.ascii(); - } else { - compute_code2 = code2.substr(0, cpos).ascii(); - compute_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii(); - } - } + if (p_fragment_code) { + _add_stage(p_fragment_code, STAGE_TYPE_FRAGMENT); } } } @@ -198,6 +135,49 @@ void ShaderRD::_clear_version(Version *p_version) { } } +void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, const Version *p_version, const StageTemplate &p_template) { + for (uint32_t i = 0; i < p_template.chunks.size(); i++) { + const StageTemplate::Chunk &chunk = p_template.chunks[i]; + switch (chunk.type) { + case StageTemplate::Chunk::TYPE_VERSION_DEFINES: { + builder.append("\n"); //make sure defines begin at newline + builder.append(general_defines.get_data()); + builder.append(variant_defines[p_variant].get_data()); + for (int j = 0; j < p_version->custom_defines.size(); j++) { + builder.append(p_version->custom_defines[j].get_data()); + } + builder.append("\n"); //make sure defines begin at newline + if (p_version->uniforms.size()) { + builder.append("#define MATERIAL_UNIFORMS_USED\n"); + } + for (Map<StringName, CharString>::Element *E = p_version->code_sections.front(); E; E = E->next()) { + builder.append(String("#define ") + String(E->key()) + "_CODE_USED\n"); + } + } break; + case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: { + builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) + } break; + case StageTemplate::Chunk::TYPE_VERTEX_GLOBALS: { + builder.append(p_version->vertex_globals.get_data()); // vertex globals + } break; + case StageTemplate::Chunk::TYPE_FRAGMENT_GLOBALS: { + builder.append(p_version->fragment_globals.get_data()); // fragment globals + } break; + case StageTemplate::Chunk::TYPE_COMPUTE_GLOBALS: { + builder.append(p_version->compute_globals.get_data()); // compute globals + } break; + case StageTemplate::Chunk::TYPE_CODE: { + if (p_version->code_sections.has(chunk.code)) { + builder.append(p_version->code_sections[chunk.code].get_data()); + } + } break; + case StageTemplate::Chunk::TYPE_TEXT: { + builder.append(chunk.text.get_data()); + } break; + } + } +} + void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { if (!variants_enabled[p_variant]) { return; //variant is disabled, return @@ -214,29 +194,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { //vertex stage StringBuilder builder; - - builder.append(vertex_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - builder.append(general_defines.get_data()); - builder.append(variant_defines[p_variant].get_data()); - - for (int j = 0; j < p_version->custom_defines.size(); j++) { - builder.append(p_version->custom_defines[j].get_data()); - } - - builder.append(vertex_code0.get_data()); //first part of vertex - - builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) - - builder.append(vertex_code1.get_data()); //second part of vertex - - builder.append(p_version->vertex_globals.get_data()); // vertex globals - - builder.append(vertex_code2.get_data()); //third part of vertex - - builder.append(p_version->vertex_code.get_data()); // code - - builder.append(vertex_code3.get_data()); //fourth of vertex + _build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_VERTEX]); current_source = builder.as_string(); RD::ShaderStageData stage; @@ -254,33 +212,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { current_stage = RD::SHADER_STAGE_FRAGMENT; StringBuilder builder; - - builder.append(fragment_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - - builder.append(general_defines.get_data()); - builder.append(variant_defines[p_variant].get_data()); - for (int j = 0; j < p_version->custom_defines.size(); j++) { - builder.append(p_version->custom_defines[j].get_data()); - } - - builder.append(fragment_code0.get_data()); //first part of fragment - - builder.append(p_version->uniforms.get_data()); //uniforms (same for fragment and fragment) - - builder.append(fragment_code1.get_data()); //first part of fragment - - builder.append(p_version->fragment_globals.get_data()); // fragment globals - - builder.append(fragment_code2.get_data()); //third part of fragment - - builder.append(p_version->fragment_light.get_data()); // fragment light - - builder.append(fragment_code3.get_data()); //fourth part of fragment - - builder.append(p_version->fragment_code.get_data()); // fragment code - - builder.append(fragment_code4.get_data()); //fourth part of fragment + _build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_FRAGMENT]); current_source = builder.as_string(); RD::ShaderStageData stage; @@ -298,30 +230,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { current_stage = RD::SHADER_STAGE_COMPUTE; StringBuilder builder; - - builder.append(compute_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - builder.append(base_compute_defines.get_data()); - builder.append(general_defines.get_data()); - builder.append(variant_defines[p_variant].get_data()); - - for (int j = 0; j < p_version->custom_defines.size(); j++) { - builder.append(p_version->custom_defines[j].get_data()); - } - - builder.append(compute_code0.get_data()); //first part of compute - - builder.append(p_version->uniforms.get_data()); //uniforms (same for compute and fragment) - - builder.append(compute_code1.get_data()); //second part of compute - - builder.append(p_version->compute_globals.get_data()); // compute globals - - builder.append(compute_code2.get_data()); //third part of compute - - builder.append(p_version->compute_code.get_data()); // code - - builder.append(compute_code3.get_data()); //fourth of compute + _build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_COMPUTE]); current_source = builder.as_string(); RD::ShaderStageData stage; @@ -364,29 +273,7 @@ RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_versio //vertex stage StringBuilder builder; - - builder.append(vertex_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - builder.append(general_defines.get_data()); - builder.append(variant_defines[i].get_data()); - - for (int j = 0; j < version->custom_defines.size(); j++) { - builder.append(version->custom_defines[j].get_data()); - } - - builder.append(vertex_code0.get_data()); //first part of vertex - - builder.append(version->uniforms.get_data()); //uniforms (same for vertex and fragment) - - builder.append(vertex_code1.get_data()); //second part of vertex - - builder.append(version->vertex_globals.get_data()); // vertex globals - - builder.append(vertex_code2.get_data()); //third part of vertex - - builder.append(version->vertex_code.get_data()); // code - - builder.append(vertex_code3.get_data()); //fourth of vertex + _build_variant_code(builder, i, version, stage_templates[STAGE_TYPE_VERTEX]); RS::ShaderNativeSourceCode::Version::Stage stage; stage.name = "vertex"; @@ -399,32 +286,7 @@ RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_versio //fragment stage StringBuilder builder; - - builder.append(fragment_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - builder.append(general_defines.get_data()); - builder.append(variant_defines[i].get_data()); - for (int j = 0; j < version->custom_defines.size(); j++) { - builder.append(version->custom_defines[j].get_data()); - } - - builder.append(fragment_code0.get_data()); //first part of fragment - - builder.append(version->uniforms.get_data()); //uniforms (same for fragment and fragment) - - builder.append(fragment_code1.get_data()); //first part of fragment - - builder.append(version->fragment_globals.get_data()); // fragment globals - - builder.append(fragment_code2.get_data()); //third part of fragment - - builder.append(version->fragment_light.get_data()); // fragment light - - builder.append(fragment_code3.get_data()); //fourth part of fragment - - builder.append(version->fragment_code.get_data()); // fragment code - - builder.append(fragment_code4.get_data()); //fourth part of fragment + _build_variant_code(builder, i, version, stage_templates[STAGE_TYPE_FRAGMENT]); RS::ShaderNativeSourceCode::Version::Stage stage; stage.name = "fragment"; @@ -437,30 +299,7 @@ RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_versio //compute stage StringBuilder builder; - - builder.append(compute_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - builder.append(base_compute_defines.get_data()); - builder.append(general_defines.get_data()); - builder.append(variant_defines[i].get_data()); - - for (int j = 0; j < version->custom_defines.size(); j++) { - builder.append(version->custom_defines[j].get_data()); - } - - builder.append(compute_code0.get_data()); //first part of compute - - builder.append(version->uniforms.get_data()); //uniforms (same for compute and fragment) - - builder.append(compute_code1.get_data()); //second part of compute - - builder.append(version->compute_globals.get_data()); // compute globals - - builder.append(compute_code2.get_data()); //third part of compute - - builder.append(version->compute_code.get_data()); // code - - builder.append(compute_code3.get_data()); //fourth of compute + _build_variant_code(builder, i, version, stage_templates[STAGE_TYPE_COMPUTE]); RS::ShaderNativeSourceCode::Version::Stage stage; stage.name = "compute"; @@ -518,17 +357,18 @@ void ShaderRD::_compile_version(Version *p_version) { p_version->valid = true; } -void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector<String> &p_custom_defines) { +void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) { ERR_FAIL_COND(is_compute); Version *version = version_owner.getornull(p_version); ERR_FAIL_COND(!version); version->vertex_globals = p_vertex_globals.utf8(); - version->vertex_code = p_vertex_code.utf8(); - version->fragment_light = p_fragment_light.utf8(); version->fragment_globals = p_fragment_globals.utf8(); - version->fragment_code = p_fragment_code.utf8(); version->uniforms = p_uniforms.utf8(); + version->code_sections.clear(); + for (Map<String, String>::Element *E = p_code.front(); E; E = E->next()) { + version->code_sections[StringName(E->key().to_upper())] = E->get().utf8(); + } version->custom_defines.clear(); for (int i = 0; i < p_custom_defines.size(); i++) { @@ -542,15 +382,20 @@ void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const S } } -void ShaderRD::version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector<String> &p_custom_defines) { +void ShaderRD::version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) { ERR_FAIL_COND(!is_compute); Version *version = version_owner.getornull(p_version); ERR_FAIL_COND(!version); + version->compute_globals = p_compute_globals.utf8(); - version->compute_code = p_compute_code.utf8(); version->uniforms = p_uniforms.utf8(); + version->code_sections.clear(); + for (Map<String, String>::Element *E = p_code.front(); E; E = E->next()) { + version->code_sections[StringName(E->key().to_upper())] = E->get().utf8(); + } + version->custom_defines.clear(); for (int i = 0; i < p_custom_defines.size(); i++) { version->custom_defines.push_back(p_custom_defines[i].utf8()); diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index e0f4dcf2d0..f20d539621 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -32,7 +32,9 @@ #define SHADER_RD_H #include "core/os/mutex.h" +#include "core/string/string_builder.h" #include "core/templates/hash_map.h" +#include "core/templates/local_vector.h" #include "core/templates/map.h" #include "core/templates/rid_owner.h" #include "core/variant/variant.h" @@ -52,12 +54,9 @@ class ShaderRD { struct Version { CharString uniforms; CharString vertex_globals; - CharString vertex_code; CharString compute_globals; - CharString compute_code; - CharString fragment_light; CharString fragment_globals; - CharString fragment_code; + Map<StringName, CharString> code_sections; Vector<CharString> custom_defines; RID *variants; //same size as version defines @@ -76,31 +75,44 @@ class ShaderRD { RID_Owner<Version> version_owner; - CharString fragment_codev; //for version and extensions - CharString fragment_code0; - CharString fragment_code1; - CharString fragment_code2; - CharString fragment_code3; - CharString fragment_code4; - - CharString vertex_codev; //for version and extensions - CharString vertex_code0; - CharString vertex_code1; - CharString vertex_code2; - CharString vertex_code3; + struct StageTemplate { + struct Chunk { + enum Type { + TYPE_VERSION_DEFINES, + TYPE_MATERIAL_UNIFORMS, + TYPE_VERTEX_GLOBALS, + TYPE_FRAGMENT_GLOBALS, + TYPE_COMPUTE_GLOBALS, + TYPE_CODE, + TYPE_TEXT + }; + + Type type; + StringName code; + CharString text; + }; + LocalVector<Chunk> chunks; + }; bool is_compute = false; - CharString compute_codev; //for version and extensions - CharString compute_code0; - CharString compute_code1; - CharString compute_code2; - CharString compute_code3; - const char *name; CharString base_compute_defines; + enum StageType { + STAGE_TYPE_VERTEX, + STAGE_TYPE_FRAGMENT, + STAGE_TYPE_COMPUTE, + STAGE_TYPE_MAX, + }; + + StageTemplate stage_templates[STAGE_TYPE_MAX]; + + void _build_variant_code(StringBuilder &p_builder, uint32_t p_variant, const Version *p_version, const StageTemplate &p_template); + + void _add_stage(const char *p_code, StageType p_stage_type); + protected: ShaderRD(); void setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name); @@ -108,8 +120,8 @@ protected: public: RID version_create(); - void version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector<String> &p_custom_defines); - void version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector<String> &p_custom_defines); + void version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines); + void version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines); _FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) { ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID()); diff --git a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl index 63f086a83d..b70e0b6bd5 100644 --- a/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl +++ b/servers/rendering/renderer_rd/shaders/bokeh_dof.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #define BLOCK_SIZE 8 diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index 3b39edc70e..8b97ec119f 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #ifdef USE_ATTRIBUTES layout(location = 0) in vec2 vertex_attrib; @@ -26,17 +26,15 @@ layout(location = 3) out vec2 pixel_size_interp; #endif -#ifdef USE_MATERIAL_UNIFORMS +#ifdef MATERIAL_UNIFORMS_USED layout(set = 1, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ + +#MATERIAL_UNIFORMS + } material; #endif -/* clang-format off */ -VERTEX_SHADER_GLOBALS -/* clang-format on */ +#GLOBALS void main() { vec4 instance_custom = vec4(0.0); @@ -132,9 +130,7 @@ void main() { float point_size = 1.0; #endif { - /* clang-format off */ -VERTEX_SHADER_CODE - /* clang-format on */ +#CODE : VERTEX } #ifdef USE_NINEPATCH @@ -212,7 +208,7 @@ VERTEX_SHADER_CODE #version 450 -VERSION_DEFINES +#VERSION_DEFINES #include "canvas_uniforms_inc.glsl" @@ -228,11 +224,11 @@ layout(location = 3) in vec2 pixel_size_interp; layout(location = 0) out vec4 frag_color; -#ifdef USE_MATERIAL_UNIFORMS +#ifdef MATERIAL_UNIFORMS_USED layout(set = 1, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ + +#MATERIAL_UNIFORMS + } material; #endif @@ -260,11 +256,9 @@ vec2 sdf_to_screen_uv(vec2 p_sdf) { return p_sdf * canvas_data.sdf_to_screen; } -/* clang-format off */ -FRAGMENT_SHADER_GLOBALS -/* clang-format on */ +#GLOBALS -#ifdef LIGHT_SHADER_CODE_USED +#ifdef LIGHT_CODE_USED vec4 light_compute( vec3 light_vertex, @@ -278,9 +272,9 @@ vec4 light_compute( vec2 uv, vec4 color, bool is_directional) { vec4 light = vec4(0.0); - /* clang-format off */ -LIGHT_SHADER_CODE - /* clang-format on */ + +#CODE : LIGHT + return light; } @@ -356,7 +350,7 @@ vec3 light_normal_compute(vec3 light_vec, vec3 normal, vec3 base_color, vec3 lig //float distance = length(shadow_pos); vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv -#ifdef LIGHT_SHADER_CODE_USED +#ifdef LIGHT_CODE_USED , vec3 shadow_modulate #endif @@ -395,7 +389,7 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv } vec4 shadow_color = unpackUnorm4x8(light_array.data[light_base].shadow_color); -#ifdef LIGHT_SHADER_CODE_USED +#ifdef LIGHT_CODE_USED shadow_color.rgb *= shadow_modulate; #endif @@ -504,11 +498,7 @@ void main() { normal_used = true; #endif - /* clang-format off */ - -FRAGMENT_SHADER_CODE - - /* clang-format on */ +#CODE : FRAGMENT #if defined(NORMAL_MAP_USED) normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_map_depth); @@ -543,7 +533,7 @@ FRAGMENT_SHADER_CODE vec2 direction = light_array.data[light_base].position; vec4 light_color = light_array.data[light_base].color; -#ifdef LIGHT_SHADER_CODE_USED +#ifdef LIGHT_CODE_USED vec4 shadow_modulate = vec4(1.0); light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, true); @@ -561,7 +551,7 @@ FRAGMENT_SHADER_CODE vec4 shadow_uv = vec4(shadow_pos.x, light_array.data[light_base].shadow_y_ofs, shadow_pos.y * light_array.data[light_base].shadow_zfar_inv, 1.0); light_color = light_shadow_compute(light_base, light_color, shadow_uv -#ifdef LIGHT_SHADER_CODE_USED +#ifdef LIGHT_CODE_USED , shadow_modulate.rgb #endif @@ -599,7 +589,7 @@ FRAGMENT_SHADER_CODE vec4 light_color = textureLod(sampler2D(atlas_texture, texture_sampler), tex_uv_atlas, 0.0); vec4 light_base_color = light_array.data[light_base].color; -#ifdef LIGHT_SHADER_CODE_USED +#ifdef LIGHT_CODE_USED vec4 shadow_modulate = vec4(1.0); vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height); @@ -657,7 +647,7 @@ FRAGMENT_SHADER_CODE vec4 shadow_uv = vec4(tex_ofs, light_array.data[light_base].shadow_y_ofs, distance, 1.0); light_color = light_shadow_compute(light_base, light_color, shadow_uv -#ifdef LIGHT_SHADER_CODE_USED +#ifdef LIGHT_CODE_USED , shadow_modulate.rgb #endif diff --git a/servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl index 5c25235c58..9f89f4b3b7 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) in highp vec3 vertex; @@ -32,7 +32,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(push_constant, binding = 0, std430) uniform Constants { mat4 projection; diff --git a/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl b/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl index 302ad03b41..65a554e839 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_sdf.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/cluster_debug.glsl b/servers/rendering/renderer_rd/shaders/cluster_debug.glsl index 70a875192c..40da2c6e5c 100644 --- a/servers/rendering/renderer_rd/shaders/cluster_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_debug.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl index ca92d2104e..da7d189281 100644 --- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) in vec3 vertex_attrib; @@ -63,7 +63,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES #if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) && defined(has_GL_KHR_shader_subgroup_vote) diff --git a/servers/rendering/renderer_rd/shaders/cluster_store.glsl b/servers/rendering/renderer_rd/shaders/cluster_store.glsl index 5be0893c4f..b0606efa94 100644 --- a/servers/rendering/renderer_rd/shaders/cluster_store.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_store.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/copy.glsl b/servers/rendering/renderer_rd/shaders/copy.glsl index cdd35dfb3f..4110a95ddb 100644 --- a/servers/rendering/renderer_rd/shaders/copy.glsl +++ b/servers/rendering/renderer_rd/shaders/copy.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl index 9751e13b4e..8c68e2dc2f 100644 --- a/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/copy_to_fb.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) out vec2 uv_interp; @@ -37,7 +37,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(push_constant, binding = 1, std430) uniform Params { vec4 section; diff --git a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl index c3ac0bee57..dfbce29119 100644 --- a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl +++ b/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(push_constant, binding = 1, std430) uniform Params { float z_far; @@ -26,7 +26,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) in vec2 uv_interp; diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl b/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl index 7f269b7af3..9fa84657d1 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl @@ -22,7 +22,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #define BLOCK_SIZE 8 diff --git a/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl b/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl index 987545fb76..2a774b0eb4 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl @@ -22,7 +22,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #define GROUP_SIZE 64 diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl index 5cbb00baa4..ce7c03c1d4 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl +++ b/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #define GROUP_SIZE 8 diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl index 92a5682572..bfd5c4c88d 100644 --- a/servers/rendering/renderer_rd/shaders/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/gi.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/giprobe.glsl index b931461b31..49a493cdc7 100644 --- a/servers/rendering/renderer_rd/shaders/giprobe.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #ifdef MODE_DYNAMIC layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl b/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl index 515cc35507..7d4d72967a 100644 --- a/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe_debug.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES struct CellData { uint position; // xyz 10 bits @@ -172,7 +172,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) in vec4 color_interp; layout(location = 0) out vec4 frag_color; diff --git a/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl b/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl index 5b3dec0ee7..e20b3f680d 100644 --- a/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe_sdf.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; diff --git a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl index 56b3b7ccb4..5dc2d08a3b 100644 --- a/servers/rendering/renderer_rd/shaders/giprobe_write.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe_write.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl index 8a11c35b78..466442b67a 100644 --- a/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl +++ b/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #define BLOCK_SIZE 8 diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index cb6d8dc7f6..c438352c05 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; @@ -146,11 +146,11 @@ layout(set = 2, binding = 1) uniform texture2D height_field_texture; /* SET 3: MATERIAL */ -#ifdef USE_MATERIAL_UNIFORMS +#ifdef MATERIAL_UNIFORMS_USED layout(set = 3, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ + +#MATERIAL_UNIFORMS + } material; #endif @@ -196,11 +196,7 @@ bool emit_subparticle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom return true; } -/* clang-format off */ - -COMPUTE_SHADER_GLOBALS - -/* clang-format on */ +#GLOBALS void main() { uint particle = gl_GlobalInvocationID.x; @@ -540,10 +536,6 @@ void main() { } if (PARTICLE.is_active) { - /* clang-format off */ - -COMPUTE_SHADER_CODE - - /* clang-format on */ +#CODE : PROCESS } } diff --git a/servers/rendering/renderer_rd/shaders/particles_copy.glsl b/servers/rendering/renderer_rd/shaders/particles_copy.glsl index 6c782b6045..80adb49619 100644 --- a/servers/rendering/renderer_rd/shaders/particles_copy.glsl +++ b/servers/rendering/renderer_rd/shaders/particles_copy.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/resolve.glsl b/servers/rendering/renderer_rd/shaders/resolve.glsl index e83c4ca93b..2286a26485 100644 --- a/servers/rendering/renderer_rd/shaders/resolve.glsl +++ b/servers/rendering/renderer_rd/shaders/resolve.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/roughness_limiter.glsl b/servers/rendering/renderer_rd/shaders/roughness_limiter.glsl index 464895928a..7b964675ca 100644 --- a/servers/rendering/renderer_rd/shaders/roughness_limiter.glsl +++ b/servers/rendering/renderer_rd/shaders/roughness_limiter.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 76edec1cb6..fce17c47e8 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #include "scene_forward_clustered_inc.glsl" @@ -81,11 +81,11 @@ layout(location = 5) out vec3 tangent_interp; layout(location = 6) out vec3 binormal_interp; #endif -#ifdef USE_MATERIAL_UNIFORMS +#ifdef MATERIAL_UNIFORMS_USED layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ + +#MATERIAL_UNIFORMS + } material; #endif @@ -99,11 +99,7 @@ layout(location = 8) out float dp_clip; layout(location = 9) out flat uint instance_index; -/* clang-format off */ - -VERTEX_SHADER_GLOBALS - -/* clang-format on */ +#GLOBALS void main() { vec4 instance_custom = vec4(0.0); @@ -230,11 +226,7 @@ void main() { mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix; { - /* clang-format off */ - -VERTEX_SHADER_CODE - - /* clang-format on */ +#CODE : VERTEX } // using local coordinates (default) @@ -325,7 +317,7 @@ VERTEX_SHADER_CODE #version 450 -VERSION_DEFINES +#VERSION_DEFINES #include "scene_forward_clustered_inc.glsl" @@ -372,19 +364,15 @@ layout(location = 9) in flat uint instance_index; #define LIGHT_TRANSMITTANCE_USED #endif -#ifdef USE_MATERIAL_UNIFORMS +#ifdef MATERIAL_UNIFORMS_USED layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ -} material; -#endif -/* clang-format off */ +#MATERIAL_UNIFORMS -FRAGMENT_SHADER_GLOBALS +} material; +#endif -/* clang-format on */ +#GLOBALS #ifdef MODE_RENDER_DEPTH @@ -581,18 +569,14 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, #endif inout vec3 diffuse_light, inout vec3 specular_light) { -#if defined(USE_LIGHT_SHADER_CODE) +#if defined(LIGHT_CODE_USED) // light is written by the light shader vec3 normal = N; vec3 light = L; vec3 view = V; - /* clang-format off */ - -LIGHT_SHADER_CODE - - /* clang-format on */ +#CODE : LIGHT #else @@ -794,7 +778,7 @@ LIGHT_SHADER_CODE alpha = min(alpha, clamp(1.0 - attenuation), 0.0, 1.0)); #endif -#endif //defined(USE_LIGHT_SHADER_CODE) +#endif //defined(LIGHT_CODE_USED) } #ifndef USE_NO_SHADOWS @@ -1925,11 +1909,7 @@ void main() { #endif // ALPHA_ANTIALIASING_EDGE_USED { - /* clang-format off */ - -FRAGMENT_SHADER_CODE - - /* clang-format on */ +#CODE : FRAGMENT } #ifdef LIGHT_TRANSMITTANCE_USED diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl index 06dc4b13de..78e0a85341 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl index a5afe74cb2..62d1cffb0a 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl +++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl index 218605a962..7e06516d90 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl +++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl index e4c3f3a84b..8b58796962 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl index 08da283dad..0eacbc5363 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #define MAX_CASCADES 8 @@ -153,7 +153,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) out vec4 frag_color; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl index dc7238abed..99db35bb34 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_fields.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_fields.glsl deleted file mode 100644 index 69d8824d8a..0000000000 --- a/servers/rendering/renderer_rd/shaders/sdfgi_fields.glsl +++ /dev/null @@ -1,182 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = OCT_RES, local_size_y = OCT_RES, local_size_z = 1) in; - -/* clang-format on */ - -#define MAX_CASCADES 8 - -layout(rgba16f, set = 0, binding = 1) uniform restrict image2DArray irradiance_texture; -layout(rg16f, set = 0, binding = 2) uniform restrict image2DArray depth_texture; - -layout(rgba32ui, set = 0, binding = 3) uniform restrict uimage2DArray irradiance_history_texture; -layout(rg32ui, set = 0, binding = 4) uniform restrict uimage2DArray depth_history_texture; - -struct CascadeData { - vec3 offset; //offset of (0,0,0) in world coordinates - float to_cell; // 1/bounds * grid_size -}; - -layout(set = 0, binding = 5, std140) uniform Cascades { - CascadeData data[MAX_CASCADES]; -} -cascades; - -#define DEPTH_HISTORY_BITS 24 -#define IRRADIANCE_HISTORY_BITS 16 - -layout(push_constant, binding = 0, std430) uniform Params { - vec3 grid_size; - uint max_cascades; - - uint probe_axis_size; - uint cascade; - uint history_size; - uint pad0; - - ivec3 scroll; //scroll in probes - uint pad1; -} -params; - -void main() { - ivec2 local = ivec2(gl_LocalInvocationID.xy); - ivec2 probe = ivec2(gl_WorkGroupID.xy); - - ivec3 probe_cell; - probe_cell.x = probe.x % int(params.probe_axis_size); - probe_cell.y = probe.y; - probe_cell.z = probe.x / int(params.probe_axis_size); - -#ifdef MODE_SCROLL_BEGIN - - ivec3 read_cell = probe_cell - params.scroll; - - uint src_layer = (params.history_size + 1) * params.cascade; - uint dst_layer = (params.history_size + 1) * params.max_cascades; - - for (uint i = 0; i <= params.history_size; i++) { - ivec3 write_pos = ivec3(probe * OCT_RES + local, int(i)); - - if (any(lessThan(read_pos, ivec3(0))) || any(greaterThanEqual(read_pos, ivec3(params.probe_axis_size)))) { - // nowhere to read from for scrolling, try finding the value from upper probes - -#ifdef MODE_IRRADIANCE - imageStore(irradiance_history_texture, write_pos, uvec4(0)); -#endif -#ifdef MODE_DEPTH - imageStore(depth_history_texture, write_pos, uvec4(0)); -#endif - } else { - ivec3 read_pos; - read_pos.xy = read_cell.xy; - read_pos.x += read_cell.z * params.probe_axis_size; - read_pos.xy = read_pos.xy * OCT_RES + local; - read_pos.z = int(i); - -#ifdef MODE_IRRADIANCE - uvec4 value = imageLoad(irradiance_history_texture, read_pos); - imageStore(irradiance_history_texture, write_pos, value); -#endif -#ifdef MODE_DEPTH - uvec2 value = imageLoad(depth_history_texture, read_pos); - imageStore(depth_history_texture, write_pos, value); -#endif - } - } - -#endif // MODE_SCROLL_BEGIN - -#ifdef MODE_SCROLL_END - - uint src_layer = (params.history_size + 1) * params.max_cascades; - uint dst_layer = (params.history_size + 1) * params.cascade; - - for (uint i = 0; i <= params.history_size; i++) { - ivec3 pos = ivec3(probe * OCT_RES + local, int(i)); - -#ifdef MODE_IRRADIANCE - uvec4 value = imageLoad(irradiance_history_texture, read_pos); - imageStore(irradiance_history_texture, write_pos, value); -#endif -#ifdef MODE_DEPTH - uvec2 value = imageLoad(depth_history_texture, read_pos); - imageStore(depth_history_texture, write_pos, value); -#endif - } - -#endif //MODE_SCROLL_END - -#ifdef MODE_STORE - - uint src_layer = (params.history_size + 1) * params.cascade + params.history_size; - ivec3 read_pos = ivec3(probe * OCT_RES + local, int(src_layer)); - - ivec3 write_pos = ivec3(probe * (OCT_RES + 2) + ivec2(1), int(params.cascade)); - - ivec3 copy_to[4] = ivec3[](write_pos, ivec3(-2, -2, -2), ivec3(-2, -2, -2), ivec3(-2, -2, -2)); - -#ifdef MODE_IRRADIANCE - uvec4 average = imageLoad(irradiance_history_texture, read_pos); - vec4 light_accum = vec4(average / params.history_size) / float(1 << IRRADIANCE_HISTORY_BITS); - -#endif -#ifdef MODE_DEPTH - uvec2 value = imageLoad(depth_history_texture, read_pos); - vec2 depth_accum = vec4(average / params.history_size) / float(1 << IRRADIANCE_HISTORY_BITS); - - float probe_cell_size = float(params.grid_size / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell; - float max_depth = length(params.grid_size / cascades.data[params.max_cascades - 1].to_cell); - max_depth /= probe_cell_size; - - depth_value = (vec2(average / params.history_size) / float(1 << DEPTH_HISTORY_BITS)) * vec2(max_depth, max_depth * max_depth); - -#endif - - /* Fill the border if required */ - - if (local == ivec2(0, 0)) { - copy_to[1] = texture_pos + ivec3(OCT_RES - 1, -1, 0); - copy_to[2] = texture_pos + ivec3(-1, OCT_RES - 1, 0); - copy_to[3] = texture_pos + ivec3(OCT_RES, OCT_RES, 0); - } else if (local == ivec2(OCT_RES - 1, 0)) { - copy_to[1] = texture_pos + ivec3(0, -1, 0); - copy_to[2] = texture_pos + ivec3(OCT_RES, OCT_RES - 1, 0); - copy_to[3] = texture_pos + ivec3(-1, OCT_RES, 0); - } else if (local == ivec2(0, OCT_RES - 1)) { - copy_to[1] = texture_pos + ivec3(-1, 0, 0); - copy_to[2] = texture_pos + ivec3(OCT_RES - 1, OCT_RES, 0); - copy_to[3] = texture_pos + ivec3(OCT_RES, -1, 0); - } else if (local == ivec2(OCT_RES - 1, OCT_RES - 1)) { - copy_to[1] = texture_pos + ivec3(0, OCT_RES, 0); - copy_to[2] = texture_pos + ivec3(OCT_RES, 0, 0); - copy_to[3] = texture_pos + ivec3(-1, -1, 0); - } else if (local.y == 0) { - copy_to[1] = texture_pos + ivec3(OCT_RES - local.x - 1, local.y - 1, 0); - } else if (local.x == 0) { - copy_to[1] = texture_pos + ivec3(local.x - 1, OCT_RES - local.y - 1, 0); - } else if (local.y == OCT_RES - 1) { - copy_to[1] = texture_pos + ivec3(OCT_RES - local.x - 1, local.y + 1, 0); - } else if (local.x == OCT_RES - 1) { - copy_to[1] = texture_pos + ivec3(local.x + 1, OCT_RES - local.y - 1, 0); - } - - for (int i = 0; i < 4; i++) { - if (copy_to[i] == ivec3(-2, -2, -2)) { - continue; - } -#ifdef MODE_IRRADIANCE - imageStore(irradiance_texture, copy_to[i], light_accum); -#endif -#ifdef MODE_DEPTH - imageStore(depth_texture, copy_to[i], vec4(depth_value, 0.0, 0.0)); -#endif - } - -#endif // MODE_STORE -} diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl index 007e4c113a..bc376e9522 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl index 916c60ac89..aa4ded146f 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #ifdef MODE_JUMPFLOOD_OPTIMIZED #define GROUP_SIZE 8 diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl index 680d1045cd..669ffc961d 100644 --- a/servers/rendering/renderer_rd/shaders/skeleton.glsl +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl index 6c985e1f5c..9924da37d5 100644 --- a/servers/rendering/renderer_rd/shaders/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/sky.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) out vec2 uv_interp; @@ -24,7 +24,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES #define M_PI 3.14159265359 @@ -88,13 +88,9 @@ layout(set = 0, binding = 3, std140) uniform DirectionalLights { directional_lights; -#ifdef USE_MATERIAL_UNIFORMS +#ifdef MATERIAL_UNIFORMS_USED layout(set = 1, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ - -MATERIAL_UNIFORMS - - /* clang-format on */ +#MATERIAL_UNIFORMS } material; #endif @@ -127,11 +123,7 @@ layout(set = 3, binding = 0) uniform texture3D volumetric_fog_texture; #define AT_QUARTER_RES_PASS false #endif -/* clang-format off */ - -FRAGMENT_SHADER_GLOBALS - -/* clang-format on */ +#GLOBALS layout(location = 0) out vec4 frag_color; @@ -202,22 +194,10 @@ void main() { #endif #endif -// unused, just here to make our compiler happy, make sure we don't execute any light code the user adds in.. -#ifndef REALLYINCLUDETHIS - { - /* clang-format off */ - -LIGHT_SHADER_CODE - - /* clang-format on */ - } -#endif { - /* clang-format off */ -FRAGMENT_SHADER_CODE +#CODE : SKY - /* clang-format on */ } frag_color.rgb = color * params.position_multiplier.w; diff --git a/servers/rendering/renderer_rd/shaders/sort.glsl b/servers/rendering/renderer_rd/shaders/sort.glsl index e5ebb9c64b..307e60dc21 100644 --- a/servers/rendering/renderer_rd/shaders/sort.glsl +++ b/servers/rendering/renderer_rd/shaders/sort.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES // Original version here: // https://github.com/GPUOpen-LibrariesAndSDKs/GPUParticles11/blob/master/gpuparticles11/src/Shaders diff --git a/servers/rendering/renderer_rd/shaders/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/specular_merge.glsl index 0b8f406213..3579c35cce 100644 --- a/servers/rendering/renderer_rd/shaders/specular_merge.glsl +++ b/servers/rendering/renderer_rd/shaders/specular_merge.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) out vec2 uv_interp; @@ -17,7 +17,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) in vec2 uv_interp; diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/ssao.glsl index 231f8f91ec..6e945edfcd 100644 --- a/servers/rendering/renderer_rd/shaders/ssao.glsl +++ b/servers/rendering/renderer_rd/shaders/ssao.glsl @@ -21,7 +21,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES #define SSAO_ADAPTIVE_TAP_BASE_COUNT 5 diff --git a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl b/servers/rendering/renderer_rd/shaders/ssao_blur.glsl index 510a777048..d9cd2b4e85 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl +++ b/servers/rendering/renderer_rd/shaders/ssao_blur.glsl @@ -21,7 +21,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl b/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl index cb2d31f70d..ee0db6a6f0 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl +++ b/servers/rendering/renderer_rd/shaders/ssao_downsample.glsl @@ -21,7 +21,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl index 6aa7624261..687fe1e6e2 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl +++ b/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl @@ -21,7 +21,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl index 4fdf334aa5..0907423d5d 100644 --- a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl +++ b/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl @@ -20,7 +20,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl index 88a953562f..9367b641c2 100644 --- a/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl +++ b/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl index 7de91fd541..86b4da6b08 100644 --- a/servers/rendering/renderer_rd/shaders/tonemap.glsl +++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) out vec2 uv_interp; @@ -16,7 +16,7 @@ void main() { #version 450 -VERSION_DEFINES +#VERSION_DEFINES layout(location = 0) in vec2 uv_interp; diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl index ce8a459b24..cace607667 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl @@ -2,7 +2,7 @@ #version 450 -VERSION_DEFINES +#VERSION_DEFINES /* Do not use subgroups here, seems there is not much advantage and causes glitches #if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h index b546001843..551d4f4240 100644 --- a/servers/rendering/renderer_scene.h +++ b/servers/rendering/renderer_scene.h @@ -69,7 +69,7 @@ public: virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0; virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; - virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0; + virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) = 0; virtual void instance_set_visible(RID p_instance, bool p_visible) = 0; virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb) = 0; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index e8155e4025..2c865186b4 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -752,7 +752,7 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh } } -void RendererSceneCull::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) { +void RendererSceneCull::instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) { Instance *instance = instance_owner.getornull(p_instance); ERR_FAIL_COND(!instance); diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 32f4334288..d7d59665ec 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -840,7 +840,7 @@ public: virtual void instance_set_transform(RID p_instance, const Transform &p_transform); virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); - virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material); + virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material); virtual void instance_set_visible(RID p_instance, bool p_visible); virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index e82d5cc3f8..683a22fd9a 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -703,7 +703,7 @@ public: FUNC2(instance_set_transform, RID, const Transform &) FUNC2(instance_attach_object_instance_id, RID, ObjectID) FUNC3(instance_set_blend_shape_weight, RID, int, float) - FUNC3(instance_set_surface_material, RID, int, RID) + FUNC3(instance_set_surface_override_material, RID, int, RID) FUNC2(instance_set_visible, RID, bool) FUNC2(instance_set_custom_aabb, RID, AABB) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 4ae0eda232..f5228f9747 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -3109,20 +3109,20 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St } switch (p_varying.stage) { case ShaderNode::Varying::STAGE_UNKNOWN: // first assign - if (current_function == String("vertex")) { + if (current_function == varying_function_names.vertex) { p_varying.stage = ShaderNode::Varying::STAGE_VERTEX; - } else if (current_function == String("fragment")) { + } else if (current_function == varying_function_names.fragment) { p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT; } break; case ShaderNode::Varying::STAGE_VERTEX: - if (current_function == String("fragment")) { + if (current_function == varying_function_names.fragment) { *r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'."); return false; } break; case ShaderNode::Varying::STAGE_FRAGMENT: - if (current_function == String("vertex")) { + if (current_function == varying_function_names.vertex) { *r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'."); return false; } @@ -3139,25 +3139,25 @@ bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, Str *r_message = RTR("Varying must be assigned before using!"); return false; case ShaderNode::Varying::STAGE_VERTEX: - if (current_function == String("fragment")) { + if (current_function == varying_function_names.fragment) { p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT; - } else if (current_function == String("light")) { + } else if (current_function == varying_function_names.light) { p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT; } break; case ShaderNode::Varying::STAGE_FRAGMENT: - if (current_function == String("light")) { + if (current_function == varying_function_names.light) { p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT; } break; case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT: - if (current_function == String("light")) { + if (current_function == varying_function_names.light) { *r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'"); return false; } break; case ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT: - if (current_function == String("fragment")) { + if (current_function == varying_function_names.fragment) { *r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'"); return false; } @@ -5847,7 +5847,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun //check return type BlockNode *b = p_block; - if (b && b->parent_function && (b->parent_function->name == "vertex" || b->parent_function->name == "fragment" || b->parent_function->name == "light")) { + if (b && b->parent_function && p_function_info.main_function) { _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name)); return ERR_PARSE_ERROR; } @@ -7246,26 +7246,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } bool ShaderLanguage::has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name) { - if (p_functions.has("vertex")) { - if (p_functions["vertex"].built_ins.has(p_name)) { - return true; - } - } - if (p_functions.has("fragment")) { - if (p_functions["fragment"].built_ins.has(p_name)) { - return true; - } - } - if (p_functions.has("light")) { - if (p_functions["light"].built_ins.has(p_name)) { - return true; - } - } - if (p_functions.has("compute")) { - if (p_functions["compute"].built_ins.has(p_name)) { + for (Map<StringName, ShaderLanguage::FunctionInfo>::Element *E = p_functions.front(); E; E = E->next()) { + if (E->get().built_ins.has(p_name)) { return true; } } + return false; } @@ -7399,11 +7385,12 @@ String ShaderLanguage::get_shader_type(const String &p_code) { return String(); } -Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) { +Error ShaderLanguage::compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func) { clear(); code = p_code; global_var_get_type_func = p_global_variable_type_func; + varying_function_names = p_varying_function_names; nodes = nullptr; @@ -7416,10 +7403,11 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Functi return OK; } -Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) { +Error ShaderLanguage::complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint) { clear(); code = p_code; + varying_function_names = p_varying_function_names; nodes = nullptr; global_var_get_type_func = p_global_variable_type_func; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 14594b039c..03327f9677 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -331,6 +331,17 @@ public: MAX_INSTANCE_UNIFORM_INDICES = 16 }; + struct VaryingFunctionNames { + StringName fragment; + StringName vertex; + StringName light; + VaryingFunctionNames() { + fragment = "fragment"; + vertex = "vertex"; + light = "light"; + } + }; + struct Node { Node *next = nullptr; @@ -769,7 +780,8 @@ public: Map<StringName, BuiltInInfo> built_ins; Map<StringName, StageFunctionInfo> stage_functions; - bool can_discard; + bool can_discard = false; + bool main_function = false; }; static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name); @@ -796,6 +808,8 @@ private: StringName current_function; bool last_const = false; + VaryingFunctionNames varying_function_names; + TkPos _get_tkpos() { TkPos tkp; tkp.char_idx = char_idx; @@ -898,8 +912,8 @@ public: void clear(); static String get_shader_type(const String &p_code); - Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func); - Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint); + Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func); + Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const VaryingFunctionNames &p_varying_function_names, const Set<String> &p_shader_types, GlobalVariableGetTypeFunc p_global_variable_type_func, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint); String get_error_text(); int get_error_line(); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index e99b8504bb..f5f7e2e53d 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -74,6 +74,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM2"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CUSTOM3"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].can_discard = false; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].main_function = true; //builtins shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; @@ -139,6 +140,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["RADIANCE"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["IRRADIANCE"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].can_discard = true; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].main_function = true; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR_THRESHOLD"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_HASH_SCALE"] = ShaderLanguage::TYPE_FLOAT; @@ -171,6 +173,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["light"].can_discard = true; + shader_modes[RS::SHADER_SPATIAL].functions["light"].main_function = true; //order used puts first enum mode (default) first shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mix"); @@ -236,6 +239,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].main_function = true; shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2; shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SHADOW_VERTEX"] = ShaderLanguage::TYPE_VEC2; @@ -257,6 +261,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].main_function = true; { ShaderLanguage::StageFunctionInfo func; @@ -294,6 +299,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].main_function = true; shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform"); @@ -310,34 +316,34 @@ ShaderTypes::ShaderTypes() { /************ PARTICLES **************************/ shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3; - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["MASS"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL; - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4; - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4; - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_VELOCITY"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_COLOR"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_CUSTOM"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_POSITION"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_ROT_SCALE"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_VELOCITY"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_COLOR"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_CUSTOM"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["COLLIDED"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["COLLISION_NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["COLLISION_DEPTH"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["ATTRACTOR_FORCE"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_PARTICLES].functions["compute"].can_discard = false; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["MASS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RESTART"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4; + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_VELOCITY"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_COLOR"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_CUSTOM"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RESTART_POSITION"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RESTART_ROT_SCALE"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RESTART_VELOCITY"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RESTART_COLOR"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RESTART_CUSTOM"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLIDED"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLISION_NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLISION_DEPTH"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["ATTRACTOR_FORCE"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_PARTICLES].functions["process"].main_function = true; { ShaderLanguage::StageFunctionInfo emit_vertex_func; @@ -347,7 +353,7 @@ ShaderTypes::ShaderTypes() { emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("custom", ShaderLanguage::TYPE_VEC4)); emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("flags", ShaderLanguage::TYPE_UINT)); emit_vertex_func.return_type = ShaderLanguage::TYPE_BOOL; //whether it could emit - shader_modes[RS::SHADER_PARTICLES].functions["compute"].stage_functions["emit_subparticle"] = emit_vertex_func; + shader_modes[RS::SHADER_PARTICLES].functions["process"].stage_functions["emit_subparticle"] = emit_vertex_func; } shader_modes[RS::SHADER_PARTICLES].modes.push_back("collision_use_scale"); @@ -384,14 +390,15 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_SIZE"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3; - shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["EYEDIR"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["HALF_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["QUARTER_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["FOG"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["EYEDIR"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["HALF_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["QUARTER_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_SKY].functions["sky"].built_ins["FOG"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SKY].functions["sky"].main_function = true; shader_modes[RS::SHADER_SKY].modes.push_back("use_half_res_pass"); shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass"); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 809343114c..f8644b5ecb 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1706,7 +1706,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("instance_set_transform", "instance", "transform"), &RenderingServer::instance_set_transform); ClassDB::bind_method(D_METHOD("instance_attach_object_instance_id", "instance", "id"), &RenderingServer::instance_attach_object_instance_id); ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight); - ClassDB::bind_method(D_METHOD("instance_set_surface_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_material); + ClassDB::bind_method(D_METHOD("instance_set_surface_override_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_override_material); ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &RenderingServer::instance_set_visible); // ClassDB::bind_method(D_METHOD("instance_set_use_lightmap", "instance", "lightmap_instance", "lightmap"), &RenderingServer::instance_set_use_lightmap); ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &RenderingServer::instance_set_custom_aabb); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 6a8bb83ec1..694fae7fde 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1124,7 +1124,7 @@ public: virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0; virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; - virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0; + virtual void instance_set_surface_override_material(RID p_instance, int p_surface, RID p_material) = 0; virtual void instance_set_visible(RID p_instance, bool p_visible) = 0; virtual void instance_set_custom_aabb(RID p_instance, AABB aabb) = 0; diff --git a/tests/test_shader_lang.cpp b/tests/test_shader_lang.cpp index a023f35506..2169350c02 100644 --- a/tests/test_shader_lang.cpp +++ b/tests/test_shader_lang.cpp @@ -344,7 +344,7 @@ MainLoop *test() { Set<String> types; types.insert("spatial"); - Error err = sl.compile(code, dt, rm, types, nullptr); + Error err = sl.compile(code, dt, rm, ShaderLanguage::VaryingFunctionNames(), types, nullptr); if (err) { print_line("Error at line: " + rtos(sl.get_error_line()) + ": " + sl.get_error_text()); diff --git a/thirdparty/README.md b/thirdparty/README.md index cacc0275dd..dbdc568d64 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -89,15 +89,16 @@ will limit its functionality to IPv4 only. ## etcpak - Upstream: https://github.com/wolfpld/etcpak -- Version: git (403d38b3f1cb347c196d845d0a05e44a00d17169, 2021) +- Version: git (f27daea656ff77671580f838a889e33049430ebd, 2021) - License: BSD-3-Clause -Important: Some Godot-made changes, see `patches` folders. - Files extracted from upstream source: -- All `.cpp` and `.hpp` files in the root folder except `Application.cpp`. -- `lz4` folder. +- Only the files relevant for compression (i.e. `Process*.cpp` and their deps): + ``` + Dither.{cpp,hpp} ForceInline.hpp Math.hpp ProcessCommon.hpp ProcessRGB.{cpp,hpp} + ProcessDxtc.{cpp,hpp} Tables.{cpp,hpp} Vector.hpp + ``` - `AUTHORS.txt` and `LICENSE.txt` ## fonts diff --git a/thirdparty/etcpak/Bitmap.cpp b/thirdparty/etcpak/Bitmap.cpp deleted file mode 100644 index ef318318ac..0000000000 --- a/thirdparty/etcpak/Bitmap.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include <png.h> -#include "lz4/lz4.h" - -#include "Bitmap.hpp" -#include "Debug.hpp" - -Bitmap::Bitmap( const char* fn, unsigned int lines, bool bgr ) - : m_block( nullptr ) - , m_lines( lines ) - , m_alpha( true ) - , m_sema( 0 ) -{ - FILE* f = fopen( fn, "rb" ); - assert( f ); - - char buf[4]; - fread( buf, 1, 4, f ); - if( memcmp( buf, "raw4", 4 ) == 0 ) - { - uint8_t a; - fread( &a, 1, 1, f ); - m_alpha = a == 1; - uint32_t d; - fread( &d, 1, 4, f ); - m_size.x = d; - fread( &d, 1, 4, f ); - m_size.y = d; - DBGPRINT( "Raw bitmap " << fn << " " << m_size.x << "x" << m_size.y ); - - assert( m_size.x % 4 == 0 ); - assert( m_size.y % 4 == 0 ); - - int32_t csize; - fread( &csize, 1, 4, f ); - char* cbuf = new char[csize]; - fread( cbuf, 1, csize, f ); - fclose( f ); - - m_block = m_data = new uint32_t[m_size.x*m_size.y]; - m_linesLeft = m_size.y / 4; - - LZ4_decompress_fast( cbuf, (char*)m_data, m_size.x*m_size.y*4 ); - delete[] cbuf; - - for( int i=0; i<m_size.y/4; i++ ) - { - m_sema.unlock(); - } - } - else - { - fseek( f, 0, SEEK_SET ); - - unsigned int sig_read = 0; - int bit_depth, color_type, interlace_type; - - png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); - png_infop info_ptr = png_create_info_struct( png_ptr ); - setjmp( png_jmpbuf( png_ptr ) ); - - png_init_io( png_ptr, f ); - png_set_sig_bytes( png_ptr, sig_read ); - - png_uint_32 w, h; - - png_read_info( png_ptr, info_ptr ); - png_get_IHDR( png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, &interlace_type, NULL, NULL ); - - m_size = v2i( w, h ); - - png_set_strip_16( png_ptr ); - if( color_type == PNG_COLOR_TYPE_PALETTE ) - { - png_set_palette_to_rgb( png_ptr ); - } - else if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 ) - { - png_set_expand_gray_1_2_4_to_8( png_ptr ); - } - if( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) - { - png_set_tRNS_to_alpha( png_ptr ); - } - if( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) - { - png_set_gray_to_rgb(png_ptr); - } - if( bgr ) - { - png_set_bgr(png_ptr); - } - - switch( color_type ) - { - case PNG_COLOR_TYPE_PALETTE: - if( !png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) - { - png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER ); - m_alpha = false; - } - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - png_set_gray_to_rgb( png_ptr ); - break; - case PNG_COLOR_TYPE_RGB: - png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER ); - m_alpha = false; - break; - default: - break; - } - - DBGPRINT( "Bitmap " << fn << " " << w << "x" << h ); - - assert( w % 4 == 0 ); - assert( h % 4 == 0 ); - - m_block = m_data = new uint32_t[w*h]; - m_linesLeft = h / 4; - - m_load = std::async( std::launch::async, [this, f, png_ptr, info_ptr]() mutable - { - auto ptr = m_data; - unsigned int lines = 0; - for( int i=0; i<m_size.y / 4; i++ ) - { - for( int j=0; j<4; j++ ) - { - png_read_rows( png_ptr, (png_bytepp)&ptr, NULL, 1 ); - ptr += m_size.x; - } - lines++; - if( lines >= m_lines ) - { - lines = 0; - m_sema.unlock(); - } - } - - if( lines != 0 ) - { - m_sema.unlock(); - } - - png_read_end( png_ptr, info_ptr ); - png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); - fclose( f ); - } ); - } -} - -Bitmap::Bitmap( const v2i& size ) - : m_data( new uint32_t[size.x*size.y] ) - , m_block( nullptr ) - , m_lines( 1 ) - , m_linesLeft( size.y / 4 ) - , m_size( size ) - , m_sema( 0 ) -{ -} - -Bitmap::Bitmap( const Bitmap& src, unsigned int lines ) - : m_lines( lines ) - , m_alpha( src.Alpha() ) - , m_sema( 0 ) -{ -} - -Bitmap::~Bitmap() -{ - delete[] m_data; -} - -void Bitmap::Write( const char* fn ) -{ - FILE* f = fopen( fn, "wb" ); - assert( f ); - - png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); - png_infop info_ptr = png_create_info_struct( png_ptr ); - setjmp( png_jmpbuf( png_ptr ) ); - png_init_io( png_ptr, f ); - - png_set_IHDR( png_ptr, info_ptr, m_size.x, m_size.y, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE ); - - png_write_info( png_ptr, info_ptr ); - - uint32_t* ptr = m_data; - for( int i=0; i<m_size.y; i++ ) - { - png_write_rows( png_ptr, (png_bytepp)(&ptr), 1 ); - ptr += m_size.x; - } - - png_write_end( png_ptr, info_ptr ); - png_destroy_write_struct( &png_ptr, &info_ptr ); - - fclose( f ); -} - -const uint32_t* Bitmap::NextBlock( unsigned int& lines, bool& done ) -{ - std::lock_guard<std::mutex> lock( m_lock ); - lines = std::min( m_lines, m_linesLeft ); - auto ret = m_block; - m_sema.lock(); - m_block += m_size.x * 4 * lines; - m_linesLeft -= lines; - done = m_linesLeft == 0; - return ret; -} diff --git a/thirdparty/etcpak/Bitmap.hpp b/thirdparty/etcpak/Bitmap.hpp deleted file mode 100644 index fae8c936ed..0000000000 --- a/thirdparty/etcpak/Bitmap.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __DARKRL__BITMAP_HPP__ -#define __DARKRL__BITMAP_HPP__ - -#include <future> -#include <memory> -#include <mutex> -#include <stdint.h> - -#include "Semaphore.hpp" -#include "Vector.hpp" - -enum class Channels -{ - RGB, - Alpha -}; - -class Bitmap -{ -public: - Bitmap( const char* fn, unsigned int lines, bool bgr ); - Bitmap( const v2i& size ); - virtual ~Bitmap(); - - void Write( const char* fn ); - - uint32_t* Data() { if( m_load.valid() ) m_load.wait(); return m_data; } - const uint32_t* Data() const { if( m_load.valid() ) m_load.wait(); return m_data; } - const v2i& Size() const { return m_size; } - bool Alpha() const { return m_alpha; } - - const uint32_t* NextBlock( unsigned int& lines, bool& done ); - -protected: - Bitmap( const Bitmap& src, unsigned int lines ); - - uint32_t* m_data; - uint32_t* m_block; - unsigned int m_lines; - unsigned int m_linesLeft; - v2i m_size; - bool m_alpha; - Semaphore m_sema; - std::mutex m_lock; - std::future<void> m_load; -}; - -typedef std::shared_ptr<Bitmap> BitmapPtr; - -#endif diff --git a/thirdparty/etcpak/BitmapDownsampled.cpp b/thirdparty/etcpak/BitmapDownsampled.cpp deleted file mode 100644 index 0eb0d81185..0000000000 --- a/thirdparty/etcpak/BitmapDownsampled.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include <string.h> -#include <utility> - -#include "BitmapDownsampled.hpp" -#include "Debug.hpp" - -BitmapDownsampled::BitmapDownsampled( const Bitmap& bmp, unsigned int lines ) - : Bitmap( bmp, lines ) -{ - m_size.x = std::max( 1, bmp.Size().x / 2 ); - m_size.y = std::max( 1, bmp.Size().y / 2 ); - - int w = std::max( m_size.x, 4 ); - int h = std::max( m_size.y, 4 ); - - DBGPRINT( "Subbitmap " << m_size.x << "x" << m_size.y ); - - m_block = m_data = new uint32_t[w*h]; - - if( m_size.x < w || m_size.y < h ) - { - memset( m_data, 0, w*h*sizeof( uint32_t ) ); - m_linesLeft = h / 4; - unsigned int lines = 0; - for( int i=0; i<h/4; i++ ) - { - for( int j=0; j<4; j++ ) - { - lines++; - if( lines > m_lines ) - { - lines = 0; - m_sema.unlock(); - } - } - } - if( lines != 0 ) - { - m_sema.unlock(); - } - } - else - { - m_linesLeft = h / 4; - m_load = std::async( std::launch::async, [this, &bmp, w, h]() mutable - { - auto ptr = m_data; - auto src1 = bmp.Data(); - auto src2 = src1 + bmp.Size().x; - unsigned int lines = 0; - for( int i=0; i<h/4; i++ ) - { - for( int j=0; j<4; j++ ) - { - for( int k=0; k<m_size.x; k++ ) - { - int r = ( ( *src1 & 0x000000FF ) + ( *(src1+1) & 0x000000FF ) + ( *src2 & 0x000000FF ) + ( *(src2+1) & 0x000000FF ) ) / 4; - int g = ( ( ( *src1 & 0x0000FF00 ) + ( *(src1+1) & 0x0000FF00 ) + ( *src2 & 0x0000FF00 ) + ( *(src2+1) & 0x0000FF00 ) ) / 4 ) & 0x0000FF00; - int b = ( ( ( *src1 & 0x00FF0000 ) + ( *(src1+1) & 0x00FF0000 ) + ( *src2 & 0x00FF0000 ) + ( *(src2+1) & 0x00FF0000 ) ) / 4 ) & 0x00FF0000; - int a = ( ( ( ( ( *src1 & 0xFF000000 ) >> 8 ) + ( ( *(src1+1) & 0xFF000000 ) >> 8 ) + ( ( *src2 & 0xFF000000 ) >> 8 ) + ( ( *(src2+1) & 0xFF000000 ) >> 8 ) ) / 4 ) & 0x00FF0000 ) << 8; - *ptr++ = r | g | b | a; - src1 += 2; - src2 += 2; - } - src1 += m_size.x * 2; - src2 += m_size.x * 2; - } - lines++; - if( lines >= m_lines ) - { - lines = 0; - m_sema.unlock(); - } - } - - if( lines != 0 ) - { - m_sema.unlock(); - } - } ); - } -} - -BitmapDownsampled::~BitmapDownsampled() -{ -} diff --git a/thirdparty/etcpak/BitmapDownsampled.hpp b/thirdparty/etcpak/BitmapDownsampled.hpp deleted file mode 100644 index b7313808df..0000000000 --- a/thirdparty/etcpak/BitmapDownsampled.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __DARKRL__BITMAPDOWNSAMPLED_HPP__ -#define __DARKRL__BITMAPDOWNSAMPLED_HPP__ - -#include "Bitmap.hpp" - -class BitmapDownsampled : public Bitmap -{ -public: - BitmapDownsampled( const Bitmap& bmp, unsigned int lines ); - ~BitmapDownsampled(); -}; - -#endif diff --git a/thirdparty/etcpak/BlockData.cpp b/thirdparty/etcpak/BlockData.cpp deleted file mode 100644 index 4906e69492..0000000000 --- a/thirdparty/etcpak/BlockData.cpp +++ /dev/null @@ -1,1296 +0,0 @@ -#include <assert.h> -#include <string.h> - -#include "BlockData.hpp" -#include "ColorSpace.hpp" -#include "Debug.hpp" -#include "MipMap.hpp" -#include "mmap.hpp" -#include "ProcessRGB.hpp" -#include "ProcessDxtc.hpp" -#include "Tables.hpp" -#include "TaskDispatch.hpp" - -#ifdef __ARM_NEON -# include <arm_neon.h> -#endif - -#if defined __SSE4_1__ || defined __AVX2__ || defined _MSC_VER -# ifdef _MSC_VER -# include <intrin.h> -# include <Windows.h> -# define _bswap(x) _byteswap_ulong(x) -# define _bswap64(x) _byteswap_uint64(x) -# else -# include <x86intrin.h> -# endif -#endif - -#ifndef _bswap -# define _bswap(x) __builtin_bswap32(x) -# define _bswap64(x) __builtin_bswap64(x) -#endif - -static uint8_t table59T58H[8] = { 3,6,11,16,23,32,41,64 }; - -BlockData::BlockData( const char* fn ) - : m_file( fopen( fn, "rb" ) ) -{ - assert( m_file ); - fseek( m_file, 0, SEEK_END ); - m_maplen = ftell( m_file ); - fseek( m_file, 0, SEEK_SET ); - m_data = (uint8_t*)mmap( nullptr, m_maplen, PROT_READ, MAP_SHARED, fileno( m_file ), 0 ); - - auto data32 = (uint32_t*)m_data; - if( *data32 == 0x03525650 ) - { - // PVR - switch( *(data32+2) ) - { - case 6: - m_type = Etc1; - break; - case 7: - m_type = Dxt1; - break; - case 11: - m_type = Dxt5; - break; - case 22: - m_type = Etc2_RGB; - break; - case 23: - m_type = Etc2_RGBA; - break; - default: - assert( false ); - break; - } - - m_size.y = *(data32+6); - m_size.x = *(data32+7); - m_dataOffset = 52 + *(data32+12); - } - else if( *data32 == 0x58544BAB ) - { - // KTX - switch( *(data32+7) ) - { - case 0x9274: - m_type = Etc2_RGB; - break; - case 0x9278: - m_type = Etc2_RGBA; - break; - default: - assert( false ); - break; - } - - m_size.x = *(data32+9); - m_size.y = *(data32+10); - m_dataOffset = sizeof( uint32_t ) * 17 + *(data32+15); - } - else - { - assert( false ); - } -} - -static uint8_t* OpenForWriting( const char* fn, size_t len, const v2i& size, FILE** f, int levels, BlockData::Type type ) -{ - *f = fopen( fn, "wb+" ); - assert( *f ); - fseek( *f, len - 1, SEEK_SET ); - const char zero = 0; - fwrite( &zero, 1, 1, *f ); - fseek( *f, 0, SEEK_SET ); - - auto ret = (uint8_t*)mmap( nullptr, len, PROT_WRITE, MAP_SHARED, fileno( *f ), 0 ); - auto dst = (uint32_t*)ret; - - *dst++ = 0x03525650; // version - *dst++ = 0; // flags - switch( type ) // pixelformat[0] - { - case BlockData::Etc1: - *dst++ = 6; - break; - case BlockData::Etc2_RGB: - *dst++ = 22; - break; - case BlockData::Etc2_RGBA: - *dst++ = 23; - break; - case BlockData::Dxt1: - *dst++ = 7; - break; - case BlockData::Dxt5: - *dst++ = 11; - break; - default: - assert( false ); - break; - } - *dst++ = 0; // pixelformat[1] - *dst++ = 0; // colourspace - *dst++ = 0; // channel type - *dst++ = size.y; // height - *dst++ = size.x; // width - *dst++ = 1; // depth - *dst++ = 1; // num surfs - *dst++ = 1; // num faces - *dst++ = levels; // mipmap count - *dst++ = 0; // metadata size - - return ret; -} - -static int AdjustSizeForMipmaps( const v2i& size, int levels ) -{ - int len = 0; - v2i current = size; - for( int i=1; i<levels; i++ ) - { - assert( current.x != 1 || current.y != 1 ); - current.x = std::max( 1, current.x / 2 ); - current.y = std::max( 1, current.y / 2 ); - len += std::max( 4, current.x ) * std::max( 4, current.y ) / 2; - } - assert( current.x == 1 && current.y == 1 ); - return len; -} - -BlockData::BlockData( const char* fn, const v2i& size, bool mipmap, Type type ) - : m_size( size ) - , m_dataOffset( 52 ) - , m_maplen( m_size.x*m_size.y/2 ) - , m_type( type ) -{ - assert( m_size.x%4 == 0 && m_size.y%4 == 0 ); - - uint32_t cnt = m_size.x * m_size.y / 16; - DBGPRINT( cnt << " blocks" ); - - int levels = 1; - - if( mipmap ) - { - levels = NumberOfMipLevels( size ); - DBGPRINT( "Number of mipmaps: " << levels ); - m_maplen += AdjustSizeForMipmaps( size, levels ); - } - - if( type == Etc2_RGBA || type == Dxt5 ) m_maplen *= 2; - - m_maplen += m_dataOffset; - m_data = OpenForWriting( fn, m_maplen, m_size, &m_file, levels, type ); -} - -BlockData::BlockData( const v2i& size, bool mipmap, Type type ) - : m_size( size ) - , m_dataOffset( 52 ) - , m_file( nullptr ) - , m_maplen( m_size.x*m_size.y/2 ) - , m_type( type ) -{ - assert( m_size.x%4 == 0 && m_size.y%4 == 0 ); - if( mipmap ) - { - const int levels = NumberOfMipLevels( size ); - m_maplen += AdjustSizeForMipmaps( size, levels ); - } - - if( type == Etc2_RGBA || type == Dxt5 ) m_maplen *= 2; - - m_maplen += m_dataOffset; - m_data = new uint8_t[m_maplen]; -} - -BlockData::~BlockData() -{ - if( m_file ) - { - munmap( m_data, m_maplen ); - fclose( m_file ); - } - else - { - delete[] m_data; - } -} - -void BlockData::Process( const uint32_t* src, uint32_t blocks, size_t offset, size_t width, Channels type, bool dither ) -{ - auto dst = ((uint64_t*)( m_data + m_dataOffset )) + offset; - - if( type == Channels::Alpha ) - { - if( m_type != Etc1 ) - { - CompressEtc2Alpha( src, dst, blocks, width ); - } - else - { - CompressEtc1Alpha( src, dst, blocks, width ); - } - } - else - { - switch( m_type ) - { - case Etc1: - if( dither ) - { - CompressEtc1RgbDither( src, dst, blocks, width ); - } - else - { - CompressEtc1Rgb( src, dst, blocks, width ); - } - break; - case Etc2_RGB: - CompressEtc2Rgb( src, dst, blocks, width ); - break; - case Dxt1: - if( dither ) - { - CompressDxt1Dither( src, dst, blocks, width ); - } - else - { - CompressDxt1( src, dst, blocks, width ); - } - break; - default: - assert( false ); - break; - } - } -} - -void BlockData::ProcessRGBA( const uint32_t* src, uint32_t blocks, size_t offset, size_t width ) -{ - auto dst = ((uint64_t*)( m_data + m_dataOffset )) + offset * 2; - - switch( m_type ) - { - case Etc2_RGBA: - CompressEtc2Rgba( src, dst, blocks, width ); - break; - case Dxt5: - CompressDxt5( src, dst, blocks, width ); - break; - default: - assert( false ); - break; - } -} - -namespace -{ - -static etcpak_force_inline int32_t expand6(uint32_t value) -{ - return (value << 2) | (value >> 4); -} - -static etcpak_force_inline int32_t expand7(uint32_t value) -{ - return (value << 1) | (value >> 6); -} - -static etcpak_force_inline void DecodeT( uint64_t block, uint32_t* dst, uint32_t w ) -{ - const auto r0 = ( block >> 24 ) & 0x1B; - const auto rh0 = ( r0 >> 3 ) & 0x3; - const auto rl0 = r0 & 0x3; - const auto g0 = ( block >> 20 ) & 0xF; - const auto b0 = ( block >> 16 ) & 0xF; - - const auto r1 = ( block >> 12 ) & 0xF; - const auto g1 = ( block >> 8 ) & 0xF; - const auto b1 = ( block >> 4 ) & 0xF; - - const auto cr0 = ( ( rh0 << 6 ) | ( rl0 << 4 ) | ( rh0 << 2 ) | rl0); - const auto cg0 = ( g0 << 4 ) | g0; - const auto cb0 = ( b0 << 4 ) | b0; - - const auto cr1 = ( r1 << 4 ) | r1; - const auto cg1 = ( g1 << 4 ) | g1; - const auto cb1 = ( b1 << 4 ) | b1; - - const auto codeword_hi = ( block >> 2 ) & 0x3; - const auto codeword_lo = block & 0x1; - const auto codeword = ( codeword_hi << 1 ) | codeword_lo; - - const auto c2r = clampu8( cr1 + table59T58H[codeword] ); - const auto c2g = clampu8( cg1 + table59T58H[codeword] ); - const auto c2b = clampu8( cb1 + table59T58H[codeword] ); - - const auto c3r = clampu8( cr1 - table59T58H[codeword] ); - const auto c3g = clampu8( cg1 - table59T58H[codeword] ); - const auto c3b = clampu8( cb1 - table59T58H[codeword] ); - - const uint32_t col_tab[4] = { - uint32_t(cr0 | ( cg0 << 8 ) | ( cb0 << 16 ) | 0xFF000000), - uint32_t(c2r | ( c2g << 8 ) | ( c2b << 16 ) | 0xFF000000), - uint32_t(cr1 | ( cg1 << 8 ) | ( cb1 << 16 ) | 0xFF000000), - uint32_t(c3r | ( c3g << 8 ) | ( c3b << 16 ) | 0xFF000000) - }; - - const uint32_t indexes = ( block >> 32 ) & 0xFFFFFFFF; - for( uint8_t j = 0; j < 4; j++ ) - { - for( uint8_t i = 0; i < 4; i++ ) - { - //2bit indices distributed on two lane 16bit numbers - const uint8_t index = ( ( ( indexes >> ( j + i * 4 + 16 ) ) & 0x1 ) << 1) | ( ( indexes >> ( j + i * 4 ) ) & 0x1); - dst[j * w + i] = col_tab[index]; - } - } -} - -static etcpak_force_inline void DecodeTAlpha( uint64_t block, uint64_t alpha, uint32_t* dst, uint32_t w ) -{ - const auto r0 = ( block >> 24 ) & 0x1B; - const auto rh0 = ( r0 >> 3 ) & 0x3; - const auto rl0 = r0 & 0x3; - const auto g0 = ( block >> 20 ) & 0xF; - const auto b0 = ( block >> 16 ) & 0xF; - - const auto r1 = ( block >> 12 ) & 0xF; - const auto g1 = ( block >> 8 ) & 0xF; - const auto b1 = ( block >> 4 ) & 0xF; - - const auto cr0 = ( ( rh0 << 6 ) | ( rl0 << 4 ) | ( rh0 << 2 ) | rl0); - const auto cg0 = ( g0 << 4 ) | g0; - const auto cb0 = ( b0 << 4 ) | b0; - - const auto cr1 = ( r1 << 4 ) | r1; - const auto cg1 = ( g1 << 4 ) | g1; - const auto cb1 = ( b1 << 4 ) | b1; - - const auto codeword_hi = ( block >> 2 ) & 0x3; - const auto codeword_lo = block & 0x1; - const auto codeword = (codeword_hi << 1) | codeword_lo; - - const int32_t base = alpha >> 56; - const int32_t mul = ( alpha >> 52 ) & 0xF; - const auto tbl = g_alpha[( alpha >> 48 ) & 0xF]; - - const auto c2r = clampu8( cr1 + table59T58H[codeword] ); - const auto c2g = clampu8( cg1 + table59T58H[codeword] ); - const auto c2b = clampu8( cb1 + table59T58H[codeword] ); - - const auto c3r = clampu8( cr1 - table59T58H[codeword] ); - const auto c3g = clampu8( cg1 - table59T58H[codeword] ); - const auto c3b = clampu8( cb1 - table59T58H[codeword] ); - - const uint32_t col_tab[4] = { - uint32_t(cr0 | ( cg0 << 8 ) | ( cb0 << 16 )), - uint32_t(c2r | ( c2g << 8 ) | ( c2b << 16 )), - uint32_t(cr1 | ( cg1 << 8 ) | ( cb1 << 16 )), - uint32_t(c3r | ( c3g << 8 ) | ( c3b << 16 )) - }; - - const uint32_t indexes = ( block >> 32 ) & 0xFFFFFFFF; - for( uint8_t j = 0; j < 4; j++ ) - { - for( uint8_t i = 0; i < 4; i++ ) - { - //2bit indices distributed on two lane 16bit numbers - const uint8_t index = ( ( ( indexes >> ( j + i * 4 + 16 ) ) & 0x1 ) << 1 ) | ( ( indexes >> ( j + i * 4 ) ) & 0x1 ); - const auto amod = tbl[( alpha >> ( 45 - j * 3 - i * 12 ) ) & 0x7]; - const uint32_t a = clampu8( base + amod * mul ); - dst[j * w + i] = col_tab[index] | ( a << 24 ); - } - } -} - -static etcpak_force_inline void DecodeH( uint64_t block, uint32_t* dst, uint32_t w ) -{ - const uint32_t indexes = ( block >> 32 ) & 0xFFFFFFFF; - - const auto r0444 = ( block >> 27 ) & 0xF; - const auto g0444 = ( ( block >> 20 ) & 0x1 ) | ( ( ( block >> 24 ) & 0x7 ) << 1 ); - const auto b0444 = ( ( block >> 15 ) & 0x7 ) | ( ( ( block >> 19 ) & 0x1 ) << 3 ); - - const auto r1444 = ( block >> 11 ) & 0xF; - const auto g1444 = ( block >> 7 ) & 0xF; - const auto b1444 = ( block >> 3 ) & 0xF; - - const auto r0 = ( r0444 << 4 ) | r0444; - const auto g0 = ( g0444 << 4 ) | g0444; - const auto b0 = ( b0444 << 4 ) | b0444; - - const auto r1 = ( r1444 << 4 ) | r1444; - const auto g1 = ( g1444 << 4 ) | g1444; - const auto b1 = ( b1444 << 4 ) | b1444; - - const auto codeword_hi = ( ( block & 0x1 ) << 1 ) | ( ( block & 0x4 ) ); - const auto c0 = ( r0444 << 8 ) | ( g0444 << 4 ) | ( b0444 << 0 ); - const auto c1 = ( block >> 3 ) & ( ( 1 << 12 ) - 1 ); - const auto codeword_lo = ( c0 >= c1 ) ? 1 : 0; - const auto codeword = codeword_hi | codeword_lo; - - const uint32_t col_tab[] = { - uint32_t(clampu8( r0 + table59T58H[codeword] ) | ( clampu8( g0 + table59T58H[codeword] ) << 8 ) | ( clampu8( b0 + table59T58H[codeword] ) << 16 )), - uint32_t(clampu8( r0 - table59T58H[codeword] ) | ( clampu8( g0 - table59T58H[codeword] ) << 8 ) | ( clampu8( b0 - table59T58H[codeword] ) << 16 )), - uint32_t(clampu8( r1 + table59T58H[codeword] ) | ( clampu8( g1 + table59T58H[codeword] ) << 8 ) | ( clampu8( b1 + table59T58H[codeword] ) << 16 )), - uint32_t(clampu8( r1 - table59T58H[codeword] ) | ( clampu8( g1 - table59T58H[codeword] ) << 8 ) | ( clampu8( b1 - table59T58H[codeword] ) << 16 )) - }; - - for( uint8_t j = 0; j < 4; j++ ) - { - for( uint8_t i = 0; i < 4; i++ ) - { - const uint8_t index = ( ( ( indexes >> ( j + i * 4 + 16 ) ) & 0x1 ) << 1 ) | ( ( indexes >> ( j + i * 4 ) ) & 0x1 ); - dst[j * w + i] = col_tab[index] | 0xFF000000; - } - } -} - -static etcpak_force_inline void DecodeHAlpha( uint64_t block, uint64_t alpha, uint32_t* dst, uint32_t w ) -{ - const uint32_t indexes = ( block >> 32 ) & 0xFFFFFFFF; - - const auto r0444 = ( block >> 27 ) & 0xF; - const auto g0444 = ( ( block >> 20 ) & 0x1 ) | ( ( ( block >> 24 ) & 0x7 ) << 1 ); - const auto b0444 = ( ( block >> 15 ) & 0x7 ) | ( ( ( block >> 19 ) & 0x1 ) << 3 ); - - const auto r1444 = ( block >> 11 ) & 0xF; - const auto g1444 = ( block >> 7 ) & 0xF; - const auto b1444 = ( block >> 3 ) & 0xF; - - const auto r0 = ( r0444 << 4 ) | r0444; - const auto g0 = ( g0444 << 4 ) | g0444; - const auto b0 = ( b0444 << 4 ) | b0444; - - const auto r1 = ( r1444 << 4 ) | r1444; - const auto g1 = ( g1444 << 4 ) | g1444; - const auto b1 = ( b1444 << 4 ) | b1444; - - const auto codeword_hi = ( ( block & 0x1 ) << 1 ) | ( ( block & 0x4 ) ); - const auto c0 = ( r0444 << 8 ) | ( g0444 << 4 ) | ( b0444 << 0 ); - const auto c1 = ( block >> 3 ) & ( ( 1 << 12 ) - 1 ); - const auto codeword_lo = ( c0 >= c1 ) ? 1 : 0; - const auto codeword = codeword_hi | codeword_lo; - - const int32_t base = alpha >> 56; - const int32_t mul = ( alpha >> 52 ) & 0xF; - const auto tbl = g_alpha[(alpha >> 48) & 0xF]; - - const uint32_t col_tab[] = { - uint32_t(clampu8( r0 + table59T58H[codeword] ) | ( clampu8( g0 + table59T58H[codeword] ) << 8 ) | ( clampu8( b0 + table59T58H[codeword] ) << 16 )), - uint32_t(clampu8( r0 - table59T58H[codeword] ) | ( clampu8( g0 - table59T58H[codeword] ) << 8 ) | ( clampu8( b0 - table59T58H[codeword] ) << 16 )), - uint32_t(clampu8( r1 + table59T58H[codeword] ) | ( clampu8( g1 + table59T58H[codeword] ) << 8 ) | ( clampu8( b1 + table59T58H[codeword] ) << 16 )), - uint32_t(clampu8( r1 - table59T58H[codeword] ) | ( clampu8( g1 - table59T58H[codeword] ) << 8 ) | ( clampu8( b1 - table59T58H[codeword] ) << 16 )) - }; - - for( uint8_t j = 0; j < 4; j++ ) - { - for( uint8_t i = 0; i < 4; i++ ) - { - const uint8_t index = ( ( ( indexes >> ( j + i * 4 + 16 ) ) & 0x1 ) << 1 ) | ( ( indexes >> ( j + i * 4 ) ) & 0x1 ); - const auto amod = tbl[( alpha >> ( 45 - j * 3 - i * 12) ) & 0x7]; - const uint32_t a = clampu8( base + amod * mul ); - dst[j * w + i] = col_tab[index] | ( a << 24 ); - } - } -} - -static etcpak_force_inline void DecodePlanar( uint64_t block, uint32_t* dst, uint32_t w ) -{ - const auto bv = expand6((block >> ( 0 + 32)) & 0x3F); - const auto gv = expand7((block >> ( 6 + 32)) & 0x7F); - const auto rv = expand6((block >> (13 + 32)) & 0x3F); - - const auto bh = expand6((block >> (19 + 32)) & 0x3F); - const auto gh = expand7((block >> (25 + 32)) & 0x7F); - - const auto rh0 = (block >> (32 - 32)) & 0x01; - const auto rh1 = ((block >> (34 - 32)) & 0x1F) << 1; - const auto rh = expand6(rh0 | rh1); - - const auto bo0 = (block >> (39 - 32)) & 0x07; - const auto bo1 = ((block >> (43 - 32)) & 0x3) << 3; - const auto bo2 = ((block >> (48 - 32)) & 0x1) << 5; - const auto bo = expand6(bo0 | bo1 | bo2); - const auto go0 = (block >> (49 - 32)) & 0x3F; - const auto go1 = ((block >> (56 - 32)) & 0x01) << 6; - const auto go = expand7(go0 | go1); - const auto ro = expand6((block >> (57 - 32)) & 0x3F); - -#ifdef __ARM_NEON - uint64_t init = uint64_t(uint16_t(rh-ro)) | ( uint64_t(uint16_t(gh-go)) << 16 ) | ( uint64_t(uint16_t(bh-bo)) << 32 ); - int16x8_t chco = vreinterpretq_s16_u64( vdupq_n_u64( init ) ); - init = uint64_t(uint16_t( (rv-ro) - 4 * (rh-ro) )) | ( uint64_t(uint16_t( (gv-go) - 4 * (gh-go) )) << 16 ) | ( uint64_t(uint16_t( (bv-bo) - 4 * (bh-bo) )) << 32 ); - int16x8_t cvco = vreinterpretq_s16_u64( vdupq_n_u64( init ) ); - init = uint64_t(4*ro+2) | ( uint64_t(4*go+2) << 16 ) | ( uint64_t(4*bo+2) << 32 ) | ( uint64_t(0xFFF) << 48 ); - int16x8_t col = vreinterpretq_s16_u64( vdupq_n_u64( init ) ); - - for( int j=0; j<4; j++ ) - { - for( int i=0; i<4; i++ ) - { - uint8x8_t c = vqshrun_n_s16( col, 2 ); - vst1_lane_u32( dst+j*w+i, vreinterpret_u32_u8( c ), 0 ); - col = vaddq_s16( col, chco ); - } - col = vaddq_s16( col, cvco ); - } -#elif defined __AVX2__ - const auto R0 = 4*ro+2; - const auto G0 = 4*go+2; - const auto B0 = 4*bo+2; - const auto RHO = rh-ro; - const auto GHO = gh-go; - const auto BHO = bh-bo; - - __m256i cvco = _mm256_setr_epi16( rv - ro, gv - go, bv - bo, 0, rv - ro, gv - go, bv - bo, 0, rv - ro, gv - go, bv - bo, 0, rv - ro, gv - go, bv - bo, 0 ); - __m256i col = _mm256_setr_epi16( R0, G0, B0, 0xFFF, R0+RHO, G0+GHO, B0+BHO, 0xFFF, R0+2*RHO, G0+2*GHO, B0+2*BHO, 0xFFF, R0+3*RHO, G0+3*GHO, B0+3*BHO, 0xFFF ); - - for( int j=0; j<4; j++ ) - { - __m256i c = _mm256_srai_epi16( col, 2 ); - __m128i s = _mm_packus_epi16( _mm256_castsi256_si128( c ), _mm256_extracti128_si256( c, 1 ) ); - _mm_storeu_si128( (__m128i*)(dst+j*w), s ); - col = _mm256_add_epi16( col, cvco ); - } -#elif defined __SSE4_1__ - __m128i chco = _mm_setr_epi16( rh - ro, gh - go, bh - bo, 0, 0, 0, 0, 0 ); - __m128i cvco = _mm_setr_epi16( (rv - ro) - 4 * (rh - ro), (gv - go) - 4 * (gh - go), (bv - bo) - 4 * (bh - bo), 0, 0, 0, 0, 0 ); - __m128i col = _mm_setr_epi16( 4*ro+2, 4*go+2, 4*bo+2, 0xFFF, 0, 0, 0, 0 ); - - for( int j=0; j<4; j++ ) - { - for( int i=0; i<4; i++ ) - { - __m128i c = _mm_srai_epi16( col, 2 ); - __m128i s = _mm_packus_epi16( c, c ); - dst[j*w+i] = _mm_cvtsi128_si32( s ); - col = _mm_add_epi16( col, chco ); - } - col = _mm_add_epi16( col, cvco ); - } -#else - for( int j=0; j<4; j++ ) - { - for( int i=0; i<4; i++ ) - { - const uint32_t r = (i * (rh - ro) + j * (rv - ro) + 4 * ro + 2) >> 2; - const uint32_t g = (i * (gh - go) + j * (gv - go) + 4 * go + 2) >> 2; - const uint32_t b = (i * (bh - bo) + j * (bv - bo) + 4 * bo + 2) >> 2; - if( ( ( r | g | b ) & ~0xFF ) == 0 ) - { - dst[j*w+i] = r | ( g << 8 ) | ( b << 16 ) | 0xFF000000; - } - else - { - const auto rc = clampu8( r ); - const auto gc = clampu8( g ); - const auto bc = clampu8( b ); - dst[j*w+i] = rc | ( gc << 8 ) | ( bc << 16 ) | 0xFF000000; - } - } - } -#endif -} - -static etcpak_force_inline void DecodePlanarAlpha( uint64_t block, uint64_t alpha, uint32_t* dst, uint32_t w ) -{ - const auto bv = expand6((block >> ( 0 + 32)) & 0x3F); - const auto gv = expand7((block >> ( 6 + 32)) & 0x7F); - const auto rv = expand6((block >> (13 + 32)) & 0x3F); - - const auto bh = expand6((block >> (19 + 32)) & 0x3F); - const auto gh = expand7((block >> (25 + 32)) & 0x7F); - - const auto rh0 = (block >> (32 - 32)) & 0x01; - const auto rh1 = ((block >> (34 - 32)) & 0x1F) << 1; - const auto rh = expand6(rh0 | rh1); - - const auto bo0 = (block >> (39 - 32)) & 0x07; - const auto bo1 = ((block >> (43 - 32)) & 0x3) << 3; - const auto bo2 = ((block >> (48 - 32)) & 0x1) << 5; - const auto bo = expand6(bo0 | bo1 | bo2); - const auto go0 = (block >> (49 - 32)) & 0x3F; - const auto go1 = ((block >> (56 - 32)) & 0x01) << 6; - const auto go = expand7(go0 | go1); - const auto ro = expand6((block >> (57 - 32)) & 0x3F); - - const int32_t base = alpha >> 56; - const int32_t mul = ( alpha >> 52 ) & 0xF; - const auto tbl = g_alpha[( alpha >> 48 ) & 0xF]; - -#ifdef __ARM_NEON - uint64_t init = uint64_t(uint16_t(rh-ro)) | ( uint64_t(uint16_t(gh-go)) << 16 ) | ( uint64_t(uint16_t(bh-bo)) << 32 ); - int16x8_t chco = vreinterpretq_s16_u64( vdupq_n_u64( init ) ); - init = uint64_t(uint16_t( (rv-ro) - 4 * (rh-ro) )) | ( uint64_t(uint16_t( (gv-go) - 4 * (gh-go) )) << 16 ) | ( uint64_t(uint16_t( (bv-bo) - 4 * (bh-bo) )) << 32 ); - int16x8_t cvco = vreinterpretq_s16_u64( vdupq_n_u64( init ) ); - init = uint64_t(4*ro+2) | ( uint64_t(4*go+2) << 16 ) | ( uint64_t(4*bo+2) << 32 ); - int16x8_t col = vreinterpretq_s16_u64( vdupq_n_u64( init ) ); - - for( int j=0; j<4; j++ ) - { - for( int i=0; i<4; i++ ) - { - const auto amod = tbl[(alpha >> ( 45 - j*3 - i*12 )) & 0x7]; - const uint32_t a = clampu8( base + amod * mul ); - uint8x8_t c = vqshrun_n_s16( col, 2 ); - dst[j*w+i] = vget_lane_u32( vreinterpret_u32_u8( c ), 0 ) | ( a << 24 ); - col = vaddq_s16( col, chco ); - } - col = vaddq_s16( col, cvco ); - } -#elif defined __SSE4_1__ - __m128i chco = _mm_setr_epi16( rh - ro, gh - go, bh - bo, 0, 0, 0, 0, 0 ); - __m128i cvco = _mm_setr_epi16( (rv - ro) - 4 * (rh - ro), (gv - go) - 4 * (gh - go), (bv - bo) - 4 * (bh - bo), 0, 0, 0, 0, 0 ); - __m128i col = _mm_setr_epi16( 4*ro+2, 4*go+2, 4*bo+2, 0, 0, 0, 0, 0 ); - - for( int j=0; j<4; j++ ) - { - for( int i=0; i<4; i++ ) - { - const auto amod = tbl[(alpha >> ( 45 - j*3 - i*12 )) & 0x7]; - const uint32_t a = clampu8( base + amod * mul ); - __m128i c = _mm_srai_epi16( col, 2 ); - __m128i s = _mm_packus_epi16( c, c ); - dst[j*w+i] = _mm_cvtsi128_si32( s ) | ( a << 24 ); - col = _mm_add_epi16( col, chco ); - } - col = _mm_add_epi16( col, cvco ); - } -#else - for (auto j = 0; j < 4; j++) - { - for (auto i = 0; i < 4; i++) - { - const uint32_t r = (i * (rh - ro) + j * (rv - ro) + 4 * ro + 2) >> 2; - const uint32_t g = (i * (gh - go) + j * (gv - go) + 4 * go + 2) >> 2; - const uint32_t b = (i * (bh - bo) + j * (bv - bo) + 4 * bo + 2) >> 2; - const auto amod = tbl[(alpha >> ( 45 - j*3 - i*12 )) & 0x7]; - const uint32_t a = clampu8( base + amod * mul ); - if( ( ( r | g | b ) & ~0xFF ) == 0 ) - { - dst[j*w+i] = r | ( g << 8 ) | ( b << 16 ) | ( a << 24 ); - } - else - { - const auto rc = clampu8( r ); - const auto gc = clampu8( g ); - const auto bc = clampu8( b ); - dst[j*w+i] = rc | ( gc << 8 ) | ( bc << 16 ) | ( a << 24 ); - } - } - } -#endif -} - -} - -BitmapPtr BlockData::Decode() -{ - switch( m_type ) - { - case Etc1: - case Etc2_RGB: - return DecodeRGB(); - case Etc2_RGBA: - return DecodeRGBA(); - case Dxt1: - return DecodeDxt1(); - case Dxt5: - return DecodeDxt5(); - default: - assert( false ); - return nullptr; - } -} - -static etcpak_force_inline uint64_t ConvertByteOrder( uint64_t d ) -{ - uint32_t word[2]; - memcpy( word, &d, 8 ); - word[0] = _bswap( word[0] ); - word[1] = _bswap( word[1] ); - memcpy( &d, word, 8 ); - return d; -} - -static etcpak_force_inline void DecodeRGBPart( uint64_t d, uint32_t* dst, uint32_t w ) -{ - d = ConvertByteOrder( d ); - - uint32_t br[2], bg[2], bb[2]; - - if( d & 0x2 ) - { - int32_t dr, dg, db; - - uint32_t r0 = ( d & 0xF8000000 ) >> 27; - uint32_t g0 = ( d & 0x00F80000 ) >> 19; - uint32_t b0 = ( d & 0x0000F800 ) >> 11; - - dr = ( int32_t(d) << 5 ) >> 29; - dg = ( int32_t(d) << 13 ) >> 29; - db = ( int32_t(d) << 21 ) >> 29; - - int32_t r1 = int32_t(r0) + dr; - int32_t g1 = int32_t(g0) + dg; - int32_t b1 = int32_t(b0) + db; - - // T mode - if ( (r1 < 0) || (r1 > 31) ) - { - DecodeT( d, dst, w ); - return; - } - - // H mode - if ((g1 < 0) || (g1 > 31)) - { - DecodeH( d, dst, w ); - return; - } - - // P mode - if( (b1 < 0) || (b1 > 31) ) - { - DecodePlanar( d, dst, w ); - return; - } - - br[0] = ( r0 << 3 ) | ( r0 >> 2 ); - br[1] = ( r1 << 3 ) | ( r1 >> 2 ); - bg[0] = ( g0 << 3 ) | ( g0 >> 2 ); - bg[1] = ( g1 << 3 ) | ( g1 >> 2 ); - bb[0] = ( b0 << 3 ) | ( b0 >> 2 ); - bb[1] = ( b1 << 3 ) | ( b1 >> 2 ); - } - else - { - br[0] = ( ( d & 0xF0000000 ) >> 24 ) | ( ( d & 0xF0000000 ) >> 28 ); - br[1] = ( ( d & 0x0F000000 ) >> 20 ) | ( ( d & 0x0F000000 ) >> 24 ); - bg[0] = ( ( d & 0x00F00000 ) >> 16 ) | ( ( d & 0x00F00000 ) >> 20 ); - bg[1] = ( ( d & 0x000F0000 ) >> 12 ) | ( ( d & 0x000F0000 ) >> 16 ); - bb[0] = ( ( d & 0x0000F000 ) >> 8 ) | ( ( d & 0x0000F000 ) >> 12 ); - bb[1] = ( ( d & 0x00000F00 ) >> 4 ) | ( ( d & 0x00000F00 ) >> 8 ); - } - - unsigned int tcw[2]; - tcw[0] = ( d & 0xE0 ) >> 5; - tcw[1] = ( d & 0x1C ) >> 2; - - uint32_t b1 = ( d >> 32 ) & 0xFFFF; - uint32_t b2 = ( d >> 48 ); - - b1 = ( b1 | ( b1 << 8 ) ) & 0x00FF00FF; - b1 = ( b1 | ( b1 << 4 ) ) & 0x0F0F0F0F; - b1 = ( b1 | ( b1 << 2 ) ) & 0x33333333; - b1 = ( b1 | ( b1 << 1 ) ) & 0x55555555; - - b2 = ( b2 | ( b2 << 8 ) ) & 0x00FF00FF; - b2 = ( b2 | ( b2 << 4 ) ) & 0x0F0F0F0F; - b2 = ( b2 | ( b2 << 2 ) ) & 0x33333333; - b2 = ( b2 | ( b2 << 1 ) ) & 0x55555555; - - uint32_t idx = b1 | ( b2 << 1 ); - - if( d & 0x1 ) - { - for( int i=0; i<4; i++ ) - { - for( int j=0; j<4; j++ ) - { - const auto mod = g_table[tcw[j/2]][idx & 0x3]; - const auto r = br[j/2] + mod; - const auto g = bg[j/2] + mod; - const auto b = bb[j/2] + mod; - if( ( ( r | g | b ) & ~0xFF ) == 0 ) - { - dst[j*w+i] = r | ( g << 8 ) | ( b << 16 ) | 0xFF000000; - } - else - { - const auto rc = clampu8( r ); - const auto gc = clampu8( g ); - const auto bc = clampu8( b ); - dst[j*w+i] = rc | ( gc << 8 ) | ( bc << 16 ) | 0xFF000000; - } - idx >>= 2; - } - } - } - else - { - for( int i=0; i<4; i++ ) - { - const auto tbl = g_table[tcw[i/2]]; - const auto cr = br[i/2]; - const auto cg = bg[i/2]; - const auto cb = bb[i/2]; - - for( int j=0; j<4; j++ ) - { - const auto mod = tbl[idx & 0x3]; - const auto r = cr + mod; - const auto g = cg + mod; - const auto b = cb + mod; - if( ( ( r | g | b ) & ~0xFF ) == 0 ) - { - dst[j*w+i] = r | ( g << 8 ) | ( b << 16 ) | 0xFF000000; - } - else - { - const auto rc = clampu8( r ); - const auto gc = clampu8( g ); - const auto bc = clampu8( b ); - dst[j*w+i] = rc | ( gc << 8 ) | ( bc << 16 ) | 0xFF000000; - } - idx >>= 2; - } - } - } -} - -static etcpak_force_inline void DecodeRGBAPart( uint64_t d, uint64_t alpha, uint32_t* dst, uint32_t w ) -{ - d = ConvertByteOrder( d ); - alpha = _bswap64( alpha ); - - uint32_t br[2], bg[2], bb[2]; - - if( d & 0x2 ) - { - int32_t dr, dg, db; - - uint32_t r0 = ( d & 0xF8000000 ) >> 27; - uint32_t g0 = ( d & 0x00F80000 ) >> 19; - uint32_t b0 = ( d & 0x0000F800 ) >> 11; - - dr = ( int32_t(d) << 5 ) >> 29; - dg = ( int32_t(d) << 13 ) >> 29; - db = ( int32_t(d) << 21 ) >> 29; - - int32_t r1 = int32_t(r0) + dr; - int32_t g1 = int32_t(g0) + dg; - int32_t b1 = int32_t(b0) + db; - - // T mode - if ( (r1 < 0) || (r1 > 31) ) - { - DecodeTAlpha( d, alpha, dst, w ); - return; - } - - // H mode - if ( (g1 < 0) || (g1 > 31) ) - { - DecodeHAlpha( d, alpha, dst, w ); - return; - } - - // P mode - if ( (b1 < 0) || (b1 > 31) ) - { - DecodePlanarAlpha( d, alpha, dst, w ); - return; - } - - br[0] = ( r0 << 3 ) | ( r0 >> 2 ); - br[1] = ( r1 << 3 ) | ( r1 >> 2 ); - bg[0] = ( g0 << 3 ) | ( g0 >> 2 ); - bg[1] = ( g1 << 3 ) | ( g1 >> 2 ); - bb[0] = ( b0 << 3 ) | ( b0 >> 2 ); - bb[1] = ( b1 << 3 ) | ( b1 >> 2 ); - } - else - { - br[0] = ( ( d & 0xF0000000 ) >> 24 ) | ( ( d & 0xF0000000 ) >> 28 ); - br[1] = ( ( d & 0x0F000000 ) >> 20 ) | ( ( d & 0x0F000000 ) >> 24 ); - bg[0] = ( ( d & 0x00F00000 ) >> 16 ) | ( ( d & 0x00F00000 ) >> 20 ); - bg[1] = ( ( d & 0x000F0000 ) >> 12 ) | ( ( d & 0x000F0000 ) >> 16 ); - bb[0] = ( ( d & 0x0000F000 ) >> 8 ) | ( ( d & 0x0000F000 ) >> 12 ); - bb[1] = ( ( d & 0x00000F00 ) >> 4 ) | ( ( d & 0x00000F00 ) >> 8 ); - } - - unsigned int tcw[2]; - tcw[0] = ( d & 0xE0 ) >> 5; - tcw[1] = ( d & 0x1C ) >> 2; - - uint32_t b1 = ( d >> 32 ) & 0xFFFF; - uint32_t b2 = ( d >> 48 ); - - b1 = ( b1 | ( b1 << 8 ) ) & 0x00FF00FF; - b1 = ( b1 | ( b1 << 4 ) ) & 0x0F0F0F0F; - b1 = ( b1 | ( b1 << 2 ) ) & 0x33333333; - b1 = ( b1 | ( b1 << 1 ) ) & 0x55555555; - - b2 = ( b2 | ( b2 << 8 ) ) & 0x00FF00FF; - b2 = ( b2 | ( b2 << 4 ) ) & 0x0F0F0F0F; - b2 = ( b2 | ( b2 << 2 ) ) & 0x33333333; - b2 = ( b2 | ( b2 << 1 ) ) & 0x55555555; - - uint32_t idx = b1 | ( b2 << 1 ); - - const int32_t base = alpha >> 56; - const int32_t mul = ( alpha >> 52 ) & 0xF; - const auto atbl = g_alpha[( alpha >> 48 ) & 0xF]; - - if( d & 0x1 ) - { - for( int i=0; i<4; i++ ) - { - for( int j=0; j<4; j++ ) - { - const auto mod = g_table[tcw[j/2]][idx & 0x3]; - const auto r = br[j/2] + mod; - const auto g = bg[j/2] + mod; - const auto b = bb[j/2] + mod; - const auto amod = atbl[(alpha >> ( 45 - j*3 - i*12 )) & 0x7]; - const uint32_t a = clampu8( base + amod * mul ); - if( ( ( r | g | b ) & ~0xFF ) == 0 ) - { - dst[j*w+i] = r | ( g << 8 ) | ( b << 16 ) | ( a << 24 ); - } - else - { - const auto rc = clampu8( r ); - const auto gc = clampu8( g ); - const auto bc = clampu8( b ); - dst[j*w+i] = rc | ( gc << 8 ) | ( bc << 16 ) | ( a << 24 ); - } - idx >>= 2; - } - } - } - else - { - for( int i=0; i<4; i++ ) - { - const auto tbl = g_table[tcw[i/2]]; - const auto cr = br[i/2]; - const auto cg = bg[i/2]; - const auto cb = bb[i/2]; - - for( int j=0; j<4; j++ ) - { - const auto mod = tbl[idx & 0x3]; - const auto r = cr + mod; - const auto g = cg + mod; - const auto b = cb + mod; - const auto amod = atbl[(alpha >> ( 45 - j*3 - i*12 )) & 0x7]; - const uint32_t a = clampu8( base + amod * mul ); - if( ( ( r | g | b ) & ~0xFF ) == 0 ) - { - dst[j*w+i] = r | ( g << 8 ) | ( b << 16 ) | ( a << 24 ); - } - else - { - const auto rc = clampu8( r ); - const auto gc = clampu8( g ); - const auto bc = clampu8( b ); - dst[j*w+i] = rc | ( gc << 8 ) | ( bc << 16 ) | ( a << 24 ); - } - idx >>= 2; - } - } - } -} - -BitmapPtr BlockData::DecodeRGB() -{ - auto ret = std::make_shared<Bitmap>( m_size ); - - const uint64_t* src = (const uint64_t*)( m_data + m_dataOffset ); - uint32_t* dst = ret->Data(); - - for( int y=0; y<m_size.y/4; y++ ) - { - for( int x=0; x<m_size.x/4; x++ ) - { - uint64_t d = *src++; - DecodeRGBPart( d, dst, m_size.x ); - dst += 4; - } - dst += m_size.x*3; - } - - return ret; -} - -BitmapPtr BlockData::DecodeRGBA() -{ - auto ret = std::make_shared<Bitmap>( m_size ); - - const uint64_t* src = (const uint64_t*)( m_data + m_dataOffset ); - uint32_t* dst = ret->Data(); - - for( int y=0; y<m_size.y/4; y++ ) - { - for( int x=0; x<m_size.x/4; x++ ) - { - uint64_t a = *src++; - uint64_t d = *src++; - DecodeRGBAPart( d, a, dst, m_size.x ); - dst += 4; - } - dst += m_size.x*3; - } - - return ret; -} - -static etcpak_force_inline void DecodeDxt1Part( uint64_t d, uint32_t* dst, uint32_t w ) -{ - uint8_t* in = (uint8_t*)&d; - uint16_t c0, c1; - uint32_t idx; - memcpy( &c0, in, 2 ); - memcpy( &c1, in+2, 2 ); - memcpy( &idx, in+4, 4 ); - - uint8_t r0 = ( ( c0 & 0xF800 ) >> 8 ) | ( ( c0 & 0xF800 ) >> 13 ); - uint8_t g0 = ( ( c0 & 0x07E0 ) >> 3 ) | ( ( c0 & 0x07E0 ) >> 9 ); - uint8_t b0 = ( ( c0 & 0x001F ) << 3 ) | ( ( c0 & 0x001F ) >> 2 ); - - uint8_t r1 = ( ( c1 & 0xF800 ) >> 8 ) | ( ( c1 & 0xF800 ) >> 13 ); - uint8_t g1 = ( ( c1 & 0x07E0 ) >> 3 ) | ( ( c1 & 0x07E0 ) >> 9 ); - uint8_t b1 = ( ( c1 & 0x001F ) << 3 ) | ( ( c1 & 0x001F ) >> 2 ); - - uint32_t dict[4]; - - dict[0] = 0xFF000000 | ( b0 << 16 ) | ( g0 << 8 ) | r0; - dict[1] = 0xFF000000 | ( b1 << 16 ) | ( g1 << 8 ) | r1; - - uint32_t r, g, b; - if( c0 > c1 ) - { - r = (2*r0+r1)/3; - g = (2*g0+g1)/3; - b = (2*b0+b1)/3; - dict[2] = 0xFF000000 | ( b << 16 ) | ( g << 8 ) | r; - r = (2*r1+r0)/3; - g = (2*g1+g0)/3; - b = (2*b1+b0)/3; - dict[3] = 0xFF000000 | ( b << 16 ) | ( g << 8 ) | r; - } - else - { - r = (int(r0)+r1)/2; - g = (int(g0)+g1)/2; - b = (int(b0)+b1)/2; - dict[2] = 0xFF000000 | ( b << 16 ) | ( g << 8 ) | r; - dict[3] = 0xFF000000; - } - - memcpy( dst+0, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+1, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+2, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+3, dict + (idx & 0x3), 4 ); - idx >>= 2; - dst += w; - - memcpy( dst+0, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+1, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+2, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+3, dict + (idx & 0x3), 4 ); - idx >>= 2; - dst += w; - - memcpy( dst+0, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+1, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+2, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+3, dict + (idx & 0x3), 4 ); - idx >>= 2; - dst += w; - - memcpy( dst+0, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+1, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+2, dict + (idx & 0x3), 4 ); - idx >>= 2; - memcpy( dst+3, dict + (idx & 0x3), 4 ); -} - -static etcpak_force_inline void DecodeDxt5Part( uint64_t a, uint64_t d, uint32_t* dst, uint32_t w ) -{ - uint8_t* ain = (uint8_t*)&a; - uint8_t a0, a1; - uint64_t aidx = 0; - memcpy( &a0, ain, 1 ); - memcpy( &a1, ain+1, 1 ); - memcpy( &aidx, ain+2, 6 ); - - uint8_t* in = (uint8_t*)&d; - uint16_t c0, c1; - uint32_t idx; - memcpy( &c0, in, 2 ); - memcpy( &c1, in+2, 2 ); - memcpy( &idx, in+4, 4 ); - - uint32_t adict[8]; - adict[0] = a0 << 24; - adict[1] = a1 << 24; - if( a0 > a1 ) - { - adict[2] = ( (6*a0+1*a1)/7 ) << 24; - adict[3] = ( (5*a0+2*a1)/7 ) << 24; - adict[4] = ( (4*a0+3*a1)/7 ) << 24; - adict[5] = ( (3*a0+4*a1)/7 ) << 24; - adict[6] = ( (2*a0+5*a1)/7 ) << 24; - adict[7] = ( (1*a0+6*a1)/7 ) << 24; - } - else - { - adict[2] = ( (4*a0+1*a1)/5 ) << 24; - adict[3] = ( (3*a0+2*a1)/5 ) << 24; - adict[4] = ( (2*a0+3*a1)/5 ) << 24; - adict[5] = ( (1*a0+4*a1)/5 ) << 24; - adict[6] = 0; - adict[7] = 0xFF000000; - } - - uint8_t r0 = ( ( c0 & 0xF800 ) >> 8 ) | ( ( c0 & 0xF800 ) >> 13 ); - uint8_t g0 = ( ( c0 & 0x07E0 ) >> 3 ) | ( ( c0 & 0x07E0 ) >> 9 ); - uint8_t b0 = ( ( c0 & 0x001F ) << 3 ) | ( ( c0 & 0x001F ) >> 2 ); - - uint8_t r1 = ( ( c1 & 0xF800 ) >> 8 ) | ( ( c1 & 0xF800 ) >> 13 ); - uint8_t g1 = ( ( c1 & 0x07E0 ) >> 3 ) | ( ( c1 & 0x07E0 ) >> 9 ); - uint8_t b1 = ( ( c1 & 0x001F ) << 3 ) | ( ( c1 & 0x001F ) >> 2 ); - - uint32_t dict[4]; - - dict[0] = ( b0 << 16 ) | ( g0 << 8 ) | r0; - dict[1] = ( b1 << 16 ) | ( g1 << 8 ) | r1; - - uint32_t r, g, b; - if( c0 > c1 ) - { - r = (2*r0+r1)/3; - g = (2*g0+g1)/3; - b = (2*b0+b1)/3; - dict[2] = ( b << 16 ) | ( g << 8 ) | r; - r = (2*r1+r0)/3; - g = (2*g1+g0)/3; - b = (2*b1+b0)/3; - dict[3] = ( b << 16 ) | ( g << 8 ) | r; - } - else - { - r = (int(r0)+r1)/2; - g = (int(g0)+g1)/2; - b = (int(b0)+b1)/2; - dict[2] = ( b << 16 ) | ( g << 8 ) | r; - dict[3] = 0; - } - - dst[0] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[1] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[2] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[3] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst += w; - - dst[0] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[1] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[2] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[3] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst += w; - - dst[0] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[1] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[2] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[3] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst += w; - - dst[0] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[1] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[2] = dict[idx & 0x3] | adict[aidx & 0x7]; - idx >>= 2; - aidx >>= 3; - dst[3] = dict[idx & 0x3] | adict[aidx & 0x7]; -} - -BitmapPtr BlockData::DecodeDxt1() -{ - auto ret = std::make_shared<Bitmap>( m_size ); - - const uint64_t* src = (const uint64_t*)( m_data + m_dataOffset ); - uint32_t* dst = ret->Data(); - - for( int y=0; y<m_size.y/4; y++ ) - { - for( int x=0; x<m_size.x/4; x++ ) - { - uint64_t d = *src++; - DecodeDxt1Part( d, dst, m_size.x ); - dst += 4; - } - dst += m_size.x*3; - } - - return ret; -} - -BitmapPtr BlockData::DecodeDxt5() -{ - auto ret = std::make_shared<Bitmap>( m_size ); - - const uint64_t* src = (const uint64_t*)( m_data + m_dataOffset ); - uint32_t* dst = ret->Data(); - - for( int y=0; y<m_size.y/4; y++ ) - { - for( int x=0; x<m_size.x/4; x++ ) - { - uint64_t a = *src++; - uint64_t d = *src++; - DecodeDxt5Part( a, d, dst, m_size.x ); - dst += 4; - } - dst += m_size.x*3; - } - - return ret; -} diff --git a/thirdparty/etcpak/BlockData.hpp b/thirdparty/etcpak/BlockData.hpp deleted file mode 100644 index 209e35b4e6..0000000000 --- a/thirdparty/etcpak/BlockData.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __BLOCKDATA_HPP__ -#define __BLOCKDATA_HPP__ - -#include <condition_variable> -#include <future> -#include <memory> -#include <mutex> -#include <stdint.h> -#include <stdio.h> -#include <vector> - -#include "Bitmap.hpp" -#include "ForceInline.hpp" -#include "Vector.hpp" - -class BlockData -{ -public: - enum Type - { - Etc1, - Etc2_RGB, - Etc2_RGBA, - Dxt1, - Dxt5 - }; - - BlockData( const char* fn ); - BlockData( const char* fn, const v2i& size, bool mipmap, Type type ); - BlockData( const v2i& size, bool mipmap, Type type ); - ~BlockData(); - - BitmapPtr Decode(); - - void Process( const uint32_t* src, uint32_t blocks, size_t offset, size_t width, Channels type, bool dither ); - void ProcessRGBA( const uint32_t* src, uint32_t blocks, size_t offset, size_t width ); - - const v2i& Size() const { return m_size; } - -private: - etcpak_no_inline BitmapPtr DecodeRGB(); - etcpak_no_inline BitmapPtr DecodeRGBA(); - etcpak_no_inline BitmapPtr DecodeDxt1(); - etcpak_no_inline BitmapPtr DecodeDxt5(); - - uint8_t* m_data; - v2i m_size; - size_t m_dataOffset; - FILE* m_file; - size_t m_maplen; - Type m_type; -}; - -typedef std::shared_ptr<BlockData> BlockDataPtr; - -#endif diff --git a/thirdparty/etcpak/ColorSpace.cpp b/thirdparty/etcpak/ColorSpace.cpp deleted file mode 100644 index 0411541066..0000000000 --- a/thirdparty/etcpak/ColorSpace.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include <math.h> -#include <stdint.h> - -#include "Math.hpp" -#include "ColorSpace.hpp" - -namespace Color -{ - - static const XYZ white( v3b( 255, 255, 255 ) ); - static const v3f rwhite( 1.f / white.x, 1.f / white.y, 1.f / white.z ); - - - XYZ::XYZ( float _x, float _y, float _z ) - : x( _x ) - , y( _y ) - , z( _z ) - { - } - - XYZ::XYZ( const v3b& rgb ) - { - const float r = rgb.x / 255.f; - const float g = rgb.y / 255.f; - const float b = rgb.z / 255.f; - - const float rl = sRGB2linear( r ); - const float gl = sRGB2linear( g ); - const float bl = sRGB2linear( b ); - - x = 0.4124f * rl + 0.3576f * gl + 0.1805f * bl; - y = 0.2126f * rl + 0.7152f * gl + 0.0722f * bl; - z = 0.0193f * rl + 0.1192f * gl + 0.9505f * bl; - } - - static float revlab( float t ) - { - const float p1 = 6.f/29.f; - const float p2 = 4.f/29.f; - - if( t > p1 ) - { - return t*t*t; - } - else - { - return 3 * sq( p1 ) * ( t - p2 ); - } - } - - XYZ::XYZ( const Lab& lab ) - { - y = white.y * revlab( 1.f/116.f * ( lab.L + 16 ) ); - x = white.x * revlab( 1.f/116.f * ( lab.L + 16 ) + 1.f/500.f * lab.a ); - z = white.z * revlab( 1.f/116.f * ( lab.L + 16 ) - 1.f/200.f * lab.b ); - } - - v3i XYZ::RGB() const - { - const float rl = 3.2406f * x - 1.5372f * y - 0.4986f * z; - const float gl = -0.9689f * x + 1.8758f * y + 0.0415f * z; - const float bl = 0.0557f * x - 0.2040f * y + 1.0570f * z; - - const float r = linear2sRGB( rl ); - const float g = linear2sRGB( gl ); - const float b = linear2sRGB( bl ); - - return v3i( clampu8( int32_t( r * 255 ) ), clampu8( int32_t( g * 255 ) ), clampu8( int32_t( b * 255 ) ) ); - } - - - Lab::Lab() - : L( 0 ) - , a( 0 ) - , b( 0 ) - { - } - - Lab::Lab( float L, float a, float b ) - : L( L ) - , a( a ) - , b( b ) - { - } - - static float labfunc( float t ) - { - const float p1 = (6.f/29.f)*(6.f/29.f)*(6.f/29.f); - const float p2 = (1.f/3.f)*(29.f/6.f)*(29.f/6.f); - const float p3 = (4.f/29.f); - - if( t > p1 ) - { - return pow( t, 1.f/3.f ); - } - else - { - return p2 * t + p3; - } - } - - Lab::Lab( const XYZ& xyz ) - { - L = 116 * labfunc( xyz.y * rwhite.y ) - 16; - a = 500 * ( labfunc( xyz.x * rwhite.x ) - labfunc( xyz.y * rwhite.y ) ); - b = 200 * ( labfunc( xyz.y * rwhite.y ) - labfunc( xyz.z * rwhite.z ) ); - } - - Lab::Lab( const v3b& rgb ) - { - new(this) Lab( XYZ( rgb ) ); - } - -} diff --git a/thirdparty/etcpak/ColorSpace.hpp b/thirdparty/etcpak/ColorSpace.hpp deleted file mode 100644 index c9d0a9cf3f..0000000000 --- a/thirdparty/etcpak/ColorSpace.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __DARKRL__COLORSPACE_HPP__ -#define __DARKRL__COLORSPACE_HPP__ - -#include "Vector.hpp" - -namespace Color -{ - - class Lab; - - class XYZ - { - public: - XYZ( float x, float y, float z ); - XYZ( const v3b& rgb ); - XYZ( const Lab& lab ); - - v3i RGB() const; - - float x, y, z; - }; - - class Lab - { - public: - Lab(); - Lab( float L, float a, float b ); - Lab( const XYZ& xyz ); - Lab( const v3b& rgb ); - - float L, a, b; - }; - -} - -#endif diff --git a/thirdparty/etcpak/DataProvider.cpp b/thirdparty/etcpak/DataProvider.cpp deleted file mode 100644 index 6bd4b105ed..0000000000 --- a/thirdparty/etcpak/DataProvider.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include <assert.h> -#include <utility> - -#include "BitmapDownsampled.hpp" -#include "DataProvider.hpp" -#include "MipMap.hpp" - -DataProvider::DataProvider( const char* fn, bool mipmap, bool bgr ) - : m_offset( 0 ) - , m_mipmap( mipmap ) - , m_done( false ) - , m_lines( 32 ) -{ - m_bmp.emplace_back( new Bitmap( fn, m_lines, bgr ) ); - m_current = m_bmp[0].get(); -} - -DataProvider::~DataProvider() -{ -} - -unsigned int DataProvider::NumberOfParts() const -{ - unsigned int parts = ( ( m_bmp[0]->Size().y / 4 ) + m_lines - 1 ) / m_lines; - - if( m_mipmap ) - { - v2i current = m_bmp[0]->Size(); - int levels = NumberOfMipLevels( current ); - unsigned int lines = m_lines; - for( int i=1; i<levels; i++ ) - { - assert( current.x != 1 || current.y != 1 ); - current.x = std::max( 1, current.x / 2 ); - current.y = std::max( 1, current.y / 2 ); - lines *= 2; - parts += ( ( std::max( 4, current.y ) / 4 ) + lines - 1 ) / lines; - } - assert( current.x == 1 && current.y == 1 ); - } - - return parts; -} - -DataPart DataProvider::NextPart() -{ - assert( !m_done ); - - unsigned int lines = m_lines; - bool done; - - const auto ptr = m_current->NextBlock( lines, done ); - DataPart ret = { - ptr, - std::max<unsigned int>( 4, m_current->Size().x ), - lines, - m_offset - }; - - m_offset += m_current->Size().x / 4 * lines; - - if( done ) - { - if( m_mipmap && ( m_current->Size().x != 1 || m_current->Size().y != 1 ) ) - { - m_lines *= 2; - m_bmp.emplace_back( new BitmapDownsampled( *m_current, m_lines ) ); - m_current = m_bmp[m_bmp.size()-1].get(); - } - else - { - m_done = true; - } - } - - return ret; -} diff --git a/thirdparty/etcpak/DataProvider.hpp b/thirdparty/etcpak/DataProvider.hpp deleted file mode 100644 index e773801ed6..0000000000 --- a/thirdparty/etcpak/DataProvider.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __DATAPROVIDER_HPP__ -#define __DATAPROVIDER_HPP__ - -#include <memory> -#include <stdint.h> -#include <vector> - -#include "Bitmap.hpp" - -struct DataPart -{ - const uint32_t* src; - unsigned int width; - unsigned int lines; - unsigned int offset; -}; - -class DataProvider -{ -public: - DataProvider( const char* fn, bool mipmap, bool bgr ); - ~DataProvider(); - - unsigned int NumberOfParts() const; - - DataPart NextPart(); - - bool Alpha() const { return m_bmp[0]->Alpha(); } - const v2i& Size() const { return m_bmp[0]->Size(); } - const Bitmap& ImageData() const { return *m_bmp[0]; } - -private: - std::vector<std::unique_ptr<Bitmap>> m_bmp; - Bitmap* m_current; - unsigned int m_offset; - unsigned int m_lines; - bool m_mipmap; - bool m_done; -}; - -#endif diff --git a/thirdparty/etcpak/Debug.cpp b/thirdparty/etcpak/Debug.cpp deleted file mode 100644 index 72dc4e0526..0000000000 --- a/thirdparty/etcpak/Debug.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include <algorithm> -#include <vector> -#include "Debug.hpp" - -static std::vector<DebugLog::Callback*> s_callbacks; - -void DebugLog::Message( const char* msg ) -{ - for( auto it = s_callbacks.begin(); it != s_callbacks.end(); ++it ) - { - (*it)->OnDebugMessage( msg ); - } -} - -void DebugLog::AddCallback( Callback* c ) -{ - const auto it = std::find( s_callbacks.begin(), s_callbacks.end(), c ); - if( it == s_callbacks.end() ) - { - s_callbacks.push_back( c ); - } -} - -void DebugLog::RemoveCallback( Callback* c ) -{ - const auto it = std::find( s_callbacks.begin(), s_callbacks.end(), c ); - if( it != s_callbacks.end() ) - { - s_callbacks.erase( it ); - } -} diff --git a/thirdparty/etcpak/Debug.hpp b/thirdparty/etcpak/Debug.hpp deleted file mode 100644 index 524eaa7baf..0000000000 --- a/thirdparty/etcpak/Debug.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __DARKRL__DEBUG_HPP__ -#define __DARKRL__DEBUG_HPP__ - -#ifdef DEBUG -# include <sstream> -# define DBGPRINT(msg) { std::stringstream __buf; __buf << msg; DebugLog::Message( __buf.str().c_str() ); } -#else -# define DBGPRINT(msg) ((void)0) -#endif - -class DebugLog -{ -public: - struct Callback - { - virtual void OnDebugMessage( const char* msg ) = 0; - }; - - static void Message( const char* msg ); - static void AddCallback( Callback* c ); - static void RemoveCallback( Callback* c ); - -private: - DebugLog() {} -}; - -#endif diff --git a/thirdparty/etcpak/Error.cpp b/thirdparty/etcpak/Error.cpp deleted file mode 100644 index 014ecdab66..0000000000 --- a/thirdparty/etcpak/Error.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include <stdint.h> - -#include "Error.hpp" -#include "Math.hpp" - -float CalcMSE3( const Bitmap& bmp, const Bitmap& out ) -{ - float err = 0; - - const uint32_t* p1 = bmp.Data(); - const uint32_t* p2 = out.Data(); - size_t cnt = bmp.Size().x * bmp.Size().y; - - for( size_t i=0; i<cnt; i++ ) - { - uint32_t c1 = *p1++; - uint32_t c2 = *p2++; - - err += sq( ( c1 & 0x000000FF ) - ( c2 & 0x000000FF ) ); - err += sq( ( ( c1 & 0x0000FF00 ) >> 8 ) - ( ( c2 & 0x0000FF00 ) >> 8 ) ); - err += sq( ( ( c1 & 0x00FF0000 ) >> 16 ) - ( ( c2 & 0x00FF0000 ) >> 16 ) ); - } - - err /= cnt * 3; - - return err; -} - -float CalcMSE1( const Bitmap& bmp, const Bitmap& out ) -{ - float err = 0; - - const uint32_t* p1 = bmp.Data(); - const uint32_t* p2 = out.Data(); - size_t cnt = bmp.Size().x * bmp.Size().y; - - for( size_t i=0; i<cnt; i++ ) - { - uint32_t c1 = *p1++; - uint32_t c2 = *p2++; - - err += sq( ( c1 >> 24 ) - ( c2 & 0xFF ) ); - } - - err /= cnt; - - return err; -} diff --git a/thirdparty/etcpak/Error.hpp b/thirdparty/etcpak/Error.hpp deleted file mode 100644 index 9817754b74..0000000000 --- a/thirdparty/etcpak/Error.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ERROR_HPP__ -#define __ERROR_HPP__ - -#include "Bitmap.hpp" - -float CalcMSE3( const Bitmap& bmp, const Bitmap& out ); -float CalcMSE1( const Bitmap& bmp, const Bitmap& out ); - -#endif diff --git a/thirdparty/etcpak/MipMap.hpp b/thirdparty/etcpak/MipMap.hpp deleted file mode 100644 index d3b4bc9e7c..0000000000 --- a/thirdparty/etcpak/MipMap.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __MIPMAP_HPP__ -#define __MIPMAP_HPP__ - -#include "Vector.hpp" - -inline int NumberOfMipLevels( const v2i& size ) -{ - return (int)floor( log2( std::max( size.x, size.y ) ) ) + 1; -} - -#endif diff --git a/thirdparty/etcpak/Semaphore.hpp b/thirdparty/etcpak/Semaphore.hpp deleted file mode 100644 index 9e42dbb9e0..0000000000 --- a/thirdparty/etcpak/Semaphore.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __DARKRL__SEMAPHORE_HPP__ -#define __DARKRL__SEMAPHORE_HPP__ - -#include <condition_variable> -#include <mutex> - -class Semaphore -{ -public: - Semaphore( int count ) : m_count( count ) {} - - void lock() - { - std::unique_lock<std::mutex> lock( m_mutex ); - m_cv.wait( lock, [this](){ return m_count != 0; } ); - m_count--; - } - - void unlock() - { - std::lock_guard<std::mutex> lock( m_mutex ); - m_count++; - m_cv.notify_one(); - } - - bool try_lock() - { - std::lock_guard<std::mutex> lock( m_mutex ); - if( m_count == 0 ) - { - return false; - } - else - { - m_count--; - return true; - } - } - -private: - std::mutex m_mutex; - std::condition_variable m_cv; - unsigned int m_count; -}; - -#endif diff --git a/thirdparty/etcpak/System.cpp b/thirdparty/etcpak/System.cpp deleted file mode 100644 index 041f2676e8..0000000000 --- a/thirdparty/etcpak/System.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include <algorithm> -#ifdef _WIN32 -# include <windows.h> -#else -# include <unistd.h> -#endif - -#include "System.hpp" - -unsigned int System::CPUCores() -{ - static unsigned int cores = 0; - if( cores == 0 ) - { - int tmp; -#ifdef _WIN32 - SYSTEM_INFO info; - GetSystemInfo( &info ); - tmp = (int)info.dwNumberOfProcessors; -#else -# ifndef _SC_NPROCESSORS_ONLN -# ifdef _SC_NPROC_ONLN -# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN -# elif defined _SC_CRAY_NCPU -# define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU -# endif -# endif - tmp = (int)(long)sysconf( _SC_NPROCESSORS_ONLN ); -#endif - cores = (unsigned int)std::max( tmp, 1 ); - } - return cores; -} - -void System::SetThreadName( std::thread& thread, const char* name ) -{ -#ifdef _MSC_VER - const DWORD MS_VC_EXCEPTION=0x406D1388; - -# pragma pack( push, 8 ) - struct THREADNAME_INFO - { - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; - }; -# pragma pack(pop) - - DWORD ThreadId = GetThreadId( static_cast<HANDLE>( thread.native_handle() ) ); - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = ThreadId; - info.dwFlags = 0; - - __try - { - RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } -#endif -} diff --git a/thirdparty/etcpak/System.hpp b/thirdparty/etcpak/System.hpp deleted file mode 100644 index 1a09bb15e1..0000000000 --- a/thirdparty/etcpak/System.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __DARKRL__SYSTEM_HPP__ -#define __DARKRL__SYSTEM_HPP__ - -#include <thread> - -class System -{ -public: - System() = delete; - - static unsigned int CPUCores(); - static void SetThreadName( std::thread& thread, const char* name ); -}; - -#endif diff --git a/thirdparty/etcpak/TaskDispatch.cpp b/thirdparty/etcpak/TaskDispatch.cpp deleted file mode 100644 index b1ba17953b..0000000000 --- a/thirdparty/etcpak/TaskDispatch.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include <assert.h> -#include <stdio.h> -#ifndef _MSC_VER -#include <pthread.h> -#endif - -#include "Debug.hpp" -#include "System.hpp" -#include "TaskDispatch.hpp" - -static TaskDispatch* s_instance = nullptr; - -TaskDispatch::TaskDispatch( size_t workers ) - : m_exit( false ) - , m_jobs( 0 ) -{ - assert( !s_instance ); - s_instance = this; - - assert( workers >= 1 ); - workers--; - - m_workers.reserve( workers ); - for( size_t i=0; i<workers; i++ ) - { - char tmp[16]; - sprintf( tmp, "Worker %zu", i ); -#ifdef _MSC_VER - auto worker = std::thread( [this]{ Worker(); } ); - System::SetThreadName( worker, tmp ); -#else // Using pthread. - auto worker = std::thread( [this, tmp]{ -#ifdef __APPLE__ - pthread_setname_np( tmp ); -#else // Linux or MinGW. - pthread_setname_np( pthread_self(), tmp ); -#endif - Worker(); - } ); -#endif - m_workers.emplace_back( std::move( worker ) ); - } - - DBGPRINT( "Task dispatcher with " << m_workers.size() + 1 << " workers" ); -} - -TaskDispatch::~TaskDispatch() -{ - m_exit = true; - m_queueLock.lock(); - m_cvWork.notify_all(); - m_queueLock.unlock(); - - for( auto& worker : m_workers ) - { - worker.join(); - } - - assert( s_instance ); - s_instance = nullptr; -} - -void TaskDispatch::Queue( const std::function<void(void)>& f ) -{ - std::unique_lock<std::mutex> lock( s_instance->m_queueLock ); - s_instance->m_queue.emplace_back( f ); - const auto size = s_instance->m_queue.size(); - lock.unlock(); - if( size > 1 ) - { - s_instance->m_cvWork.notify_one(); - } -} - -void TaskDispatch::Queue( std::function<void(void)>&& f ) -{ - std::unique_lock<std::mutex> lock( s_instance->m_queueLock ); - s_instance->m_queue.emplace_back( std::move( f ) ); - const auto size = s_instance->m_queue.size(); - lock.unlock(); - if( size > 1 ) - { - s_instance->m_cvWork.notify_one(); - } -} - -void TaskDispatch::Sync() -{ - std::unique_lock<std::mutex> lock( s_instance->m_queueLock ); - while( !s_instance->m_queue.empty() ) - { - auto f = s_instance->m_queue.back(); - s_instance->m_queue.pop_back(); - lock.unlock(); - f(); - lock.lock(); - } - s_instance->m_cvJobs.wait( lock, []{ return s_instance->m_jobs == 0; } ); -} - -void TaskDispatch::Worker() -{ - for(;;) - { - std::unique_lock<std::mutex> lock( m_queueLock ); - m_cvWork.wait( lock, [this]{ return !m_queue.empty() || m_exit; } ); - if( m_exit ) return; - auto f = m_queue.back(); - m_queue.pop_back(); - m_jobs++; - lock.unlock(); - f(); - lock.lock(); - m_jobs--; - bool notify = m_jobs == 0 && m_queue.empty(); - lock.unlock(); - if( notify ) - { - m_cvJobs.notify_all(); - } - } -} diff --git a/thirdparty/etcpak/TaskDispatch.hpp b/thirdparty/etcpak/TaskDispatch.hpp deleted file mode 100644 index b513de4c0c..0000000000 --- a/thirdparty/etcpak/TaskDispatch.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __DARKRL__TASKDISPATCH_HPP__ -#define __DARKRL__TASKDISPATCH_HPP__ - -#include <atomic> -#include <condition_variable> -#include <functional> -#include <mutex> -#include <thread> -#include <vector> - -class TaskDispatch -{ -public: - TaskDispatch( size_t workers ); - ~TaskDispatch(); - - static void Queue( const std::function<void(void)>& f ); - static void Queue( std::function<void(void)>&& f ); - - static void Sync(); - -private: - void Worker(); - - std::vector<std::function<void(void)>> m_queue; - std::mutex m_queueLock; - std::condition_variable m_cvWork, m_cvJobs; - std::atomic<bool> m_exit; - size_t m_jobs; - - std::vector<std::thread> m_workers; -}; - -#endif diff --git a/thirdparty/etcpak/Timing.cpp b/thirdparty/etcpak/Timing.cpp deleted file mode 100644 index 2af851f9a9..0000000000 --- a/thirdparty/etcpak/Timing.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include <chrono> - -#include "Timing.hpp" - -uint64_t GetTime() -{ - return std::chrono::time_point_cast<std::chrono::microseconds>( std::chrono::high_resolution_clock::now() ).time_since_epoch().count(); -} diff --git a/thirdparty/etcpak/Timing.hpp b/thirdparty/etcpak/Timing.hpp deleted file mode 100644 index 3767e20f24..0000000000 --- a/thirdparty/etcpak/Timing.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __DARKRL__TIMING_HPP__ -#define __DARKRL__TIMING_HPP__ - -#include <stdint.h> - -uint64_t GetTime(); - -#endif diff --git a/thirdparty/etcpak/lz4/lz4.c b/thirdparty/etcpak/lz4/lz4.c deleted file mode 100644 index 08cf6b5cd7..0000000000 --- a/thirdparty/etcpak/lz4/lz4.c +++ /dev/null @@ -1,1516 +0,0 @@ -/* - LZ4 - Fast LZ compression algorithm - Copyright (C) 2011-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 source repository : https://github.com/Cyan4973/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - - -/************************************** -* Tuning parameters -**************************************/ -/* - * HEAPMODE : - * Select how default compression functions will allocate memory for their hash table, - * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). - */ -#define HEAPMODE 0 - -/* - * ACCELERATION_DEFAULT : - * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 - */ -#define ACCELERATION_DEFAULT 1 - - -/************************************** -* CPU Feature Detection -**************************************/ -/* - * LZ4_FORCE_SW_BITCOUNT - * Define this parameter if your target system or compiler does not support hardware bit count - */ -#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */ -# define LZ4_FORCE_SW_BITCOUNT -#endif - - -/************************************** -* Includes -**************************************/ -#include "lz4.h" - - -/************************************** -* Compiler Options -**************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# define FORCE_INLINE static __forceinline -# include <intrin.h> -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */ -#else -# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ -# if defined(__GNUC__) || defined(__clang__) -# define FORCE_INLINE static inline __attribute__((always_inline)) -# else -# define FORCE_INLINE static inline -# endif -# else -# define FORCE_INLINE static -# endif /* __STDC_VERSION__ */ -#endif /* _MSC_VER */ - -/* LZ4_GCC_VERSION is defined into lz4.h */ -#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) -# define expect(expr,value) (__builtin_expect ((expr),(value)) ) -#else -# define expect(expr,value) (expr) -#endif - -#define likely(expr) expect((expr) != 0, 1) -#define unlikely(expr) expect((expr) != 0, 0) - - -/************************************** -* Memory routines -**************************************/ -#include <stdlib.h> /* malloc, calloc, free */ -#define ALLOCATOR(n,s) calloc(n,s) -#define FREEMEM free -#include <string.h> /* memset, memcpy */ -#define MEM_INIT memset - - -/************************************** -* Basic Types -**************************************/ -#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ -# include <stdint.h> - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef uint32_t U32; - typedef int32_t S32; - typedef uint64_t U64; -#else - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef unsigned int U32; - typedef signed int S32; - typedef unsigned long long U64; -#endif - - -/************************************** -* Reading and writing into memory -**************************************/ -#define STEPSIZE sizeof(size_t) - -static unsigned LZ4_64bits(void) { return sizeof(void*)==8; } - -static unsigned LZ4_isLittleEndian(void) -{ - const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ - return one.c[0]; -} - - -static U16 LZ4_read16(const void* memPtr) -{ - U16 val16; - memcpy(&val16, memPtr, 2); - return val16; -} - -static U16 LZ4_readLE16(const void* memPtr) -{ - if (LZ4_isLittleEndian()) - { - return LZ4_read16(memPtr); - } - else - { - const BYTE* p = (const BYTE*)memPtr; - return (U16)((U16)p[0] + (p[1]<<8)); - } -} - -static void LZ4_writeLE16(void* memPtr, U16 value) -{ - if (LZ4_isLittleEndian()) - { - memcpy(memPtr, &value, 2); - } - else - { - BYTE* p = (BYTE*)memPtr; - p[0] = (BYTE) value; - p[1] = (BYTE)(value>>8); - } -} - -static U32 LZ4_read32(const void* memPtr) -{ - U32 val32; - memcpy(&val32, memPtr, 4); - return val32; -} - -static U64 LZ4_read64(const void* memPtr) -{ - U64 val64; - memcpy(&val64, memPtr, 8); - return val64; -} - -static size_t LZ4_read_ARCH(const void* p) -{ - if (LZ4_64bits()) - return (size_t)LZ4_read64(p); - else - return (size_t)LZ4_read32(p); -} - - -static void LZ4_copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); } - -static void LZ4_copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); } - -/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */ -static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd) -{ - BYTE* d = (BYTE*)dstPtr; - const BYTE* s = (const BYTE*)srcPtr; - BYTE* e = (BYTE*)dstEnd; - do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e); -} - - -/************************************** -* Common Constants -**************************************/ -#define MINMATCH 4 - -#define COPYLENGTH 8 -#define LASTLITERALS 5 -#define MFLIMIT (COPYLENGTH+MINMATCH) -static const int LZ4_minLength = (MFLIMIT+1); - -#define KB *(1 <<10) -#define MB *(1 <<20) -#define GB *(1U<<30) - -#define MAXD_LOG 16 -#define MAX_DISTANCE ((1 << MAXD_LOG) - 1) - -#define ML_BITS 4 -#define ML_MASK ((1U<<ML_BITS)-1) -#define RUN_BITS (8-ML_BITS) -#define RUN_MASK ((1U<<RUN_BITS)-1) - - -/************************************** -* Common Utils -**************************************/ -#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ - - -/************************************** -* Common functions -**************************************/ -static unsigned LZ4_NbCommonBytes (register size_t val) -{ - if (LZ4_isLittleEndian()) - { - if (LZ4_64bits()) - { -# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r = 0; - _BitScanForward64( &r, (U64)val ); - return (int)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_ctzll((U64)val) >> 3); -# else - static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; - return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; -# endif - } - else /* 32 bits */ - { -# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r; - _BitScanForward( &r, (U32)val ); - return (int)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_ctz((U32)val) >> 3); -# else - static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; - return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; -# endif - } - } - else /* Big Endian CPU */ - { - if (LZ4_64bits()) - { -# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r = 0; - _BitScanReverse64( &r, val ); - return (unsigned)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_clzll((U64)val) >> 3); -# else - unsigned r; - if (!(val>>32)) { r=4; } else { r=0; val>>=32; } - if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } - r += (!val); - return r; -# endif - } - else /* 32 bits */ - { -# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) - unsigned long r = 0; - _BitScanReverse( &r, (unsigned long)val ); - return (unsigned)(r>>3); -# elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (__builtin_clz((U32)val) >> 3); -# else - unsigned r; - if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } - r += (!val); - return r; -# endif - } - } -} - -static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) -{ - const BYTE* const pStart = pIn; - - while (likely(pIn<pInLimit-(STEPSIZE-1))) - { - size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); - if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; } - pIn += LZ4_NbCommonBytes(diff); - return (unsigned)(pIn - pStart); - } - - if (LZ4_64bits()) if ((pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } - if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; } - if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++; - return (unsigned)(pIn - pStart); -} - - -#ifndef LZ4_COMMONDEFS_ONLY -/************************************** -* Local Constants -**************************************/ -#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) -#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) -#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ - -static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1)); -static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */ - - -/************************************** -* Local Structures and types -**************************************/ -typedef struct { - U32 hashTable[HASH_SIZE_U32]; - U32 currentOffset; - U32 initCheck; - const BYTE* dictionary; - BYTE* bufferStart; /* obsolete, used for slideInputBuffer */ - U32 dictSize; -} LZ4_stream_t_internal; - -typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive; -typedef enum { byPtr, byU32, byU16 } tableType_t; - -typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive; -typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; - -typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; -typedef enum { full = 0, partial = 1 } earlyEnd_directive; - - -/************************************** -* Local Utils -**************************************/ -int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } -int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } -int LZ4_sizeofState() { return LZ4_STREAMSIZE; } - - - -/******************************** -* Compression functions -********************************/ - -static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType) -{ - if (tableType == byU16) - return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); - else - return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); -} - -static const U64 prime5bytes = 889523592379ULL; -static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType) -{ - const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; - const U32 hashMask = (1<<hashLog) - 1; - return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask; -} - -static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType) -{ - if (LZ4_64bits()) - return LZ4_hashSequence64(sequence, tableType); - return LZ4_hashSequence((U32)sequence, tableType); -} - -static U32 LZ4_hashPosition(const void* p, tableType_t tableType) { return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType); } - -static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) -{ - switch (tableType) - { - case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; } - case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; } - case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; } - } -} - -static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) -{ - U32 h = LZ4_hashPosition(p, tableType); - LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); -} - -static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) -{ - if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; } - if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } - { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ -} - -static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) -{ - U32 h = LZ4_hashPosition(p, tableType); - return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); -} - -FORCE_INLINE int LZ4_compress_generic( - void* const ctx, - const char* const source, - char* const dest, - const int inputSize, - const int maxOutputSize, - const limitedOutput_directive outputLimited, - const tableType_t tableType, - const dict_directive dict, - const dictIssue_directive dictIssue, - const U32 acceleration) -{ - LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx; - - const BYTE* ip = (const BYTE*) source; - const BYTE* base; - const BYTE* lowLimit; - const BYTE* const lowRefLimit = ip - dictPtr->dictSize; - const BYTE* const dictionary = dictPtr->dictionary; - const BYTE* const dictEnd = dictionary + dictPtr->dictSize; - const size_t dictDelta = dictEnd - (const BYTE*)source; - const BYTE* anchor = (const BYTE*) source; - const BYTE* const iend = ip + inputSize; - const BYTE* const mflimit = iend - MFLIMIT; - const BYTE* const matchlimit = iend - LASTLITERALS; - - BYTE* op = (BYTE*) dest; - BYTE* const olimit = op + maxOutputSize; - - U32 forwardH; - size_t refDelta=0; - - /* Init conditions */ - if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ - switch(dict) - { - case noDict: - default: - base = (const BYTE*)source; - lowLimit = (const BYTE*)source; - break; - case withPrefix64k: - base = (const BYTE*)source - dictPtr->currentOffset; - lowLimit = (const BYTE*)source - dictPtr->dictSize; - break; - case usingExtDict: - base = (const BYTE*)source - dictPtr->currentOffset; - lowLimit = (const BYTE*)source; - break; - } - if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ - if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ - - /* First Byte */ - LZ4_putPosition(ip, ctx, tableType, base); - ip++; forwardH = LZ4_hashPosition(ip, tableType); - - /* Main Loop */ - for ( ; ; ) - { - const BYTE* match; - BYTE* token; - { - const BYTE* forwardIp = ip; - unsigned step = 1; - unsigned searchMatchNb = acceleration << LZ4_skipTrigger; - - /* Find a match */ - do { - U32 h = forwardH; - ip = forwardIp; - forwardIp += step; - step = (searchMatchNb++ >> LZ4_skipTrigger); - - if (unlikely(forwardIp > mflimit)) goto _last_literals; - - match = LZ4_getPositionOnHash(h, ctx, tableType, base); - if (dict==usingExtDict) - { - if (match<(const BYTE*)source) - { - refDelta = dictDelta; - lowLimit = dictionary; - } - else - { - refDelta = 0; - lowLimit = (const BYTE*)source; - } - } - forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putPositionOnHash(ip, h, ctx, tableType, base); - - } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0) - || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) - || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) ); - } - - /* Catch up */ - while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; } - - { - /* Encode Literal length */ - unsigned litLength = (unsigned)(ip - anchor); - token = op++; - if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) - return 0; /* Check output limit */ - if (litLength>=RUN_MASK) - { - int len = (int)litLength-RUN_MASK; - *token=(RUN_MASK<<ML_BITS); - for(; len >= 255 ; len-=255) *op++ = 255; - *op++ = (BYTE)len; - } - else *token = (BYTE)(litLength<<ML_BITS); - - /* Copy Literals */ - LZ4_wildCopy(op, anchor, op+litLength); - op+=litLength; - } - -_next_match: - /* Encode Offset */ - LZ4_writeLE16(op, (U16)(ip-match)); op+=2; - - /* Encode MatchLength */ - { - unsigned matchLength; - - if ((dict==usingExtDict) && (lowLimit==dictionary)) - { - const BYTE* limit; - match += refDelta; - limit = ip + (dictEnd-match); - if (limit > matchlimit) limit = matchlimit; - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); - ip += MINMATCH + matchLength; - if (ip==limit) - { - unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit); - matchLength += more; - ip += more; - } - } - else - { - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - ip += MINMATCH + matchLength; - } - - if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit))) - return 0; /* Check output limit */ - if (matchLength>=ML_MASK) - { - *token += ML_MASK; - matchLength -= ML_MASK; - for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; } - if (matchLength >= 255) { matchLength-=255; *op++ = 255; } - *op++ = (BYTE)matchLength; - } - else *token += (BYTE)(matchLength); - } - - anchor = ip; - - /* Test end of chunk */ - if (ip > mflimit) break; - - /* Fill table */ - LZ4_putPosition(ip-2, ctx, tableType, base); - - /* Test next position */ - match = LZ4_getPosition(ip, ctx, tableType, base); - if (dict==usingExtDict) - { - if (match<(const BYTE*)source) - { - refDelta = dictDelta; - lowLimit = dictionary; - } - else - { - refDelta = 0; - lowLimit = (const BYTE*)source; - } - } - LZ4_putPosition(ip, ctx, tableType, base); - if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1) - && (match+MAX_DISTANCE>=ip) - && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) ) - { token=op++; *token=0; goto _next_match; } - - /* Prepare next loop */ - forwardH = LZ4_hashPosition(++ip, tableType); - } - -_last_literals: - /* Encode Last Literals */ - { - const size_t lastRun = (size_t)(iend - anchor); - if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) - return 0; /* Check output limit */ - if (lastRun >= RUN_MASK) - { - size_t accumulator = lastRun - RUN_MASK; - *op++ = RUN_MASK << ML_BITS; - for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; - *op++ = (BYTE) accumulator; - } - else - { - *op++ = (BYTE)(lastRun<<ML_BITS); - } - memcpy(op, anchor, lastRun); - op += lastRun; - } - - /* End */ - return (int) (((char*)op)-dest); -} - - -int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) -{ - LZ4_resetStream((LZ4_stream_t*)state); - if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; - - if (maxOutputSize >= LZ4_compressBound(inputSize)) - { - if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); - else - return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); - } - else - { - if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); - else - return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); - } -} - - -int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) -{ -#if (HEAPMODE) - void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ -#else - LZ4_stream_t ctx; - void* ctxPtr = &ctx; -#endif - - int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); - -#if (HEAPMODE) - FREEMEM(ctxPtr); -#endif - return result; -} - - -int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize) -{ - return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1); -} - - -/* hidden debug function */ -/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */ -int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) -{ - LZ4_stream_t ctx; - - LZ4_resetStream(&ctx); - - if (inputSize < LZ4_64Klimit) - return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); - else - return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration); -} - - -/******************************** -* destSize variant -********************************/ - -static int LZ4_compress_destSize_generic( - void* const ctx, - const char* const src, - char* const dst, - int* const srcSizePtr, - const int targetDstSize, - const tableType_t tableType) -{ - const BYTE* ip = (const BYTE*) src; - const BYTE* base = (const BYTE*) src; - const BYTE* lowLimit = (const BYTE*) src; - const BYTE* anchor = ip; - const BYTE* const iend = ip + *srcSizePtr; - const BYTE* const mflimit = iend - MFLIMIT; - const BYTE* const matchlimit = iend - LASTLITERALS; - - BYTE* op = (BYTE*) dst; - BYTE* const oend = op + targetDstSize; - BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */; - BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */); - BYTE* const oMaxSeq = oMaxLit - 1 /* token */; - - U32 forwardH; - - - /* Init conditions */ - if (targetDstSize < 1) return 0; /* Impossible to store anything */ - if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ - if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ - if (*srcSizePtr<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ - - /* First Byte */ - *srcSizePtr = 0; - LZ4_putPosition(ip, ctx, tableType, base); - ip++; forwardH = LZ4_hashPosition(ip, tableType); - - /* Main Loop */ - for ( ; ; ) - { - const BYTE* match; - BYTE* token; - { - const BYTE* forwardIp = ip; - unsigned step = 1; - unsigned searchMatchNb = 1 << LZ4_skipTrigger; - - /* Find a match */ - do { - U32 h = forwardH; - ip = forwardIp; - forwardIp += step; - step = (searchMatchNb++ >> LZ4_skipTrigger); - - if (unlikely(forwardIp > mflimit)) - goto _last_literals; - - match = LZ4_getPositionOnHash(h, ctx, tableType, base); - forwardH = LZ4_hashPosition(forwardIp, tableType); - LZ4_putPositionOnHash(ip, h, ctx, tableType, base); - - } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) - || (LZ4_read32(match) != LZ4_read32(ip)) ); - } - - /* Catch up */ - while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } - - { - /* Encode Literal length */ - unsigned litLength = (unsigned)(ip - anchor); - token = op++; - if (op + ((litLength+240)/255) + litLength > oMaxLit) - { - /* Not enough space for a last match */ - op--; - goto _last_literals; - } - if (litLength>=RUN_MASK) - { - unsigned len = litLength - RUN_MASK; - *token=(RUN_MASK<<ML_BITS); - for(; len >= 255 ; len-=255) *op++ = 255; - *op++ = (BYTE)len; - } - else *token = (BYTE)(litLength<<ML_BITS); - - /* Copy Literals */ - LZ4_wildCopy(op, anchor, op+litLength); - op += litLength; - } - -_next_match: - /* Encode Offset */ - LZ4_writeLE16(op, (U16)(ip-match)); op+=2; - - /* Encode MatchLength */ - { - size_t matchLength; - - matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); - - if (op + ((matchLength+240)/255) > oMaxMatch) - { - /* Match description too long : reduce it */ - matchLength = (15-1) + (oMaxMatch-op) * 255; - } - //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH); - ip += MINMATCH + matchLength; - - if (matchLength>=ML_MASK) - { - *token += ML_MASK; - matchLength -= ML_MASK; - while (matchLength >= 255) { matchLength-=255; *op++ = 255; } - *op++ = (BYTE)matchLength; - } - else *token += (BYTE)(matchLength); - } - - anchor = ip; - - /* Test end of block */ - if (ip > mflimit) break; - if (op > oMaxSeq) break; - - /* Fill table */ - LZ4_putPosition(ip-2, ctx, tableType, base); - - /* Test next position */ - match = LZ4_getPosition(ip, ctx, tableType, base); - LZ4_putPosition(ip, ctx, tableType, base); - if ( (match+MAX_DISTANCE>=ip) - && (LZ4_read32(match)==LZ4_read32(ip)) ) - { token=op++; *token=0; goto _next_match; } - - /* Prepare next loop */ - forwardH = LZ4_hashPosition(++ip, tableType); - } - -_last_literals: - /* Encode Last Literals */ - { - size_t lastRunSize = (size_t)(iend - anchor); - if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) - { - /* adapt lastRunSize to fill 'dst' */ - lastRunSize = (oend-op) - 1; - lastRunSize -= (lastRunSize+240)/255; - } - ip = anchor + lastRunSize; - - if (lastRunSize >= RUN_MASK) - { - size_t accumulator = lastRunSize - RUN_MASK; - *op++ = RUN_MASK << ML_BITS; - for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; - *op++ = (BYTE) accumulator; - } - else - { - *op++ = (BYTE)(lastRunSize<<ML_BITS); - } - memcpy(op, anchor, lastRunSize); - op += lastRunSize; - } - - /* End */ - *srcSizePtr = (int) (((const char*)ip)-src); - return (int) (((char*)op)-dst); -} - - -static int LZ4_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) -{ - LZ4_resetStream((LZ4_stream_t*)state); - - if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */ - { - return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); - } - else - { - if (*srcSizePtr < LZ4_64Klimit) - return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16); - else - return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, LZ4_64bits() ? byU32 : byPtr); - } -} - - -int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) -{ -#if (HEAPMODE) - void* ctx = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ -#else - LZ4_stream_t ctxBody; - void* ctx = &ctxBody; -#endif - - int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); - -#if (HEAPMODE) - FREEMEM(ctx); -#endif - return result; -} - - - -/******************************** -* Streaming functions -********************************/ - -LZ4_stream_t* LZ4_createStream(void) -{ - LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64); - LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */ - LZ4_resetStream(lz4s); - return lz4s; -} - -void LZ4_resetStream (LZ4_stream_t* LZ4_stream) -{ - MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t)); -} - -int LZ4_freeStream (LZ4_stream_t* LZ4_stream) -{ - FREEMEM(LZ4_stream); - return (0); -} - - -#define HASH_UNIT sizeof(size_t) -int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) -{ - LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; - const BYTE* p = (const BYTE*)dictionary; - const BYTE* const dictEnd = p + dictSize; - const BYTE* base; - - if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */ - LZ4_resetStream(LZ4_dict); - - if (dictSize < (int)HASH_UNIT) - { - dict->dictionary = NULL; - dict->dictSize = 0; - return 0; - } - - if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB; - dict->currentOffset += 64 KB; - base = p - dict->currentOffset; - dict->dictionary = p; - dict->dictSize = (U32)(dictEnd - p); - dict->currentOffset += dict->dictSize; - - while (p <= dictEnd-HASH_UNIT) - { - LZ4_putPosition(p, dict->hashTable, byU32, base); - p+=3; - } - - return dict->dictSize; -} - - -static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) -{ - if ((LZ4_dict->currentOffset > 0x80000000) || - ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */ - { - /* rescale hash table */ - U32 delta = LZ4_dict->currentOffset - 64 KB; - const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; - int i; - for (i=0; i<HASH_SIZE_U32; i++) - { - if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0; - else LZ4_dict->hashTable[i] -= delta; - } - LZ4_dict->currentOffset = 64 KB; - if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB; - LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize; - } -} - - -int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) -{ - LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream; - const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; - - const BYTE* smallest = (const BYTE*) source; - if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */ - if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd; - LZ4_renormDictT(streamPtr, smallest); - if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; - - /* Check overlapping input/dictionary space */ - { - const BYTE* sourceEnd = (const BYTE*) source + inputSize; - if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) - { - streamPtr->dictSize = (U32)(dictEnd - sourceEnd); - if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; - if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; - streamPtr->dictionary = dictEnd - streamPtr->dictSize; - } - } - - /* prefix mode : source data follows dictionary */ - if (dictEnd == (const BYTE*)source) - { - int result; - if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration); - else - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration); - streamPtr->dictSize += (U32)inputSize; - streamPtr->currentOffset += (U32)inputSize; - return result; - } - - /* external dictionary mode */ - { - int result; - if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration); - else - result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration); - streamPtr->dictionary = (const BYTE*)source; - streamPtr->dictSize = (U32)inputSize; - streamPtr->currentOffset += (U32)inputSize; - return result; - } -} - - -/* Hidden debug function, to force external dictionary mode */ -int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize) -{ - LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict; - int result; - const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; - - const BYTE* smallest = dictEnd; - if (smallest > (const BYTE*) source) smallest = (const BYTE*) source; - LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest); - - result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); - - streamPtr->dictionary = (const BYTE*)source; - streamPtr->dictSize = (U32)inputSize; - streamPtr->currentOffset += (U32)inputSize; - - return result; -} - - -int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) -{ - LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; - const BYTE* previousDictEnd = dict->dictionary + dict->dictSize; - - if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */ - if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize; - - memmove(safeBuffer, previousDictEnd - dictSize, dictSize); - - dict->dictionary = (const BYTE*)safeBuffer; - dict->dictSize = (U32)dictSize; - - return dictSize; -} - - - -/******************************* -* Decompression functions -*******************************/ -/* - * This generic decompression function cover all use cases. - * It shall be instantiated several times, using different sets of directives - * Note that it is essential this generic function is really inlined, - * in order to remove useless branches during compilation optimization. - */ -FORCE_INLINE int LZ4_decompress_generic( - const char* const source, - char* const dest, - int inputSize, - int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */ - - int endOnInput, /* endOnOutputSize, endOnInputSize */ - int partialDecoding, /* full, partial */ - int targetOutputSize, /* only used if partialDecoding==partial */ - int dict, /* noDict, withPrefix64k, usingExtDict */ - const BYTE* const lowPrefix, /* == dest if dict == noDict */ - const BYTE* const dictStart, /* only if dict==usingExtDict */ - const size_t dictSize /* note : = 0 if noDict */ - ) -{ - /* Local Variables */ - const BYTE* ip = (const BYTE*) source; - const BYTE* const iend = ip + inputSize; - - BYTE* op = (BYTE*) dest; - BYTE* const oend = op + outputSize; - BYTE* cpy; - BYTE* oexit = op + targetOutputSize; - const BYTE* const lowLimit = lowPrefix - dictSize; - - const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize; - const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4}; - const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; - - const int safeDecode = (endOnInput==endOnInputSize); - const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); - - - /* Special cases */ - if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ - if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ - if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); - - - /* Main Loop */ - while (1) - { - unsigned token; - size_t length; - const BYTE* match; - - /* get literal length */ - token = *ip++; - if ((length=(token>>ML_BITS)) == RUN_MASK) - { - unsigned s; - do - { - s = *ip++; - length += s; - } - while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255)); - if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */ - if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */ - } - - /* copy literals */ - cpy = op+length; - if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) - || ((!endOnInput) && (cpy>oend-COPYLENGTH))) - { - if (partialDecoding) - { - if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ - if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ - } - else - { - if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ - if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ - } - memcpy(op, ip, length); - ip += length; - op += length; - break; /* Necessarily EOF, due to parsing restrictions */ - } - LZ4_wildCopy(op, ip, cpy); - ip += length; op = cpy; - - /* get offset */ - match = cpy - LZ4_readLE16(ip); ip+=2; - if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */ - - /* get matchlength */ - length = token & ML_MASK; - if (length == ML_MASK) - { - unsigned s; - do - { - if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; - s = *ip++; - length += s; - } while (s==255); - if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */ - } - length += MINMATCH; - - /* check external dictionary */ - if ((dict==usingExtDict) && (match < lowPrefix)) - { - if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ - - if (length <= (size_t)(lowPrefix-match)) - { - /* match can be copied as a single segment from external dictionary */ - match = dictEnd - (lowPrefix-match); - memmove(op, match, length); op += length; - } - else - { - /* match encompass external dictionary and current segment */ - size_t copySize = (size_t)(lowPrefix-match); - memcpy(op, dictEnd - copySize, copySize); - op += copySize; - copySize = length - copySize; - if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */ - { - BYTE* const endOfMatch = op + copySize; - const BYTE* copyFrom = lowPrefix; - while (op < endOfMatch) *op++ = *copyFrom++; - } - else - { - memcpy(op, lowPrefix, copySize); - op += copySize; - } - } - continue; - } - - /* copy repeated sequence */ - cpy = op + length; - if (unlikely((op-match)<8)) - { - const size_t dec64 = dec64table[op-match]; - op[0] = match[0]; - op[1] = match[1]; - op[2] = match[2]; - op[3] = match[3]; - match += dec32table[op-match]; - LZ4_copy4(op+4, match); - op += 8; match -= dec64; - } else { LZ4_copy8(op, match); op+=8; match+=8; } - - if (unlikely(cpy>oend-12)) - { - if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */ - if (op < oend-8) - { - LZ4_wildCopy(op, match, oend-8); - match += (oend-8) - op; - op = oend-8; - } - while (op<cpy) *op++ = *match++; - } - else - LZ4_wildCopy(op, match, cpy); - op=cpy; /* correction */ - } - - /* end of decoding */ - if (endOnInput) - return (int) (((char*)op)-dest); /* Nb of output bytes decoded */ - else - return (int) (((const char*)ip)-source); /* Nb of input bytes read */ - - /* Overflow error detected */ -_output_error: - return (int) (-(((const char*)ip)-source))-1; -} - - -int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0); -} - -int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0); -} - -int LZ4_decompress_fast(const char* source, char* dest, int originalSize) -{ - return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB); -} - - -/* streaming decompression functions */ - -typedef struct -{ - const BYTE* externalDict; - size_t extDictSize; - const BYTE* prefixEnd; - size_t prefixSize; -} LZ4_streamDecode_t_internal; - -/* - * If you prefer dynamic allocation methods, - * LZ4_createStreamDecode() - * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure. - */ -LZ4_streamDecode_t* LZ4_createStreamDecode(void) -{ - LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LZ4_streamDecode_t)); - return lz4s; -} - -int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream) -{ - FREEMEM(LZ4_stream); - return 0; -} - -/* - * LZ4_setStreamDecode - * Use this function to instruct where to find the dictionary - * This function is not necessary if previous data is still available where it was decoded. - * Loading a size of 0 is allowed (same effect as no dictionary). - * Return : 1 if OK, 0 if error - */ -int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize) -{ - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; - lz4sd->prefixSize = (size_t) dictSize; - lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; - lz4sd->externalDict = NULL; - lz4sd->extDictSize = 0; - return 1; -} - -/* -*_continue() : - These decoding functions allow decompression of multiple blocks in "streaming" mode. - Previously decoded blocks must still be available at the memory position where they were decoded. - If it's not possible, save the relevant part of decoded data into a safe buffer, - and indicate where it stands using LZ4_setStreamDecode() -*/ -int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) -{ - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; - int result; - - if (lz4sd->prefixEnd == (BYTE*)dest) - { - result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, - endOnInputSize, full, 0, - usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) return result; - lz4sd->prefixSize += result; - lz4sd->prefixEnd += result; - } - else - { - lz4sd->extDictSize = lz4sd->prefixSize; - lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; - result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, - endOnInputSize, full, 0, - usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) return result; - lz4sd->prefixSize = result; - lz4sd->prefixEnd = (BYTE*)dest + result; - } - - return result; -} - -int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) -{ - LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; - int result; - - if (lz4sd->prefixEnd == (BYTE*)dest) - { - result = LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, full, 0, - usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) return result; - lz4sd->prefixSize += originalSize; - lz4sd->prefixEnd += originalSize; - } - else - { - lz4sd->extDictSize = lz4sd->prefixSize; - lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize; - result = LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, full, 0, - usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); - if (result <= 0) return result; - lz4sd->prefixSize = originalSize; - lz4sd->prefixEnd = (BYTE*)dest + originalSize; - } - - return result; -} - - -/* -Advanced decoding functions : -*_usingDict() : - These decoding functions work the same as "_continue" ones, - the dictionary must be explicitly provided within parameters -*/ - -FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize) -{ - if (dictSize==0) - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0); - if (dictStart+dictSize == dest) - { - if (dictSize >= (int)(64 KB - 1)) - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0); - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0); - } - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); -} - -int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) -{ - return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize); -} - -int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize) -{ - return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize); -} - -/* debug function */ -int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); -} - - -/*************************************************** -* Obsolete Functions -***************************************************/ -/* obsolete compression functions */ -int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); } -int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); } -int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); } -int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); } -int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); } -int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); } - -/* -These function names are deprecated and should no longer be used. -They are only provided here for compatibility with older user programs. -- LZ4_uncompress is totally equivalent to LZ4_decompress_fast -- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe -*/ -int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); } -int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); } - - -/* Obsolete Streaming functions */ - -int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; } - -static void LZ4_init(LZ4_stream_t_internal* lz4ds, BYTE* base) -{ - MEM_INIT(lz4ds, 0, LZ4_STREAMSIZE); - lz4ds->bufferStart = base; -} - -int LZ4_resetStreamState(void* state, char* inputBuffer) -{ - if ((((size_t)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ - LZ4_init((LZ4_stream_t_internal*)state, (BYTE*)inputBuffer); - return 0; -} - -void* LZ4_create (char* inputBuffer) -{ - void* lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64); - LZ4_init ((LZ4_stream_t_internal*)lz4ds, (BYTE*)inputBuffer); - return lz4ds; -} - -char* LZ4_slideInputBuffer (void* LZ4_Data) -{ - LZ4_stream_t_internal* ctx = (LZ4_stream_t_internal*)LZ4_Data; - int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB); - return (char*)(ctx->bufferStart + dictSize); -} - -/* Obsolete streaming decompression functions */ - -int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize) -{ - return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); -} - -int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize) -{ - return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); -} - -#endif /* LZ4_COMMONDEFS_ONLY */ - diff --git a/thirdparty/etcpak/lz4/lz4.h b/thirdparty/etcpak/lz4/lz4.h deleted file mode 100644 index 3e74002256..0000000000 --- a/thirdparty/etcpak/lz4/lz4.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - LZ4 - Fast LZ compression algorithm - Header File - Copyright (C) 2011-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - LZ4 source repository : https://github.com/Cyan4973/lz4 - - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c -*/ -#pragma once - -#if defined (__cplusplus) -extern "C" { -#endif - -/* - * lz4.h provides block compression functions, and gives full buffer control to programmer. - * If you need to generate inter-operable compressed data (respecting LZ4 frame specification), - * and can let the library handle its own memory, please use lz4frame.h instead. -*/ - -/************************************** -* Version -**************************************/ -#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ -#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */ -#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */ -#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) -int LZ4_versionNumber (void); - -/************************************** -* Tuning parameter -**************************************/ -/* - * LZ4_MEMORY_USAGE : - * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) - * Increasing memory usage improves compression ratio - * Reduced memory usage can improve speed, due to cache effect - * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache - */ -#define LZ4_MEMORY_USAGE 14 - - -/************************************** -* Simple Functions -**************************************/ - -int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); -int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize); - -/* -LZ4_compress_default() : - Compresses 'sourceSize' bytes from buffer 'source' - into already allocated 'dest' buffer of size 'maxDestSize'. - Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize). - It also runs faster, so it's a recommended setting. - If the function cannot compress 'source' into a more limited 'dest' budget, - compression stops *immediately*, and the function result is zero. - As a consequence, 'dest' content is not valid. - This function never writes outside 'dest' buffer, nor read outside 'source' buffer. - sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE - maxDestSize : full or partial size of buffer 'dest' (which must be already allocated) - return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize) - or 0 if compression fails - -LZ4_decompress_safe() : - compressedSize : is the precise full size of the compressed block. - maxDecompressedSize : is the size of destination buffer, which must be already allocated. - return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize) - If destination buffer is not large enough, decoding will stop and output an error code (<0). - If the source stream is detected malformed, the function will stop decoding and return a negative result. - This function is protected against buffer overflow exploits, including malicious data packets. - It never writes outside output buffer, nor reads outside input buffer. -*/ - - -/************************************** -* Advanced Functions -**************************************/ -#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ -#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) - -/* -LZ4_compressBound() : - Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) - This function is primarily useful for memory allocation purposes (destination buffer size). - Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). - Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize) - inputSize : max supported value is LZ4_MAX_INPUT_SIZE - return : maximum output size in a "worst case" scenario - or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) -*/ -int LZ4_compressBound(int inputSize); - -/* -LZ4_compress_fast() : - Same as LZ4_compress_default(), but allows to select an "acceleration" factor. - The larger the acceleration value, the faster the algorithm, but also the lesser the compression. - It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. - An acceleration value of "1" is the same as regular LZ4_compress_default() - Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1. -*/ -int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); - - -/* -LZ4_compress_fast_extState() : - Same compression function, just using an externally allocated memory space to store compression state. - Use LZ4_sizeofState() to know how much memory must be allocated, - and allocate it on 8-bytes boundaries (using malloc() typically). - Then, provide it as 'void* state' to compression function. -*/ -int LZ4_sizeofState(void); -int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration); - - -/* -LZ4_compress_destSize() : - Reverse the logic, by compressing as much data as possible from 'source' buffer - into already allocated buffer 'dest' of size 'targetDestSize'. - This function either compresses the entire 'source' content into 'dest' if it's large enough, - or fill 'dest' buffer completely with as much data as possible from 'source'. - *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'. - New value is necessarily <= old value. - return : Nb bytes written into 'dest' (necessarily <= targetDestSize) - or 0 if compression fails -*/ -int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize); - - -/* -LZ4_decompress_fast() : - originalSize : is the original and therefore uncompressed size - return : the number of bytes read from the source buffer (in other words, the compressed size) - If the source stream is detected malformed, the function will stop decoding and return a negative result. - Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes. - note : This function fully respect memory boundaries for properly formed compressed data. - It is a bit faster than LZ4_decompress_safe(). - However, it does not provide any protection against intentionally modified data stream (malicious input). - Use this function in trusted environment only (data to decode comes from a trusted source). -*/ -int LZ4_decompress_fast (const char* source, char* dest, int originalSize); - -/* -LZ4_decompress_safe_partial() : - This function decompress a compressed block of size 'compressedSize' at position 'source' - into destination buffer 'dest' of size 'maxDecompressedSize'. - The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached, - reducing decompression time. - return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize) - Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller. - Always control how many bytes were decoded. - If the source stream is detected malformed, the function will stop decoding and return a negative result. - This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets -*/ -int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); - - -/*********************************************** -* Streaming Compression Functions -***********************************************/ -#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) -#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long)) -/* - * LZ4_stream_t - * information structure to track an LZ4 stream. - * important : init this structure content before first use ! - * note : only allocated directly the structure if you are statically linking LZ4 - * If you are using liblz4 as a DLL, please use below construction methods instead. - */ -typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t; - -/* - * LZ4_resetStream - * Use this function to init an allocated LZ4_stream_t structure - */ -void LZ4_resetStream (LZ4_stream_t* streamPtr); - -/* - * LZ4_createStream will allocate and initialize an LZ4_stream_t structure - * LZ4_freeStream releases its memory. - * In the context of a DLL (liblz4), please use these methods rather than the static struct. - * They are more future proof, in case of a change of LZ4_stream_t size. - */ -LZ4_stream_t* LZ4_createStream(void); -int LZ4_freeStream (LZ4_stream_t* streamPtr); - -/* - * LZ4_loadDict - * Use this function to load a static dictionary into LZ4_stream. - * Any previous data will be forgotten, only 'dictionary' will remain in memory. - * Loading a size of 0 is allowed. - * Return : dictionary size, in bytes (necessarily <= 64 KB) - */ -int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); - -/* - * LZ4_compress_fast_continue - * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. - * Important : Previous data blocks are assumed to still be present and unmodified ! - * 'dst' buffer must be already allocated. - * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. - * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero. - */ -int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration); - -/* - * LZ4_saveDict - * If previously compressed data block is not guaranteed to remain available at its memory location - * save it into a safer place (char* safeBuffer) - * Note : you don't need to call LZ4_loadDict() afterwards, - * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue() - * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error - */ -int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize); - - -/************************************************ -* Streaming Decompression Functions -************************************************/ - -#define LZ4_STREAMDECODESIZE_U64 4 -#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) -typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t; -/* - * LZ4_streamDecode_t - * information structure to track an LZ4 stream. - * init this structure content using LZ4_setStreamDecode or memset() before first use ! - * - * In the context of a DLL (liblz4) please prefer usage of construction methods below. - * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future. - * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure - * LZ4_freeStreamDecode releases its memory. - */ -LZ4_streamDecode_t* LZ4_createStreamDecode(void); -int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); - -/* - * LZ4_setStreamDecode - * Use this function to instruct where to find the dictionary. - * Setting a size of 0 is allowed (same effect as reset). - * Return : 1 if OK, 0 if error - */ -int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); - -/* -*_continue() : - These decoding functions allow decompression of multiple blocks in "streaming" mode. - Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB) - In the case of a ring buffers, decoding buffer must be either : - - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions) - In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB). - - Larger than encoding buffer, by a minimum of maxBlockSize more bytes. - maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block. - In which case, encoding and decoding buffers do not need to be synchronized, - and encoding ring buffer can have any size, including small ones ( < 64 KB). - - _At least_ 64 KB + 8 bytes + maxBlockSize. - In which case, encoding and decoding buffers do not need to be synchronized, - and encoding ring buffer can have any size, including larger than decoding buffer. - Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer, - and indicate where it is saved using LZ4_setStreamDecode() -*/ -int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize); -int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize); - - -/* -Advanced decoding functions : -*_usingDict() : - These decoding functions work the same as - a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue() - They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure. -*/ -int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize); -int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); - - - -/************************************** -* Obsolete Functions -**************************************/ -/* Deprecate Warnings */ -/* Should these warnings messages be a problem, - it is generally possible to disable them, - with -Wno-deprecated-declarations for gcc - or _CRT_SECURE_NO_WARNINGS in Visual for example. - You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */ -#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK -# define LZ4_DEPRECATE_WARNING_DEFBLOCK -# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) -# if (LZ4_GCC_VERSION >= 405) || defined(__clang__) -# define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) -# elif (LZ4_GCC_VERSION >= 301) -# define LZ4_DEPRECATED(message) __attribute__((deprecated)) -# elif defined(_MSC_VER) -# define LZ4_DEPRECATED(message) __declspec(deprecated(message)) -# else -# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler") -# define LZ4_DEPRECATED(message) -# endif -#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */ - -/* Obsolete compression functions */ -/* These functions are planned to start generate warnings by r131 approximately */ -int LZ4_compress (const char* source, char* dest, int sourceSize); -int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); -int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); -int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); -int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); -int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); - -/* Obsolete decompression functions */ -/* These function names are completely deprecated and must no longer be used. - They are only provided here for compatibility with older programs. - - LZ4_uncompress is the same as LZ4_decompress_fast - - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe - These function prototypes are now disabled; uncomment them only if you really need them. - It is highly recommended to stop using these prototypes and migrate to maintained ones */ -/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */ -/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */ - -/* Obsolete streaming functions; use new streaming interface whenever possible */ -LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer); -LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void); -LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer); -LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state); - -/* Obsolete streaming decoding functions */ -LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize); -LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); - - -#if defined (__cplusplus) -} -#endif diff --git a/thirdparty/etcpak/mmap.cpp b/thirdparty/etcpak/mmap.cpp deleted file mode 100644 index c2460ee9e4..0000000000 --- a/thirdparty/etcpak/mmap.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "mmap.hpp" - -#ifdef _WIN32 -# include <io.h> -# include <windows.h> - -void* mmap( void* addr, size_t length, int prot, int flags, int fd, off_t offset ) -{ - HANDLE hnd; - void* map = nullptr; - - switch( prot ) - { - case PROT_READ: - if( hnd = CreateFileMapping( HANDLE( _get_osfhandle( fd ) ), nullptr, PAGE_READONLY, 0, DWORD( length ), nullptr ) ) - { - map = MapViewOfFile( hnd, FILE_MAP_READ, 0, 0, length ); - CloseHandle( hnd ); - } - break; - case PROT_WRITE: - if( hnd = CreateFileMapping( HANDLE( _get_osfhandle( fd ) ), nullptr, PAGE_READWRITE, 0, DWORD( length ), nullptr ) ) - { - map = MapViewOfFile( hnd, FILE_MAP_WRITE, 0, 0, length ); - CloseHandle( hnd ); - } - break; - } - - return map ? (char*)map + offset : (void*)-1; -} - -int munmap( void* addr, size_t length ) -{ - return UnmapViewOfFile( addr ) != 0 ? 0 : -1; -} - -#endif diff --git a/thirdparty/etcpak/mmap.hpp b/thirdparty/etcpak/mmap.hpp deleted file mode 100644 index e4cfe7759c..0000000000 --- a/thirdparty/etcpak/mmap.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __MMAP_HPP__ -#define __MMAP_HPP__ - -#ifndef _WIN32 -# include <sys/mman.h> -#else -# include <string.h> -# include <sys/types.h> - -# define PROT_READ 1 -# define PROT_WRITE 2 -# define MAP_SHARED 0 - -void* mmap( void* addr, size_t length, int prot, int flags, int fd, off_t offset ); -int munmap( void* addr, size_t length ); - -#endif - -#endif diff --git a/thirdparty/etcpak/patches/libpng-unbundle.patch b/thirdparty/etcpak/patches/libpng-unbundle.patch deleted file mode 100644 index e3c07412c6..0000000000 --- a/thirdparty/etcpak/patches/libpng-unbundle.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/thirdparty/etcpak/Bitmap.cpp b/thirdparty/etcpak/Bitmap.cpp -index 6aa36f5caa..ef318318ac 100644 ---- a/thirdparty/etcpak/Bitmap.cpp -+++ b/thirdparty/etcpak/Bitmap.cpp -@@ -3,7 +3,7 @@ - #include <string.h> - #include <assert.h> - --#include "libpng/png.h" -+#include <png.h> - #include "lz4/lz4.h" - - #include "Bitmap.hpp" diff --git a/thirdparty/etcpak/patches/llvm-c++11-narrowing-errors.patch b/thirdparty/etcpak/patches/llvm-c++11-narrowing-errors.patch deleted file mode 100644 index ab0d1e63a2..0000000000 --- a/thirdparty/etcpak/patches/llvm-c++11-narrowing-errors.patch +++ /dev/null @@ -1,64 +0,0 @@ -diff --git a/thirdparty/etcpak/BlockData.cpp b/thirdparty/etcpak/BlockData.cpp -index bd738085f3..395b55246b 100644 ---- a/thirdparty/etcpak/BlockData.cpp -+++ b/thirdparty/etcpak/BlockData.cpp -@@ -334,10 +334,10 @@ static etcpak_force_inline void DecodeT( uint64_t block, uint32_t* dst, uint32_t - const auto c3b = clampu8( cb1 - table59T58H[codeword] ); - - const uint32_t col_tab[4] = { -- cr0 | ( cg0 << 8 ) | ( cb0 << 16 ) | 0xFF000000, -- c2r | ( c2g << 8 ) | ( c2b << 16 ) | 0xFF000000, -- cr1 | ( cg1 << 8 ) | ( cb1 << 16 ) | 0xFF000000, -- c3r | ( c3g << 8 ) | ( c3b << 16 ) | 0xFF000000 -+ uint32_t(cr0 | ( cg0 << 8 ) | ( cb0 << 16 ) | 0xFF000000), -+ uint32_t(c2r | ( c2g << 8 ) | ( c2b << 16 ) | 0xFF000000), -+ uint32_t(cr1 | ( cg1 << 8 ) | ( cb1 << 16 ) | 0xFF000000), -+ uint32_t(c3r | ( c3g << 8 ) | ( c3b << 16 ) | 0xFF000000) - }; - - const uint32_t indexes = ( block >> 32 ) & 0xFFFFFFFF; -@@ -389,10 +389,10 @@ static etcpak_force_inline void DecodeTAlpha( uint64_t block, uint64_t alpha, ui - const auto c3b = clampu8( cb1 - table59T58H[codeword] ); - - const uint32_t col_tab[4] = { -- cr0 | ( cg0 << 8 ) | ( cb0 << 16 ), -- c2r | ( c2g << 8 ) | ( c2b << 16 ), -- cr1 | ( cg1 << 8 ) | ( cb1 << 16 ), -- c3r | ( c3g << 8 ) | ( c3b << 16 ) -+ uint32_t(cr0 | ( cg0 << 8 ) | ( cb0 << 16 )), -+ uint32_t(c2r | ( c2g << 8 ) | ( c2b << 16 )), -+ uint32_t(cr1 | ( cg1 << 8 ) | ( cb1 << 16 )), -+ uint32_t(c3r | ( c3g << 8 ) | ( c3b << 16 )) - }; - - const uint32_t indexes = ( block >> 32 ) & 0xFFFFFFFF; -@@ -436,10 +436,10 @@ static etcpak_force_inline void DecodeH( uint64_t block, uint32_t* dst, uint32_t - const auto codeword = codeword_hi | codeword_lo; - - const uint32_t col_tab[] = { -- clampu8( r0 + table59T58H[codeword] ) | ( clampu8( g0 + table59T58H[codeword] ) << 8 ) | ( clampu8( b0 + table59T58H[codeword] ) << 16 ), -- clampu8( r0 - table59T58H[codeword] ) | ( clampu8( g0 - table59T58H[codeword] ) << 8 ) | ( clampu8( b0 - table59T58H[codeword] ) << 16 ), -- clampu8( r1 + table59T58H[codeword] ) | ( clampu8( g1 + table59T58H[codeword] ) << 8 ) | ( clampu8( b1 + table59T58H[codeword] ) << 16 ), -- clampu8( r1 - table59T58H[codeword] ) | ( clampu8( g1 - table59T58H[codeword] ) << 8 ) | ( clampu8( b1 - table59T58H[codeword] ) << 16 ) -+ uint32_t(clampu8( r0 + table59T58H[codeword] ) | ( clampu8( g0 + table59T58H[codeword] ) << 8 ) | ( clampu8( b0 + table59T58H[codeword] ) << 16 )), -+ uint32_t(clampu8( r0 - table59T58H[codeword] ) | ( clampu8( g0 - table59T58H[codeword] ) << 8 ) | ( clampu8( b0 - table59T58H[codeword] ) << 16 )), -+ uint32_t(clampu8( r1 + table59T58H[codeword] ) | ( clampu8( g1 + table59T58H[codeword] ) << 8 ) | ( clampu8( b1 + table59T58H[codeword] ) << 16 )), -+ uint32_t(clampu8( r1 - table59T58H[codeword] ) | ( clampu8( g1 - table59T58H[codeword] ) << 8 ) | ( clampu8( b1 - table59T58H[codeword] ) << 16 )) - }; - - for( uint8_t j = 0; j < 4; j++ ) -@@ -483,10 +483,10 @@ static etcpak_force_inline void DecodeHAlpha( uint64_t block, uint64_t alpha, ui - const auto tbl = g_alpha[(alpha >> 48) & 0xF]; - - const uint32_t col_tab[] = { -- clampu8( r0 + table59T58H[codeword] ) | ( clampu8( g0 + table59T58H[codeword] ) << 8 ) | ( clampu8( b0 + table59T58H[codeword] ) << 16 ), -- clampu8( r0 - table59T58H[codeword] ) | ( clampu8( g0 - table59T58H[codeword] ) << 8 ) | ( clampu8( b0 - table59T58H[codeword] ) << 16 ), -- clampu8( r1 + table59T58H[codeword] ) | ( clampu8( g1 + table59T58H[codeword] ) << 8 ) | ( clampu8( b1 + table59T58H[codeword] ) << 16 ), -- clampu8( r1 - table59T58H[codeword] ) | ( clampu8( g1 - table59T58H[codeword] ) << 8 ) | ( clampu8( b1 - table59T58H[codeword] ) << 16 ) -+ uint32_t(clampu8( r0 + table59T58H[codeword] ) | ( clampu8( g0 + table59T58H[codeword] ) << 8 ) | ( clampu8( b0 + table59T58H[codeword] ) << 16 )), -+ uint32_t(clampu8( r0 - table59T58H[codeword] ) | ( clampu8( g0 - table59T58H[codeword] ) << 8 ) | ( clampu8( b0 - table59T58H[codeword] ) << 16 )), -+ uint32_t(clampu8( r1 + table59T58H[codeword] ) | ( clampu8( g1 + table59T58H[codeword] ) << 8 ) | ( clampu8( b1 + table59T58H[codeword] ) << 16 )), -+ uint32_t(clampu8( r1 - table59T58H[codeword] ) | ( clampu8( g1 - table59T58H[codeword] ) << 8 ) | ( clampu8( b1 - table59T58H[codeword] ) << 16 )) - }; - - for( uint8_t j = 0; j < 4; j++ ) diff --git a/thirdparty/etcpak/patches/pthread-setname.patch b/thirdparty/etcpak/patches/pthread-setname.patch deleted file mode 100644 index e2b009a1b3..0000000000 --- a/thirdparty/etcpak/patches/pthread-setname.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff --git a/thirdparty/etcpak/System.cpp b/thirdparty/etcpak/System.cpp -index 1383d0ecd0..041f2676e8 100644 ---- a/thirdparty/etcpak/System.cpp -+++ b/thirdparty/etcpak/System.cpp -@@ -2,7 +2,6 @@ - #ifdef _WIN32 - # include <windows.h> - #else --# include <pthread.h> - # include <unistd.h> - #endif - -@@ -35,7 +34,7 @@ unsigned int System::CPUCores() - - void System::SetThreadName( std::thread& thread, const char* name ) - { --#ifdef _WIN32 -+#ifdef _MSC_VER - const DWORD MS_VC_EXCEPTION=0x406D1388; - - # pragma pack( push, 8 ) -@@ -62,7 +61,5 @@ void System::SetThreadName( std::thread& thread, const char* name ) - __except(EXCEPTION_EXECUTE_HANDLER) - { - } --#elif !defined(__APPLE__) -- pthread_setname_np( thread.native_handle(), name ); - #endif - } -diff --git a/thirdparty/etcpak/TaskDispatch.cpp b/thirdparty/etcpak/TaskDispatch.cpp -index 7287da4de2..b1ba17953b 100644 ---- a/thirdparty/etcpak/TaskDispatch.cpp -+++ b/thirdparty/etcpak/TaskDispatch.cpp -@@ -1,5 +1,8 @@ - #include <assert.h> - #include <stdio.h> -+#ifndef _MSC_VER -+#include <pthread.h> -+#endif - - #include "Debug.hpp" - #include "System.hpp" -@@ -22,15 +25,19 @@ TaskDispatch::TaskDispatch( size_t workers ) - { - char tmp[16]; - sprintf( tmp, "Worker %zu", i ); --#ifdef __APPLE__ -+#ifdef _MSC_VER -+ auto worker = std::thread( [this]{ Worker(); } ); -+ System::SetThreadName( worker, tmp ); -+#else // Using pthread. - auto worker = std::thread( [this, tmp]{ -+#ifdef __APPLE__ - pthread_setname_np( tmp ); -+#else // Linux or MinGW. -+ pthread_setname_np( pthread_self(), tmp ); -+#endif - Worker(); - } ); --#else -- auto worker = std::thread( [this]{ Worker(); } ); - #endif -- System::SetThreadName( worker, tmp ); - m_workers.emplace_back( std::move( worker ) ); - } - diff --git a/thirdparty/etcpak/patches/windows-mingw-bswap.patch b/thirdparty/etcpak/patches/windows-mingw-bswap.patch deleted file mode 100644 index c09192f573..0000000000 --- a/thirdparty/etcpak/patches/windows-mingw-bswap.patch +++ /dev/null @@ -1,50 +0,0 @@ -diff --git a/thirdparty/etcpak/BlockData.cpp b/thirdparty/etcpak/BlockData.cpp -index a2cd032c5b..bd738085f3 100644 ---- a/thirdparty/etcpak/BlockData.cpp -+++ b/thirdparty/etcpak/BlockData.cpp -@@ -15,7 +15,7 @@ - # include <arm_neon.h> - #endif - --#ifdef __SSE4_1__ -+#if defined __SSE4_1__ || defined __AVX2__ || defined _MSC_VER - # ifdef _MSC_VER - # include <intrin.h> - # include <Windows.h> -@@ -24,12 +24,6 @@ - # else - # include <x86intrin.h> - # endif --#else --# ifndef _MSC_VER --# include <byteswap.h> --# define _bswap(x) bswap_32(x) --# define _bswap64(x) bswap_64(x) --# endif - #endif - - #ifndef _bswap -diff --git a/thirdparty/etcpak/ProcessRGB.cpp b/thirdparty/etcpak/ProcessRGB.cpp -index 220d5c55e2..9dc5a78b67 100644 ---- a/thirdparty/etcpak/ProcessRGB.cpp -+++ b/thirdparty/etcpak/ProcessRGB.cpp -@@ -1,5 +1,6 @@ - #include <array> - #include <string.h> -+#include <limits> - - #ifdef __ARM_NEON - # include <arm_neon.h> -@@ -21,12 +22,6 @@ - # else - # include <x86intrin.h> - # endif --#else --# ifndef _MSC_VER --# include <byteswap.h> --# define _bswap(x) bswap_32(x) --# define _bswap64(x) bswap_64(x) --# endif - #endif - - #ifndef _bswap |