diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..06bc825 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,112 @@ +name: CI +on: [push, pull_request] +env: + DEVELOPER_DIR: /Applications/Xcode_12.2.app/Contents/Developer +jobs: + windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: cache-vulkansdk + id: cache-vulkansdk + uses: actions/cache@v1 + with: + path: "VulkanSDK" + key: VulkanSDK-1.2.162.0-Installer + - name: vulkansdk + if: steps.cache-vulkansdk.outputs.cache-hit != 'true' + run: | + Invoke-WebRequest -Uri https://sdk.lunarg.com/sdk/download/1.2.162.0/windows/VulkanSDK-1.2.162.0-Installer.exe?Human=true -OutFile VulkanSDK-1.2.162.0-Installer.exe + 7z x -aoa ./VulkanSDK-1.2.162.0-Installer.exe -oVulkanSDK + Remove-Item .\VulkanSDK\Demos, .\VulkanSDK\Samples, .\VulkanSDK\Third-Party, .\VulkanSDK\Tools, .\VulkanSDK\Tools32, .\VulkanSDK\Bin32, .\VulkanSDK\Lib32 -Recurse + - name: cache-swig + id: cache-swig + uses: actions/cache@v1 + with: + path: "SWIG" + key: swigwin-4.0.2 + - name: swig + if: steps.cache-swig.outputs.cache-hit != 'true' + run: | + Invoke-WebRequest -Uri https://nchc.dl.sourceforge.net/project/swig/swigwin/swigwin-4.0.2/swigwin-4.0.2.zip -OutFile swigwin-4.0.2.zip + 7z x swigwin-4.0.2.zip + mv swigwin-4.0.2 SWIG + - name: build + run: | + $env:VULKAN_SDK="$(pwd)\VulkanSDK" + $env:SWIG_DIR="$(pwd)\SWIG" + $env:SWIG_EXECUTABLE="$(pwd)\SWIG\swig.exe" + $env:PATH="$env:PATH;$env:SWIG_DIR" + mkdir build; cd build + cmake -A x64 ../src + cmake --build . --config Release -j 2 + + ubuntu: # no needs to install swig for it is already there + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: cache-vulkansdk + id: cache-vulkansdk + uses: actions/cache@v1 + with: + path: "1.2.162.0" + key: vulkansdk-linux-x86_64-1.2.162.0 + - name: vulkansdk + if: steps.cache-vulkansdk.outputs.cache-hit != 'true' + run: | + wget https://sdk.lunarg.com/sdk/download/1.2.162.0/linux/vulkansdk-linux-x86_64-1.2.162.0.tar.gz?Human=true -O vulkansdk-linux-x86_64-1.2.162.0.tar.gz + tar -xf vulkansdk-linux-x86_64-1.2.162.0.tar.gz + rm -rf 1.2.162.0/source 1.2.162.0/samples + find 1.2.162.0 -type f | grep -v -E 'vulkan|glslang' | xargs rm + - name: build + run: | + export VULKAN_SDK=`pwd`/1.2.162.0/x86_64 + mkdir build && cd build + cmake ../src + cmake --build . -j 2 + + macos: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: cache-vulkansdk + id: cache-vulkansdk + uses: actions/cache@v1 + with: + path: "vulkansdk-macos-1.2.162.0" + key: vulkansdk-macos-1.2.162.0 + - name: vulkansdk + if: steps.cache-vulkansdk.outputs.cache-hit != 'true' + run: | + wget https://sdk.lunarg.com/sdk/download/1.2.162.0/mac/vulkansdk-macos-1.2.162.0.dmg?Human=true -O vulkansdk-macos-1.2.162.0.dmg + hdiutil attach vulkansdk-macos-1.2.162.0.dmg + cp -r /Volumes/vulkansdk-macos-1.2.162.0 . + rm -rf vulkansdk-macos-1.2.162.0/Applications + find vulkansdk-macos-1.2.162.0 -type f | grep -v -E 'vulkan|glslang|MoltenVK' | xargs rm + hdiutil detach /Volumes/vulkansdk-macos-1.2.162.0 + - name: install-swig + run: brew install swig + - name: build-x86_64 + run: | + export VULKAN_SDK=`pwd`/vulkansdk-macos-1.2.162.0/macOS + mkdir build-x86_64 && cd build-x86_64 + cmake -DUSE_STATIC_MOLTENVK=ON -DCMAKE_OSX_ARCHITECTURES="x86_64" \ + -DVulkan_INCLUDE_DIR=`pwd`/../vulkansdk-macos-1.2.162.0/MoltenVK/include \ + -DVulkan_LIBRARY=`pwd`/../vulkansdk-macos-1.2.162.0/MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a \ + ../src + cmake --build . -j 3 +# - name: build-arm64 +# run: | +# export VULKAN_SDK=`pwd`/vulkansdk-macos-1.2.162.0/macOS +# mkdir build-arm64 && cd build-arm64 +# cmake -DUSE_STATIC_MOLTENVK=ON -DCMAKE_OSX_ARCHITECTURES="arm64" \ +# -DVulkan_INCLUDE_DIR=`pwd`/../vulkansdk-macos-1.2.162.0/MoltenVK/include \ +# -DVulkan_LIBRARY=`pwd`/../vulkansdk-macos-1.2.162.0/MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a \ +# ../src +# cmake --build . -j 3 \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6035a54 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,307 @@ +name: release +on: + push: + tags: + - '*' + +env: + DEVELOPER_DIR: /Applications/Xcode_12.2.app/Contents/Developer + APPLICATION_NAME: rife-ncnn-vulkan-python + +jobs: + + setup: + runs-on: ubuntu-latest + outputs: + APPNAME: ${{ steps.get_appname.outputs.APPNAME }} + VERSION: ${{ steps.get_version.outputs.VERSION }} + steps: + - name: get-appname + id: get_appname + run: echo ::set-output name=APPNAME::${APPLICATION_NAME} + - name: get-version + id: get_version + run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} + + ubuntu: + needs: [setup] + runs-on: ubuntu-latest + env: + PACKAGENAME: ${{ needs.setup.outputs.APPNAME }}-${{ needs.setup.outputs.VERSION }}-ubuntu + steps: + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: cache-vulkansdk + id: cache-vulkansdk + uses: actions/cache@v1 + with: + path: "1.2.162.0" + key: vulkansdk-linux-x86_64-1.2.162.0 + - name: vulkansdk + if: steps.cache-vulkansdk.outputs.cache-hit != 'true' + run: | + wget https://sdk.lunarg.com/sdk/download/1.2.162.0/linux/vulkansdk-linux-x86_64-1.2.162.0.tar.gz?Human=true -O vulkansdk-linux-x86_64-1.2.162.0.tar.gz + tar -xf vulkansdk-linux-x86_64-1.2.162.0.tar.gz + rm -rf 1.2.162.0/source 1.2.162.0/samples + find 1.2.162.0 -type f | grep -v -E 'vulkan|glslang' | xargs rm + - name: build + run: | + export VULKAN_SDK=`pwd`/1.2.162.0/x86_64 + mkdir build && cd build + cmake ../src + cmake --build . -j 2 + - name: package + run: | + mkdir -p ${{ env.PACKAGENAME }} + cp README.md LICENSE ${{ env.PACKAGENAME }} + cp build/rife_ncnn_vulkan.py ${{ env.PACKAGENAME }} + cp build/rife_ncnn_vulkan_wrapper.py ${{ env.PACKAGENAME }} + cp build/_rife_ncnn_vulkan_wrapper.so ${{ env.PACKAGENAME }} + cp -r models/ ${{ env.PACKAGENAME }} + zip -9 -r ${{ env.PACKAGENAME }}.zip ${{ env.PACKAGENAME }} + - name: upload + uses: actions/upload-artifact@v2 + with: + name: ${{ env.PACKAGENAME }} + path: ${{ env.PACKAGENAME }}.zip + + openmp-macos: + runs-on: macos-latest + steps: + - name: cache-openmp + id: cache-openmp + uses: actions/cache@v1 + with: + path: openmp-install + key: openmp-macos-release-11.0.0 + - name: checkout + if: steps.cache-openmp.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + - name: openmp + if: steps.cache-openmp.outputs.cache-hit != 'true' + run: | + wget https://github.com/llvm/llvm-project/releases/download/llvmorg-11.0.0/openmp-11.0.0.src.tar.xz + tar -xf openmp-11.0.0.src.tar.xz + cd openmp-11.0.0.src + sed -i'' -e '/.size __kmp_unnamed_critical_addr/d' runtime/src/z_Linux_asm.S + sed -i'' -e 's/__kmp_unnamed_critical_addr/___kmp_unnamed_critical_addr/g' runtime/src/z_Linux_asm.S + - name: build-x86_64 + if: steps.cache-openmp.outputs.cache-hit != 'true' + run: | + cd openmp-11.0.0.src + mkdir build-x86_64 && cd build-x86_64 + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=install -DCMAKE_OSX_ARCHITECTURES="x86_64" \ + -DLIBOMP_ENABLE_SHARED=OFF -DLIBOMP_OMPT_SUPPORT=OFF -DLIBOMP_USE_HWLOC=OFF .. + cmake --build . -j 2 + cmake --build . --target install + - name: build-arm64 + if: steps.cache-openmp.outputs.cache-hit != 'true' + run: | + cd openmp-11.0.0.src + mkdir build-arm64 && cd build-arm64 + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=install -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -DLIBOMP_ENABLE_SHARED=OFF -DLIBOMP_OMPT_SUPPORT=OFF -DLIBOMP_USE_HWLOC=OFF .. + cmake --build . -j 2 + cmake --build . --target install + - name: merge-fat-library + if: steps.cache-openmp.outputs.cache-hit != 'true' + run: | + rm -rf $GITHUB_WORKSPACE/openmp-install + mkdir -p $GITHUB_WORKSPACE/openmp-install + cp -r openmp-11.0.0.src/build-x86_64/install/include $GITHUB_WORKSPACE/openmp-install + mkdir -p $GITHUB_WORKSPACE/openmp-install/lib + lipo -create openmp-11.0.0.src/build-x86_64/install/lib/libomp.a openmp-11.0.0.src/build-arm64/install/lib/libomp.a -o $GITHUB_WORKSPACE/openmp-install/lib/libomp.a + - name: upload + uses: actions/upload-artifact@v2 + with: + name: openmp-macos + path: openmp-install + + macos: + needs: [setup, openmp-macos] + runs-on: macos-latest + env: + PACKAGENAME: ${{ needs.setup.outputs.APPNAME }}-${{ needs.setup.outputs.VERSION }}-macos + steps: + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: download-openmp-macos + uses: actions/download-artifact@v2 + with: + name: openmp-macos + path: openmp-macos + - name: install-openmp + run: | + sudo cp openmp-macos/include/* $DEVELOPER_DIR/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include + sudo cp openmp-macos/lib/libomp.a $DEVELOPER_DIR/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib + - name: cache-vulkansdk + id: cache-vulkansdk + uses: actions/cache@v1 + with: + path: "vulkansdk-macos-1.2.162.0" + key: vulkansdk-macos-1.2.162.0 + - name: vulkansdk + if: steps.cache-vulkansdk.outputs.cache-hit != 'true' + run: | + wget https://sdk.lunarg.com/sdk/download/1.2.162.0/mac/vulkansdk-macos-1.2.162.0.dmg?Human=true -O vulkansdk-macos-1.2.162.0.dmg + hdiutil attach vulkansdk-macos-1.2.162.0.dmg + cp -r /Volumes/vulkansdk-macos-1.2.162.0 . + rm -rf vulkansdk-macos-1.2.162.0/Applications + find vulkansdk-macos-1.2.162.0 -type f | grep -v -E 'vulkan|glslang|MoltenVK' | xargs rm + hdiutil detach /Volumes/vulkansdk-macos-1.2.162.0 + - name: install-swig + run: brew install swig + - name: build-x86_64 + run: | + export VULKAN_SDK=`pwd`/vulkansdk-macos-1.2.162.0/macOS + mkdir build-x86_64 && cd build-x86_64 + cmake -DUSE_STATIC_MOLTENVK=ON -DCMAKE_OSX_ARCHITECTURES="x86_64" \ + -DOpenMP_C_FLAGS="-Xclang -fopenmp" -DOpenMP_CXX_FLAGS="-Xclang -fopenmp" \ + -DOpenMP_C_LIB_NAMES="libomp" -DOpenMP_CXX_LIB_NAMES="libomp" \ + -DOpenMP_libomp_LIBRARY="$DEVELOPER_DIR/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libomp.a" \ + -DVulkan_INCLUDE_DIR=`pwd`/../vulkansdk-macos-1.2.162.0/MoltenVK/include \ + -DVulkan_LIBRARY=`pwd`/../vulkansdk-macos-1.2.162.0/MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a \ + ../src + cmake --build . -j 3 +# - name: build-arm64 +# run: | +# export VULKAN_SDK=`pwd`/vulkansdk-macos-1.2.162.0/macOS +# mkdir build-arm64 && cd build-arm64 +# cmake -DUSE_STATIC_MOLTENVK=ON -DCMAKE_OSX_ARCHITECTURES="arm64" \ +# -DCMAKE_CROSSCOMPILING=ON -DCMAKE_SYSTEM_PROCESSOR=arm64 \ +# -DOpenMP_C_FLAGS="-Xclang -fopenmp" -DOpenMP_CXX_FLAGS="-Xclang -fopenmp" \ +# -DOpenMP_C_LIB_NAMES="libomp" -DOpenMP_CXX_LIB_NAMES="libomp" \ +# -DOpenMP_libomp_LIBRARY="$DEVELOPER_DIR/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libomp.a" \ +# -DVulkan_INCLUDE_DIR=`pwd`/../vulkansdk-macos-1.2.162.0/MoltenVK/include \ +# -DVulkan_LIBRARY=`pwd`/../vulkansdk-macos-1.2.162.0/MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a \ +# ../src +# cmake --build . -j 2 + - name: package + run: | + mkdir -p ${{ env.PACKAGENAME }} + cp README.md LICENSE ${{ env.PACKAGENAME }} + cp build-x86_64/rife_ncnn_vulkan.py ${{ env.PACKAGENAME }} + cp build-x86_64/rife_ncnn_vulkan_wrapper.py ${{ env.PACKAGENAME }} + cp build-x86_64/_rife_ncnn_vulkan_wrapper.so ${{ env.PACKAGENAME }} + cp -r models/ ${{ env.PACKAGENAME }} + zip -9 -r ${{ env.PACKAGENAME }}.zip ${{ env.PACKAGENAME }} + - name: upload + uses: actions/upload-artifact@v2 + with: + name: ${{ env.PACKAGENAME }} + path: ${{ env.PACKAGENAME }}.zip + + windows: + needs: [setup] + runs-on: windows-latest + env: + PACKAGENAME: ${{ needs.setup.outputs.APPNAME }}-${{ needs.setup.outputs.VERSION }}-windows + steps: + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: cache-vulkansdk + id: cache-vulkansdk + uses: actions/cache@v1 + with: + path: "VulkanSDK" + key: VulkanSDK-1.2.162.0-Installer + - name: vulkansdk + if: steps.cache-vulkansdk.outputs.cache-hit != 'true' + run: | + Invoke-WebRequest -Uri https://sdk.lunarg.com/sdk/download/1.2.162.0/windows/VulkanSDK-1.2.162.0-Installer.exe?Human=true -OutFile VulkanSDK-1.2.162.0-Installer.exe + 7z x -aoa ./VulkanSDK-1.2.162.0-Installer.exe -oVulkanSDK + Remove-Item .\VulkanSDK\Demos, .\VulkanSDK\Samples, .\VulkanSDK\Third-Party, .\VulkanSDK\Tools, .\VulkanSDK\Tools32, .\VulkanSDK\Bin32, .\VulkanSDK\Lib32 -Recurse + - name: cache-swig + id: cache-swig + uses: actions/cache@v1 + with: + path: "SWIG" + key: swigwin-4.0.2 + - name: swig + if: steps.cache-swig.outputs.cache-hit != 'true' + run: | + Invoke-WebRequest -Uri https://nchc.dl.sourceforge.net/project/swig/swigwin/swigwin-4.0.2/swigwin-4.0.2.zip -OutFile swigwin-4.0.2.zip + 7z x swigwin-4.0.2.zip + mv swigwin-4.0.2 SWIG + - name: build + run: | + $env:VULKAN_SDK="$(pwd)/VulkanSDK" + $env:SWIG_DIR="$(pwd)\SWIG" + $env:SWIG_EXECUTABLE="$(pwd)\SWIG\swig.exe" + $env:PATH="$env:PATH;$env:SWIG_DIR" + mkdir build; cd build + cmake -A x64 ../src + cmake --build . --config Release -j 2 + - name: package + run: | + mkdir ${{ env.PACKAGENAME }} + ls build + Copy-Item -Verbose -Path "README.md" -Destination "${{ env.PACKAGENAME }}" + Copy-Item -Verbose -Path "LICENSE" -Destination "${{ env.PACKAGENAME }}" + Copy-Item -Verbose -Path "src\rife_ncnn_vulkan.py" -Destination "${{ env.PACKAGENAME }}" + Copy-Item -Verbose -Path "build\rife_ncnn_vulkan_wrapper.py" -Destination "${{ env.PACKAGENAME }}" + Copy-Item -Verbose -Path "build\Release\_rife_ncnn_vulkan_wrapper.pyd" -Destination "${{ env.PACKAGENAME }}" + Copy-Item -Verbose -Path "C:\windows\system32\vcomp140.dll" -Destination "${{ env.PACKAGENAME }}" + Copy-Item -Verbose -Recurse -Path "models" -Destination "${{ env.PACKAGENAME }}" + 7z a -r ${{ env.PACKAGENAME }}.zip ${{ env.PACKAGENAME }} + - name: upload + uses: actions/upload-artifact@v2 + with: + name: ${{ env.PACKAGENAME }} + path: ${{ env.PACKAGENAME }}.zip + + release: + needs: [setup, ubuntu, macos, windows] + runs-on: ubuntu-latest + steps: + - name: download + uses: actions/download-artifact@v2 + with: + path: artifacts + + - name: create-release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ needs.setup.outputs.VERSION }} + release_name: Release ${{ needs.setup.outputs.VERSION }} + draft: false + prerelease: false + + - name: upload-ubuntu + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PACKAGENAME: ${{ needs.setup.outputs.APPNAME }}-${{ needs.setup.outputs.VERSION }}-ubuntu + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: artifacts/${{ env.PACKAGENAME }}/${{ env.PACKAGENAME }}.zip + asset_name: ${{ env.PACKAGENAME }}.zip + asset_content_type: application/zip + + - name: upload-macos + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PACKAGENAME: ${{ needs.setup.outputs.APPNAME }}-${{ needs.setup.outputs.VERSION }}-macos + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: artifacts/${{ env.PACKAGENAME }}/${{ env.PACKAGENAME }}.zip + asset_name: ${{ env.PACKAGENAME }}.zip + asset_content_type: application/zip + + - name: upload-windows + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PACKAGENAME: ${{ needs.setup.outputs.APPNAME }}-${{ needs.setup.outputs.VERSION }}-windows + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: artifacts/${{ env.PACKAGENAME }}/${{ env.PACKAGENAME }}.zip + asset_name: ${{ env.PACKAGENAME }}.zip + asset_content_type: application/zip diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7b450bf..0dcdd73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,12 +1,20 @@ +cmake_minimum_required(VERSION 3.15) cmake_policy(SET CMP0091 NEW) set(CMAKE_POLICY_DEFAULT_CMP0091 NEW) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") -project(rife-ncnn-vulkan) +project(rife-ncnn-vulkan-python) -cmake_minimum_required(VERSION 3.9) - -set(CMAKE_BUILD_TYPE Release) +# SWIG +find_package(Python REQUIRED COMPONENTS Development) +find_package(SWIG REQUIRED COMPONENTS python) +if(SWIG_FOUND) + message("SWIG found: ${SWIG_EXECUTABLE}") + INCLUDE(${SWIG_USE_FILE}) + if(NOT SWIG_python_FOUND) + message(WARNING "SWIG python bindings cannot be generated") + endif() +endif() option(USE_SYSTEM_NCNN "build with system libncnn" OFF) option(USE_SYSTEM_WEBP "build with system libwebp" OFF) @@ -33,6 +41,7 @@ macro(rife_add_shader SHADER_SRC) endmacro() include_directories(${CMAKE_CURRENT_BINARY_DIR}) +include_directories(.) if(OPENMP_FOUND) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") @@ -101,7 +110,7 @@ if(NOT USE_SYSTEM_NCNN) option(NCNN_BUILD_TOOLS "" OFF) option(NCNN_BUILD_EXAMPLES "" OFF) option(NCNN_DISABLE_RTTI "" ON) - option(NCNN_DISABLE_EXCEPTION "" ON) + option(NCNN_DISABLE_EXCEPTION "" OFF) option(WITH_LAYER_absval "" OFF) option(WITH_LAYER_argmax "" OFF) @@ -185,39 +194,39 @@ if(NOT USE_SYSTEM_NCNN) add_subdirectory(ncnn) endif() -if(USE_SYSTEM_WEBP) - set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") - find_package(WebP) - if(NOT TARGET webp) - message(WARNING "webp target not found! USE_SYSTEM_WEBP will be turned off.") - set(USE_SYSTEM_WEBP OFF) - endif() -endif() - -if(NOT USE_SYSTEM_WEBP) - # build libwebp library - if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libwebp/CMakeLists.txt") - message(FATAL_ERROR "The submodules were not downloaded! Please update submodules with \"git submodule update --init --recursive\" and try again.") - endif() - - option(WEBP_ENABLE_SIMD "" ON) - option(WEBP_BUILD_ANIM_UTILS "" OFF) - option(WEBP_BUILD_CWEBP "" OFF) - option(WEBP_BUILD_DWEBP "" OFF) - option(WEBP_BUILD_GIF2WEBP "" OFF) - option(WEBP_BUILD_IMG2WEBP "" OFF) - option(WEBP_BUILD_VWEBP "" OFF) - option(WEBP_BUILD_WEBPINFO "" OFF) - option(WEBP_BUILD_WEBPMUX "" OFF) - option(WEBP_BUILD_EXTRAS "" OFF) - option(WEBP_BUILD_WEBP_JS "" OFF) - option(WEBP_NEAR_LOSSLESS "" OFF) - option(WEBP_ENABLE_SWAP_16BIT_CSP "" OFF) - - add_subdirectory(libwebp) - - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libwebp/src) -endif() +#if(USE_SYSTEM_WEBP) +# set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") +# find_package(WebP) +# if(NOT TARGET webp) +# message(WARNING "webp target not found! USE_SYSTEM_WEBP will be turned off.") +# set(USE_SYSTEM_WEBP OFF) +# endif() +#endif() +# +#if(NOT USE_SYSTEM_WEBP) +# # build libwebp library +# if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/libwebp/CMakeLists.txt") +# message(FATAL_ERROR "The submodules were not downloaded! Please update submodules with \"git submodule update --init --recursive\" and try again.") +# endif() +# +# option(WEBP_ENABLE_SIMD "" ON) +# option(WEBP_BUILD_ANIM_UTILS "" OFF) +# option(WEBP_BUILD_CWEBP "" OFF) +# option(WEBP_BUILD_DWEBP "" OFF) +# option(WEBP_BUILD_GIF2WEBP "" OFF) +# option(WEBP_BUILD_IMG2WEBP "" OFF) +# option(WEBP_BUILD_VWEBP "" OFF) +# option(WEBP_BUILD_WEBPINFO "" OFF) +# option(WEBP_BUILD_WEBPMUX "" OFF) +# option(WEBP_BUILD_EXTRAS "" OFF) +# option(WEBP_BUILD_WEBP_JS "" OFF) +# option(WEBP_NEAR_LOSSLESS "" OFF) +# option(WEBP_ENABLE_SWAP_16BIT_CSP "" OFF) +# +# add_subdirectory(libwebp) +# +# include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libwebp/src) +#endif() rife_add_shader(rife_preproc.comp) rife_add_shader(rife_postproc.comp) @@ -231,15 +240,15 @@ rife_add_shader(warp_pack8.comp) add_custom_target(generate-spirv DEPENDS ${SHADER_SPV_HEX_FILES}) -add_executable(rife-ncnn-vulkan - main.cpp - rife.cpp - warp.cpp -) - -add_dependencies(rife-ncnn-vulkan generate-spirv) +#add_executable(rife-ncnn-vulkan +# main.cpp +# rife.cpp +# warp.cpp +#) +# +#add_dependencies(rife-ncnn-vulkan generate-spirv) -set(RIFE_LINK_LIBRARIES ncnn webp ${Vulkan_LIBRARY}) +#set(RIFE_LINK_LIBRARIES ncnn webp ${Vulkan_LIBRARY}) if(USE_STATIC_MOLTENVK) find_library(CoreFoundation NAMES CoreFoundation) @@ -263,4 +272,16 @@ if(USE_STATIC_MOLTENVK) ) endif() -target_link_libraries(rife-ncnn-vulkan ${RIFE_LINK_LIBRARIES}) +set(RIFE_LINK_LIBRARIES ncnn ${Vulkan_LIBRARY}) + +# Swig build +file(COPY ../models DESTINATION .) +file(COPY rife_ncnn_vulkan.py DESTINATION .) +set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD) +set_property(SOURCE rife.i PROPERTY CPLUSPLUS ON DEPENDS generate-spirv) +swig_add_library(rife_ncnn_vulkan_wrapper LANGUAGE python SOURCES rife.i rife.cpp warp.cpp RIFEWrapper.cpp) +add_dependencies(rife_ncnn_vulkan_wrapper generate-spirv) +target_compile_options(rife_ncnn_vulkan_wrapper PUBLIC -fexceptions) +target_link_libraries(rife_ncnn_vulkan_wrapper ${RIFE_LINK_LIBRARIES} Python::Module) +# +#target_link_libraries(rife-ncnn-vulkan ${RIFE_LINK_LIBRARIES}) diff --git a/src/RIFEWrapper.cpp b/src/RIFEWrapper.cpp new file mode 100644 index 0000000..bc03ad2 --- /dev/null +++ b/src/RIFEWrapper.cpp @@ -0,0 +1,25 @@ +// +// Created by archiemeng on 23/4/21. +// + +#include "RIFEWrapper.h" + +RIFEWrapper::RIFEWrapper(int gpuid, bool _tta_mode, bool _uhd_mode, int _num_threads, bool _rife_v2) : RIFE(gpuid, _tta_mode, _uhd_mode, _num_threads, _rife_v2) {} + +int RIFEWrapper::load(const StringType &modeldir) { +#if _WIN32 + return RIFE::load(*modeldir.wstr); +#else + return RIFE::load(*modeldir.str); +#endif +} + +int RIFEWrapper::process(const Image &inimage0, const Image &inimage1, float timestep, Image outimage) { + int c = inimage0.elempack; + ncnn::Mat inimagemat0 = ncnn::Mat(inimage0.w, inimage0.h, (void*) inimage0.data, (size_t) c, c); + ncnn::Mat inimagemat1 = ncnn::Mat(inimage1.w, inimage1.h, (void*) inimage1.data, (size_t) c, c); + ncnn::Mat outimagemat = ncnn::Mat(outimage.w, outimage.h, (void*) outimage.data, (size_t) c, c); + return RIFE::process(inimagemat0, inimagemat1, timestep, outimagemat); +} + +int get_gpu_count() { return ncnn::get_gpu_count(); } \ No newline at end of file diff --git a/src/RIFEWrapper.h b/src/RIFEWrapper.h new file mode 100644 index 0000000..027bd29 --- /dev/null +++ b/src/RIFEWrapper.h @@ -0,0 +1,38 @@ +// +// Created by archiemeng on 23/4/21. +// + +#ifndef RIFE_NCNN_VULKAN_RIFEWRAPPER_H +#define RIFE_NCNN_VULKAN_RIFEWRAPPER_H + +#include "rife.h" + +// wrapper class of ncnn::Mat +typedef struct Image{ + unsigned char *data; + int w; + int h; + int elempack; + Image(unsigned char *d, int w, int h, int channels) { + this->data = d; + this->w = w; + this->h = h; + this->elempack = channels; + } + +} Image; + +union StringType { + std::string *str; + std::wstring *wstr; +}; + +class RIFEWrapper : public RIFE { +public: + RIFEWrapper(int gpuid, bool _tta_mode, bool _uhd_mode, int _num_threads, bool _rife_v2); + int load(const StringType &modeldir); + int process(const Image &inimage0, const Image &inimage1, float timestamp, Image outimage); +}; + +int get_gpu_count(); +#endif //RIFE_NCNN_VULKAN_RIFEWRAPPER_H diff --git a/src/rife.i b/src/rife.i new file mode 100644 index 0000000..c274c19 --- /dev/null +++ b/src/rife.i @@ -0,0 +1,26 @@ +%module rife_ncnn_vulkan_wrapper + +%include "cpointer.i" +%include "carrays.i" +%include "std_string.i" +%include "std_wstring.i" +%include "stdint.i" +%include "pybuffer.i" + +%pybuffer_mutable_string(unsigned char *d); +%pointer_functions(std::string, str_p); +%pointer_functions(std::wstring, wstr_p); + +%{ +#include "rife.h" +#include "RIFEWrapper.h" +%} + +class RIFE +{ +public: + RIFE(int gpuid, bool tta_mode = false, bool uhd_mode = false, int num_threads = 1, bool rife_v2 = false); + ~RIFE(); +}; + +%include "RIFEWrapper.h" \ No newline at end of file diff --git a/src/rife_ncnn_vulkan.py b/src/rife_ncnn_vulkan.py new file mode 100644 index 0000000..b4c78e9 --- /dev/null +++ b/src/rife_ncnn_vulkan.py @@ -0,0 +1,67 @@ +import sys +from math import floor +from pathlib import Path + +from PIL import Image + +if __package__: + import importlib + + raw = importlib.import_module(f"{__package__}.rife_ncnn_vulkan_wrapper") +else: + import rife_ncnn_vulkan_wrapper as raw + + +class RIFE: + def __init__(self, gpuid: int = -1, model: str = "rife-HD", tta_mode: bool = False, uhd_mode: bool = False, num_threads: int = 1): + rife_v2 = "rife-v2" in model + self.model = model + self._raw_rife = raw.RIFEWrapper(gpuid, tta_mode, uhd_mode, num_threads, rife_v2) + self.load() + + def load(self, model_dir: str = ""): + if not model_dir: + model_dir = Path(self.model) + if not model_dir.is_absolute(): + if ( + not model_dir.is_dir() + ): # try to load it from module path if not exists as directory + dir_path = Path(__file__).parent + model_dir = dir_path.joinpath("models", self.model) + + if model_dir.exists(): + modeldir_str = raw.StringType() + if sys.platform in ("win32", "cygwin"): + modeldir_str.wstr = raw.new_wstr_p() + raw.wstr_p_assign(modeldir_str.wstr, str(model_dir)) + else: + modeldir_str.str = raw.new_str_p() + raw.str_p_assign(modeldir_str.str, str(model_dir)) + + self._raw_rife.load(modeldir_str) + else: + raise FileNotFoundError(f"{model_dir} not found") + + def process(self, im0: Image, im1: Image) -> Image: + in_bytes0, in_bytes1 = bytearray(im0.tobytes()), bytearray(im1.tobytes()) + channels = int(len(in_bytes0) / (im0.width * im0.height)) + out_bytes = bytearray(len(in_bytes0)) + + raw_in_image0 = raw.Image(in_bytes0, im0.width, im0.height, channels) + raw_in_image1 = raw.Image(in_bytes1, im1.width, im1.height, channels) + raw_out_image = raw.Image(out_bytes, im0.width, im0.height, channels) + + self._raw_rife.process(raw_in_image0, raw_in_image1, 0.5, raw_out_image) + + return Image.frombytes(im0.mode, (im0.width, im0.height), bytes(out_bytes)) + + +if __name__ == "__main__": + from time import time + + t = time() + im0, im1 = Image.open("../images/0.png"), Image.open("../images/1.png") + rife = RIFE(0) + im = rife.process(im0, im1) + im.save("../images/out_wrapper.png") + print(f"Elapsed time: {time() - t}s")