diff options
-rw-r--r-- | core/io/resource_loader.cpp | 51 | ||||
-rw-r--r-- | core/io/resource_loader.h | 9 | ||||
-rw-r--r-- | core/os/condition_variable.h | 60 | ||||
-rw-r--r-- | core/os/mutex.h | 69 | ||||
-rw-r--r-- | editor/editor_node.cpp | 33 | ||||
-rw-r--r-- | editor/editor_node.h | 4 | ||||
-rw-r--r-- | editor/editor_settings.cpp | 9 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 2 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.h | 14 | ||||
-rw-r--r-- | editor/project_manager.cpp | 14 | ||||
-rw-r--r-- | modules/cvtt/image_compress_cvtt.cpp | 23 | ||||
-rw-r--r-- | modules/multiplayer/scene_replication_config.cpp | 12 | ||||
-rw-r--r-- | scene/gui/label.cpp | 231 | ||||
-rw-r--r-- | scene/gui/label.h | 5 | ||||
-rw-r--r-- | thirdparty/README.md | 5 | ||||
-rw-r--r-- | thirdparty/cvtt/ConvectionKernels_BC67.cpp | 339 | ||||
-rw-r--r-- | thirdparty/cvtt/patches/revert_BC6H_reorg.patch | 393 |
17 files changed, 1071 insertions, 202 deletions
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index fc3547261b..22bf8571bf 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -33,6 +33,7 @@ #include "core/config/project_settings.h" #include "core/io/file_access.h" #include "core/io/resource_importer.h" +#include "core/os/condition_variable.h" #include "core/os/os.h" #include "core/string/print_string.h" #include "core/string/translation.h" @@ -233,7 +234,7 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { ThreadLoadTask &load_task = *(ThreadLoadTask *)p_userdata; load_task.loader_id = Thread::get_caller_id(); - if (load_task.semaphore) { + if (load_task.cond_var) { //this is an actual thread, so wait for Ok from semaphore thread_load_semaphore->wait(); //wait until its ok to start loading } @@ -247,7 +248,7 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { } else { load_task.status = THREAD_LOAD_LOADED; } - if (load_task.semaphore) { + if (load_task.cond_var) { if (load_task.start_next && thread_waiting_count > 0) { thread_waiting_count--; //thread loading count remains constant, this ends but another one begins @@ -258,11 +259,9 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { print_lt("END: load count: " + itos(thread_loading_count) + " / wait count: " + itos(thread_waiting_count) + " / suspended count: " + itos(thread_suspended_count) + " / active: " + itos(thread_loading_count - thread_suspended_count)); - for (int i = 0; i < load_task.poll_requests; i++) { - load_task.semaphore->post(); - } - memdelete(load_task.semaphore); - load_task.semaphore = nullptr; + load_task.cond_var->notify_all(); + memdelete(load_task.cond_var); + load_task.cond_var = nullptr; } if (load_task.resource.is_valid()) { @@ -373,7 +372,7 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String & if (load_task.resource.is_null()) { //needs to be loaded in thread - load_task.semaphore = memnew(Semaphore); + load_task.cond_var = memnew(ConditionVariable); if (thread_loading_count < thread_load_max) { thread_loading_count++; thread_load_semaphore->post(); //we have free threads, so allow one @@ -438,9 +437,8 @@ ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) { String local_path = _validate_local_path(p_path); - thread_load_mutex->lock(); + MutexLock thread_load_lock(*thread_load_mutex); if (!thread_load_tasks.has(local_path)) { - thread_load_mutex->unlock(); if (r_error) { *r_error = ERR_INVALID_PARAMETER; } @@ -449,13 +447,21 @@ Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_e ThreadLoadTask &load_task = thread_load_tasks[local_path]; - //semaphore still exists, meaning it's still loading, request poll - Semaphore *semaphore = load_task.semaphore; - if (semaphore) { - load_task.poll_requests++; + if (!load_task.cond_var && load_task.status == THREAD_LOAD_IN_PROGRESS) { + // A condition variable was never created for this task. + // That happens when a load has been initiated with subthreads disabled, + // but now another load thread needs to interact with this one (either + // because of subthreads being used this time, or because it's simply a + // threaded load running on a different thread). + // Since we want to be notified when the load ends, we must create the + // condition variable now. + load_task.cond_var = memnew(ConditionVariable); + } + //cond var still exists, meaning it's still loading, request poll + if (load_task.cond_var) { { - // As we got a semaphore, this means we are going to have to wait + // As we got a cond var, this means we are going to have to wait // until the sub-resource is done loading // // As this thread will become 'blocked' we should "exchange" its @@ -477,14 +483,13 @@ Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_e print_lt("GET: load count: " + itos(thread_loading_count) + " / wait count: " + itos(thread_waiting_count) + " / suspended count: " + itos(thread_suspended_count) + " / active: " + itos(thread_loading_count - thread_suspended_count)); } - thread_load_mutex->unlock(); - semaphore->wait(); - thread_load_mutex->lock(); + do { + load_task.cond_var->wait(thread_load_lock); + } while (load_task.cond_var); // In case of spurious wakeup. thread_suspended_count--; if (!thread_load_tasks.has(local_path)) { //may have been erased during unlock and this was always an invalid call - thread_load_mutex->unlock(); if (r_error) { *r_error = ERR_INVALID_PARAMETER; } @@ -507,8 +512,6 @@ Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_e thread_load_tasks.erase(local_path); } - thread_load_mutex->unlock(); - return resource; } @@ -1067,7 +1070,7 @@ void ResourceLoader::remove_custom_loaders() { } void ResourceLoader::initialize() { - thread_load_mutex = memnew(Mutex); + thread_load_mutex = memnew(SafeBinaryMutex<BINARY_MUTEX_TAG>); thread_load_max = OS::get_singleton()->get_processor_count(); thread_loading_count = 0; thread_waiting_count = 0; @@ -1090,7 +1093,9 @@ bool ResourceLoader::create_missing_resources_if_class_unavailable = false; bool ResourceLoader::abort_on_missing_resource = true; bool ResourceLoader::timestamp_on_load = false; -Mutex *ResourceLoader::thread_load_mutex = nullptr; +template <> +thread_local uint32_t SafeBinaryMutex<ResourceLoader::BINARY_MUTEX_TAG>::count = 0; +SafeBinaryMutex<ResourceLoader::BINARY_MUTEX_TAG> *ResourceLoader::thread_load_mutex = nullptr; HashMap<String, ResourceLoader::ThreadLoadTask> ResourceLoader::thread_load_tasks; Semaphore *ResourceLoader::thread_load_semaphore = nullptr; diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index c47b6c950a..72c1f90653 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -37,6 +37,8 @@ #include "core/os/semaphore.h" #include "core/os/thread.h" +class ConditionVariable; + class ResourceFormatLoader : public RefCounted { GDCLASS(ResourceFormatLoader, RefCounted); @@ -105,6 +107,8 @@ public: THREAD_LOAD_LOADED }; + static const int BINARY_MUTEX_TAG = 1; + private: static Ref<ResourceFormatLoader> loader[MAX_LOADERS]; static int loader_count; @@ -136,7 +140,7 @@ private: struct ThreadLoadTask { Thread *thread = nullptr; Thread::ID loader_id = 0; - Semaphore *semaphore = nullptr; + ConditionVariable *cond_var = nullptr; String local_path; String remapped_path; String type_hint; @@ -149,12 +153,11 @@ private: bool use_sub_threads = false; bool start_next = true; int requests = 0; - int poll_requests = 0; HashSet<String> sub_tasks; }; static void _thread_load_function(void *p_userdata); - static Mutex *thread_load_mutex; + static SafeBinaryMutex<BINARY_MUTEX_TAG> *thread_load_mutex; static HashMap<String, ThreadLoadTask> thread_load_tasks; static Semaphore *thread_load_semaphore; static int thread_waiting_count; diff --git a/core/os/condition_variable.h b/core/os/condition_variable.h new file mode 100644 index 0000000000..6037ff327d --- /dev/null +++ b/core/os/condition_variable.h @@ -0,0 +1,60 @@ +/**************************************************************************/ +/* condition_variable.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef CONDITION_VARIABLE_H +#define CONDITION_VARIABLE_H + +#include <condition_variable> + +// An object one or multiple threads can wait on a be notified by some other. +// Normally, you want to use a semaphore for such scenarios, but when the +// condition is something different than a count being greater than zero +// (which is the built-in logic in a semaphore) or you want to provide your +// own mutex to tie the wait-notify to some other behavior, you need to use this. + +class ConditionVariable { + mutable std::condition_variable condition; + +public: + template <class BinaryMutexT> + _ALWAYS_INLINE_ void wait(const MutexLock<BinaryMutexT> &p_lock) const { + condition.wait(const_cast<std::unique_lock<std::mutex> &>(p_lock.lock)); + } + + _ALWAYS_INLINE_ void notify_one() const { + condition.notify_one(); + } + + _ALWAYS_INLINE_ void notify_all() const { + condition.notify_all(); + } +}; + +#endif // CONDITION_VARIABLE_H diff --git a/core/os/mutex.h b/core/os/mutex.h index ceedcb235a..90cc1632e8 100644 --- a/core/os/mutex.h +++ b/core/os/mutex.h @@ -31,12 +31,20 @@ #ifndef MUTEX_H #define MUTEX_H +#include "core/error/error_macros.h" #include "core/typedefs.h" #include <mutex> +template <class MutexT> +class MutexLock; + template <class StdMutexT> class MutexImpl { + friend class MutexLock<MutexImpl<StdMutexT>>; + + using StdMutexType = StdMutexT; + mutable StdMutexT mutex; public: @@ -53,18 +61,65 @@ public: } }; +// A very special kind of mutex, used in scenarios where these +// requirements hold at the same time: +// - Must be used with a condition variable (only binary mutexes are suitable). +// - Must have recursive semnantics (or simulate, as this one does). +// The implementation keeps the lock count in TS. Therefore, only +// one object of each version of the template can exists; hence the Tag argument. +// Tags must be unique across the Godot codebase. +// Also, don't forget to declare the thread_local variable on each use. +template <int Tag> +class SafeBinaryMutex { + friend class MutexLock<SafeBinaryMutex>; + + using StdMutexType = std::mutex; + + mutable std::mutex mutex; + static thread_local uint32_t count; + +public: + _ALWAYS_INLINE_ void lock() const { + if (++count == 1) { + mutex.lock(); + } + } + + _ALWAYS_INLINE_ void unlock() const { + DEV_ASSERT(count); + if (--count == 0) { + mutex.unlock(); + } + } + + _ALWAYS_INLINE_ bool try_lock() const { + if (count) { + count++; + return true; + } else { + if (mutex.try_lock()) { + count++; + return true; + } else { + return false; + } + } + } + + ~SafeBinaryMutex() { + DEV_ASSERT(!count); + } +}; + template <class MutexT> class MutexLock { - const MutexT &mutex; + friend class ConditionVariable; + + std::unique_lock<typename MutexT::StdMutexType> lock; public: _ALWAYS_INLINE_ explicit MutexLock(const MutexT &p_mutex) : - mutex(p_mutex) { - mutex.lock(); - } - - _ALWAYS_INLINE_ ~MutexLock() { - mutex.unlock(); + lock(p_mutex.mutex) { } }; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index cf1c1016fa..6fcf092834 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -3526,7 +3526,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, // Only try to load the script if it has a name. Else, the plugin has no init script. if (script_path.length() > 0) { script_path = addon_path.get_base_dir().path_join(script_path); - scr = ResourceLoader::load(script_path); + scr = ResourceLoader::load(script_path, "Script", ResourceFormatLoader::CACHE_MODE_IGNORE); if (scr.is_null()) { show_warning(vformat(TTR("Unable to load addon script from path: '%s'."), script_path)); @@ -3984,6 +3984,15 @@ HashMap<StringName, Variant> EditorNode::get_modified_properties_for_node(Node * return modified_property_map; } +void EditorNode::update_ownership_table_for_addition_node_ancestors(Node *p_current_node, HashMap<Node *, Node *> &p_ownership_table) { + p_ownership_table.insert(p_current_node, p_current_node->get_owner()); + + for (int i = 0; i < p_current_node->get_child_count(); i++) { + Node *child = p_current_node->get_child(i); + update_ownership_table_for_addition_node_ancestors(child, p_ownership_table); + } +} + void EditorNode::update_diff_data_for_node( Node *p_edited_scene, Node *p_root, @@ -4079,6 +4088,16 @@ void EditorNode::update_diff_data_for_node( if (node_3d) { new_additive_node_entry.transform_3d = node_3d->get_relative_transform(node_3d->get_parent()); } + + // Gathers the ownership of all ancestor nodes for later use. + HashMap<Node *, Node *> ownership_table; + for (int i = 0; i < p_node->get_child_count(); i++) { + Node *child = p_node->get_child(i); + update_ownership_table_for_addition_node_ancestors(child, ownership_table); + } + + new_additive_node_entry.ownership_table = ownership_table; + p_addition_list.push_back(new_additive_node_entry); return; @@ -6203,6 +6222,18 @@ void EditorNode::reload_instances_with_path_in_edited_scenes(const String &p_ins node_3d->set_transform(additive_node_entry.transform_3d); } } + + // Restore the ownership of its ancestors + for (KeyValue<Node *, Node *> &E : additive_node_entry.ownership_table) { + Node *current_ancestor = E.key; + Node *ancestor_owner = E.value; + + if (ancestor_owner == original_node) { + ancestor_owner = instantiated_node; + } + + current_ancestor->set_owner(ancestor_owner); + } } // Restore the selection. diff --git a/editor/editor_node.h b/editor/editor_node.h index eefe45ca1f..8ad5969249 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -832,6 +832,8 @@ public: // Used if the original parent node is lost Transform2D transform_2d; Transform3D transform_3d; + // Used to keep track of the ownership of all ancestor nodes so they can be restored later. + HashMap<Node *, Node *> ownership_table; }; struct ConnectionWithNodePath { @@ -846,6 +848,8 @@ public: List<Node::GroupInfo> groups; }; + void update_ownership_table_for_addition_node_ancestors(Node *p_current_node, HashMap<Node *, Node *> &p_ownership_table); + void update_diff_data_for_node( Node *p_edited_scene, Node *p_root, diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 41d175fcd1..037bfbfd99 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -746,7 +746,16 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // TRANSLATORS: Project Manager here refers to the tool used to create/manage Godot projects. EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "project_manager/sorting_order", 0, "Last Edited,Name,Path") + +#if defined(WEB_ENABLED) + // Web platform only supports `gl_compatibility`. + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_NONE, "project_manager/default_renderer", "gl_compatibility", "forward_plus,mobile,gl_compatibility") +#elif defined(ANDROID_ENABLED) + // Use more suitable rendering method by default. + EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_NONE, "project_manager/default_renderer", "mobile", "forward_plus,mobile,gl_compatibility") +#else EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_NONE, "project_manager/default_renderer", "forward_plus", "forward_plus,mobile,gl_compatibility") +#endif if (p_extra_config.is_valid()) { if (p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) { diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 32c16255dd..3c67aa6cd5 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1613,7 +1613,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/normalize_mesh", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.normalize_mesh)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/mode", PROPERTY_HINT_ENUM, "Voxel,Tetrahedron", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), static_cast<int>(decomposition_default.mode))); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/convexhull_approximation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.convexhull_approximation)); - r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_convex_hulls", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_convex_hulls)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "decomposition/max_convex_hulls", PROPERTY_HINT_RANGE, "1,100,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.max_convex_hulls)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "decomposition/project_hull_vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), decomposition_default.project_hull_vertices)); // Primitives: Box, Sphere, Cylinder, Capsule. diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index d6d83a45d3..24d2569420 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -373,7 +373,7 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> } if (p_options.has(SNAME("decomposition/max_convex_hulls"))) { - decomposition_settings.max_convex_hulls = p_options[SNAME("decomposition/max_convex_hulls")]; + decomposition_settings.max_convex_hulls = MAX(1, (int)p_options[SNAME("decomposition/max_convex_hulls")]); } if (p_options.has(SNAME("decomposition/project_hull_vertices"))) { @@ -410,6 +410,8 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> box.instantiate(); if (p_options.has(SNAME("primitive/size"))) { box->set_size(p_options[SNAME("primitive/size")].operator Vector3() * p_applied_root_scale); + } else { + box->set_size(Vector3(2, 2, 2) * p_applied_root_scale); } Vector<Ref<Shape3D>> shapes; @@ -421,6 +423,8 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> sphere.instantiate(); if (p_options.has(SNAME("primitive/radius"))) { sphere->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale); + } else { + sphere->set_radius(1.0f * p_applied_root_scale); } Vector<Ref<Shape3D>> shapes; @@ -431,9 +435,13 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> cylinder.instantiate(); if (p_options.has(SNAME("primitive/height"))) { cylinder->set_height(p_options[SNAME("primitive/height")].operator float() * p_applied_root_scale); + } else { + cylinder->set_height(1.0f * p_applied_root_scale); } if (p_options.has(SNAME("primitive/radius"))) { cylinder->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale); + } else { + cylinder->set_radius(1.0f * p_applied_root_scale); } Vector<Ref<Shape3D>> shapes; @@ -444,9 +452,13 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> capsule.instantiate(); if (p_options.has(SNAME("primitive/height"))) { capsule->set_height(p_options[SNAME("primitive/height")].operator float() * p_applied_root_scale); + } else { + capsule->set_height(1.0f * p_applied_root_scale); } if (p_options.has(SNAME("primitive/radius"))) { capsule->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale); + } else { + capsule->set_radius(1.0f * p_applied_root_scale); } Vector<Ref<Shape3D>> shapes; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index c00ef326d0..2f3f4dd2e1 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -911,33 +911,41 @@ public: Button *rs_button = memnew(CheckBox); rs_button->set_button_group(renderer_button_group); rs_button->set_text(TTR("Forward+")); +#if defined(WEB_ENABLED) + rs_button->set_disabled(true); +#endif rs_button->set_meta(SNAME("rendering_method"), "forward_plus"); rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected)); rvb->add_child(rs_button); if (default_renderer_type == "forward_plus") { rs_button->set_pressed(true); } - rs_button = memnew(CheckBox); rs_button->set_button_group(renderer_button_group); rs_button->set_text(TTR("Mobile")); +#if defined(WEB_ENABLED) + rs_button->set_disabled(true); +#endif rs_button->set_meta(SNAME("rendering_method"), "mobile"); rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected)); rvb->add_child(rs_button); if (default_renderer_type == "mobile") { rs_button->set_pressed(true); } - rs_button = memnew(CheckBox); rs_button->set_button_group(renderer_button_group); rs_button->set_text(TTR("Compatibility")); +#if !defined(GLES3_ENABLED) + rs_button->set_disabled(true); +#endif rs_button->set_meta(SNAME("rendering_method"), "gl_compatibility"); rs_button->connect("pressed", callable_mp(this, &ProjectDialog::_renderer_selected)); rvb->add_child(rs_button); +#if defined(GLES3_ENABLED) if (default_renderer_type == "gl_compatibility") { rs_button->set_pressed(true); } - +#endif rshc->add_child(memnew(VSeparator)); // Right hand side, used for text explaining each choice. diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp index f19228cb18..ad70772270 100644 --- a/modules/cvtt/image_compress_cvtt.cpp +++ b/modules/cvtt/image_compress_cvtt.cpp @@ -30,8 +30,8 @@ #include "image_compress_cvtt.h" +#include "core/object/worker_thread_pool.h" #include "core/os/os.h" -#include "core/os/thread.h" #include "core/string/print_string.h" #include "core/templates/safe_refcount.h" @@ -129,6 +129,18 @@ static void _digest_row_task(const CVTTCompressionJobParams &p_job_params, const } } +static void _digest_job_queue(void *p_job_queue, uint32_t p_index) { + CVTTCompressionJobQueue *job_queue = static_cast<CVTTCompressionJobQueue *>(p_job_queue); + uint32_t num_tasks = job_queue->num_tasks; + uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count(); + uint32_t start = p_index * num_tasks / total_threads; + uint32_t end = (p_index + 1 == total_threads) ? num_tasks : ((p_index + 1) * num_tasks / total_threads); + + for (uint32_t i = start; i < end; i++) { + _digest_row_task(job_queue->job_params, job_queue->job_tasks[i]); + } +} + void image_compress_cvtt(Image *p_image, Image::UsedChannels p_channels) { if (p_image->get_format() >= Image::FORMAT_BPTC_RGBA) { return; //do not compress, already compressed @@ -220,7 +232,7 @@ void image_compress_cvtt(Image *p_image, Image::UsedChannels p_channels) { row_task.in_mm_bytes = in_bytes; row_task.out_mm_bytes = out_bytes; - _digest_row_task(job_queue.job_params, row_task); + tasks.push_back(row_task); out_bytes += 16 * (bw / 4); } @@ -230,6 +242,13 @@ void image_compress_cvtt(Image *p_image, Image::UsedChannels p_channels) { h = MAX(h / 2, 1); } + const CVTTCompressionRowTask *tasks_rb = tasks.ptr(); + + job_queue.job_tasks = &tasks_rb[0]; + job_queue.num_tasks = static_cast<uint32_t>(tasks.size()); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_native_group_task(&_digest_job_queue, &job_queue, WorkerThreadPool::get_singleton()->get_thread_count(), -1, true, SNAME("CVTT Compress")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + p_image->set_data(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); } diff --git a/modules/multiplayer/scene_replication_config.cpp b/modules/multiplayer/scene_replication_config.cpp index c8621e7357..f8006228de 100644 --- a/modules/multiplayer/scene_replication_config.cpp +++ b/modules/multiplayer/scene_replication_config.cpp @@ -114,6 +114,8 @@ void SceneReplicationConfig::add_property(const NodePath &p_path, int p_index) { if (p_index < 0 || p_index == properties.size()) { properties.push_back(ReplicationProperty(p_path)); + sync_props.push_back(p_path); + spawn_props.push_back(p_path); return; } @@ -126,6 +128,16 @@ void SceneReplicationConfig::add_property(const NodePath &p_path, int p_index) { c++; } properties.insert_before(I, ReplicationProperty(p_path)); + sync_props.clear(); + spawn_props.clear(); + for (const ReplicationProperty &prop : properties) { + if (prop.sync) { + sync_props.push_back(p_path); + } + if (prop.spawn) { + spawn_props.push_back(p_path); + } + } } void SceneReplicationConfig::remove_property(const NodePath &p_path) { diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 81426158a2..59f7511894 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -86,7 +86,7 @@ int Label::get_line_height(int p_line) const { } } -bool Label::_shape() { +void Label::_shape() { Ref<StyleBox> style = theme_cache.normal_style; int width = (get_size().width - style->get_minimum_size().width); @@ -101,7 +101,7 @@ bool Label::_shape() { } const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font; int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size; - ERR_FAIL_COND_V(font.is_null(), true); + ERR_FAIL_COND(font.is_null()); String txt = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text; if (visible_chars >= 0 && visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { txt = txt.substr(0, visible_chars); @@ -121,7 +121,6 @@ bool Label::_shape() { dirty = false; font_dirty = false; lines_dirty = true; - // Note for future maintainers: forgetting stable width here (e.g., setting it to -1) may fix still undiscovered bugs. } if (lines_dirty) { @@ -129,140 +128,126 @@ bool Label::_shape() { TS->free_rid(lines_rid[i]); } lines_rid.clear(); - } - - Size2i prev_minsize = minsize; - minsize = Size2(); - bool can_process_lines = false; - if (xl_text.length() == 0) { - can_process_lines = true; - lines_dirty = false; - } else { - // With autowrap on or off with trimming enabled, we won't compute the minimum size until width is stable - // (two shape requests in a row with the same width.) This avoids situations in which the initial width is - // very narrow and the label would break text into many very short lines, causing a very tall label that can - // leave a deformed container. In the remaining case (namely, autowrap off and no trimming), the label is - // free to dictate its own width, something that will be taken advtantage of. - bool can_dictate_width = autowrap_mode == TextServer::AUTOWRAP_OFF && overrun_behavior == TextServer::OVERRUN_NO_TRIMMING; - bool is_width_stable = get_size().width == stable_width; - can_process_lines = can_dictate_width || is_width_stable; - stable_width = get_size().width; - - if (can_process_lines) { - if (lines_dirty) { - BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; - switch (autowrap_mode) { - case TextServer::AUTOWRAP_WORD_SMART: - autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; - break; - case TextServer::AUTOWRAP_WORD: - autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; - break; - case TextServer::AUTOWRAP_ARBITRARY: - autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; - break; - case TextServer::AUTOWRAP_OFF: - break; - } - autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES; + BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; + switch (autowrap_mode) { + case TextServer::AUTOWRAP_WORD_SMART: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_WORD: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_ARBITRARY: + autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_OFF: + break; + } + autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES; - PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); - for (int i = 0; i < line_breaks.size(); i = i + 2) { - RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); - lines_rid.push_back(line); - } - } + PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); + for (int i = 0; i < line_breaks.size(); i = i + 2) { + RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); + lines_rid.push_back(line); + } + } - if (can_dictate_width) { - for (int i = 0; i < lines_rid.size(); i++) { - if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) { - minsize.width = TS->shaped_text_get_size(lines_rid[i]).x; - } - } + if (xl_text.length() == 0) { + minsize = Size2(1, get_line_height()); + return; + } - width = (minsize.width - style->get_minimum_size().width); + if (autowrap_mode == TextServer::AUTOWRAP_OFF) { + minsize.width = 0.0f; + for (int i = 0; i < lines_rid.size(); i++) { + if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) { + minsize.width = TS->shaped_text_get_size(lines_rid[i]).x; } + } + } - if (lines_dirty) { - BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM; - switch (overrun_behavior) { - case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS: - overrun_flags.set_flag(TextServer::OVERRUN_TRIM); - overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); - overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); - break; - case TextServer::OVERRUN_TRIM_ELLIPSIS: - overrun_flags.set_flag(TextServer::OVERRUN_TRIM); - overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); - break; - case TextServer::OVERRUN_TRIM_WORD: - overrun_flags.set_flag(TextServer::OVERRUN_TRIM); - overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); - break; - case TextServer::OVERRUN_TRIM_CHAR: - overrun_flags.set_flag(TextServer::OVERRUN_TRIM); - break; - case TextServer::OVERRUN_NO_TRIMMING: - break; - } + if (lines_dirty) { + BitField<TextServer::TextOverrunFlag> overrun_flags = TextServer::OVERRUN_NO_TRIM; + switch (overrun_behavior) { + case TextServer::OVERRUN_TRIM_WORD_ELLIPSIS: + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); + break; + case TextServer::OVERRUN_TRIM_ELLIPSIS: + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_ADD_ELLIPSIS); + break; + case TextServer::OVERRUN_TRIM_WORD: + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + overrun_flags.set_flag(TextServer::OVERRUN_TRIM_WORD_ONLY); + break; + case TextServer::OVERRUN_TRIM_CHAR: + overrun_flags.set_flag(TextServer::OVERRUN_TRIM); + break; + case TextServer::OVERRUN_NO_TRIMMING: + break; + } - // Fill after min_size calculation. + // Fill after min_size calculation. - int visible_lines = get_visible_line_count(); - if (autowrap_mode != TextServer::AUTOWRAP_OFF) { - bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size(); - if (lines_hidden) { - overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS); - } - if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - for (int i = 0; i < lines_rid.size(); i++) { - if (i < visible_lines - 1 || lines_rid.size() == 1) { - TS->shaped_text_fit_to_width(lines_rid[i], width); - } else if (i == (visible_lines - 1)) { - TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags); - } - } - } else if (lines_hidden) { + if (autowrap_mode != TextServer::AUTOWRAP_OFF) { + int visible_lines = get_visible_line_count(); + bool lines_hidden = visible_lines > 0 && visible_lines < lines_rid.size(); + if (lines_hidden) { + overrun_flags.set_flag(TextServer::OVERRUN_ENFORCE_ELLIPSIS); + } + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { + for (int i = 0; i < lines_rid.size(); i++) { + if (i < visible_lines - 1 || lines_rid.size() == 1) { + TS->shaped_text_fit_to_width(lines_rid[i], width); + } else if (i == (visible_lines - 1)) { TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags); } - } else { - // Autowrap disabled. - for (int i = 0; i < lines_rid.size(); i++) { - if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - TS->shaped_text_fit_to_width(lines_rid[i], width); - overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE); - TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); - TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); - } else { - TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); - } - } } - - int last_line = MIN(lines_rid.size(), visible_lines + lines_skipped); - int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing; - for (int64_t i = lines_skipped; i < last_line; i++) { - minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; - } - - lines_dirty = false; + } else if (lines_hidden) { + TS->shaped_text_overrun_trim_to_width(lines_rid[visible_lines - 1], width, overrun_flags); } } else { - callable_mp(this, &Label::_shape).call_deferred(); + // Autowrap disabled. + for (int i = 0; i < lines_rid.size(); i++) { + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { + TS->shaped_text_fit_to_width(lines_rid[i], width); + overrun_flags.set_flag(TextServer::OVERRUN_JUSTIFICATION_AWARE); + TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); + TS->shaped_text_fit_to_width(lines_rid[i], width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_CONSTRAIN_ELLIPSIS); + } else { + TS->shaped_text_overrun_trim_to_width(lines_rid[i], width, overrun_flags); + } + } } + lines_dirty = false; } - if (draw_pending) { - queue_redraw(); - draw_pending = false; - } + _update_visible(); - if (minsize != prev_minsize) { + if (autowrap_mode == TextServer::AUTOWRAP_OFF || !clip || overrun_behavior == TextServer::OVERRUN_NO_TRIMMING) { update_minimum_size(); } +} + +void Label::_update_visible() { + int line_spacing = settings.is_valid() ? settings->get_line_spacing() : theme_cache.line_spacing; + Ref<StyleBox> style = theme_cache.normal_style; + int lines_visible = lines_rid.size(); + + if (max_lines_visible >= 0 && lines_visible > max_lines_visible) { + lines_visible = max_lines_visible; + } - return can_process_lines; + minsize.height = 0; + int last_line = MIN(lines_rid.size(), lines_visible + lines_skipped); + for (int64_t i = lines_skipped; i < last_line; i++) { + minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; + if (minsize.height > (get_size().height - style->get_minimum_size().height + line_spacing)) { + break; + } + } } inline void draw_glyph(const Glyph &p_gl, const RID &p_canvas, const Color &p_font_color, const Vector2 &p_ofs) { @@ -372,11 +357,7 @@ void Label::_notification(int p_what) { } if (dirty || font_dirty || lines_dirty) { - if (!_shape()) { - // There will be another pass. - draw_pending = true; - break; - } + _shape(); } RID ci = get_canvas_item(); @@ -619,8 +600,6 @@ void Label::_notification(int p_what) { } ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + vsep + line_spacing; } - - draw_pending = false; } break; case NOTIFICATION_THEME_CHANGED: { @@ -912,7 +891,7 @@ void Label::set_lines_skipped(int p_lines) { } lines_skipped = p_lines; - lines_dirty = true; + _update_visible(); queue_redraw(); } @@ -926,7 +905,7 @@ void Label::set_max_lines_visible(int p_lines) { } max_lines_visible = p_lines; - lines_dirty = true; + _update_visible(); queue_redraw(); } diff --git a/scene/gui/label.h b/scene/gui/label.h index 36b85f7af8..2350525236 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -46,7 +46,6 @@ private: bool clip = false; TextServer::OverrunBehavior overrun_behavior = TextServer::OVERRUN_NO_TRIMMING; Size2 minsize; - real_t stable_width = -1; bool uppercase = false; bool lines_dirty = true; @@ -65,7 +64,6 @@ private: float visible_ratio = 1.0; int lines_skipped = 0; int max_lines_visible = -1; - bool draw_pending = false; Ref<LabelSettings> settings; @@ -83,7 +81,8 @@ private: int font_shadow_outline_size; } theme_cache; - bool _shape(); + void _update_visible(); + void _shape(); void _invalidate(); protected: diff --git a/thirdparty/README.md b/thirdparty/README.md index f883a3a6da..92e0a91596 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -70,6 +70,11 @@ Files extracted from upstream source: - all .cpp, .h, and .txt files except the folders MakeTables and etc2packer. +Changes related to BC6H packing and unpacking made upstream in +https://github.com/elasota/cvtt/commit/2e4b6b2747aec11f4cc6dd09ef43fa8ce769f6e2 +have been removed as they caused massive quality regressions. Apply the patches +in the `patches/` folder when syncing on newer upstream commits. + ## doctest diff --git a/thirdparty/cvtt/ConvectionKernels_BC67.cpp b/thirdparty/cvtt/ConvectionKernels_BC67.cpp index 021d658c08..011f51570b 100644 --- a/thirdparty/cvtt/ConvectionKernels_BC67.cpp +++ b/thirdparty/cvtt/ConvectionKernels_BC67.cpp @@ -76,6 +76,205 @@ namespace cvtt }; } + namespace BC6HData + { + enum EField + { + NA, // N/A + M, // Mode + D, // Shape + RW, + RX, + RY, + RZ, + GW, + GX, + GY, + GZ, + BW, + BX, + BY, + BZ, + }; + + struct ModeDescriptor + { + EField m_eField; + uint8_t m_uBit; + }; + + const ModeDescriptor g_modeDescriptors[14][82] = + { + { // Mode 1 (0x00) - 10 5 5 5 + { M, 0 },{ M, 1 },{ GY, 4 },{ BY, 4 },{ BZ, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 2 (0x01) - 7 6 6 6 + { M, 0 },{ M, 1 },{ GY, 5 },{ GZ, 4 },{ GZ, 5 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 3 (0x02) - 11 5 4 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RW,10 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 4 (0x06) - 11 4 5 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GW,10 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 0 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ GY, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 5 (0x0a) - 11 4 4 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 }, + { BY, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BW,10 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 1 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ BZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 6 (0x0e) - 9 5 5 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 7 (0x12) - 8 6 5 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ GZ, 4 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 3 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 8 (0x16) - 8 5 6 5 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 0 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ GZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 9 (0x1a) - 8 5 5 6 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ BY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 10 (0x1e) - 6 6 6 6 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ GZ, 4 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GY, 5 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ GZ, 5 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, + { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, + { D, 3 },{ D, 4 }, + }, + + { // Mode 11 (0x03) - 10 10 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RX, 9 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GX, 9 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BX, 9 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 12 (0x07) - 11 9 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 13 (0x0b) - 12 8 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, + { RX, 5 },{ RX, 6 },{ RX, 7 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, + { GX, 5 },{ GX, 6 },{ GX, 7 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, + { BX, 5 },{ BX, 6 },{ BX, 7 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + + { // Mode 14 (0x0f) - 16 4 + { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, + { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, + { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, + { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,15 }, + { RW,14 },{ RW,13 },{ RW,12 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,15 }, + { GW,14 },{ GW,13 },{ GW,12 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,15 }, + { BW,14 },{ BW,13 },{ BW,12 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, + { NA, 0 },{ NA, 0 }, + }, + }; + } + namespace BC7Data { enum AlphaMode @@ -2998,9 +3197,9 @@ void cvtt::Internal::BC6HComputer::Pack(uint32_t flags, const PixelBlockF16* inp const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode]; - BC6H_IO::WriteFunc_t writeFunc = BC6H_IO::g_writeFuncs[mode]; + const BC6HData::ModeDescriptor *desc = BC6HData::g_modeDescriptors[mode]; - const int headerBits = modeInfo.m_partitioned ? 82 : 65; + const size_t headerBits = modeInfo.m_partitioned ? 82 : 65; for (int subset = 0; subset < 2; subset++) { @@ -3017,16 +3216,58 @@ void cvtt::Internal::BC6HComputer::Pack(uint32_t flags, const PixelBlockF16* inp uint16_t modeID = modeInfo.m_modeID; PackingVector pv; + pv.Init(); - { - uint32_t header[3]; - writeFunc(header, modeID, partition, - eps[0][0][0], eps[0][1][0], eps[1][0][0], eps[1][1][0], - eps[0][0][1], eps[0][1][1], eps[1][0][1], eps[1][1][1], - eps[0][0][2], eps[0][1][2], eps[1][0][2], eps[1][1][2] - ); - - pv.InitPacked(header, headerBits); + for (size_t i = 0; i < headerBits; i++) { + int32_t codedValue = 0; + switch (desc[i].m_eField) { + case BC6HData::M: + codedValue = modeID; + break; + case BC6HData::D: + codedValue = partition; + break; + case BC6HData::RW: + codedValue = eps[0][0][0]; + break; + case BC6HData::RX: + codedValue = eps[0][1][0]; + break; + case BC6HData::RY: + codedValue = eps[1][0][0]; + break; + case BC6HData::RZ: + codedValue = eps[1][1][0]; + break; + case BC6HData::GW: + codedValue = eps[0][0][1]; + break; + case BC6HData::GX: + codedValue = eps[0][1][1]; + break; + case BC6HData::GY: + codedValue = eps[1][0][1]; + break; + case BC6HData::GZ: + codedValue = eps[1][1][1]; + break; + case BC6HData::BW: + codedValue = eps[0][0][2]; + break; + case BC6HData::BX: + codedValue = eps[0][1][2]; + break; + case BC6HData::BY: + codedValue = eps[1][0][2]; + break; + case BC6HData::BZ: + codedValue = eps[1][1][2]; + break; + default: + assert(false); + break; + } + pv.Pack(static_cast<uint16_t>((codedValue >> desc[i].m_uBit) & 1), 1); } int fixupIndex1 = 0; @@ -3058,11 +3299,14 @@ void cvtt::Internal::BC6HComputer::SignExtendSingle(int &v, int bits) void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_t *pBC, bool isSigned) { + UnpackingVector pv; + pv.Init(pBC); + int numModeBits = 2; - int modeBits = pBC[0] & 0x3; + int modeBits = pv.Unpack(2); if (modeBits != 0 && modeBits != 1) { - modeBits = pBC[0] & 0x1f; + modeBits |= pv.Unpack(3) << 2; numModeBits += 3; } @@ -3088,10 +3332,10 @@ void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_ } const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode]; - const int headerBits = modeInfo.m_partitioned ? 82 : 65; - const BC6H_IO::ReadFunc_t readFunc = BC6H_IO::g_readFuncs[mode]; + const size_t headerBits = modeInfo.m_partitioned ? 82 : 65; + const BC6HData::ModeDescriptor *desc = BC6HData::g_modeDescriptors[mode]; - uint16_t partition = 0; + int32_t partition = 0; int32_t eps[2][2][3]; for (int subset = 0; subset < 2; subset++) @@ -3099,24 +3343,55 @@ void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_ for (int ch = 0; ch < 3; ch++) eps[subset][epi][ch] = 0; - UnpackingVector pv; - pv.Init(pBC); - - { - uint32_t header[3]; - uint16_t codedEPs[2][2][3]; - pv.UnpackStart(header, headerBits); + for (size_t i = numModeBits; i < headerBits; i++) { + int32_t *pCodedValue = NULL; - readFunc(header, partition, - codedEPs[0][0][0], codedEPs[0][1][0], codedEPs[1][0][0], codedEPs[1][1][0], - codedEPs[0][0][1], codedEPs[0][1][1], codedEPs[1][0][1], codedEPs[1][1][1], - codedEPs[0][0][2], codedEPs[0][1][2], codedEPs[1][0][2], codedEPs[1][1][2] - ); + switch (desc[i].m_eField) { + case BC6HData::D: + pCodedValue = &partition; + break; + case BC6HData::RW: + pCodedValue = &eps[0][0][0]; + break; + case BC6HData::RX: + pCodedValue = &eps[0][1][0]; + break; + case BC6HData::RY: + pCodedValue = &eps[1][0][0]; + break; + case BC6HData::RZ: + pCodedValue = &eps[1][1][0]; + break; + case BC6HData::GW: + pCodedValue = &eps[0][0][1]; + break; + case BC6HData::GX: + pCodedValue = &eps[0][1][1]; + break; + case BC6HData::GY: + pCodedValue = &eps[1][0][1]; + break; + case BC6HData::GZ: + pCodedValue = &eps[1][1][1]; + break; + case BC6HData::BW: + pCodedValue = &eps[0][0][2]; + break; + case BC6HData::BX: + pCodedValue = &eps[0][1][2]; + break; + case BC6HData::BY: + pCodedValue = &eps[1][0][2]; + break; + case BC6HData::BZ: + pCodedValue = &eps[1][1][2]; + break; + default: + assert(false); + break; + } - for (int subset = 0; subset < 2; subset++) - for (int epi = 0; epi < 2; epi++) - for (int ch = 0; ch < 3; ch++) - eps[subset][epi][ch] = codedEPs[subset][epi][ch]; + (*pCodedValue) |= pv.Unpack(1) << desc[i].m_uBit; } uint16_t modeID = modeInfo.m_modeID; diff --git a/thirdparty/cvtt/patches/revert_BC6H_reorg.patch b/thirdparty/cvtt/patches/revert_BC6H_reorg.patch new file mode 100644 index 0000000000..11f9b9db46 --- /dev/null +++ b/thirdparty/cvtt/patches/revert_BC6H_reorg.patch @@ -0,0 +1,393 @@ +diff --git a/thirdparty/cvtt/ConvectionKernels_BC67.cpp b/thirdparty/cvtt/ConvectionKernels_BC67.cpp +index 021d658c08..011f51570b 100644 +--- a/thirdparty/cvtt/ConvectionKernels_BC67.cpp ++++ b/thirdparty/cvtt/ConvectionKernels_BC67.cpp +@@ -76,6 +76,205 @@ namespace cvtt + }; + } + ++ namespace BC6HData ++ { ++ enum EField ++ { ++ NA, // N/A ++ M, // Mode ++ D, // Shape ++ RW, ++ RX, ++ RY, ++ RZ, ++ GW, ++ GX, ++ GY, ++ GZ, ++ BW, ++ BX, ++ BY, ++ BZ, ++ }; ++ ++ struct ModeDescriptor ++ { ++ EField m_eField; ++ uint8_t m_uBit; ++ }; ++ ++ const ModeDescriptor g_modeDescriptors[14][82] = ++ { ++ { // Mode 1 (0x00) - 10 5 5 5 ++ { M, 0 },{ M, 1 },{ GY, 4 },{ BY, 4 },{ BZ, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, ++ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 2 (0x01) - 7 6 6 6 ++ { M, 0 },{ M, 1 },{ GY, 5 },{ GZ, 4 },{ GZ, 5 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, ++ { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 3 (0x02) - 11 5 4 4 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { RW,10 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 }, ++ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 }, ++ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, ++ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 4 (0x06) - 11 4 5 4 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 }, ++ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { GW,10 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,10 }, ++ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 0 }, ++ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ GY, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 5 (0x0a) - 11 4 4 5 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,10 }, ++ { BY, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,10 }, ++ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BW,10 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ BZ, 1 }, ++ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ BZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 6 (0x0e) - 9 5 5 5 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, ++ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 7 (0x12) - 8 6 5 5 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ GZ, 4 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 3 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, ++ { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 8 (0x16) - 8 5 6 5 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 0 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ GZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BZ, 1 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, ++ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 9 (0x1a) - 8 5 5 6 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ BY, 5 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { GZ, 4 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { BZ, 0 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, ++ { BZ, 2 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ BZ, 3 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 10 (0x1e) - 6 6 6 6 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ GZ, 4 },{ BZ, 0 },{ BZ, 1 },{ BY, 4 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GY, 5 },{ BY, 5 },{ BZ, 2 },{ GY, 4 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ GZ, 5 },{ BZ, 3 },{ BZ, 5 },{ BZ, 4 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { RX, 5 },{ GY, 0 },{ GY, 1 },{ GY, 2 },{ GY, 3 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { GX, 5 },{ GZ, 0 },{ GZ, 1 },{ GZ, 2 },{ GZ, 3 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BX, 5 },{ BY, 0 },{ BY, 1 },{ BY, 2 },{ BY, 3 },{ RY, 0 },{ RY, 1 },{ RY, 2 },{ RY, 3 },{ RY, 4 }, ++ { RY, 5 },{ RZ, 0 },{ RZ, 1 },{ RZ, 2 },{ RZ, 3 },{ RZ, 4 },{ RZ, 5 },{ D, 0 },{ D, 1 },{ D, 2 }, ++ { D, 3 },{ D, 4 }, ++ }, ++ ++ { // Mode 11 (0x03) - 10 10 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RX, 9 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GX, 9 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BX, 9 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, ++ { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, ++ { NA, 0 },{ NA, 0 }, ++ }, ++ ++ { // Mode 12 (0x07) - 11 9 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { RX, 5 },{ RX, 6 },{ RX, 7 },{ RX, 8 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { GX, 5 },{ GX, 6 },{ GX, 7 },{ GX, 8 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BX, 5 },{ BX, 6 },{ BX, 7 },{ BX, 8 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, ++ { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, ++ { NA, 0 },{ NA, 0 }, ++ }, ++ ++ { // Mode 13 (0x0b) - 12 8 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RX, 4 }, ++ { RX, 5 },{ RX, 6 },{ RX, 7 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GX, 4 }, ++ { GX, 5 },{ GX, 6 },{ GX, 7 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BX, 4 }, ++ { BX, 5 },{ BX, 6 },{ BX, 7 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, ++ { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, ++ { NA, 0 },{ NA, 0 }, ++ }, ++ ++ { // Mode 14 (0x0f) - 16 4 ++ { M, 0 },{ M, 1 },{ M, 2 },{ M, 3 },{ M, 4 },{ RW, 0 },{ RW, 1 },{ RW, 2 },{ RW, 3 },{ RW, 4 }, ++ { RW, 5 },{ RW, 6 },{ RW, 7 },{ RW, 8 },{ RW, 9 },{ GW, 0 },{ GW, 1 },{ GW, 2 },{ GW, 3 },{ GW, 4 }, ++ { GW, 5 },{ GW, 6 },{ GW, 7 },{ GW, 8 },{ GW, 9 },{ BW, 0 },{ BW, 1 },{ BW, 2 },{ BW, 3 },{ BW, 4 }, ++ { BW, 5 },{ BW, 6 },{ BW, 7 },{ BW, 8 },{ BW, 9 },{ RX, 0 },{ RX, 1 },{ RX, 2 },{ RX, 3 },{ RW,15 }, ++ { RW,14 },{ RW,13 },{ RW,12 },{ RW,11 },{ RW,10 },{ GX, 0 },{ GX, 1 },{ GX, 2 },{ GX, 3 },{ GW,15 }, ++ { GW,14 },{ GW,13 },{ GW,12 },{ GW,11 },{ GW,10 },{ BX, 0 },{ BX, 1 },{ BX, 2 },{ BX, 3 },{ BW,15 }, ++ { BW,14 },{ BW,13 },{ BW,12 },{ BW,11 },{ BW,10 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, ++ { NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 },{ NA, 0 }, ++ { NA, 0 },{ NA, 0 }, ++ }, ++ }; ++ } ++ + namespace BC7Data + { + enum AlphaMode +@@ -2998,9 +3197,9 @@ void cvtt::Internal::BC6HComputer::Pack(uint32_t flags, const PixelBlockF16* inp + + const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode]; + +- BC6H_IO::WriteFunc_t writeFunc = BC6H_IO::g_writeFuncs[mode]; ++ const BC6HData::ModeDescriptor *desc = BC6HData::g_modeDescriptors[mode]; + +- const int headerBits = modeInfo.m_partitioned ? 82 : 65; ++ const size_t headerBits = modeInfo.m_partitioned ? 82 : 65; + + for (int subset = 0; subset < 2; subset++) + { +@@ -3017,16 +3216,58 @@ void cvtt::Internal::BC6HComputer::Pack(uint32_t flags, const PixelBlockF16* inp + uint16_t modeID = modeInfo.m_modeID; + + PackingVector pv; ++ pv.Init(); + +- { +- uint32_t header[3]; +- writeFunc(header, modeID, partition, +- eps[0][0][0], eps[0][1][0], eps[1][0][0], eps[1][1][0], +- eps[0][0][1], eps[0][1][1], eps[1][0][1], eps[1][1][1], +- eps[0][0][2], eps[0][1][2], eps[1][0][2], eps[1][1][2] +- ); +- +- pv.InitPacked(header, headerBits); ++ for (size_t i = 0; i < headerBits; i++) { ++ int32_t codedValue = 0; ++ switch (desc[i].m_eField) { ++ case BC6HData::M: ++ codedValue = modeID; ++ break; ++ case BC6HData::D: ++ codedValue = partition; ++ break; ++ case BC6HData::RW: ++ codedValue = eps[0][0][0]; ++ break; ++ case BC6HData::RX: ++ codedValue = eps[0][1][0]; ++ break; ++ case BC6HData::RY: ++ codedValue = eps[1][0][0]; ++ break; ++ case BC6HData::RZ: ++ codedValue = eps[1][1][0]; ++ break; ++ case BC6HData::GW: ++ codedValue = eps[0][0][1]; ++ break; ++ case BC6HData::GX: ++ codedValue = eps[0][1][1]; ++ break; ++ case BC6HData::GY: ++ codedValue = eps[1][0][1]; ++ break; ++ case BC6HData::GZ: ++ codedValue = eps[1][1][1]; ++ break; ++ case BC6HData::BW: ++ codedValue = eps[0][0][2]; ++ break; ++ case BC6HData::BX: ++ codedValue = eps[0][1][2]; ++ break; ++ case BC6HData::BY: ++ codedValue = eps[1][0][2]; ++ break; ++ case BC6HData::BZ: ++ codedValue = eps[1][1][2]; ++ break; ++ default: ++ assert(false); ++ break; ++ } ++ pv.Pack(static_cast<uint16_t>((codedValue >> desc[i].m_uBit) & 1), 1); + } + + int fixupIndex1 = 0; +@@ -3058,11 +3299,14 @@ void cvtt::Internal::BC6HComputer::SignExtendSingle(int &v, int bits) + + void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_t *pBC, bool isSigned) + { ++ UnpackingVector pv; ++ pv.Init(pBC); ++ + int numModeBits = 2; +- int modeBits = pBC[0] & 0x3; ++ int modeBits = pv.Unpack(2); + if (modeBits != 0 && modeBits != 1) + { +- modeBits = pBC[0] & 0x1f; ++ modeBits |= pv.Unpack(3) << 2; + numModeBits += 3; + } + +@@ -3088,10 +3332,10 @@ void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_ + } + + const BC7Data::BC6HModeInfo& modeInfo = BC7Data::g_hdrModes[mode]; +- const int headerBits = modeInfo.m_partitioned ? 82 : 65; +- const BC6H_IO::ReadFunc_t readFunc = BC6H_IO::g_readFuncs[mode]; ++ const size_t headerBits = modeInfo.m_partitioned ? 82 : 65; ++ const BC6HData::ModeDescriptor *desc = BC6HData::g_modeDescriptors[mode]; + +- uint16_t partition = 0; ++ int32_t partition = 0; + int32_t eps[2][2][3]; + + for (int subset = 0; subset < 2; subset++) +@@ -3099,24 +3343,55 @@ void cvtt::Internal::BC6HComputer::UnpackOne(PixelBlockF16 &output, const uint8_ + for (int ch = 0; ch < 3; ch++) + eps[subset][epi][ch] = 0; + +- UnpackingVector pv; +- pv.Init(pBC); +- +- { +- uint32_t header[3]; +- uint16_t codedEPs[2][2][3]; +- pv.UnpackStart(header, headerBits); ++ for (size_t i = numModeBits; i < headerBits; i++) { ++ int32_t *pCodedValue = NULL; + +- readFunc(header, partition, +- codedEPs[0][0][0], codedEPs[0][1][0], codedEPs[1][0][0], codedEPs[1][1][0], +- codedEPs[0][0][1], codedEPs[0][1][1], codedEPs[1][0][1], codedEPs[1][1][1], +- codedEPs[0][0][2], codedEPs[0][1][2], codedEPs[1][0][2], codedEPs[1][1][2] +- ); ++ switch (desc[i].m_eField) { ++ case BC6HData::D: ++ pCodedValue = &partition; ++ break; ++ case BC6HData::RW: ++ pCodedValue = &eps[0][0][0]; ++ break; ++ case BC6HData::RX: ++ pCodedValue = &eps[0][1][0]; ++ break; ++ case BC6HData::RY: ++ pCodedValue = &eps[1][0][0]; ++ break; ++ case BC6HData::RZ: ++ pCodedValue = &eps[1][1][0]; ++ break; ++ case BC6HData::GW: ++ pCodedValue = &eps[0][0][1]; ++ break; ++ case BC6HData::GX: ++ pCodedValue = &eps[0][1][1]; ++ break; ++ case BC6HData::GY: ++ pCodedValue = &eps[1][0][1]; ++ break; ++ case BC6HData::GZ: ++ pCodedValue = &eps[1][1][1]; ++ break; ++ case BC6HData::BW: ++ pCodedValue = &eps[0][0][2]; ++ break; ++ case BC6HData::BX: ++ pCodedValue = &eps[0][1][2]; ++ break; ++ case BC6HData::BY: ++ pCodedValue = &eps[1][0][2]; ++ break; ++ case BC6HData::BZ: ++ pCodedValue = &eps[1][1][2]; ++ break; ++ default: ++ assert(false); ++ break; ++ } + +- for (int subset = 0; subset < 2; subset++) +- for (int epi = 0; epi < 2; epi++) +- for (int ch = 0; ch < 3; ch++) +- eps[subset][epi][ch] = codedEPs[subset][epi][ch]; ++ (*pCodedValue) |= pv.Unpack(1) << desc[i].m_uBit; + } + + uint16_t modeID = modeInfo.m_modeID; |