├── .gitignore ├── LICENSE ├── README.md ├── regenerate_shader.png ├── screenshot-v1.5-benchmark.png ├── screenshot-v1.5-multiple-images.png ├── screenshot-v1.5-single-image.png ├── waifu2x.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── waifu2x-gui.xcscheme └── waifu2x ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets ├── AppIcon.appiconset │ ├── 1200-1024.png │ ├── 1200-128.png │ ├── 1200-16.png │ ├── 1200-256.png │ ├── 1200-257.png │ ├── 1200-32.png │ ├── 1200-33.png │ ├── 1200-512.png │ ├── 1200-513.png │ ├── 1200-64.png │ └── Contents.json └── Contents.json ├── Base.lproj └── Main.storyboard ├── CMakeLists-waifu2x-ncnn-vulkan.txt ├── DragDropImageView.h ├── DragDropImageView.m ├── DragDropTableView.h ├── DragDropTableView.m ├── GPUInfo.h ├── GPUInfo.mm ├── Info.plist ├── MoltenVK_icd.json ├── ViewController.h ├── ViewController.mm ├── VulkanSDK └── .gitkeep ├── benchmark ├── 1000x1000.png ├── 2000x2000.png ├── 200x200.png ├── 4000x4000.png └── 400x400.png ├── main.m ├── ncnn └── .gitkeep ├── waifu2x-ncnn-vulkan ├── .gitkeep └── models │ └── .gitkeep ├── waifu2x.entitlements ├── waifu2xmac.h └── waifu2xmac.mm /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata 3 | waifu2x/VulkanSDK/* 4 | waifu2x/ncnn/* 5 | waifu2x/waifu2x-ncnn-vulkan/* 6 | build 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Cocoa Oikawa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # waifu2x-ncnn-vulkan-macos 2 | As its long long name suggested. 3 | 4 | ### Acknowledgement 5 | - [waifu2x-ncnn-vulkan](https://github.com/nihui/waifu2x-ncnn-vulkan) 6 | - [ncnn](https://github.com/Tencent/ncnn) 7 | - [Vulkan SDK](https://vulkan.lunarg.com/sdk/home) 8 | 9 | ### Thanks 10 | Thanks to [@shincurry](https://github.com/shincurry) for contributing to the UI of this project. 11 | 12 | ### Usage 13 | 14 | #### Single Mode 15 | 1. Click `Single` on the top tab 16 | 2. Drag and drop the image you intentded to upscale to the left image cell 17 | 3. Adjust the settings at the bottom 18 | 4. Click `2x!` and the generated image will be shown at the right image cell 19 | 5. Drag the image from the right image cell to where you want to save it (the filename will be `waifu2x-output.png`) 20 | 21 | ![screenshot](screenshot-v1.5-single-image.png) 22 | 23 | #### Multiple Mode 24 | 1. Click `Multiple` on the top tab 25 | 2. Drag and drop images or directories to the table. (Only decodable images will be processed) 26 | 3. Adjust the settings at the bottom 27 | 4. Click `2x!` and the generated images will be saved at where them from with an extra `.png` extension. For example, 28 | 29 | Input 30 | 31 | ``` 32 | . 33 | ├── 1 34 | │   ├── IMG_2185.JPG 35 | │   ├── IMG_2211.JPG 36 | │   └── IMG_2212.JPG 37 | ├── 2 38 | │   └── IMG_2208.PNG 39 | └── IMG_2213.JPG 40 | ``` 41 | 42 | Output 43 | ``` 44 | . 45 | . 46 | ├── 1 47 | │   ├── IMG_2185.JPG 48 | │   ├── IMG_2185.JPG.png 49 | │   ├── IMG_2211.JPG 50 | │   ├── IMG_2211.JPG.png 51 | │   ├── IMG_2212.JPG 52 | │   └── IMG_2212.JPG.png 53 | ├── 2 54 | │   ├── IMG_2208.PNG 55 | │   └── IMG_2208.PNG.png 56 | ├── IMG_2213.JPG 57 | └── IMG_2213.JPG.png 58 | ``` 59 | 60 | ![screenshot](screenshot-v1.5-multiple-images.png) 61 | 62 | #### Benchmark 63 | 64 | To run benchmark, please click `waifu2x-gui` -> `Benchmark` 65 | 66 | ![screenshot](screenshot-v1.5-benchmark.png) 67 | 68 | ### Build Instructions 69 | Download lastest Vulkan SDK at [https://vulkan.lunarg.com/sdk/home](https://vulkan.lunarg.com/sdk/home). 70 | 71 | At the time of this README.md wrote, 1.2.131.2 was the newest version for macOS. 72 | 73 | ```bash 74 | brew install protobuf 75 | 76 | # clone this repo first 77 | git clone --depth=1 https://github.com/BlueCocoa/waifu2x-ncnn-vulkan-macos 78 | 79 | # download lastest Vulkan SDK 80 | export VULKAN_SDK_VER="1.2.131.2" 81 | wget https://sdk.lunarg.com/sdk/download/${VULKAN_SDK_VER}/mac/vulkansdk-macos-${VULKAN_SDK_VER}.tar.gz?Human=true -O vulkansdk-macos-${VULKAN_SDK_VER}.tar.gz 82 | tar xf vulkansdk-macos-${VULKAN_SDK_VER}.tar.gz 83 | rm -rf waifu2x-ncnn-vulkan-macos/waifu2x/VulkanSDK 84 | mv vulkansdk-macos-${VULKAN_SDK_VER} waifu2x-ncnn-vulkan-macos/waifu2x/VulkanSDK 85 | 86 | # clone Tencent/ncnn 87 | git clone --depth=1 https://github.com/Tencent/ncnn ncnn 88 | 89 | # clone nihui/waifu2x-ncnn-vulkan 90 | # (At the time of writing) https://github.com/nihui/waifu2x-ncnn-vulkan/tree/4b626f8d4a1f8ce331aa4678d93d3628d9670361 91 | rm -rf waifu2x-ncnn-vulkan-macos/waifu2x/waifu2x-ncnn-vulkan 92 | git clone --depth=1 https://github.com/nihui/waifu2x-ncnn-vulkan waifu2x-ncnn-vulkan-macos/waifu2x/waifu2x-ncnn-vulkan 93 | 94 | # check your cmake installation 95 | which cmake 96 | # if it goes with /Applications/CMake.app/Contents/bin/cmake 97 | # then you need to install it in /usr/local/bin via follow command 98 | sudo "/Applications/CMake.app/Contents/bin/cmake-gui" --install 99 | 100 | # build ncnn 101 | rm -rf ncnn/build && mkdir -p ncnn/build && pushd ncnn/build 102 | cmake -DNCNN_VULKAN=ON -D CMAKE_BUILD_TYPE=Release .. 103 | make -j`sysctl -n hw.ncpu` && make install 104 | cp -rf install/* ../../waifu2x-ncnn-vulkan-macos/waifu2x/ncnn 105 | 106 | # compile waifu2x-ncnn-vulkan-macos 107 | # and the compiled application will be placed at `build/Release/waifu2x-gui.app` 108 | cd waifu2x-ncnn-vulkan-macos 109 | xcodebuild 110 | ``` 111 | 112 | ### Notice 113 | After the first compilation, if you want to modify this project only, you may set those flags in `Build Phases -> Run Script` to `false` to avoid recompile ncnn and regenerate shader. 114 | 115 | ![regenerate_shader](regenerate_shader.png) 116 | 117 | ## Speed Comparison between Macs 118 | 119 | ### Environment 1 120 | 121 | - MacBook Pro 15-inch 2018 122 | - macOS 10.14.6 (18G103) 123 | - Intel Core i9 8950HK 124 | - AMD Radeon Pro Vega 20 125 | 126 | |Model|Image Size|Target Size|Block Size|Total Time(sec)|GPU Memory(MB)| 127 | |---|---|---|---|---|---| 128 | |models-cunet|200x200|400x400|400/200/100|0.47/0.43/0.49|613/613/172| 129 | |models-cunet|400x400|800x800|400/200/100|0.97/0.88/0.95|2407/614/173| 130 | |models-cunet|1000x1000|2000x2000|400/200/100|3.56/3.61/4.18|2415/617/175| 131 | |models-cunet|2000x2000|4000x4000|400/200/100|12.72/13.22/15.49|2420/669/193| 132 | |models-cunet|4000x4000|8000x8000|400/200/100|49.79/51.51/60.60|2452/645/197| 133 | |models-upconv_7_anime_style_art_rgb|200x200|400x400|400/200/100|0.26/0.24/0.20|460/460/119| 134 | |models-upconv_7_anime_style_art_rgb|400x400|800x800|400/200/100|0.47/0.40/0.40|1741/460/120| 135 | |models-upconv_7_anime_style_art_rgb|1000x1000|2000x2000|400/200/100|1.67/1.64/1.73|1765/463/121| 136 | |models-upconv_7_anime_style_art_rgb|2000x2000|4000x4000|400/200/100|6.12/6.11/6.49|1769/466/122| 137 | |models-upconv_7_anime_style_art_rgb|4000x4000|8000x8000|400/200/100|23.75/23.71/25.27|1801/489/142| 138 | 139 | noise: 2, scale: 2, gpuid: 0, tta mode: NO 140 | 141 | ### Environment 2 142 | 143 | - MacBook Pro 15-inch 2018 144 | - macOS 10.14.6 (18G84) 145 | - Intel Core i9 8850HK 146 | - AMD Radeon 560X 147 | 148 | |Model|Image Size|Target Size|Block Size|Total Time(sec)|GPU Memory(MB)| 149 | |---|---|---|---|---|---| 150 | |models-cunet|200x200|400x400|400/200/100|2.00/0.53/0.56|613/613/172| 151 | |models-cunet|400x400|800x800|400/200/100|1.29/1.18/1.26|2407/614/173| 152 | |models-cunet|1000x1000|2000x2000|400/200/100|5.20/5.17/5.85|2415/617/175| 153 | |models-cunet|2000x2000|4000x4000|400/200/100|19.07/19.35/22.25|2420/669/193| 154 | |models-cunet|4000x4000|8000x8000|400/200/100|74.49/76.73/88.12|2452/644/197| 155 | |models-upconv_7_anime_style_art_rgb|200x200|400x400|400/200/100|0.31/0.27/0.27|460/460/119| 156 | |models-upconv_7_anime_style_art_rgb|400x400|800x800|400/200/100|0.65/0.54/0.55|1741/460/119| 157 | |models-upconv_7_anime_style_art_rgb|1000x1000|2000x2000|400/200/100|2.41/2.34/2.48|1765/463/121| 158 | |models-upconv_7_anime_style_art_rgb|2000x2000|4000x4000|400/200/100|8.74/8.84/9.43|1769/466/122| 159 | |models-upconv_7_anime_style_art_rgb|4000x4000|8000x8000|400/200/100|32.66/33.00/35.29|1801/489/142| 160 | 161 | noise: 2, scale: 2, gpuid: 0, tta mode: NO 162 | 163 | ### Environment 3 164 | 165 | - MacBook Pro 15-inch 2018 166 | - macOS 10.14.6 (18G103) 167 | - Intel Core i9 8950HK 168 | - Intel UHD Graphics 630 169 | 170 | |Model|Image Size|Target Size|Block Size|Total Time(sec)|GPU Memory(MB)| 171 | |---|---|---|---|---|---| 172 | |models-cunet|200x200|400x400|400/200/100|0.95/0.99/0.87|616/616/176| 173 | |models-cunet|400x400|800x800|400/200/100|2.53/2.27/2.48|2408/616/176| 174 | |models-cunet|1000x1000|2000x2000|400/200/100|12.40/12.00/13.31|2408/616/176| 175 | |models-cunet|2000x2000|4000x4000|400/200/100|44.50/46.81/52.13|2408/669/196| 176 | |models-cunet|4000x4000|8000x8000|400/200/100|175.64/185.56/222.58|2431/637/196| 177 | |models-upconv_7_anime_style_art_rgb|200x200|400x400|400/200/100|1.07/1.27/0.83|466/466/125| 178 | |models-upconv_7_anime_style_art_rgb|400x400|800x800|400/200/100|2.30/1.09/1.11|1746/466/125| 179 | |models-upconv_7_anime_style_art_rgb|1000x1000|2000x2000|400/200/100|6.30/5.70/5.92|1762/466/125| 180 | |models-upconv_7_anime_style_art_rgb|2000x2000|4000x4000|400/200/100|22.12/22.48/23.71|1762/466/125| 181 | |models-upconv_7_anime_style_art_rgb|4000x4000|8000x8000|400/200/100|87.28/89.11/93.98|1780/482/141| 182 | 183 | noise: 2, scale: 2, gpuid: 1, tta mode: NO 184 | 185 | ### Environment 4 186 | 187 | - MacBook 12-inch Early 2016 188 | - macOS 10.14.6 (18G84) 189 | - Intel Core m7 6Y75 190 | - Intel HD Graphics 515 191 | 192 | |Model|Image Size|Target Size|Block Size|Total Time(sec)|GPU Memory(MB)| 193 | |---|---|---|---|---|---| 194 | |models-cunet|200x200|400x400|400/200/100|1.12/1.41/1.23|616/616/176| 195 | |models-cunet|400x400|800x800|400/200/100|3.06/2.90/3.34|2408/616/176| 196 | |models-cunet|1000x1000|2000x2000|400/200/100|18.29/17.81/19.89|2408/616/176| 197 | |models-cunet|2000x2000|4000x4000|400/200/100|66.55/71.79/85.83|2408/665/196| 198 | |models-cunet|4000x4000|8000x8000|400/200/100|288.38/337.44/385.85|2431/637/196| 199 | |models-upconv_7_anime_style_art_rgb|200x200|400x400|400/200/100|0.63/0.69/0.53|466/466/125| 200 | |models-upconv_7_anime_style_art_rgb|400x400|800x800|400/200/100|1.62/1.43/1.47|1746/466/125| 201 | |models-upconv_7_anime_style_art_rgb|1000x1000|2000x2000|400/200/100|9.19/9.06/9.46|1762/466/125| 202 | |models-upconv_7_anime_style_art_rgb|2000x2000|4000x4000|400/200/100|35.52/37.66/41.57|1762/466/125| 203 | |models-upconv_7_anime_style_art_rgb|4000x4000|8000x8000|400/200/100|199.20/182.04/159.11|1780/482/141| 204 | 205 | noise: 2, scale: 2, gpuid: 0, tta mode: NO 206 | 207 | ## Speed Comparison (not really) with waifu2x-caffe-cui & waifu2x-ncnn-vulkan 208 | 209 | ### Environment (waifu2x-caffe-cui & waifu2x-ncnn-vulkan) 210 | 211 | - Windows 10 1809 212 | - AMD R7-1700 213 | - Nvidia GTX-1070 214 | - Nvidia driver 419.67 215 | - CUDA 10.1.105 216 | - cuDNN 10.1 217 | 218 | ### Environment (waifu2x-ncnn-vulkan-macos) 219 | 220 | - macOS 10.14.6 (18G103) 221 | - Intel Core i9 8950HK 222 | - AMD Radeon Pro Vega 20 223 | 224 | ### cunet 225 | 226 | ||Image Size|Target Size|Block Size|Total Time(s)|GPU Memory(MB)| 227 | |---|---|---|---|---|---| 228 | |waifu2x-ncnn-vulkan-macOS|200x200|400x400|400/200/100|0.46/0.44/0.43|621/621/180| 229 | |waifu2x-ncnn-vulkan|200x200|400x400|400/200/100|0.86/0.86/0.82|638/638/197| 230 | |waifu2x-caffe-cui|200x200|400x400|400/200/100|2.54/2.39/2.36|3017/936/843| 231 | |waifu2x-ncnn-vulkan-macOS|400x400|800x800|400/200/100|0.91/0.84/0.92|2415/621/180| 232 | |waifu2x-ncnn-vulkan|400x400|800x800|400/200/100|1.17/1.04/1.02|2430/638/197| 233 | |waifu2x-caffe-cui|400x400|800x800|400/200/100|2.91/2.43/2.7|3202/1389/1178| 234 | |waifu2x-ncnn-vulkan-macOS|1000x1000|2000x2000|400/200/100|3.54/3.58/4.18|2422/624/182| 235 | |waifu2x-ncnn-vulkan|1000x1000|2000x2000|400/200/100|2.35/2.26/2.46|2430/638/197| 236 | |waifu2x-caffe-cui|1000x1000|2000x2000|400/200/100|4.04/3.79/4.35|3258/1582/1175| 237 | |waifu2x-ncnn-vulkan-macOS|2000x2000|4000x4000|400/200/100|12.83/13.25/15.44|2426/676/200| 238 | |waifu2x-ncnn-vulkan|2000x2000|4000x4000|400/200/100|6.46/6.59/7.49|2430/686/213| 239 | |waifu2x-caffe-cui|2000x2000|4000x4000|400/200/100|7.01/7.54/10.11|3258/1499/1200| 240 | |waifu2x-ncnn-vulkan-macOS|4000x4000|8000x8000|400/200/100|49.56/51.44/60.56|2459/651/203| 241 | |waifu2x-ncnn-vulkan|4000x4000|8000x8000|400/200/100|22.78/23.78/27.61|2448/654/213| 242 | |waifu2x-caffe-cui|4000x4000|8000x8000|400/200/100|18.45/21.85/31.82|3325/1652/1236| 243 | 244 | ### upconv_7_anime_style_art_rgb 245 | 246 | ||Image Size|Target Size|Block Size|Total Time(s)|GPU Memory(MB)| 247 | |---|---|---|---|---|---| 248 | |waifu2x-ncnn-vulkan-macOS|200x200|400x400|400/200/100|0.23/0.20/0.22|465/465/125| 249 | |waifu2x-ncnn-vulkan|200x200|400x400|400/200/100|0.74/0.75/0.72|482/482/142| 250 | |waifu2x-caffe-cui|200x200|400x400|400/200/100|2.04/1.99/1.99|995/546/459| 251 | |waifu2x-ncnn-vulkan-macOS|400x400|800x800|400/200/100|0.49/0.42/0.41|1747/466/125| 252 | |waifu2x-ncnn-vulkan|400x400|800x800|400/200/100|0.95/0.83/0.81|1762/482/142| 253 | |waifu2x-caffe-cui|400x400|800x800|400/200/100|2.08/2.12/2.11|995/546/459| 254 | |waifu2x-ncnn-vulkan-macOS|1000x1000|2000x2000|400/200/100|1.67/1.60/1.68|1770/468/127| 255 | |waifu2x-ncnn-vulkan|1000x1000|2000x2000|400/200/100|1.52/1.41/1.44|1778/482/142| 256 | |waifu2x-caffe-cui|1000x1000|2000x2000|400/200/100|2.72/2.60/2.68|1015/570/459| 257 | |waifu2x-ncnn-vulkan-macOS|2000x2000|4000x4000|400/200/100|6.11/5.89/6.18|1774/472/128| 258 | |waifu2x-ncnn-vulkan|2000x2000|4000x4000|400/200/100|3.45/3.42/3.63|1778/482/142| 259 | |waifu2x-caffe-cui|2000x2000|4000x4000|400/200/100|3.90/4.01/4.35|1015/521/462| 260 | |waifu2x-ncnn-vulkan-macOS|4000x4000|8000x8000|400/200/100|22.92/22.70/24.16|1806/495/147| 261 | |waifu2x-ncnn-vulkan|4000x4000|8000x8000|400/200/100|11.16/11.29/12.07|1796/498/158| 262 | |waifu2x-caffe-cui|4000x4000|8000x8000|400/200/100|9.24/9.81/11.16|995/546/436| 263 | 264 | -------------------------------------------------------------------------------- /regenerate_shader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/regenerate_shader.png -------------------------------------------------------------------------------- /screenshot-v1.5-benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/screenshot-v1.5-benchmark.png -------------------------------------------------------------------------------- /screenshot-v1.5-multiple-images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/screenshot-v1.5-multiple-images.png -------------------------------------------------------------------------------- /screenshot-v1.5-single-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/screenshot-v1.5-single-image.png -------------------------------------------------------------------------------- /waifu2x.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 400697F22270C19400B79110 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 400697F12270C19400B79110 /* AppDelegate.m */; }; 11 | 400697F52270C19400B79110 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 400697F42270C19400B79110 /* ViewController.mm */; }; 12 | 400697F72270C19600B79110 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 400697F62270C19600B79110 /* Assets.xcassets */; }; 13 | 400697FA2270C19600B79110 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 400697F82270C19600B79110 /* Main.storyboard */; }; 14 | 400697FD2270C19600B79110 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 400697FC2270C19600B79110 /* main.m */; }; 15 | 4006992F2270CA5300B79110 /* vulkan.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4006992E2270CA5300B79110 /* vulkan.framework */; }; 16 | 400699302270CA8000B79110 /* vulkan.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4006992E2270CA5300B79110 /* vulkan.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 4006997B2270D21A00B79110 /* waifu2xmac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4006997A2270D21A00B79110 /* waifu2xmac.mm */; }; 18 | 402AD32D22711C9800F0A985 /* MoltenVK_icd.json in Resources */ = {isa = PBXBuildFile; fileRef = 402AD32C22711C9700F0A985 /* MoltenVK_icd.json */; }; 19 | 408F05EC227113F700189EE2 /* libMoltenVK.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 40F8881D2270D63600261851 /* libMoltenVK.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 20 | 40F888262270F66E00261851 /* DragDropImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40F888252270F66E00261851 /* DragDropImageView.m */; }; 21 | CC70F70223FE547C00C9DAE6 /* GPUInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC70F70123FE547C00C9DAE6 /* GPUInfo.mm */; }; 22 | CC70F70523FE7D5D00C9DAE6 /* DragDropTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = CC70F70423FE7D5D00C9DAE6 /* DragDropTableView.m */; }; 23 | CC70F70723FEC03D00C9DAE6 /* benchmark in Resources */ = {isa = PBXBuildFile; fileRef = CC70F70623FEC03D00C9DAE6 /* benchmark */; }; 24 | CCE86B1123FD615300E73B94 /* libncnn.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CCE86B0D23FD615300E73B94 /* libncnn.a */; }; 25 | CCE86B8423FD630600E73B94 /* waifu2x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CCE86B5223FD630500E73B94 /* waifu2x.cpp */; }; 26 | CCE86B8723FD631D00E73B94 /* models in Resources */ = {isa = PBXBuildFile; fileRef = CCE86B8623FD631D00E73B94 /* models */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXCopyFilesBuildPhase section */ 30 | 400698062270C22A00B79110 /* CopyFiles */ = { 31 | isa = PBXCopyFilesBuildPhase; 32 | buildActionMask = 12; 33 | dstPath = ""; 34 | dstSubfolderSpec = 10; 35 | files = ( 36 | 408F05EC227113F700189EE2 /* libMoltenVK.dylib in CopyFiles */, 37 | 400699302270CA8000B79110 /* vulkan.framework in CopyFiles */, 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXCopyFilesBuildPhase section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 400697ED2270C19400B79110 /* waifu2x-gui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "waifu2x-gui.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 400697F02270C19400B79110 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 46 | 400697F12270C19400B79110 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 47 | 400697F32270C19400B79110 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 48 | 400697F42270C19400B79110 /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; 49 | 400697F62270C19600B79110 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 50 | 400697F92270C19600B79110 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 51 | 400697FB2270C19600B79110 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 400697FC2270C19600B79110 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 53 | 400697FE2270C19600B79110 /* waifu2x.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = waifu2x.entitlements; sourceTree = ""; }; 54 | 4006992E2270CA5300B79110 /* vulkan.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = vulkan.framework; path = macOS/Frameworks/vulkan.framework; sourceTree = ""; }; 55 | 400699792270D21A00B79110 /* waifu2xmac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = waifu2xmac.h; sourceTree = ""; }; 56 | 4006997A2270D21A00B79110 /* waifu2xmac.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = waifu2xmac.mm; sourceTree = ""; }; 57 | 402AD32C22711C9700F0A985 /* MoltenVK_icd.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = MoltenVK_icd.json; path = waifu2x/MoltenVK_icd.json; sourceTree = SOURCE_ROOT; }; 58 | 40F8881D2270D63600261851 /* libMoltenVK.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libMoltenVK.dylib; path = MoltenVK/macOS/dynamic/libMoltenVK.dylib; sourceTree = ""; }; 59 | 40F888242270F66E00261851 /* DragDropImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DragDropImageView.h; sourceTree = ""; }; 60 | 40F888252270F66E00261851 /* DragDropImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DragDropImageView.m; sourceTree = ""; }; 61 | CC70F70023FE547C00C9DAE6 /* GPUInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPUInfo.h; sourceTree = ""; }; 62 | CC70F70123FE547C00C9DAE6 /* GPUInfo.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GPUInfo.mm; sourceTree = ""; }; 63 | CC70F70323FE7D5D00C9DAE6 /* DragDropTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DragDropTableView.h; sourceTree = ""; }; 64 | CC70F70423FE7D5D00C9DAE6 /* DragDropTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DragDropTableView.m; sourceTree = ""; }; 65 | CC70F70623FEC03D00C9DAE6 /* benchmark */ = {isa = PBXFileReference; lastKnownFileType = folder; path = benchmark; sourceTree = ""; }; 66 | CCE86B0A23FD615300E73B94 /* ncnnConfig.cmake */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ncnnConfig.cmake; sourceTree = ""; }; 67 | CCE86B0B23FD615300E73B94 /* ncnn.cmake */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ncnn.cmake; sourceTree = ""; }; 68 | CCE86B0C23FD615300E73B94 /* ncnn-release.cmake */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "ncnn-release.cmake"; sourceTree = ""; }; 69 | CCE86B0D23FD615300E73B94 /* libncnn.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libncnn.a; sourceTree = ""; }; 70 | CCE86B4B23FD630500E73B94 /* stb_image_write.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stb_image_write.h; sourceTree = ""; }; 71 | CCE86B4C23FD630500E73B94 /* win32dirent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = win32dirent.h; sourceTree = ""; }; 72 | CCE86B4D23FD630500E73B94 /* stb_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stb_image.h; sourceTree = ""; }; 73 | CCE86B4E23FD630500E73B94 /* wic_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wic_image.h; sourceTree = ""; }; 74 | CCE86B4F23FD630500E73B94 /* filesystem_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filesystem_utils.h; sourceTree = ""; }; 75 | CCE86B5123FD630500E73B94 /* waifu2x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = waifu2x.h; sourceTree = ""; }; 76 | CCE86B5223FD630500E73B94 /* waifu2x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = waifu2x.cpp; sourceTree = ""; }; 77 | CCE86B8623FD631D00E73B94 /* models */ = {isa = PBXFileReference; lastKnownFileType = folder; path = models; sourceTree = ""; }; 78 | /* End PBXFileReference section */ 79 | 80 | /* Begin PBXFrameworksBuildPhase section */ 81 | 400697EA2270C19400B79110 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | 4006992F2270CA5300B79110 /* vulkan.framework in Frameworks */, 86 | CCE86B1123FD615300E73B94 /* libncnn.a in Frameworks */, 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | /* End PBXFrameworksBuildPhase section */ 91 | 92 | /* Begin PBXGroup section */ 93 | 400697E42270C19400B79110 = { 94 | isa = PBXGroup; 95 | children = ( 96 | 400697EF2270C19400B79110 /* waifu2x */, 97 | 400697EE2270C19400B79110 /* Products */, 98 | 40F468A32271EAAA001098D8 /* Frameworks */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 400697EE2270C19400B79110 /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 400697ED2270C19400B79110 /* waifu2x-gui.app */, 106 | ); 107 | name = Products; 108 | sourceTree = ""; 109 | }; 110 | 400697EF2270C19400B79110 /* waifu2x */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 400699792270D21A00B79110 /* waifu2xmac.h */, 114 | 4006997A2270D21A00B79110 /* waifu2xmac.mm */, 115 | 40F888242270F66E00261851 /* DragDropImageView.h */, 116 | 40F888252270F66E00261851 /* DragDropImageView.m */, 117 | CC70F70323FE7D5D00C9DAE6 /* DragDropTableView.h */, 118 | CC70F70423FE7D5D00C9DAE6 /* DragDropTableView.m */, 119 | 400697F02270C19400B79110 /* AppDelegate.h */, 120 | 400697F12270C19400B79110 /* AppDelegate.m */, 121 | 400697F32270C19400B79110 /* ViewController.h */, 122 | 400697F42270C19400B79110 /* ViewController.mm */, 123 | CC70F70023FE547C00C9DAE6 /* GPUInfo.h */, 124 | CC70F70123FE547C00C9DAE6 /* GPUInfo.mm */, 125 | 400697F62270C19600B79110 /* Assets.xcassets */, 126 | 400697F82270C19600B79110 /* Main.storyboard */, 127 | 400697FB2270C19600B79110 /* Info.plist */, 128 | 400697FC2270C19600B79110 /* main.m */, 129 | CC70F70623FEC03D00C9DAE6 /* benchmark */, 130 | 400697FE2270C19600B79110 /* waifu2x.entitlements */, 131 | CCE86B1423FD630500E73B94 /* waifu2x-ncnn-vulkan */, 132 | CCE86B0423FD60C700E73B94 /* ncnn */, 133 | 400698082270C28B00B79110 /* VulkanSDK */, 134 | ); 135 | path = waifu2x; 136 | sourceTree = ""; 137 | }; 138 | 400698082270C28B00B79110 /* VulkanSDK */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 40F8881D2270D63600261851 /* libMoltenVK.dylib */, 142 | 402AD32C22711C9700F0A985 /* MoltenVK_icd.json */, 143 | 4006992E2270CA5300B79110 /* vulkan.framework */, 144 | ); 145 | path = VulkanSDK; 146 | sourceTree = ""; 147 | }; 148 | 40F468A32271EAAA001098D8 /* Frameworks */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | ); 152 | name = Frameworks; 153 | sourceTree = ""; 154 | }; 155 | CCE86B0423FD60C700E73B94 /* ncnn */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | CCE86B1223FD616600E73B94 /* include */, 159 | CCE86B0723FD615300E73B94 /* lib */, 160 | ); 161 | path = ncnn; 162 | sourceTree = ""; 163 | }; 164 | CCE86B0723FD615300E73B94 /* lib */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | CCE86B0823FD615300E73B94 /* cmake */, 168 | CCE86B0D23FD615300E73B94 /* libncnn.a */, 169 | ); 170 | path = lib; 171 | sourceTree = ""; 172 | }; 173 | CCE86B0823FD615300E73B94 /* cmake */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | CCE86B0923FD615300E73B94 /* ncnn */, 177 | ); 178 | path = cmake; 179 | sourceTree = ""; 180 | }; 181 | CCE86B0923FD615300E73B94 /* ncnn */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | CCE86B0A23FD615300E73B94 /* ncnnConfig.cmake */, 185 | CCE86B0B23FD615300E73B94 /* ncnn.cmake */, 186 | CCE86B0C23FD615300E73B94 /* ncnn-release.cmake */, 187 | ); 188 | path = ncnn; 189 | sourceTree = ""; 190 | }; 191 | CCE86B1223FD616600E73B94 /* include */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | ); 195 | path = include; 196 | sourceTree = ""; 197 | }; 198 | CCE86B1423FD630500E73B94 /* waifu2x-ncnn-vulkan */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | CCE86B8623FD631D00E73B94 /* models */, 202 | CCE86B4823FD630500E73B94 /* src */, 203 | ); 204 | path = "waifu2x-ncnn-vulkan"; 205 | sourceTree = ""; 206 | }; 207 | CCE86B4823FD630500E73B94 /* src */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | CCE86B4B23FD630500E73B94 /* stb_image_write.h */, 211 | CCE86B4C23FD630500E73B94 /* win32dirent.h */, 212 | CCE86B4D23FD630500E73B94 /* stb_image.h */, 213 | CCE86B4E23FD630500E73B94 /* wic_image.h */, 214 | CCE86B4F23FD630500E73B94 /* filesystem_utils.h */, 215 | CCE86B5123FD630500E73B94 /* waifu2x.h */, 216 | CCE86B5223FD630500E73B94 /* waifu2x.cpp */, 217 | ); 218 | path = src; 219 | sourceTree = ""; 220 | }; 221 | /* End PBXGroup section */ 222 | 223 | /* Begin PBXNativeTarget section */ 224 | 400697EC2270C19400B79110 /* waifu2x-gui */ = { 225 | isa = PBXNativeTarget; 226 | buildConfigurationList = 400698012270C19600B79110 /* Build configuration list for PBXNativeTarget "waifu2x-gui" */; 227 | buildPhases = ( 228 | 400699322270CC7500B79110 /* ShellScript */, 229 | 400697E92270C19400B79110 /* Sources */, 230 | 400697EA2270C19400B79110 /* Frameworks */, 231 | 400697EB2270C19400B79110 /* Resources */, 232 | 400698062270C22A00B79110 /* CopyFiles */, 233 | ); 234 | buildRules = ( 235 | ); 236 | dependencies = ( 237 | ); 238 | name = "waifu2x-gui"; 239 | productName = waifu2x; 240 | productReference = 400697ED2270C19400B79110 /* waifu2x-gui.app */; 241 | productType = "com.apple.product-type.application"; 242 | }; 243 | /* End PBXNativeTarget section */ 244 | 245 | /* Begin PBXProject section */ 246 | 400697E52270C19400B79110 /* Project object */ = { 247 | isa = PBXProject; 248 | attributes = { 249 | LastUpgradeCheck = 1020; 250 | ORGANIZATIONNAME = "Cocoa Oikawa"; 251 | TargetAttributes = { 252 | 400697EC2270C19400B79110 = { 253 | CreatedOnToolsVersion = 10.1; 254 | SystemCapabilities = { 255 | com.apple.Sandbox = { 256 | enabled = 0; 257 | }; 258 | }; 259 | }; 260 | }; 261 | }; 262 | buildConfigurationList = 400697E82270C19400B79110 /* Build configuration list for PBXProject "waifu2x" */; 263 | compatibilityVersion = "Xcode 9.3"; 264 | developmentRegion = en; 265 | hasScannedForEncodings = 0; 266 | knownRegions = ( 267 | en, 268 | Base, 269 | ); 270 | mainGroup = 400697E42270C19400B79110; 271 | productRefGroup = 400697EE2270C19400B79110 /* Products */; 272 | projectDirPath = ""; 273 | projectRoot = ""; 274 | targets = ( 275 | 400697EC2270C19400B79110 /* waifu2x-gui */, 276 | ); 277 | }; 278 | /* End PBXProject section */ 279 | 280 | /* Begin PBXResourcesBuildPhase section */ 281 | 400697EB2270C19400B79110 /* Resources */ = { 282 | isa = PBXResourcesBuildPhase; 283 | buildActionMask = 2147483647; 284 | files = ( 285 | CCE86B8723FD631D00E73B94 /* models in Resources */, 286 | 402AD32D22711C9800F0A985 /* MoltenVK_icd.json in Resources */, 287 | 400697F72270C19600B79110 /* Assets.xcassets in Resources */, 288 | 400697FA2270C19600B79110 /* Main.storyboard in Resources */, 289 | CC70F70723FEC03D00C9DAE6 /* benchmark in Resources */, 290 | ); 291 | runOnlyForDeploymentPostprocessing = 0; 292 | }; 293 | /* End PBXResourcesBuildPhase section */ 294 | 295 | /* Begin PBXShellScriptBuildPhase section */ 296 | 400699322270CC7500B79110 /* ShellScript */ = { 297 | isa = PBXShellScriptBuildPhase; 298 | buildActionMask = 2147483647; 299 | files = ( 300 | ); 301 | inputFileListPaths = ( 302 | ); 303 | inputPaths = ( 304 | ); 305 | outputFileListPaths = ( 306 | ); 307 | outputPaths = ( 308 | ); 309 | runOnlyForDeploymentPostprocessing = 0; 310 | shellPath = /bin/sh; 311 | shellScript = "REGENERATE_SHADER=true\nif (${REGENERATE_SHADER}); then\n export VULKAN_SDK=\"${SRCROOT}/waifu2x/VulkanSDK/macOS\"\n export PATH=\"/Applications/CMake.app/Contents/bin:${PATH}\"\n cp -f \"${SRCROOT}/waifu2x/CMakeLists-waifu2x-ncnn-vulkan.txt\" \"${SRCROOT}/waifu2x/waifu2x-ncnn-vulkan/src/CMakeLists.txt\"\n cd ${SRCROOT}/waifu2x/waifu2x-ncnn-vulkan/src\n rm -rf build && mkdir -p build && cd build\n cmake ..\n make -j`sysctl -n hw.ncpu`\n cp -f *.h \"${SRCROOT}/waifu2x/waifu2x-ncnn-vulkan/src\"\nfi\n"; 312 | }; 313 | /* End PBXShellScriptBuildPhase section */ 314 | 315 | /* Begin PBXSourcesBuildPhase section */ 316 | 400697E92270C19400B79110 /* Sources */ = { 317 | isa = PBXSourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | CC70F70223FE547C00C9DAE6 /* GPUInfo.mm in Sources */, 321 | 400697F52270C19400B79110 /* ViewController.mm in Sources */, 322 | 4006997B2270D21A00B79110 /* waifu2xmac.mm in Sources */, 323 | 400697FD2270C19600B79110 /* main.m in Sources */, 324 | CC70F70523FE7D5D00C9DAE6 /* DragDropTableView.m in Sources */, 325 | 400697F22270C19400B79110 /* AppDelegate.m in Sources */, 326 | CCE86B8423FD630600E73B94 /* waifu2x.cpp in Sources */, 327 | 40F888262270F66E00261851 /* DragDropImageView.m in Sources */, 328 | ); 329 | runOnlyForDeploymentPostprocessing = 0; 330 | }; 331 | /* End PBXSourcesBuildPhase section */ 332 | 333 | /* Begin PBXVariantGroup section */ 334 | 400697F82270C19600B79110 /* Main.storyboard */ = { 335 | isa = PBXVariantGroup; 336 | children = ( 337 | 400697F92270C19600B79110 /* Base */, 338 | ); 339 | name = Main.storyboard; 340 | sourceTree = ""; 341 | }; 342 | /* End PBXVariantGroup section */ 343 | 344 | /* Begin XCBuildConfiguration section */ 345 | 400697FF2270C19600B79110 /* Debug */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ALWAYS_SEARCH_USER_PATHS = NO; 349 | CLANG_ANALYZER_NONNULL = YES; 350 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 351 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 352 | CLANG_CXX_LIBRARY = "libc++"; 353 | CLANG_ENABLE_MODULES = YES; 354 | CLANG_ENABLE_OBJC_ARC = YES; 355 | CLANG_ENABLE_OBJC_WEAK = YES; 356 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 357 | CLANG_WARN_BOOL_CONVERSION = YES; 358 | CLANG_WARN_COMMA = YES; 359 | CLANG_WARN_CONSTANT_CONVERSION = YES; 360 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 361 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 362 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 363 | CLANG_WARN_EMPTY_BODY = YES; 364 | CLANG_WARN_ENUM_CONVERSION = YES; 365 | CLANG_WARN_INFINITE_RECURSION = YES; 366 | CLANG_WARN_INT_CONVERSION = YES; 367 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 368 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 369 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 370 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 371 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 372 | CLANG_WARN_STRICT_PROTOTYPES = YES; 373 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 374 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 375 | CLANG_WARN_UNREACHABLE_CODE = YES; 376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 377 | CODE_SIGN_IDENTITY = "Mac Developer"; 378 | COPY_PHASE_STRIP = NO; 379 | DEBUG_INFORMATION_FORMAT = dwarf; 380 | ENABLE_STRICT_OBJC_MSGSEND = YES; 381 | ENABLE_TESTABILITY = YES; 382 | GCC_C_LANGUAGE_STANDARD = gnu11; 383 | GCC_DYNAMIC_NO_PIC = NO; 384 | GCC_NO_COMMON_BLOCKS = YES; 385 | GCC_OPTIMIZATION_LEVEL = 0; 386 | GCC_PREPROCESSOR_DEFINITIONS = ( 387 | "DEBUG=1", 388 | "$(inherited)", 389 | ); 390 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 391 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 392 | GCC_WARN_UNDECLARED_SELECTOR = YES; 393 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 394 | GCC_WARN_UNUSED_FUNCTION = YES; 395 | GCC_WARN_UNUSED_VARIABLE = YES; 396 | MACOSX_DEPLOYMENT_TARGET = 10.14; 397 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 398 | MTL_FAST_MATH = YES; 399 | ONLY_ACTIVE_ARCH = YES; 400 | SDKROOT = macosx; 401 | }; 402 | name = Debug; 403 | }; 404 | 400698002270C19600B79110 /* Release */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | ALWAYS_SEARCH_USER_PATHS = NO; 408 | CLANG_ANALYZER_NONNULL = YES; 409 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 410 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 411 | CLANG_CXX_LIBRARY = "libc++"; 412 | CLANG_ENABLE_MODULES = YES; 413 | CLANG_ENABLE_OBJC_ARC = YES; 414 | CLANG_ENABLE_OBJC_WEAK = YES; 415 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 416 | CLANG_WARN_BOOL_CONVERSION = YES; 417 | CLANG_WARN_COMMA = YES; 418 | CLANG_WARN_CONSTANT_CONVERSION = YES; 419 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 420 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 421 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 422 | CLANG_WARN_EMPTY_BODY = YES; 423 | CLANG_WARN_ENUM_CONVERSION = YES; 424 | CLANG_WARN_INFINITE_RECURSION = YES; 425 | CLANG_WARN_INT_CONVERSION = YES; 426 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 427 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 428 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 429 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 430 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 431 | CLANG_WARN_STRICT_PROTOTYPES = YES; 432 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 433 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 434 | CLANG_WARN_UNREACHABLE_CODE = YES; 435 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 436 | CODE_SIGN_IDENTITY = "Mac Developer"; 437 | COPY_PHASE_STRIP = NO; 438 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 439 | ENABLE_NS_ASSERTIONS = NO; 440 | ENABLE_STRICT_OBJC_MSGSEND = YES; 441 | GCC_C_LANGUAGE_STANDARD = gnu11; 442 | GCC_NO_COMMON_BLOCKS = YES; 443 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 444 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 445 | GCC_WARN_UNDECLARED_SELECTOR = YES; 446 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 447 | GCC_WARN_UNUSED_FUNCTION = YES; 448 | GCC_WARN_UNUSED_VARIABLE = YES; 449 | MACOSX_DEPLOYMENT_TARGET = 10.14; 450 | MTL_ENABLE_DEBUG_INFO = NO; 451 | MTL_FAST_MATH = YES; 452 | SDKROOT = macosx; 453 | }; 454 | name = Release; 455 | }; 456 | 400698022270C19600B79110 /* Debug */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 460 | CODE_SIGN_STYLE = Automatic; 461 | COMBINE_HIDPI_IMAGES = YES; 462 | DEVELOPMENT_TEAM = FT787279D2; 463 | FRAMEWORK_SEARCH_PATHS = ( 464 | "$(inherited)", 465 | "$(PROJECT_DIR)/waifu2x", 466 | "$(PROJECT_DIR)/waifu2x/VulkanSDK/macOS/Frameworks", 467 | "$(PROJECT_DIR)/waifu2x/VulkanSDK/MoltenVK/macOS/framework", 468 | ); 469 | GCC_VERSION = ""; 470 | HEADER_SEARCH_PATHS = ( 471 | /usr/local/Cellar/libomp/9.0.0/include, 472 | "$(SRCROOT)/waifu2x/VulkanSDK/macOS/include", 473 | "$(SRCROOT)/waifu2x/ncnn/include/ncnn", 474 | ); 475 | INFOPLIST_FILE = waifu2x/Info.plist; 476 | LD_RUNPATH_SEARCH_PATHS = ( 477 | "$(inherited)", 478 | "@executable_path/../Frameworks", 479 | ); 480 | LIBRARY_SEARCH_PATHS = ( 481 | /usr/local/Cellar/libomp/9.0.0/lib, 482 | "$(SRCROOT)/waifu2x/VulkanSDK/macOS/lib", 483 | "$(PROJECT_DIR)/waifu2x/VulkanSDK/MoltenVK/macOS/dynamic", 484 | "$(PROJECT_DIR)/waifu2x/ncnn/lib", 485 | ); 486 | MACOSX_DEPLOYMENT_TARGET = 10.10; 487 | MARKETING_VERSION = 1.5; 488 | PRODUCT_BUNDLE_IDENTIFIER = "moe.cocoaneko.waifu2x-gui"; 489 | PRODUCT_NAME = "$(TARGET_NAME)"; 490 | STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; 491 | }; 492 | name = Debug; 493 | }; 494 | 400698032270C19600B79110 /* Release */ = { 495 | isa = XCBuildConfiguration; 496 | buildSettings = { 497 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 498 | CODE_SIGN_STYLE = Automatic; 499 | COMBINE_HIDPI_IMAGES = YES; 500 | DEVELOPMENT_TEAM = FT787279D2; 501 | FRAMEWORK_SEARCH_PATHS = ( 502 | "$(inherited)", 503 | "$(PROJECT_DIR)/waifu2x", 504 | "$(PROJECT_DIR)/waifu2x/VulkanSDK/macOS/Frameworks", 505 | "$(PROJECT_DIR)/waifu2x/VulkanSDK/MoltenVK/macOS/framework", 506 | ); 507 | GCC_VERSION = ""; 508 | HEADER_SEARCH_PATHS = ( 509 | /usr/local/Cellar/libomp/9.0.0/include, 510 | "$(SRCROOT)/waifu2x/VulkanSDK/macOS/include", 511 | "$(SRCROOT)/waifu2x/ncnn/include/ncnn", 512 | ); 513 | INFOPLIST_FILE = waifu2x/Info.plist; 514 | LD_RUNPATH_SEARCH_PATHS = ( 515 | "$(inherited)", 516 | "@executable_path/../Frameworks", 517 | ); 518 | LIBRARY_SEARCH_PATHS = ( 519 | /usr/local/Cellar/libomp/9.0.0/lib, 520 | "$(SRCROOT)/waifu2x/VulkanSDK/macOS/lib", 521 | "$(PROJECT_DIR)/waifu2x/VulkanSDK/MoltenVK/macOS/dynamic", 522 | "$(PROJECT_DIR)/waifu2x/ncnn/lib", 523 | ); 524 | MACOSX_DEPLOYMENT_TARGET = 10.10; 525 | MARKETING_VERSION = 1.5; 526 | PRODUCT_BUNDLE_IDENTIFIER = "moe.cocoaneko.waifu2x-gui"; 527 | PRODUCT_NAME = "$(TARGET_NAME)"; 528 | STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; 529 | }; 530 | name = Release; 531 | }; 532 | /* End XCBuildConfiguration section */ 533 | 534 | /* Begin XCConfigurationList section */ 535 | 400697E82270C19400B79110 /* Build configuration list for PBXProject "waifu2x" */ = { 536 | isa = XCConfigurationList; 537 | buildConfigurations = ( 538 | 400697FF2270C19600B79110 /* Debug */, 539 | 400698002270C19600B79110 /* Release */, 540 | ); 541 | defaultConfigurationIsVisible = 0; 542 | defaultConfigurationName = Release; 543 | }; 544 | 400698012270C19600B79110 /* Build configuration list for PBXNativeTarget "waifu2x-gui" */ = { 545 | isa = XCConfigurationList; 546 | buildConfigurations = ( 547 | 400698022270C19600B79110 /* Debug */, 548 | 400698032270C19600B79110 /* Release */, 549 | ); 550 | defaultConfigurationIsVisible = 0; 551 | defaultConfigurationName = Release; 552 | }; 553 | /* End XCConfigurationList section */ 554 | }; 555 | rootObject = 400697E52270C19400B79110 /* Project object */; 556 | } 557 | -------------------------------------------------------------------------------- /waifu2x.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /waifu2x.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /waifu2x.xcodeproj/xcshareddata/xcschemes/waifu2x-gui.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /waifu2x/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // waifu2x 4 | // 5 | // Created by Cocoa on 2019/4/25. 6 | // Copyright © 2019-2020 Cocoa. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface AppDelegate : NSWindowController 13 | 14 | @property (assign) id viewController; 15 | - (IBAction)benchmark:(id)sender; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /waifu2x/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // waifu2x 4 | // 5 | // Created by Cocoa on 2019/4/25. 6 | // Copyright © 2019-2020 Cocoa. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag { 18 | if (!flag) { 19 | for (id window in sender.windows) { 20 | [window makeKeyAndOrderFront:self]; 21 | } 22 | } 23 | return YES; 24 | } 25 | 26 | - (IBAction)benchmark:(id)sender { 27 | [self.viewController performSelector:@selector(benchmark)]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-1024.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-128.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-16.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-256.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-257.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-257.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-32.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-33.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-512.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-513.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-513.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/1200-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/Assets.xcassets/AppIcon.appiconset/1200-64.png -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "1200-16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "1200-32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "1200-33.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "1200-64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "1200-128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "1200-256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "1200-257.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "1200-512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "1200-513.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "1200-1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /waifu2x/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /waifu2x/CMakeLists-waifu2x-ncnn-vulkan.txt: -------------------------------------------------------------------------------- 1 | project(waifu2x-ncnn-vulkan) 2 | 3 | cmake_minimum_required(VERSION 3.1) 4 | 5 | set(CMAKE_BUILD_TYPE Release) 6 | 7 | find_package(Vulkan REQUIRED) 8 | 9 | find_program(GLSLANGVALIDATOR_EXECUTABLE NAMES glslangValidator PATHS $ENV{VULKAN_SDK}/bin NO_CMAKE_FIND_ROOT_PATH) 10 | message(STATUS "Found glslangValidator: ${GLSLANGVALIDATOR_EXECUTABLE}") 11 | 12 | macro(compile_shader SHADER_SRC) 13 | set(SHADER_SRC_FULLPATH ${CMAKE_CURRENT_SOURCE_DIR}/${SHADER_SRC}) 14 | 15 | get_filename_component(SHADER_SRC_NAME_WE ${SHADER_SRC} NAME_WE) 16 | set(SHADER_SPV_HEX_FILE ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_SRC_NAME_WE}.spv.hex.h) 17 | add_custom_command( 18 | OUTPUT ${SHADER_SPV_HEX_FILE} 19 | COMMAND ${GLSLANGVALIDATOR_EXECUTABLE} 20 | ARGS -V -s -e ${SHADER_SRC_NAME_WE} --source-entrypoint main -x -o ${SHADER_SPV_HEX_FILE} ${SHADER_SRC_FULLPATH} 21 | DEPENDS ${SHADER_SRC_FULLPATH} 22 | COMMENT "Building SPIR-V module ${SHADER_SRC_NAME_WE}.spv" 23 | VERBATIM 24 | ) 25 | set_source_files_properties(${SHADER_SPV_HEX_FILE} PROPERTIES GENERATED TRUE) 26 | list(APPEND SHADER_SPV_HEX_FILES ${SHADER_SPV_HEX_FILE}) 27 | 28 | # fp16 storage 29 | set(SHADER_fp16s_SRC_NAME_WE "${SHADER_SRC_NAME_WE}_fp16s") 30 | 31 | set(SHADER_fp16s_SPV_HEX_FILE ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_fp16s_SRC_NAME_WE}.spv.hex.h) 32 | add_custom_command( 33 | OUTPUT ${SHADER_fp16s_SPV_HEX_FILE} 34 | COMMAND ${GLSLANGVALIDATOR_EXECUTABLE} 35 | ARGS -DNCNN_fp16_storage=1 -V -s -e ${SHADER_fp16s_SRC_NAME_WE} --source-entrypoint main -x -o ${SHADER_fp16s_SPV_HEX_FILE} ${SHADER_SRC_FULLPATH} 36 | DEPENDS ${SHADER_SRC_FULLPATH} 37 | COMMENT "Building SPIR-V module ${SHADER_fp16s_SRC_NAME_WE}.spv" 38 | VERBATIM 39 | ) 40 | set_source_files_properties(${SHADER_fp16s_SPV_HEX_FILE} PROPERTIES GENERATED TRUE) 41 | list(APPEND SHADER_SPV_HEX_FILES ${SHADER_fp16s_SPV_HEX_FILE}) 42 | 43 | # int8 storage 44 | set(SHADER_int8s_SRC_NAME_WE "${SHADER_SRC_NAME_WE}_int8s") 45 | 46 | set(SHADER_int8s_SPV_HEX_FILE ${CMAKE_CURRENT_BINARY_DIR}/${SHADER_int8s_SRC_NAME_WE}.spv.hex.h) 47 | add_custom_command( 48 | OUTPUT ${SHADER_int8s_SPV_HEX_FILE} 49 | COMMAND ${GLSLANGVALIDATOR_EXECUTABLE} 50 | ARGS -DNCNN_fp16_storage=1 -DNCNN_int8_storage=1 -V -s -e ${SHADER_int8s_SRC_NAME_WE} --source-entrypoint main -x -o ${SHADER_int8s_SPV_HEX_FILE} ${SHADER_SRC_FULLPATH} 51 | DEPENDS ${SHADER_SRC_FULLPATH} 52 | COMMENT "Building SPIR-V module ${SHADER_int8s_SRC_NAME_WE}.spv" 53 | VERBATIM 54 | ) 55 | set_source_files_properties(${SHADER_int8s_SPV_HEX_FILE} PROPERTIES GENERATED TRUE) 56 | list(APPEND SHADER_SPV_HEX_FILES ${SHADER_int8s_SPV_HEX_FILE}) 57 | endmacro() 58 | 59 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 60 | 61 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 62 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 63 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 64 | 65 | set(ncnn_DIR "${CMAKE_SOURCE_DIR}/../../ncnn/lib/cmake/ncnn") 66 | find_package(ncnn REQUIRED) 67 | 68 | # look for vulkan compute shader and compile 69 | set(SHADER_SPV_HEX_FILES) 70 | 71 | compile_shader(waifu2x_preproc.comp) 72 | compile_shader(waifu2x_postproc.comp) 73 | compile_shader(waifu2x_preproc_tta.comp) 74 | compile_shader(waifu2x_postproc_tta.comp) 75 | 76 | add_custom_target(generate-spirv DEPENDS ${SHADER_SPV_HEX_FILES}) 77 | 78 | add_executable(waifu2x-ncnn-vulkan main.cpp waifu2x.cpp) 79 | 80 | add_dependencies(waifu2x-ncnn-vulkan generate-spirv) 81 | 82 | target_link_libraries(waifu2x-ncnn-vulkan ncnn ${Vulkan_LIBRARY} ${OpenMP_CXX_LIBRARIES}) 83 | -------------------------------------------------------------------------------- /waifu2x/DragDropImageView.h: -------------------------------------------------------------------------------- 1 | /* 2 | File: DragDropImageView.h 3 | Abstract: Custom subclass of NSImageView with support for drag and drop operations. 4 | Version: 1.1 5 | 6 | Copyright (C) 2011 Apple Inc. All Rights Reserved. 7 | 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | @protocol DragDropImageViewDelegate; 14 | 15 | @interface DragDropImageView : NSImageView 16 | { 17 | //highlight the drop zone 18 | BOOL highlight; 19 | } 20 | 21 | @property (assign) BOOL allowDrag; 22 | @property (assign) BOOL allowDrop; 23 | @property (assign) id delegate; 24 | @property (retain) NSString *path; 25 | 26 | - (id)initWithCoder:(NSCoder *)coder; 27 | 28 | @end 29 | 30 | @protocol DragDropImageViewDelegate 31 | 32 | - (void)dropComplete:(NSString *)filePath; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /waifu2x/DragDropImageView.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: DragDropImageView.m 3 | Abstract: Custom subclass of NSImageView with support for drag and drop operations. 4 | Version: 1.1 5 | 6 | Copyright (C) 2011 Apple Inc. All Rights Reserved. 7 | 8 | */ 9 | 10 | #import "DragDropImageView.h" 11 | 12 | @implementation DragDropImageView 13 | 14 | @synthesize allowDrag; 15 | @synthesize allowDrop; 16 | @synthesize delegate; 17 | 18 | NSString *kPrivateDragUTI = @"moe.cocoaneko.cocoadraganddrop"; 19 | 20 | - (id)initWithCoder:(NSCoder *)coder 21 | { 22 | /*------------------------------------------------------ 23 | Init method called for Interface Builder objects 24 | --------------------------------------------------------*/ 25 | self=[super initWithCoder:coder]; 26 | if ( self ) { 27 | //register for all the image types we can display 28 | [self registerForDraggedTypes:[NSImage imageTypes]]; 29 | self.allowDrag = YES; 30 | self.allowDrop = YES; 31 | } 32 | return self; 33 | } 34 | 35 | #pragma mark - Destination Operations 36 | 37 | - (NSDragOperation)draggingEntered:(id )sender 38 | { 39 | if (!self.allowDrop) 40 | return NSDragOperationNone; 41 | /*------------------------------------------------------ 42 | method called whenever a drag enters our drop zone 43 | --------------------------------------------------------*/ 44 | 45 | // Check if the pasteboard contains image data and source/user wants it copied 46 | if ( [NSImage canInitWithPasteboard:[sender draggingPasteboard]] && 47 | [sender draggingSourceOperationMask] & 48 | NSDragOperationCopy ) { 49 | 50 | //highlight our drop zone 51 | highlight=YES; 52 | 53 | [self setNeedsDisplay: YES]; 54 | 55 | /* When an image from one window is dragged over another, we want to resize the dragging item to 56 | * preview the size of the image as it would appear if the user dropped it in. */ 57 | [sender enumerateDraggingItemsWithOptions:NSDraggingItemEnumerationConcurrent 58 | forView:self 59 | classes:[NSArray arrayWithObject:[NSPasteboardItem class]] 60 | searchOptions:@{} 61 | usingBlock:^(NSDraggingItem *draggingItem, NSInteger idx, BOOL *stop) { 62 | 63 | /* Only resize a fragging item if it originated from one of our windows. To do this, 64 | * we declare a custom UTI that will only be assigned to dragging items we created. Here 65 | * we check if the dragging item can represent our custom UTI. If it can't we stop. */ 66 | if ( ![[[draggingItem item] types] containsObject:kPrivateDragUTI] ) { 67 | 68 | *stop = YES; 69 | 70 | } else { 71 | /* In order for the dragging item to actually resize, we have to reset its contents. 72 | * The frame is going to be the destination view's bounds. (Coordinates are local 73 | * to the destination view here). 74 | * For the contents, we'll grab the old contents and use those again. If you wanted 75 | * to perform other modifications in addition to the resize you could do that here. */ 76 | [draggingItem setDraggingFrame:self.bounds contents:[[[draggingItem imageComponents] objectAtIndex:0] contents]]; 77 | } 78 | }]; 79 | 80 | //accept data as a copy operation 81 | return NSDragOperationCopy; 82 | } 83 | 84 | return NSDragOperationNone; 85 | } 86 | 87 | - (void)draggingExited:(id )sender 88 | { 89 | /*------------------------------------------------------ 90 | method called whenever a drag exits our drop zone 91 | --------------------------------------------------------*/ 92 | //remove highlight of the drop zone 93 | highlight=NO; 94 | 95 | [self setNeedsDisplay: YES]; 96 | } 97 | 98 | -(void)drawRect:(NSRect)rect 99 | { 100 | /*------------------------------------------------------ 101 | draw method is overridden to do drop highlighing 102 | --------------------------------------------------------*/ 103 | //do the usual draw operation to display the image 104 | [super drawRect:rect]; 105 | 106 | if ( highlight ) { 107 | //highlight by overlaying a gray border 108 | [[NSColor grayColor] set]; 109 | [NSBezierPath setDefaultLineWidth: 5]; 110 | [NSBezierPath strokeRect: rect]; 111 | } 112 | } 113 | 114 | - (BOOL)prepareForDragOperation:(id )sender 115 | { 116 | /*------------------------------------------------------ 117 | method to determine if we can accept the drop 118 | --------------------------------------------------------*/ 119 | //finished with the drag so remove any highlighting 120 | highlight=NO; 121 | 122 | [self setNeedsDisplay: YES]; 123 | 124 | //check to see if we can accept the data 125 | return [NSImage canInitWithPasteboard: [sender draggingPasteboard]]; 126 | } 127 | 128 | - (BOOL)performDragOperation:(id )sender 129 | { 130 | /*------------------------------------------------------ 131 | method that should handle the drop data 132 | --------------------------------------------------------*/ 133 | if ([sender draggingSource] != self ) { 134 | NSURL* fileURL; 135 | 136 | //set the image using the best representation we can get from the pasteboard 137 | if([NSImage canInitWithPasteboard: [sender draggingPasteboard]]) { 138 | NSImage *newImage = [[NSImage alloc] initWithPasteboard: [sender draggingPasteboard]]; 139 | [self setImage:newImage]; 140 | // NSRect selfFrame = self.frame; 141 | // selfFrame.size = newImage.size; 142 | // selfFrame.origin = CGPointMake(0, 0); 143 | // self.frame = selfFrame; 144 | // self.superview.frame = self.frame; 145 | // [newImage release]; 146 | } 147 | 148 | //if the drag comes from a file, set the window title to the filename 149 | fileURL=[NSURL URLFromPasteboard: [sender draggingPasteboard]]; 150 | self.path = fileURL.path; 151 | [[self window] setTitle: fileURL!=NULL ? [fileURL lastPathComponent] : @"(no name)"]; 152 | if ([self.delegate respondsToSelector:@selector(dropComplete:)]) { 153 | [self.delegate dropComplete:[fileURL path]]; 154 | } 155 | } 156 | 157 | return YES; 158 | } 159 | 160 | - (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)newFrame; 161 | { 162 | /*------------------------------------------------------ 163 | delegate operation to set the standard window frame 164 | --------------------------------------------------------*/ 165 | //get window frame size 166 | NSRect ContentRect=self.window.frame; 167 | 168 | //set it to the image frame size 169 | ContentRect.size=[[self image] size]; 170 | 171 | return [NSWindow frameRectForContentRect:ContentRect styleMask: [window styleMask]]; 172 | }; 173 | 174 | #pragma mark - Source Operations 175 | 176 | - (void)mouseDown:(NSEvent*)event 177 | { 178 | if (self.allowDrag) { 179 | NSPoint dragPosition; 180 | NSRect imageLocation; 181 | 182 | dragPosition = [self convertPoint:[event locationInWindow] fromView:nil]; 183 | dragPosition.x -= 16; 184 | dragPosition.y -= 16; 185 | imageLocation.origin = dragPosition; 186 | imageLocation.size = NSMakeSize(32,32); 187 | [self dragPromisedFilesOfTypes:[NSArray arrayWithObject:NSPasteboardTypePDF] fromRect:imageLocation source:self slideBack:YES event:event]; 188 | } 189 | } 190 | 191 | - (void)dragImage:(NSImage *)anImage at:(NSPoint)viewLocation offset:(NSSize)initialOffset event:(NSEvent *)event pasteboard:(NSPasteboard *)pboard source:(id)sourceObj slideBack:(BOOL)slideFlag 192 | { 193 | if (![self image]) { 194 | return; 195 | } 196 | 197 | //create a new image for our semi-transparent drag image 198 | NSImage* dragImage=[[NSImage alloc] initWithSize:[[self image] size]]; 199 | 200 | [dragImage lockFocus];//draw inside of our dragImage 201 | //draw our original image as 50% transparent 202 | [[self image] dissolveToPoint: NSZeroPoint fraction: .5]; 203 | [dragImage unlockFocus];//finished drawing 204 | [dragImage setScalesWhenResized:NO];//we want the image to resize 205 | // Old code that scales drag proxy to view size 206 | // [dragImage setSize:[self bounds].size];//change to the size we are displaying 207 | 208 | // Find size of scaled image inside the view 209 | 210 | NSSize scaledImageSize; // Size (width,height) of the scaled image in the view 211 | float scale; // multiplier for the scaled image 212 | 213 | float imageRatio = dragImage.size.width / dragImage.size.height; 214 | 215 | float viewRatio = [self bounds].size.width / [self bounds].size.height; 216 | 217 | if(imageRatio < viewRatio) 218 | { 219 | scale = [self bounds].size.height / dragImage.size.height; 220 | } 221 | else 222 | { 223 | scale = [self bounds].size.width / dragImage.size.width; 224 | } 225 | 226 | 227 | scaledImageSize.width = scale * dragImage.size.width; 228 | scaledImageSize.height = scale * dragImage.size.height; 229 | 230 | [dragImage setSize:scaledImageSize];//change to the size we are displaying 231 | 232 | [super dragImage:dragImage at:self.bounds.origin offset:NSZeroSize event:event pasteboard:pboard source:sourceObj slideBack:slideFlag]; 233 | } 234 | 235 | - (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination 236 | { 237 | NSArray *representations; 238 | NSData *bitmapData; 239 | 240 | representations = [[self image] representations]; 241 | 242 | if ([[[representations objectAtIndex:0] className] isEqualToString:@"NSBitmapImageRep"]) { 243 | bitmapData = [NSBitmapImageRep representationOfImageRepsInArray:representations 244 | usingType:NSPNGFileType properties:@{}]; 245 | } else { 246 | NSLog(@"%@", [[[[self image] representations] objectAtIndex:0] className]); 247 | 248 | [[self image] lockFocus]; 249 | NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0.0, 0.0, [self image].size.width, self.image.size.height)]; 250 | [[self image] unlockFocus]; 251 | 252 | bitmapData = [bitmapRep representationUsingType:NSBitmapImageFileTypePNG properties:@{}]; 253 | } 254 | 255 | NSString *filename = self.path.lastPathComponent ? [NSString stringWithFormat:@"%@-2x.png", self.path.lastPathComponent] : @"waifu2x-output.png"; 256 | [bitmapData writeToFile:[[dropDestination path] stringByAppendingPathComponent:filename] atomically:YES]; 257 | return [NSArray arrayWithObjects:filename, nil]; 258 | } 259 | 260 | - (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context 261 | { 262 | /*------------------------------------------------------ 263 | NSDraggingSource protocol method. Returns the types of operations allowed in a certain context. 264 | --------------------------------------------------------*/ 265 | switch (context) { 266 | case NSDraggingContextOutsideApplication: 267 | return NSDragOperationCopy; 268 | 269 | //by using this fall through pattern, we will remain compatible if the contexts get more precise in the future. 270 | case NSDraggingContextWithinApplication: 271 | default: 272 | return NSDragOperationCopy; 273 | break; 274 | } 275 | } 276 | 277 | - (BOOL)acceptsFirstMouse:(NSEvent *)event 278 | { 279 | /*------------------------------------------------------ 280 | accept activation click as click in window 281 | --------------------------------------------------------*/ 282 | //so source doesn't have to be the active window 283 | return YES; 284 | } 285 | 286 | - (void)pasteboard:(NSPasteboard *)sender item:(NSPasteboardItem *)item provideDataForType:(NSString *)type 287 | { 288 | /*------------------------------------------------------ 289 | method called by pasteboard to support promised 290 | drag types. 291 | --------------------------------------------------------*/ 292 | //sender has accepted the drag and now we need to send the data for the type we promised 293 | if ( [type compare: NSPasteboardTypeTIFF] == NSOrderedSame ) { 294 | 295 | //set data for TIFF type on the pasteboard as requested 296 | [sender setData:[[self image] TIFFRepresentation] forType:NSPasteboardTypeTIFF]; 297 | 298 | } else if ( [type compare: NSPasteboardTypePDF] == NSOrderedSame ) { 299 | 300 | //set data for PDF type on the pasteboard as requested 301 | [sender setData:[self dataWithPDFInsideRect:[self bounds]] forType:NSPasteboardTypePDF]; 302 | } 303 | 304 | } 305 | @end 306 | -------------------------------------------------------------------------------- /waifu2x/DragDropTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DragDropTableView.h 3 | // waifu2x-gui 4 | // 5 | // Created by Cocoa on 20/02/2020. 6 | // Copyright © 2020 Cocoa Oikawa. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @protocol DragDropTableViewDelegate; 15 | 16 | @interface DragDropTableView : NSTableView 17 | 18 | @property (assign) BOOL allowDrop; 19 | @property (assign) id dropDelegate; 20 | 21 | - (id)initWithCoder:(NSCoder *)coder; 22 | 23 | @end 24 | 25 | @protocol DragDropTableViewDelegate 26 | 27 | - (void)dropTableComplete:(NSArray *)files; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /waifu2x/DragDropTableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DragDropTableView.m 3 | // waifu2x-gui 4 | // 5 | // Created by Cocoa on 20/02/2020. 6 | // Copyright © 2020 Cocoa Oikawa. All rights reserved. 7 | // 8 | 9 | #import "DragDropTableView.h" 10 | 11 | @implementation DragDropTableView 12 | 13 | @synthesize dropDelegate; 14 | 15 | - (id)initWithCoder:(NSCoder *)coder { 16 | self = [super initWithCoder:coder]; 17 | if ( self ) { 18 | self.allowDrop = YES; 19 | [self registerForDraggedTypes:[NSArray arrayWithObject:(NSString *)kUTTypeFileURL]]; 20 | } 21 | return self; 22 | } 23 | 24 | - (NSDragOperation)draggingEntered:(id)sender { 25 | if (!self.allowDrop) { 26 | return NSDragOperationNone; 27 | } 28 | 29 | return NSDragOperationCopy; 30 | } 31 | 32 | - (BOOL)performDragOperation:(id )sender { 33 | NSArray* acceptedTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeFolder, (NSString *)kUTTypeImage, nil]; 34 | NSArray* urls = [sender.draggingPasteboard 35 | readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] 36 | options:[NSDictionary dictionaryWithObjectsAndKeys: 37 | [NSNumber numberWithBool:YES], NSPasteboardURLReadingFileURLsOnlyKey, 38 | acceptedTypes, NSPasteboardURLReadingContentsConformToTypesKey, nil] 39 | ]; 40 | 41 | NSMutableArray * files = [[NSMutableArray alloc] init]; 42 | for (NSURL * fileurl in urls) { 43 | BOOL isDirectory; 44 | NSString * filepath = fileurl.filePathURL.path; 45 | if ([[NSFileManager defaultManager] fileExistsAtPath:filepath isDirectory:&isDirectory]) { 46 | if (isDirectory) { 47 | NSDirectoryEnumerator * enumerator = [[NSFileManager defaultManager] enumeratorAtPath:filepath]; 48 | [enumerator skipDescendants]; 49 | for (NSString * file in enumerator) { 50 | NSString * path = [NSString stringWithFormat:@"%@/%@", filepath, file]; 51 | BOOL isDirectory; 52 | if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory]) { 53 | if (!isDirectory) { 54 | [files addObject:path]; 55 | } 56 | } 57 | } 58 | } else { 59 | [files addObject:filepath]; 60 | } 61 | } 62 | } 63 | 64 | if ([self.dropDelegate respondsToSelector:@selector(dropTableComplete:)]) { 65 | [self.dropDelegate dropTableComplete:files]; 66 | } 67 | 68 | return YES; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /waifu2x/GPUInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // GPUInfo.h 3 | // waifu2x-gui 4 | // 5 | // Created by Cocoa on 20/02/2020. 6 | // Copyright © 2020 Cocoa Oikawa. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface GPUInfo : NSObject 16 | 17 | + (instancetype)initWithName:(NSString *)name deviceID:(uint32_t)deviceID physicalDevice:(VkPhysicalDevice)device; 18 | 19 | @property (strong) NSString * name; 20 | @property (nonatomic) uint32_t deviceID; 21 | @property (nonatomic) VkPhysicalDevice physicalDevice; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /waifu2x/GPUInfo.mm: -------------------------------------------------------------------------------- 1 | // 2 | // GPUInfo.m 3 | // waifu2x-gui 4 | // 5 | // Created by Cocoa on 20/02/2020. 6 | // Copyright © 2020 Cocoa Oikawa. All rights reserved. 7 | // 8 | 9 | #import "GPUInfo.h" 10 | 11 | @implementation GPUInfo 12 | 13 | @synthesize name; 14 | @synthesize deviceID; 15 | @synthesize physicalDevice; 16 | 17 | + (instancetype)initWithName:(NSString *)name deviceID:(uint32_t)deviceID physicalDevice:(VkPhysicalDevice)device { 18 | GPUInfo * info = [[GPUInfo alloc] init]; 19 | if (info) { 20 | [info setName:name]; 21 | [info setDeviceID:deviceID]; 22 | [info setPhysicalDevice:device]; 23 | } 24 | return info; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /waifu2x/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2019-2020 Cocoa. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /waifu2x/MoltenVK_icd.json: -------------------------------------------------------------------------------- 1 | { 2 | "file_format_version" : "1.0.0", 3 | "ICD": { 4 | "library_path": "../Frameworks/libMoltenVK.dylib", 5 | "api_version" : "1.0.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /waifu2x/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // waifu2x 4 | // 5 | // Created by Cocoa on 2019/4/25. 6 | // Copyright © 2019-2020 Cocoa. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | #import "DragDropImageView.h" 12 | #import "DragDropTableView.h" 13 | 14 | @interface ViewController : NSViewController 15 | 16 | - (IBAction)waifu2x:(id)sender; 17 | - (void)benchmark; 18 | 19 | @property (weak) IBOutlet DragDropImageView *inputImageView; 20 | @property (weak) IBOutlet DragDropImageView *outputImageView; 21 | @property (weak) IBOutlet NSTextField *statusLabel; 22 | @property (weak) IBOutlet NSProgressIndicator *waifu2xProgress; 23 | @property (weak) IBOutlet NSTextField *noiseParameter; 24 | @property (weak) IBOutlet NSTextField *scaleParameter; 25 | @property (weak) IBOutlet NSTextField *tilesizeParameter; 26 | @property (weak) IBOutlet NSTextField *loadingJobsParameter; 27 | @property (weak) IBOutlet NSTextField *processingJobsParameter; 28 | @property (weak) IBOutlet NSTextField *savingJobsParameter; 29 | @property (weak) IBOutlet NSPopUpButton *gpuIDButton; 30 | @property (weak) IBOutlet NSPopUpButton *modelButton; 31 | @property (weak) IBOutlet NSTextField *vramStaticticsLabel; 32 | @property (weak) IBOutlet NSTabView *processingModeTab; 33 | @property (weak) IBOutlet DragDropTableView *multipleImageTableView; 34 | @property (weak) IBOutlet NSButton *startButton; 35 | @property (weak) IBOutlet NSButton *ttaModeButton; 36 | 37 | @end 38 | 39 | -------------------------------------------------------------------------------- /waifu2x/ViewController.mm: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // waifu2x 4 | // 5 | // Created by Cocoa on 2019/4/25. 6 | // Copyright © 2019-2020 Cocoa. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import 12 | #import 13 | #import "waifu2xmac.h" 14 | #import "GPUInfo.h" 15 | #import "gpu.h" 16 | 17 | @interface ViewController() { 18 | VkInstance gpuInstance; 19 | } 20 | 21 | @property (strong) NSString * inputImagePath; 22 | @property (strong) NSArray * gpus; 23 | @property (nonatomic) uint32_t currentGPUID; 24 | @property (strong, nonatomic) NSTimer * vramStaticticsTimer; 25 | @property (strong, nonatomic) NSMutableArray * inputImageFiles; 26 | @property (atomic) BOOL isProcessing; 27 | @property (nonatomic) BOOL isBenchmarking; 28 | 29 | @end 30 | 31 | @implementation ViewController 32 | 33 | @synthesize inputImageView; 34 | @synthesize outputImageView; 35 | @synthesize statusLabel; 36 | @synthesize waifu2xProgress; 37 | @synthesize noiseParameter, scaleParameter, tilesizeParameter, loadingJobsParameter, processingJobsParameter, savingJobsParameter; 38 | @synthesize gpus; 39 | @synthesize vramStaticticsLabel; 40 | @synthesize processingModeTab; 41 | @synthesize multipleImageTableView; 42 | @synthesize ttaModeButton; 43 | 44 | - (void)viewDidLoad { 45 | [super viewDidLoad]; 46 | ((AppDelegate *)[NSApp delegate]).viewController = self; 47 | 48 | [self.statusLabel setStringValue:NSLocalizedString(@"Idle", @"")]; 49 | [self.waifu2xProgress setMinValue:0.0]; 50 | [self.waifu2xProgress setMaxValue:100.0]; 51 | 52 | [self.inputImageView setAllowDrop:YES]; 53 | [self.inputImageView setAllowDrag:NO]; 54 | [self.inputImageView setImageScaling:NSImageScaleProportionallyUpOrDown]; 55 | [self.inputImageView setDelegate:self]; 56 | 57 | [self.outputImageView setAllowDrag:YES]; 58 | [self.outputImageView setImageScaling:NSImageScaleProportionallyUpOrDown]; 59 | 60 | [self.modelButton removeAllItems]; 61 | [self.modelButton addItemWithTitle:@"cunet"]; 62 | [self.modelButton addItemWithTitle:@"upconv_7_anime_style_art_rgb"]; 63 | [self.modelButton addItemWithTitle:@"upconv_7_photo"]; 64 | 65 | [self.gpuIDButton removeAllItems]; 66 | if (![self createGPUInstance]) { 67 | [self.statusLabel setStringValue:@"Error: cannot create GPU instance with Vulkan"]; 68 | } 69 | 70 | self.inputImageFiles = [[NSMutableArray alloc] init]; 71 | 72 | [self.multipleImageTableView setDataSource:self]; 73 | [self.multipleImageTableView setDelegate:self]; 74 | [self.multipleImageTableView setAllowDrop:YES]; 75 | [self.multipleImageTableView setDropDelegate:self]; 76 | 77 | [self.processingModeTab setDelegate:self]; 78 | } 79 | 80 | - (void)changeGPU:(NSPopUpButton *)sender { 81 | self.currentGPUID = (uint32_t)[self.gpuIDButton indexOfSelectedItem]; 82 | } 83 | 84 | - (BOOL)createGPUInstance { 85 | // copied from Tencent/ncnn/gpu.cpp with minor changes 86 | // https://github.com/Tencent/ncnn/blob/master/src/gpu.cpp 87 | VkResult ret; 88 | 89 | std::vector enabledLayers; 90 | std::vector enabledExtensions; 91 | 92 | uint32_t instanceExtensionPropertyCount; 93 | ret = vkEnumerateInstanceExtensionProperties(NULL, &instanceExtensionPropertyCount, NULL); 94 | if (ret != VK_SUCCESS) { 95 | fprintf(stderr, "vkEnumerateInstanceExtensionProperties failed %d\n", ret); 96 | return NO; 97 | } 98 | 99 | std::vector instanceExtensionProperties(instanceExtensionPropertyCount); 100 | ret = vkEnumerateInstanceExtensionProperties(NULL, &instanceExtensionPropertyCount, instanceExtensionProperties.data()); 101 | if (ret != VK_SUCCESS) { 102 | fprintf(stderr, "vkEnumerateInstanceExtensionProperties failed %d\n", ret); 103 | return NO; 104 | } 105 | 106 | static int support_VK_KHR_get_physical_device_properties2 = 0; 107 | for (uint32_t j=0; jgpuInstance); 137 | if (ret != VK_SUCCESS) { 138 | fprintf(stderr, "vkCreateInstance failed %d\n", ret); 139 | return NO; 140 | } 141 | 142 | uint32_t physicalDeviceCount = 0; 143 | ret = vkEnumeratePhysicalDevices(self->gpuInstance, &physicalDeviceCount, 0); 144 | if (ret != VK_SUCCESS) { 145 | fprintf(stderr, "vkEnumeratePhysicalDevices failed %d\n", ret); 146 | } 147 | 148 | std::vector physicalDevices(physicalDeviceCount); 149 | ret = vkEnumeratePhysicalDevices(self->gpuInstance, &physicalDeviceCount, physicalDevices.data()); 150 | if (ret != VK_SUCCESS) { 151 | fprintf(stderr, "vkEnumeratePhysicalDevices failed %d\n", ret); 152 | } 153 | 154 | NSMutableArray * gpus = [NSMutableArray arrayWithCapacity:physicalDeviceCount]; 155 | for (uint32_t i=0; i * tilesizes = @[@(400), @(200), @(100)]; 236 | NSArray * inputSizes = @[@(200), @(400), @(1000), @(2000), @(4000)]; 237 | NSArray * outputfiles = @[@"/tmp/waifu2x-macos-benchmark.png"]; 238 | 239 | self.isProcessing = YES; 240 | self.isBenchmarking = YES; 241 | [self allowUserIntereaction:NO]; 242 | 243 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 244 | [result addObject:@"|Model|Image Size|Target Size|Block Size|Total Time(sec)|GPU Memory(MB)|"]; 245 | [result addObject:@"|---|---|---|---|---|---|"]; 246 | for (NSString * model in models) { 247 | for (NSNumber * inputSize in inputSizes) { 248 | int imageSize = inputSize.intValue; 249 | int targetSize = imageSize * scale; 250 | NSString * inputfile = [[NSBundle mainBundle] pathForResource:[[NSString alloc] initWithFormat:@"benchmark/%dx%d", imageSize, imageSize] ofType:@"png"]; 251 | if (inputfile == nil) { continue; } 252 | 253 | NSMutableArray *> * tilesResult = [[NSMutableArray alloc] initWithCapacity:tilesizes.count]; 254 | for (NSNumber * tilesize in tilesizes) { 255 | NSMutableArray * tileResult = [[NSMutableArray alloc] initWithCapacity:2]; 256 | int tsize = [tilesize intValue]; 257 | dispatch_sync(dispatch_get_main_queue(), ^{ 258 | [self.statusLabel setStringValue:[[NSString alloc] initWithFormat:@"Benchmark - %@ - (%dx%d)@%d", model, imageSize, imageSize, tsize]]; 259 | }); 260 | 261 | double usage = 0; 262 | std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); 263 | 264 | [waifu2xmac input:@[inputfile] 265 | output:outputfiles 266 | noise:noise 267 | scale:scale 268 | tilesize:tsize 269 | model:model 270 | gpuid:gpuID 271 | tta_mode:enableTTAMode 272 | load_job_num:1 273 | proc_job_num:1 274 | save_job_num:1 275 | single_mode:NO 276 | VRAMUsage:&usage 277 | progress:nil]; 278 | 279 | std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); 280 | 281 | dispatch_sync(dispatch_get_main_queue(), ^{ 282 | double elapsed_time = std::chrono::duration_cast(end - begin).count() / 1000.0; 283 | [tileResult addObject:@(elapsed_time)]; 284 | [tileResult addObject:@(usage)]; 285 | [tilesResult addObject:tileResult]; 286 | }); 287 | } 288 | 289 | NSMutableString * totalTime = [[NSMutableString alloc] init]; 290 | NSMutableString * memoryUsage = [[NSMutableString alloc] init]; 291 | NSMutableString * tilesizeDesc = [[NSMutableString alloc] init]; 292 | for (NSUInteger index = 0; index < tilesizes.count; index++) { 293 | NSMutableArray * tileResult = tilesResult[index]; 294 | [tilesizeDesc appendFormat:@"%d/", tilesizes[index].intValue]; 295 | [totalTime appendFormat:@"%.2lf/", tileResult[0].doubleValue]; 296 | [memoryUsage appendFormat:@"%.0lf/", tileResult[1].doubleValue]; 297 | } 298 | [result addObject:[[NSString alloc] initWithFormat:@"|%@|%dx%d|%dx%d|%@|%@|%@|", 299 | model, 300 | imageSize, imageSize, 301 | targetSize, targetSize, 302 | [tilesizeDesc substringToIndex:tilesizeDesc.length - 1], 303 | [totalTime substringToIndex:totalTime.length - 1], 304 | [memoryUsage substringToIndex:memoryUsage.length - 1]]]; 305 | } 306 | } 307 | 308 | dispatch_sync(dispatch_get_main_queue(), ^{ 309 | [self.statusLabel setStringValue:NSLocalizedString(@"Idle", @"")]; 310 | [self allowUserIntereaction:YES]; 311 | self.isProcessing = NO; 312 | self.isBenchmarking = NO; 313 | 314 | unlink("/tmp/waifu2x-macos-benchmark.png"); 315 | 316 | NSAlert *alert = [[NSAlert alloc] init]; 317 | [alert addButtonWithTitle:@"Copy"]; 318 | [alert addButtonWithTitle:@"Cancel"]; 319 | [alert setMessageText:@"Benchmark Result"]; 320 | NSMutableString * resultString = [[NSMutableString alloc] init]; 321 | for (NSString * p in result) { 322 | [resultString appendFormat:@"%@\n", p]; 323 | } 324 | [resultString appendFormat:@"\nnoise: %d, scale: %d, gpuid: %d, tta mode: %@\n", noise, scale, gpuID, enableTTAMode ? @"YES" : @"NO"]; 325 | [alert setInformativeText:resultString]; 326 | [alert setAlertStyle:NSAlertStyleInformational]; 327 | [alert beginSheetModalForWindow:[self view].window completionHandler:^(NSModalResponse returnCode) { 328 | if (returnCode == 1000) { 329 | [[NSPasteboard generalPasteboard] clearContents]; 330 | [[NSPasteboard generalPasteboard] setString:resultString forType:NSStringPboardType]; 331 | } 332 | }]; 333 | }); 334 | }); 335 | } 336 | 337 | - (void)allowUserIntereaction:(BOOL)enabled { 338 | if ([self.processingModeTab indexOfTabViewItem:[self.processingModeTab selectedTabViewItem]] == 1) { 339 | [self.multipleImageTableView setAllowDrop:enabled]; 340 | } else { 341 | [self.inputImageView setAllowDrop:enabled]; 342 | [self.inputImageView setEditable:enabled]; 343 | [self.inputImageView setAllowsCutCopyPaste:enabled]; 344 | [self.outputImageView setAllowDrag:enabled]; 345 | [self.outputImageView setEditable:enabled]; 346 | [self.outputImageView setAllowsCutCopyPaste:enabled]; 347 | } 348 | [self.startButton setEnabled:enabled]; 349 | } 350 | 351 | - (IBAction)waifu2x:(NSButton *)sender { 352 | int noise = self.noiseParameter.intValue; 353 | int scale = self.scaleParameter.intValue; 354 | int tilesize = self.tilesizeParameter.intValue; 355 | int load_jobs = self.loadingJobsParameter.intValue; 356 | int proc_jobs = self.processingJobsParameter.intValue; 357 | int save_jobs = self.savingJobsParameter.intValue; 358 | NSString * model = [NSString stringWithFormat:@"models-%@", [self.modelButton selectedItem].title]; 359 | int gpuID = self.gpus[self.gpuIDButton.indexOfSelectedItem].deviceID; 360 | BOOL enableTTAMode = self.ttaModeButton.state == NSControlStateValueOn; 361 | BOOL isSingleMode = true; 362 | 363 | NSArray * inputpaths = nil; 364 | NSArray * outputpaths = nil; 365 | if ([self.processingModeTab indexOfTabViewItem:[self.processingModeTab selectedTabViewItem]] == 1) { 366 | if (self.inputImageFiles.count == 0) { 367 | return; 368 | } 369 | 370 | inputpaths = self.inputImageFiles; 371 | outputpaths = [self generateOutputPaths:self.inputImageFiles]; 372 | isSingleMode = false; 373 | } else { 374 | if (!self.inputImageView.image) { 375 | return; 376 | } 377 | 378 | char tmp_filename_buf[32] = {'\0'}; 379 | const char * template_filename = "/tmp/isrm-XXXXXX"; 380 | strncpy(tmp_filename_buf, template_filename, strlen(template_filename)); 381 | int err = mkstemp(tmp_filename_buf); 382 | if (err < 1) { 383 | [self.statusLabel setStringValue:[NSString stringWithFormat:@"Error: cannot create tmp file: %s", strerror(errno)]]; 384 | return; 385 | } 386 | outputpaths = @[[NSString stringWithFormat:@"%s.png", tmp_filename_buf]]; 387 | inputpaths = @[self.inputImagePath]; 388 | } 389 | 390 | [self allowUserIntereaction:NO]; 391 | self.isProcessing = YES; 392 | 393 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 394 | NSImage * result = [waifu2xmac input:inputpaths 395 | output:outputpaths 396 | noise:noise 397 | scale:scale 398 | tilesize:tilesize 399 | model:model 400 | gpuid:gpuID 401 | tta_mode:enableTTAMode 402 | load_job_num:load_jobs 403 | proc_job_num:proc_jobs 404 | save_job_num:save_jobs 405 | single_mode:isSingleMode 406 | VRAMUsage:nullptr 407 | progress:^(int current, int total, NSString *description) { 408 | dispatch_async(dispatch_get_main_queue(), ^{ 409 | [self.statusLabel setStringValue:[NSString stringWithFormat:@"[%d/%d] %@", current, total, description]]; 410 | [self.waifu2xProgress setDoubleValue:((double)current)/total * 100]; 411 | }); 412 | }]; 413 | 414 | self.isProcessing = NO; 415 | 416 | dispatch_async(dispatch_get_main_queue(), ^{ 417 | [self allowUserIntereaction:YES]; 418 | if (isSingleMode) { 419 | if (!result) { 420 | return; 421 | } 422 | 423 | [self.outputImageView setImage:result]; 424 | unlink(outputpaths[0].UTF8String); 425 | } 426 | }); 427 | }); 428 | } 429 | 430 | #pragma mark - DragDropImageViewDelegate 431 | 432 | - (void)dropComplete:(NSString *)filePath { 433 | self.inputImagePath = filePath; 434 | } 435 | 436 | #pragma mark - DragDropTableViewDelegate 437 | 438 | - (void)dropTableComplete:(NSArray *)files { 439 | [self.inputImageFiles addObjectsFromArray:files]; 440 | [self.multipleImageTableView reloadData]; 441 | } 442 | 443 | #pragma mark - NSTableViewDataSource 444 | 445 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { 446 | if (tableView == self.multipleImageTableView) { 447 | return self.inputImageFiles.count; 448 | } else { 449 | return 0; 450 | } 451 | } 452 | 453 | #pragma mark - NSTableViewDelegate 454 | 455 | - (nullable NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row { 456 | if (tableView == self.multipleImageTableView) { 457 | NSTableCellView * cell = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self]; 458 | [cell.textField setStringValue:[self.inputImageFiles objectAtIndex:row]]; 459 | return cell; 460 | } else { 461 | return nil; 462 | } 463 | } 464 | 465 | - (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation { 466 | return YES; 467 | } 468 | 469 | - (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation { 470 | return NSDragOperationCopy; 471 | } 472 | 473 | #pragma mark - NSTabViewDelegate 474 | 475 | - (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(nullable NSTabViewItem *)tabViewItem { 476 | return !self.isProcessing; 477 | } 478 | 479 | - (IBAction)delete:(id)sender { 480 | if ([self.processingModeTab indexOfTabViewItem:[self.processingModeTab selectedTabViewItem]] == 1) { 481 | NSIndexSet * selectedSet = [self.multipleImageTableView selectedRowIndexes]; 482 | if (selectedSet.count > 0) { 483 | [self.inputImageFiles removeObjectsAtIndexes:selectedSet]; 484 | [self.multipleImageTableView reloadData]; 485 | if (selectedSet.count == 1) { 486 | [self.multipleImageTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedSet.firstIndex] byExtendingSelection:NO]; 487 | } 488 | } else { 489 | NSBeep(); 490 | } 491 | } 492 | } 493 | 494 | @end 495 | -------------------------------------------------------------------------------- /waifu2x/VulkanSDK/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/VulkanSDK/.gitkeep -------------------------------------------------------------------------------- /waifu2x/benchmark/1000x1000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/benchmark/1000x1000.png -------------------------------------------------------------------------------- /waifu2x/benchmark/2000x2000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/benchmark/2000x2000.png -------------------------------------------------------------------------------- /waifu2x/benchmark/200x200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/benchmark/200x200.png -------------------------------------------------------------------------------- /waifu2x/benchmark/4000x4000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/benchmark/4000x4000.png -------------------------------------------------------------------------------- /waifu2x/benchmark/400x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/benchmark/400x400.png -------------------------------------------------------------------------------- /waifu2x/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // waifu2x 4 | // 5 | // Created by Cocoa on 2019/4/25. 6 | // Copyright © 2019-2020 Cocoa. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | setenv("VK_ICD_FILENAMES", [[NSBundle mainBundle] pathForResource:@"MoltenVK_icd" ofType:@"json"].UTF8String, 1); 13 | return NSApplicationMain(argc, argv); 14 | } 15 | -------------------------------------------------------------------------------- /waifu2x/ncnn/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/ncnn/.gitkeep -------------------------------------------------------------------------------- /waifu2x/waifu2x-ncnn-vulkan/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/waifu2x-ncnn-vulkan/.gitkeep -------------------------------------------------------------------------------- /waifu2x/waifu2x-ncnn-vulkan/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moeoverflow/waifu2x-ncnn-vulkan-macos/438d89774b59959a8d634ba88b70ae111f6f01ee/waifu2x/waifu2x-ncnn-vulkan/models/.gitkeep -------------------------------------------------------------------------------- /waifu2x/waifu2x.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /waifu2x/waifu2xmac.h: -------------------------------------------------------------------------------- 1 | // 2 | // waifu2xmac.h 3 | // waifu2xmac 4 | // 5 | // Created by Cocoa on 2019/4/25. 6 | // Copyright © 2019-2020 Cocoa. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "GPUInfo.h" 12 | 13 | typedef void (^waifu2xProgressBlock)(int current, int total, NSString * description); 14 | 15 | @interface waifu2xmac : NSObject 16 | 17 | + (NSImage *)input:(NSArray *)inputpaths 18 | output:(NSArray *)outputpaths 19 | noise:(int)noise 20 | scale:(int)scale 21 | tilesize:(int)tilesize 22 | model:(NSString *)model 23 | gpuid:(int)gpuid 24 | tta_mode:(BOOL)enable_tta_mode 25 | load_job_num:(int)jobs_load 26 | proc_job_num:(int)jobs_proc 27 | save_job_num:(int)jobs_save 28 | single_mode:(BOOL)is_single_mode 29 | VRAMUsage:(double *)usage 30 | progress:(waifu2xProgressBlock)cb; 31 | 32 | @end 33 | 34 | -------------------------------------------------------------------------------- /waifu2x/waifu2xmac.mm: -------------------------------------------------------------------------------- 1 | // 2 | // waifu2xmac.mm 3 | // waifu2xmac 4 | // 5 | // Created by Cocoa on 2019/4/25. 6 | // Copyright © 2019-2020 Cocoa. All rights reserved. 7 | // 8 | 9 | #import "waifu2xmac.h" 10 | #import "waifu2x-ncnn-vulkan/src/waifu2x.h" 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | // image decoder and encoder with stb 17 | #define STB_IMAGE_IMPLEMENTATION 18 | #define STBI_NO_PSD 19 | #define STBI_NO_TGA 20 | #define STBI_NO_GIF 21 | #define STBI_NO_HDR 22 | #define STBI_NO_PIC 23 | #include "stb_image.h" 24 | #define STB_IMAGE_WRITE_IMPLEMENTATION 25 | #include "stb_image_write.h" 26 | 27 | // ncnn 28 | #include "cpu.h" 29 | #include "gpu.h" 30 | #include "platform.h" 31 | #include "waifu2x-ncnn-vulkan/src/filesystem_utils.h" 32 | 33 | class Task 34 | { 35 | public: 36 | int id; 37 | 38 | path_t inpath; 39 | path_t outpath; 40 | 41 | ncnn::Mat inimage; 42 | ncnn::Mat outimage; 43 | }; 44 | 45 | class TaskQueue 46 | { 47 | public: 48 | TaskQueue() 49 | { 50 | } 51 | 52 | void put(const Task& v) 53 | { 54 | lock.lock(); 55 | 56 | while (tasks.size() >= 8) // FIXME hardcode queue length 57 | { 58 | condition.wait(lock); 59 | } 60 | 61 | tasks.push(v); 62 | 63 | lock.unlock(); 64 | 65 | condition.signal(); 66 | } 67 | 68 | void get(Task& v) 69 | { 70 | lock.lock(); 71 | 72 | while (tasks.size() == 0) 73 | { 74 | condition.wait(lock); 75 | } 76 | 77 | v = tasks.front(); 78 | tasks.pop(); 79 | 80 | lock.unlock(); 81 | 82 | condition.signal(); 83 | } 84 | 85 | private: 86 | ncnn::Mutex lock; 87 | ncnn::ConditionVariable condition; 88 | std::queue tasks; 89 | }; 90 | 91 | TaskQueue toproc; 92 | TaskQueue tosave; 93 | 94 | class LoadThreadParams 95 | { 96 | public: 97 | int scale; 98 | int jobs_load; 99 | 100 | // session data 101 | std::vector input_files; 102 | std::vector output_files; 103 | }; 104 | 105 | void* load(void* args) 106 | { 107 | const LoadThreadParams* ltp = (const LoadThreadParams*)args; 108 | const int count = (int)ltp->input_files.size(); 109 | const int scale = ltp->scale; 110 | 111 | #pragma omp parallel for num_threads(ltp->jobs_load) 112 | for (int i=0; iinput_files[i]; 115 | 116 | unsigned char* pixeldata = 0; 117 | int w; 118 | int h; 119 | int c; 120 | 121 | #if _WIN32 122 | pixeldata = wic_decode_image(imagepath.c_str(), &w, &h, &c); 123 | #else // _WIN32 124 | pixeldata = stbi_load(imagepath.c_str(), &w, &h, &c, 3); 125 | #endif // _WIN32 126 | if (pixeldata) 127 | { 128 | Task v; 129 | v.id = i; 130 | v.inpath = imagepath; 131 | v.outpath = ltp->output_files[i]; 132 | 133 | v.inimage = ncnn::Mat(w, h, (void*)pixeldata, (size_t)3, 3); 134 | v.outimage = ncnn::Mat(w * scale, h * scale, (size_t)3u, 3); 135 | 136 | toproc.put(v); 137 | } 138 | else 139 | { 140 | #if _WIN32 141 | fwprintf(stderr, L"decode image %ls failed\n", imagepath.c_str()); 142 | #else // _WIN32 143 | fprintf(stderr, "decode image %s failed\n", imagepath.c_str()); 144 | #endif // _WIN32 145 | } 146 | } 147 | 148 | return 0; 149 | } 150 | 151 | class ProcThreadParams 152 | { 153 | public: 154 | const Waifu2x* waifu2x; 155 | }; 156 | 157 | void* proc(void* args) 158 | { 159 | const ProcThreadParams* ptp = (const ProcThreadParams*)args; 160 | const Waifu2x* waifu2x = ptp->waifu2x; 161 | 162 | for (;;) 163 | { 164 | Task v; 165 | 166 | toproc.get(v); 167 | 168 | if (v.id == -233) 169 | break; 170 | 171 | waifu2x->process(v.inimage, v.outimage); 172 | 173 | tosave.put(v); 174 | } 175 | 176 | return 0; 177 | } 178 | 179 | class SaveThreadParams 180 | { 181 | public: 182 | int verbose; 183 | }; 184 | 185 | void* save(void* args) 186 | { 187 | const SaveThreadParams* stp = (const SaveThreadParams*)args; 188 | const int verbose = stp->verbose; 189 | 190 | for (;;) 191 | { 192 | Task v; 193 | 194 | tosave.get(v); 195 | 196 | if (v.id == -233) 197 | break; 198 | 199 | // free input pixel data 200 | { 201 | unsigned char* pixeldata = (unsigned char*)v.inimage.data; 202 | #if _WIN32 203 | free(pixeldata); 204 | #else 205 | stbi_image_free(pixeldata); 206 | #endif 207 | } 208 | 209 | #if _WIN32 210 | int success = wic_encode_image(v.outpath.c_str(), v.outimage.w, v.outimage.h, 3, v.outimage.data); 211 | #else 212 | int success = stbi_write_png(v.outpath.c_str(), v.outimage.w, v.outimage.h, 3, v.outimage.data, 0); 213 | #endif 214 | if (success) 215 | { 216 | if (verbose) 217 | { 218 | #if _WIN32 219 | fwprintf(stderr, L"%ls -> %ls done\n", v.inpath.c_str(), v.outpath.c_str()); 220 | #else 221 | fprintf(stderr, "%s -> %s done\n", v.inpath.c_str(), v.outpath.c_str()); 222 | #endif 223 | } 224 | } 225 | else 226 | { 227 | #if _WIN32 228 | fwprintf(stderr, L"encode image %ls failed\n", v.outpath.c_str()); 229 | #else 230 | fprintf(stderr, "encode image %s failed\n", v.outpath.c_str()); 231 | #endif 232 | } 233 | } 234 | 235 | return 0; 236 | } 237 | 238 | @implementation waifu2xmac 239 | 240 | + (NSImage *)input:(NSArray *)inputpaths 241 | output:(NSArray *)outputpaths 242 | noise:(int)noise 243 | scale:(int)scale 244 | tilesize:(int)tilesize 245 | model:(NSString *)model 246 | gpuid:(int)gpuid 247 | tta_mode:(BOOL)enable_tta_mode 248 | load_job_num:(int)jobs_load 249 | proc_job_num:(int)jobs_proc 250 | save_job_num:(int)jobs_save 251 | single_mode:(BOOL)is_single_mode 252 | VRAMUsage:(double *)usage 253 | progress:(waifu2xProgressBlock)cb { 254 | NSImage * result = nil; 255 | int total = 9; 256 | 257 | if (inputpaths.count != outputpaths.count) { 258 | if (cb) cb(1, total, NSLocalizedString(@"Error: inequivalent number of input / output files", @"")); 259 | } 260 | 261 | if (cb) cb(1, total, NSLocalizedString(@"Check parameters...", @"")); 262 | if (noise < -1 || noise > 3) 263 | { 264 | if (cb) cb(1, total, NSLocalizedString(@"Error: supported noise is 0, 1 or 2", @"")); 265 | return nil; 266 | } 267 | 268 | if (scale < 1 || scale > 2) 269 | { 270 | if (cb) cb(1, total, NSLocalizedString(@"Error: supported scale is 1 or 2", @"")); 271 | return nil; 272 | } 273 | 274 | if (tilesize < 32) 275 | { 276 | if (cb) cb(1, total, NSLocalizedString(@"Error: tilesize should no less than 32", @"")); 277 | return nil; 278 | } 279 | 280 | if (jobs_proc <= 0) 281 | { 282 | jobs_proc = INT32_MAX; 283 | } 284 | 285 | if (jobs_load <= 0) 286 | { 287 | jobs_load = 1; 288 | } 289 | 290 | if (jobs_save <= 0) 291 | { 292 | jobs_save = 2; 293 | } 294 | 295 | if (cb) cb(2, total, NSLocalizedString(@"Prepare models...", @"")); 296 | 297 | int prepadding = 0; 298 | if ([model isEqualToString:@"models-cunet"]) { 299 | if (noise == -1) 300 | { 301 | prepadding = 18; 302 | } 303 | else if (scale == 1) 304 | { 305 | prepadding = 28; 306 | } 307 | else if (scale == 2) 308 | { 309 | prepadding = 18; 310 | } 311 | } else if ([model isEqualToString:@"models-upconv_7_anime_style_art_rgb"]) { 312 | prepadding = 7; 313 | } else if ([model isEqualToString:@"models-upconv_7_photo"]) { 314 | prepadding = 7; 315 | } else { 316 | if (cb) cb(3, total, NSLocalizedString(@"[ERROR] No such model", @"")); 317 | return nil; 318 | } 319 | 320 | NSString * parampath = nil; 321 | NSString * modelpath = nil; 322 | if (noise == -1) 323 | { 324 | parampath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"models/%@/scale2.0x_model.param", model] ofType:nil]; 325 | modelpath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"models/%@/scale2.0x_model.bin", model] ofType:nil]; 326 | } 327 | else if (scale == 1) 328 | { 329 | parampath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"models/%@/noise%d_model.param", model, noise] ofType:nil]; 330 | modelpath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"models/%@/noise%d_model.bin", model, noise] ofType:nil]; 331 | } 332 | else if (scale == 2) 333 | { 334 | parampath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"models/%@/noise%d_scale2.0x_model.param", model, noise] ofType:nil]; 335 | modelpath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"models/%@/noise%d_scale2.0x_model.bin", model, noise] ofType:nil]; 336 | } 337 | 338 | if (cb) cb(3, total, NSLocalizedString(@"Creating GPU instance...", @"")); 339 | ncnn::create_gpu_instance(); 340 | int cpu_count = std::max(1, ncnn::get_cpu_count()); 341 | jobs_load = std::min(jobs_load, cpu_count); 342 | jobs_save = std::min(jobs_save, cpu_count); 343 | 344 | int gpu_count = ncnn::get_gpu_count(); 345 | if (gpuid < 0 || gpuid >= gpu_count) 346 | { 347 | if (cb) cb(3, total, NSLocalizedString(@"[ERROR] Invalid gpu device", @"")); 348 | 349 | ncnn::destroy_gpu_instance(); 350 | return nil; 351 | } 352 | 353 | int gpu_queue_count = ncnn::get_gpu_info(gpuid).compute_queue_count; 354 | const_cast(ncnn::get_gpu_info(gpuid)).buffer_offset_alignment = 16; 355 | jobs_proc = std::min(jobs_proc, gpu_queue_count); 356 | 357 | std::vector input_files; 358 | std::vector output_files; 359 | 360 | for (NSUInteger index = 0; index < inputpaths.count; index++) { 361 | input_files.emplace_back([inputpaths[index] UTF8String]); 362 | output_files.emplace_back([outputpaths[index] UTF8String]); 363 | } 364 | 365 | { 366 | Waifu2x waifu2x(gpuid, enable_tta_mode); 367 | 368 | if (cb) cb(4, total, NSLocalizedString(@"Loading models...", @"")); 369 | waifu2x.load([parampath UTF8String], [modelpath UTF8String]); 370 | 371 | waifu2x.noise = noise; 372 | waifu2x.scale = scale; 373 | waifu2x.tilesize = tilesize; 374 | waifu2x.prepadding = prepadding; 375 | 376 | // main routine 377 | { 378 | if (cb) cb(5, total, NSLocalizedString(@"Initializing pipeline...", @"")); 379 | 380 | // load image 381 | LoadThreadParams ltp; 382 | ltp.scale = scale; 383 | ltp.jobs_load = jobs_load; 384 | ltp.input_files = input_files; 385 | ltp.output_files = output_files; 386 | 387 | ncnn::Thread load_thread(load, (void*)<p); 388 | 389 | // waifu2x proc 390 | ProcThreadParams ptp; 391 | ptp.waifu2x = &waifu2x; 392 | 393 | std::vector proc_threads(jobs_proc); 394 | for (int i=0; i save_threads(jobs_save); 404 | for (int i=0; ijoin(); 425 | delete proc_threads[i]; 426 | } 427 | 428 | 429 | if (cb) cb(8, total, NSLocalizedString(@"Saving image(s)...", @"")); 430 | for (int i=0; ijoin(); 438 | delete save_threads[i]; 439 | } 440 | } 441 | } 442 | 443 | { 444 | const auto& device = ncnn::get_gpu_info(gpuid).physical_device; 445 | VkPhysicalDeviceProperties deviceProperties; 446 | vkGetPhysicalDeviceProperties(device, &deviceProperties); 447 | 448 | VkPhysicalDeviceMemoryProperties deviceMemoryProperties; 449 | VkPhysicalDeviceMemoryBudgetPropertiesEXT budget = { 450 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT 451 | }; 452 | 453 | VkPhysicalDeviceMemoryProperties2 props = { 454 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, 455 | .pNext = &budget, 456 | .memoryProperties = deviceMemoryProperties, 457 | }; 458 | vkGetPhysicalDeviceMemoryProperties2(device, &props); 459 | 460 | double used = budget.heapUsage[0]; 461 | used /= 1024.0 * 1024.0; 462 | 463 | if (usage) *usage = used; 464 | } 465 | 466 | ncnn::destroy_gpu_instance(); 467 | 468 | if (cb) cb(9, total, NSLocalizedString(@"done!", @"")); 469 | 470 | if (is_single_mode) { 471 | result = [[NSImage alloc] initWithContentsOfFile:outputpaths[0]]; 472 | } 473 | 474 | return result; 475 | } 476 | 477 | @end 478 | --------------------------------------------------------------------------------