diff --git a/.gitignore b/.gitignore index 93524df8..82608382 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ -build/ + +CMakeUserPresets.json # VS project and working files *.vcxproj.user diff --git a/.reuse/dep5 b/.reuse/dep5 deleted file mode 100644 index b5fe2e75..00000000 --- a/.reuse/dep5 +++ /dev/null @@ -1,30 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: basis_universal -Source: https://github.com/BinomialLLC/basis_universal - -# We have asked Binomial about REUSE compliance for their repo, see https://github.com/BinomialLLC/basis_universal/issues/165 -Files: * -Copyright: 2019-2026 Binomial LLC - 2016 The Android Open Source Project -License: Apache-2.0 - -Files: OpenCL/* -Copyright: 2008-2020 The Khronos Group Inc. -License: Apache-2.0 - -Files: zstd/* -Copyright: 2016-present Facebook, Inc. -License: BSD-3-Clause - -Files: encoder/3rdparty/tinyexr.h -Copyright: 2014 - 2021, Syoyo Fujita and many contributors. - 2002 Industrial Light & Magic, a division of Lucas -License: BSD-3-Clause - -Files: encoder/3rdparty/qoi.h -Copyright: 2021 Dominic Szablewski - https://phoboslab.org -License: MIT - -Files: encoder/3rdparty/tinydds.h -Copyright: 2019 DeanoC -License: MIT diff --git a/CMakeLists.txt b/CMakeLists.txt index c3f8e281..39e4d072 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,12 @@ # It should also work without this option, but we do not test with it. cmake_minimum_required(VERSION 3.20) +if (NOT CMAKE_OSX_DEPLOYMENT_TARGET) + # Needed otherwise Xcode builds with the default installed SDK which can often be + # more recent than the macOS version being used. Must be before project. + set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "macOS Deployment Target") +endif() + project(basisu C CXX) # pybind11: allow old Python finder modules without complaining @@ -9,8 +15,6 @@ if (POLICY CMP0148) cmake_policy(SET CMP0148 OLD) endif() -add_compile_definitions($<$:_DEBUG=1>) - if (CMAKE_SYSTEM_NAME STREQUAL "WASI") set(BASISU_BUILD_WASM TRUE) else() @@ -20,18 +24,26 @@ endif() set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -option(BASISU_STATIC "static linking" FALSE) +option(BASISU_STATIC "static linking" TRUE) # NO-OP. basisu_encoder always built as a static library. option(BASISU_SAN "sanitize" FALSE) option(BASISU_EXAMPLES "build examples" TRUE) +option(BASISU_TOOL "build basisu tool" TRUE) option(BASISU_WASM_THREADING "Enable WASI threading support" OFF) option(BASISU_BUILD_PYTHON "Build native Python module via pybind11" OFF) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin) +# Using a generator expression here prevents multi-config generators (VS, Xcode, +# Ninja Multi-Config) from appending a per-configuration subdirectory. This is +# a MUCH simpler alternative to specifying RUNTIME_OUTPUT_DIRECTORY_ +# for each target and each config. +# NOTE: This means the output will be overwritten by a subsequent build for a +# different but that is true of the alternative too. +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_SOURCE_DIR}/bin>) # For MSVC builds default to SSE enabled, and determine if it's a 64-bit (-A x64) vs. 32-bit (-A Win32) build. if (MSVC) + # TODO: Fix me for Windows ARM option(BASISU_SSE "SSE 4.1 support" TRUE) - if ( CMAKE_GENERATOR_PLATFORM STREQUAL Win32 ) + if ( CMAKE_GENERATOR_PLATFORM STREQUAL "Win32" ) set(BASISU_BUILD_X64 0) else() set(BASISU_BUILD_X64 1) @@ -78,7 +90,8 @@ if (BASISU_BUILD_WASM) # WASM cannot use OpenCL set(BASISU_OPENCL OFF CACHE BOOL "" FORCE) - # WASM cannot use static linking + # WASM cannot use dynamic linking + # TODO: Fix this untrue statement. basisu_encoder always built as a static library. set(BASISU_STATIC OFF CACHE BOOL "" FORCE) # WASM cannot use sanitizers @@ -95,11 +108,19 @@ message("Initial BASISU_ZSTD=${BASISU_ZSTD}") message("Initial BASISU_OPENCL=${BASISU_OPENCL}") message("Initial BASISU_SAN=${BASISU_SAN}") message("Initial BASISU_EXAMPLES=${BASISU_EXAMPLES}") +message("Initial BASISU_TOOL=${BASISU_TOOL}") + +if(MINGW) + # Check if the Threads package is provided; if using Mingw it MIGHT be + find_package(Threads) +elseif(LINUX) + find_package(Threads REQUIRED) +endif() -if ((NOT MSVC) AND BASISU_OPENCL) - # With MSVC builds we use the Khronos lib/include files in the project's "OpenCL" directory, to completely avoid requiring fiddly to install vendor SDK's. +if ((NOT WIN32) AND BASISU_OPENCL) + # For Windows builds we use the Khronos lib/include files in the project's "OpenCL" directory, to completely avoid requiring fiddly to install vendor SDK's. # Otherwise we use the system's (if any). - find_package(OpenCL) + find_package(OpenCL REQUIRED) message(STATUS "OpenCL found: ${OPENCL_FOUND}") message(STATUS "OpenCL includes: ${OpenCL_INCLUDE_DIRS}") message(STATUS "OpenCL libraries: ${OpenCL_LIBRARIES}") @@ -129,90 +150,112 @@ else() message("Zstandard disabled") endif() +####################################################################### +# Specify floating point handling +# +# For deterministic results specify FP compile options for uniform +# handling of floating point operations across platforms and compilers + +# Compiler info query helpers + +# On CMake 3.25 or older CXX_COMPILER_FRONTEND_VARIANT is not always set +if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "") + set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "${CMAKE_CXX_COMPILER_ID}") +endif() + +#cmake_print_variables( +# CMAKE_CXX_COMPILER_ID +# CMAKE_CXX_COMPILER_VERSION +# CMAKE_CXX_COMPILER_FRONTEND_VARIANT +#) + +# Compiler accepts MSVC-style command line options +set(is_msvc_fe "$") +# Compiler accepts GNU-style command line options +set(is_gnu_fe1 "$") +# Compiler accepts AppleClang-style command line options, which is also GNU-style +set(is_gnu_fe2 "$") +# Compiler accepts GNU-style command line options +set(is_gnu_fe "$") + +# Compiler is Visual Studio cl.exe +set(is_msvccl "$>") +# Compiler is Visual Studio clangcl.exe +set(is_clangcl "$>") +# Compiler is upstream clang with the standard frontend +set(is_clang "$>") + +# Genex debug helper. Note that CXX_COMPILER_ID can only be used in +# compilation targets so won't work in a custom target. +#if(NOT TARGET debug_isgnufe1) +# add_custom_target(debug_isgnufe1 +# COMMAND ${CMAKE_COMMAND} -E echo "is_gnufe1_exp = $" +# ) +#endif() + +# On MSVC and CLangCL, set /fp:strict and /fp:precise, on clang +# -ffp-model=precise and on GNU CC -ffp-contract=off. These result in +# precise semantics always being used and fused multiply-add never +# being used, +add_compile_options( + $<$,19.30>>:/fp:strict> + $<$,19.30>>:/fp:precise> + $<${is_clangcl}:/fp:precise> + $<$,14.0.0>>:-Xclang$-ffp-contract=off> + $<$,10.0.0>>:-ffp-model=precise> + $<${is_gnu_fe}:-ffp-contract=off> + # Hide noise from clang and clangcl 20 warning the 2nd fp option changes + # one of the settings made the first. + $<$,20.0.0>>:-Wno-overriding-option> +) +####################################################################### + if (NOT MSVC AND NOT BASISU_BUILD_WASM) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") - - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + add_compile_options($<$:-g>) + # If you want to set an optimization option for non-debug too, use this instead. + #add_compile_options($,-g,-O3>) if (BASISU_SAN) message("Enabling SAN") - - set(SANITIZE_FLAGS "-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize=alignment") - - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${SANITIZE_FLAGS}") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${SANITIZE_FLAGS}") - - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${SANITIZE_FLAGS}") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${SANITIZE_FLAGS}") - endif() - # set(CMAKE_CXX_FLAGS -std=c++17) - set(GCC_COMPILE_FLAGS "-fvisibility=hidden -fPIC -fno-strict-aliasing -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 -Wall -Wextra -Wno-misleading-indentation") - - if (NOT BASISU_BUILD_X64) - set(GCC_COMPILE_FLAGS "${GCC_COMPILE_FLAGS} -m32") + add_compile_options(-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize=alignment) endif() - if (EMSCRIPTEN) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -DBASISU_SUPPORT_SSE=0") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1 -DBASISU_SUPPORT_SSE=0") - - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_LINK_FLAGS}") - elseif (BASISU_STATIC) - if (BASISU_SSE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=1 -msse4.1") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=1 -msse4.1") - else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=0") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=0") - endif() - - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_LINK_FLAGS} -static-libgcc -static-libstdc++ -static") - else() - if (BASISU_SSE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=1 -msse4.1") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=1 -msse4.1") - else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=0") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=0") - endif() - - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_LINK_FLAGS} -Wl,-rpath .") + # Add common non-MSVC flags excluding -fPIC. + add_compile_options(-fvisibility=hidden -fno-strict-aliasing -D_LARGEFILE64_SOURCE=1 + -D_FILE_OFFSET_BITS=64 -Wall -Wextra -Wno-unused-local-typedefs + -Wno-unused-value -Wno-unused-parameter -Wno-unused-variable + -Wno-misleading-indentation + -Wno-maybe-uninitialized -Wno-unused-function + -Wno-stringop-overflow -Wno-unknown-warning-option) + # Add -fPIC ONLY on non-Windows platforms + if (NOT WIN32) + add_compile_options(-fPIC) endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COMPILE_FLAGS}") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${GCC_COMPILE_FLAGS}") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${GCC_COMPILE_FLAGS} -D_DEBUG") + # AppleClang 14 raises this warning in zstd.cpp. + add_compile_options("$<$,$,17>>:-Wno-bitwise-instead-of-logical>") + + add_compile_options("$<$:-Wno-reorder;-Wno-class-memaccess;-Wno-deprecated-copy>") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COMPILE_FLAGS}") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${GCC_COMPILE_FLAGS}") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${GCC_COMPILE_FLAGS} -D_DEBUG") + add_compile_options($<$>:-m32>) + add_compile_definitions($<$:_DEBUG>) + if (EMSCRIPTEN) + add_link_options("SHELL:-s ALLOW_MEMORY_GROWTH=1") + endif() elseif (BASISU_BUILD_WASM) # _WASI_EMULATED_PROCESS_CLOCKS/-lwasi-emulated-process-clocks is only for ZStd add_compile_definitions(_WASI_EMULATED_PROCESS_CLOCKS) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lwasi-emulated-process-clocks") + add_link_options(-lwasi-emulated-process-clocks) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing -fvisibility=hidden -Wall -Wextra -Wno-unknown-warning-option") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing -fvisibility=hidden -Wall -Wextra -Wno-unknown-warning-option") + add_compile_options(-fno-strict-aliasing -fvisibility=hidden -Wall -Wextra -Wno-unknown-warning-option) - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") + add_compile_options($,-g,-O2>) - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2") - # We need a few MB of stack - don't skip this or WASMTime will silently allow the stack to grow into the heap or static memory, causing corruption. - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack-first -Wl,-z,stack-size=8388608") + add_link_options(-Wl,--stack-first -Wl,-z,stack-size=8388608) else() - if (BASISU_SSE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=1") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=1") - else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_SSE=0") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_SSE=0") - endif() + add_compile_options("$<$:-Wno-unused-variable;-Wno-unused-function>") endif() # Define the source files for the static library @@ -296,155 +339,117 @@ endif() # Create the static library add_library(basisu_encoder STATIC ${ENCODER_LIB_SRC_LIST}) -# Create the basisu executable and link against the static library -add_executable(basisu basisu_tool.cpp) -target_link_libraries(basisu PRIVATE basisu_encoder) - -# Create the new example executable and link against the static library -if(BASISU_EXAMPLES) - add_executable(example example/example.cpp) - target_link_libraries(example PRIVATE basisu_encoder) - - add_executable(example_capi example_capi/example_capi.c encoder/basisu_wasm_api.cpp encoder/basisu_wasm_transcoder_api.cpp) - target_link_libraries(example_capi PRIVATE basisu_encoder) - - add_executable(example_transcoding example_transcoding/example_transcoding.cpp example_transcoding/utils.cpp zstd/zstddeclib.c transcoder/basisu_transcoder.cpp) -endif() +target_include_directories(basisu_encoder +INTERFACE + $ + $ # So KTX-Software can use it. +) -if (BASISU_BUILD_WASM) - # Add proper suffix - set_target_properties(basisu PROPERTIES SUFFIX ".wasm") - - if(BASISU_EXAMPLES) - set_target_properties(example PROPERTIES SUFFIX ".wasm") - set_target_properties(example_capi PROPERTIES SUFFIX ".wasm") - set_target_properties(example_transcoding PROPERTIES SUFFIX ".wasm") - endif() +if (EMSCRIPTEN) + target_compile_definitions(basisu_encoder PUBLIC BASISU_SUPPORT_SSE=0) +else() + target_compile_definitions(basisu_encoder PUBLIC + BASISU_SUPPORT_SSE=$,1,0> + ) + target_compile_definitions(basisu_encoder PUBLIC + BASISU_WASI_THREADS=$,1,0> + ) + target_compile_options(basisu_encoder PRIVATE + "$<$,$>:-msse4.1>" + ) + target_compile_options(basisu_encoder PUBLIC + "$<$:-fno-exceptions -fno-rtti>" + ) +endif() - if (BASISU_WASM_THREADING) - # multithreaded: use "basisu_mt.wasm" - set_target_properties(basisu PROPERTIES OUTPUT_NAME "basisu_mt") - - if(BASISU_EXAMPLES) - set_target_properties(example PROPERTIES OUTPUT_NAME "example_mt") - set_target_properties(example_capi PROPERTIES OUTPUT_NAME "example_capi_mt") - set_target_properties(example_transcoding PROPERTIES OUTPUT_NAME "example_transcoding_mt") - endif() - +target_compile_definitions(basisu_encoder PRIVATE "BASISD_SUPPORT_KTX2_ZSTD=$,1,0>") +if (BASISU_OPENCL) + # basisu uses this to confirm the library has been compiled with OpenCL support hence PUBLIC. + target_compile_definitions(basisu_encoder PUBLIC BASISU_SUPPORT_OPENCL=1) + if (NOT WIN32) # True when the target system is not Windows. + # For Non-Windows builds, use the system OpenCL headers/libs, if cmake found them. + target_include_directories(basisu_encoder PRIVATE ${OpenCL_INCLUDE_DIRS}) + target_link_libraries(basisu_encoder PRIVATE ${OpenCL_LIBRARIES}) else() - # single-threaded: use "basisu_st.wasm" - set_target_properties(basisu PROPERTIES OUTPUT_NAME "basisu_st") - - if(BASISU_EXAMPLES) - set_target_properties(example PROPERTIES OUTPUT_NAME "example_st") - set_target_properties(example_capi PROPERTIES OUTPUT_NAME "example_capi_st") - set_target_properties(example_transcoding PROPERTIES OUTPUT_NAME "example_transcoding_st") + # For Windows builds, we use our local copies of the OpenCL import lib and Khronos headers. + target_include_directories(basisu_encoder PRIVATE "OpenCL") + if (BASISU_BUILD_X64) + target_link_libraries(basisu_encoder PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/OpenCL/lib/OpenCL64.lib") + else() + target_link_libraries(basisu_encoder PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/OpenCL/lib/OpenCL.lib") endif() - endif() +else() + target_compile_definitions(basisu_encoder PUBLIC BASISU_SUPPORT_OPENCL=0) +endif() - # 256 MB initial, 3.5 GB max — safe defaults for BasisU - target_link_options(basisu PRIVATE - -Wl,--initial-memory=268435456 - -Wl,--max-memory=3758096384 - ) +if (NOT MSVC AND NOT BASISU_BUILD_WASM) + # Only link 'm' on non-Windows platforms (Linux, macOS) + if (NOT WIN32) + target_link_libraries(basisu_encoder INTERFACE m) + endif() + if(Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + target_link_libraries(basisu_encoder INTERFACE Threads::Threads) + elseif(LINUX) + target_link_libraries(basisu_encoder INTERFACE dl Threads::Threads) + endif() + if (BASISU_STATIC AND MINGW) + target_link_options(basisu_encoder INTERFACE -static-libgcc -static-libstdc++ -static) + endif() +endif() - if (BASISU_EXAMPLES) - target_link_options(example PRIVATE - -Wl,--initial-memory=268435456 - -Wl,--max-memory=3758096384 - ) - target_link_options(example_capi PRIVATE - -Wl,--initial-memory=268435456 - -Wl,--max-memory=3758096384 - ) - target_link_options(example_transcoding PRIVATE +macro(set_common_executable_properties target link_encoder) + #if (MSVC) + target_sources(${target} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/basisu.manifest") + #endif() + if (${link_encoder}) + target_link_libraries(${target} PRIVATE basisu_encoder) + endif() + if (NOT BASISU_STATIC AND NOT EMSCRIPTEN AND NOT WIN32) + target_link_options(${target} PUBLIC -Wl,-rpath .) + endif() + if (BASISU_BUILD_WASM) + # Add proper suffix + set_target_properties(${target} PROPERTIES SUFFIX ".wasm") + if (BASISU_WASM_THREADING) + set_target_properties(${target} PROPERTIES OUTPUT_NAME "$_mt") + else() + set_target_properties(${target} PROPERTIES OUTPUT_NAME "$_st") + endif() + # 256 MB initial, 3.5 GB max safe defaults for BasisU + target_link_options(${target} PRIVATE -Wl,--initial-memory=268435456 -Wl,--max-memory=3758096384 ) endif() -endif() - -#if (MSVC) - target_sources(basisu PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/basisu.manifest") - if(BASISU_EXAMPLES) - target_sources(example PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/basisu.manifest") - target_sources(example_capi PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/basisu.manifest") - target_sources(example_transcoding PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/basisu.manifest") - endif() -#endif() +endmacro() -if (BASISU_ZSTD) - target_compile_definitions(basisu PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1) - if(BASISU_EXAMPLES) - target_compile_definitions(example PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1) - target_compile_definitions(example_capi PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1) - target_compile_definitions(example_transcoding PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1) - endif() -else() - target_compile_definitions(basisu PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0) - if(BASISU_EXAMPLES) - target_compile_definitions(example PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0) - target_compile_definitions(example_capi PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0) - target_compile_definitions(example_transcoding PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0) - endif() +if (BASISU_TOOL) + # Create the basisu executable + add_executable(basisu basisu_tool.cpp) + set_common_executable_properties(basisu TRUE) endif() -if (NOT MSVC) - # For Non-Windows builds, let cmake try and find the system OpenCL headers/libs for us. - if (BASISU_OPENCL AND OPENCL_FOUND) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_OPENCL=1") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_OPENCL=1") - - target_include_directories(basisu PRIVATE ${OpenCL_INCLUDE_DIRS}) - if(BASISU_EXAMPLES) - target_include_directories(example PRIVATE ${OpenCL_INCLUDE_DIRS}) - target_include_directories(example_capi PRIVATE ${OpenCL_INCLUDE_DIRS}) - endif() - target_include_directories(basisu_encoder PRIVATE ${OpenCL_INCLUDE_DIRS}) - set(BASISU_EXTRA_LIBS ${OpenCL_LIBRARIES}) - endif() -else() - # For Windows builds, we use our local copies of the OpenCL import lib and Khronos headers. - if (BASISU_OPENCL) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBASISU_SUPPORT_OPENCL=1") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBASISU_SUPPORT_OPENCL=1") - - target_include_directories(basisu PRIVATE "OpenCL") - if(BASISU_EXAMPLES) - target_include_directories(example PRIVATE "OpenCL") - target_include_directories(example_capi PRIVATE "OpenCL") - endif() - target_include_directories(basisu_encoder PRIVATE "OpenCL") +if (BASISU_EXAMPLES) + # Create the example executables + add_executable(examples example/example.cpp) + set_common_executable_properties(examples TRUE) - if (BASISU_BUILD_X64) - target_link_libraries(basisu PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/OpenCL/lib/OpenCL64.lib") - if(BASISU_EXAMPLES) - target_link_libraries(example PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/OpenCL/lib/OpenCL64.lib") - target_link_libraries(example_capi PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/OpenCL/lib/OpenCL64.lib") - endif() - else() - target_link_libraries(basisu PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/OpenCL/lib/OpenCL.lib") - if(BASISU_EXAMPLES) - target_link_libraries(example PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/OpenCL/lib/OpenCL.lib") - target_link_libraries(example_capi PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/OpenCL/lib/OpenCL.lib") - endif() - endif() - endif() -endif() + add_executable(example_capi example_capi/example_capi.c encoder/basisu_wasm_api.cpp encoder/basisu_wasm_transcoder_api.cpp) + set_common_executable_properties(example_capi TRUE) -if (NOT MSVC AND NOT BASISU_BUILD_WASM) - target_link_libraries(basisu PRIVATE m pthread ${BASISU_EXTRA_LIBS}) - if(BASISU_EXAMPLES) - target_link_libraries(example PRIVATE m pthread ${BASISU_EXTRA_LIBS}) - target_link_libraries(example_capi PRIVATE m pthread ${BASISU_EXTRA_LIBS}) - target_link_libraries(example_transcoding PRIVATE m pthread ${BASISU_EXTRA_LIBS}) - endif() + add_executable(example_transcoding example_transcoding/example_transcoding.cpp example_transcoding/utils.cpp zstd/zstddeclib.c transcoder/basisu_transcoder.cpp) + set_common_executable_properties(example_transcoding FALSE) + # As target is not linked with basisu_encoder, these values won't be imported. + target_compile_definitions(example_transcoding PRIVATE "BASISD_SUPPORT_KTX2_ZSTD=$,1,0>") + target_compile_options(example_transcoding PUBLIC + "$<$:-fno-exceptions -fno-rtti>" + ) endif() -if (NOT EMSCRIPTEN) +if (BASISU_TOOL AND NOT EMSCRIPTEN) if (UNIX AND NOT BASISU_BUILD_WASM) - if (CMAKE_BUILD_TYPE STREQUAL Release) + if (CMAKE_BUILD_TYPE STREQUAL "Release") if (APPLE) add_custom_command(TARGET basisu POST_BUILD COMMAND strip -X -x ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/basisu) #message("strip command: strip -X -x ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/basisu") @@ -456,71 +461,6 @@ if (NOT EMSCRIPTEN) endif() endif() -if (MSVC) - set_target_properties(basisu PROPERTIES - RUNTIME_OUTPUT_NAME "basisu" - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - ) - - if(BASISU_EXAMPLES) - set_target_properties(example PROPERTIES - RUNTIME_OUTPUT_NAME "example" - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - ) - endif() - - if(BASISU_EXAMPLES) - set_target_properties(example_capi PROPERTIES - RUNTIME_OUTPUT_NAME "example_capi" - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - ) - endif() - - if(BASISU_EXAMPLES) - set_target_properties(example_transcoding PROPERTIES - RUNTIME_OUTPUT_NAME "example_transcoding" - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - ) - endif() -endif() - -# ------------------------------------------------------------ -# Build WASM WASI executables (single or multi-threaded) -# ------------------------------------------------------------ -if (BASISU_BUILD_WASM) - target_compile_options(basisu_encoder PRIVATE -fno-exceptions -fno-rtti) - target_compile_options(basisu PRIVATE -fno-exceptions -fno-rtti) - - if (BASISU_EXAMPLES) - target_compile_options(example PRIVATE -fno-exceptions -fno-rtti) - target_compile_options(example_capi PRIVATE -fno-exceptions -fno-rtti) - target_compile_options(example_transcoding PRIVATE -fno-exceptions -fno-rtti) - endif() -endif() - -if (BASISU_BUILD_WASM AND BASISU_WASM_THREADING) - target_compile_definitions(basisu_encoder PRIVATE BASISU_WASI_THREADS=1) - target_compile_definitions(basisu PRIVATE BASISU_WASI_THREADS=1) - - if (BASISU_EXAMPLES) - target_compile_definitions(example PRIVATE BASISU_WASI_THREADS=1) - target_compile_definitions(example_capi PRIVATE BASISU_WASI_THREADS=1) - target_compile_definitions(example_transcoding PRIVATE BASISU_WASI_THREADS=1) - endif() -endif() - # ------------------------------------------------------------ # Build WASM WASI API module (single or multi-threaded) # ------------------------------------------------------------ @@ -538,7 +478,7 @@ if (BASISU_BUILD_WASM) add_executable(${BASISU_WASM_OUTPUT_NAME} ${BASISU_WASM_API_SRC}) target_link_libraries(${BASISU_WASM_OUTPUT_NAME} PRIVATE basisu_encoder) - + set_target_properties(${BASISU_WASM_OUTPUT_NAME} PROPERTIES SUFFIX ".wasm") # Common WASM options @@ -548,10 +488,9 @@ if (BASISU_BUILD_WASM) -Wl,--stack-first -Wl,-z,stack-size=8388608 ) - target_compile_options(${BASISU_WASM_OUTPUT_NAME} PRIVATE -fno-exceptions -fno-rtti) - + set_target_properties(${BASISU_WASM_OUTPUT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py/wasm + RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py/wasm> ) # Threading options @@ -568,7 +507,6 @@ if (BASISU_BUILD_WASM) target_compile_definitions(${BASISU_WASM_OUTPUT_NAME} PRIVATE BASISU_WASI_THREADS=1) endif() - endif() if (BASISU_BUILD_WASM) @@ -579,11 +517,11 @@ if (BASISU_BUILD_WASM) set(BASISU_TRANSCODER_WASM_OUTPUT_NAME "basisu_transcoder_module_st") endif() - add_executable(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} + add_executable(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/encoder/basisu_wasm_transcoder_api.cpp ${CMAKE_CURRENT_SOURCE_DIR}/transcoder/basisu_transcoder.cpp ${CMAKE_CURRENT_SOURCE_DIR}/zstd/zstddeclib.c) - + set_target_properties(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} PROPERTIES SUFFIX ".wasm") target_link_options(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} PRIVATE @@ -592,9 +530,9 @@ if (BASISU_BUILD_WASM) -Wl,-z,stack-size=4194304 ) target_compile_options(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} PRIVATE -fno-exceptions -fno-rtti) - + set_target_properties(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py/wasm + RUNTIME_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py/wasm> ) endif() @@ -609,9 +547,9 @@ if (BASISU_BUILD_PYTHON AND NOT BASISU_BUILD_WASM) pybind11_add_module(basisu_python python/basisu_encoder_pybind11.cpp - encoder/basisu_wasm_api.cpp + encoder/basisu_wasm_api.cpp ) - + # Ensure PIC ONLY for this target set_property(TARGET basisu_python PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -619,51 +557,38 @@ if (BASISU_BUILD_PYTHON AND NOT BASISU_BUILD_WASM) # Put basisu_python so into python/basisu_py set_target_properties(basisu_python PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py + LIBRARY_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py> PREFIX "" # Required by Python OUTPUT_NAME "basisu_python" # Just to be explicit ) - + if (MSVC) - set_target_properties(basisu_python PROPERTIES - LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py - LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py - LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py - LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py - SUFFIX ".pyd" - ) + set_target_properties(basisu_python PROPERTIES SUFFIX ".pyd") endif() - endif() if (BASISU_BUILD_PYTHON AND NOT BASISU_BUILD_WASM) find_package(pybind11 CONFIG REQUIRED) - + message(STATUS "Building pybind11 Python extension: basisu_transcoder_python") pybind11_add_module(basisu_transcoder_python python/basisu_transcoder_pybind11.cpp - encoder/basisu_wasm_transcoder_api.cpp + encoder/basisu_wasm_transcoder_api.cpp transcoder/basisu_transcoder.cpp zstd/zstddeclib.c ) - + # Ensure PIC ONLY for this target set_property(TARGET basisu_transcoder_python PROPERTY POSITION_INDEPENDENT_CODE ON) - + set_target_properties(basisu_transcoder_python PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py + LIBRARY_OUTPUT_DIRECTORY $<1:${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py> PREFIX "" OUTPUT_NAME "basisu_transcoder_python" ) - + if (MSVC) - set_target_properties(basisu_transcoder_python PROPERTIES - LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py - LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py - LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py - LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_SOURCE_DIR}/python/basisu_py - SUFFIX ".pyd" - ) + set_target_properties(basisu_transcoder_python PROPERTIES SUFFIX ".pyd") endif() endif() diff --git a/LICENSES/BSD-3-clause.txt b/LICENSES/BSD-3-Clause.txt similarity index 100% rename from LICENSES/BSD-3-clause.txt rename to LICENSES/BSD-3-Clause.txt diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 00000000..a63c36ac --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,39 @@ +version = 1 +SPDX-PackageName = "basis_universal" +SPDX-PackageDownloadLocation = "https://github.com/BinomialLLC/basis_universal" + +[[annotations]] +path = "**" +precedence = "aggregate" +SPDX-FileCopyrightText = ["2019-2024 Binomial LLC", "2016 The Android Open Source Project"] +SPDX-License-Identifier = "Apache-2.0" + +[[annotations]] +path = "OpenCL/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2008-2020 The Khronos Group Inc." +SPDX-License-Identifier = "Apache-2.0" + +[[annotations]] +path = "zstd/**" +precedence = "aggregate" +SPDX-FileCopyrightText = "2016-present Facebook, Inc." +SPDX-License-Identifier = "BSD-3-Clause" + +[[annotations]] +path = "encoder/3rdparty/tinyexr.h" +precedence = "aggregate" +SPDX-FileCopyrightText = ["2014 - 2021, Syoyo Fujita and many contributors.", "2002 Industrial Light & Magic, a division of Lucas"] +SPDX-License-Identifier = "BSD-3-Clause" + +[[annotations]] +path = "encoder/3rdparty/qoi.h" +precedence = "aggregate" +SPDX-FileCopyrightText = "2021 Dominic Szablewski - https://phoboslab.org" +SPDX-License-Identifier = "MIT" + +[[annotations]] +path = "encoder/3rdparty/tinydds.h" +precedence = "aggregate" +SPDX-FileCopyrightText = "2019 DeanoC" +SPDX-License-Identifier = "MIT" diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 00000000..ecb3b59e --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1,7 @@ + +* + +!.gitignore +!ocl_kernels.cl +!clean.bat +!readme.txt diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 00000000..3467e412 --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,5 @@ + +* + +!.gitignore +!readme.txt diff --git a/encoder/basisu_astc_ldr_common.cpp b/encoder/basisu_astc_ldr_common.cpp index a66969a8..770966fa 100644 --- a/encoder/basisu_astc_ldr_common.cpp +++ b/encoder/basisu_astc_ldr_common.cpp @@ -878,7 +878,7 @@ namespace astc_ldr } #endif - // TODO: Try two-step Lanczos iteration/Rayleigh–Ritz approximation in a 2-dimensional Krylov subspace method vs. power method. + // TODO: Try two-step Lanczos iteration/Rayleigh-Ritz approximation in a 2-dimensional Krylov subspace method vs. power method. static vec4F calc_pca_4D(uint32_t num_pixels, const vec4F* pPixels, const vec4F& mean_f) { float m00 = 0, m01 = 0, m02 = 0, m03 = 0; @@ -1127,7 +1127,7 @@ namespace astc_ldr { BASISU_NOTE_UNUSED(weight_ise_index); - assert((ccs_index >= 0) && (ccs_index <= 3)); + assert(ccs_index <= 3); assert((total_weights <= 32) || (total_weights == 65)); uint64_t total_err = 0; @@ -4414,7 +4414,7 @@ namespace astc_ldr const cem_encode_params& enc_params, uint32_t flags) { assert(g_initialized); - assert((ccs_index >= 0) && (ccs_index <= 3)); + assert(ccs_index <= 3); assert((ps.m_num_pixels) && (ps.m_num_pixels <= ASTC_LDR_MAX_BLOCK_PIXELS)); assert(pWeights0 && pWeights1); @@ -4830,7 +4830,7 @@ namespace astc_ldr uint32_t endpoint_ise_range, uint32_t weight_ise_range, vec4F& low_endpoint, vec4F& high_endpoint, float* pWeights0, float *pWeights1, uint32_t flags) { - assert((ccs_index >= 0) && (ccs_index <= 3)); + assert(ccs_index <= 3); const uint32_t num_endpoint_levels = astc_helpers::get_ise_levels(endpoint_ise_range); // astc_helpers::BISE_64_LEVELS=raw weights ([0,64], NOT [0,63]) diff --git a/transcoder/basisu_transcoder.cpp b/transcoder/basisu_transcoder.cpp index 1321c7da..a511d8d6 100644 --- a/transcoder/basisu_transcoder.cpp +++ b/transcoder/basisu_transcoder.cpp @@ -1,4 +1,4 @@ -// basisu_transcoder.cpp +// basisu_transcoder.cpp // Copyright (C) 2019-2026 Binomial LLC. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -32148,11 +32148,9 @@ namespace bc7f { scaledLow[i] = (xMinColor[i] << (8 - total_bits)); scaledLow[i] |= (scaledLow[i] >> total_bits); - assert(scaledLow[i] <= 255); scaledHigh[i] = (xMaxColor[i] << (8 - total_bits)); scaledHigh[i] |= (scaledHigh[i] >> total_bits); - assert(scaledHigh[i] <= 255); } float err0 = 0, err1 = 0; @@ -32222,11 +32220,9 @@ namespace bc7f { scaledLow[i] = (xMinColor[i] << (8 - total_bits)); scaledLow[i] |= (scaledLow[i] >> total_bits); - assert(scaledLow[i] <= 255); scaledHigh[i] = (xMaxColor[i] << (8 - total_bits)); scaledHigh[i] |= (scaledHigh[i] >> total_bits); - assert(scaledHigh[i] <= 255); } float err = 0; diff --git a/transcoder/basisu_transcoder_internal.h b/transcoder/basisu_transcoder_internal.h index c830795a..17844897 100644 --- a/transcoder/basisu_transcoder_internal.h +++ b/transcoder/basisu_transcoder_internal.h @@ -1758,7 +1758,7 @@ namespace basist return (int)std::round(d / (float)L); } - // L = quant step, alpha in [0,1.2] (typical 0.7–0.85) + // L = quant step, alpha in [0,1.2] (typical 0.7-0.85) if (L <= 0) return 0; @@ -2123,7 +2123,7 @@ namespace basist enum { TABLE_BITS = 8 }; // 256..1024 entries typical (8..10) enum { TABLE_SIZE = 1 << TABLE_BITS }; enum { MANT_BITS = 23 }; - enum { FRAC_BITS = MANT_BITS - TABLE_BITS }; + enum { FRAC_BITS = (int)MANT_BITS - (int)TABLE_BITS }; enum { FRAC_MASK = (1u << FRAC_BITS) - 1u }; extern bool g_initialized;