diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index e08af4a57..ef198d386 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -18,18 +18,18 @@ jobs: strategy: fail-fast: false matrix: - compiler: [gcc12, clang17, clang19] + compiler: [gcc14, gcc16, clang23] build_type: [Debug] include: - - compiler: gcc12 - CC: "/usr/bin/gcc-12" - CXX: "/usr/bin/g++-12" - - compiler: clang17 - CC: '/usr/bin/clang-17' - CXX: '/usr/bin/clang++-17' - - compiler: clang19 - CC: '/usr/bin/clang-19' - CXX: '/usr/bin/clang++-19' + - compiler: gcc14 + CC: "/usr/bin/gcc-14" + CXX: "/usr/bin/g++-14" + - compiler: gcc16 + CC: '/usr/bin/gcc-16' + CXX: '/usr/bin/g++-16' + - compiler: clang23 + CC: '/usr/bin/clang-23' + CXX: '/usr/bin/clang++-23' runs-on: ubuntu-24.04 @@ -49,17 +49,20 @@ jobs: sudo apt-get update sudo apt-get install -y build-essential ccache ninja-build lld libgl1-mesa-dev libxcb-cursor-dev xorg-dev libx11-xcb-dev libxrandr-dev libxcursor-dev libudev-dev libopenal-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev xvfb libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 - - name: Install Clang 17 - if: matrix.compiler == 'clang17' + - name: Install GCC 16 + if: matrix.compiler == 'gcc16' run: | - sudo apt-get install -y clang-17 + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + sudo apt-get update + sudo apt-get install -y --no-install-recommends gcc-16 g++-16 - - name: Install Clang 19 - if: matrix.compiler == 'clang19' + - name: Install Clang 23 + if: matrix.compiler == 'clang23' run: | - wget https://apt.llvm.org/llvm.sh - chmod +x ./llvm.sh - sudo ./llvm.sh 19 + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc > /dev/null + echo "deb https://apt.llvm.org/noble/ llvm-toolchain-noble-23 main" | sudo tee /etc/apt/sources.list.d/llvm-23.list + sudo apt-get update + sudo apt-get install -y --no-install-recommends clang-23 lld-23 libclang-rt-23-dev - name: Install Qt uses: jurplel/install-qt-action@v4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 519e18d38..ca11dbf61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,7 +82,7 @@ include(cmake/AddRepo.cmake) include(cmake/Version.cmake) ########################################### setup ################################################# -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) diff --git a/app/ModelBinding.cpp b/app/ModelBinding.cpp index 270c6f29a..6a7de1d08 100644 --- a/app/ModelBinding.cpp +++ b/app/ModelBinding.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace { @@ -142,7 +143,7 @@ void ModelBinding::classBegin() { } void ModelBinding::componentComplete() { - assert(m_complete == false); + Q_ASSERT(m_complete == false); if (!m_qml_target.isValid()) { qWarning() << "ModelBinding: QML property invalid!"; if (m_model) diff --git a/app/RenderThreadNotifier.cpp b/app/RenderThreadNotifier.cpp index 6b5fcb0d1..8f00dfc65 100644 --- a/app/RenderThreadNotifier.cpp +++ b/app/RenderThreadNotifier.cpp @@ -22,6 +22,7 @@ #include #include #include +#include RenderThreadNotifier::RenderThreadNotifier(QObject *parent) : QObject{parent} @@ -41,8 +42,8 @@ RenderThreadNotifier* RenderThreadNotifier::instance() void RenderThreadNotifier::set_root_window(QQuickWindow* root_window) { - assert(m_root_window == nullptr); - assert(root_window); + Q_ASSERT(m_root_window == nullptr); + Q_ASSERT(root_window); m_root_window = root_window; } @@ -53,8 +54,8 @@ void RenderThreadNotifier::notify() #ifndef __EMSCRIPTEN__ if (QThread::currentThread() != QCoreApplication::instance()->thread()) qDebug() << "RenderThreadNotifier::notify() current thread: " << QThread::currentThread() << " this.thread: " << this->thread(); - assert(QThread::currentThread() == QCoreApplication::instance()->thread()); - assert(m_root_window != nullptr); + Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); + Q_ASSERT(m_root_window != nullptr); auto* runnable = QRunnable::create([]() { // qDebug() << "QCoreApplication::processEvents called on: " << QThread::currentThread() << "(" << QThread::currentThread()->objectName() << ")"; diff --git a/app/RenderingContext.cpp b/app/RenderingContext.cpp index 0c60b1c4c..f0517b302 100644 --- a/app/RenderingContext.cpp +++ b/app/RenderingContext.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -76,7 +77,7 @@ RenderingContext::RenderingContext(QObject* parent) , m(std::make_unique()) { using TilePattern = nucleus::tile::TileLoadService::UrlPattern; - assert(QThread::currentThread() == QCoreApplication::instance()->thread()); + Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); #ifdef ALP_ENABLE_THREADING m->scheduler_thread = std::make_unique(); diff --git a/app/TerrainRenderer.cpp b/app/TerrainRenderer.cpp index 52de76f1d..fbf8b1dcf 100644 --- a/app/TerrainRenderer.cpp +++ b/app/TerrainRenderer.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "RenderingContext.h" #include "TerrainRendererItem.h" @@ -161,6 +162,6 @@ nucleus::camera::Controller* TerrainRenderer::controller() const { return m_came std::shared_ptr TerrainRenderer::eaws_report_load_service() { - assert(m_eaws_report_load_service); + Q_ASSERT(m_eaws_report_load_service); return m_eaws_report_load_service; } diff --git a/apps/webgpu_app/App.cpp b/apps/webgpu_app/App.cpp index e1a19a291..166c73bbf 100644 --- a/apps/webgpu_app/App.cpp +++ b/apps/webgpu_app/App.cpp @@ -23,7 +23,6 @@ #include "webgpu/engine/Window.h" #include #include -#include #include //TODO maybe only for threading enabled? #include @@ -96,7 +95,7 @@ void App::init_window() // Load icon using the existing image loader auto icon = nucleus::utils::image_loader::rgba8(":/icons/logo32.png").value(); // Create SDL_Surface from the raw image data - SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom((void*)icon.bytes(), // Pixel data + SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(icon.bytes().data(), // Pixel data icon.width(), // Image width icon.height(), // Image height 32, // Bits per pixel (RGBA = 32 bits) diff --git a/apps/webgpu_app/RenderingContext.cpp b/apps/webgpu_app/RenderingContext.cpp index 1d15aae0b..b63f55d42 100644 --- a/apps/webgpu_app/RenderingContext.cpp +++ b/apps/webgpu_app/RenderingContext.cpp @@ -21,6 +21,8 @@ #include "RenderingContext.h" +#include + #include "nucleus/DataQuerier.h" #include "nucleus/tile/SchedulerDirector.h" #include "nucleus/tile/Texture3DScheduler.h" @@ -44,7 +46,7 @@ RenderingContext::RenderingContext() { using TilePattern = nucleus::tile::TileLoadService::UrlPattern; - assert(QThread::currentThread() == QCoreApplication::instance()->thread()); + Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); #ifdef ALP_ENABLE_THREADING m_scheduler_thread = std::make_unique(); diff --git a/apps/webgpu_app/compute/nodes/NodeRenderer.cpp b/apps/webgpu_app/compute/nodes/NodeRenderer.cpp index 228e284ec..bad5542b4 100644 --- a/apps/webgpu_app/compute/nodes/NodeRenderer.cpp +++ b/apps/webgpu_app/compute/nodes/NodeRenderer.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -230,7 +231,7 @@ void NodeRenderer::rename(const std::string& new_name) int NodeRenderer::get_input_socket_id(const std::string& input_socket_name) const { - assert(m_node->has_input_socket(input_socket_name)); + Q_ASSERT(m_node->has_input_socket(input_socket_name)); for (size_t i = 0; i < m_node->input_sockets().size(); i++) { if (input_socket_name == m_node->input_sockets().at(i).name()) { @@ -243,7 +244,7 @@ int NodeRenderer::get_input_socket_id(const std::string& input_socket_name) cons int NodeRenderer::get_output_socket_id(const std::string& output_socket_name) const { - assert(m_node->has_output_socket(output_socket_name)); + Q_ASSERT(m_node->has_output_socket(output_socket_name)); for (size_t i = 0; i < m_node->output_sockets().size(); i++) { if (output_socket_name == m_node->output_sockets().at(i).name()) { diff --git a/apps/webgpu_app/ui/LogoPanel.cpp b/apps/webgpu_app/ui/LogoPanel.cpp index 06c04d517..17e9122f4 100644 --- a/apps/webgpu_app/ui/LogoPanel.cpp +++ b/apps/webgpu_app/ui/LogoPanel.cpp @@ -35,7 +35,7 @@ LogoPanel::LogoPanel(WGPUDevice device) void LogoPanel::init_logo() { - nucleus::Raster logo = nucleus::utils::image_loader::rgba8(":/gfx/sujet.png").value(); + radix::Raster logo = nucleus::utils::image_loader::rgba8(":/gfx/sujet.png").value(); m_webigeo_logo_size = ImVec2(float(logo.width()), float(logo.height())); WGPUTextureDescriptor texture_desc {}; diff --git a/apps/webgpu_app/util/InputMapper.cpp b/apps/webgpu_app/util/InputMapper.cpp index df88ab83a..fab69c774 100644 --- a/apps/webgpu_app/util/InputMapper.cpp +++ b/apps/webgpu_app/util/InputMapper.cpp @@ -19,6 +19,7 @@ #include "InputMapper.h" #include "nucleus/camera/Controller.h" #include +#include namespace webgpu_app { @@ -156,7 +157,7 @@ void InputMapper::handle_mouse_button_event(const SDL_Event& event) const int button = event.button.button; const int action = (event.type == SDL_MOUSEBUTTONDOWN) ? SDL_PRESSED : SDL_RELEASED; - assert(button >= 0 && (size_t)button < m_buttonmap.size()); + Q_ASSERT(button >= 0 && (size_t)button < m_buttonmap.size()); if (m_gui_manager && m_gui_manager->want_capture_mouse()) return; diff --git a/cmake/SetupCMakeProject.cmake b/cmake/SetupCMakeProject.cmake new file mode 100644 index 000000000..4819c892f --- /dev/null +++ b/cmake/SetupCMakeProject.cmake @@ -0,0 +1,242 @@ +############################################################################# +# AlpineMaps.org +# Copyright (C) 2026 Adam Celarek +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +############################################################################# + +include_guard(GLOBAL) + +if(NOT COMMAND alp_add_git_repository) + include(${CMAKE_CURRENT_LIST_DIR}/AddRepo.cmake) +endif() + +if(NOT COMMAND alp_check_for_script_updates) + include(${CMAKE_CURRENT_LIST_DIR}/CheckForScriptUpdates.cmake) +endif() + +alp_check_for_script_updates("${CMAKE_CURRENT_LIST_FILE}") + +macro(_alp_append_cache_arg out var type) + if(DEFINED ${var} AND NOT "${${var}}" STREQUAL "") + set(_alp_cache_value "${${var}}") + string(REPLACE ";" "\\;" _alp_cache_value "${_alp_cache_value}") + list(APPEND ${out} "-D${var}:${type}=${_alp_cache_value}") + unset(_alp_cache_value) + endif() +endmacro() + +macro(_alp_append_key_value out var) + if(DEFINED ${var}) + set(_alp_key_value "${${var}}") + string(REPLACE ";" "\\;" _alp_key_value "${_alp_key_value}") + list(APPEND ${out} "${var}=${_alp_key_value}") + unset(_alp_key_value) + endif() +endmacro() + +set(_ALP_CMAKE_PROJECT_FORWARD_VARS + CMAKE_TOOLCHAIN_FILE + CMAKE_SYSROOT + CMAKE_FIND_ROOT_PATH + CMAKE_FIND_ROOT_PATH_MODE_PROGRAM + CMAKE_FIND_ROOT_PATH_MODE_LIBRARY + CMAKE_FIND_ROOT_PATH_MODE_INCLUDE + CMAKE_FIND_ROOT_PATH_MODE_PACKAGE + CMAKE_SYSTEM_NAME + CMAKE_SYSTEM_PROCESSOR + CMAKE_SYSTEM_VERSION + CMAKE_C_COMPILER + CMAKE_CXX_COMPILER + CMAKE_AR + CMAKE_RANLIB + CMAKE_MAKE_PROGRAM + CMAKE_CROSSCOMPILING_EMULATOR + CMAKE_POSITION_INDEPENDENT_CODE + CMAKE_MSVC_RUNTIME_LIBRARY + QT_HOST_PATH + QT_HOST_PATH_CMAKE_DIR + Qt6HostInfo_DIR + ANDROID_ABI + ANDROID_PLATFORM + ANDROID_STL + ANDROID_NDK + ANDROID_SDK_ROOT + ANDROID_USE_LEGACY_TOOLCHAIN_FILE + EMSCRIPTEN + EMSCRIPTEN_FORCE_COMPILERS + EMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES) + +function(_alp_build_and_install_cmake_project NAME SRC_DIR BUILD_DIR INSTALL_DIR BUILD_CONFIG) + set(_generator_args) + if(CMAKE_GENERATOR_PLATFORM) + list(APPEND _generator_args -A "${CMAKE_GENERATOR_PLATFORM}") + endif() + if(CMAKE_GENERATOR_TOOLSET) + list(APPEND _generator_args -T "${CMAKE_GENERATOR_TOOLSET}") + endif() + + set(_configure_args + "-DCMAKE_INSTALL_PREFIX:PATH=${INSTALL_DIR}" + ) + _alp_append_cache_arg(_configure_args CMAKE_PREFIX_PATH PATH) + + if(CMAKE_CONFIGURATION_TYPES) + _alp_append_cache_arg(_configure_args CMAKE_CONFIGURATION_TYPES STRING) + else() + list(APPEND _configure_args "-DCMAKE_BUILD_TYPE:STRING=${BUILD_CONFIG}") + endif() + + foreach(_var IN LISTS _ALP_CMAKE_PROJECT_FORWARD_VARS) + _alp_append_cache_arg(_configure_args ${_var} STRING) + endforeach() + + string(JOIN " " _alp_sanitizer_flags ${ALP_SANITIZER_FLAGS}) + + foreach(_lang C CXX) + set(_alp_effective_flags "${CMAKE_${_lang}_FLAGS}") + if(_alp_sanitizer_flags) + string(APPEND _alp_effective_flags " ${_alp_sanitizer_flags}") + endif() + if(_alp_effective_flags) + string(REPLACE ";" "\\;" _alp_effective_flags "${_alp_effective_flags}") + list(APPEND _configure_args "-DCMAKE_${_lang}_FLAGS:STRING=${_alp_effective_flags}") + endif() + foreach(_config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) + _alp_append_cache_arg(_configure_args CMAKE_${_lang}_FLAGS_${_config} STRING) + endforeach() + endforeach() + + foreach(_kind EXE SHARED MODULE STATIC) + set(_alp_effective_flags "${CMAKE_${_kind}_LINKER_FLAGS}") + if(_alp_sanitizer_flags AND NOT _kind STREQUAL "STATIC") + string(APPEND _alp_effective_flags " ${_alp_sanitizer_flags}") + endif() + if(_alp_effective_flags) + string(REPLACE ";" "\\;" _alp_effective_flags "${_alp_effective_flags}") + list(APPEND _configure_args "-DCMAKE_${_kind}_LINKER_FLAGS:STRING=${_alp_effective_flags}") + endif() + foreach(_config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) + _alp_append_cache_arg(_configure_args CMAKE_${_kind}_LINKER_FLAGS_${_config} STRING) + endforeach() + endforeach() + + list(APPEND _configure_args ${ARGN}) + + message(STATUS "[alp] Configuring ${NAME}") + execute_process( + COMMAND "${CMAKE_COMMAND}" + -G "${CMAKE_GENERATOR}" + ${_generator_args} + -S "${SRC_DIR}" + -B "${BUILD_DIR}" + ${_configure_args} + RESULT_VARIABLE _cfg_res) + + if(_cfg_res) + message(FATAL_ERROR "[alp] Configuring ${NAME} failed!") + endif() + + message(STATUS "[alp] Building + installing ${NAME}") + execute_process( + COMMAND "${CMAKE_COMMAND}" + --build "${BUILD_DIR}" + --config "${BUILD_CONFIG}" + --parallel + --target install + RESULT_VARIABLE _bld_res) + + if(_bld_res) + message(FATAL_ERROR "[alp] Building ${NAME} failed!") + endif() +endfunction() + +function(alp_setup_cmake_project arg_NAME) + set(options) + set(oneValueArgs URL COMMITISH) + set(multiValueArgs CMAKE_ARGUMENTS) + cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${oneValueArgs}" "${multiValueArgs}") + + if(NOT arg_NAME OR NOT arg_URL OR NOT arg_COMMITISH) + message(FATAL_ERROR "[alp] alp_setup_cmake_project() needs: URL COMMITISH ") + endif() + + set(_build_config "${CMAKE_BUILD_TYPE}") + if(NOT _build_config) + set(_build_config Release) + endif() + + alp_add_git_repository(${arg_NAME} URL ${arg_URL} COMMITISH ${arg_COMMITISH} DO_NOT_ADD_SUBPROJECT) + set(_src_dir "${${arg_NAME}_SOURCE_DIR}") + set(_build_dir "${CMAKE_BINARY_DIR}/alp_external/${arg_NAME}_build") + set(_install_dir "${CMAKE_BINARY_DIR}/alp_external/${arg_NAME}") + + set(_version_var "ALP_INSTALLED_${arg_NAME}_VERSION") + set(_path_var "ALP_INSTALLED_${arg_NAME}_PATH") + set(_key_parts + "URL=${arg_URL}" + "COMMITISH=${arg_COMMITISH}" + "CMAKE_ARGUMENTS=${arg_CMAKE_ARGUMENTS}" + "CMAKE_GENERATOR=${CMAKE_GENERATOR}" + "CMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}" + "CMAKE_GENERATOR_TOOLSET=${CMAKE_GENERATOR_TOOLSET}" + "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" + "CMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}" + "BUILD_CONFIG=${_build_config}") + _alp_append_key_value(_key_parts ALP_SANITIZER_FLAGS) + _alp_append_key_value(_key_parts CMAKE_PREFIX_PATH) + foreach(_var IN LISTS _ALP_CMAKE_PROJECT_FORWARD_VARS) + _alp_append_key_value(_key_parts ${_var}) + endforeach() + foreach(_lang C CXX) + _alp_append_key_value(_key_parts CMAKE_${_lang}_FLAGS) + foreach(_config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) + _alp_append_key_value(_key_parts CMAKE_${_lang}_FLAGS_${_config}) + endforeach() + endforeach() + foreach(_kind EXE SHARED MODULE STATIC) + _alp_append_key_value(_key_parts CMAKE_${_kind}_LINKER_FLAGS) + foreach(_config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) + _alp_append_key_value(_key_parts CMAKE_${_kind}_LINKER_FLAGS_${_config}) + endforeach() + endforeach() + string(JOIN "\n" _key_input ${_key_parts}) + string(SHA256 _key "${_key_input}") + + if(DEFINED ${_version_var} + AND "${${_version_var}}" STREQUAL "${_key}" + AND DEFINED ${_path_var} + AND EXISTS "${${_path_var}}") + list(PREPEND CMAKE_PREFIX_PATH "${${_path_var}}") + set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" PARENT_SCOPE) + set(ALP_${arg_NAME}_INSTALL_DIR "${${_path_var}}" PARENT_SCOPE) + return() + endif() + + file(REMOVE_RECURSE "${_build_dir}" "${_install_dir}") + _alp_build_and_install_cmake_project( + ${arg_NAME} + "${_src_dir}" + "${_build_dir}" + "${_install_dir}" + "${_build_config}" + ${arg_CMAKE_ARGUMENTS}) + + list(PREPEND CMAKE_PREFIX_PATH "${_install_dir}") + set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" PARENT_SCOPE) + set(ALP_${arg_NAME}_INSTALL_DIR "${_install_dir}" PARENT_SCOPE) + + set(${_path_var} "${_install_dir}" CACHE PATH "Install path for ${arg_NAME}" FORCE) + set(${_version_var} "${_key}" CACHE STRING "Installed cache key for ${arg_NAME}" FORCE) +endfunction() diff --git a/cmake/SetupKTX.cmake b/cmake/SetupKTX.cmake index 4c2c27df7..b527a722b 100644 --- a/cmake/SetupKTX.cmake +++ b/cmake/SetupKTX.cmake @@ -1,44 +1,70 @@ include_guard(GLOBAL) -# Adds KTX-Software (via alp_add_git_repository, pinned to commitish) and applies the -# feature-flag, Emscripten, and multi-config output-directory tweaks the ktx target needs. +if(NOT COMMAND alp_setup_cmake_project) + include(${CMAKE_CURRENT_LIST_DIR}/SetupCMakeProject.cmake) +endif() + +function(_alp_append_ktx_interface_property target property) + get_target_property(_values ${target} ${property}) + if(NOT _values) + set(_values) + endif() + list(APPEND _values ${ARGN}) + set_target_properties(${target} PROPERTIES ${property} "${_values}") +endfunction() + +# Builds and installs KTX-Software in an isolated CMake invocation, then imports +# the installed package. This keeps KTX's global CMake state out of the renderer. function(alp_setup_ktx commitish) - set(KTX_FEATURE_TESTS OFF CACHE BOOL "" FORCE) - set(KTX_FEATURE_TOOLS OFF CACHE BOOL "" FORCE) - set(KTX_FEATURE_DOC OFF CACHE BOOL "" FORCE) - set(KTX_FEATURE_JS OFF CACHE BOOL "" FORCE) - - # KTX installs its libs into a versioned subdirectory by default; override so they - # land next to everything else, then restore the previous value for other targets. - set(CMAKE_INSTALL_BINDIR_SAVED ${CMAKE_INSTALL_BINDIR}) - set(CMAKE_INSTALL_BINDIR "." CACHE STRING "" FORCE) - alp_add_git_repository(libktx URL https://github.com/KhronosGroup/KTX-Software.git COMMITISH ${commitish}) - set(CMAKE_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR_SAVED} CACHE STRING "" FORCE) + set(_ktx_build_shared ON) + if(EMSCRIPTEN OR ANDROID) + set(_ktx_build_shared OFF) + endif() + + set(_ktx_cmake_args + -DKTX_FEATURE_TESTS:BOOL=OFF + -DKTX_FEATURE_TOOLS:BOOL=OFF + -DKTX_FEATURE_DOC:BOOL=OFF + -DKTX_FEATURE_JS:BOOL=OFF + -DKTX_FEATURE_LOADTEST_APPS:STRING=OFF + "-DBUILD_SHARED_LIBS:BOOL=${_ktx_build_shared}" + -DCMAKE_INSTALL_BINDIR:STRING=. + ) if (EMSCRIPTEN AND ALP_ENABLE_THREADING) - target_compile_options(ktx PUBLIC -pthread) - target_link_options(ktx PUBLIC -pthread) + set(_ktx_c_flags "${CMAKE_C_FLAGS} -pthread") + set(_ktx_cxx_flags "${CMAKE_CXX_FLAGS} -pthread") + set(_ktx_exe_linker_flags "${CMAKE_EXE_LINKER_FLAGS} -pthread") + set(_ktx_shared_linker_flags "${CMAKE_SHARED_LINKER_FLAGS} -pthread") + list(APPEND _ktx_cmake_args + "-DCMAKE_C_FLAGS:STRING=${_ktx_c_flags}" + "-DCMAKE_CXX_FLAGS:STRING=${_ktx_cxx_flags}" + "-DCMAKE_EXE_LINKER_FLAGS:STRING=${_ktx_exe_linker_flags}" + "-DCMAKE_SHARED_LINKER_FLAGS:STRING=${_ktx_shared_linker_flags}" + ) endif() - if (EMSCRIPTEN AND TARGET ktx) - get_target_property(KTX_INTERFACE_LINK_OPTIONS ktx INTERFACE_LINK_OPTIONS) + alp_setup_cmake_project(libktx + URL https://github.com/KhronosGroup/KTX-Software.git + COMMITISH ${commitish} + CMAKE_ARGUMENTS ${_ktx_cmake_args} + ) + + find_package(Ktx CONFIG REQUIRED + PATHS "${ALP_libktx_INSTALL_DIR}" + NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH) + + if (EMSCRIPTEN AND ALP_ENABLE_THREADING) + _alp_append_ktx_interface_property(KTX::ktx INTERFACE_COMPILE_OPTIONS -pthread) + _alp_append_ktx_interface_property(KTX::ktx INTERFACE_LINK_OPTIONS -pthread) + endif() + + if (EMSCRIPTEN AND TARGET KTX::ktx) + get_target_property(KTX_INTERFACE_LINK_OPTIONS KTX::ktx INTERFACE_LINK_OPTIONS) if (KTX_INTERFACE_LINK_OPTIONS) list(FILTER KTX_INTERFACE_LINK_OPTIONS EXCLUDE REGEX "STACK_SIZE=96kb") - set_target_properties(ktx PROPERTIES INTERFACE_LINK_OPTIONS "${KTX_INTERFACE_LINK_OPTIONS}") + set_target_properties(KTX::ktx PROPERTIES INTERFACE_LINK_OPTIONS "${KTX_INTERFACE_LINK_OPTIONS}") endif() endif() - - if (NOT EMSCRIPTEN) - # NOTE: KTX builds into an additional Release/Debug directory. The following - # moves the builds directory for the targets ktx and ktx_read to the binary dir - foreach(ktx_target ktx ktx_read) - if (TARGET ${ktx_target}) - set_target_properties(${ktx_target} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" - RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}" - RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}" - ) - endif() - endforeach() - endif() endfunction() diff --git a/gl_engine/AvalancheWarningLayer.cpp b/gl_engine/AvalancheWarningLayer.cpp index 1b0fb20d2..e408dd556 100644 --- a/gl_engine/AvalancheWarningLayer.cpp +++ b/gl_engine/AvalancheWarningLayer.cpp @@ -22,6 +22,7 @@ #include "ShaderRegistry.h" #include "TileGeometry.h" #include +#include #include namespace gl_engine { @@ -55,8 +56,8 @@ void AvalancheWarningLayer::draw( m_texture_array->bind(2); m_shader->set_uniform("texture_sampler", 2); - nucleus::Raster zoom_level_raster = { glm::uvec2 { 1024, 1 } }; - nucleus::Raster array_index_raster = { glm::uvec2 { 1024, 1 } }; + radix::Raster zoom_level_raster(glm::uvec2 { 1024, 1 }); + radix::Raster array_index_raster(glm::uvec2 { 1024, 1 }); for (unsigned i = 0; i < std::min(unsigned(draw_list.size()), 1024u); ++i) { const auto layer = m_gpu_array_helper.layer(draw_list[i].id); zoom_level_raster.pixel({ i, 0 }) = layer.id.zoom_level; @@ -100,8 +101,8 @@ void AvalancheWarningLayer::update_gpu_tiles(const std::vector 2048 are not supported on all devices - assert(!m_texture_array); + Q_ASSERT(new_limit < 2048); // array textures with size > 2048 are not supported on all devices + Q_ASSERT(!m_texture_array); m_gpu_array_helper.set_tile_limit(new_limit); } diff --git a/gl_engine/AvalancheWarningLayer.h b/gl_engine/AvalancheWarningLayer.h index e87117504..3eaeefe74 100644 --- a/gl_engine/AvalancheWarningLayer.h +++ b/gl_engine/AvalancheWarningLayer.h @@ -20,10 +20,10 @@ #include "Texture.h" #include -#include #include #include #include +#include namespace camera { class Definition; diff --git a/gl_engine/Context.cpp b/gl_engine/Context.cpp index 04eb5ae65..dc35c7a58 100644 --- a/gl_engine/Context.cpp +++ b/gl_engine/Context.cpp @@ -24,6 +24,7 @@ #include "TileGeometry.h" #include "TrackManager.h" #include +#include using namespace gl_engine; @@ -36,19 +37,19 @@ Context::~Context() = default; TrackManager* Context::track_manager() { - assert(is_alive()); + Q_ASSERT(is_alive()); return m_track_manager.get(); } ShaderRegistry* Context::shader_registry() { - assert(is_alive()); + Q_ASSERT(is_alive()); return m_shader_registry.get(); } void Context::internal_initialise() { - assert(!m_shader_registry); + Q_ASSERT(!m_shader_registry); // init of shader registry and track manager should be moved out of here for more flexibility, similar to tile_geometry m_shader_registry = std::make_shared(); m_track_manager = std::make_shared(m_shader_registry.get()); @@ -86,7 +87,7 @@ AvalancheWarningLayer* Context::eaws_layer() const { return m_eaws_layer.get(); void Context::set_ortho_layer(std::shared_ptr new_layer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_ortho_layer = std::move(new_layer); } @@ -94,13 +95,13 @@ TextureLayer* Context::surfaceshaded_layer() const { return m_surfaceshaded_laye void Context::set_surfaceshaded_layer(std::shared_ptr new_layer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_surfaceshaded_layer = std::move(new_layer); } void Context::set_eaws_layer(std::shared_ptr new_layer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_eaws_layer = std::move(new_layer); } @@ -108,7 +109,7 @@ TileGeometry* Context::tile_geometry() const { return m_tile_geometry.get(); } void Context::set_tile_geometry(std::shared_ptr new_tile_geometry) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_tile_geometry = std::move(new_tile_geometry); } @@ -116,6 +117,6 @@ gl_engine::MapLabels* Context::map_label_manager() const { return m_map_label_ma void Context::set_map_label_manager(std::shared_ptr new_map_label_manager) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_map_label_manager = std::move(new_map_label_manager); } diff --git a/gl_engine/Framebuffer.cpp b/gl_engine/Framebuffer.cpp index 77328ddf8..1dfd439e2 100644 --- a/gl_engine/Framebuffer.cpp +++ b/gl_engine/Framebuffer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef ANDROID #include #endif @@ -58,7 +59,7 @@ QOpenGLTexture::TextureFormat internal_format_qt(Framebuffer::ColourFormat f) case Framebuffer::ColourFormat::RGBA32F: return QOpenGLTexture::TextureFormat::RGBA32F; } - assert(false); + Q_ASSERT(false); return QOpenGLTexture::TextureFormat::NoFormat; } @@ -86,7 +87,7 @@ GLenum format(Framebuffer::ColourFormat f) case Framebuffer::ColourFormat::RGBA32F: return GL_RGBA; } - assert(false); + Q_ASSERT(false); return GLenum(-1); } @@ -106,10 +107,10 @@ QOpenGLTexture::TextureFormat internal_format_qt(Framebuffer::DepthFormat f) case Framebuffer::DepthFormat::Float32: return QOpenGLTexture::TextureFormat::D32F; case Framebuffer::DepthFormat::None: // prevent compiler warning - assert(false); // extra assert, so we can from the line number which issue it is + Q_ASSERT(false); // extra assert, so we can from the line number which issue it is return QOpenGLTexture::TextureFormat::NoFormat; } - assert(false); + Q_ASSERT(false); return QOpenGLTexture::TextureFormat::NoFormat; } @@ -132,7 +133,7 @@ GLenum type(Framebuffer::ColourFormat f) case Framebuffer::ColourFormat::R32UI: return GL_UNSIGNED_INT; } - assert(false); + Q_ASSERT(false); return GLenum(-1); } @@ -146,10 +147,10 @@ GLenum type(Framebuffer::DepthFormat f) case Framebuffer::DepthFormat::Float32: return GL_FLOAT; case Framebuffer::DepthFormat::None: // prevent compiler warning - assert(false); // extra assert, so we can from the line number which issue it is + Q_ASSERT(false); // extra assert, so we can from the line number which issue it is return GLenum(-1); } - assert(false); + Q_ASSERT(false); return GLenum(-1); } @@ -170,7 +171,7 @@ QImage::Format qimage_format(Framebuffer::ColourFormat f) throw std::logic_error("unsupported, QImage does not support the color format of the texture"); } - assert(false); + Q_ASSERT(false); return QImage::Format_Invalid; } @@ -255,13 +256,13 @@ void Framebuffer::bind() void Framebuffer::bind_colour_texture(unsigned index, unsigned location) { - assert(index < m_colour_textures.size()); + Q_ASSERT(index < m_colour_textures.size()); m_colour_textures[index]->bind(location); } void Framebuffer::bind_depth_texture(unsigned location) { - assert(m_depth_format != DepthFormat::None); + Q_ASSERT(m_depth_format != DepthFormat::None); m_depth_texture->bind(location); } @@ -272,7 +273,7 @@ QOpenGLTexture* Framebuffer::depth_texture() QImage Framebuffer::read_colour_attachment(unsigned index) { - assert(index < m_colour_textures.size()); + Q_ASSERT(index < m_colour_textures.size()); auto texFormat = m_colour_definitions[index]; @@ -288,7 +289,7 @@ QImage Framebuffer::read_colour_attachment(unsigned index) f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index); QImage image({ static_cast(m_size.x), static_cast(m_size.y) }, qimage_format(texFormat)); - assert(!image.isNull()); + Q_ASSERT(!image.isNull()); f->glReadPixels(0, 0, int(m_size.x), int(m_size.y), format(texFormat), type(texFormat), image.bits()); #if QT_VERSION > QT_VERSION_CHECK(6, 9, 0) image.flip(Qt::Orientation::Vertical); @@ -302,7 +303,7 @@ QImage Framebuffer::read_colour_attachment(unsigned index) template T Framebuffer::read_colour_attachment_pixel(unsigned int index, const glm::dvec2& normalised_device_coordinates) { - assert(index < m_colour_textures.size()); + Q_ASSERT(index < m_colour_textures.size()); auto texFormat = m_colour_definitions[index]; switch (texFormat) { @@ -316,16 +317,16 @@ T Framebuffer::read_colour_attachment_pixel(unsigned int index, const glm::dvec2 // unsupported or untested. // you really should add a unit test if you move something down to the supported section // as the support accross platforms (webassembly, android, ios?) is patchy - assert(false); + Q_ASSERT(false); return {}; case Framebuffer::ColourFormat::RGBA8: // case Framebuffer::ColourFormat::SRGBA8: - assert(sizeof(T) == 4); + Q_ASSERT(sizeof(T) == 4); if (sizeof(T) != 4) return {}; break; case Framebuffer::ColourFormat::RGBA32F: - assert(sizeof(T) == 16); + Q_ASSERT(sizeof(T) == 16); if (sizeof(T) != 16) return {}; break; @@ -367,7 +368,7 @@ void Framebuffer::reset_fbo() // Tell OpenGL how many attachments to use f->glDrawBuffers(m_colour_textures.size(), draw_attachments.data()); - // assert(f->glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + // Q_ASSERT(f->glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); } diff --git a/gl_engine/SSAO.cpp b/gl_engine/SSAO.cpp index 2706755a6..3a9064944 100644 --- a/gl_engine/SSAO.cpp +++ b/gl_engine/SSAO.cpp @@ -22,6 +22,7 @@ #include "ShaderRegistry.h" #include #include +#include #include #include @@ -64,7 +65,7 @@ SSAO::SSAO(ShaderRegistry* shader_registry) } void SSAO::recreate_kernel(unsigned int size) { - assert(size <= MAX_SSAO_KERNEL_SIZE); + Q_ASSERT(size <= MAX_SSAO_KERNEL_SIZE); std::uniform_real_distribution randomFloats(0.0, 1.0); // generates random floats between 0.0 and 1.0 std::default_random_engine generator; m_ssao_kernel.clear(); diff --git a/gl_engine/ShaderProgram.cpp b/gl_engine/ShaderProgram.cpp index 8c4e2ed6b..9e9ac75d9 100644 --- a/gl_engine/ShaderProgram.cpp +++ b/gl_engine/ShaderProgram.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #if defined(__ANDROID__) #include // for GL_INVALID_INDEX! DONT EXACTLY KNOW WHY I NEED THIS HERE! (on other platforms it works without) @@ -183,7 +184,7 @@ ShaderProgram::ShaderProgram(QString vertex_shader, QString fragment_shader, Sha , m_defines(defines) { reload(); - assert(m_q_shader_program); + Q_ASSERT(m_q_shader_program); } int ShaderProgram::attribute_location(const std::string& name) diff --git a/gl_engine/Texture.cpp b/gl_engine/Texture.cpp index 41883fd0c..c343af264 100644 --- a/gl_engine/Texture.cpp +++ b/gl_engine/Texture.cpp @@ -21,6 +21,7 @@ #include #include +#include #ifdef __EMSCRIPTEN__ #include #include @@ -97,9 +98,9 @@ void gl_engine::Texture::bind(unsigned int texture_unit) void gl_engine::Texture::setParams(Filter min_filter, Filter mag_filter, bool anisotropic_filtering) { // doesn't make sense, does it? - assert(mag_filter != Filter::MipMapLinear); + Q_ASSERT(mag_filter != Filter::MipMapLinear); - assert(gl_tex_params(m_format).is_texture_filterable || (min_filter == Filter::Nearest && mag_filter == Filter::Nearest)); + Q_ASSERT(gl_tex_params(m_format).is_texture_filterable || (min_filter == Filter::Nearest && mag_filter == Filter::Nearest)); m_min_filter = min_filter; m_mag_filter = mag_filter; @@ -116,8 +117,8 @@ void gl_engine::Texture::setParams(Filter min_filter, Filter mag_filter, bool an void gl_engine::Texture::allocate_array(unsigned int width, unsigned int height, unsigned int n_layers) { - assert(m_target == Target::_2dArray); - assert(m_format != Format::Invalid); + Q_ASSERT(m_target == Target::_2dArray); + Q_ASSERT(m_format != Format::Invalid); auto mip_level_count = 1; if (m_min_filter == Filter::MipMapLinear) @@ -141,7 +142,7 @@ void gl_engine::Texture::upload(const nucleus::utils::ColourTexture& texture) const auto height = GLsizei(texture.height()); const auto p = gl_tex_params(m_format); if (m_format == Format::CompressedRGBA8) { - assert(m_min_filter != Filter::MipMapLinear); + Q_ASSERT(m_min_filter != Filter::MipMapLinear); const auto format = gl_engine::Texture::compressed_texture_format(); f->glCompressedTexImage2D(GLenum(m_target), 0, format, width, height, 0, GLsizei(texture.n_bytes()), texture.data()); } else if (m_format == Format::RGBA8 || m_format == Format::SRGBA8) { @@ -149,16 +150,16 @@ void gl_engine::Texture::upload(const nucleus::utils::ColourTexture& texture) if (m_min_filter == Filter::MipMapLinear) f->glGenerateMipmap(GLenum(m_target)); } else { - assert(false); + Q_ASSERT(false); } } void gl_engine::Texture::upload(const nucleus::utils::ColourTexture& texture, unsigned int array_index) { - assert(texture.width() == m_width); - assert(texture.height() == m_height); - assert(array_index < m_n_layers); - assert(m_min_filter != Filter::MipMapLinear); // use the upload function with nucleus::utils::MipmappedColourTexture + Q_ASSERT(texture.width() == m_width); + Q_ASSERT(texture.height() == m_height); + Q_ASSERT(array_index < m_n_layers); + Q_ASSERT(m_min_filter != Filter::MipMapLinear); // use the upload function with nucleus::utils::MipmappedColourTexture auto* f = QOpenGLContext::currentContext()->extraFunctions(); f->glBindTexture(GLenum(m_target), m_id); @@ -171,16 +172,16 @@ void gl_engine::Texture::upload(const nucleus::utils::ColourTexture& texture, un } else if (m_format == Format::RGBA8 || m_format == Format::SRGBA8) { f->glTexSubImage3D(GLenum(m_target), 0, 0, 0, GLint(array_index), width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, texture.data()); } else { - assert(false); + Q_ASSERT(false); } } void gl_engine::Texture::upload(const nucleus::utils::MipmappedColourTexture& mipped_texture, unsigned int array_index) { - assert(mipped_texture.size() > 0); - assert(mipped_texture.front().width() == m_width); - assert(mipped_texture.front().height() == m_height); - assert(array_index < m_n_layers); + Q_ASSERT(mipped_texture.size() > 0); + Q_ASSERT(mipped_texture.front().width() == m_width); + Q_ASSERT(mipped_texture.front().height() == m_height); + Q_ASSERT(array_index < m_n_layers); auto* f = QOpenGLContext::currentContext()->extraFunctions(); f->glBindTexture(GLenum(m_target), m_id); @@ -196,27 +197,27 @@ void gl_engine::Texture::upload(const nucleus::utils::MipmappedColourTexture& mi } else if (m_format == Format::RGBA8 || m_format == Format::SRGBA8) { f->glTexSubImage3D(GLenum(m_target), mip_level, 0, 0, GLint(array_index), width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, texture.data()); } else { - assert(false); + Q_ASSERT(false); } ++mip_level; } } -template void gl_engine::Texture::upload(const nucleus::Raster& texture, unsigned int array_index) +template void gl_engine::Texture::upload(const radix::Raster& texture, unsigned int array_index) { - assert(m_target == Target::_2dArray); + Q_ASSERT(m_target == Target::_2dArray); const auto p = gl_tex_params(m_format); - assert(m_format != Format::CompressedRGBA8); - assert(m_format != Format::Invalid); - assert(sizeof(T) == p.n_bytes_per_element * p.n_elements); + Q_ASSERT(m_format != Format::CompressedRGBA8); + Q_ASSERT(m_format != Format::Invalid); + Q_ASSERT(sizeof(T) == p.n_bytes_per_element * p.n_elements); if (!p.is_texture_filterable) { - assert(m_mag_filter == Filter::Nearest); - assert(m_min_filter == Filter::Nearest); + Q_ASSERT(m_mag_filter == Filter::Nearest); + Q_ASSERT(m_min_filter == Filter::Nearest); } - assert(array_index < m_n_layers); - assert(texture.width() == m_width); - assert(texture.height() == m_height); + Q_ASSERT(array_index < m_n_layers); + Q_ASSERT(texture.width() == m_width); + Q_ASSERT(texture.height() == m_height); const auto width = GLsizei(texture.width()); const auto height = GLsizei(texture.height()); @@ -224,49 +225,49 @@ template void gl_engine::Texture::upload(const nucleus::Raster& auto* f = QOpenGLContext::currentContext()->extraFunctions(); f->glBindTexture(GLenum(m_target), m_id); f->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - f->glTexSubImage3D(GLenum(m_target), 0, 0, 0, GLint(array_index), width, height, 1, p.format, p.type, texture.bytes()); + f->glTexSubImage3D(GLenum(m_target), 0, 0, 0, GLint(array_index), width, height, 1, p.format, p.type, texture.bytes().data()); if (m_min_filter == Filter::MipMapLinear) f->glGenerateMipmap(GLenum(m_target)); } -template void gl_engine::Texture::upload(const nucleus::Raster&, unsigned); -template void gl_engine::Texture::upload(const nucleus::Raster&, unsigned); -template void gl_engine::Texture::upload(const nucleus::Raster&, unsigned); -template void gl_engine::Texture::upload>(const nucleus::Raster>&, unsigned); -template void gl_engine::Texture::upload>(const nucleus::Raster>&, unsigned); -template void gl_engine::Texture::upload>(const nucleus::Raster>&, unsigned); -template void gl_engine::Texture::upload>(const nucleus::Raster>&, unsigned); -template void gl_engine::Texture::upload>(const nucleus::Raster>&, unsigned); - -template void gl_engine::Texture::upload(const nucleus::Raster& texture) +template void gl_engine::Texture::upload(const radix::Raster&, unsigned); +template void gl_engine::Texture::upload(const radix::Raster&, unsigned); +template void gl_engine::Texture::upload(const radix::Raster&, unsigned); +template void gl_engine::Texture::upload>(const radix::Raster>&, unsigned); +template void gl_engine::Texture::upload>(const radix::Raster>&, unsigned); +template void gl_engine::Texture::upload>(const radix::Raster>&, unsigned); +template void gl_engine::Texture::upload>(const radix::Raster>&, unsigned); +template void gl_engine::Texture::upload>(const radix::Raster>&, unsigned); + +template void gl_engine::Texture::upload(const radix::Raster& texture) { - assert(m_target == Target::_2d); + Q_ASSERT(m_target == Target::_2d); const auto p = gl_tex_params(m_format); - assert(m_format != Format::CompressedRGBA8); - assert(m_format != Format::Invalid); - assert(sizeof(T) == p.n_bytes_per_element * p.n_elements); + Q_ASSERT(m_format != Format::CompressedRGBA8); + Q_ASSERT(m_format != Format::Invalid); + Q_ASSERT(sizeof(T) == p.n_bytes_per_element * p.n_elements); if (!p.is_texture_filterable) { - assert(m_mag_filter == Filter::Nearest); - assert(m_min_filter == Filter::Nearest); + Q_ASSERT(m_mag_filter == Filter::Nearest); + Q_ASSERT(m_min_filter == Filter::Nearest); } QOpenGLExtraFunctions* f = QOpenGLContext::currentContext()->extraFunctions(); f->glBindTexture(GLenum(m_target), m_id); f->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - f->glTexImage2D(GLenum(m_target), 0, p.internal_format, GLsizei(texture.width()), GLsizei(texture.height()), 0, p.format, p.type, texture.bytes()); + f->glTexImage2D(GLenum(m_target), 0, p.internal_format, GLsizei(texture.width()), GLsizei(texture.height()), 0, p.format, p.type, texture.bytes().data()); if (m_min_filter == Filter::MipMapLinear) f->glGenerateMipmap(GLenum(m_target)); } -template void gl_engine::Texture::upload(const nucleus::Raster&); -template void gl_engine::Texture::upload(const nucleus::Raster&); -template void gl_engine::Texture::upload(const nucleus::Raster&); -template void gl_engine::Texture::upload>(const nucleus::Raster>&); -template void gl_engine::Texture::upload>(const nucleus::Raster>&); -template void gl_engine::Texture::upload>(const nucleus::Raster>&); -template void gl_engine::Texture::upload>(const nucleus::Raster>&); -template void gl_engine::Texture::upload>(const nucleus::Raster>&); +template void gl_engine::Texture::upload(const radix::Raster&); +template void gl_engine::Texture::upload(const radix::Raster&); +template void gl_engine::Texture::upload(const radix::Raster&); +template void gl_engine::Texture::upload>(const radix::Raster>&); +template void gl_engine::Texture::upload>(const radix::Raster>&); +template void gl_engine::Texture::upload>(const radix::Raster>&); +template void gl_engine::Texture::upload>(const radix::Raster>&); +template void gl_engine::Texture::upload>(const radix::Raster>&); GLenum gl_engine::Texture::compressed_texture_format() { diff --git a/gl_engine/Texture.h b/gl_engine/Texture.h index 808bb053c..41328a8e5 100644 --- a/gl_engine/Texture.h +++ b/gl_engine/Texture.h @@ -24,7 +24,7 @@ #ifdef ANDROID #include #endif -#include +#include #include namespace gl_engine { @@ -61,8 +61,8 @@ class Texture { void upload(const nucleus::utils::ColourTexture& texture); void upload(const nucleus::utils::ColourTexture& texture, unsigned array_index); void upload(const nucleus::utils::MipmappedColourTexture& mipped_texture, unsigned array_index); - template void upload(const nucleus::Raster& texture, unsigned int array_index); - template void upload(const nucleus::Raster& texture); + template void upload(const radix::Raster& texture, unsigned int array_index); + template void upload(const radix::Raster& texture); static GLenum compressed_texture_format(); static nucleus::utils::ColourTexture::Format compression_algorithm(); @@ -82,15 +82,15 @@ class Texture { unsigned m_n_layers = unsigned(-1); }; -extern template void gl_engine::Texture::upload(const nucleus::Raster&); -extern template void gl_engine::Texture::upload(const nucleus::Raster&); -extern template void gl_engine::Texture::upload>(const nucleus::Raster>&); -extern template void gl_engine::Texture::upload>(const nucleus::Raster>&); -extern template void gl_engine::Texture::upload>(const nucleus::Raster>&); -extern template void gl_engine::Texture::upload>(const nucleus::Raster>&); +extern template void gl_engine::Texture::upload(const radix::Raster&); +extern template void gl_engine::Texture::upload(const radix::Raster&); +extern template void gl_engine::Texture::upload>(const radix::Raster>&); +extern template void gl_engine::Texture::upload>(const radix::Raster>&); +extern template void gl_engine::Texture::upload>(const radix::Raster>&); +extern template void gl_engine::Texture::upload>(const radix::Raster>&); -extern template void gl_engine::Texture::upload(const nucleus::Raster&, unsigned int); -extern template void gl_engine::Texture::upload>(const nucleus::Raster>&, unsigned int); -extern template void gl_engine::Texture::upload>(const nucleus::Raster>&, unsigned int); +extern template void gl_engine::Texture::upload(const radix::Raster&, unsigned int); +extern template void gl_engine::Texture::upload>(const radix::Raster>&, unsigned int); +extern template void gl_engine::Texture::upload>(const radix::Raster>&, unsigned int); } // namespace gl_engine diff --git a/gl_engine/TextureLayer.cpp b/gl_engine/TextureLayer.cpp index c16c0bd1a..51506a7f9 100644 --- a/gl_engine/TextureLayer.cpp +++ b/gl_engine/TextureLayer.cpp @@ -23,6 +23,7 @@ #include "Texture.h" #include "TileGeometry.h" #include +#include namespace gl_engine { @@ -55,8 +56,8 @@ void TextureLayer::draw( m_texture_array->bind(2); m_shader->set_uniform("texture_sampler", 2); - nucleus::Raster zoom_level_raster = { glm::uvec2 { 1024, 1 } }; - nucleus::Raster array_index_raster = { glm::uvec2 { 1024, 1 } }; + radix::Raster zoom_level_raster(glm::uvec2 { 1024, 1 }); + radix::Raster array_index_raster(glm::uvec2 { 1024, 1 }); for (unsigned i = 0; i < std::min(unsigned(draw_list.size()), 1024u); ++i) { const auto layer = m_gpu_array_helper.layer(draw_list[i].id); zoom_level_raster.pixel({ i, 0 }) = layer.id.zoom_level; @@ -86,8 +87,8 @@ void TextureLayer::update_gpu_tiles(const std::vector& delete } for (const auto& tile : new_tiles) { // test for validity - assert(tile.id.zoom_level < 100); - assert(tile.texture); + Q_ASSERT(tile.id.zoom_level < 100); + Q_ASSERT(tile.texture); // find empty spot and upload texture const auto layer_index = m_gpu_array_helper.add_tile(tile.id); @@ -97,8 +98,8 @@ void TextureLayer::update_gpu_tiles(const std::vector& delete void TextureLayer::set_tile_limit(unsigned int new_limit) { - assert(new_limit < 2048); // array textures with size > 2048 are not supported on all devices - assert(!m_texture_array); + Q_ASSERT(new_limit < 2048); // array textures with size > 2048 are not supported on all devices + Q_ASSERT(!m_texture_array); m_gpu_array_helper.set_tile_limit(new_limit); } diff --git a/gl_engine/TextureLayer.h b/gl_engine/TextureLayer.h index 1190ac1b9..a8a37ea57 100644 --- a/gl_engine/TextureLayer.h +++ b/gl_engine/TextureLayer.h @@ -20,10 +20,10 @@ #include "UniformBuffer.h" #include -#include #include #include #include +#include namespace nucleus::camera { class Definition; diff --git a/gl_engine/TileGeometry.cpp b/gl_engine/TileGeometry.cpp index f455117e9..1c5816060 100644 --- a/gl_engine/TileGeometry.cpp +++ b/gl_engine/TileGeometry.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,7 @@ void TileGeometry::init() { using nucleus::utils::terrain_mesh_index_generator::surface_quads_with_curtains; - assert(QOpenGLContext::currentContext()); + Q_ASSERT(QOpenGLContext::currentContext()); const auto indices = surface_quads_with_curtains(m_texture_resolution); auto index_buffer = std::make_unique(QOpenGLBuffer::IndexBuffer); index_buffer->create(); @@ -142,9 +143,9 @@ void TileGeometry::draw(ShaderProgram* shader, const nucleus::camera::Definition std::vector packed_id; packed_id.reserve(draw_list.size()); - nucleus::Raster zoom_level_raster = { glm::uvec2 { 1024, 1 } }; - nucleus::Raster array_index_raster = { glm::uvec2 { 1024, 1 } }; - nucleus::Raster bounds_raster = { glm::uvec2 { 1024, 1 } }; + radix::Raster zoom_level_raster(glm::uvec2 { 1024, 1 }); + radix::Raster array_index_raster(glm::uvec2 { 1024, 1 }); + radix::Raster bounds_raster(glm::uvec2 { 1024, 1 }); for (unsigned i = 0; i < std::min(unsigned(draw_list.size()), 1024u); ++i) { const auto& tile = draw_list[i]; bounds.push_back(glm::vec4 { tile.bounds.min.x - camera.position().x, @@ -173,10 +174,10 @@ void TileGeometry::draw(ShaderProgram* shader, const nucleus::camera::Definition m_instance_tile_id_buffer->write(0, packed_id.data(), GLsizei(packed_id.size() * sizeof(decltype(packed_id)::value_type))); m_dtm_array_index_buffer->bind(); - m_dtm_array_index_buffer->write(0, array_index_raster.bytes(), GLsizei(array_index_raster.width() * sizeof(uint16_t))); + m_dtm_array_index_buffer->write(0, array_index_raster.bytes().data(), GLsizei(array_index_raster.width() * sizeof(uint16_t))); m_dtm_zoom_buffer->bind(); - m_dtm_zoom_buffer->write(0, zoom_level_raster.bytes(), GLsizei(zoom_level_raster.width() * sizeof(uint8_t))); + m_dtm_zoom_buffer->write(0, zoom_level_raster.bytes().data(), GLsizei(zoom_level_raster.width() * sizeof(uint8_t))); f->glDrawElementsInstanced(GL_TRIANGLE_STRIP, GLsizei(m_index_buffer.second), GL_UNSIGNED_SHORT, nullptr, GLsizei(draw_list.size())); f->glBindVertexArray(0); @@ -186,7 +187,7 @@ void TileGeometry::set_aabb_decorator(const nucleus::tile::utils::AabbDecoratorP void TileGeometry::set_tile_limit(unsigned int new_limit) { - assert(!m_dtm_textures); + Q_ASSERT(!m_dtm_textures); m_gpu_array_helper.set_tile_limit(new_limit); } @@ -203,8 +204,8 @@ void TileGeometry::update_gpu_tiles(const std::vector& deleted_ } for (const auto& tile : new_tiles) { // test for validity - assert(tile.id.zoom_level < 100); - assert(tile.surface); + Q_ASSERT(tile.id.zoom_level < 100); + Q_ASSERT(tile.surface); // find empty spot and upload texture const auto layer_index = m_gpu_array_helper.add_tile(tile.id); diff --git a/gl_engine/TileGeometry.h b/gl_engine/TileGeometry.h index bfbae759c..27c89d1ac 100644 --- a/gl_engine/TileGeometry.h +++ b/gl_engine/TileGeometry.h @@ -19,10 +19,10 @@ #pragma once #include -#include #include #include #include +#include namespace camera { class Definition; diff --git a/gl_engine/Window.cpp b/gl_engine/Window.cpp index 7c2ea8c0f..00db5f627 100644 --- a/gl_engine/Window.cpp +++ b/gl_engine/Window.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -109,7 +110,7 @@ void Window::initialise_gpu() #endif QOpenGLExtraFunctions* f = QOpenGLContext::currentContext()->extraFunctions(); - assert(f->hasOpenGLFeature(QOpenGLExtraFunctions::OpenGLFeature::MultipleRenderTargets)); + Q_ASSERT(f->hasOpenGLFeature(QOpenGLExtraFunctions::OpenGLFeature::MultipleRenderTargets)); Q_UNUSED(f); DepthBufferClipType depth_buffer_clip_type = DepthBufferClipType::MinusOneToOne; @@ -533,7 +534,7 @@ void Window::pick_value(const glm::dvec2& screen_space_coordinates) void Window::update_eaws_reports(const nucleus::avalanche::UboEawsReports& newUboEawsReports) { - assert(m_eaws_reports_ubo); + Q_ASSERT(m_eaws_reports_ubo); m_eaws_reports_ubo->data = newUboEawsReports; m_eaws_reports_ubo->update_gpu_data(); emit update_requested(); diff --git a/nucleus/AbstractRenderWindow.h b/nucleus/AbstractRenderWindow.h index b6f7fe2d0..706c3b92e 100644 --- a/nucleus/AbstractRenderWindow.h +++ b/nucleus/AbstractRenderWindow.h @@ -23,6 +23,7 @@ #include +#include "camera/Definition.h" #include "utils/ColourTexture.h" class QOpenGLFramebufferObject; @@ -33,7 +34,6 @@ namespace tile::utils { using AabbDecoratorPtr = std::shared_ptr; } namespace camera { - class Definition; class AbstractDepthTester; } diff --git a/nucleus/CMakeLists.txt b/nucleus/CMakeLists.txt index 30e2f255e..de298cacc 100644 --- a/nucleus/CMakeLists.txt +++ b/nucleus/CMakeLists.txt @@ -22,8 +22,7 @@ project(alpine-renderer-nucleus LANGUAGES C CXX) alp_add_git_repository(stb_slim URL https://github.com/AlpineMapsOrgDependencies/stb_slim.git COMMITISH 547fade2a12793e1bea4733d59646b4f436e25a4) -alp_add_git_repository(radix URL https://github.com/AlpineMapsOrg/radix.git COMMITISH e939e10c5a40866950b68a0bc04c851bcfcf5dad NOT_SYSTEM) -alp_add_git_repository(tl_expected URL https://github.com/TartanLlama/expected.git COMMITISH v1.1.0 DO_NOT_ADD_SUBPROJECT) +alp_add_git_repository(radix URL https://github.com/AlpineMapsOrg/radix.git COMMITISH 9720bce6399f4581e35edc88f87651f020348b34 NOT_SYSTEM) alp_add_git_repository(zppbits URL https://github.com/eyalz800/zpp_bits.git COMMITISH v4.4.25 DO_NOT_ADD_SUBPROJECT) if(ALP_ENABLE_LABELS) alp_add_git_repository(vector_tiles URL https://github.com/AlpineMapsOrg/vector-tile.git COMMITISH faba88257716c4bc01ebd44d8b8b98f711ecb78c) @@ -40,9 +39,6 @@ add_library(goofy_tc INTERFACE) target_include_directories(goofy_tc INTERFACE ${goofy_tc_SOURCE_DIR}) set_target_properties(goofy_tc PROPERTIES SYSTEM true) -add_library(tl_expected INTERFACE) -target_include_directories(tl_expected INTERFACE ${tl_expected_SOURCE_DIR}/include) - add_library(cdt INTERFACE) target_include_directories(cdt INTERFACE ${cdt_SOURCE_DIR}/CDT/include) @@ -67,7 +63,6 @@ add_library(nucleus_version STATIC qt_add_library(nucleus STATIC AbstractRenderWindow.h event_parameter.h - Raster.h Raster3D.h srs.h srs.cpp tile/utils.h tile/utils.cpp @@ -182,7 +177,7 @@ endif() target_include_directories(nucleus PUBLIC ${CMAKE_SOURCE_DIR}) # Please keep Qt::Gui outside the nucleus. If you need it optional via a cmake based switch -target_link_libraries(nucleus PUBLIC radix Qt::Core Qt::Network zppbits tl_expected nucleus_version stb_slim goofy_tc cdt ktx) +target_link_libraries(nucleus PUBLIC radix Qt::Core Qt::Network zppbits nucleus_version stb_slim goofy_tc cdt KTX::ktx) qt_add_resources(nucleus "height_data" PREFIX "/map" diff --git a/nucleus/DataQuerier.cpp b/nucleus/DataQuerier.cpp index 09ec9f3dd..6a29c63b5 100644 --- a/nucleus/DataQuerier.cpp +++ b/nucleus/DataQuerier.cpp @@ -22,9 +22,10 @@ nucleus::DataQuerier::DataQuerier(tile::MemoryCache* cache) : m_memory_cache(cache) -{} +{ +} -tl::expected nucleus::DataQuerier::get_altitude(const glm::dvec2& lat_long) const +std::expected nucleus::DataQuerier::get_altitude(const glm::dvec2& lat_long) const { return tile::cache_queries::query_altitude(m_memory_cache, lat_long); } diff --git a/nucleus/DataQuerier.h b/nucleus/DataQuerier.h index aa793a827..4a2354646 100644 --- a/nucleus/DataQuerier.h +++ b/nucleus/DataQuerier.h @@ -24,14 +24,13 @@ namespace nucleus { -class DataQuerier -{ +class DataQuerier { tile::MemoryCache* m_memory_cache = nullptr; public: DataQuerier(tile::MemoryCache* cache); - [[nodiscard]] tl::expected get_altitude(const glm::dvec2& lat_long) const; + [[nodiscard]] std::expected get_altitude(const glm::dvec2& lat_long) const; }; } // namespace nucleus diff --git a/nucleus/EngineContext.cpp b/nucleus/EngineContext.cpp index d5b147cb1..9f0265f19 100644 --- a/nucleus/EngineContext.cpp +++ b/nucleus/EngineContext.cpp @@ -18,6 +18,8 @@ #include "EngineContext.h" +#include + using namespace nucleus; EngineContext::EngineContext() { } @@ -31,11 +33,11 @@ EngineContext::EngineContext(QObject* parent) { } -EngineContext::~EngineContext() { assert(m_initialised == m_destroyed); } +EngineContext::~EngineContext() { Q_ASSERT(m_initialised == m_destroyed); } void EngineContext::initialise() { - assert(!m_initialised); + Q_ASSERT(!m_initialised); internal_initialise(); m_initialised = true; emit initialised(); @@ -43,8 +45,8 @@ void EngineContext::initialise() void EngineContext::destroy() { - assert(m_initialised); - assert(!m_destroyed); + Q_ASSERT(m_initialised); + Q_ASSERT(!m_destroyed); internal_destroy(); m_destroyed = true; } diff --git a/nucleus/Raster.h b/nucleus/Raster.h deleted file mode 100644 index 322537c3c..000000000 --- a/nucleus/Raster.h +++ /dev/null @@ -1,188 +0,0 @@ -/***************************************************************************** - * AlpineMaps.org - * Copyright (C) 2022 Adam Celarek - * Copyright (C) 2024 Gerald Kimmersdorfer - * Copyright (C) 2024 Lucas Dworschak - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace nucleus { - -template -class Raster { - std::vector m_data; - unsigned m_width = 0; - unsigned m_height = 0; - -public: - Raster() = default; - Raster(unsigned square_side_length, std::vector&& vector) - : m_data(std::move(vector)) - , m_width(square_side_length) - , m_height(square_side_length) - { - assert(m_data.size() == m_width * m_height); - } - Raster(unsigned square_side_length) - : m_data(square_side_length * square_side_length) - , m_width(square_side_length) - , m_height(square_side_length) - { - } - Raster(const glm::uvec2& size) - : m_data(size.x * size.y) - , m_width(size.x) - , m_height(size.y) - { - } - Raster(const glm::uvec2& size, const T& fill_value) - : m_data(size.x * size.y, fill_value) - , m_width(size.x) - , m_height(size.y) - { - } - - [[nodiscard]] const std::vector& buffer() const { return m_data; } - [[nodiscard]] std::vector& buffer() { return m_data; } - [[nodiscard]] unsigned width() const { return m_width; } - [[nodiscard]] unsigned height() const { return m_height; } - [[nodiscard]] glm::uvec2 size() const { return { m_width, m_height }; } - [[nodiscard]] size_t size_in_bytes() const { return m_data.size() * sizeof(T); } - [[nodiscard]] size_t size_per_line() const { return m_width * sizeof(T); } - [[nodiscard]] size_t buffer_length() const { return m_data.size(); } - [[nodiscard]] const T& pixel(const glm::uvec2& position) const - { - assert(position.x < m_width); - assert(position.y < m_height); - return m_data[position.x + m_width * position.y]; - } - [[nodiscard]] T& pixel(const glm::uvec2& position) - { - assert(position.x < m_width); - assert(position.y < m_height); - return m_data[position.x + m_width * position.y]; - } - [[nodiscard]] const uint8_t* bytes() const { return reinterpret_cast(m_data.data()); } - [[nodiscard]] uint8_t* bytes() { return reinterpret_cast(m_data.data()); } - - void fill(const T& value) { std::fill(begin(), end(), value); } - - /// cheaper than concatenate_horizontally, works only if other has the same width - void append_vertically(const Raster& other) - { - // currently only supports combining with other raster of equal width (otherwise we need to fill either the current or the other raster with 0 values) - assert(other.width() == width()); - if (other.width() != width()) - return; - - m_height += other.height(); - - m_data.reserve(m_data.size() + (other.width() * other.height())); - m_data.insert(end(), other.begin(), other.end()); - } - - auto begin() { return m_data.begin(); } - auto end() { return m_data.end(); } - auto begin() const { return m_data.begin(); } - auto end() const { return m_data.end(); } - auto cbegin() const { return m_data.cbegin(); } - auto cend() const { return m_data.cend(); } - - const T* data() const { return m_data.data(); } - T* data() { return m_data.data(); } -}; - -namespace detail { - template - glm::vec avg(const glm::vec& a, const glm::vec& b, const glm::vec& c, const glm::vec& d) - { - glm::vec r; - for (unsigned i = 0u; i < n_dims; ++i) { - r[i] = (a[i] + b[i] + c[i] + d[i]) / 4; - } - return r; - } - template T avg(const T& a, const T& b, const T& c, const T& d) { return (a + b + c + d) / 4; } -} // namespace detail - -template std::vector> generate_mipmap(Raster raster) -{ - assert(raster.width() == raster.height()); // this code is not tested for differing sizes - assert(raster.width() > 1); // also not tested - assert((raster.width() & (raster.width() - 1)) == 0); // only power of two tested - auto resolution = raster.size(); - std::vector> mipmap; - { - auto n = 0; - for (auto x = glm::compMax(resolution); x != 0; x >>= 1) - ++n; - - mipmap.reserve(n); - } - mipmap.push_back(std::move(raster)); - while (glm::compMax(resolution) > 1) { - resolution = resolution / 2u; - Raster& u = mipmap.back(); - mipmap.push_back(Raster(resolution)); - Raster& r = mipmap.back(); - for (unsigned i = 0u; i < resolution.x; ++i) { - for (unsigned j = 0u; j < resolution.y; ++j) { - // clang-format off - r.pixel({ i, j }) = detail::avg(u.pixel({ i * 2, j * 2 }), - u.pixel({ i * 2, j * 2 + 1 }), - u.pixel({ i * 2 + 1, j * 2 }), - u.pixel({ i * 2 + 1, j * 2 + 1 })); - // clang-format on - } - } - } - return mipmap; -} - -template Raster resize(const Raster& raster, const glm::uvec2& new_size, T fill) -{ - Raster n = Raster(new_size, fill); - for (auto i = 0u; i < std::min(raster.width(), new_size.x); ++i) { - for (auto j = 0u; j < std::min(raster.height(), new_size.y); ++j) { - n.pixel({ i, j }) = raster.pixel({ i, j }); - } - } - return n; -} - -/// more expensive than append_vertically, works only if a and b have the same height. -template Raster concatenate_horizontally(const Raster& a, const Raster& b) -{ - assert(a.height() == b.height()); - Raster r({ a.width() + b.width(), a.height() }); - if (a.height() != b.height()) - return r; // shouldn't happen - - for (auto l = 0u; l < a.height(); ++l) { - auto i = std::copy_n(&a.pixel({ 0, l }), a.width(), &r.pixel({ 0, l })); - std::copy_n(&b.pixel({ 0, l }), b.width(), i); - } - return r; -} -} diff --git a/nucleus/Raster3D.h b/nucleus/Raster3D.h index cd5b86275..395c47542 100644 --- a/nucleus/Raster3D.h +++ b/nucleus/Raster3D.h @@ -22,7 +22,7 @@ #pragma once #include -#include +#include #include #include #include @@ -44,7 +44,7 @@ class Raster3D { , m_height(square_side_length) , m_depth(depth) { - assert(m_data.size() == m_width * m_height * m_depth); + Q_ASSERT(m_data.size() == m_width * m_height * m_depth); } Raster3D(unsigned square_side_length, unsigned depth) : m_data(square_side_length * square_side_length * depth) @@ -80,16 +80,16 @@ class Raster3D { [[nodiscard]] size_t buffer_length() const { return m_data.size(); } [[nodiscard]] const T& pixel(const glm::uvec3& position) const { - assert(position.x < m_width); - assert(position.y < m_height); - assert(position.z < m_depth); + Q_ASSERT(position.x < m_width); + Q_ASSERT(position.y < m_height); + Q_ASSERT(position.z < m_depth); return m_data[position.x + m_width * position.y + m_width * m_height * position.z]; } [[nodiscard]] T& pixel(const glm::uvec3& position) { - assert(position.x < m_width); - assert(position.y < m_height); - assert(position.z < m_depth); + Q_ASSERT(position.x < m_width); + Q_ASSERT(position.y < m_height); + Q_ASSERT(position.z < m_depth); return m_data[position.x + m_width * position.y + m_width * m_height * position.z]; } [[nodiscard]] const uint8_t* bytes() const { return reinterpret_cast(m_data.data()); } diff --git a/nucleus/avalanche/ReportLoadService.cpp b/nucleus/avalanche/ReportLoadService.cpp index 0d1ff958c..54e61e00a 100644 --- a/nucleus/avalanche/ReportLoadService.cpp +++ b/nucleus/avalanche/ReportLoadService.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/nucleus/avalanche/ReportLoadService.h b/nucleus/avalanche/ReportLoadService.h index 2c9f926d9..36503f553 100644 --- a/nucleus/avalanche/ReportLoadService.h +++ b/nucleus/avalanche/ReportLoadService.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include class QNetworkAccessManager; diff --git a/nucleus/avalanche/Scheduler.cpp b/nucleus/avalanche/Scheduler.cpp index 957a0edc6..9d477968e 100644 --- a/nucleus/avalanche/Scheduler.cpp +++ b/nucleus/avalanche/Scheduler.cpp @@ -20,6 +20,7 @@ #include "Scheduler.h" #include "eaws.h" #include +#include #include namespace nucleus::avalanche { @@ -42,18 +43,18 @@ void Scheduler::transform_and_emit(const std::vector& n for (const auto& quad : new_quads) { nucleus::tile::GpuEawsTile gpu_tile_from_quad; gpu_tile_from_quad.id = quad.id; - nucleus::Raster quad_as_raster = to_raster(quad, m_default_raster, m_uint_id_manager); - gpu_tile_from_quad.texture = std::make_shared>(quad_as_raster); + radix::Raster quad_as_raster = to_raster(quad, m_default_raster, m_uint_id_manager); + gpu_tile_from_quad.texture = std::make_shared>(quad_as_raster); new_gpu_tiles.push_back(gpu_tile_from_quad); } emit gpu_tiles_updated(deleted_quads, new_gpu_tiles); } -nucleus::Raster Scheduler::to_raster( - const nucleus::tile::DataQuad& quad, const nucleus::Raster& default_raster, std::shared_ptr uint_id_manager) +radix::Raster Scheduler::to_raster( + const nucleus::tile::DataQuad& quad, const radix::Raster& default_raster, std::shared_ptr uint_id_manager) { - std::array, 4> quad_rasters; + std::array, 4> quad_rasters; std::array quad_ids; for (const auto& tile : quad.tiles) { const auto quad_index = unsigned(quad_position(tile.id)); @@ -65,7 +66,7 @@ nucleus::Raster Scheduler::to_raster( } // Read vector tile from data - tl::expected result = vector_tile_reader(*tile.data, tile.id); + std::expected result = vector_tile_reader(*tile.data, tile.id); // could not read vector tile from data, use default raster if (!result.has_value()) { @@ -78,7 +79,7 @@ nucleus::Raster Scheduler::to_raster( QImage eawsImage = draw_regions(eaws_region_tile, uint_id_manager, 256, 256, tile.id); // Convert Qimage to raster with a 16bit uint region id - nucleus::Raster eaws_raster_16bit(glm::uvec2(256, 256), 0); + radix::Raster eaws_raster_16bit(glm::uvec2(256, 256), 0); for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { glm::u8vec4 color_vector_8bit(0, 0, 0, 0); @@ -90,17 +91,27 @@ nucleus::Raster Scheduler::to_raster( } // Collect raster of current tile in quad - quad_rasters[quad_index] = nucleus::Raster(eaws_raster_16bit); + quad_rasters[quad_index] = radix::Raster(eaws_raster_16bit); } // Merge 4 tiles from quad into one raster representing the quad - nucleus::Raster quad_as_raster - = nucleus::concatenate_horizontally(quad_rasters[unsigned(tile::QuadPosition::TopLeft)], quad_rasters[unsigned(tile::QuadPosition::TopRight)]); - quad_as_raster.append_vertically( - nucleus::concatenate_horizontally(quad_rasters[unsigned(tile::QuadPosition::BottomLeft)], quad_rasters[unsigned(tile::QuadPosition::BottomRight)])); + auto top + = radix::raster::concatenate_horizontally(quad_rasters[unsigned(tile::QuadPosition::TopLeft)], quad_rasters[unsigned(tile::QuadPosition::TopRight)]); + auto bottom = radix::raster::concatenate_horizontally( + quad_rasters[unsigned(tile::QuadPosition::BottomLeft)], quad_rasters[unsigned(tile::QuadPosition::BottomRight)]); + if (!top || !bottom) { + Q_ASSERT(false && "Avalanche quad rasters must have compatible dimensions"); + return {}; + } + + auto quad_as_raster = radix::raster::concatenate_vertically(*top, *bottom); + if (!quad_as_raster) { + Q_ASSERT(false && "Avalanche quad raster rows must have compatible dimensions"); + return {}; + } // return raster represntation of provided quad - return quad_as_raster; + return std::move(*quad_as_raster); } } // namespace nucleus::avalanche diff --git a/nucleus/avalanche/Scheduler.h b/nucleus/avalanche/Scheduler.h index 260bc3b00..dfb3a223d 100644 --- a/nucleus/avalanche/Scheduler.h +++ b/nucleus/avalanche/Scheduler.h @@ -28,8 +28,8 @@ class Scheduler : public nucleus::tile::Scheduler { public: Scheduler(const Scheduler::Settings& settings); ~Scheduler(); - static nucleus::Raster to_raster( - const nucleus::tile::DataQuad& quad, const nucleus::Raster& default_raster, std::shared_ptr uint_id_manager); + static radix::Raster to_raster( + const nucleus::tile::DataQuad& quad, const radix::Raster& default_raster, std::shared_ptr uint_id_manager); std::shared_ptr get_uint_id_manager() { return m_uint_id_manager; } signals: @@ -39,7 +39,7 @@ class Scheduler : public nucleus::tile::Scheduler { void transform_and_emit(const std::vector& new_quads, const std::vector& deleted_quads) override; private: - nucleus::Raster m_default_raster; + radix::Raster m_default_raster; std::shared_ptr m_uint_id_manager; }; diff --git a/nucleus/avalanche/UIntIdManager.cpp b/nucleus/avalanche/UIntIdManager.cpp index 8d6d9801f..d64442fbc 100644 --- a/nucleus/avalanche/UIntIdManager.cpp +++ b/nucleus/avalanche/UIntIdManager.cpp @@ -27,7 +27,8 @@ #include #include #include -#include +#include +#include #include namespace nucleus::avalanche { @@ -37,7 +38,7 @@ UIntIdManager::UIntIdManager(const QDate& reference_date) // intern_id = 0 means "no region" m_region_id_to_internal_id[QString("")] = 0; m_internal_id_to_region_id[0] = QString(""); - assert(m_max_internal_id == 0); + Q_ASSERT(m_max_internal_id == 0); } uint UIntIdManager::convert_region_id_to_internal_id(const QString& region_id) diff --git a/nucleus/avalanche/UIntIdManager.h b/nucleus/avalanche/UIntIdManager.h index 5be115b72..4b457cf00 100644 --- a/nucleus/avalanche/UIntIdManager.h +++ b/nucleus/avalanche/UIntIdManager.h @@ -3,7 +3,7 @@ #include #include #include -#include +#include class QNetworkAccessManager; namespace nucleus::avalanche { diff --git a/nucleus/avalanche/eaws.cpp b/nucleus/avalanche/eaws.cpp index 1bea72a17..60d748bf1 100644 --- a/nucleus/avalanche/eaws.cpp +++ b/nucleus/avalanche/eaws.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ namespace nucleus::avalanche { -tl::expected vector_tile_reader(const QByteArray& input_data, const radix::tile::Id& tile_id) +std::expected vector_tile_reader(const QByteArray& input_data, const radix::tile::Id& tile_id) { // This name could theoretically be changed by the EAWS (very unlikely though) const QString& name_of_layer_with_eaws_regions = "micro-regions"; @@ -44,7 +45,7 @@ tl::expected vector_tile_reader(const QByteArray& input_dat if (!layers.contains(name_of_layer_with_eaws_regions.toStdString())) { QString error_message = "ERROR in vector_tile::reader::eaws_region: The vector tile contains no layer with name " + name_of_layer_with_eaws_regions + "."; - return tl::unexpected(error_message); + return std::unexpected(error_message); } // Get the relevant layer and check if it contains data @@ -52,13 +53,13 @@ tl::expected vector_tile_reader(const QByteArray& input_dat if (layer.featureCount() <= 0) { QString error_message = "ERROR in vector_tile::reader::eaws_region: The vector tile contains no EAWS micro-regions in the layer \"" + name_of_layer_with_eaws_regions + "\"."; - return tl::unexpected(error_message); + return std::unexpected(error_message); } // Ensure extend > 0. Extend is an integer representing the resolution of the square tile. Usually the extend is 4096 if (layer.getExtent() <= 0) { QString error_message = "ERROR in vector_tile::reader::eaws_region: Vector tile has extend <= 0."; - return tl::unexpected(error_message); + return std::unexpected(error_message); } uint extent = layer.getExtent(); @@ -95,20 +96,20 @@ tl::expected vector_tile_reader(const QByteArray& input_dat } // Combine all regions with their tile id and return this pair - return tl::expected(RegionTile(tile_id, regions_to_be_returned)); + return std::expected(RegionTile(tile_id, regions_to_be_returned)); } // Auxillary function: Calculates new coordinates of a region boundary after zoom in / out std::vector transform_vertices(const Region& region, const radix::tile::Id& tile_id_in, const radix::tile::Id& tile_id_out, QImage* img) { // Check if input is consistent - assert(img->devicePixelRatio() == 1.0); - assert((region.resolution.x > 0 && region.resolution.y > 0)); - assert((img->width() > 0 && img->height() > 0)); - assert(tile_id_in.coords.x < qPow(2, tile_id_in.zoom_level)); - assert(tile_id_in.coords.y < qPow(2, tile_id_in.zoom_level)); - assert(tile_id_out.coords.x < qPow(2, tile_id_out.zoom_level)); - assert(tile_id_out.coords.y < qPow(2, tile_id_out.zoom_level)); + Q_ASSERT(img->devicePixelRatio() == 1.0); + Q_ASSERT((region.resolution.x > 0 && region.resolution.y > 0)); + Q_ASSERT((img->width() > 0 && img->height() > 0)); + Q_ASSERT(tile_id_in.coords.x < qPow(2, tile_id_in.zoom_level)); + Q_ASSERT(tile_id_in.coords.y < qPow(2, tile_id_in.zoom_level)); + Q_ASSERT(tile_id_out.coords.x < qPow(2, tile_id_out.zoom_level)); + Q_ASSERT(tile_id_out.coords.y < qPow(2, tile_id_out.zoom_level)); // Check whether we are zooming in or out for the output raster uint zoom_level_in = tile_id_in.zoom_level; @@ -123,8 +124,8 @@ std::vector transform_vertices(const Region& region, const radix::tile: if (zoom_level_in < zoom_level_out) { // Output tile origin must lie within input tile - assert(origin_in.x <= origin_out.x && origin_in.y <= origin_out.y); - assert(origin_out.x + tile_size_out <= origin_in.x + tile_size_in && origin_out.y + tile_size_out <= origin_in.y + tile_size_in); + Q_ASSERT(origin_in.x <= origin_out.x && origin_in.y <= origin_out.y); + Q_ASSERT(origin_out.x + tile_size_out <= origin_in.x + tile_size_in && origin_out.y + tile_size_out <= origin_in.y + tile_size_in); // Determine origin of output tile w.r.t to input tile. Result in [0,1]x[0,1] since the output origin lies within the input tile relative_origin = glm::vec2((origin_out.x - origin_in.x) / tile_size_in, (origin_out.y - origin_in.y) / tile_size_in); @@ -135,12 +136,12 @@ std::vector transform_vertices(const Region& region, const radix::tile: } // This case does not work and it is not clear at this point if this case is necessary - assert(zoom_level_in <= zoom_level_out); + Q_ASSERT(zoom_level_in <= zoom_level_out); /* else if (zoom_level_out < zoom_level_in) { // zoom_in > zoom_out => Output tile origin must lie within input tile - assert(origin_out.x <= origin_in.x && origin_out.y <= origin_in.y); - assert(origin_in.x + tile_size_in <= origin_out.x + tile_size_out && origin_in.y + tile_size_in <= origin_out.y + tile_size_out); + Q_ASSERT(origin_out.x <= origin_in.x && origin_out.y <= origin_in.y); + Q_ASSERT(origin_in.x + tile_size_in <= origin_out.x + tile_size_out && origin_in.y + tile_size_in <= origin_out.y + tile_size_out); // Determine origin of input tile w.r.t to output tile. Results in [0,1]x[0,1] since the input origin must lie within the ouput tile relative_origin = glm::vec2((origin_in.x - origin_out.x) / tile_size_out, (origin_in.y - origin_out.y) / tile_size_out); @@ -178,7 +179,7 @@ QImage draw_regions(const RegionTile& region_tile, painter.setRenderHint(QPainter::Antialiasing, false); // Draw all regions to the image - assert(region_tile.second.size() > 0); + Q_ASSERT(region_tile.second.size() > 0); radix::tile::Id tile_id_in = region_tile.first; for (const auto& region : region_tile.second) { // Only draw regions as of July 1st 2025 @@ -195,15 +196,15 @@ QImage draw_regions(const RegionTile& region_tile, painter.setPen(QPen(color_of_region)); // we also have to set the pen if we want to draw boundaries // Draw polygon: The first point is implicitly connected to the last point, and the polygon is filled with the current brush(). - assert(img.devicePixelRatio() == 1.0); + Q_ASSERT(img.devicePixelRatio() == 1.0); painter.drawPolygon(transformed_vertices_as_QPointFs.data(), transformed_vertices_as_QPointFs.size()); - assert(img.devicePixelRatio() == 1.0); + Q_ASSERT(img.devicePixelRatio() == 1.0); } // return image with all regions in it return img; } -nucleus::Raster rasterize_regions(const RegionTile& region_tile, +radix::Raster rasterize_regions(const RegionTile& region_tile, std::shared_ptr internal_id_manager, const uint raster_width, const uint raster_height, @@ -215,7 +216,7 @@ nucleus::Raster rasterize_regions(const RegionTile& region_tile, return raster; } -nucleus::Raster rasterize_regions(const RegionTile& region_tile, std::shared_ptr internal_id_manager) +radix::Raster rasterize_regions(const RegionTile& region_tile, std::shared_ptr internal_id_manager) { return rasterize_regions(region_tile, internal_id_manager, region_tile.second[0].resolution.x, region_tile.second[0].resolution.y, region_tile.first); } diff --git a/nucleus/avalanche/eaws.h b/nucleus/avalanche/eaws.h index 0a6ba661d..95ebda30f 100644 --- a/nucleus/avalanche/eaws.h +++ b/nucleus/avalanche/eaws.h @@ -19,9 +19,9 @@ #include #include -#include +#include #include -#include +#include namespace radix::tile { struct Id; @@ -56,7 +56,7 @@ using RegionTile = std::pair>; * @param input_data: An array holding the data read froma vector tile (usually obtained by reading a from a mvt file). * @param tile_id: The zoom, x-y-cordinates and tile-scheme belonging to the input data */ -tl::expected vector_tile_reader(const QByteArray& input_data, const radix::tile::Id& tile_id); +std::expected vector_tile_reader(const QByteArray& input_data, const radix::tile::Id& tile_id); // This struct contains report data written to ubo on gpu struct UboEawsReports { @@ -74,12 +74,12 @@ QImage draw_regions(const RegionTile& region_tile, // Creates a raster from a QImage with regions in it. Throws error when raster_width or raster_height is 0. // Note: tile_id_out must have greater or equal zoomlevel than tile_id_in -nucleus::Raster rasterize_regions(const RegionTile& region_tile, +radix::Raster rasterize_regions(const RegionTile& region_tile, std::shared_ptr internal_id_manager, const uint raster_width, const uint raster_height, const radix::tile::Id& tile_id_out); // Overload: Output has same resolution as EAWS regions, throws error when regions.size() == 0 -nucleus::Raster rasterize_regions(const RegionTile& region_tile, std::shared_ptr internal_id_manager); +radix::Raster rasterize_regions(const RegionTile& region_tile, std::shared_ptr internal_id_manager); } // namespace nucleus::avalanche diff --git a/nucleus/camera/OrbitInteraction.cpp b/nucleus/camera/OrbitInteraction.cpp index 783b1fd84..fa364d338 100644 --- a/nucleus/camera/OrbitInteraction.cpp +++ b/nucleus/camera/OrbitInteraction.cpp @@ -22,6 +22,7 @@ #include "AbstractDepthTester.h" #include "gesture.h" #include +#include #include namespace nucleus::camera { @@ -79,7 +80,7 @@ std::optional OrbitInteraction::touch_event(const event_parameter::T } if (gesture->just_activated) { - assert(gesture->values.contains(gesture::ValueName::Pivot)); + Q_ASSERT(gesture->values.contains(gesture::ValueName::Pivot)); const auto& pivot = gesture->values[gesture::ValueName::Pivot]; start(pivot, camera, depth_tester); // Set m_operation_centre m_operation_centre_screen = pivot; diff --git a/nucleus/camera/gesture.h b/nucleus/camera/gesture.h index fa2fa30f9..10bd54cb7 100644 --- a/nucleus/camera/gesture.h +++ b/nucleus/camera/gesture.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -55,7 +56,7 @@ class Controller { std::optional analise(const event_parameter::Touch& t, const glm::uvec2& viewport_size) { - assert(std::is_sorted(t.points.begin(), t.points.end(), [](const auto& a, const auto& b) { return a.id < b.id; })); + Q_ASSERT(std::is_sorted(t.points.begin(), t.points.end(), [](const auto& a, const auto& b) { return a.id < b.id; })); const auto filtered_touch = filter_sloppy_touches(t, viewport_size); if (m_active_detector) { @@ -399,8 +400,8 @@ class PinchAndRotateDetector : public Detector { float rotation_val = 0; for (const auto id : m_touch_ids) { - assert(m_last_angles.contains(id)); - assert(current_angles.contains(id)); + Q_ASSERT(m_last_angles.contains(id)); + Q_ASSERT(current_angles.contains(id)); const auto last_angle = m_last_angles.at(id); const auto current_angle = current_angles.at(id); auto diff = current_angle - last_angle; @@ -411,7 +412,7 @@ class PinchAndRotateDetector : public Detector { rotation_val += diff; } rotation_val = glm::degrees(rotation_val / m_touch_ids.size()); - assert(std::abs(rotation_val) < 180); + Q_ASSERT(std::abs(rotation_val) < 180); // --- Activation --- Result g; diff --git a/nucleus/map_label/Factory.cpp b/nucleus/map_label/Factory.cpp index 3e5400779..d6fd088d0 100644 --- a/nucleus/map_label/Factory.cpp +++ b/nucleus/map_label/Factory.cpp @@ -19,13 +19,17 @@ #include "Factory.h" +#include +#include + #include #include +#include -#include "nucleus/Raster.h" #include "nucleus/picker/types.h" #include "nucleus/utils/image_loader.h" #include +#include #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION @@ -63,33 +67,39 @@ AtlasData Factory::renew_font_atlas() /** * this function needs to be called before create_labels */ -Raster Factory::label_icons() +radix::Raster Factory::label_icons() { using PoiType = vector_tile::PointOfInterest::Type; - auto icons = std::unordered_map>(); - icons[PoiType::Peak] = nucleus::utils::image_loader::rgba8(":/map_icons/peak.png").value(); - icons[PoiType::Settlement] = nucleus::utils::image_loader::rgba8(":/map_icons/city.png").value(); - icons[PoiType::AlpineHut] = nucleus::utils::image_loader::rgba8(":/map_icons/alpinehut.png").value(); - icons[PoiType::Webcam] = nucleus::utils::image_loader::rgba8(":/map_icons/camera.png").value(); - icons[PoiType::Unknown] = nucleus::Raster(icons[PoiType::Peak].size(), glm::u8vec4(255, 0, 128, 255)); - - size_t combined_height(0); - - for (int i = 0; i < int(PoiType::NumberOfElements); i++) { - PoiType type = PoiType(i); - combined_height += icons[type].height(); - } + constexpr auto icon_count = static_cast(PoiType::NumberOfElements); + std::array, icon_count> icons; + const auto icon = [&](const PoiType type) -> auto& { return icons[static_cast(type)]; }; + + icon(PoiType::Peak) = nucleus::utils::image_loader::rgba8(":/map_icons/peak.png").value(); + icon(PoiType::Settlement) = nucleus::utils::image_loader::rgba8(":/map_icons/city.png").value(); + icon(PoiType::AlpineHut) = nucleus::utils::image_loader::rgba8(":/map_icons/alpinehut.png").value(); + icon(PoiType::Webcam) = nucleus::utils::image_loader::rgba8(":/map_icons/camera.png").value(); + icon(PoiType::Unknown) = radix::Raster(icon(PoiType::Peak).size(), glm::u8vec4(255, 0, 128, 255)); - auto combined_icons = Raster({ icons[PoiType::Peak].width(), 0 }); + std::size_t combined_height = 0; - for (int i = 0; i < int(PoiType::NumberOfElements); i++) { - PoiType type = PoiType(i); + for (const auto& raster : icons) + combined_height += raster.height(); + + std::size_t current_height = 0; + for (std::size_t i = 0; i < icon_count; ++i) { + const auto type = static_cast(i); // vec4(10.0f,...) is an uv_offset to indicate that the icon texture should be used. - m_icon_uvs[type] = glm::vec4(10.0f, 10.0f + float(combined_icons.height()) / float(combined_height), 1.0f, float(icons[type].height()) / float(combined_height)); - combined_icons.append_vertically(icons[type]); + m_icon_uvs[type] = glm::vec4(10.0f, 10.0f + float(current_height) / float(combined_height), 1.0f, float(icons[i].height()) / float(combined_height)); + current_height += icons[i].height(); + } + + auto combined_icons = radix::raster::concatenate_vertically(std::span>(icons)); + if (!combined_icons) { + Q_ASSERT(false && "Map label icons must have equal widths"); + return {}; } - return combined_icons; + return std::move(*combined_icons); } std::tuple, glm::dvec3, AtlasData> Factory::create_labels(const vector_tile::PointOfInterestCollection& pois) @@ -184,7 +194,7 @@ std::vector inline Factory::create_text_meta(std::u16string* safe_chars, safe_chars->at(i) = 32; } - assert(m_font_data.char_data.contains(safe_chars->at(i))); + Q_ASSERT(m_font_data.char_data.contains(safe_chars->at(i))); int advance, lsb; stbtt_GetCodepointHMetrics(&m_font_data.fontinfo, int(safe_chars->at(i)), &advance, &lsb); diff --git a/nucleus/map_label/Factory.h b/nucleus/map_label/Factory.h index f4c64466a..a0dd82238 100644 --- a/nucleus/map_label/Factory.h +++ b/nucleus/map_label/Factory.h @@ -25,10 +25,10 @@ #include #include -#include #include #include #include +#include namespace nucleus::map_label { @@ -38,7 +38,7 @@ class Factory { public: AtlasData init_font_atlas(); AtlasData renew_font_atlas(); - Raster label_icons(); + radix::Raster label_icons(); std::tuple, glm::dvec3, AtlasData> create_labels(const vector_tile::PointOfInterestCollection& pois); static const inline std::vector m_indices = { 0, 1, 2, 0, 2, 3 }; @@ -59,4 +59,4 @@ class Factory { std::set m_new_chars; FontRenderer m_font_renderer; }; -} // namespace nucleus::maplabel +} // namespace nucleus::map_label diff --git a/nucleus/map_label/Filter.cpp b/nucleus/map_label/Filter.cpp index e864d1a0e..92f56b36a 100644 --- a/nucleus/map_label/Filter.cpp +++ b/nucleus/map_label/Filter.cpp @@ -19,6 +19,7 @@ #include "Filter.h" #include +#include namespace nucleus::map_label { @@ -61,10 +62,10 @@ void Filter::update_quads(const std::vector& updated_tiles } for (const auto& tile : updated_tiles) { - assert(tile.data); - assert(tile.id.zoom_level < 100); - assert(!m_all_pois.contains(tile.id)); - assert(std::find(removed_tiles.cbegin(), removed_tiles.cend(), tile.id) == removed_tiles.cend()); + Q_ASSERT(tile.data); + Q_ASSERT(tile.id.zoom_level < 100); + Q_ASSERT(!m_all_pois.contains(tile.id)); + Q_ASSERT(std::find(removed_tiles.cbegin(), removed_tiles.cend(), tile.id) == removed_tiles.cend()); m_tiles_to_filter.push(tile.id); m_all_pois[tile.id] = tile.data; @@ -111,7 +112,7 @@ PointOfInterestCollection Filter::apply_filter(const PointOfInterestCollection& return false; return true; } - assert(false); + Q_ASSERT(false); return true; }); return filtered_pois; diff --git a/nucleus/map_label/FontRenderer.cpp b/nucleus/map_label/FontRenderer.cpp index fddc2dcdf..a4f0876ac 100644 --- a/nucleus/map_label/FontRenderer.cpp +++ b/nucleus/map_label/FontRenderer.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -31,14 +32,14 @@ void FontRenderer::init() // load ttf file QFile file(":/fonts/Roboto/Roboto-Bold.ttf"); const auto open = file.open(QIODeviceBase::OpenModeFlag::ReadOnly); - assert(open); + Q_ASSERT(open); Q_UNUSED(open); m_font_file = file.readAll(); // init font and get info about the dimensions const auto font_init = stbtt_InitFont(&m_font_data.fontinfo, reinterpret_cast(m_font_file.constData()), stbtt_GetFontOffsetForIndex(reinterpret_cast(m_font_file.constData()), 0)); - assert(font_init); + Q_ASSERT(font_init); Q_UNUSED(font_init); m_outline_margin = int(std::ceil(m_font_outline)); @@ -50,7 +51,7 @@ void FontRenderer::init() m_texture_index = 0; - m_font_atlas.push_back(Raster({ m_font_atlas_size.width(), m_font_atlas_size.height() }, glm::u8vec2(0))); + m_font_atlas.push_back(radix::Raster({ m_font_atlas_size.width(), m_font_atlas_size.height() }, glm::u8vec2(0))); } void FontRenderer::render(std::set chars, float font_size) @@ -64,7 +65,7 @@ void FontRenderer::render(std::set chars, float font_size) // static int counter = 1; // for(size_t i = 0; i < m_font_atlas.size(); i++) // { -// Raster rgba_raster = { m_font_atlas[i].size(), { 255, 255, 0, 255 } }; +// radix::Raster rgba_raster = { m_font_atlas[i].size(), { 255, 255, 0, 255 } }; // std::transform(m_font_atlas[i].cbegin(), m_font_atlas[i].cend(), rgba_raster.begin(), [](const auto& v) { return glm::u8vec4(v.x, v.y, 0, 255); }); // const auto debug_out = QImage(rgba_raster.bytes(), font_atlas_size.width(), font_atlas_size.height(), QImage::Format_RGBA8888); // debug_out.save(QString("font_atlas_%1_%2.png").arg(i).arg(counter)); @@ -80,9 +81,9 @@ void FontRenderer::render_text(std::set chars, float font_size) // stb_truetype only supports one dimensional bitmap // we therefore have to create a 1d temp_raster that is later merged with the actual texture - std::vector> temp_raster = std::vector>(); + std::vector> temp_raster = std::vector>(); int temp_texture_index = 0; - temp_raster.push_back(Raster({ m_font_atlas_size.width(), m_font_atlas_size.height() }, uint8_t(0))); + temp_raster.push_back(radix::Raster({ m_font_atlas_size.width(), m_font_atlas_size.height() }, uint8_t(0))); for (const char16_t& c : chars) { // code adapted from stbtt_BakeFontBitmap() @@ -113,13 +114,13 @@ void FontRenderer::render_text(std::set chars, float font_size) // - e.g. if you created a bold version or a font with different font size create a separate draw-call with the separate texture array bound // - note this requires a bit of refactoring qDebug() << "Font doesnt fit into bitmap"; - assert(false); + Q_ASSERT(false); break; // doesnt fit in image´ } temp_texture_index++; - temp_raster.push_back(Raster({ m_font_atlas_size.width(), m_font_atlas_size.height() }, uint8_t(0))); - m_font_atlas.push_back(Raster({ m_font_atlas_size.width(), m_font_atlas_size.height() }, glm::u8vec2(0))); + temp_raster.push_back(radix::Raster({ m_font_atlas_size.width(), m_font_atlas_size.height() }, uint8_t(0))); + m_font_atlas.push_back(radix::Raster({ m_font_atlas_size.width(), m_font_atlas_size.height() }, glm::u8vec2(0))); m_y = m_outline_margin + m_font_padding.y; m_bottom_y = m_outline_margin + m_font_padding.y; @@ -188,7 +189,7 @@ void FontRenderer::make_outline(std::set chars) } } -std::vector> FontRenderer::font_atlas() { return m_font_atlas; } +std::vector> FontRenderer::font_atlas() { return m_font_atlas; } const FontData& FontRenderer::font_data() { return m_font_data; } } // namespace nucleus::map_label diff --git a/nucleus/map_label/FontRenderer.h b/nucleus/map_label/FontRenderer.h index 5b3b7c9d9..3be06fd78 100644 --- a/nucleus/map_label/FontRenderer.h +++ b/nucleus/map_label/FontRenderer.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include namespace nucleus::map_label { @@ -44,7 +44,7 @@ class FontRenderer void init(); void render(std::set chars, float font_size); const FontData& font_data(); - std::vector> font_atlas(); + std::vector> font_atlas(); static constexpr QSize m_font_atlas_size = QSize(1024, 1024); static constexpr int m_max_textures = 8; @@ -66,7 +66,7 @@ class FontRenderer FontData m_font_data; - std::vector> m_font_atlas; + std::vector> m_font_atlas; QByteArray m_font_file; diff --git a/nucleus/map_label/Scheduler.cpp b/nucleus/map_label/Scheduler.cpp index b7de77e8d..f98fc1007 100644 --- a/nucleus/map_label/Scheduler.cpp +++ b/nucleus/map_label/Scheduler.cpp @@ -18,6 +18,8 @@ *****************************************************************************/ #include "Scheduler.h" +#include + #include namespace nucleus::map_label { @@ -34,7 +36,7 @@ void Scheduler::transform_and_emit(const std::vector& new_quads, std::vector new_gpu_tiles; new_gpu_tiles.reserve(new_quads.size() * 4); for (const auto& data_quad : new_quads) { - assert(data_quad.n_tiles == 4); + Q_ASSERT(data_quad.n_tiles == 4); for (const auto& data_tile : data_quad.tiles) { vector_tile::PoiTile gpu_tile; gpu_tile.id = data_tile.id; @@ -57,7 +59,7 @@ void Scheduler::transform_and_emit(const std::vector& new_quads, bool Scheduler::is_ready_to_ship(const nucleus::tile::DataQuad& quad) const { - assert(m_geometry_ram_cache); + Q_ASSERT(m_geometry_ram_cache); return m_geometry_ram_cache->contains(quad.id); } diff --git a/nucleus/map_label/types.h b/nucleus/map_label/types.h index b6db4a391..b759f862c 100644 --- a/nucleus/map_label/types.h +++ b/nucleus/map_label/types.h @@ -22,7 +22,7 @@ #include -#include +#include struct stbtt_fontinfo; @@ -45,7 +45,7 @@ struct VertexData { struct AtlasData { bool changed; - std::vector> font_atlas; + std::vector> font_atlas; }; -} // namespace nucleus::maplabel +} // namespace nucleus::map_label diff --git a/nucleus/picker/PickerManager.cpp b/nucleus/picker/PickerManager.cpp index 69fd94112..032d4f2af 100644 --- a/nucleus/picker/PickerManager.cpp +++ b/nucleus/picker/PickerManager.cpp @@ -18,6 +18,7 @@ #include "PickerManager.h" #include +#include #include @@ -39,7 +40,7 @@ namespace { case Type::Unknown: return "PoiUnknwon"; } - assert(false); + Q_ASSERT(false); return "Unknown"; } } // namespace @@ -89,7 +90,7 @@ void PickerManager::update_quads(const std::vector& new_ti remove_tile(id); } for (const auto& tile : new_tiles) { - assert(tile.id.zoom_level < 100); + Q_ASSERT(tile.id.zoom_level < 100); add_tile(tile.id, tile.data); } } diff --git a/nucleus/tile/Cache.h b/nucleus/tile/Cache.h index 3a058d95c..ab5c858fc 100644 --- a/nucleus/tile/Cache.h +++ b/nucleus/tile/Cache.h @@ -20,12 +20,13 @@ #include "types.h" #include +#include #include #include #include #include #include -#include +#include #include #include #include @@ -78,8 +79,8 @@ class Cache const T& peak_at(const tile::Id& id) const; std::vector purge(unsigned remaining_capacity); - [[nodiscard]] tl::expected write_to_disk(const std::filesystem::path& path); - [[nodiscard]] tl::expected read_from_disk(const std::filesystem::path& path); + [[nodiscard]] std::expected write_to_disk(const std::filesystem::path& path); + [[nodiscard]] std::expected read_from_disk(const std::filesystem::path& path); private: template @@ -132,9 +133,9 @@ const T& Cache::peak_at(const tile::Id& id) const return m_data.at(id).data; } -template tl::expected Cache::write_to_disk(const std::filesystem::path& base_path) +template std::expected Cache::write_to_disk(const std::filesystem::path& base_path) { - const auto unexpected_error = [](const auto& e) { return tl::unexpected(QString::fromStdString(std::make_error_code(e).message())); }; + const auto unexpected_error = [](const auto& e) { return std::unexpected(QString::fromStdString(std::make_error_code(e).message())); }; static_assert(SerialisableTile); std::filesystem::create_directories(base_path); std::unordered_map data; @@ -144,11 +145,11 @@ template tl::expected Cache::write_to_disk(const } auto locker = std::scoped_lock(m_disk_cached_mutex); - const auto write = [](const auto& bytes, const auto& path) -> tl::expected { + const auto write = [](const auto& bytes, const auto& path) -> std::expected { QFile file(path); const auto success = file.open(QIODeviceBase::WriteOnly); if (!success) - return tl::unexpected(QString("Couldn't open file '%1' for writing!").arg(QString::fromStdString(path.string()))); + return std::unexpected(QString("Couldn't open file '%1' for writing!").arg(QString::fromStdString(path.string()))); file.write(bytes.data(), qint64(bytes.size())); return {}; }; @@ -218,12 +219,12 @@ template tl::expected Cache::write_to_disk(const return {}; } -template tl::expected Cache::read_from_disk(const std::filesystem::path& base_path) +template std::expected Cache::read_from_disk(const std::filesystem::path& base_path) { - const auto unexpected_error = [](const auto& e) { return tl::unexpected(QString::fromStdString(std::make_error_code(e).message())); }; + const auto unexpected_error = [](const auto& e) { return std::unexpected(QString::fromStdString(std::make_error_code(e).message())); }; auto locker = std::scoped_lock(m_data_mutex, m_disk_cached_mutex); - assert(SerialisableTile); - const auto check_version = [&unexpected_error](auto* in, const auto& path) -> tl::expected { + Q_ASSERT(SerialisableTile); + const auto check_version = [&unexpected_error](auto* in, const auto& path) -> std::expected { std::remove_cvref_t version_info = {}; { const auto r = (*in)(version_info); @@ -233,7 +234,7 @@ template tl::expected Cache::read_from_disk(cons if (version_info != T::version_information) { version_info[version_info.size() - 1] = 0; // make sure that the string is 0 terminated. - return tl::unexpected(QString("Cache file '%1' has incompatible version! Disk " + return std::unexpected(QString("Cache file '%1' has incompatible version! Disk " "version is '%2', but we expected '%3'.") .arg(QString::fromStdString(path.string())) .arg(version_info.data()) @@ -241,11 +242,11 @@ template tl::expected Cache::read_from_disk(cons } return {}; }; - const auto read_all = [](const auto& path) -> tl::expected { + const auto read_all = [](const auto& path) -> std::expected { QFile file(path); const auto success = file.open(QIODeviceBase::ReadOnly); if (!success) - return tl::unexpected(QString("Couldn't open file '%1' for reading!").arg(QString::fromStdString(path.string()))); + return std::unexpected(QString("Couldn't open file '%1' for reading!").arg(QString::fromStdString(path.string()))); return file.readAll(); }; const auto clean_up = [&]() { @@ -259,7 +260,7 @@ template tl::expected Cache::read_from_disk(cons const auto bytes = read_all(path); if (!bytes.has_value()) { clean_up(); - return tl::unexpected(bytes.error()); + return std::unexpected(bytes.error()); } zpp::bits::in in(bytes.value()); { @@ -286,7 +287,7 @@ template tl::expected Cache::read_from_disk(cons const auto bytes = read_all(path); if (!bytes.has_value()) { clean_up(); - return tl::unexpected(bytes.error()); + return std::unexpected(bytes.error()); } zpp::bits::in in(bytes.value()); { diff --git a/nucleus/tile/GeometryScheduler.cpp b/nucleus/tile/GeometryScheduler.cpp index 9460bddf9..f373c281e 100644 --- a/nucleus/tile/GeometryScheduler.cpp +++ b/nucleus/tile/GeometryScheduler.cpp @@ -47,11 +47,11 @@ void GeometryScheduler::transform_and_emit(const std::vector& ne if (tile.data->size()) { // tile is available using namespace nucleus::utils; - gpu_tile.surface = std::make_shared>( + gpu_tile.surface = std::make_shared>( image_loader::rgba8(*tile.data).and_then(error::wrap_to_expected(conversion::to_u16raster)).value_or(m_default_raster)); } else { // tile is not available (use default tile) - gpu_tile.surface = std::make_shared>(m_default_raster); + gpu_tile.surface = std::make_shared>(m_default_raster); } new_gpu_tiles.push_back(gpu_tile); } diff --git a/nucleus/tile/GeometryScheduler.h b/nucleus/tile/GeometryScheduler.h index 974a95666..bdcf019fd 100644 --- a/nucleus/tile/GeometryScheduler.h +++ b/nucleus/tile/GeometryScheduler.h @@ -30,7 +30,7 @@ class GeometryScheduler : public Scheduler { ~GeometryScheduler() override; void set_texture_compression_algorithm(nucleus::utils::ColourTexture::Format compression_algorithm); - static Raster to_raster(const tile::DataQuad& data_quad, const Raster& default_raster); + static radix::Raster to_raster(const tile::DataQuad& data_quad, const radix::Raster& default_raster); signals: void gpu_tiles_updated(const std::vector& deleted_tiles, const std::vector& new_tiles); @@ -39,7 +39,7 @@ class GeometryScheduler : public Scheduler { void transform_and_emit(const std::vector& new_quads, const std::vector& deleted_quads) override; private: - Raster m_default_raster; + radix::Raster m_default_raster; }; } // namespace nucleus::tile diff --git a/nucleus/tile/GpuArrayHelper.cpp b/nucleus/tile/GpuArrayHelper.cpp index 73ff8af07..d4c51ef20 100644 --- a/nucleus/tile/GpuArrayHelper.cpp +++ b/nucleus/tile/GpuArrayHelper.cpp @@ -65,16 +65,13 @@ GpuArrayHelper::LayerInfo GpuArrayHelper::layer(Id tile_id) const return { tile_id, m_id_to_layer.at(tile_id) }; } -bool GpuArrayHelper::contains(Id tile_id) const -{ - return m_id_to_layer.contains(tile_id); -} +bool GpuArrayHelper::contains(Id tile_id) const { return m_id_to_layer.contains(tile_id); } GpuArrayHelper::Dictionary GpuArrayHelper::generate_dictionary() const { const auto hash_to_pixel = [](uint16_t hash) { return glm::uvec2(hash & 255, hash >> 8); }; - nucleus::Raster packed_ids({ 256, 256 }, glm::u32vec2(-1, -1)); - nucleus::Raster layers({ 256, 256 }, 0); + radix::Raster packed_ids({ 256, 256 }, glm::u32vec2(-1, -1)); + radix::Raster layers({ 256, 256 }, 0); for (const auto& [id, layer] : m_id_to_layer) { auto hash = nucleus::srs::hash_uint16(id); while (packed_ids.pixel(hash_to_pixel(hash)) != glm::u32vec2(-1, -1)) diff --git a/nucleus/tile/GpuArrayHelper.h b/nucleus/tile/GpuArrayHelper.h index b077a667c..3a93edd55 100644 --- a/nucleus/tile/GpuArrayHelper.h +++ b/nucleus/tile/GpuArrayHelper.h @@ -19,15 +19,15 @@ #pragma once #include "types.h" -#include +#include namespace nucleus::tile { class GpuArrayHelper { public: struct Dictionary { - nucleus::Raster packed_ids; - nucleus::Raster layers; + radix::Raster packed_ids; + radix::Raster layers; }; struct LayerInfo { tile::Id id; diff --git a/nucleus/tile/RateLimiter.cpp b/nucleus/tile/RateLimiter.cpp index 5eb0f049e..223d6e62b 100644 --- a/nucleus/tile/RateLimiter.cpp +++ b/nucleus/tile/RateLimiter.cpp @@ -19,6 +19,7 @@ #include "RateLimiter.h" #include +#include #include using namespace nucleus::tile; @@ -35,8 +36,8 @@ RateLimiter::~RateLimiter() = default; void RateLimiter::set_limit(unsigned int rate, unsigned int period_msecs) { - assert(rate < unsigned(std::numeric_limits::max())); - assert(period_msecs < unsigned(std::numeric_limits::max())); + Q_ASSERT(rate < unsigned(std::numeric_limits::max())); + Q_ASSERT(period_msecs < unsigned(std::numeric_limits::max())); m_rate = rate; m_rate_period_msecs = period_msecs; } diff --git a/nucleus/tile/Scheduler.cpp b/nucleus/tile/Scheduler.cpp index 54e078743..64c493eff 100644 --- a/nucleus/tile/Scheduler.cpp +++ b/nucleus/tile/Scheduler.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -140,7 +141,7 @@ void Scheduler::update_gpu_quads() m_gpu_cached.visit([&should_refine](const GpuCacheInfo& quad) { return should_refine(quad.id); }); const auto superfluous_quads = m_gpu_cached.purge(m.gpu_quad_limit); - assert(m_gpu_cached.n_cached_objects() <= m.gpu_quad_limit); + Q_ASSERT(m_gpu_cached.n_cached_objects() <= m.gpu_quad_limit); // elimitate double entries (happens when the gpu has not enough space for all quads selected above) std::unordered_set superfluous_ids; @@ -188,11 +189,11 @@ void Scheduler::purge_ram_cache() emit stats_ready(m_name, stats); } -tl::expected Scheduler::persist_tiles() +bool Scheduler::persist_tiles() { if (m_name == "unnamed" || m_name.isEmpty()) { - return tl::unexpected(QString("Not persisitng tiles as the scheduler is not named, and this would cause name conflicts in the file system." - "Name your scheduler, e.g., by using the scheduler director.")); + qWarning() << "Not persisting tiles because the scheduler is not named."; + return false; } const auto start = std::chrono::steady_clock::now(); const auto r = m_ram_cache.write_to_disk(disk_cache_path()); @@ -204,22 +205,23 @@ tl::expected Scheduler::persist_tiles() .arg(m_ram_cache.n_cached_objects()); if (!r.has_value()) { - qDebug() << QString("Writing tiles to disk into %1 failed: %2. Removing all files.").arg(QString::fromStdString(disk_cache_path().string())).arg(r.error()); + qWarning() + << QString("Writing tiles to disk into %1 failed: %2. Removing all files.").arg(QString::fromStdString(disk_cache_path().string())).arg(r.error()); std::filesystem::remove_all(disk_cache_path()); } - return r; + return r.has_value(); } void Scheduler::schedule_update() { - assert(m.update_timeout < unsigned(std::numeric_limits::max())); + Q_ASSERT(m.update_timeout < unsigned(std::numeric_limits::max())); if (m_enabled && !m_update_timer->isActive()) m_update_timer->start(int(m.update_timeout)); } void Scheduler::schedule_purge() { - assert(m.purge_timeout < unsigned(std::numeric_limits::max())); + Q_ASSERT(m.purge_timeout < unsigned(std::numeric_limits::max())); if (m_enabled && !m_purge_timer->isActive()) { m_purge_timer->start(int(m.purge_timeout)); } @@ -227,7 +229,7 @@ void Scheduler::schedule_purge() void Scheduler::schedule_persist() { - assert(m.persist_timeout < unsigned(std::numeric_limits::max())); + Q_ASSERT(m.persist_timeout < unsigned(std::numeric_limits::max())); if (!m_persist_timer->isActive()) { m_persist_timer->start(int(m.persist_timeout)); } @@ -254,13 +256,13 @@ void Scheduler::clear_full_cache() set_ram_quad_limit(old_ram_quad_limit); } -tl::expected Scheduler::read_disk_cache() +std::expected Scheduler::read_disk_cache() { if (m_name == "unnamed" || m_name.isEmpty()) { const auto error = QString("Not reading tiles as the scheduler is not named, and this would cause name conflicts in the file system." "Name your scheduler, e.g., by using the scheduler director."); qDebug() << error; - return tl::unexpected(error); + return std::unexpected(error); } const auto r = m_ram_cache.read_from_disk(disk_cache_path()); if (r.has_value()) { @@ -269,7 +271,9 @@ tl::expected Scheduler::read_disk_cache() stats["n_quads_ram_max"] = m.ram_quad_limit; emit stats_ready(m_name, stats); } else { - qDebug() << QString("Reading tiles from disk cache (%1) failed: \n%2\nRemoving all files.").arg(QString::fromStdString(disk_cache_path().string())).arg(r.error()); + qDebug() << QString("Reading tiles from disk cache (%1) failed: \n%2\nRemoving all files.") + .arg(QString::fromStdString(disk_cache_path().string())) + .arg(r.error()); std::filesystem::remove_all(disk_cache_path()); } return r; @@ -312,7 +316,7 @@ unsigned int Scheduler::persist_timeout() const { return m.persist_timeout; } void Scheduler::set_persist_timeout(unsigned int new_persist_timeout) { - assert(new_persist_timeout < unsigned(std::numeric_limits::max())); + Q_ASSERT(new_persist_timeout < unsigned(std::numeric_limits::max())); m.persist_timeout = new_persist_timeout; if (m_persist_timer->isActive()) { @@ -333,7 +337,7 @@ std::filesystem::path Scheduler::disk_cache_path() void Scheduler::set_purge_timeout(unsigned int new_purge_timeout) { - assert(new_purge_timeout < unsigned(std::numeric_limits::max())); + Q_ASSERT(new_purge_timeout < unsigned(std::numeric_limits::max())); m.purge_timeout = new_purge_timeout; if (m_purge_timer->isActive()) { @@ -345,15 +349,9 @@ void Scheduler::set_ram_quad_limit(unsigned int new_ram_quad_limit) { m.ram_quad void Scheduler::set_gpu_quad_limit(unsigned int new_gpu_quad_limit) { m.gpu_quad_limit = new_gpu_quad_limit; } -void Scheduler::set_aabb_decorator(const utils::AabbDecoratorPtr& new_aabb_decorator) -{ - m_aabb_decorator = new_aabb_decorator; -} +void Scheduler::set_aabb_decorator(const utils::AabbDecoratorPtr& new_aabb_decorator) { m_aabb_decorator = new_aabb_decorator; } -bool Scheduler::enabled() const -{ - return m_enabled; -} +bool Scheduler::enabled() const { return m_enabled; } void Scheduler::set_enabled(bool new_enabled) { @@ -363,7 +361,7 @@ void Scheduler::set_enabled(bool new_enabled) void Scheduler::set_update_timeout(unsigned new_update_timeout) { - assert(m.update_timeout < unsigned(std::numeric_limits::max())); + Q_ASSERT(m.update_timeout < unsigned(std::numeric_limits::max())); m.update_timeout = new_update_timeout; if (m_update_timer->isActive()) { m_update_timer->start(m.update_timeout); diff --git a/nucleus/tile/Scheduler.h b/nucleus/tile/Scheduler.h index 211a4ce21..5c85ae2e3 100644 --- a/nucleus/tile/Scheduler.h +++ b/nucleus/tile/Scheduler.h @@ -21,12 +21,12 @@ #include -#include -#include #include "Cache.h" #include "nucleus/camera/Definition.h" #include "radix/tile.h" #include "types.h" +#include +#include class QTimer; @@ -38,7 +38,7 @@ namespace nucleus::tile { namespace utils { class AabbDecorator; using AabbDecoratorPtr = std::shared_ptr; -} +} // namespace utils class Scheduler : public QObject { Q_OBJECT @@ -82,10 +82,10 @@ class Scheduler : public QObject { [[nodiscard]] unsigned int persist_timeout() const; void set_persist_timeout(unsigned int new_persist_timeout); - tl::expected read_disk_cache(); + std::expected read_disk_cache(); void set_retirement_age_for_tile_cache(unsigned int new_retirement_age_for_tile_cache); - + void set_dataquerier(std::shared_ptr dataquerier); std::shared_ptr dataquerier() const; @@ -112,7 +112,7 @@ public slots: void update_gpu_quads(); void send_quad_requests(); void purge_ram_cache(); - tl::expected persist_tiles(); + bool persist_tiles(); protected: void schedule_update(); @@ -137,4 +137,4 @@ public slots: Cache m_ram_cache; Cache m_gpu_cached; }; -} +} // namespace nucleus::tile diff --git a/nucleus/tile/SlotLimiter.cpp b/nucleus/tile/SlotLimiter.cpp index d98b9abc7..2b61dab1c 100644 --- a/nucleus/tile/SlotLimiter.cpp +++ b/nucleus/tile/SlotLimiter.cpp @@ -18,6 +18,8 @@ #include "SlotLimiter.h" +#include + using namespace nucleus::tile; SlotLimiter::SlotLimiter(QObject* parent) @@ -27,7 +29,7 @@ SlotLimiter::SlotLimiter(QObject* parent) void SlotLimiter::set_limit(unsigned new_limit) { - assert(new_limit > 0); + Q_ASSERT(new_limit > 0); m_limit = new_limit; } diff --git a/nucleus/tile/TextureScheduler.cpp b/nucleus/tile/TextureScheduler.cpp index 13d5048f9..dfd870167 100644 --- a/nucleus/tile/TextureScheduler.cpp +++ b/nucleus/tile/TextureScheduler.cpp @@ -19,6 +19,7 @@ #include "TextureScheduler.h" #include "conversion.h" #include +#include #include namespace nucleus::tile { @@ -48,13 +49,16 @@ void TextureScheduler::transform_and_emit(const std::vector& new emit gpu_tiles_updated(deleted_quads, new_gpu_tiles); } -void TextureScheduler::set_texture_compression_algorithm(nucleus::utils::ColourTexture::Format compression_algorithm) { m_compression_algorithm = compression_algorithm; } +void TextureScheduler::set_texture_compression_algorithm(nucleus::utils::ColourTexture::Format compression_algorithm) +{ + m_compression_algorithm = compression_algorithm; +} -Raster TextureScheduler::to_raster(const tile::DataQuad& quad, const Raster& default_raster) +radix::Raster TextureScheduler::to_raster(const tile::DataQuad& quad, const radix::Raster& default_raster) { - assert(quad.n_tiles == 4); + Q_ASSERT(quad.n_tiles == 4); - std::array, 4> quad_rasters; + std::array, 4> quad_rasters; std::array quad_ids; for (const auto& tile : quad.tiles) { const auto quad_index = unsigned(quad_position(tile.id)); @@ -69,10 +73,22 @@ Raster TextureScheduler::to_raster(const tile::DataQuad& quad, cons } } - auto ortho_raster = nucleus::concatenate_horizontally(quad_rasters[unsigned(tile::QuadPosition::TopLeft)], quad_rasters[unsigned(tile::QuadPosition::TopRight)]); - ortho_raster.append_vertically(nucleus::concatenate_horizontally(quad_rasters[unsigned(tile::QuadPosition::BottomLeft)], quad_rasters[unsigned(tile::QuadPosition::BottomRight)])); + auto top + = radix::raster::concatenate_horizontally(quad_rasters[unsigned(tile::QuadPosition::TopLeft)], quad_rasters[unsigned(tile::QuadPosition::TopRight)]); + auto bottom = radix::raster::concatenate_horizontally( + quad_rasters[unsigned(tile::QuadPosition::BottomLeft)], quad_rasters[unsigned(tile::QuadPosition::BottomRight)]); + if (!top || !bottom) { + Q_ASSERT(false && "Texture quad rasters must have compatible dimensions"); + return {}; + } + + auto ortho_raster = radix::raster::concatenate_vertically(*top, *bottom); + if (!ortho_raster) { + Q_ASSERT(false && "Texture quad raster rows must have compatible dimensions"); + return {}; + } - return ortho_raster; + return std::move(*ortho_raster); } } // namespace nucleus::tile diff --git a/nucleus/tile/TextureScheduler.h b/nucleus/tile/TextureScheduler.h index 3fe17a24c..fa05d578d 100644 --- a/nucleus/tile/TextureScheduler.h +++ b/nucleus/tile/TextureScheduler.h @@ -30,7 +30,7 @@ class TextureScheduler : public Scheduler { ~TextureScheduler() override; void set_texture_compression_algorithm(nucleus::utils::ColourTexture::Format compression_algorithm); - static Raster to_raster(const tile::DataQuad& data_quad, const Raster& default_raster); + static radix::Raster to_raster(const tile::DataQuad& data_quad, const radix::Raster& default_raster); signals: void gpu_tiles_updated(const std::vector& deleted_tiles, const std::vector& new_tiles); @@ -40,7 +40,7 @@ class TextureScheduler : public Scheduler { private: nucleus::utils::ColourTexture::Format m_compression_algorithm = nucleus::utils::ColourTexture::Format::Uncompressed_RGBA; - Raster m_default_raster; + radix::Raster m_default_raster; }; } // namespace nucleus::tile diff --git a/nucleus/tile/TileLoadService.cpp b/nucleus/tile/TileLoadService.cpp index 4ba5875e5..2f38cc365 100644 --- a/nucleus/tile/TileLoadService.cpp +++ b/nucleus/tile/TileLoadService.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -94,7 +95,7 @@ QString TileLoadService::build_tile_url(tile::Id tile_id) const if (!m_load_balancing_targets.empty()) { const unsigned hash = qHash(tile_address) % 1024; const auto index = unsigned((float(hash) / 1024.1f) * float(m_load_balancing_targets.size())); - assert(index < m_load_balancing_targets.size()); + Q_ASSERT(index < m_load_balancing_targets.size()); return m_base_url.arg(m_load_balancing_targets[index]) + tile_address + m_file_ending; } return m_base_url + tile_address + m_file_ending; @@ -107,7 +108,7 @@ unsigned int TileLoadService::transfer_timeout() const void TileLoadService::set_transfer_timeout(unsigned int new_transfer_timeout) { - assert(new_transfer_timeout < unsigned(std::numeric_limits::max())); + Q_ASSERT(new_transfer_timeout < unsigned(std::numeric_limits::max())); m_transfer_timeout = new_transfer_timeout; } diff --git a/nucleus/tile/cache_quieries.h b/nucleus/tile/cache_quieries.h index 3ae0ca1aa..de228dc4a 100644 --- a/nucleus/tile/cache_quieries.h +++ b/nucleus/tile/cache_quieries.h @@ -20,6 +20,8 @@ #pragma once #include "nucleus/srs.h" + +#include #include "nucleus/tile/Cache.h" #include "radix/height_encoding.h" @@ -27,7 +29,7 @@ namespace nucleus::tile::cache_queries { -inline tl::expected query_altitude(MemoryCache* cache, const glm::dvec2& lat_long) +inline std::expected query_altitude(MemoryCache* cache, const glm::dvec2& lat_long) { const auto world_space = srs::lat_long_to_world(lat_long); nucleus::tile::Data selected_tile; @@ -41,8 +43,8 @@ inline tl::expected query_altitude(MemoryCache* cache, const glm return false; }); if (!selected_tile.data) - return tl::unexpected(QString("Couldn't find altitude for %1/%2").arg(lat_long.x).arg(lat_long.y)); - assert(selected_tile.data->size()); + return std::unexpected(QString("Couldn't find altitude for %1/%2").arg(lat_long.x).arg(lat_long.y)); + Q_ASSERT(selected_tile.data->size()); const auto bounds = srs::tile_bounds(selected_tile.id); const auto uv = (world_space - bounds.min) / bounds.size(); @@ -55,8 +57,8 @@ inline tl::expected query_altitude(MemoryCache* cache, const glm return radix::height_encoding::to_float(glm::u8vec3(px)); } } - assert(false); - return tl::unexpected(QString("Couldn't find altitude for %1/%2").arg(lat_long.x).arg(lat_long.y)); + Q_ASSERT(false); + return std::unexpected(QString("Couldn't find altitude for %1/%2").arg(lat_long.x).arg(lat_long.y)); } } // namespace nucleus::tile::cache_queries diff --git a/nucleus/tile/conversion.cpp b/nucleus/tile/conversion.cpp index 104594dac..016a7e803 100644 --- a/nucleus/tile/conversion.cpp +++ b/nucleus/tile/conversion.cpp @@ -21,9 +21,9 @@ namespace nucleus::tile::conversion { -Raster to_u16raster(const Raster& raster) +radix::Raster to_u16raster(const radix::Raster& raster) { - Raster retval(raster.size()); + radix::Raster retval(raster.size()); std::transform(raster.begin(), raster.end(), retval.begin(), [](const glm::u8vec4& rgba) { return uint16_t(rgba.x) << 8 | uint16_t(rgba.y); }); diff --git a/nucleus/tile/conversion.h b/nucleus/tile/conversion.h index a349fb850..0218fcfee 100644 --- a/nucleus/tile/conversion.h +++ b/nucleus/tile/conversion.h @@ -22,7 +22,8 @@ #include #include -#include +#include +#include #ifdef QT_GUI_LIB #include @@ -33,19 +34,19 @@ namespace nucleus::tile::conversion { /** * @brief Converts an RGBA8 raster to a uint16_t raster by packing the rg channels. ba are ignored. */ -Raster to_u16raster(const Raster& raster); +radix::Raster to_u16raster(const radix::Raster& raster); #ifdef QT_GUI_LIB -inline Raster qimage_to_u16raster(const QImage& qimage) +inline radix::Raster qimage_to_u16raster(const QImage& qimage) { if (qimage.format() != QImage::Format_ARGB32 && qimage.format() != QImage::Format_RGB32) { // let's hope that the format is always ARGB32 // if not, please implement the conversion, that'll give better performance. // the assert will be disabled in release, just as a backup. - assert(false); + Q_ASSERT(false); return qimage_to_u16raster(qimage.convertedTo(QImage::Format_ARGB32)); } - Raster raster({ qimage.width(), qimage.height() }); + radix::Raster raster({ qimage.width(), qimage.height() }); const auto* image_pointer = reinterpret_cast(qimage.constBits()); for (uint16_t& r : raster) { @@ -55,17 +56,17 @@ inline Raster qimage_to_u16raster(const QImage& qimage) return raster; } -inline nucleus::Raster to_rgba8raster(const QImage& image) +inline radix::Raster to_rgba8raster(const QImage& image) { if (image.format() != QImage::Format_RGBA8888) { // let's hope that the format is always Format_ARGB32 // if not, please implement the conversion, that'll give better performance. // the assert will be disabled in release, just as a backup. - assert(false); + Q_ASSERT(false); return to_rgba8raster(image.convertedTo(QImage::Format_RGBA8888)); } - nucleus::Raster raster({ image.width(), image.height() }); + radix::Raster raster({ image.width(), image.height() }); // const auto* image_pointer = reinterpret_cast(image.constBits()); // for (glm::u8vec4& v : raster) { @@ -79,9 +80,9 @@ inline nucleus::Raster to_rgba8raster(const QImage& image) return raster; } -[[nodiscard]] inline QImage to_QImage(const nucleus::Raster& raster) +[[nodiscard]] inline QImage to_QImage(const radix::Raster& raster) { - // assert(m_data.size() == m_width * m_height * 4); // Ensure the data is RGBA8 + // Q_ASSERT(m_data.size() == m_width * m_height * 4); // Ensure the data is RGBA8 QImage image(raster.width(), raster.height(), QImage::Format_RGBA8888); memcpy(image.bits(), raster.data(), raster.size_in_bytes()); return image; @@ -117,7 +118,7 @@ inline glm::u8vec4 uint162alpineRGBA(uint16_t v) } #ifdef QT_GUI_LIB -inline QImage u8raster_to_qimage(const nucleus::Raster& raster) +inline QImage u8raster_to_qimage(const radix::Raster& raster) { size_t width = raster.width(); size_t height = raster.height(); @@ -134,7 +135,7 @@ inline QImage u8raster_to_qimage(const nucleus::Raster& raster) return image; } -inline QImage u8raster_2_to_qimage(const nucleus::Raster& raster1, const nucleus::Raster& raster2) +inline QImage u8raster_2_to_qimage(const radix::Raster& raster1, const radix::Raster& raster2) { size_t width = raster1.width(); size_t height = raster1.height(); diff --git a/nucleus/tile/setup.h b/nucleus/tile/setup.h index b9d5de220..292ef8622 100644 --- a/nucleus/tile/setup.h +++ b/nucleus/tile/setup.h @@ -29,6 +29,7 @@ #include "utils.h" #include #include +#include #include #include @@ -191,7 +192,7 @@ inline utils::AabbDecoratorPtr aabb_decorator() { QFile file(":/map/height_data.atb"); const auto open = file.open(QIODeviceBase::OpenModeFlag::ReadOnly); - assert(open); + Q_ASSERT(open); Q_UNUSED(open); const QByteArray data = file.readAll(); return nucleus::tile::utils::AabbDecorator::make(radix::TileHeights::deserialise(data)); diff --git a/nucleus/tile/types.h b/nucleus/tile/types.h index 79a48d5f2..f85b40cd2 100644 --- a/nucleus/tile/types.h +++ b/nucleus/tile/types.h @@ -18,7 +18,6 @@ #pragma once - #include #include @@ -26,10 +25,6 @@ #include #include -namespace nucleus { -template -class Raster; -} namespace nucleus::tile { using namespace radix::tile; @@ -45,14 +40,14 @@ struct NetworkInfo { template static NetworkInfo join(const Ts&... infos) { - const auto info_array = std::array{infos...}; + const auto info_array = std::array { infos... }; Status status = Status::Good; uint64_t timestamp = std::numeric_limits::max(); for (const auto& i : info_array) { status = std::max(status, i.status); timestamp = std::min(timestamp, i.timestamp); } - return {status, timestamp}; + return { status, timestamp }; } }; @@ -62,9 +57,8 @@ concept NamedTile = requires(T t) { }; template -concept SerialisableTile = requires(T t) { - requires std::is_same, const std::array>::value; -}; +concept SerialisableTile + = requires(T t) { requires std::is_same, const std::array>::value; }; struct Data { tile::Id id; @@ -96,7 +90,7 @@ static_assert(NamedTile); struct GpuEawsTile { tile::Id id; - std::shared_ptr> texture; + std::shared_ptr> texture; }; static_assert(NamedTile); @@ -111,7 +105,6 @@ struct TileBounds { tile::SrsAndHeightBounds bounds = {}; }; - struct GpuEawsQuad { tile::Id id; std::array tiles; @@ -119,12 +112,11 @@ struct GpuEawsQuad { static_assert(NamedTile); - struct GpuGeometryTile { tile::Id id; tile::SrsAndHeightBounds bounds = {}; - std::shared_ptr> surface; + std::shared_ptr> surface; }; static_assert(NamedTile); -} // namespace nucleus::tile::tile_types +} // namespace nucleus::tile diff --git a/nucleus/timing/TimerInterface.cpp b/nucleus/timing/TimerInterface.cpp index 717209f5b..2f06e4267 100644 --- a/nucleus/timing/TimerInterface.cpp +++ b/nucleus/timing/TimerInterface.cpp @@ -18,6 +18,8 @@ #include "TimerInterface.h" +#include + namespace nucleus::timing { TimerInterface::TimerInterface(const QString& name, const QString& group, int queue_size, float average_weight) @@ -29,13 +31,13 @@ TimerInterface::TimerInterface(const QString& name, const QString& group, int qu } void TimerInterface::start() { - //assert(m_state == TimerStates::READY); + //Q_ASSERT(m_state == TimerStates::READY); _start(); m_state = TimerStates::RUNNING; } void TimerInterface::stop() { - //assert(m_state == TimerStates::RUNNING); + //Q_ASSERT(m_state == TimerStates::RUNNING); _stop(); m_state = TimerStates::STOPPED; } diff --git a/nucleus/utils/ColourTexture.cpp b/nucleus/utils/ColourTexture.cpp index da6e4f7ff..74a3ca255 100644 --- a/nucleus/utils/ColourTexture.cpp +++ b/nucleus/utils/ColourTexture.cpp @@ -20,6 +20,7 @@ #include "ColourTexture.h" #include +#include #include #include #include @@ -27,82 +28,83 @@ #define GOOFYTC_IMPLEMENTATION #include - namespace { -std::vector to_dxt1(const nucleus::Raster& image) +std::vector to_dxt1(const radix::Raster& image) { - assert(image.width() == image.height()); - assert(image.width() % 16 == 0); - assert(image.size_per_line() * image.height() == image.width() * image.height() * 4); - assert(image.size_in_bytes() == image.width() * image.height() * 4); + Q_ASSERT(image.width() == image.height()); + Q_ASSERT(image.width() % 16 == 0); + Q_ASSERT(image.size_per_line() * image.height() == image.width() * image.height() * 4); + Q_ASSERT(image.size_in_bytes() == image.width() * image.height() * 4); - struct alignas(16) AlignedBlock - { + struct alignas(16) AlignedBlock { std::array data; }; static_assert(sizeof(AlignedBlock) == 16); const auto n_bytes_in = size_t(image.size_in_bytes()); const auto n_bytes_out = image.width() * image.height() / 2; - assert(n_bytes_in % sizeof(AlignedBlock) == 0); + Q_ASSERT(n_bytes_in % sizeof(AlignedBlock) == 0); auto aligned_in = std::vector(n_bytes_in / sizeof(AlignedBlock)); auto data_ptr = reinterpret_cast(aligned_in.data()); - std::copy(image.bytes(), image.bytes() + n_bytes_in, data_ptr); + std::ranges::copy(image.bytes(), reinterpret_cast(data_ptr)); std::vector compressed(n_bytes_out); const auto result = goofy::compressDXT1(compressed.data(), data_ptr, (uint32_t)image.width(), (uint32_t)image.height(), (uint32_t)image.width() * 4); - assert(result == 0); + Q_ASSERT(result == 0); Q_UNUSED(result); return compressed; } -std::vector to_etc1(const nucleus::Raster& image) +std::vector to_etc1(const radix::Raster& image) { - assert(image.width() == image.height()); - assert(image.width() % 16 == 0); - assert(image.size_per_line() * image.height() == image.width() * image.height() * 4); - assert(image.size_in_bytes() == image.width() * image.height() * 4); + Q_ASSERT(image.width() == image.height()); + Q_ASSERT(image.width() % 16 == 0); + Q_ASSERT(image.size_per_line() * image.height() == image.width() * image.height() * 4); + Q_ASSERT(image.size_in_bytes() == image.width() * image.height() * 4); - struct alignas(16) AlignedBlock - { + struct alignas(16) AlignedBlock { std::array data; }; static_assert(sizeof(AlignedBlock) == 16); const auto n_bytes_in = size_t(image.size_in_bytes()); const auto n_bytes_out = image.width() * image.height() / 2; - assert(n_bytes_in % sizeof(AlignedBlock) == 0); + Q_ASSERT(n_bytes_in % sizeof(AlignedBlock) == 0); auto aligned_in = std::vector(n_bytes_in / sizeof(AlignedBlock)); auto data_ptr = reinterpret_cast(aligned_in.data()); - std::copy(image.bytes(), image.bytes() + n_bytes_in, data_ptr); + std::ranges::copy(image.bytes(), reinterpret_cast(data_ptr)); std::vector compressed(n_bytes_out); const auto result = goofy::compressETC1(compressed.data(), data_ptr, (uint32_t)image.width(), (uint32_t)image.height(), (uint32_t)image.width() * 4); - assert(result == 0); + Q_ASSERT(result == 0); Q_UNUSED(result); return compressed; } -std::vector to_uncompressed_rgba(const nucleus::Raster& image) +std::vector to_uncompressed_rgba(const radix::Raster& image) { size_t size_in_bytes = image.size_in_bytes(); - assert(size_in_bytes == (size_t)image.width() * image.height() * 4); + Q_ASSERT(size_in_bytes == (size_t)image.width() * image.height() * 4); std::vector data(size_in_bytes); // Note: AND Another copy... We copy the data two times (once in stb_image_loader.cpp) - std::copy(image.bytes(), image.bytes() + image.size_in_bytes(), data.data()); + std::ranges::copy(image.bytes(), reinterpret_cast(data.data())); return data; } -std::vector to_compressed(const nucleus::Raster& image, nucleus::utils::ColourTexture::Format algorithm) +std::vector to_compressed(const radix::Raster& image, nucleus::utils::ColourTexture::Format algorithm) { using Algorithm = nucleus::utils::ColourTexture::Format; - assert(image.width() == image.height()); - assert(image.width() % 4 == 0 || image.width() == 2 || image.width() == 1); + if (image.buffer().empty()) { + Q_ASSERT(false && "Cannot encode an empty colour raster"); + return {}; + } + Q_ASSERT(image.width() == image.height()); + Q_ASSERT(image.width() % 4 == 0 || image.width() == 2 || image.width() == 1); switch (algorithm) { case Algorithm::Uncompressed_RGBA: @@ -115,7 +117,7 @@ std::vector to_compressed(const nucleus::Raster& image, nu avg += glm::u32vec4(c); } avg /= image.buffer_length(); - auto v = to_dxt1(nucleus::resize(image, { 16, 16 }, glm::u8vec4(avg))); + auto v = to_dxt1(radix::raster::resize(image, { 16, 16 }, glm::u8vec4(avg))); if (image.width() == 8) { for (auto i = 16u; i < 32; ++i) v[i] = v[i + 16u]; @@ -133,7 +135,7 @@ std::vector to_compressed(const nucleus::Raster& image, nu avg += glm::u32vec4(c); } avg /= image.buffer_length(); - auto v = to_etc1(nucleus::resize(image, { 16, 16 }, glm::u8vec4(avg))); + auto v = to_etc1(radix::raster::resize(image, { 16, 16 }, glm::u8vec4(avg))); if (image.width() == 8) { for (auto i = 16u; i < 32; ++i) v[i] = v[i + 16u]; @@ -144,11 +146,12 @@ std::vector to_compressed(const nucleus::Raster& image, nu return v; } } - throw std::runtime_error("Unsupported algorithm for nucleus::Raster"); + Q_ASSERT(false && "Unsupported colour texture format"); + return {}; } } // namespace -nucleus::utils::ColourTexture::ColourTexture(const nucleus::Raster& image, Format format) +nucleus::utils::ColourTexture::ColourTexture(const radix::Raster& image, Format format) : m_data(to_compressed(image, format)) , m_width(unsigned(image.width())) , m_height(unsigned(image.height())) @@ -157,9 +160,14 @@ nucleus::utils::ColourTexture::ColourTexture(const nucleus::Raster& } nucleus::utils::MipmappedColourTexture nucleus::utils::generate_mipmapped_colour_texture( - const nucleus::Raster& texture, ColourTexture::Format format) + const radix::Raster& texture, ColourTexture::Format format) { - auto mip_levels = nucleus::generate_mipmap(texture); + auto mip_levels_result = radix::raster::generate_mipmap(texture); + if (!mip_levels_result) { + Q_ASSERT(false && "Colour textures require square, power-of-two rasters"); + return {}; + } + auto mip_levels = std::move(*mip_levels_result); nucleus::utils::MipmappedColourTexture colour_texture = {}; for (const auto& level : mip_levels) { colour_texture.emplace_back(level, format); diff --git a/nucleus/utils/ColourTexture.h b/nucleus/utils/ColourTexture.h index 633ef59fc..1df28a6ba 100644 --- a/nucleus/utils/ColourTexture.h +++ b/nucleus/utils/ColourTexture.h @@ -19,9 +19,9 @@ #pragma once -#include #include -#include "nucleus/Raster.h" +#include +#include namespace nucleus::utils { @@ -36,7 +36,7 @@ class ColourTexture { Format m_format = Format::Uncompressed_RGBA; public: - explicit ColourTexture(const nucleus::Raster& data, Format format); + explicit ColourTexture(const radix::Raster& data, Format format); [[nodiscard]] const uint8_t* data() const { return m_data.data(); } [[nodiscard]] size_t n_bytes() const { return m_data.size(); } [[nodiscard]] unsigned width() const { return m_width; } @@ -45,6 +45,6 @@ class ColourTexture { }; using MipmappedColourTexture = std::vector; -MipmappedColourTexture generate_mipmapped_colour_texture(const nucleus::Raster& data, ColourTexture::Format format); +MipmappedColourTexture generate_mipmapped_colour_texture(const radix::Raster& data, ColourTexture::Format format); } // namespace nucleus::utils diff --git a/nucleus/utils/error.h b/nucleus/utils/error.h index bb6b0e3d4..993ab973b 100644 --- a/nucleus/utils/error.h +++ b/nucleus/utils/error.h @@ -18,15 +18,16 @@ #pragma once #include -#include +#include #include namespace nucleus::utils::error { -template auto wrap_to_expected(F&& func) +template +auto wrap_to_expected(F&& func) { return [func = std::forward(func)](auto&& value) { using ReturnType = decltype(func(std::forward(value))); - return tl::expected { func(std::forward(value)) }; + return std::expected { func(std::forward(value)) }; }; } diff --git a/nucleus/utils/geopng_decoder.cpp b/nucleus/utils/geopng_decoder.cpp index d53c75a56..4fdae2a6b 100644 --- a/nucleus/utils/geopng_decoder.cpp +++ b/nucleus/utils/geopng_decoder.cpp @@ -50,13 +50,13 @@ std::vector possible_aabb_paths(const std::filesystem::pa return candidates; } -tl::expected, std::string> load_aabb_from_file(const std::filesystem::path& file_path) +std::expected, std::string> load_aabb_from_file(const std::filesystem::path& file_path) { const std::string path_str = file_path.string(); QFile aabb_file(QString::fromStdString(path_str)); if (!aabb_file.open(QIODevice::ReadOnly)) { - return tl::make_unexpected("Failed to open file " + path_str); + return std::unexpected("Failed to open file " + path_str); } QTextStream file_contents(&aabb_file); @@ -66,25 +66,27 @@ tl::expected, std::string> load_aabb_from_file( QString line = file_contents.readLine(); contents[i] = line.toFloat(&float_conversion_ok); if (!float_conversion_ok) { - return tl::make_unexpected("Failed to parse file " + path_str + ": Could not convert \"" + line.toStdString() + "\" to float"); + return std::unexpected("Failed to parse file " + path_str + ": Could not convert \"" + line.toStdString() + "\" to float"); } } if (contents[0] >= contents[2]) { - return tl::make_unexpected("Failed to parse file " + path_str + ": x_min (" + std::to_string(contents[0]) + ") must not be >= x_max (" + std::to_string(contents[2]) + ")"); + return std::unexpected( + "Failed to parse file " + path_str + ": x_min (" + std::to_string(contents[0]) + ") must not be >= x_max (" + std::to_string(contents[2]) + ")"); } if (contents[1] >= contents[3]) { - return tl::make_unexpected("Failed to parse file " + path_str + ": y_min (" + std::to_string(contents[1]) + ") must not be >= y_max (" + std::to_string(contents[3]) + ")"); + return std::unexpected( + "Failed to parse file " + path_str + ": y_min (" + std::to_string(contents[1]) + ") must not be >= y_max (" + std::to_string(contents[3]) + ")"); } return radix::geometry::Aabb<2, double> { { contents[0], contents[1] }, { contents[2], contents[3] } }; } -void write_encoded_float_png(const Raster& data, const QString& filename) +void write_encoded_float_png(const radix::Raster& data, const QString& filename) { constexpr float range = ENCODED_FLOAT_RANGE_MAX - ENCODED_FLOAT_RANGE_MIN; - Raster out(glm::uvec2(data.width(), data.height())); + radix::Raster out(glm::uvec2(data.width(), data.height())); for (size_t i = 0; i < data.buffer().size(); ++i) { const float clamped = std::clamp(data.buffer()[i], ENCODED_FLOAT_RANGE_MIN, ENCODED_FLOAT_RANGE_MAX); const uint32_t packed = static_cast((clamped - ENCODED_FLOAT_RANGE_MIN) / range * static_cast(std::numeric_limits::max())); @@ -93,7 +95,7 @@ void write_encoded_float_png(const Raster& data, const QString& filename) image_writer::rgba8_as_png(out, filename); } -glm::vec2 scan_encoded_float_range(const Raster& image, bool& likely_encoded_float) +glm::vec2 scan_encoded_float_range(const radix::Raster& image, bool& likely_encoded_float) { constexpr float range = ENCODED_FLOAT_RANGE_MAX - ENCODED_FLOAT_RANGE_MIN; float min_val = std::numeric_limits::max(); diff --git a/nucleus/utils/geopng_decoder.h b/nucleus/utils/geopng_decoder.h index ef29911db..2230fa7f9 100644 --- a/nucleus/utils/geopng_decoder.h +++ b/nucleus/utils/geopng_decoder.h @@ -19,12 +19,12 @@ #pragma once +#include #include #include -#include #include +#include #include -#include #include class QString; @@ -45,17 +45,17 @@ std::vector possible_aabb_paths(const std::filesystem::pa // Parses a sidecar AABB .txt file describing the world-space extent of a geo-PNG. // The file contains exactly four lines: min_x, min_y, max_x, max_y // Returns the parsed AABB, or an error message on failure -tl::expected, std::string> load_aabb_from_file(const std::filesystem::path& file_path); +std::expected, std::string> load_aabb_from_file(const std::filesystem::path& file_path); -// Encodes a Raster as a geo-PNG: each float is clamped to +// Encodes a radix::Raster as a geo-PNG: each float is clamped to // [ENCODED_FLOAT_RANGE_MIN, ENCODED_FLOAT_RANGE_MAX], mapped to [0,1], packed // as a u32, and stored across the R,G,B,A channels of a u8 PNG. -void write_encoded_float_png(const Raster& data, const QString& filename); +void write_encoded_float_png(const radix::Raster& data, const QString& filename); // Scans an RGBA-encoded float image. Returns {min, max} of decoded values. // Determines whether its likely_encoded_float with the heuristic that either: // - >= 1% of decoded float values are approx. 0.0 // - all decoded values share the same sign -glm::vec2 scan_encoded_float_range(const Raster& image, bool& likely_encoded_float); +glm::vec2 scan_encoded_float_range(const radix::Raster& image, bool& likely_encoded_float); } // namespace nucleus::utils::geopng diff --git a/nucleus/utils/image_loader.cpp b/nucleus/utils/image_loader.cpp index 7a290652f..d1b43db48 100644 --- a/nucleus/utils/image_loader.cpp +++ b/nucleus/utils/image_loader.cpp @@ -37,11 +37,11 @@ #include #include -#include +#include namespace nucleus::utils::image_loader { -tl::expected, QString> rgba8(const QByteArray& byteArray) +std::expected, QString> rgba8(const QByteArray& byteArray) { int width, height, channels; const int requested_channels = 4; // Request 4 channels to always get RGBA8 images @@ -54,24 +54,25 @@ tl::expected, QString> rgba8(const QByteArray& byteArray) ); if (data == nullptr) { - return tl::make_unexpected(QString("nucleus image_loader: Failed to decode image bytes.")); + return std::unexpected(QString("nucleus image_loader: Failed to decode image bytes.")); } // NOTE: We copy the contents of the data pointer into a Raster object. Sadly // we can't use the allocated memory directly, because for that we would need a custom // allocator for the std::vector class. - Raster raster(glm::uvec2(width, height)); - memcpy(raster.data(), data, raster.size_in_bytes()); + radix::Raster raster(glm::uvec2(width, height)); + const auto raster_bytes = raster.bytes(); + memcpy(raster_bytes.data(), data, raster_bytes.size()); stbi_image_free(data); return raster; } -tl::expected, QString> rgba8(const QString& filename) +std::expected, QString> rgba8(const QString& filename) { QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { - return tl::make_unexpected(QString("nucleus image_loader: Failed to open file %1").arg(filename)); + return std::unexpected(QString("nucleus image_loader: Failed to open file %1").arg(filename)); } QByteArray byteArray = file.readAll(); @@ -81,6 +82,6 @@ tl::expected, QString> rgba8(const QString& filename) return rgba8(byteArray); } -tl::expected, QString> rgba8(const char* filename) { return rgba8(QString(filename)); } +std::expected, QString> rgba8(const char* filename) { return rgba8(QString(filename)); } } // namespace nucleus::utils::image_loader diff --git a/nucleus/utils/image_loader.h b/nucleus/utils/image_loader.h index 3013c567e..d65f07564 100644 --- a/nucleus/utils/image_loader.h +++ b/nucleus/utils/image_loader.h @@ -20,14 +20,14 @@ #pragma once #include -#include -#include +#include +#include namespace nucleus::utils::image_loader { -tl::expected, QString> rgba8(const QByteArray& byteArray); +std::expected, QString> rgba8(const QByteArray& byteArray); -tl::expected, QString> rgba8(const QString& filename); -tl::expected, QString> rgba8(const char* filename); +std::expected, QString> rgba8(const QString& filename); +std::expected, QString> rgba8(const char* filename); } // namespace nucleus::utils::image_loader diff --git a/nucleus/utils/image_writer.cpp b/nucleus/utils/image_writer.cpp index 0fb55f7c8..d3515888e 100644 --- a/nucleus/utils/image_writer.cpp +++ b/nucleus/utils/image_writer.cpp @@ -23,13 +23,14 @@ #include #include +#include namespace nucleus::utils::image_writer { -void rgba8_as_png(const Raster& data, const QString& filename) +void rgba8_as_png(const radix::Raster& data, const QString& filename) { - assert(data.width() > 0); - assert(data.height() > 0); + Q_ASSERT(data.width() > 0); + Q_ASSERT(data.height() > 0); int result = stbi_write_png(filename.toUtf8().constData(), // File name data.width(), // Image width @@ -46,9 +47,9 @@ void rgba8_as_png(const Raster& data, const QString& filename) void rgba8_as_png(const QByteArray& data, const glm::uvec2& resolution, const QString& filename) { - assert(resolution.x > 0); - assert(resolution.y > 0); - assert(data.size() == static_cast(resolution.x * resolution.y * 4)); // Ensure data size matches resolution + Q_ASSERT(resolution.x > 0); + Q_ASSERT(resolution.y > 0); + Q_ASSERT(data.size() == static_cast(resolution.x * resolution.y * 4)); // Ensure data size matches resolution int result = stbi_write_png(filename.toUtf8().constData(), // File name static_cast(resolution.x), // Image width diff --git a/nucleus/utils/image_writer.h b/nucleus/utils/image_writer.h index 1b9db3624..4ca95c3b5 100644 --- a/nucleus/utils/image_writer.h +++ b/nucleus/utils/image_writer.h @@ -18,12 +18,12 @@ #pragma once -#include #include +#include namespace nucleus::utils::image_writer { -void rgba8_as_png(const Raster& data, const QString& filename); +void rgba8_as_png(const radix::Raster& data, const QString& filename); void rgba8_as_png(const QByteArray& data, const glm::uvec2& resolution, const QString& filename); diff --git a/nucleus/utils/rasterizer.h b/nucleus/utils/rasterizer.h index 7168d795d..87d5d0a90 100644 --- a/nucleus/utils/rasterizer.h +++ b/nucleus/utils/rasterizer.h @@ -16,6 +16,8 @@ * along with this program. If not, see . *****************************************************************************/ +#include + #include #include @@ -263,8 +265,8 @@ namespace details { template void render_triangle(const PixelWriterFunction& pixel_writer, const std::array triangle, unsigned int triangle_index, float distance) { - assert(triangle[0].y <= triangle[1].y); - assert(triangle[1].y <= triangle[2].y); + Q_ASSERT(triangle[0].y <= triangle[1].y); + Q_ASSERT(triangle[1].y <= triangle[2].y); auto edge_top_bottom = triangle[2] - triangle[0]; auto edge_top_middle = triangle[1] - triangle[0]; @@ -504,7 +506,7 @@ std::vector triangulize(std::vector polygon_points, std::v * * example usage: * const std::vector triangle_points = { glm::vec2(30.5, 10.5), glm::vec2(10.5, 30.5), glm::vec2(50.5, 50.5) }; - * nucleus::Raster output({ 64, 64 }, 0u); + * radix::Raster output({ 64, 64 }, 0u); * const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; * nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangle_points); */ @@ -525,7 +527,7 @@ template void rasterize_triangl * * example usage: * const std::vector line = { glm::vec2(30.5, 10.5), glm::vec2(50.5, 30.5), glm::vec2(30.5, 50.5), glm::vec2(10.5, 30.5), glm::vec2(30.5, 10.5) }; - * nucleus::Raster output({ 64, 64 }, 0u); + * radix::Raster output({ 64, 64 }, 0u); * const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; * nucleus::utils::rasterizer::rasterize_line(pixel_writer, line); */ @@ -543,7 +545,7 @@ template void rasterize_line(co * * example usage: * const std::vector polygon_points = { glm::vec2(30.5, 10.5), glm::vec2(10.5, 30.5), glm::vec2(50.5, 50.5) }; - * nucleus::Raster output({ 64, 64 }, 0u); + * radix::Raster output({ 64, 64 }, 0u); * const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; * nucleus::utils::rasterizer::rasterize_polygon(pixel_writer, polygon_points); */ diff --git a/nucleus/utils/terrain_mesh_index_generator.h b/nucleus/utils/terrain_mesh_index_generator.h index 075dd495f..38e17e51a 100644 --- a/nucleus/utils/terrain_mesh_index_generator.h +++ b/nucleus/utils/terrain_mesh_index_generator.h @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include @@ -46,8 +46,8 @@ namespace nucleus::utils::terrain_mesh_index_generator { template std::vector surface_quads(unsigned vertex_side_length) { - assert(vertex_side_length >= 2); - assert(vertex_side_length * vertex_side_length < std::numeric_limits::max()); + Q_ASSERT(vertex_side_length >= 2); + Q_ASSERT(vertex_side_length * vertex_side_length < std::numeric_limits::max()); std::vector indices; const auto height = vertex_side_length; const auto width = vertex_side_length; @@ -69,8 +69,8 @@ std::vector surface_quads(unsigned vertex_side_length) template std::vector surface_quads_with_curtains(unsigned vertex_side_length) { - assert(vertex_side_length >= 2); - assert(vertex_side_length * vertex_side_length < std::numeric_limits::max()); + Q_ASSERT(vertex_side_length >= 2); + Q_ASSERT(vertex_side_length * vertex_side_length < std::numeric_limits::max()); std::vector indices = surface_quads(vertex_side_length); const auto height = vertex_side_length; const auto width = vertex_side_length; diff --git a/nucleus/vector_tile/parse.cpp b/nucleus/vector_tile/parse.cpp index 78bf62a64..d7ee35d7b 100644 --- a/nucleus/vector_tile/parse.cpp +++ b/nucleus/vector_tile/parse.cpp @@ -19,6 +19,8 @@ #include "parse.h" #include "util.h" +#include + #include #include @@ -33,7 +35,7 @@ nucleus::vector_tile::PointOfInterest::Type type_from_layer_name(const std::stri return nucleus::vector_tile::PointOfInterest::Type::AlpineHut; if (name == "webcams") return nucleus::vector_tile::PointOfInterest::Type::Webcam; - assert(false); + Q_ASSERT(false); return nucleus::vector_tile::PointOfInterest::Type::Unknown; } diff --git a/unittests/gl_engine/UnittestGLContext.cpp b/unittests/gl_engine/UnittestGLContext.cpp index a0c7ba020..e9e7d1794 100644 --- a/unittests/gl_engine/UnittestGLContext.cpp +++ b/unittests/gl_engine/UnittestGLContext.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include UnittestGLContext::UnittestGLContext() @@ -48,7 +49,7 @@ UnittestGLContext::UnittestGLContext() surface.create(); const auto r = m_context.create(); - assert(r); + Q_ASSERT(r); Q_UNUSED(r); m_context.makeCurrent(&surface); diff --git a/unittests/gl_engine/main.cpp b/unittests/gl_engine/main.cpp index 8a0beefc6..02be96777 100644 --- a/unittests/gl_engine/main.cpp +++ b/unittests/gl_engine/main.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "unittests_gl/UnittestGlWindow.h" @@ -87,7 +88,7 @@ int main( int argc, char* argv[] ) { surface.create(); QOpenGLContext c; const auto r = c.create(); - assert(r); + Q_ASSERT(r); c.makeCurrent(&surface); gl_window.initializeGL(); return 0; diff --git a/unittests/gl_engine/texture.cpp b/unittests/gl_engine/texture.cpp index 359327c96..6f1c531e9 100644 --- a/unittests/gl_engine/texture.cpp +++ b/unittests/gl_engine/texture.cpp @@ -17,6 +17,7 @@ *****************************************************************************/ #include +#include #include #include "UnittestGLContext.h" @@ -87,7 +88,7 @@ void test_unsigned_texture_with(const TexelType& texel_value, gl_engine::Texture Framebuffer b(Framebuffer::DepthFormat::None, { Framebuffer::ColourFormat::RGBA8 }, { 1, 1 }); b.bind(); - const auto tex = nucleus::Raster({ 1, 1 }, texel_value); + const auto tex = radix::Raster({ 1, 1 }, texel_value); gl_engine::Texture opengl_texture(gl_engine::Texture::Target::_2d, format); opengl_texture.bind(0); opengl_texture.setParams(gl_engine::Texture::Filter::Nearest, gl_engine::Texture::Filter::Nearest); @@ -100,7 +101,7 @@ void test_unsigned_texture_with(const TexelType& texel_value, gl_engine::Texture return "mediump"; if (sizeof(Type) == 4) return "highp"; - assert(false); + Q_ASSERT(false); return "Type has unexpected size"; }; @@ -139,7 +140,7 @@ void test_float_texture_with(const TexelType& texel_value, gl_engine::Texture::F Framebuffer b(Framebuffer::DepthFormat::None, { Framebuffer::ColourFormat::RGBA8 }, { 1, 1 }); b.bind(); - const auto tex = nucleus::Raster({ 1, 1 }, texel_value); + const auto tex = radix::Raster({ 1, 1 }, texel_value); gl_engine::Texture opengl_texture(gl_engine::Texture::Target::_2d, format); opengl_texture.bind(0); opengl_texture.setParams(gl_engine::Texture::Filter::Nearest, gl_engine::Texture::Filter::Nearest); @@ -185,8 +186,8 @@ void test_unsigned_texture_array_with(const std::array& texel_valu opengl_texture.setParams(gl_engine::Texture::Filter::Nearest, gl_engine::Texture::Filter::Nearest); opengl_texture.allocate_array(1, 1, 2); - const auto tex0 = nucleus::Raster({ 1, 1 }, texel_value[0]); - const auto tex1 = nucleus::Raster({ 1, 1 }, texel_value[1]); + const auto tex0 = radix::Raster({ 1, 1 }, texel_value[0]); + const auto tex1 = radix::Raster({ 1, 1 }, texel_value[1]); opengl_texture.upload(tex0, 0); opengl_texture.upload(tex1, 1); @@ -197,7 +198,7 @@ void test_unsigned_texture_array_with(const std::array& texel_valu return "mediump"; if (sizeof(Type) == 4) return "highp"; - assert(false); + Q_ASSERT(false); return "Type has unexpected size"; }; @@ -274,7 +275,7 @@ QImage create_test_rgba_qimage(unsigned width, unsigned height) } return test_texture; } -nucleus::Raster create_test_rgba_raster(unsigned width, unsigned height) { return nucleus::tile::conversion::to_rgba8raster(create_test_rgba_qimage(width, height)); } +radix::Raster create_test_rgba_raster(unsigned width, unsigned height) { return nucleus::tile::conversion::to_rgba8raster(create_test_rgba_qimage(width, height)); } } // namespace @@ -417,7 +418,7 @@ TEST_CASE("gl texture") Framebuffer b(Framebuffer::DepthFormat::None, { Framebuffer::ColourFormat::RGBA8 }, { 1, 1 }); b.bind(); - const auto tex = nucleus::Raster({ 1, 1 }, glm::u8vec2(240, 120)); + const auto tex = radix::Raster({ 1, 1 }, glm::u8vec2(240, 120)); gl_engine::Texture opengl_texture(gl_engine::Texture::Target::_2d, gl_engine::Texture::Format::RG8); opengl_texture.bind(0); opengl_texture.setParams(gl_engine::Texture::Filter::Linear, gl_engine::Texture::Filter::Linear); @@ -484,14 +485,14 @@ TEST_CASE("gl texture") opengl_texture.upload(ColourTexture(test_raster, texture_type.first), 0); } { - auto test_raster = nucleus::Raster(glm::uvec2(256), glm::u8vec4(42,142,242,255)); + auto test_raster = radix::Raster(glm::uvec2(256), glm::u8vec4(42,142,242,255)); if (use_mipmaps) opengl_texture.upload(generate_mipmapped_colour_texture(test_raster, texture_type.first), 1); else opengl_texture.upload(ColourTexture(test_raster, texture_type.first), 1); } { - auto test_raster = nucleus::Raster(glm::uvec2(256), glm::u8vec4(222,111,0,255)); + auto test_raster = radix::Raster(glm::uvec2(256), glm::u8vec4(222,111,0,255)); if (use_mipmaps) opengl_texture.upload(generate_mipmapped_colour_texture(test_raster, texture_type.first), 2); else @@ -563,8 +564,8 @@ TEST_CASE("gl texture") gl_engine::Texture opengl_texture(gl_engine::Texture::Target::_2dArray, gl_engine::Texture::Format::R16UI); opengl_texture.allocate_array(1, 1, 2); opengl_texture.setParams(gl_engine::Texture::Filter::Nearest, gl_engine::Texture::Filter::Nearest); - opengl_texture.upload(nucleus::Raster({ 1, 1 }, uint16_t((120 * 65535) / 255)), 0); - opengl_texture.upload(nucleus::Raster({ 1, 1 }, uint16_t((190 * 65535) / 255)), 1); + opengl_texture.upload(radix::Raster({ 1, 1 }, uint16_t((120 * 65535) / 255)), 0); + opengl_texture.upload(radix::Raster({ 1, 1 }, uint16_t((190 * 65535) / 255)), 1); ShaderProgram shader = create_debug_shader(R"( uniform mediump usampler2DArray texture_sampler; @@ -613,8 +614,8 @@ TEST_CASE("gl texture") gl_engine::Texture opengl_texture(gl_engine::Texture::Target::_2dArray, gl_engine::Texture::Format::R8UI); opengl_texture.allocate_array(1, 1, 2); opengl_texture.setParams(gl_engine::Texture::Filter::Nearest, gl_engine::Texture::Filter::Nearest); - opengl_texture.upload(nucleus::Raster({ 1, 1 }, uint8_t(120)), 0); - opengl_texture.upload(nucleus::Raster({ 1, 1 }, uint8_t(190)), 1); + opengl_texture.upload(radix::Raster({ 1, 1 }, uint8_t(120)), 0); + opengl_texture.upload(radix::Raster({ 1, 1 }, uint8_t(190)), 1); ShaderProgram shader = create_debug_shader(R"( uniform mediump usampler2DArray texture_sampler; diff --git a/unittests/nucleus/CMakeLists.txt b/unittests/nucleus/CMakeLists.txt index 3c3efbbba..867b648fa 100644 --- a/unittests/nucleus/CMakeLists.txt +++ b/unittests/nucleus/CMakeLists.txt @@ -24,7 +24,6 @@ alp_add_unittest(unittests_nucleus utils_stopwatch.cpp DrawListGenerator.cpp test_helpers.h test_helpers.cpp - raster.cpp rasterizer.cpp terrain_mesh_index_generator.cpp srs.cpp diff --git a/unittests/nucleus/DrawListGenerator.cpp b/unittests/nucleus/DrawListGenerator.cpp index f21ce59a3..bc95211b4 100644 --- a/unittests/nucleus/DrawListGenerator.cpp +++ b/unittests/nucleus/DrawListGenerator.cpp @@ -21,6 +21,7 @@ #include #include +#include #include "nucleus/camera/PositionStorage.h" #include "nucleus/tile/DrawListGenerator.h" @@ -99,7 +100,7 @@ TEST_CASE("nucleus/tile/DrawListGenerator benchmark") QFile file(":/map/height_data.atb"); const auto open = file.open(QIODeviceBase::OpenModeFlag::ReadOnly); - assert(open); + Q_ASSERT(open); Q_UNUSED(open); const QByteArray data = file.readAll(); const auto decorator = nucleus::tile::utils::AabbDecorator::make(radix::TileHeights::deserialise(data)); diff --git a/unittests/nucleus/RateTester.cpp b/unittests/nucleus/RateTester.cpp index 5e13ad3d9..559f9b6a6 100644 --- a/unittests/nucleus/RateTester.cpp +++ b/unittests/nucleus/RateTester.cpp @@ -16,6 +16,8 @@ * along with this program. If not, see . *****************************************************************************/ +#include + #include #include @@ -37,7 +39,7 @@ RateTester::~RateTester() unsigned n_events_in_time_frame = 1; const auto event_time = *i; for (auto j = std::reverse_iterator(i); j != m_events.rend(); j++) { - assert(*j <= event_time); + Q_ASSERT(*j <= event_time); if (event_time - *j < m_period * 1'000ll) ++n_events_in_time_frame; else diff --git a/unittests/nucleus/avalanche_warning_layer.cpp b/unittests/nucleus/avalanche_warning_layer.cpp index 711434025..45b45d95d 100644 --- a/unittests/nucleus/avalanche_warning_layer.cpp +++ b/unittests/nucleus/avalanche_warning_layer.cpp @@ -68,7 +68,7 @@ TEST_CASE("nucleus/EAWS Vector Tiles") // Check if reader returns a std::vector with EAWS regions when reading mvt file radix::tile::Id tile_id_0_0_0({ 0, glm::uvec2(0, 0), radix::tile::Scheme::SlippyMap }); - tl::expected result = nucleus::avalanche::vector_tile_reader(test_data, tile_id_0_0_0); + std::expected result = nucleus::avalanche::vector_tile_reader(test_data, tile_id_0_0_0); CHECK(result.has_value()); // Check if EAWS region struct is initialized with empty attributes @@ -232,8 +232,8 @@ TEST_CASE("nucleus/avalanche/ReportLoadService") REQUIRE(spy.count() == 1); QList arguments = spy.takeFirst(); REQUIRE(arguments.size() == 1); - tl::expected, QString> result - = qvariant_cast, QString>>(arguments.at(0)); + std::expected, QString> result + = qvariant_cast, QString>>(arguments.at(0)); CHECK(result.has_value()); if (result.has_value()) { nucleus::avalanche::UboEawsReports ubo = arguments.at(0).value(); @@ -263,7 +263,7 @@ std::pair load_tile_from_file(const { QByteArray test_data = load_raw_data_from_file(test_file_name); CHECK(test_data.size() > 0); - tl::expected result = nucleus::avalanche::vector_tile_reader(test_data, tile_id); + std::expected result = nucleus::avalanche::vector_tile_reader(test_data, tile_id); CHECK(result.has_value()); nucleus::avalanche::RegionTile region_tile = result.value(); return std::pair(test_data, region_tile); @@ -279,7 +279,7 @@ TEST_CASE("nucleus/avalanche/Scheduler") nucleus::tile::DataQuad quad; quad.id = radix::tile::Id { 6, { 33, 22 }, radix::tile::Scheme::SlippyMap }; std::vector tiles; - std::vector> rasters; + std::vector> rasters; rasters.reserve(4); unsigned int idx = 1; for (radix::tile::Id tile_id : quad.id.children()) { @@ -295,7 +295,7 @@ TEST_CASE("nucleus/avalanche/Scheduler") quad.n_tiles = 4; // use "to_raster" on quad and compare result to previously loaded tile rasters - nucleus::Raster default_raster(glm::uvec2(256, 256), glm::uint16 { 255 }); + radix::Raster default_raster(glm::uvec2(256, 256), glm::uint16 { 255 }); const auto joined = nucleus::avalanche::Scheduler::to_raster(quad, default_raster, id_manager); REQUIRE(joined.width() == 512); REQUIRE(joined.height() == 512); diff --git a/unittests/nucleus/map_labels.cpp b/unittests/nucleus/map_labels.cpp index 460bb5cf9..fe64755c6 100644 --- a/unittests/nucleus/map_labels.cpp +++ b/unittests/nucleus/map_labels.cpp @@ -35,7 +35,7 @@ TEST_CASE("nucleus/map_label/factory") auto i = 0u; for (const auto& rg_raster : a.font_atlas) { CAPTURE(rg_raster); - auto rgba_raster = nucleus::Raster(rg_raster.size()); + auto rgba_raster = radix::Raster(rg_raster.size()); std::transform(rg_raster.begin(), rg_raster.end(), rgba_raster.begin(), [](glm::u8vec2 rg) { return glm::u8vec4 { rg.x, rg.y, 0, 255 }; }); const auto qimage = nucleus::tile::conversion::to_QImage(rgba_raster); qimage.save(QString("font_atlas_%0.png").arg(i)); diff --git a/unittests/nucleus/raster.cpp b/unittests/nucleus/raster.cpp deleted file mode 100644 index 143135136..000000000 --- a/unittests/nucleus/raster.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/***************************************************************************** - * Alpine Terrain Builder - * Copyright (C) 2022 alpinemaps.org - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *****************************************************************************/ - -#include "catch2_helpers.h" - -#include - -#include "nucleus/Raster.h" -#include "test_helpers.h" - -using nucleus::Raster; - -TEST_CASE("nucleus/Raster") -{ - SECTION("empty and interface") - { - const Raster raster; - CHECK(raster.buffer().empty()); - CHECK(raster.width() == 0); - CHECK(raster.height() == 0); - CHECK(raster.begin() == raster.end()); - CHECK(raster.cbegin() == raster.cend()); - CHECK(raster.buffer_length() == 0); - } - - SECTION("square default") - { - const Raster raster(64); - CHECK(raster.width() == 64); - CHECK(raster.height() == 64); - } - SECTION("non-square default") - { - const Raster raster(glm::uvec2(5, 10)); - CHECK(raster.width() == 5); - CHECK(raster.height() == 10); - } - - SECTION("move raster") - { - Raster raster(1); - const auto other = std::move(raster); - CHECK(other.width() == 1); - CHECK(other.height() == 1); - } - - SECTION("move vector into raster") - { - std::vector vector(1); - const Raster raster(1, std::move(vector)); - CHECK(raster.width() == 1); - CHECK(raster.height() == 1); - } - - SECTION("write data") - { - Raster raster(16); - int i = 0; - for (auto& v : raster) { - v = i++; - } - - i = 0; - bool check = true; - for (auto& v : raster) { - check &= v == i++; - } - CHECK(check); - } - - SECTION("pixel access") - { - Raster raster({ 3, 4 }); - int i = 0; - for (auto& v : raster) { - v = i++; - } - CHECK(raster.pixel({ 0, 0 }) == 0); - CHECK(raster.pixel({ 1, 0 }) == 1); - CHECK(raster.pixel({ 2, 0 }) == 2); - CHECK(raster.pixel({ 0, 1 }) == 3); - CHECK(raster.pixel({ 1, 1 }) == 4); - CHECK(raster.pixel({ 2, 1 }) == 5); - CHECK(raster.pixel({ 2, 3 }) == i - 1); - - raster.pixel({ 2, 1 }) = 21; - raster.pixel({ 2, 2 }) = 22; - CHECK(raster.pixel({ 2, 1 }) == 21); - CHECK(raster.pixel({ 2, 2 }) == 22); - } - - SECTION("create filled") - { - Raster raster({ 3, 4 }, 421); - for (int p : raster) { - CHECK(p == 421); - } - } - - SECTION("fill") - { - Raster raster({ 3, 4 }, 421); - raster.fill(657); - for (int p : raster) { - CHECK(p == 657); - } - } - - SECTION("resize 1") - { - Raster a({ 4, 3 }, 1); - const auto b = resize(a, { 2, 1 }, 2); - CHECK(b.pixel({ 0, 0 }) == 1); - CHECK(b.pixel({ 1, 0 }) == 1); - } - - SECTION("resize 2") - { - Raster a({ 2, 1 }, 1); - const auto b = resize(a, { 4, 3 }, 2); - CHECK(b.pixel({ 0, 0 }) == 1); - CHECK(b.pixel({ 0, 1 }) == 2); - CHECK(b.pixel({ 0, 2 }) == 2); - - CHECK(b.pixel({ 1, 0 }) == 1); - CHECK(b.pixel({ 1, 1 }) == 2); - CHECK(b.pixel({ 1, 2 }) == 2); - - for (auto i = 0u; i < 3; ++i) { - CHECK(b.pixel({ 2, i }) == 2); - CHECK(b.pixel({ 3, i }) == 2); - } - } - - SECTION("create mip maps") - { - // clang-format off - Raster raster({ 4, 4 }, glm::u8vec4(0u, 0u, 0u, 0u)); - raster.pixel({ 0, 0 }) = glm::u8vec4(100u, 0u, 100u, 0u); - raster.pixel({ 0, 1 }) = glm::u8vec4(100u, 0u, 100u, 150u); - raster.pixel({ 1, 0 }) = glm::u8vec4(200u, 200u, 100u, 250u); - raster.pixel({ 1, 1 }) = glm::u8vec4(0u, 200u, 100u, 0u); - - raster.pixel({ 0, 2 }) = glm::u8vec4(10u, 20u, 30u, 40u); - raster.pixel({ 0, 3 }) = glm::u8vec4(10u, 20u, 30u, 40u); - raster.pixel({ 1, 2 }) = glm::u8vec4(10u, 20u, 30u, 40u); - raster.pixel({ 1, 3 }) = glm::u8vec4(10u, 20u, 30u, 40u); - - raster.pixel({ 2, 0 }) = glm::u8vec4(200u, 250u, 0u, 255u); - raster.pixel({ 2, 1 }) = glm::u8vec4(200u, 250u, 0u, 255u); - raster.pixel({ 3, 0 }) = glm::u8vec4(200u, 250u, 0u, 255u); - raster.pixel({ 3, 1 }) = glm::u8vec4(200u, 250u, 0u, 255u); - - raster.pixel({ 2, 2 }) = glm::u8vec4(0u, 0u, 0u, 1u); - raster.pixel({ 2, 3 }) = glm::u8vec4(3u, 0u, 0u, 1u); - raster.pixel({ 3, 2 }) = glm::u8vec4(0u, 0u, 1u, 1u); - raster.pixel({ 3, 3 }) = glm::u8vec4(0u, 1u, 2u, 1u); - - const auto mipmap = generate_mipmap(raster); - REQUIRE(mipmap.size() == 3); - CHECK(mipmap.at(0).size() == glm::uvec2(4, 4)); - CHECK(mipmap.at(1).size() == glm::uvec2(2, 2)); - CHECK(mipmap.at(2).size() == glm::uvec2(1, 1)); - - for (auto i = 0u; i < raster.buffer_length(); ++i) { - CHECK(mipmap.at(0).buffer().at(i) == raster.buffer().at(i)); - } - CHECK(mipmap.at(1).pixel({ 0, 0 }) == glm::u8vec4(100u, 100u, 100u, 100u)); - CHECK(mipmap.at(1).pixel({ 0, 1 }) == glm::u8vec4(10u, 20u, 30u, 40u)); - CHECK(mipmap.at(1).pixel({ 1, 0 }) == glm::u8vec4(200u, 250u, 0u, 255u)); - CHECK(mipmap.at(1).pixel({ 1, 1 }) == glm::u8vec4(0u, 0u, 0u, 1u)); - - CHECK(mipmap.at(2).pixel({ 0, 0 }) == glm::u8vec4(77u, 92u, 32u, 99u)); - // clang-format on - } - - SECTION("create mip maps with uint16") - { - // clang-format off - Raster raster({ 2, 2 }, 0u); - raster.pixel({ 0, 0 }) = 65535u; - raster.pixel({ 0, 1 }) = 65535u; - raster.pixel({ 1, 0 }) = 65535u; - raster.pixel({ 1, 1 }) = 65535u; - - const auto mipmap = generate_mipmap(raster); - REQUIRE(mipmap.size() == 2); - CHECK(mipmap.at(0).size() == glm::uvec2(2, 2)); - CHECK(mipmap.at(1).size() == glm::uvec2(1, 1)); - - CHECK(mipmap.at(0).pixel({ 0, 0 }) == 65535u); - CHECK(mipmap.at(0).pixel({ 0, 1 }) == 65535u); - CHECK(mipmap.at(0).pixel({ 1, 0 }) == 65535u); - CHECK(mipmap.at(0).pixel({ 1, 1 }) == 65535u); - - CHECK(mipmap.at(1).pixel({ 0, 0 }) == 65535u); - // clang-format on - } - - SECTION("append_vertically") - { - Raster raster1({ 3, 4 }, 421); - Raster raster2({ 3, 2 }, 657); - raster1.append_vertically(raster2); - - REQUIRE(raster1.width() == 3); - REQUIRE(raster1.height() == 6); - - CHECK(raster1.pixel({ 0, 0 }) == 421); - CHECK(raster1.pixel({ 0, 3 }) == 421); - CHECK(raster1.pixel({ 2, 3 }) == 421); - - CHECK(raster1.pixel({ 0, 4 }) == 657); - CHECK(raster1.pixel({ 2, 4 }) == 657); - CHECK(raster1.pixel({ 2, 5 }) == 657); - } - - SECTION("concatenate_horizontally") - { - Raster raster1({ 2, 2 }, 421); - Raster raster2({ 2, 2 }, 657); - const auto result = concatenate_horizontally(raster1, raster2); - - REQUIRE(result.width() == 4); - REQUIRE(result.height() == 2); - - CHECK(result.pixel({ 0, 0 }) == 421); - CHECK(result.pixel({ 0, 1 }) == 421); - CHECK(result.pixel({ 1, 0 }) == 421); - CHECK(result.pixel({ 1, 1 }) == 421); - CHECK(result.pixel({ 2, 0 }) == 657); - CHECK(result.pixel({ 3, 1 }) == 657); - CHECK(result.pixel({ 2, 0 }) == 657); - CHECK(result.pixel({ 3, 1 }) == 657); - } -} diff --git a/unittests/nucleus/rasterizer.cpp b/unittests/nucleus/rasterizer.cpp index d2d1b7191..938666af3 100644 --- a/unittests/nucleus/rasterizer.cpp +++ b/unittests/nucleus/rasterizer.cpp @@ -25,7 +25,8 @@ #include -#include "nucleus/Raster.h" +#include +#include #include "nucleus/tile/conversion.h" #include "nucleus/utils/rasterizer.h" @@ -312,7 +313,7 @@ TEST_CASE("nucleus/rasterizer") // test was added, since there was a case where the second to last row was never rendered const std::vector polygon_points = { glm::vec2(5, 1), glm::vec2(5, 5), glm::vec2(1, 5) }; - nucleus::Raster output({ 7, 7 }, 0u); + radix::Raster output({ 7, 7 }, 0u); const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; nucleus::utils::rasterizer::rasterize_polygon(pixel_writer, polygon_points); @@ -333,17 +334,17 @@ TEST_CASE("nucleus/rasterizer") glm::vec2(10.5, 30.5), }; - nucleus::Raster output({ 64, 64 }, 0u); + radix::Raster output({ 64, 64 }, 0u); const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; nucleus::utils::rasterizer::rasterize_polygon(pixel_writer, polygon_points); const auto edges = nucleus::utils::rasterizer::generate_neighbour_edges(polygon_points); const auto triangles = nucleus::utils::rasterizer::triangulize(polygon_points, edges); - nucleus::Raster output2({ 64, 64 }, 0u); + radix::Raster output2({ 64, 64 }, 0u); auto pixel_writer2 = [&output2](glm::ivec2 pos) { output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles, 0); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -357,15 +358,15 @@ TEST_CASE("nucleus/rasterizer") // two triangles const std::vector triangles = { glm::vec2(30.5, 10.5), glm::vec2(10.5, 30.5), glm::vec2(50.5, 50.5), glm::vec2(5.5, 5.5), glm::vec2(15.5, 10.5), glm::vec2(5.5, 15.5) }; - nucleus::Raster output({ 64, 64 }, 0u); + radix::Raster output({ 64, 64 }, 0u); const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles); - nucleus::Raster output2({ 64, 64 }, 0u); + radix::Raster output2({ 64, 64 }, 0u); auto pixel_writer2 = [&output2](glm::ivec2 pos) { output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles, 0); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -377,15 +378,15 @@ TEST_CASE("nucleus/rasterizer") SECTION("rasterize triangle small") { const std::vector triangles_small = { glm::vec2(2, 2), glm::vec2(1, 3), glm::vec2(3.8, 3.8) }; - nucleus::Raster output({ 6, 6 }, 0u); + radix::Raster output({ 6, 6 }, 0u); const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles_small); - nucleus::Raster output2({ 6, 6 }, 0u); + radix::Raster output2({ 6, 6 }, 0u); const auto pixel_writer2 = [&output2](glm::ivec2 pos) { output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles_small, 0); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -398,15 +399,15 @@ TEST_CASE("nucleus/rasterizer") { // less than one pixel const std::vector triangles_smallest = { glm::vec2(30.4, 30.4), glm::vec2(30.8, 30.6), glm::vec2(30.8, 30.8) }; - nucleus::Raster output({ 64, 64 }, 0u); + radix::Raster output({ 64, 64 }, 0u); const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles_smallest); - nucleus::Raster output2({ 64, 64 }, 0u); + radix::Raster output2({ 64, 64 }, 0u); const auto pixel_writer2 = [&output2](glm::ivec2 pos) { output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles_smallest, 0); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -420,7 +421,7 @@ TEST_CASE("nucleus/rasterizer") // less than one pixel const std::vector triangles = { glm::vec2(5.35, 5.35), glm::vec2(5.40, 5.40), glm::vec2(5.45, 5.35) }; auto size = glm::vec2(10, 10); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 4.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -432,14 +433,14 @@ TEST_CASE("nucleus/rasterizer") nucleus::utils::rasterizer::details::add_circle_end_cap(pixel_writer, triangles[1], 1, distance); nucleus::utils::rasterizer::details::add_circle_end_cap(pixel_writer, triangles[2], 1, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -459,7 +460,7 @@ TEST_CASE("nucleus/rasterizer") glm::vec2(5.5, 15.5) }; // const std::vector triangles = { glm::vec2(5.35, 5.35), glm::vec2(5.40, 5.40), glm::vec2(5.45, 5.35) }; auto size = glm::vec2(64, 64); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 5.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -469,14 +470,14 @@ TEST_CASE("nucleus/rasterizer") }; nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -489,7 +490,7 @@ TEST_CASE("nucleus/rasterizer") { const std::vector triangles = { glm::vec2(30.5, 10.5), glm::vec2(45.5, 45.5), glm::vec2(10.5, 45.5) }; auto size = glm::vec2(64, 64); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 4.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -499,14 +500,14 @@ TEST_CASE("nucleus/rasterizer") }; nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -522,7 +523,7 @@ TEST_CASE("nucleus/rasterizer") // } // ; // auto size = glm::vec2(64, 64); - // nucleus::Raster output(size, 0u); + // radix::Raster output(size, 0u); // float distance = 5.0; // radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -532,14 +533,14 @@ TEST_CASE("nucleus/rasterizer") // }; // nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles, distance); - // nucleus::Raster output2(size, 0u); + // radix::Raster output2(size, 0u); // const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { // if (bounds.contains(pos)) // output2.pixel(pos) = 255; // }; // rasterize_triangle_sdf(pixel_writer2, triangles, distance); - // CHECK(output.buffer() == output2.buffer()); + // CHECK(std::ranges::equal(output.buffer(), output2.buffer())); // #ifdef WRITE_DEBUG_IMAGE // // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -563,13 +564,13 @@ TEST_CASE("nucleus/rasterizer") const std::vector triangles_grid = { glm::vec2(12.4023 * orig_scale, 0.2754 * orig_scale), glm::vec2(7.0312 * orig_scale, 10.8027 * orig_scale), glm::vec2(7.3633 * orig_scale, 11.0684 * orig_scale) }; - nucleus::Raster output({ orig_size, orig_size }, 0u); + radix::Raster output({ orig_size, orig_size }, 0u); const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles_grid); // next write the same triangle to larger raster constexpr int enlarged_size = 2048; - nucleus::Raster output_enlarged({ enlarged_size, enlarged_size }, 0u); + radix::Raster output_enlarged({ enlarged_size, enlarged_size }, 0u); { constexpr double enlarged_scale = enlarged_size / 16.0; @@ -629,15 +630,15 @@ TEST_CASE("nucleus/rasterizer") auto triangles = nucleus::utils::rasterizer::triangulize(vertices, edges); - nucleus::Raster output({ 64, 64 }, 0u); + radix::Raster output({ 64, 64 }, 0u); const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles); - nucleus::Raster output2({ 64, 64 }, 0u); + radix::Raster output2({ 64, 64 }, 0u); auto pixel_writer2 = [&output2](glm::ivec2 pos) { output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles, 0); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE auto image = nucleus::tile::conversion::u8raster_2_to_qimage(output, output2); @@ -650,7 +651,7 @@ TEST_CASE("nucleus/rasterizer") constexpr auto cells = 8u; constexpr auto cell_size = 32u; - nucleus::Raster output({ cells * cell_size, cells * cell_size }, 0u); + radix::Raster output({ cells * cell_size, cells * cell_size }, 0u); const auto pixel_writer = [&output](glm::ivec2 pos) { output.pixel(pos) = 255; }; const std::vector> polygon_points = { { { 11.5, 16 }, { 12.9, 3.9 }, { 4.8, 5.5 } }, @@ -788,7 +789,7 @@ TEST_CASE("nucleus/rasterizer") }; auto size = glm::vec2(30, 30); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 0.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -798,14 +799,14 @@ TEST_CASE("nucleus/rasterizer") }; nucleus::utils::rasterizer::rasterize_triangle(pixel_writer, triangles, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; }; rasterize_triangle_sdf(pixel_writer2, triangles, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -824,7 +825,7 @@ TEST_CASE("nucleus/rasterizer") const std::vector line_right_to_left_2pixel = { glm::vec2(2.3, 23.7), glm::vec2(6.5, 22.3) }; auto size = glm::vec2(30, 30); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 0.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -839,7 +840,7 @@ TEST_CASE("nucleus/rasterizer") nucleus::utils::rasterizer::rasterize_line(pixel_writer, line_left_to_right_2pixel, distance); nucleus::utils::rasterizer::rasterize_line(pixel_writer, line_right_to_left_2pixel, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; @@ -851,7 +852,7 @@ TEST_CASE("nucleus/rasterizer") rasterize_line_sdf(pixel_writer2, line_left_to_right_2pixel, distance); rasterize_line_sdf(pixel_writer2, line_right_to_left_2pixel, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -864,7 +865,7 @@ TEST_CASE("nucleus/rasterizer") { const std::vector line = { glm::vec2(10.5, 10.5), glm::vec2(10.5, 50.5), glm::vec2(50.5, 50.5), glm::vec2(50.5, 10.5), glm::vec2(10.5, 10.5) }; auto size = glm::vec2(64, 64); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 0.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -874,14 +875,14 @@ TEST_CASE("nucleus/rasterizer") }; nucleus::utils::rasterizer::rasterize_line(pixel_writer, line, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; }; rasterize_line_sdf(pixel_writer2, line, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -894,7 +895,7 @@ TEST_CASE("nucleus/rasterizer") { const std::vector line = { glm::vec2(30.5, 10.5), glm::vec2(50.5, 30.5), glm::vec2(30.5, 50.5), glm::vec2(10.5, 30.5), glm::vec2(30.5, 10.5) }; auto size = glm::vec2(64, 64); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 0.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -904,14 +905,14 @@ TEST_CASE("nucleus/rasterizer") }; nucleus::utils::rasterizer::rasterize_line(pixel_writer, line, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; }; rasterize_line_sdf(pixel_writer2, line, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -924,7 +925,7 @@ TEST_CASE("nucleus/rasterizer") { const std::vector line = { glm::vec2(10.5, 10.5), glm::vec2(10.5, 50.5), glm::vec2(50.5, 50.5), glm::vec2(50.5, 10.5), glm::vec2(10.5, 10.5) }; auto size = glm::vec2(64, 64); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 2.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -934,14 +935,14 @@ TEST_CASE("nucleus/rasterizer") }; nucleus::utils::rasterizer::rasterize_line(pixel_writer, line, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; }; rasterize_line_sdf(pixel_writer2, line, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) @@ -955,7 +956,7 @@ TEST_CASE("nucleus/rasterizer") const std::vector line = { glm::vec2(30.5, 10.5), glm::vec2(50.5, 30.5), glm::vec2(30.5, 50.5), glm::vec2(10.5, 30.5), glm::vec2(30.5, 10.5) }; // const std::vector line = { glm::vec2(30.5, 10.5), glm::vec2(50.5, 30.5) }; auto size = glm::vec2(64, 64); - nucleus::Raster output(size, 0u); + radix::Raster output(size, 0u); float distance = 2.0; radix::geometry::Aabb2 bounds = { { 0, 0 }, size }; @@ -965,14 +966,14 @@ TEST_CASE("nucleus/rasterizer") }; nucleus::utils::rasterizer::rasterize_line(pixel_writer, line, distance); - nucleus::Raster output2(size, 0u); + radix::Raster output2(size, 0u); const auto pixel_writer2 = [&output2, bounds](glm::ivec2 pos) { if (bounds.contains(pos)) output2.pixel(pos) = 255; }; rasterize_line_sdf(pixel_writer2, line, distance); - CHECK(output.buffer() == output2.buffer()); + CHECK(std::ranges::equal(output.buffer(), output2.buffer())); #ifdef WRITE_RASTERIZER_DEBUG_IMAGE // DEBUG: save image (image saved to build/Desktop-Profile/unittests/nucleus) diff --git a/unittests/nucleus/tile_scheduler.cpp b/unittests/nucleus/tile_scheduler.cpp index 1801dffe9..c1245f11d 100644 --- a/unittests/nucleus/tile_scheduler.cpp +++ b/unittests/nucleus/tile_scheduler.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,7 @@ std::unique_ptr scheduler_with_true_heights() QFile file(":/map/height_data.atb"); const auto open = file.open(QIODeviceBase::OpenModeFlag::ReadOnly); - assert(open); + Q_ASSERT(open); Q_UNUSED(open); const QByteArray data = file.readAll(); const auto decorator = AabbDecorator::make(TileHeights::deserialise(data)); diff --git a/unittests/nucleus/tile_util.cpp b/unittests/nucleus/tile_util.cpp index 7794de043..0320566d1 100644 --- a/unittests/nucleus/tile_util.cpp +++ b/unittests/nucleus/tile_util.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -60,7 +61,7 @@ TEST_CASE("tile/utils/refine_functor") QFile file(":/map/height_data.atb"); const auto open = file.open(QIODeviceBase::OpenModeFlag::ReadOnly); - assert(open); + Q_ASSERT(open); Q_UNUSED(open); const QByteArray data = file.readAll(); const auto decorator = AabbDecorator::make(radix::TileHeights::deserialise(data)); @@ -94,7 +95,7 @@ TEST_CASE("tile/utils/camera_frustum_contains_tile") using nucleus::tile::utils::camera_frustum_contains_tile_old; QFile file(":/map/height_data.atb"); const auto open = file.open(QIODeviceBase::OpenModeFlag::ReadOnly); - assert(open); + Q_ASSERT(open); Q_UNUSED(open); const QByteArray data = file.readAll(); const auto decorator = AabbDecorator::make(radix::TileHeights::deserialise(data)); @@ -145,7 +146,7 @@ TEST_CASE("tile/utils/camera_frustum_contains_tile") QFile file(":/map/height_data.atb"); const auto open = file.open(QIODeviceBase::OpenModeFlag::ReadOnly); - assert(open); + Q_ASSERT(open); Q_UNUSED(open); const QByteArray data = file.readAll(); const auto decorator = AabbDecorator::make(TileHeights::deserialise(data)); diff --git a/unittests/webgpu_engine/UnittestWebgpuContext.cpp b/unittests/webgpu_engine/UnittestWebgpuContext.cpp index b396ef9dd..26f8c8069 100644 --- a/unittests/webgpu_engine/UnittestWebgpuContext.cpp +++ b/unittests/webgpu_engine/UnittestWebgpuContext.cpp @@ -19,7 +19,7 @@ #include "UnittestWebgpuContext.h" #include "webgpu/base/webgpu_interface.hpp" -#include +#include #include #include #include @@ -94,13 +94,13 @@ UnittestWebgpuContext::UnittestWebgpuContext(bool use_default_limits, WGPULimits instance_desc.requiredFeatures = &timed_wait_feature; instance = wgpuCreateInstance(&instance_desc); - assert(instance); + Q_ASSERT(instance); WGPURequestAdapterOptions adapter_opts {}; adapter_opts.powerPreference = WGPUPowerPreference_HighPerformance; adapter_opts.compatibleSurface = nullptr; adapter = webgpu::requestAdapterSync(instance, adapter_opts); - assert(adapter); + Q_ASSERT(adapter); std::vector requiredFeatures; requiredFeatures.push_back(WGPUFeatureName_TimestampQuery); @@ -128,10 +128,10 @@ UnittestWebgpuContext::UnittestWebgpuContext(bool use_default_limits, WGPULimits }; device = webgpu::requestDeviceSync(instance, adapter, device_desc); - assert(device); + Q_ASSERT(device); queue = wgpuDeviceGetQueue(device); - assert(queue); + Q_ASSERT(queue); ctx.init(instance, device, adapter, nullptr, queue); ctx.resource_registry().recreate_all(device); diff --git a/webgpu/base/Framebuffer.cpp b/webgpu/base/Framebuffer.cpp index b8f1a9ed2..e47aa56e4 100644 --- a/webgpu/base/Framebuffer.cpp +++ b/webgpu/base/Framebuffer.cpp @@ -19,7 +19,7 @@ #include "Framebuffer.h" -#include +#include namespace webgpu { @@ -71,7 +71,7 @@ void Framebuffer::recreate_depth_texture() void Framebuffer::recreate_color_texture(size_t index) { - assert(index < m_format.color_formats.size()); + Q_ASSERT(index < m_format.color_formats.size()); WGPUTextureDescriptor texture_desc {}; texture_desc.label = WGPUStringView { .data = "framebuffer color texture", .length = WGPU_STRLEN }; @@ -110,13 +110,13 @@ const raii::Texture& Framebuffer::color_texture(size_t index) const raii::TextureView& Framebuffer::depth_texture_view() { - assert(m_depth_texture_view); + Q_ASSERT(m_depth_texture_view); return *m_depth_texture_view.get(); } const raii::Texture& Framebuffer::depth_texture() { - assert(m_depth_texture); + Q_ASSERT(m_depth_texture); return *m_depth_texture.get(); } @@ -160,8 +160,8 @@ std::unique_ptr Framebuffer::begin_render_pass(WGPUComm // ToDo: Implement this function glm::vec4 Framebuffer::read_colour_attachment_pixel(size_t index, const glm::dvec2& normalised_device_coordinates) { - assert(index < m_color_textures.size()); - assert(normalised_device_coordinates.x >= 0.0 && normalised_device_coordinates.x <= 1.0); + Q_ASSERT(index < m_color_textures.size()); + Q_ASSERT(normalised_device_coordinates.x >= 0.0 && normalised_device_coordinates.x <= 1.0); return {}; } diff --git a/webgpu/base/RenderResourceRegistry.cpp b/webgpu/base/RenderResourceRegistry.cpp index 056aa27fc..f5177ce21 100644 --- a/webgpu/base/RenderResourceRegistry.cpp +++ b/webgpu/base/RenderResourceRegistry.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include namespace webgpu { @@ -48,7 +48,7 @@ bool RenderResourceRegistry::has_shader(const std::string& name) const { return const raii::ShaderModule& RenderResourceRegistry::shader(const std::string& name) const { auto it = m_shader_index.find(name); - assert(it != m_shader_index.end()); + Q_ASSERT(it != m_shader_index.end()); return *m_shaders[it->second].module; } @@ -67,7 +67,7 @@ bool RenderResourceRegistry::has_bind_group_layout(const std::string& name) cons const raii::BindGroupLayout& RenderResourceRegistry::bind_group_layout(const std::string& name) const { auto it = m_layout_index.find(name); - assert(it != m_layout_index.end()); + Q_ASSERT(it != m_layout_index.end()); return *m_layouts[it->second].layout; } diff --git a/webgpu/base/raii/Pipeline.cpp b/webgpu/base/raii/Pipeline.cpp index 32481caf7..5c020a77a 100644 --- a/webgpu/base/raii/Pipeline.cpp +++ b/webgpu/base/raii/Pipeline.cpp @@ -19,6 +19,8 @@ #include "Pipeline.h" +#include + #include #include #include @@ -30,7 +32,7 @@ GenericRenderPipeline::GenericRenderPipeline(WGPUDevice device, const ShaderModu const std::vector>& blend_states) : m_framebuffer_format { framebuffer_format } { - assert(blend_states.size() <= framebuffer_format.color_formats.size()); + Q_ASSERT(blend_states.size() <= framebuffer_format.color_formats.size()); std::vector color_target_states; diff --git a/webgpu/base/raii/RawBuffer.h b/webgpu/base/raii/RawBuffer.h index d24d88e42..608a2127d 100644 --- a/webgpu/base/raii/RawBuffer.h +++ b/webgpu/base/raii/RawBuffer.h @@ -22,6 +22,7 @@ #include "base_types.h" #include #include +#include #include #include #include @@ -57,7 +58,7 @@ template class RawBuffer : public GpuResource #include +#include #include #include @@ -101,9 +102,9 @@ uint32_t Texture::max_mip_level_count(glm::uvec2 size) void Texture::write(WGPUQueue queue, const nucleus::utils::ColourTexture& data, uint32_t layer) { - assert(static_cast(data.width()) == m_descriptor.size.width); - assert(static_cast(data.height()) == m_descriptor.size.height); - assert(data.format() == nucleus::utils::ColourTexture::Format::Uncompressed_RGBA); // TODO compressed textures + Q_ASSERT(static_cast(data.width()) == m_descriptor.size.width); + Q_ASSERT(static_cast(data.height()) == m_descriptor.size.height); + Q_ASSERT(data.format() == nucleus::utils::ColourTexture::Format::Uncompressed_RGBA); // TODO compressed textures WGPUTexelCopyTextureInfo image_copy_texture {}; image_copy_texture.texture = m_handle; @@ -123,10 +124,10 @@ void Texture::write(WGPUQueue queue, const nucleus::utils::ColourTexture& data, void Texture::write(WGPUQueue queue, const nucleus::utils::ColourTexture3D& data, glm::uvec3 offset, uint32_t base_mip_level) { - assert(offset.x % 4 == 0); - assert(offset.y % 4 == 0); - assert(data.width() % 4 == 0); - assert(data.height() % 4 == 0); + Q_ASSERT(offset.x % 4 == 0); + Q_ASSERT(offset.y % 4 == 0); + Q_ASSERT(data.width() % 4 == 0); + Q_ASSERT(data.height() % 4 == 0); WGPUTexelCopyTextureInfo image_copy_texture {}; image_copy_texture.texture = m_handle; image_copy_texture.aspect = WGPUTextureAspect::WGPUTextureAspect_All; @@ -144,7 +145,7 @@ void Texture::write(WGPUQueue queue, const nucleus::utils::ColourTexture3D& data texture_data_layout.rowsPerImage = (data.height() + 3) / 4; // Also different for BC4 break; default: - assert(false && "Texture format not Implemented"); + Q_ASSERT(false && "Texture format not Implemented"); } texture_data_layout.offset = 0; @@ -234,7 +235,7 @@ void Texture::save_to_file(WGPUDevice device, const std::string& filename, size_ case WGPUTextureFormat::WGPUTextureFormat_R32Float: { const float* float_data = reinterpret_cast(data->data()); const size_t num_floats = data->size() / sizeof(float); - nucleus::Raster raster(glm::uvec2(width(), height())); + radix::Raster raster(glm::uvec2(width(), height())); std::copy(float_data, float_data + num_floats, raster.buffer().data()); nucleus::utils::geopng::write_encoded_float_png(raster, QString::fromStdString(filename)); } break; diff --git a/webgpu/base/raii/Texture.h b/webgpu/base/raii/Texture.h index 1454a0c3c..57b9a6e8d 100644 --- a/webgpu/base/raii/Texture.h +++ b/webgpu/base/raii/Texture.h @@ -22,9 +22,11 @@ #include "RawBuffer.h" #include "TextureView.h" #include "base_types.h" -#include "nucleus/Raster.h" #include "nucleus/utils/ColourTexture.h" #include "nucleus/utils/ColourTexture3D.h" +#include + +#include #include @@ -52,12 +54,13 @@ class Texture : public GpuResource void write(WGPUQueue queue, const nucleus::Raster& data, uint32_t layer = 0) + template + void write(WGPUQueue queue, const radix::Raster& data, uint32_t layer = 0) { // TODO maybe assert if RasterElementT and WGPUTextureFormat of this texture are compatible? - assert(static_cast(data.width()) == m_descriptor.size.width); - assert(static_cast(data.height()) == m_descriptor.size.height); + Q_ASSERT(static_cast(data.width()) == m_descriptor.size.width); + Q_ASSERT(static_cast(data.height()) == m_descriptor.size.height); WGPUTexelCopyTextureInfo texel_copy_texture_info {}; texel_copy_texture_info.texture = m_handle; @@ -72,7 +75,7 @@ class Texture : public GpuResource #include #include #include diff --git a/webgpu/base/util/VertexBufferInfo.cpp b/webgpu/base/util/VertexBufferInfo.cpp index a95728638..26237ed72 100644 --- a/webgpu/base/util/VertexBufferInfo.cpp +++ b/webgpu/base/util/VertexBufferInfo.cpp @@ -18,15 +18,15 @@ #include "util/VertexBufferInfo.h" -#include +#include namespace webgpu::util { WGPUVertexBufferLayout SingleVertexBufferInfo::vertex_buffer_layout() const { - assert(m_step_mode != WGPUVertexStepMode_Undefined); - assert(m_vertex_attributes.size() != 0); - assert(m_stride != 0); + Q_ASSERT(m_step_mode != WGPUVertexStepMode_Undefined); + Q_ASSERT(m_vertex_attributes.size() != 0); + Q_ASSERT(m_stride != 0); WGPUVertexBufferLayout vertex_buffer_layout {}; vertex_buffer_layout.arrayStride = m_stride; diff --git a/webgpu/base/webgpu_interface.cpp b/webgpu/base/webgpu_interface.cpp index 9c0cef025..4388c4c97 100644 --- a/webgpu/base/webgpu_interface.cpp +++ b/webgpu/base/webgpu_interface.cpp @@ -53,7 +53,7 @@ #include "util/string_cast.h" #include -#include +#include #include #ifdef __EMSCRIPTEN__ @@ -317,7 +317,7 @@ WGPUAdapter requestAdapterSync(WGPUInstance instance, const WGPURequestAdapterOp qFatal() << "Failed to obtain instance, WGPUWaitStatus was " << status; } - assert(request_ended_data.request_ended); + Q_ASSERT(request_ended_data.request_ended); return request_ended_data.adapter; } diff --git a/webgpu/compute/GpuTileStorage.cpp b/webgpu/compute/GpuTileStorage.cpp index 3626a01c7..6d0c0a0be 100644 --- a/webgpu/compute/GpuTileStorage.cpp +++ b/webgpu/compute/GpuTileStorage.cpp @@ -18,6 +18,8 @@ #include "GpuTileStorage.h" +#include + #include "nucleus/tile/conversion.h" #include "nucleus/utils/image_loader.h" @@ -40,10 +42,10 @@ TileStorageTexture::TileStorageTexture(WGPUDevice device, const glm::uvec2& reso void TileStorageTexture::store(size_t layer, const QByteArray& data) { - assert(layer < m_capacity); + Q_ASSERT(layer < m_capacity); // convert to raster and store in texture array - const nucleus::Raster height_image = nucleus::utils::image_loader::rgba8(data).value(); + const radix::Raster height_image = nucleus::utils::image_loader::rgba8(data).value(); const auto heightraster = nucleus::tile::conversion::to_u16raster(height_image); m_texture_array->texture().write(m_queue, heightraster, uint32_t(layer)); @@ -59,7 +61,7 @@ size_t TileStorageTexture::store(const QByteArray& data) void TileStorageTexture::reserve(size_t layer) { - assert(!m_layers_used[layer]); + Q_ASSERT(!m_layers_used[layer]); set_layer_used(layer); } @@ -80,7 +82,7 @@ void TileStorageTexture::clear() void TileStorageTexture::clear(size_t layer) { - assert(layer < m_capacity); + Q_ASSERT(layer < m_capacity); // update used layers if (m_layers_used.at(layer)) { @@ -115,7 +117,7 @@ const webgpu::raii::TextureWithSampler& TileStorageTexture::texture() const { re size_t TileStorageTexture::find_unused_layer_index() const { - assert(m_num_stored < m_capacity); + Q_ASSERT(m_num_stored < m_capacity); auto found_at = std::find(m_layers_used.begin(), m_layers_used.end(), false); return found_at - m_layers_used.begin(); diff --git a/webgpu/compute/NodeGraph.cpp b/webgpu/compute/NodeGraph.cpp index c08061970..5fb8ff1d9 100644 --- a/webgpu/compute/NodeGraph.cpp +++ b/webgpu/compute/NodeGraph.cpp @@ -22,8 +22,9 @@ #include #include +#include +#include #include -#include namespace webgpu_compute::nodes { @@ -39,7 +40,7 @@ const NodeRunFailureInfo& GraphRunFailureInfo::node_run_failure_info() const { r Node* NodeGraph::add_node(const std::string& name, std::unique_ptr node) { - assert(!m_nodes.contains(name)); + Q_ASSERT(!m_nodes.contains(name)); node->set_node_name(name); m_nodes.emplace(name, std::move(node)); return m_nodes.at(name).get(); @@ -48,7 +49,7 @@ Node* NodeGraph::add_node(const std::string& name, std::unique_ptr node) void NodeGraph::remove_node(const std::string& name) { auto it = m_nodes.find(name); - assert(it != m_nodes.end()); + Q_ASSERT(it != m_nodes.end()); Node* node = it->second.get(); for (auto& socket : node->input_sockets()) @@ -65,8 +66,8 @@ void NodeGraph::remove_node(const std::string& name) void NodeGraph::rename_node(const std::string& old_name, const std::string& new_name) { - assert(m_nodes.contains(old_name)); - assert(!m_nodes.contains(new_name)); + Q_ASSERT(m_nodes.contains(old_name)); + Q_ASSERT(!m_nodes.contains(new_name)); auto node = std::move(m_nodes.at(old_name)); m_nodes.erase(old_name); node->set_node_name(new_name); @@ -83,7 +84,7 @@ std::unordered_map>& NodeGraph::get_nodes() { const std::unordered_map>& NodeGraph::get_nodes() const { return m_nodes; } -tl::expected, std::string> NodeGraph::compute_topological_order() +std::expected, std::string> NodeGraph::compute_topological_order() { // basic idea: find topological ordering by counting in-coming edges (in-degree) // 1. start with nodes that have no incoming edges @@ -96,7 +97,7 @@ tl::expected, std::string> NodeGraph::compute_topological_ord // known as https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm if (m_nodes.empty()) - return tl::unexpected(std::string("node graph is empty")); + return std::unexpected(std::string("node graph is empty")); std::unordered_map in_degrees; std::queue node_queue; @@ -132,7 +133,7 @@ tl::expected, std::string> NodeGraph::compute_topological_ord for (auto& [node, in_degree] : in_degrees) { if (in_degree) { - return tl::unexpected(std::string("cycle in node graph detected")); + return std::unexpected(std::string("cycle in node graph detected")); } } @@ -177,7 +178,7 @@ void NodeGraph::run() void NodeGraph::emit_graph_failure(NodeRunFailureInfo info) { auto it = std::find_if(m_nodes.begin(), m_nodes.end(), [&info](const auto& key_value_pair) { return key_value_pair.second.get() == &info.node(); }); - assert(it != m_nodes.end()); + Q_ASSERT(it != m_nodes.end()); emit run_failed(GraphRunFailureInfo(it->first, info)); } diff --git a/webgpu/compute/NodeGraph.h b/webgpu/compute/NodeGraph.h index dbe79294f..67e73ca50 100644 --- a/webgpu/compute/NodeGraph.h +++ b/webgpu/compute/NodeGraph.h @@ -21,9 +21,9 @@ #include "GraphRunContext.h" #include "nodes/Node.h" +#include #include #include -#include #include namespace webgpu_compute::nodes { @@ -74,7 +74,7 @@ class NodeGraph : public QObject { // finds topological order of nodes and connects run_finished and run slots accordingly // safe to call multiple times - [[nodiscard]] tl::expected, std::string> compute_topological_order(); + [[nodiscard]] std::expected, std::string> compute_topological_order(); void connect_node_signals_and_slots(); public slots: diff --git a/webgpu/compute/NodeGraphSerialization.cpp b/webgpu/compute/NodeGraphSerialization.cpp index 154f5370f..4425f3860 100644 --- a/webgpu/compute/NodeGraphSerialization.cpp +++ b/webgpu/compute/NodeGraphSerialization.cpp @@ -74,13 +74,13 @@ QJsonObject serialize_node_graph(const NodeGraph& graph) return root; } -tl::expected, std::string> deserialize_node_graph(const QJsonObject& root, webgpu::Context& ctx) +std::expected, std::string> deserialize_node_graph(const QJsonObject& root, webgpu::Context& ctx) { // Format / version guard if (root["format"].toString() != QLatin1String(NODE_GRAPH_JSON_FORMAT)) - return tl::unexpected(std::string("invalid format tag (expected \"") + NODE_GRAPH_JSON_FORMAT + "\")"); + return std::unexpected(std::string("invalid format tag (expected \"") + NODE_GRAPH_JSON_FORMAT + "\")"); if (root["version"].toInt(-1) != NODE_GRAPH_JSON_VERSION) - return tl::unexpected(std::string("unsupported version (expected ") + std::to_string(NODE_GRAPH_JSON_VERSION) + ")"); + return std::unexpected(std::string("unsupported version (expected ") + std::to_string(NODE_GRAPH_JSON_VERSION) + ")"); auto graph = std::make_unique(); @@ -92,13 +92,13 @@ tl::expected, std::string> deserialize_node_graph(con const std::string type_name = node_obj["type"].toString().toStdString(); if (node_name.empty()) - return tl::unexpected(std::string("node entry is missing \"name\"")); + return std::unexpected(std::string("node entry is missing \"name\"")); if (graph->exists_node(node_name)) - return tl::unexpected("duplicate node name: \"" + node_name + "\""); + return std::unexpected("duplicate node name: \"" + node_name + "\""); auto node = NodeRegistry::instance().try_create(type_name, ctx); if (!node) - return tl::unexpected("unknown node type: \"" + type_name + "\""); + return std::unexpected("unknown node type: \"" + type_name + "\""); node->set_enabled(node_obj["enabled"].toBool(true)); if (node_obj.contains("settings")) @@ -120,23 +120,23 @@ tl::expected, std::string> deserialize_node_graph(con const std::string to_socket = to_obj["socket"].toString().toStdString(); if (!graph->exists_node(from_node)) - return tl::unexpected("connection references unknown source node \"" + from_node + "\""); + return std::unexpected("connection references unknown source node \"" + from_node + "\""); if (!graph->exists_node(to_node)) - return tl::unexpected("connection references unknown destination node \"" + to_node + "\""); + return std::unexpected("connection references unknown destination node \"" + to_node + "\""); Node& src = graph->get_node(from_node); Node& dst = graph->get_node(to_node); if (!src.has_output_socket(from_socket)) - return tl::unexpected("node \"" + from_node + "\" has no output socket \"" + from_socket + "\""); + return std::unexpected("node \"" + from_node + "\" has no output socket \"" + from_socket + "\""); if (!dst.has_input_socket(to_socket)) - return tl::unexpected("node \"" + to_node + "\" has no input socket \"" + to_socket + "\""); + return std::unexpected("node \"" + to_node + "\" has no input socket \"" + to_socket + "\""); OutputSocket& output = src.output_socket(from_socket); InputSocket& input = dst.input_socket(to_socket); if (output.type() != input.type()) - return tl::unexpected("type mismatch: \"" + from_node + "\":\"" + from_socket + "\" -> \"" + to_node + "\":\"" + to_socket + "\""); + return std::unexpected("type mismatch: \"" + from_node + "\":\"" + from_socket + "\" -> \"" + to_node + "\":\"" + to_socket + "\""); input.connect(output); } @@ -144,7 +144,7 @@ tl::expected, std::string> deserialize_node_graph(con // Cycle / empty check before wiring Qt signals auto topo = graph->compute_topological_order(); if (!topo) - return tl::unexpected(topo.error()); + return std::unexpected(topo.error()); graph->connect_node_signals_and_slots(); return graph; diff --git a/webgpu/compute/NodeGraphSerialization.h b/webgpu/compute/NodeGraphSerialization.h index 02f7132c9..ba1244a1c 100644 --- a/webgpu/compute/NodeGraphSerialization.h +++ b/webgpu/compute/NodeGraphSerialization.h @@ -20,9 +20,9 @@ #include "NodeGraph.h" #include +#include #include #include -#include #include namespace webgpu_compute::nodes { @@ -49,6 +49,6 @@ inline constexpr int NODE_GRAPH_JSON_VERSION = 1; /// Creates a graph from JSON, with full validation (format/version, duplicate or unknown /// node types, unknown sockets, socket type mismatches, cycles). On success the returned /// graph is fully wired (connect_node_signals_and_slots has been called). Ignores "ui". -[[nodiscard]] tl::expected, std::string> deserialize_node_graph(const QJsonObject& root, webgpu::Context& ctx); +[[nodiscard]] std::expected, std::string> deserialize_node_graph(const QJsonObject& root, webgpu::Context& ctx); } // namespace webgpu_compute::nodes diff --git a/webgpu/compute/NodeRegistry.cpp b/webgpu/compute/NodeRegistry.cpp index 792ca3fba..5f862e317 100644 --- a/webgpu/compute/NodeRegistry.cpp +++ b/webgpu/compute/NodeRegistry.cpp @@ -33,7 +33,7 @@ #include "nodes/TileStitchNode.h" #include #include -#include +#include namespace webgpu_compute { @@ -80,7 +80,7 @@ std::unique_ptr NodeRegistry::create(const std::string& type_name, auto node = try_create(type_name, ctx); if (!node) { qCritical() << "NodeRegistry::create: no node registered for type" << QString::fromStdString(type_name); - assert(false && "NodeRegistry::create: unknown node type"); + Q_ASSERT(false && "NodeRegistry::create: unknown node type"); } return node; } diff --git a/webgpu/compute/RectangularTileRegion.cpp b/webgpu/compute/RectangularTileRegion.cpp index 80e1ef017..f7fc4ac1d 100644 --- a/webgpu/compute/RectangularTileRegion.cpp +++ b/webgpu/compute/RectangularTileRegion.cpp @@ -18,12 +18,14 @@ #include "RectangularTileRegion.h" +#include + namespace webgpu_compute { std::vector RectangularTileRegion::get_tiles() const { - assert(min.x <= max.x); - assert(min.y <= max.y); + Q_ASSERT(min.x <= max.x); + Q_ASSERT(min.y <= max.y); std::vector tiles; tiles.reserve((max.x - min.x + 1) * (max.y - min.y + 1)); for (unsigned x = min.x; x <= max.x; x++) { diff --git a/webgpu/compute/nodes/ExportNode.cpp b/webgpu/compute/nodes/ExportNode.cpp index d179c6e52..3e1a5c39c 100644 --- a/webgpu/compute/nodes/ExportNode.cpp +++ b/webgpu/compute/nodes/ExportNode.cpp @@ -22,13 +22,12 @@ #include #include #include -#include #include #include #include -#include #include #include +#include namespace webgpu_compute::nodes { @@ -53,8 +52,8 @@ static void ensure_parent_dir(const std::string& file_path) { std::filesystem::c static void write_texture_file(const QByteArray& data, glm::uvec2 dims, const std::string& file_path) { const uint32_t bpp = static_cast(data.size()) / (dims.x * dims.y); - nucleus::Raster raster(dims); - auto& buf = raster.buffer(); + radix::Raster raster(dims); + auto buf = raster.buffer(); for (uint32_t y = 0; y < dims.y; y++) { for (uint32_t x = 0; x < dims.x; x++) { const uint32_t idx = (y * dims.x + x) * bpp; @@ -71,7 +70,7 @@ static void write_texture_file(const QByteArray& data, glm::uvec2 dims, const st static void write_buffer_file(const std::vector& data, glm::uvec2 dims, const std::string& file_path) { - nucleus::Raster raster(dims); + radix::Raster raster(dims); for (size_t i = 0; i < data.size(); i++) raster.buffer()[i] = static_cast(data[i]); ensure_parent_dir(file_path); diff --git a/webgpu/compute/nodes/LoadTextureNode.cpp b/webgpu/compute/nodes/LoadTextureNode.cpp index a0e6ec2bf..dc2d2697f 100644 --- a/webgpu/compute/nodes/LoadTextureNode.cpp +++ b/webgpu/compute/nodes/LoadTextureNode.cpp @@ -46,13 +46,13 @@ void LoadTextureNode::run_impl() qDebug() << "loading texture from " << m_settings.file_path; auto path = QString::fromStdString(m_settings.file_path); - tl::expected, QString> expected_image = nucleus::utils::image_loader::rgba8(path); + std::expected, QString> expected_image = nucleus::utils::image_loader::rgba8(path); if (!expected_image.has_value()) { fail_run("Failed to load image file at " + m_settings.file_path + ": " + expected_image.error().toStdString()); return; } - nucleus::Raster image = expected_image.value(); + radix::Raster image = expected_image.value(); m_output_texture = create_texture(m_ctx->device(), image.width(), image.height(), m_settings.format, m_settings.usage); m_output_texture->texture().write(m_ctx->queue(), image); diff --git a/webgpu/compute/nodes/Node.cpp b/webgpu/compute/nodes/Node.cpp index e28cc3b9e..eebfa17ad 100644 --- a/webgpu/compute/nodes/Node.cpp +++ b/webgpu/compute/nodes/Node.cpp @@ -19,6 +19,7 @@ #include "Node.h" #include +#include namespace webgpu_compute::nodes { @@ -42,7 +43,7 @@ InputSocket::InputSocket(Node& node, const std::string& name, DataType type) void InputSocket::connect(OutputSocket& output_socket) { - assert(type() == output_socket.type()); + Q_ASSERT(type() == output_socket.type()); if (is_socket_connected()) { m_connected_socket->remove_connected_socket(*this); } @@ -63,7 +64,7 @@ const OutputSocket& InputSocket::connected_socket() const { return *m_connected_ Data InputSocket::get_connected_data() { - assert(m_connected_socket != nullptr); + Q_ASSERT(m_connected_socket != nullptr); return m_connected_socket->get_data(); } @@ -75,7 +76,7 @@ OutputSocket::OutputSocket(Node& node, const std::string& name, DataType type, O void OutputSocket::connect(InputSocket& input_socket) { - assert(type() == input_socket.type()); + Q_ASSERT(type() == input_socket.type()); m_connected_sockets.push_back(&input_socket); input_socket.m_connected_socket = this; } @@ -86,14 +87,14 @@ const std::vector& OutputSocket::connected_sockets() const { retur Data OutputSocket::get_data() { Data output = m_output_func(); - assert(output.index() == type()); + Q_ASSERT(output.index() == type()); return output; } void OutputSocket::remove_connected_socket(InputSocket& input_socket) { auto it = std::find(m_connected_sockets.begin(), m_connected_sockets.end(), &input_socket); - assert(it != m_connected_sockets.end()); + Q_ASSERT(it != m_connected_sockets.end()); m_connected_sockets.erase(it); } diff --git a/webgpu/compute/nodes/TileStitchNode.cpp b/webgpu/compute/nodes/TileStitchNode.cpp index b5ec6700e..8f6834e7b 100644 --- a/webgpu/compute/nodes/TileStitchNode.cpp +++ b/webgpu/compute/nodes/TileStitchNode.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -51,7 +52,7 @@ void TileStitchNode::run_impl() // get tile ids to process const auto& tile_ids = *std::get*>()>(input_socket("tile ids").get_connected_data()); const auto& textures = *std::get*>()>(input_socket("texture data").get_connected_data()); - assert(tile_ids.size() == textures.size()); + Q_ASSERT(tile_ids.size() == textures.size()); // The original tile size is as configured in the settings glm::uvec2 so = m_settings.tile_size; @@ -81,8 +82,8 @@ void TileStitchNode::run_impl() // Check if inside bounds if (size_pixels.x > MAX_STITCHED_IMAGE_SIZE || size_pixels.y > MAX_STITCHED_IMAGE_SIZE) { - fail_run("Stitched image size would exceeds maximum size of " + std::to_string(MAX_STITCHED_IMAGE_SIZE) + "x" - + std::to_string(MAX_STITCHED_IMAGE_SIZE) + " pixel for zoom level " + std::to_string(zl)); + fail_run("Stitched image size would exceeds maximum size of " + std::to_string(MAX_STITCHED_IMAGE_SIZE) + "x" + std::to_string(MAX_STITCHED_IMAGE_SIZE) + + " pixel for zoom level " + std::to_string(zl)); return; } @@ -113,7 +114,7 @@ void TileStitchNode::run_impl() auto& tex = m_output_texture->texture(); // store them in this context, otherwise they get deleted too soon (might not be necessary...) - std::map> images; + std::map> images; // Load the tiles and upload them directly to the gpu texture for (size_t i = 0; i < tile_ids.size(); i++) { const auto& tile_id = tile_ids[i]; @@ -131,7 +132,7 @@ void TileStitchNode::run_impl() // Load image (NOTE: Only supports u8vec4 so far) images[i] = nucleus::utils::image_loader::rgba8(texture_data).value(); const auto& image = images[i]; - assert(image.width() == so.x && image.height() == so.y); + Q_ASSERT(image.width() == so.x && image.height() == so.y); WGPUTexelCopyTextureInfo image_copy_texture {}; image_copy_texture.texture = tex.handle(); @@ -149,7 +150,7 @@ void TileStitchNode::run_impl() copy_extent.height = s.y; copy_extent.depthOrArrayLayers = 1; - wgpuQueueWriteTexture(m_ctx->queue(), &image_copy_texture, image.bytes(), uint32_t(image.size_in_bytes()), &texture_data_layout, ©_extent); + wgpuQueueWriteTexture(m_ctx->queue(), &image_copy_texture, image.bytes().data(), uint32_t(image.bytes().size()), &texture_data_layout, ©_extent); } complete_run(); diff --git a/webgpu/engine/Context.cpp b/webgpu/engine/Context.cpp index 99a8aab63..8941bb63d 100644 --- a/webgpu/engine/Context.cpp +++ b/webgpu/engine/Context.cpp @@ -20,6 +20,8 @@ #include "Context.h" +#include + #include namespace webgpu_engine { @@ -33,7 +35,7 @@ Context::~Context() = default; void Context::internal_initialise() { - assert(m_webgpu_ctx_ptr != nullptr); + Q_ASSERT(m_webgpu_ctx_ptr != nullptr); auto& reg = webgpu_ctx().resource_registry(); reg.set_local_shader_path("webgpu", ALP_SHADER_DIR_WEBGPU); @@ -186,7 +188,7 @@ TileMeshRenderer* Context::tile_mesh_renderer() const { return m_tile_mesh_rende void Context::set_tile_mesh_renderer(std::shared_ptr new_tile_mesh_renderer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_tile_mesh_renderer = std::move(new_tile_mesh_renderer); } @@ -194,7 +196,7 @@ CloudRenderer* Context::cloud_renderer() const { return m_cloud_renderer.get(); void Context::set_cloud_renderer(std::shared_ptr new_cloud_renderer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_cloud_renderer = std::move(new_cloud_renderer); } @@ -202,7 +204,7 @@ AtmosphereRenderer* Context::atmosphere_renderer() const { return m_atmosphere_r void Context::set_atmosphere_renderer(std::shared_ptr new_atmosphere_renderer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_atmosphere_renderer = std::move(new_atmosphere_renderer); } @@ -210,7 +212,7 @@ OverlayRenderer* Context::overlay_renderer() const { return m_overlay_renderer.g void Context::set_overlay_renderer(std::shared_ptr new_overlay_renderer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_overlay_renderer = std::move(new_overlay_renderer); } @@ -218,7 +220,7 @@ TrackRenderer* Context::track_renderer() const { return m_track_renderer.get(); void Context::set_track_renderer(std::shared_ptr new_track_renderer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_track_renderer = std::move(new_track_renderer); } @@ -234,7 +236,7 @@ void Context::request_redraw() { emit redraw_requested(); } void Context::set_ortho_layer(std::shared_ptr new_ortho_layer) { - assert(!is_alive()); // only set before init is called. + Q_ASSERT(!is_alive()); // only set before init is called. m_ortho_layer = std::move(new_ortho_layer); }*/ diff --git a/webgpu/engine/Window.cpp b/webgpu/engine/Window.cpp index d0201cb61..a8fdd99e8 100644 --- a/webgpu/engine/Window.cpp +++ b/webgpu/engine/Window.cpp @@ -24,6 +24,8 @@ #include "overlay/OverlayRenderer.h" #include "webgpu/base/raii/RenderPassEncoder.h" #include "webgpu/engine/Context.h" +#include + #include #include #include @@ -44,7 +46,7 @@ void Window::set_context(Context* context) void Window::initialise_gpu() { - assert(m_context != nullptr); // just make sure that context is set + Q_ASSERT(m_context != nullptr); // just make sure that context is set create_buffers(); diff --git a/webgpu/engine/cloud/CloudRenderer.cpp b/webgpu/engine/cloud/CloudRenderer.cpp index 2be1bd257..e46787f12 100644 --- a/webgpu/engine/cloud/CloudRenderer.cpp +++ b/webgpu/engine/cloud/CloudRenderer.cpp @@ -22,6 +22,8 @@ #include "nucleus/camera/Definition.h" #include "nucleus/srs.h" #include "nucleus/utils/terrain_mesh_index_generator.h" +#include + #include #include @@ -474,8 +476,8 @@ void CloudRenderer::update_gpu_tiles_cloud(const std::vector& } for (const auto& tile : new_tiles) { // test for validity - assert(tile.id.zoom_level < 100); - assert(tile.texture); + Q_ASSERT(tile.id.zoom_level < 100); + Q_ASSERT(tile.texture); // Atlas is full if (m_loaded_cloud_textures.n_occupied() >= m_loaded_cloud_textures.size()) { @@ -488,9 +490,9 @@ void CloudRenderer::update_gpu_tiles_cloud(const std::vector& uint32_t atlas_x = layer_index & ATLAS_MASK_XY; uint32_t atlas_y = (layer_index >> ATLAS_BITS_XY) & ATLAS_MASK_XY; uint32_t atlas_z = (layer_index >> (2 * ATLAS_BITS_XY)) & ATLAS_MASK_Z; - assert(atlas_x < ATLAS_SCALE_XY); - assert(atlas_y < ATLAS_SCALE_XY); - assert(atlas_z < ATLAS_SCALE_Z); + Q_ASSERT(atlas_x < ATLAS_SCALE_XY); + Q_ASSERT(atlas_y < ATLAS_SCALE_XY); + Q_ASSERT(atlas_z < ATLAS_SCALE_Z); // Note: z is "up" in texture space for (int i = 0; i < tile.texture->size(); ++i) { const auto& level = tile.texture->at(i); diff --git a/webgpu/engine/overlay/TextureOverlay.cpp b/webgpu/engine/overlay/TextureOverlay.cpp index 496782ceb..15b40936e 100644 --- a/webgpu/engine/overlay/TextureOverlay.cpp +++ b/webgpu/engine/overlay/TextureOverlay.cpp @@ -20,6 +20,8 @@ #include "TextureOverlay.h" #include "webgpu/engine/Context.h" +#include + #include #include #include @@ -40,7 +42,7 @@ TextureOverlay::TextureOverlay() void TextureOverlay::load_image(const QString& path) { - assert(m_is_ready && "load_image must be called after ready()"); + Q_ASSERT(m_is_ready && "load_image must be called after ready()"); m_linked_texture = nullptr; // owned source takes over const auto image = nucleus::utils::image_loader::rgba8(path).value(); create_texture(*m_ctx, uint32_t(image.width()), uint32_t(image.height())); @@ -53,8 +55,8 @@ void TextureOverlay::link_texture(const webgpu::raii::TextureWithSampler* textur void TextureOverlay::load_texture(const webgpu::raii::TextureWithSampler& source) { - assert(m_is_ready && "load_texture must be called after ready()"); - assert(source.texture().descriptor().format == WGPUTextureFormat_RGBA8Unorm && "load_texture requires an RGBA8Unorm source texture"); + Q_ASSERT(m_is_ready && "load_texture must be called after ready()"); + Q_ASSERT(source.texture().descriptor().format == WGPUTextureFormat_RGBA8Unorm && "load_texture requires an RGBA8Unorm source texture"); m_linked_texture = nullptr; // owned source takes over create_texture(*m_ctx, uint32_t(source.texture().width()), uint32_t(source.texture().height())); @@ -194,7 +196,7 @@ void TextureOverlay::draw(const WGPUCommandEncoder& command_encoder, glm::uvec2 /*output_size*/) { const webgpu::raii::TextureWithSampler* tex = m_linked_texture ? m_linked_texture : m_overlay_texture.get(); - assert(tex && m_pipeline); + Q_ASSERT(tex && m_pipeline); webgpu::raii::BindGroup bind_group(m_ctx->device(), m_ctx->resource_registry().bind_group_layout("texture_overlay"), diff --git a/webgpu/engine/overlay/TextureOverlay.h b/webgpu/engine/overlay/TextureOverlay.h index 6158d6fb9..9095ee4b0 100644 --- a/webgpu/engine/overlay/TextureOverlay.h +++ b/webgpu/engine/overlay/TextureOverlay.h @@ -21,8 +21,8 @@ #include "Overlay.h" #include #include -#include #include +#include #include #include #include diff --git a/webgpu/engine/tile_mesh/TileMeshRenderer.cpp b/webgpu/engine/tile_mesh/TileMeshRenderer.cpp index ccbdff02e..9fd869936 100644 --- a/webgpu/engine/tile_mesh/TileMeshRenderer.cpp +++ b/webgpu/engine/tile_mesh/TileMeshRenderer.cpp @@ -24,6 +24,7 @@ #include "nucleus/srs.h" #include "nucleus/utils/terrain_mesh_index_generator.h" #include +#include #include #include #include @@ -315,8 +316,8 @@ void TileMeshRenderer::update_gpu_tiles_height(const std::vector +#include #include #include #include @@ -136,7 +137,7 @@ void TrackRenderer::add_track(const Track& track, const glm::vec4& color) void TrackRenderer::add_world_positions(const std::vector& world_positions, const glm::vec4& color) { - assert(!world_positions.empty()); + Q_ASSERT(!world_positions.empty()); m_position_buffers.emplace_back(std::make_unique>( m_ctx->device(), WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst, world_positions.size(), "track renderer, storage buffer for points"));