├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── dictionaries │ └── ncv_dict.xml ├── jarRepositories.xml └── misc.xml ├── LICENSE ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── texture.jpg │ ├── cpp │ ├── CMakeLists.txt │ ├── core │ │ ├── android_permissions.cpp │ │ ├── android_permissions.hpp │ │ └── event_loop.hpp │ ├── devices │ │ ├── accelerometer.cpp │ │ ├── accelerometer.hpp │ │ ├── camera.cpp │ │ ├── camera.hpp │ │ ├── image_reader.cpp │ │ └── image_reader.hpp │ ├── engine │ │ ├── generic.hpp │ │ └── vulkan.hpp │ ├── graphics │ │ ├── complex_context.cpp │ │ ├── complex_context.hpp │ │ ├── data │ │ │ ├── index.hpp │ │ │ ├── model_view_projection.hpp │ │ │ ├── texture.cpp │ │ │ ├── texture.hpp │ │ │ ├── types.hpp │ │ │ └── vertex.hpp │ │ ├── pipeline.cpp │ │ ├── pipeline.hpp │ │ ├── resources │ │ │ ├── base.cpp │ │ │ ├── base.hpp │ │ │ ├── buffer.cpp │ │ │ ├── buffer.hpp │ │ │ ├── image.cpp │ │ │ ├── image.hpp │ │ │ └── types.hpp │ │ ├── simple_context.cpp │ │ ├── simple_context.hpp │ │ ├── vulkan_context.cpp │ │ └── vulkan_context.hpp │ ├── main.cpp │ ├── metadata │ │ ├── version.cpp │ │ ├── version.dat │ │ └── version.hpp │ ├── utilities │ │ ├── helpers.hpp │ │ └── log.hpp │ ├── version.cmake │ └── vk_util │ │ ├── vk_helpers.cpp │ │ ├── vk_helpers.hpp │ │ └── vk_version.hpp │ ├── res │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ ├── drawable │ │ └── ic_launcher_background.xml │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ └── values │ │ └── strings.xml │ └── shaders │ ├── camera-mapping.frag │ ├── image-mapping.frag │ └── simple.vert ├── build.gradle ├── doc └── res │ ├── android-logo.svg │ ├── cpp-logo.svg │ ├── demo.gif │ ├── toc.svg │ └── vulkan-logo.svg ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/assetWizardSettings.xml 45 | .idea/dictionaries/* 46 | !.idea/dictionaries/ncv_dict.xml 47 | .idea/libraries 48 | # Android Studio 3 in .gitignore file. 49 | .idea/caches 50 | .idea/modules.xml 51 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 52 | .idea/navEditor.xml 53 | 54 | # Keystore files 55 | # Uncomment the following lines if you do not want to check your keystore files in. 56 | #*.jks 57 | #*.keystore 58 | 59 | # External native build folder generated in Android Studio 2.2 and later 60 | .externalNativeBuild 61 | .cxx/ 62 | 63 | # Google Services (e.g. APIs or Firebase) 64 | # google-services.json 65 | 66 | # Freeline 67 | freeline.py 68 | freeline/ 69 | freeline_project_description.json 70 | 71 | # fastlane 72 | fastlane/report.xml 73 | fastlane/Preview.html 74 | fastlane/screenshots 75 | fastlane/test_output 76 | fastlane/readme.md 77 | 78 | # Version control 79 | vcs.xml 80 | 81 | # lint 82 | lint/intermediates/ 83 | lint/generated/ 84 | lint/outputs/ 85 | lint/tmp/ 86 | # lint/reports/ 87 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/dictionaries/ncv_dict.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | addr 5 | astr 6 | attribs 7 | autofocus 8 | ccenter 9 | cerr 10 | conv 11 | coords 12 | cout 13 | cright 14 | dbuf 15 | deps 16 | descs 17 | exts 18 | filestream 19 | fmts 20 | fout 21 | framebuffers 22 | framerate 23 | glpipe 24 | hwbuf 25 | imgs 26 | immut 27 | infos 28 | javaless 29 | jstrarray 30 | konstantinos 31 | ktzevani 32 | landroid 33 | lchar 34 | lext 35 | lextension 36 | libvulkan 37 | ljava 38 | loglevel 39 | lstr 40 | marg 41 | maximun 42 | mresult 43 | mtype 44 | multisampling 45 | nativecameravulkan 46 | natproto 47 | npos 48 | opengl 49 | pflag 50 | proc 51 | ptimer 52 | qfam 53 | qfamily 54 | qprops 55 | qret 56 | rchar 57 | readersensor 58 | reqs 59 | rstr 60 | sarg 61 | semver 62 | shaders 63 | sstr 64 | stbi 65 | subpass 66 | suffi 67 | swapchain 68 | terminat 69 | thiz 70 | tzevanidis 71 | tztech 72 | ubos 73 | uint 74 | vbuffer 75 | vert 76 | vkinfo 77 | vuid 78 | vulkan 79 | wdangling 80 | wdst 81 | yaxis 82 | ycbcr 83 | zbuffer 84 | 85 | 86 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 Konstantinos Tzevanidis 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | plugins { 19 | id 'com.android.application' 20 | } 21 | 22 | android { 23 | compileSdkVersion 30 24 | buildToolsVersion "30.0.3" 25 | 26 | ndkVersion "22.0.7026061" 27 | 28 | defaultConfig { 29 | applicationId "com.ktzevani.nativecameravulkan" 30 | 31 | minSdkVersion 26 32 | targetSdkVersion 30 33 | 34 | // ONLY FOR APK PRODUCTION 35 | // Set version numbers manually according to the contents of main/cpp/metadata/version.cpp 36 | 37 | versionCode 2 38 | versionName "0.3.0-7" 39 | 40 | externalNativeBuild { 41 | cmake { 42 | cppFlags "-std=c++17 -frtti -fexceptions" 43 | arguments "-DANDROID_STL=c++_shared" 44 | } 45 | } 46 | } 47 | 48 | buildTypes { 49 | release { 50 | minifyEnabled true 51 | debuggable false 52 | jniDebuggable false 53 | renderscriptDebuggable false 54 | renderscriptOptimLevel 3 55 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 56 | } 57 | } 58 | 59 | externalNativeBuild { 60 | cmake { 61 | path "src/main/cpp/CMakeLists.txt" 62 | version "3.19.2" 63 | } 64 | } 65 | 66 | sourceSets { 67 | main { 68 | jniLibs { 69 | srcDir System.getenv('LIBRARIES_ROOT') + "/vulkan_validation_layers/bin/android-1.2.162" 70 | } 71 | } 72 | } 73 | } 74 | 75 | dependencies { 76 | implementation fileTree(dir: 'libs', include: ['*.jar']) 77 | implementation 'androidx.appcompat:appcompat:1.2.0' 78 | implementation 'androidx.constraintlayout:constraintlayout:2.0.2' 79 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 38 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/assets/texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/assets/texture.jpg -------------------------------------------------------------------------------- /app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 Konstantinos Tzevanidis 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | cmake_minimum_required(VERSION 3.19.2) 18 | 19 | project(native-camera-vulkan) 20 | 21 | set(BUILD_FLAVOR 22 | #"SIMPLE_VULKAN" 23 | "COMPLEX_VULKAN" 24 | ) 25 | 26 | if(BUILD_FLAVOR STREQUAL "SIMPLE_VULKAN") 27 | add_definitions(-DNCV_USE_VULKAN_SIMPLE) 28 | elseif(BUILD_FLAVOR STREQUAL "COMPLEX_VULKAN") 29 | add_definitions(-DNCV_USE_VULKAN_COMPLETE) 30 | endif() 31 | 32 | add_definitions( 33 | -DVK_USE_PLATFORM_ANDROID_KHR #required 34 | -DVK_NO_PROTOTYPES #required 35 | -DNDEBUG 36 | #-DNCV_VULKAN_VALIDATION_ENABLED 37 | #-DNCV_LOGGING_ENABLED 38 | #-DNCV_PROFILING_ENABLED 39 | ) 40 | 41 | add_library(native_app_glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) 42 | 43 | # Export ANativeActivity_onCreate(), 44 | # Refer to: https://github.com/android-ndk/ndk/issues/381. 45 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate") 46 | 47 | set(Project_SOURCES core/*.cpp devices/*.cpp engine/*.cpp vk_util/*.cpp main.cpp) 48 | 49 | if(BUILD_FLAVOR STREQUAL "SIMPLE_VULKAN") 50 | set(Project_SOURCES ${Project_SOURCES} 51 | graphics/simple_context.cpp 52 | graphics/vulkan_context.cpp) 53 | elseif(BUILD_FLAVOR STREQUAL "COMPLEX_VULKAN") 54 | set(Project_SOURCES ${Project_SOURCES} 55 | graphics/data/*.cpp 56 | graphics/resources/*.cpp 57 | graphics/pipeline.cpp 58 | graphics/complex_context.cpp 59 | graphics/vulkan_context.cpp) 60 | endif() 61 | 62 | file(GLOB SOURCES ${Project_SOURCES}) 63 | 64 | add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/metadata/version.cpp 65 | COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/version.cmake 66 | DEPENDS ${SOURCES} 67 | COMMENT "Updating Version" 68 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 69 | 70 | add_library(app_version SHARED ${CMAKE_CURRENT_SOURCE_DIR}/metadata/version.cpp) 71 | add_library(native-camera-vulkan SHARED ${SOURCES}) 72 | 73 | include_directories(${ANDROID_NDK}/sources/android/native_app_glue 74 | $ENV{LIBRARIES_ROOT}/vulkan 75 | $ENV{LIBRARIES_ROOT}/vulkan_hpp 76 | $ENV{LIBRARIES_ROOT}/stb 77 | $ENV{LIBRARIES_ROOT}/glm 78 | .) 79 | 80 | target_link_libraries(native-camera-vulkan 81 | android 82 | dl 83 | native_app_glue 84 | app_version 85 | log 86 | mediandk 87 | camera2ndk) -------------------------------------------------------------------------------- /app/src/main/cpp/core/android_permissions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace ::std; 25 | 26 | static jclass load_java_class(JNIEnv* a_env, jobject a_instance, const string& a_class_name) 27 | { 28 | jclass NativeActivity = a_env->FindClass("android/app/NativeActivity"); 29 | jclass ClassLoader = a_env->FindClass("java/lang/ClassLoader"); 30 | 31 | jmethodID NativeActivity_getClassLoader = 32 | a_env->GetMethodID(NativeActivity, "getClassLoader", "()Ljava/lang/ClassLoader;"); 33 | 34 | jobject ClassLoaderObj = a_env->CallObjectMethod(a_instance, NativeActivity_getClassLoader); 35 | 36 | jmethodID loadClass = 37 | a_env->GetMethodID(ClassLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); 38 | 39 | jstring j_class_name = a_env->NewStringUTF(a_class_name.c_str()); 40 | 41 | return static_cast(a_env->CallObjectMethod(ClassLoaderObj, loadClass, j_class_name)); 42 | } 43 | 44 | namespace core 45 | { 46 | void android_permissions::request_camera_permission(android_app *a_app) 47 | { 48 | auto instance = a_app->activity->clazz; 49 | auto env = a_app->activity->env; 50 | auto vm = a_app->activity->vm; 51 | 52 | if(vm->AttachCurrentThread(&env, nullptr) != JNI_OK) 53 | throw runtime_error("Could not attach thread to running VM."); 54 | 55 | jclass ActivityCompat = load_java_class(env, instance, "androidx/core/app/ActivityCompat"); 56 | 57 | jmethodID ActivityCompat_requestPermissions = 58 | env->GetStaticMethodID(ActivityCompat, "requestPermissions", 59 | "(Landroid/app/Activity;[Ljava/lang/String;I)V"); 60 | 61 | jstring camera_permission = env->NewStringUTF("android.permission.CAMERA"); 62 | jobjectArray perms = env->NewObjectArray(1, env->FindClass("java/lang/String"), nullptr); 63 | env->SetObjectArrayElement(perms, 0, camera_permission); 64 | env->CallStaticVoidMethod(ActivityCompat, ActivityCompat_requestPermissions, instance, perms, 1); 65 | 66 | vm->DetachCurrentThread(); 67 | } 68 | 69 | bool android_permissions::is_camera_permitted(android_app *a_app) 70 | { 71 | auto instance = a_app->activity->clazz; 72 | auto env = a_app->activity->env; 73 | auto vm = a_app->activity->vm; 74 | 75 | if(vm->AttachCurrentThread(&env, nullptr) != JNI_OK) 76 | throw runtime_error("Could not attach thread to running VM."); 77 | 78 | jclass ContextCompat = load_java_class(env, instance, "androidx/core/content/ContextCompat"); 79 | 80 | jmethodID ContextCompat_checkSelfPermission = 81 | env->GetStaticMethodID(ContextCompat, "checkSelfPermission", 82 | "(Landroid/content/Context;Ljava/lang/String;)I"); 83 | 84 | jstring camera_permission = env->NewStringUTF("android.permission.CAMERA"); 85 | jint result = env->CallStaticIntMethod(ContextCompat, ContextCompat_checkSelfPermission, 86 | instance, camera_permission); 87 | 88 | vm->DetachCurrentThread(); 89 | 90 | return result == 0; 91 | } 92 | } -------------------------------------------------------------------------------- /app/src/main/cpp/core/android_permissions.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_ANDROID_PERMISSIONS_HPP 19 | #define NCV_ANDROID_PERMISSIONS_HPP 20 | 21 | class android_app; 22 | 23 | namespace core 24 | { 25 | class android_permissions 26 | { 27 | public: 28 | static bool is_camera_permitted(android_app *a_app); 29 | static void request_camera_permission(android_app *a_app); 30 | }; 31 | } 32 | 33 | #endif //NCV_ANDROID_PERMISSIONS_HPP 34 | -------------------------------------------------------------------------------- /app/src/main/cpp/core/event_loop.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_EVENT_LOOP_HPP 19 | #define NCV_EVENT_LOOP_HPP 20 | 21 | #include 22 | #include 23 | 24 | namespace core 25 | { 26 | template 27 | class event_loop 28 | { 29 | public: 30 | 31 | event_loop(android_app* a_app, std::shared_ptr& a_engine) : 32 | m_app{a_app}, m_engine{a_engine} 33 | { 34 | if constexpr(__ncv_logging_enabled) 35 | _log_android(::utilities::log_level::info) << "Event loop is created."; 36 | } 37 | 38 | ~event_loop() 39 | { 40 | if constexpr(__ncv_logging_enabled) 41 | _log_android(::utilities::log_level::info) << "Destroying event loop..."; 42 | } 43 | 44 | void run() 45 | { 46 | int32_t result; 47 | android_poll_source* source; 48 | 49 | m_app->onAppCmd = T::app_cmd_handler; 50 | m_app->onInputEvent = T::app_input_handler; 51 | 52 | while(true) 53 | { 54 | while((result = ALooper_pollAll(m_engine->is_rendering() ? 0 : -1, nullptr, nullptr, 55 | reinterpret_cast(&source))) >= 0 ) 56 | { 57 | if(source != nullptr) 58 | source->process(m_app, source); 59 | 60 | if(result == LOOPER_ID_USER) 61 | { 62 | if constexpr(__ncv_logging_enabled) 63 | _log_android(::utilities::log_level::verbose) << "Processing devices input..."; 64 | m_engine->process_devices_input(); 65 | } 66 | if(m_app->destroyRequested) 67 | { 68 | if constexpr(__ncv_logging_enabled) 69 | _log_android(::utilities::log_level::info) << "Terminating event loop..."; 70 | return; 71 | } 72 | } 73 | if(m_engine->is_rendering()) 74 | { 75 | if constexpr(__ncv_logging_enabled) 76 | _log_android(::utilities::log_level::verbose) << "Processing application display..."; 77 | m_engine->process_display(); 78 | } 79 | } 80 | } 81 | 82 | private: 83 | 84 | android_app* m_app = nullptr; 85 | std::shared_ptr m_engine; 86 | }; 87 | 88 | } 89 | 90 | #endif //NCV_EVENT_LOOP_HPP -------------------------------------------------------------------------------- /app/src/main/cpp/devices/accelerometer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace ::std; 25 | using namespace ::utilities; 26 | 27 | namespace devices 28 | { 29 | accelerometer::accelerometer(android_app *a_app, const string &a_package_name) 30 | : m_queue{nullptr, [&](ASensorEventQueue* pt){ 31 | ASensorManager_destroyEventQueue(m_manager, pt); 32 | }} 33 | { 34 | m_manager = ASensorManager_getInstanceForPackage(a_package_name.c_str()); 35 | m_sensor = ASensorManager_getDefaultSensor(m_manager, ASENSOR_TYPE_ACCELEROMETER); 36 | m_queue.reset(ASensorManager_createEventQueue(m_manager, a_app->looper, LOOPER_ID_USER, nullptr, nullptr)); 37 | 38 | if constexpr(__ncv_logging_enabled) 39 | _log_android(log_level::info) << "Logical accelerometer created."; 40 | } 41 | 42 | accelerometer::~accelerometer() 43 | { 44 | if constexpr(__ncv_logging_enabled) 45 | _log_android(log_level::info) << "Destroying accelerometer sensor..."; 46 | } 47 | 48 | void accelerometer::disable() 49 | { 50 | m_rate = 0; 51 | ASensorEventQueue_disableSensor(m_queue.get(), m_sensor); 52 | } 53 | 54 | void accelerometer::enable(int32_t a_rate) 55 | { 56 | m_rate = a_rate < 1 ? 1 : (a_rate > max_rate ? max_rate : a_rate); 57 | ASensorEventQueue_enableSensor(m_queue.get(), m_sensor); 58 | ASensorEventQueue_setEventRate(m_queue.get(), m_sensor, 10e6L / a_rate); 59 | } 60 | 61 | glm::vec3 accelerometer::get_acceleration() 62 | { 63 | array events; 64 | int e_count = -1; 65 | 66 | if(m_rate < 1) 67 | return {0.f, 0.f, 0.f}; 68 | 69 | while((e_count = ASensorEventQueue_getEvents(m_queue.get(), events.data(), max_rate - 1)) > 0) 70 | if(e_count < max_rate - 1) 71 | break; 72 | 73 | if(e_count-- < 1) 74 | return {0.f, 0.f, 0.f}; 75 | 76 | if constexpr(__ncv_logging_enabled) 77 | _log_android(log_level::verbose) 78 | << "Accelerometer: x=" << events[e_count].acceleration.x 79 | << " y=" << events[e_count].acceleration.y 80 | << " z=" << events[e_count].acceleration.z; 81 | 82 | return glm::vec3{ 83 | events[e_count].acceleration.x, 84 | events[e_count].acceleration.y, 85 | events[e_count].acceleration.z 86 | }; 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/cpp/devices/accelerometer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_ACCELEROMETER_HPP 19 | #define NCV_ACCELEROMETER_HPP 20 | 21 | #include 22 | #include 23 | 24 | class ASensorEventQueue; 25 | class ASensorManager; 26 | class ASensor; 27 | class android_app; 28 | 29 | namespace devices 30 | { 31 | class accelerometer 32 | { 33 | public: 34 | 35 | using ASensorEventQueue_ptr = std::unique_ptr>; 36 | 37 | constexpr static float g = 9.81f; 38 | constexpr static uint32_t max_rate = 120u; 39 | 40 | explicit accelerometer(android_app* a_app, const std::string& a_package_name); 41 | ~accelerometer(); 42 | 43 | void disable(); 44 | void enable(int32_t a_rate = 60); 45 | glm::vec3 get_acceleration(); 46 | 47 | private: 48 | 49 | ASensorEventQueue_ptr m_queue; 50 | ASensorManager* m_manager = nullptr; 51 | const ASensor* m_sensor = nullptr; 52 | 53 | uint32_t m_rate = 0; 54 | }; 55 | } 56 | 57 | #endif //NCV_ACCELEROMETER_HPP 58 | -------------------------------------------------------------------------------- /app/src/main/cpp/devices/camera.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace ::std; 26 | using namespace ::utilities; 27 | 28 | namespace devices 29 | { 30 | camera::camera(ANativeWindow* a_window) 31 | : m_manager{nullptr, ACameraManager_delete}, 32 | m_ids{nullptr, ACameraManager_deleteCameraIdList}, 33 | m_device{nullptr, ACameraDevice_close}, 34 | m_outputs{nullptr, ACaptureSessionOutputContainer_free}, 35 | m_img_reader_output{nullptr, ACaptureSessionOutput_free}, 36 | m_session{nullptr, ACameraCaptureSession_close}, 37 | m_capture_req{nullptr, ACaptureRequest_free}, 38 | m_target{nullptr, ACameraOutputTarget_free} 39 | { 40 | if(!a_window) 41 | throw runtime_error("Invalid window handle."); 42 | 43 | m_manager.reset(ACameraManager_create()); 44 | 45 | if(!m_manager.get()) 46 | throw runtime_error("Cannot create camera manager."); 47 | 48 | auto pt = m_ids.release(); 49 | auto result = ACameraManager_getCameraIdList(m_manager.get(), &pt); 50 | m_ids.reset(pt); 51 | 52 | if(result != ACAMERA_OK) 53 | { 54 | stringstream sstr; 55 | sstr << "Failed to acquire camera list. (code: " << result << ")."; 56 | throw runtime_error(sstr.str().c_str()); 57 | } 58 | 59 | if(m_ids->numCameras < 1) 60 | throw runtime_error("No cameras found."); 61 | 62 | string selected_camera; 63 | 64 | for(uint32_t i = 0; i < m_ids->numCameras; ++i) 65 | { 66 | auto cam_id = m_ids->cameraIds[i]; 67 | ACameraMetadata* metadata = nullptr; 68 | result = ACameraManager_getCameraCharacteristics(m_manager.get(), cam_id, &metadata); 69 | if(result != ACAMERA_OK || !metadata) 70 | continue; 71 | ACameraMetadata_const_entry entry; 72 | if(ACameraMetadata_getConstEntry(metadata, ACAMERA_LENS_FACING, &entry) == ACAMERA_OK) 73 | { 74 | auto facing = static_cast(entry.data.u8[0]); 75 | 76 | // Select which camera to use (front or back) 77 | 78 | if(facing == ACAMERA_LENS_FACING_BACK) 79 | selected_camera = string(cam_id); 80 | } 81 | ACameraMetadata_free(metadata); 82 | } 83 | 84 | if(selected_camera.size() < 1) 85 | throw runtime_error("Cannot find appropriate device."); 86 | 87 | { 88 | auto pt = m_device.release(); 89 | result = ACameraManager_openCamera(m_manager.get(), selected_camera.c_str(), 90 | &m_dev_state_cbs, &pt); 91 | m_device.reset(pt); 92 | } 93 | 94 | if(result != ACAMERA_OK || !m_device.get()) 95 | { 96 | stringstream sstr; 97 | sstr << "Couldn't open camera. (code: " << result << ")."; 98 | throw runtime_error(sstr.str()); 99 | } 100 | 101 | { 102 | auto pt = m_outputs.release(); 103 | result = ACaptureSessionOutputContainer_create(&pt); 104 | m_outputs.reset(pt); 105 | } 106 | 107 | if(result != ACAMERA_OK) 108 | throw runtime_error("Capture session output container creation failed."); 109 | 110 | { 111 | auto pt = m_img_reader_output.release(); 112 | result = ACaptureSessionOutput_create(a_window, &pt); 113 | m_img_reader_output.reset(pt); 114 | } 115 | 116 | if(result != ACAMERA_OK) 117 | throw runtime_error("Capture session image reader output creation failed."); 118 | 119 | result = ACaptureSessionOutputContainer_add(m_outputs.get(), m_img_reader_output.get()); 120 | 121 | if(result != ACAMERA_OK) 122 | throw runtime_error("Couldn't add image reader output session to container."); 123 | 124 | { 125 | auto pt = m_session.release(); 126 | result = ACameraDevice_createCaptureSession(m_device.get(), m_outputs.get(), 127 | &m_cap_state_cbs, &pt); 128 | m_session.reset(pt); 129 | } 130 | 131 | if(result != ACAMERA_OK) 132 | throw runtime_error("Couldn't create capture session."); 133 | 134 | { 135 | auto pt = m_capture_req.release(); 136 | result = ACameraDevice_createCaptureRequest(m_device.get(), TEMPLATE_PREVIEW, &pt); 137 | m_capture_req.reset(pt); 138 | } 139 | 140 | if(result != ACAMERA_OK) 141 | throw runtime_error("Couldn't create capture request."); 142 | 143 | { 144 | auto pt = m_target.release(); 145 | result = ACameraOutputTarget_create(a_window, &pt); 146 | m_target.reset(pt); 147 | } 148 | 149 | if(result != ACAMERA_OK) 150 | throw runtime_error("Couldn't create camera output target."); 151 | 152 | result = ACaptureRequest_addTarget(m_capture_req.get(), m_target.get()); 153 | 154 | if(result != ACAMERA_OK) 155 | throw runtime_error("Couldn't add capture request to camera output target."); 156 | 157 | if constexpr(__ncv_logging_enabled) 158 | _log_android(log_level::info) << "Camera logical device created."; 159 | } 160 | 161 | camera::~camera() 162 | { 163 | if constexpr(__ncv_logging_enabled) 164 | _log_android(log_level::info) << "Destroying camera device..."; 165 | } 166 | 167 | void camera::start_capturing() 168 | { 169 | auto pt = m_capture_req.release(); 170 | ACameraCaptureSession_setRepeatingRequest(m_session.get(), nullptr, 1, &pt, nullptr); 171 | m_capture_req.reset(pt); 172 | } 173 | 174 | void camera::stop_capturing() 175 | { 176 | ACameraCaptureSession_stopRepeating(m_session.get()); 177 | } 178 | } -------------------------------------------------------------------------------- /app/src/main/cpp/devices/camera.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_CAMERA_HPP 19 | #define NCV_CAMERA_HPP 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | namespace devices 30 | { 31 | class camera 32 | { 33 | public: 34 | 35 | using ACameraManager_ptr = std::unique_ptr; 36 | using ACameraIdList_ptr = std::unique_ptr; 37 | using ACameraDevice_ptr = std::unique_ptr; 38 | using ACaptureSessionOutputContainer_ptr = 39 | std::unique_ptr; 40 | using ACaptureSessionOutput_ptr = 41 | std::unique_ptr; 42 | using ACameraCaptureSession_ptr = 43 | std::unique_ptr; 44 | using ACaptureRequest_ptr = std::unique_ptr; 45 | using ACameraOutputTarget_ptr = 46 | std::unique_ptr; 47 | 48 | camera(ANativeWindow* a_window); 49 | ~camera(); 50 | 51 | void start_capturing(); 52 | void stop_capturing(); 53 | 54 | static void on_device_disconnected(void* a_obj, ACameraDevice* a_device) 55 | {} 56 | 57 | static void on_device_error(void* a_obj, ACameraDevice* a_device, int a_err_code) 58 | {} 59 | 60 | static void on_session_closed(void* a_obj, ACameraCaptureSession* a_session) 61 | {} 62 | 63 | static void on_session_ready(void* a_obj, ACameraCaptureSession* a_session) 64 | {} 65 | 66 | static void on_session_active(void* a_obj, ACameraCaptureSession* a_session) 67 | {} 68 | 69 | private: 70 | 71 | ACameraDevice_stateCallbacks m_dev_state_cbs 72 | { 73 | this, 74 | on_device_disconnected, 75 | on_device_error 76 | }; 77 | 78 | ACameraCaptureSession_stateCallbacks m_cap_state_cbs 79 | { 80 | this, 81 | on_session_closed, 82 | on_session_ready, 83 | on_session_active 84 | }; 85 | 86 | ACameraManager_ptr m_manager; 87 | ACameraIdList_ptr m_ids; 88 | ACameraDevice_ptr m_device; 89 | ACaptureSessionOutputContainer_ptr m_outputs; 90 | ACaptureSessionOutput_ptr m_img_reader_output; 91 | ACameraCaptureSession_ptr m_session; 92 | ACaptureRequest_ptr m_capture_req; 93 | ACameraOutputTarget_ptr m_target; 94 | }; 95 | 96 | } 97 | 98 | #endif //NCV_CAMERA_HPP 99 | -------------------------------------------------------------------------------- /app/src/main/cpp/devices/image_reader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | using namespace ::std; 22 | using namespace ::utilities; 23 | 24 | namespace devices 25 | { 26 | image_reader::image_reader(uint32_t a_width, uint32_t a_height, uint32_t a_format, uint64_t a_usage, 27 | uint32_t a_max_images) 28 | : m_cur_index{a_max_images-1}, m_reader{nullptr, AImageReader_delete} 29 | { 30 | if(a_max_images < 2) 31 | throw runtime_error("Max images must be at least 2."); 32 | 33 | for(uint32_t i = 0; i < a_max_images; ++i) 34 | m_images.push_back({nullptr, AImage_delete}); 35 | 36 | m_buffers = vector(a_max_images, nullptr); 37 | 38 | auto pt = m_reader.release(); 39 | AImageReader_newWithUsage(a_width, a_height, a_format, a_usage, m_images.size()+2, &pt); 40 | m_reader.reset(pt); 41 | 42 | if(!m_reader) 43 | throw runtime_error("Failed to create image reader."); 44 | 45 | auto result = AImageReader_getWindow(m_reader.get(), &m_window); 46 | 47 | if (result != AMEDIA_OK || m_window == nullptr) 48 | throw runtime_error("Failed to obtain window handle."); 49 | 50 | if constexpr(__ncv_logging_enabled) 51 | _log_android(log_level::info) << "Image reader created."; 52 | } 53 | 54 | image_reader::~image_reader() 55 | { 56 | if constexpr(__ncv_logging_enabled) 57 | _log_android(log_level::info) << "Destroying image reader..."; 58 | } 59 | 60 | AHardwareBuffer * image_reader::get_latest_buffer() 61 | { 62 | AImage *image = nullptr; 63 | auto result = AImageReader_acquireLatestImage(m_reader.get(), &image); 64 | if(result != AMEDIA_OK || !image) 65 | { 66 | if constexpr(__ncv_logging_enabled) 67 | _log_android(log_level::verbose) << "Failed to acquire image from camera."; 68 | } 69 | else 70 | { 71 | AHardwareBuffer* buffer = nullptr; 72 | auto result = AImage_getHardwareBuffer(image, &buffer); 73 | if(result != AMEDIA_OK || !buffer) 74 | { 75 | if constexpr(__ncv_logging_enabled) 76 | _log_android(log_level::verbose) << "Failed to acquire hardware buffer."; 77 | } 78 | else 79 | { 80 | m_cur_index++; 81 | if(m_cur_index == m_images.size()) 82 | m_cur_index = 0; 83 | m_images[m_cur_index].reset(image); 84 | m_buffers[m_cur_index] = buffer; 85 | } 86 | } 87 | 88 | return m_buffers[m_cur_index]; 89 | } 90 | 91 | ANativeWindow * image_reader::get_window() const 92 | { 93 | return m_window; 94 | } 95 | } -------------------------------------------------------------------------------- /app/src/main/cpp/devices/image_reader.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_IMAGE_READER_HPP 19 | #define NCV_IMAGE_READER_HPP 20 | 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | namespace devices 27 | { 28 | class image_reader 29 | { 30 | public: 31 | 32 | using image_ptr = std::unique_ptr; 33 | using img_reader_ptr = std::unique_ptr; 34 | 35 | image_reader(uint32_t a_width, uint32_t a_height, uint32_t a_format, uint64_t a_usage, 36 | uint32_t a_max_images); 37 | 38 | ~image_reader(); 39 | 40 | AHardwareBuffer* get_latest_buffer(); 41 | ANativeWindow* get_window() const; 42 | 43 | private: 44 | 45 | uint32_t m_cur_index; 46 | ANativeWindow* m_window = nullptr; 47 | std::vector m_buffers; 48 | 49 | img_reader_ptr m_reader; 50 | std::vector m_images; 51 | }; 52 | } 53 | 54 | #endif // NCV_IMAGE_READER_HPP -------------------------------------------------------------------------------- /app/src/main/cpp/engine/generic.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_GENERIC_HPP 19 | #define NCV_GENERIC_HPP 20 | 21 | #include 22 | 23 | class android_app; 24 | class AInputEvent; 25 | 26 | namespace engine 27 | { 28 | template 29 | class generic 30 | { 31 | public: 32 | 33 | generic(const std::string& a_package_name, const std::string& a_app_name, uint32_t a_app_version) 34 | : m_package_name{a_package_name}, m_app_name{a_app_name}, m_app_version{a_app_version} 35 | { 36 | if constexpr(__ncv_logging_enabled) 37 | { 38 | _log_android(::utilities::log_level::debug) << "Generic engine has been initialized."; 39 | } 40 | } 41 | 42 | virtual ~generic() 43 | { 44 | if constexpr(__ncv_logging_enabled) 45 | _log_android(::utilities::log_level::debug) << "Destroying generic engine..."; 46 | }; 47 | 48 | virtual void process_devices_input() = 0; 49 | virtual void process_display() = 0; 50 | 51 | bool is_rendering() const 52 | { 53 | return m_rendering; 54 | } 55 | 56 | static void app_cmd_handler(android_app* a_app, int32_t a_cmd) 57 | { 58 | T::_app_cmd_handler(a_app, a_cmd); 59 | } 60 | 61 | static int32_t app_input_handler(android_app* a_app, AInputEvent* a_event) 62 | { 63 | return T::_app_input_handler(a_app, a_event); 64 | } 65 | 66 | protected: 67 | 68 | virtual void start_engine() = 0; 69 | virtual void stop_engine() = 0; 70 | 71 | const std::string m_package_name, m_app_name; 72 | const uint32_t m_app_version; 73 | 74 | android_app* m_app = nullptr; 75 | bool m_rendering = false; 76 | bool m_cam_permission = false; 77 | }; 78 | 79 | } 80 | 81 | #endif //NCV_GENERIC_HPP 82 | -------------------------------------------------------------------------------- /app/src/main/cpp/engine/vulkan.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_VULKAN_HPP 19 | #define NCV_VULKAN_HPP 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace graphics 31 | { 32 | class simple_context; 33 | class complex_context; 34 | } 35 | 36 | namespace engine 37 | { 38 | template 39 | class vulkan: public generic> 40 | { 41 | public: 42 | 43 | typedef struct 44 | { 45 | glm::vec<2, uint32_t> screen_size; 46 | glm::vec2 touch_pos; 47 | glm::vec4 back_color; 48 | } data; 49 | 50 | vulkan(android_app* a_app, const std::string& a_package_name, const std::string& a_app_name, 51 | uint32_t a_app_version); 52 | ~vulkan(); 53 | void process_devices_input(); 54 | void process_display(); 55 | static void _app_cmd_handler(android_app* a_app, int32_t a_cmd); 56 | static int32_t _app_input_handler(android_app* a_app, AInputEvent* a_event); 57 | 58 | private: 59 | 60 | void start_engine(); 61 | void stop_engine() noexcept; 62 | 63 | static std::chrono::time_point m_time_pt; 64 | uint64_t m_frames_processed = 0; 65 | 66 | data m_state = {{0u, 0u}, {0.f, 0.f}, {1.f, 1.f, 1.f, 1.f}}; 67 | 68 | T m_context; 69 | 70 | std::shared_ptr<::devices::accelerometer> m_accelerometer; 71 | std::shared_ptr<::devices::image_reader> m_img_reader; 72 | std::shared_ptr<::devices::camera> m_camera; 73 | }; 74 | 75 | template 76 | inline vulkan::vulkan(android_app *a_app, const std::string &a_package_name, 77 | const std::string &a_app_name, uint32_t a_app_version) 78 | : generic{a_package_name, a_app_name, a_app_version}, 79 | m_context{a_app_name} 80 | { 81 | // Register application context both ways 82 | 83 | this->m_app = a_app; 84 | a_app->userData = this; 85 | 86 | if constexpr(__ncv_logging_enabled) 87 | _log_android(::utilities::log_level::info) << "Vulkan engine has been initialized."; 88 | } 89 | 90 | template 91 | inline vulkan::~vulkan() 92 | { 93 | if constexpr(__ncv_logging_enabled) 94 | _log_android(::utilities::log_level::info) << "Destroying vulkan engine..."; 95 | } 96 | 97 | template 98 | inline void vulkan::process_devices_input() 99 | { 100 | using ::devices::accelerometer; 101 | 102 | if(!this->m_rendering) 103 | return; 104 | 105 | int32_t c = floorf(((m_state.touch_pos.x * m_state.touch_pos.y) / 106 | (m_state.screen_size.s * m_state.screen_size.t)) * 65535.f); 107 | 108 | c = c > 0xffff ? 0xffff : c; 109 | 110 | m_state.back_color = { 111 | ((c & 0xff00) >> 8) / 255.f, 112 | (c & 0xff) / 255.f, 113 | powf((accelerometer::g - fabsf(m_accelerometer->get_acceleration().y)) / accelerometer::g, 2.0f), 114 | 1.f 115 | }; 116 | 117 | if constexpr(__ncv_logging_enabled) 118 | _log_android(::utilities::log_level::verbose) << "Devices input has been processed."; 119 | } 120 | 121 | template 122 | inline void vulkan::process_display() 123 | { 124 | using std::chrono::nanoseconds; 125 | using std::chrono::high_resolution_clock; 126 | using std::chrono::duration_cast; 127 | 128 | if constexpr(__ncv_profiling_enabled) 129 | { 130 | if constexpr(std::is_same()) 131 | if(this->m_cam_permission) 132 | m_context.render_frame(m_state.back_color, m_img_reader->get_latest_buffer()); 133 | else 134 | m_context.render_frame(m_state.back_color); 135 | else if constexpr(std::is_same()) 136 | m_context.render_frame(m_state.back_color); 137 | m_frames_processed++; 138 | auto ns = duration_cast(high_resolution_clock::now() - m_time_pt); 139 | _log_android(::utilities::log_level::verbose) << "Rate of processed frames: " 140 | << m_frames_processed / (ns.count() / 1e+9) << " Hz"; 141 | } 142 | else 143 | { 144 | if constexpr(std::is_same()) 145 | if(this->m_cam_permission) 146 | m_context.render_frame(m_state.back_color, m_img_reader->get_latest_buffer()); 147 | else 148 | m_context.render_frame(m_state.back_color); 149 | else if constexpr(std::is_same()) 150 | m_context.render_frame(m_state.back_color); 151 | } 152 | 153 | if constexpr(__ncv_logging_enabled) 154 | _log_android(::utilities::log_level::verbose) << "Display has been processed."; 155 | } 156 | 157 | template 158 | inline void vulkan::_app_cmd_handler(android_app *a_app, int32_t a_cmd) 159 | { 160 | vulkan *engine = reinterpret_cast(a_app->userData); 161 | ::core::android_permissions permissions; 162 | 163 | switch (a_cmd) 164 | { 165 | case APP_CMD_SAVE_STATE: 166 | engine->m_app->savedState = malloc(sizeof(data)); 167 | *reinterpret_cast(engine->m_app->savedState) = engine->m_state; 168 | engine->m_app->savedStateSize = sizeof(data); 169 | break; 170 | case APP_CMD_INIT_WINDOW: 171 | if(engine->m_state.screen_size.s == 0u) 172 | engine->m_state.screen_size = { 173 | ANativeWindow_getWidth(engine->m_app->window), 174 | ANativeWindow_getHeight(engine->m_app->window) 175 | }; 176 | break; 177 | case APP_CMD_GAINED_FOCUS: 178 | engine->m_cam_permission = permissions.is_camera_permitted(engine->m_app); 179 | engine->start_engine(); 180 | break; 181 | case APP_CMD_TERM_WINDOW: 182 | engine->stop_engine(); 183 | break; 184 | default: 185 | break; 186 | } 187 | 188 | if constexpr(__ncv_logging_enabled) 189 | _log_android(::utilities::log_level::verbose) 190 | << "Application command (code: " << a_cmd << ") is processed."; 191 | } 192 | 193 | template 194 | inline int32_t vulkan::_app_input_handler(android_app *a_app, AInputEvent *a_event) 195 | { 196 | vulkan *engine = reinterpret_cast(a_app->userData); 197 | int32_t result = 0; 198 | auto e_type = AInputEvent_getType(a_event); 199 | 200 | if (e_type == AINPUT_EVENT_TYPE_MOTION) 201 | { 202 | engine->m_state.touch_pos = { 203 | AMotionEvent_getX(a_event, 0), 204 | AMotionEvent_getY(a_event, 0) 205 | }; 206 | 207 | result = 1; 208 | } 209 | 210 | if constexpr(__ncv_logging_enabled) 211 | { 212 | if (e_type != AINPUT_EVENT_TYPE_MOTION) 213 | _log_android(::utilities::log_level::verbose) << "Input processed (event: " 214 | << e_type << ")"; 215 | else 216 | _log_android(::utilities::log_level::verbose) 217 | << "Input processed (event: " << e_type << ", " << " data: " 218 | << "{x=" << engine->m_state.touch_pos.x << ", y=" 219 | << engine->m_state.touch_pos.y << "})."; 220 | } 221 | 222 | return result; 223 | } 224 | 225 | template 226 | inline void vulkan::start_engine() 227 | { 228 | using namespace ::devices; 229 | 230 | // Initialize camera and image reader 231 | 232 | m_accelerometer = std::make_shared(this->m_app, this->m_package_name); 233 | 234 | if constexpr(std::is_same()) 235 | { 236 | if(this->m_cam_permission) 237 | { 238 | m_img_reader = std::make_shared(m_state.screen_size.s, m_state.screen_size.t, 239 | AIMAGE_FORMAT_PRIVATE, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE, 4); 240 | m_camera = std::make_shared(m_img_reader->get_window()); 241 | m_camera->start_capturing(); 242 | 243 | while (!m_img_reader->get_latest_buffer()) 244 | usleep(10000u); 245 | } 246 | } 247 | 248 | // Reset framerate counters 249 | 250 | if constexpr(__ncv_profiling_enabled) 251 | { 252 | m_time_pt = std::chrono::high_resolution_clock::now(); 253 | m_frames_processed = 0; 254 | } 255 | 256 | // Initialize graphics 257 | 258 | if constexpr(std::is_same()) 259 | { 260 | if(this->m_cam_permission) 261 | m_context.initialize_graphics(this->m_app, m_img_reader->get_latest_buffer()); 262 | else 263 | m_context.initialize_graphics(this->m_app); 264 | } 265 | else if constexpr(std::is_same()) 266 | { 267 | m_context.initialize_graphics(this->m_app); 268 | } 269 | 270 | this->m_rendering = true; 271 | 272 | m_accelerometer->enable(); 273 | 274 | if constexpr(__ncv_logging_enabled) 275 | _log_android(::utilities::log_level::info) << "Vulkan engine has been started."; 276 | } 277 | 278 | template 279 | inline void vulkan::stop_engine() noexcept 280 | { 281 | if constexpr(std::is_same()) 282 | if(this->m_cam_permission) 283 | m_camera->stop_capturing(); 284 | this->m_rendering = false; 285 | m_accelerometer->disable(); 286 | if constexpr(std::is_same()) 287 | { 288 | m_camera.reset(); 289 | m_img_reader.reset(); 290 | } 291 | m_accelerometer.reset(); 292 | if constexpr(__ncv_logging_enabled) 293 | _log_android(::utilities::log_level::info) << "Vulkan engine has been stopped."; 294 | return; 295 | } 296 | 297 | template 298 | std::chrono::time_point vulkan::m_time_pt = 299 | std::chrono::high_resolution_clock::now(); 300 | } 301 | 302 | #endif //NCV_VULKAN_HPP 303 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/data/index.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_INDEX_HPP 19 | #define NCV_INDEX_HPP 20 | 21 | #include 22 | #include 23 | 24 | namespace graphics { namespace data { 25 | static const std::vector index_set = std::vector 26 | { 27 | 0, 1, 2, 2, 3, 0, 28 | 7, 5, 4, 7, 6, 5, 29 | 8, 9, 10, 10, 11, 8, 30 | 12, 13, 14, 14, 15, 12, 31 | 16, 17, 18, 18, 19, 16, 32 | 20, 21, 22, 22, 23, 20 33 | }; 34 | }} 35 | 36 | #endif //NCV_INDEX_HPP 37 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/data/model_view_projection.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_MODEL_VIEW_PROJECTION_HPP 19 | #define NCV_MODEL_VIEW_PROJECTION_HPP 20 | 21 | #define GLM_FORCE_RADIANS 22 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace graphics{ namespace data{ 29 | struct model_view_projection 30 | { 31 | model_view_projection(float a_screen_ratio) 32 | { 33 | m_model = rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 0.0f, 1.0f)) * 34 | scale(glm::mat4(1.0f), glm::vec3(0.325f, 0.325f, 0.325f)); 35 | m_view = lookAt(glm::vec3(0.0f, 0.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), 36 | glm::vec3(0.0f, 1.0f, 0.0f)); 37 | m_projection = glm::perspective(glm::radians(45.0f), a_screen_ratio, 0.1f, 10.0f); 38 | m_projection[1][1] *= -1; 39 | } 40 | 41 | void set_camera_y(float a_yaxis) 42 | { 43 | m_view = lookAt(glm::vec3(0.0f, 0.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), 44 | glm::vec3(0.0f, a_yaxis, 0.0f)); 45 | } 46 | 47 | void rotate_view(std::chrono::time_point& ref_time) 48 | { 49 | auto cur_time = std::chrono::high_resolution_clock::now(); 50 | auto time_elapsed = std::chrono::duration_cast(cur_time - ref_time); 51 | auto angle = (static_cast(time_elapsed.count() % 3600000000) / 3.6e+9f) * 360.0f; 52 | 53 | m_model = 54 | translate(glm::mat4(1.0f), glm::vec3(0.04f, 0.0f, 0.0f)) * 55 | rotate(glm::mat4(1.0f), glm::radians(28.0f), glm::vec3(0.0f, -1.0f, 0.0f)) * 56 | rotate(glm::mat4(1.0f), glm::radians(angle), glm::vec3(1.0f, 0.0f, 0.0f)) * 57 | rotate(glm::mat4(1.0f), glm::radians(-90.0f), glm::vec3(0.0f, 0.0f, 1.0f)) * 58 | scale(glm::mat4(1.0f), glm::vec3(0.325f, 0.325f, 0.325f)); 59 | } 60 | 61 | glm::mat4 m_model; 62 | glm::mat4 m_view; 63 | glm::mat4 m_projection; 64 | }; 65 | }} 66 | 67 | #endif //NCV_MODEL_VIEW_PROJECTION_HPP 68 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/data/texture.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | #define STB_IMAGE_IMPLEMENTATION 21 | 22 | #include 23 | #include 24 | 25 | namespace graphics{ namespace data{ 26 | 27 | texture::texture(AAssetManager *a_ass_mgr, const std::string &a_filename) 28 | { 29 | AAsset* file = AAssetManager_open(a_ass_mgr, a_filename.c_str(), AASSET_MODE_BUFFER); 30 | 31 | if(!file) 32 | throw std::runtime_error{"Unknown error. Couldn't open texture file."}; 33 | 34 | auto file_data = std::vector(AAsset_getLength(file)); 35 | 36 | if(AAsset_read(file, file_data.data(), file_data.size()) != file_data.size()) 37 | { 38 | AAsset_close(file); 39 | throw std::runtime_error{"Unknown error. Couldn't read from texture file."}; 40 | } 41 | 42 | AAsset_close(file); 43 | 44 | int tex_width, tex_height, tex_channels; 45 | 46 | auto cvt_data = stbi_load_from_memory(file_data.data(), file_data.size(), &tex_height, &tex_width, 47 | &tex_channels, STBI_rgb_alpha); 48 | 49 | if(!cvt_data) 50 | throw std::runtime_error{"Could not convert loaded texture."}; 51 | 52 | m_extent = {static_cast(tex_width), static_cast(tex_height), 1}; 53 | 54 | m_data.resize(tex_width * tex_height * 4); 55 | 56 | memcpy(m_data.data(), cvt_data, m_data.size()); 57 | 58 | stbi_image_free(cvt_data); 59 | } 60 | 61 | }} -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/data/texture.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_TEXTURE_HPP 19 | #define NCV_TEXTURE_HPP 20 | 21 | #include 22 | #include 23 | 24 | class AAssetManager; 25 | 26 | namespace graphics{ namespace data{ 27 | 28 | class texture 29 | { 30 | public: 31 | typedef unsigned char stbi_uc; 32 | typedef struct 33 | { 34 | uint32_t width; 35 | uint32_t height; 36 | uint32_t depth; 37 | } extent3d; 38 | 39 | texture(AAssetManager* a_ass_mgr, const std::string& a_filename); 40 | std::vector& get_data() { return m_data; } 41 | extent3d get_extent() { return m_extent; } 42 | private: 43 | std::vector m_data; 44 | extent3d m_extent; 45 | }; 46 | 47 | }} 48 | 49 | #endif //NCV_TEXTURE_HPP 50 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/data/types.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_DATA_TYPES_HPP 19 | #define NCV_DATA_TYPES_HPP 20 | 21 | #include 22 | 23 | namespace graphics { namespace data { 24 | typedef uint16_t index_format; 25 | class model_view_projection; 26 | class vertex_format; 27 | class texture; 28 | typedef unsigned char stbi_uc; 29 | }} 30 | 31 | #endif //NCV_DATA_TYPES_HPP 32 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/data/vertex.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_VERTEX_HPP 19 | #define NCV_VERTEX_HPP 20 | 21 | #include 22 | #include 23 | 24 | namespace graphics{ namespace data{ 25 | struct vertex_format 26 | { 27 | glm::vec4 position; 28 | glm::vec4 color; 29 | glm::vec2 tex_coords; 30 | }; 31 | 32 | static const std::vector vertex_set = std::vector 33 | { 34 | {{-1.0f, 1.0f, 1.0f, 1.0f}, {1.f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}, 35 | {{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, 36 | {{1.0f, -1.0f, 1.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, 37 | {{-1.0f, -1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, 38 | 39 | {{-1.0f, 1.0f, -1.0f, 1.0f}, {1.f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}}, 40 | {{1.0f, 1.0f, -1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, 41 | {{1.0f, -1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, 42 | {{-1.0f, -1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, 43 | 44 | {{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, 45 | {{1.0f, 1.0f, -1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, 46 | {{1.0f, -1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, 47 | {{1.0f, -1.0f, 1.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, 48 | 49 | {{-1.0f, 1.0f, -1.0f, 1.0f}, {1.f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}, 50 | {{-1.0f, 1.0f, 1.0f, 1.0f}, {1.f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}}, 51 | {{-1.0f, -1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, 52 | {{-1.0f, -1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, 53 | 54 | {{-1.0f, 1.0f, -1.0f, 1.0f}, {1.f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}}, 55 | {{1.0f, 1.0f, -1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, 56 | {{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, 57 | {{-1.0f, 1.0f, 1.0f, 1.0f}, {1.f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}, 58 | 59 | {{-1.0f, -1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f}}, 60 | {{1.0f, -1.0f, 1.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, 61 | {{1.0f, -1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, 62 | {{-1.0f, -1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.0f}} 63 | }; 64 | }} 65 | 66 | #endif //NCV_VERTEX_HPP 67 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/pipeline.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace ::std; 24 | using namespace ::vk; 25 | using namespace ::utilities; 26 | 27 | namespace graphics 28 | { 29 | pipeline::pipeline(const parameters &a_params, const shaders_info &a_shaders_info) 30 | : m_params{a_params}, m_shaders_info{a_shaders_info} 31 | { 32 | AAsset* file = AAssetManager_open(m_params.ass_mgr, 33 | ("shaders/" + m_shaders_info.vert_filename + ".spv").c_str(), AASSET_MODE_BUFFER); 34 | 35 | if(!file) 36 | throw runtime_error{"Unknown error. Couldn't open shader file."}; 37 | 38 | vector file_contents(AAsset_getLength(file)); 39 | 40 | if(AAsset_read(file, file_contents.data(), file_contents.size()) != file_contents.size()) 41 | { 42 | AAsset_close(file); 43 | throw runtime_error{"Unknown error. Couldn't load shader file contents."}; 44 | } 45 | 46 | ShaderModuleCreateInfo shader_info; 47 | 48 | shader_info.codeSize = file_contents.size(); 49 | shader_info.pCode = reinterpret_cast(file_contents.data()); 50 | 51 | m_vertex_shader = m_params.device.createShaderModule(shader_info); 52 | 53 | AAsset_close(file); 54 | 55 | file = AAssetManager_open(m_params.ass_mgr, 56 | ("shaders/" + m_shaders_info.frag_filename + ".spv").c_str(), AASSET_MODE_BUFFER); 57 | 58 | if(!file) 59 | throw runtime_error{"Unknown error. Couldn't open shader file."}; 60 | 61 | file_contents.resize(AAsset_getLength(file)); 62 | 63 | if(AAsset_read(file, file_contents.data(), file_contents.size()) != file_contents.size()) 64 | { 65 | AAsset_close(file); 66 | throw runtime_error{"Unknown error. Couldn't load shader file contents."}; 67 | } 68 | 69 | shader_info.codeSize = file_contents.size(); 70 | shader_info.pCode = reinterpret_cast(file_contents.data()); 71 | 72 | m_fragment_shader = m_params.device.createShaderModule(shader_info); 73 | 74 | AAsset_close(file); 75 | 76 | if constexpr(__ncv_logging_enabled) 77 | _log_android(log_level::info) << "Shaders loaded with success, shader modules created."; 78 | 79 | // Shaders stage creation info 80 | 81 | PipelineShaderStageCreateInfo vertex_shader_stage_info; 82 | PipelineShaderStageCreateInfo fragment_shader_stage_info; 83 | 84 | vertex_shader_stage_info.stage = ShaderStageFlagBits::eVertex; 85 | vertex_shader_stage_info.module = m_vertex_shader; 86 | vertex_shader_stage_info.pName = "main"; 87 | 88 | fragment_shader_stage_info.stage = ShaderStageFlagBits::eFragment; 89 | fragment_shader_stage_info.module = m_fragment_shader; 90 | fragment_shader_stage_info.pName = "main"; 91 | 92 | vector shader_stages_info; 93 | 94 | shader_stages_info.push_back(vertex_shader_stage_info); 95 | shader_stages_info.push_back(fragment_shader_stage_info); 96 | 97 | // Acquire vertex-related information (Input and Assembly) 98 | 99 | vector bind_descs; 100 | vector attr_descs; 101 | 102 | VertexInputBindingDescription vertex_bind_desc; 103 | 104 | vertex_bind_desc.binding = 0; 105 | vertex_bind_desc.stride = sizeof(data::vertex_format); 106 | vertex_bind_desc.inputRate = VertexInputRate::eVertex; 107 | 108 | bind_descs.push_back(vertex_bind_desc); 109 | 110 | VertexInputAttributeDescription vertex_geom_desc; 111 | 112 | vertex_geom_desc.location = 0; 113 | vertex_geom_desc.binding = vertex_bind_desc.binding; 114 | vertex_geom_desc.format = Format::eR32G32B32A32Sfloat; 115 | vertex_geom_desc.offset = offsetof(data::vertex_format, position); 116 | 117 | VertexInputAttributeDescription vertex_color_desc; 118 | 119 | vertex_color_desc.location = 1; 120 | vertex_color_desc.binding = vertex_bind_desc.binding; 121 | vertex_color_desc.format = Format::eR32G32B32A32Sfloat; 122 | vertex_color_desc.offset = offsetof(data::vertex_format, color); 123 | 124 | VertexInputAttributeDescription vertex_tex_coords; 125 | 126 | vertex_tex_coords.location = 2; 127 | vertex_tex_coords.binding = vertex_bind_desc.binding; 128 | vertex_tex_coords.format = Format::eR32G32Sfloat; 129 | vertex_tex_coords.offset = offsetof(data::vertex_format, tex_coords); 130 | 131 | attr_descs.push_back(vertex_geom_desc); 132 | attr_descs.push_back(vertex_color_desc); 133 | attr_descs.push_back(vertex_tex_coords); 134 | 135 | PipelineVertexInputStateCreateInfo vertex_input_info; 136 | 137 | vertex_input_info.vertexBindingDescriptionCount = bind_descs.size(); 138 | vertex_input_info.vertexAttributeDescriptionCount = attr_descs.size(); 139 | vertex_input_info.pVertexBindingDescriptions = bind_descs.data(); 140 | vertex_input_info.pVertexAttributeDescriptions = attr_descs.data(); 141 | 142 | PipelineInputAssemblyStateCreateInfo vertex_assembly_info; 143 | 144 | vertex_assembly_info.topology = PrimitiveTopology::eTriangleList; 145 | vertex_assembly_info.primitiveRestartEnable = false; 146 | 147 | // Setting viewport and scissor information 148 | 149 | Viewport viewport; 150 | 151 | viewport.x = viewport.y = .0f; 152 | viewport.width = static_cast(m_params.surface_extent.width); 153 | viewport.height = static_cast(m_params.surface_extent.height); 154 | viewport.minDepth = .0f; 155 | viewport.maxDepth = 1.f; 156 | 157 | Rect2D scissor; 158 | 159 | scissor.offset = Offset2D{0, 0}; 160 | scissor.extent = m_params.surface_extent; 161 | 162 | PipelineViewportStateCreateInfo viewport_info; 163 | 164 | viewport_info.viewportCount = 1; 165 | viewport_info.pViewports = &viewport; 166 | viewport_info.scissorCount = 1; 167 | viewport_info.pScissors = &scissor; 168 | 169 | // Setting up rasterizer 170 | 171 | PipelineRasterizationStateCreateInfo rasterizer_info; 172 | 173 | rasterizer_info.depthClampEnable = false; 174 | rasterizer_info.rasterizerDiscardEnable = false; 175 | rasterizer_info.polygonMode = PolygonMode::eFill; 176 | rasterizer_info.lineWidth = 1.f; 177 | rasterizer_info.cullMode = CullModeFlagBits::eBack; 178 | rasterizer_info.frontFace = FrontFace::eClockwise; 179 | rasterizer_info.depthBiasEnable = false; 180 | rasterizer_info.depthBiasConstantFactor = .0f; 181 | rasterizer_info.depthBiasClamp = .0f; 182 | rasterizer_info.depthBiasSlopeFactor = .0f; 183 | 184 | // Setup multi-sampling 185 | 186 | PipelineMultisampleStateCreateInfo multisampling_info; 187 | 188 | multisampling_info.sampleShadingEnable = false; 189 | multisampling_info.rasterizationSamples = SampleCountFlagBits::e1; 190 | multisampling_info.minSampleShading = 1.f; 191 | multisampling_info.pSampleMask = nullptr; 192 | multisampling_info.alphaToCoverageEnable = false; 193 | multisampling_info.alphaToOneEnable = false; 194 | 195 | // Setup depth and stencil testing 196 | 197 | PipelineDepthStencilStateCreateInfo depth_stencil_info; 198 | 199 | depth_stencil_info.depthTestEnable = true; 200 | depth_stencil_info.depthWriteEnable = true; 201 | depth_stencil_info.depthCompareOp = CompareOp::eLess; 202 | depth_stencil_info.depthBoundsTestEnable = false; 203 | depth_stencil_info.minDepthBounds = 0.0f; 204 | depth_stencil_info.maxDepthBounds = 1.0f; 205 | depth_stencil_info.stencilTestEnable = false; 206 | //depth_stencil_info.front = {}; 207 | //depth_stencil_info.back = {}; 208 | 209 | // Setup color blending state 210 | 211 | PipelineColorBlendAttachmentState color_blend_attachment; 212 | 213 | color_blend_attachment.colorWriteMask = ColorComponentFlagBits::eR | ColorComponentFlagBits::eG | 214 | ColorComponentFlagBits::eB | ColorComponentFlagBits::eA; 215 | color_blend_attachment.blendEnable = false; 216 | color_blend_attachment.srcColorBlendFactor = BlendFactor::eOne; 217 | color_blend_attachment.dstColorBlendFactor = BlendFactor::eZero; 218 | color_blend_attachment.colorBlendOp = BlendOp::eAdd; 219 | color_blend_attachment.srcAlphaBlendFactor = BlendFactor::eOne; 220 | color_blend_attachment.dstAlphaBlendFactor = BlendFactor::eZero; 221 | color_blend_attachment.alphaBlendOp = BlendOp::eAdd; 222 | 223 | PipelineColorBlendStateCreateInfo color_blend_info; 224 | 225 | color_blend_info.logicOpEnable = false; 226 | color_blend_info.logicOp = LogicOp::eCopy; 227 | color_blend_info.attachmentCount = 1; 228 | color_blend_info.pAttachments = &color_blend_attachment; 229 | color_blend_info.blendConstants[0.0f] = .0f; 230 | color_blend_info.blendConstants[1.0f] = .0f; 231 | color_blend_info.blendConstants[2.0f] = .0f; 232 | color_blend_info.blendConstants[3.0f] = .0f; 233 | 234 | // Setup dynamic state for pipeline 235 | 236 | // NO dynamic state is defined so just pass nullptr to pipeline creation 237 | 238 | // Setup pipeline layout 239 | 240 | DescriptorSetLayoutBinding ubo_layout_binding; 241 | 242 | ubo_layout_binding.binding = 0; 243 | ubo_layout_binding.descriptorType = DescriptorType::eUniformBuffer; 244 | ubo_layout_binding.descriptorCount = 1; 245 | ubo_layout_binding.stageFlags = ShaderStageFlagBits::eVertex; 246 | ubo_layout_binding.pImmutableSamplers = nullptr; 247 | 248 | array sampler_binding; 249 | 250 | if(a_params.immut_sampler) 251 | { 252 | sampler_binding[0].binding = 1; 253 | sampler_binding[0].descriptorCount = 1; 254 | sampler_binding[0].descriptorType = DescriptorType::eCombinedImageSampler; 255 | sampler_binding[0].stageFlags = ShaderStageFlagBits::eFragment; 256 | sampler_binding[0].pImmutableSamplers = &a_params.immut_sampler; 257 | } 258 | else 259 | { 260 | sampler_binding[0].binding = 1; 261 | sampler_binding[0].descriptorCount = 1; 262 | sampler_binding[0].descriptorType = DescriptorType::eCombinedImageSampler; 263 | sampler_binding[0].stageFlags = ShaderStageFlagBits::eFragment; 264 | sampler_binding[0].pImmutableSamplers = nullptr; 265 | } 266 | 267 | array desc_bindings = { 268 | ubo_layout_binding, sampler_binding[0] 269 | }; 270 | 271 | DescriptorSetLayoutCreateInfo desc_set_layout_info; 272 | 273 | desc_set_layout_info.bindingCount = desc_bindings.size(); 274 | desc_set_layout_info.pBindings = desc_bindings.data(); 275 | 276 | m_desc_set_layout = m_params.device.createDescriptorSetLayout(desc_set_layout_info); 277 | 278 | PipelineLayoutCreateInfo pipeline_layout_info; 279 | 280 | pipeline_layout_info.setLayoutCount = 1; 281 | pipeline_layout_info.pSetLayouts = &m_desc_set_layout; 282 | pipeline_layout_info.pushConstantRangeCount = 0; 283 | pipeline_layout_info.pPushConstantRanges = nullptr; 284 | 285 | //-- Instantiate graphics pipeline with all of the above 286 | 287 | // Create pipeline layout 288 | 289 | m_pipeline_layout = m_params.device.createPipelineLayout(pipeline_layout_info); 290 | 291 | // Create graphics pipeline 292 | 293 | GraphicsPipelineCreateInfo graphics_pipeline_info; 294 | 295 | graphics_pipeline_info.stageCount = shader_stages_info.size(); 296 | graphics_pipeline_info.pStages = shader_stages_info.data(); 297 | graphics_pipeline_info.pVertexInputState = &vertex_input_info; 298 | graphics_pipeline_info.pInputAssemblyState = &vertex_assembly_info; 299 | graphics_pipeline_info.pViewportState = &viewport_info; 300 | graphics_pipeline_info.pRasterizationState = &rasterizer_info; 301 | graphics_pipeline_info.pMultisampleState = &multisampling_info; 302 | graphics_pipeline_info.pDepthStencilState = &depth_stencil_info; 303 | graphics_pipeline_info.pColorBlendState = &color_blend_info; 304 | graphics_pipeline_info.pDynamicState = nullptr; 305 | graphics_pipeline_info.layout = m_pipeline_layout; 306 | graphics_pipeline_info.renderPass = m_params.render_pass; 307 | graphics_pipeline_info.subpass = 0; 308 | graphics_pipeline_info.basePipelineHandle = nullptr; 309 | graphics_pipeline_info.basePipelineIndex = -1; 310 | 311 | auto call_result = m_params.device.createGraphicsPipeline(nullptr, graphics_pipeline_info); 312 | 313 | if(call_result.result != Result::eSuccess) 314 | { 315 | destroy_resources(); 316 | throw runtime_error{"Result is: " + to_string(call_result.result) + 317 | " Couldn't create graphics pipeline."}; 318 | } 319 | 320 | m_graphics_pipeline = call_result.value; 321 | } 322 | 323 | pipeline::~pipeline() 324 | { 325 | destroy_resources(); 326 | } 327 | 328 | Pipeline& pipeline::get() 329 | { 330 | return m_graphics_pipeline; 331 | } 332 | 333 | DescriptorSetLayout& pipeline::get_desc_set() 334 | { 335 | return m_desc_set_layout; 336 | } 337 | 338 | PipelineLayout& pipeline::get_layout() 339 | { 340 | return m_pipeline_layout; 341 | } 342 | 343 | void pipeline::destroy_resources() noexcept 344 | { 345 | m_params.device.destroyDescriptorSetLayout(m_desc_set_layout); 346 | m_params.device.destroyPipelineLayout(m_pipeline_layout); 347 | m_params.device.destroyPipeline(m_graphics_pipeline); 348 | m_params.device.destroyShaderModule(m_fragment_shader); 349 | m_params.device.destroyShaderModule(m_vertex_shader); 350 | } 351 | } -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/pipeline.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_GRAPHICS_PIPELINE_HPP 19 | #define NCV_GRAPHICS_PIPELINE_HPP 20 | 21 | #include 22 | 23 | class AAssetManager; 24 | 25 | namespace graphics 26 | { 27 | class pipeline 28 | { 29 | public: 30 | 31 | struct shaders_info 32 | { 33 | const std::string vert_filename; 34 | const std::string frag_filename; 35 | }; 36 | 37 | struct parameters 38 | { 39 | AAssetManager* ass_mgr; 40 | vk::Device device; 41 | vk::Extent2D surface_extent; 42 | vk::RenderPass render_pass; 43 | vk::Sampler immut_sampler; 44 | }; 45 | 46 | pipeline(const parameters& a_params, const shaders_info& a_shaders_info); 47 | 48 | ~pipeline(); 49 | 50 | vk::Pipeline& get(); 51 | vk::DescriptorSetLayout& get_desc_set(); 52 | vk::PipelineLayout& get_layout(); 53 | 54 | private: 55 | 56 | void destroy_resources() noexcept; 57 | 58 | parameters m_params; 59 | shaders_info m_shaders_info; 60 | 61 | vk::ShaderModule m_vertex_shader = nullptr; 62 | vk::ShaderModule m_fragment_shader = nullptr; 63 | vk::DescriptorSetLayout m_desc_set_layout = nullptr; 64 | vk::PipelineLayout m_pipeline_layout = nullptr; 65 | vk::Pipeline m_graphics_pipeline = nullptr; 66 | }; 67 | 68 | } 69 | 70 | #endif //NCV_GRAPHICS_PIPELINE_HPP 71 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/resources/base.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | using namespace ::vk; 21 | 22 | namespace graphics{ namespace resources{ 23 | 24 | base::base(const PhysicalDevice& a_gpu, const UniqueDevice& a_device) 25 | : m_device{a_device.get()} 26 | { 27 | m_mem_props = a_gpu.getMemoryProperties(); 28 | } 29 | 30 | int base::get_memory_index(uint32_t a_memory_type_bits, memory_location a_location) noexcept 31 | { 32 | int mem_index {0}; 33 | 34 | MemoryPropertyFlags mem_flags = MemoryPropertyFlags{0}; 35 | 36 | switch(a_location) 37 | { 38 | case memory_location::device: 39 | mem_flags = MemoryPropertyFlagBits::eDeviceLocal; 40 | break; 41 | case memory_location::host: 42 | mem_flags = MemoryPropertyFlagBits::eHostVisible | MemoryPropertyFlagBits::eHostCoherent; 43 | break; 44 | default: 45 | break; 46 | } 47 | 48 | if(a_location == memory_location::external) 49 | { 50 | for(auto& type : m_mem_props.memoryTypes) 51 | { 52 | if((a_memory_type_bits & (1 << mem_index)) && 53 | ((type.propertyFlags & mem_flags) == MemoryPropertyFlags{0})) 54 | break; 55 | mem_index++; 56 | } 57 | } 58 | else 59 | { 60 | for(auto& type : m_mem_props.memoryTypes) 61 | { 62 | if((a_memory_type_bits & (1 << mem_index)) && 63 | (type.propertyFlags & mem_flags)) 64 | break; 65 | mem_index++; 66 | } 67 | } 68 | 69 | return mem_index; 70 | } 71 | 72 | }} 73 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/resources/base.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_RESOURCES_BASE_HPP 19 | #define NCV_RESOURCES_BASE_HPP 20 | 21 | #include 22 | 23 | namespace graphics{ namespace resources{ 24 | 25 | class base 26 | { 27 | public: 28 | 29 | enum class memory_location 30 | { 31 | device, 32 | host, 33 | external 34 | }; 35 | 36 | base(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device); 37 | 38 | size_t data_size() { return m_data_size; } 39 | 40 | protected: 41 | 42 | int get_memory_index(uint32_t a_memory_type_bits, memory_location a_location) noexcept; 43 | 44 | vk::Device m_device = nullptr; 45 | vk::PhysicalDeviceMemoryProperties m_mem_props; 46 | size_t m_data_size = 0; 47 | vk::DeviceSize m_size = 0; 48 | }; 49 | 50 | }} 51 | 52 | #endif //NCV_RESOURCES_BASE_HPP 53 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/resources/buffer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | using namespace ::std; 21 | using namespace ::vk; 22 | 23 | namespace graphics{ namespace resources{ 24 | 25 | void buffer_base::destroy_resources() noexcept 26 | { 27 | if(!!m_buffer) 28 | m_device.destroyBuffer(m_buffer); 29 | if(!!m_memory) 30 | m_device.freeMemory(m_memory); 31 | } 32 | 33 | buffer::buffer(const PhysicalDevice &a_gpu, const UniqueDevice &a_device, 34 | BufferUsageFlags a_usage, SharingMode a_sharing, uint32_t a_size) 35 | : buffer_base{a_gpu, a_device} 36 | { 37 | BufferCreateInfo device_buffer_info; 38 | 39 | m_data_size = a_size; 40 | 41 | device_buffer_info.usage = a_usage; 42 | device_buffer_info.size = m_data_size; 43 | device_buffer_info.sharingMode = a_sharing; 44 | 45 | m_buffer = m_device.createBuffer(device_buffer_info); 46 | 47 | auto mem_reqs = m_device.getBufferMemoryRequirements(m_buffer); 48 | 49 | m_size = mem_reqs.size; 50 | 51 | MemoryAllocateInfo mem_info; 52 | 53 | mem_info.memoryTypeIndex = get_memory_index(mem_reqs.memoryTypeBits, memory_location::device); 54 | mem_info.allocationSize = mem_reqs.size; 55 | 56 | try 57 | { 58 | m_memory = m_device.allocateMemory(mem_info); 59 | } 60 | catch(exception const &e) 61 | { 62 | destroy_resources(); 63 | throw e; 64 | } 65 | 66 | try 67 | { 68 | m_device.bindBufferMemory(m_buffer, m_memory, 0); 69 | } 70 | catch(exception const &e) 71 | { 72 | destroy_resources(); 73 | throw e; 74 | } 75 | } 76 | }} 77 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/resources/buffer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_RESOURCES_BUFFER_HPP 19 | #define NCV_RESOURCES_BUFFER_HPP 20 | 21 | #include 22 | #include 23 | 24 | namespace graphics{ namespace resources 25 | { 26 | class buffer_base : public base 27 | { 28 | public: 29 | 30 | buffer_base(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device) 31 | : base{a_gpu, a_device} 32 | {} 33 | 34 | virtual ~buffer_base() { destroy_resources(); } 35 | 36 | vk::Buffer& get() { return m_buffer; } 37 | 38 | protected: 39 | 40 | virtual void destroy_resources() noexcept; 41 | 42 | vk::DeviceMemory m_memory = nullptr; 43 | vk::Buffer m_buffer = nullptr; 44 | }; 45 | 46 | template 47 | class buffer : public buffer_base 48 | {}; 49 | 50 | template 51 | class buffer {}; 52 | 53 | template 54 | class buffer : public buffer_base 55 | { 56 | public: 57 | buffer(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device, 58 | vk::BufferUsageFlags a_usage, vk::SharingMode a_sharing, const std::vector& a_data); 59 | void update(const std::vector& a_data); 60 | }; 61 | 62 | template<> 63 | class buffer : public buffer_base 64 | { 65 | public: 66 | buffer(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device, 67 | vk::BufferUsageFlags a_usage, vk::SharingMode a_sharing, uint32_t a_size); 68 | }; 69 | 70 | template 71 | class buffer : public buffer_base 72 | { 73 | public: 74 | buffer(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device, 75 | vk::BufferUsageFlags a_usage, vk::SharingMode a_sharing, const std::vector& a_data); 76 | ~buffer() { destroy_resources(); } 77 | void update_staging(const std::vector& a_data); 78 | vk::Buffer& get_staging() { return m_staging_buffer; } 79 | vk::DeviceSize size_staging() { return m_staging_size; } 80 | private: 81 | 82 | void destroy_resources() noexcept override; 83 | 84 | vk::DeviceSize m_staging_size = 0; 85 | vk::DeviceMemory m_staging_memory = nullptr; 86 | vk::Buffer m_staging_buffer = nullptr; 87 | }; 88 | 89 | template 90 | buffer::buffer(const vk::PhysicalDevice &a_gpu, const vk::UniqueDevice &a_device, 91 | vk::BufferUsageFlags a_usage, vk::SharingMode a_sharing, const std::vector &a_data) 92 | : buffer_base{a_gpu, a_device} 93 | { 94 | using namespace ::vk; 95 | using std::exception; 96 | using std::runtime_error; 97 | 98 | BufferCreateInfo device_buffer_info; 99 | 100 | m_data_size = a_data.size() * sizeof(DataFormat); 101 | 102 | device_buffer_info.usage = a_usage; 103 | device_buffer_info.size = m_data_size; 104 | device_buffer_info.sharingMode = a_sharing; 105 | 106 | m_buffer = m_device.createBuffer(device_buffer_info); 107 | 108 | auto mem_reqs = m_device.getBufferMemoryRequirements(m_buffer); 109 | 110 | m_size = mem_reqs.size; 111 | 112 | MemoryAllocateInfo mem_info; 113 | 114 | mem_info.memoryTypeIndex = get_memory_index(mem_reqs.memoryTypeBits, memory_location::host); 115 | mem_info.allocationSize = mem_reqs.size; 116 | 117 | try 118 | { 119 | m_memory = m_device.allocateMemory(mem_info); 120 | } 121 | catch(exception const &e) 122 | { 123 | destroy_resources(); 124 | throw e; 125 | } 126 | 127 | uint8_t* pt; 128 | MemoryMapFlags map_flags {0}; 129 | 130 | auto result = m_device.mapMemory(m_memory, 0, mem_reqs.size, map_flags, 131 | reinterpret_cast(&pt)); 132 | 133 | if(result == Result::eSuccess) 134 | { 135 | memcpy(pt, a_data.data(), m_size); 136 | } 137 | else 138 | { 139 | destroy_resources(); 140 | throw runtime_error{"Result is: " + to_string(result) + ". Could not copy host data."}; 141 | } 142 | 143 | m_device.unmapMemory(m_memory); 144 | 145 | try 146 | { 147 | m_device.bindBufferMemory(m_buffer, m_memory, 0); 148 | } 149 | catch(exception const &e) 150 | { 151 | destroy_resources(); 152 | throw e; 153 | } 154 | } 155 | 156 | template 157 | inline void buffer::update(const std::vector &a_data) 158 | { 159 | if(a_data.size() * sizeof(DataFormat) != m_data_size) 160 | throw std::runtime_error{"Data size differs. Cannot update buffer."}; 161 | 162 | uint8_t* pt; 163 | vk::MemoryMapFlags map_flags {0}; 164 | 165 | auto result = m_device.mapMemory(m_memory, 0, m_size, map_flags, reinterpret_cast(&pt)); 166 | 167 | if(result == vk::Result::eSuccess) 168 | memcpy(pt, a_data.data(), m_size); 169 | else 170 | throw std::runtime_error{"Result is: " + to_string(result) + ". Could not copy host data."}; 171 | 172 | m_device.unmapMemory(m_memory); 173 | } 174 | 175 | template 176 | buffer::buffer(const vk::PhysicalDevice &a_gpu, const vk::UniqueDevice &a_device, 177 | vk::BufferUsageFlags a_usage, vk::SharingMode a_sharing, const std::vector &a_data) 178 | : buffer_base{a_gpu, a_device} 179 | { 180 | using namespace ::vk; 181 | using std::exception; 182 | using std::runtime_error; 183 | 184 | BufferCreateInfo staging_buffer_info; 185 | 186 | m_data_size = a_data.size() * sizeof(DataFormat); 187 | 188 | staging_buffer_info.usage = BufferUsageFlagBits::eTransferSrc; 189 | staging_buffer_info.size = m_data_size; 190 | staging_buffer_info.sharingMode = a_sharing; 191 | 192 | m_staging_buffer = m_device.createBuffer(staging_buffer_info); 193 | 194 | auto mem_reqs = m_device.getBufferMemoryRequirements(m_staging_buffer); 195 | 196 | m_staging_size = mem_reqs.size; 197 | 198 | MemoryAllocateInfo mem_info; 199 | 200 | mem_info.memoryTypeIndex = get_memory_index(mem_reqs.memoryTypeBits, memory_location::host); 201 | mem_info.allocationSize = mem_reqs.size; 202 | 203 | try 204 | { 205 | m_staging_memory = m_device.allocateMemory(mem_info); 206 | } 207 | catch(exception const &e) 208 | { 209 | destroy_resources(); 210 | throw e; 211 | } 212 | 213 | uint8_t* pt; 214 | MemoryMapFlags map_flags {0}; 215 | 216 | auto result = m_device.mapMemory(m_staging_memory, 0, m_staging_size, map_flags, 217 | reinterpret_cast(&pt)); 218 | 219 | if(result == Result::eSuccess) 220 | { 221 | memcpy(pt, a_data.data(), m_staging_size); 222 | } 223 | else 224 | { 225 | destroy_resources(); 226 | throw runtime_error{"Result is: " + to_string(result) + ". Could not copy host data."}; 227 | } 228 | 229 | m_device.unmapMemory(m_staging_memory); 230 | 231 | try 232 | { 233 | m_device.bindBufferMemory(m_staging_buffer, m_staging_memory, 0); 234 | } 235 | catch(exception const &e) 236 | { 237 | destroy_resources(); 238 | throw e; 239 | } 240 | 241 | BufferCreateInfo device_buffer_info; 242 | 243 | device_buffer_info.usage = BufferUsageFlagBits::eTransferDst | a_usage; 244 | device_buffer_info.size = m_data_size; 245 | device_buffer_info.sharingMode = a_sharing; 246 | 247 | try 248 | { 249 | m_buffer = m_device.createBuffer(device_buffer_info); 250 | } 251 | catch (exception const &e) 252 | { 253 | destroy_resources(); 254 | throw e; 255 | } 256 | 257 | mem_reqs = m_device.getBufferMemoryRequirements(m_buffer); 258 | 259 | m_size = mem_reqs.size; 260 | 261 | mem_info.memoryTypeIndex = get_memory_index(mem_reqs.memoryTypeBits, memory_location::device); 262 | mem_info.allocationSize = mem_reqs.size; 263 | 264 | try 265 | { 266 | m_memory = m_device.allocateMemory(mem_info); 267 | m_device.bindBufferMemory(m_buffer, m_memory,0); 268 | } 269 | catch (exception const &e) 270 | { 271 | destroy_resources(); 272 | throw e; 273 | } 274 | } 275 | 276 | template 277 | inline void buffer::destroy_resources() noexcept 278 | { 279 | if(!!m_staging_buffer) 280 | m_device.destroyBuffer(m_staging_buffer); 281 | if(!!m_staging_memory) 282 | m_device.freeMemory(m_staging_memory); 283 | } 284 | 285 | template 286 | inline void buffer::update_staging(const std::vector &a_data) 287 | { 288 | if(a_data.size() * sizeof(DataFormat) != m_data_size) 289 | throw std::runtime_error{"Data size differs. Cannot update buffer."}; 290 | 291 | uint8_t* pt; 292 | vk::MemoryMapFlags map_flags {0}; 293 | 294 | auto result = m_device.mapMemory(m_staging_memory, 0, m_staging_size, map_flags, 295 | reinterpret_cast(&pt)); 296 | 297 | if(result == vk::Result::eSuccess) 298 | memcpy(pt, a_data.data(), m_staging_size); 299 | else 300 | throw std::runtime_error{"Result is: " + to_string(result) + ". Could not copy host data."}; 301 | 302 | m_device.unmapMemory(m_staging_memory); 303 | } 304 | }} 305 | 306 | #endif //NCV_RESOURCES_BUFFER_HPP 307 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/resources/image.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | using namespace ::vk; 22 | 23 | namespace graphics{ namespace resources{ 24 | 25 | void image_base::destroy_resources() noexcept 26 | { 27 | if(!!m_img_view) 28 | m_device.destroyImageView(m_img_view); 29 | if(!!m_image) 30 | m_device.destroyImage(m_image); 31 | if(!!m_memory) 32 | m_device.freeMemory(m_memory); 33 | m_img_view = nullptr; 34 | m_image = nullptr; 35 | m_memory = nullptr; 36 | } 37 | 38 | image::image(const PhysicalDevice &a_gpu, const UniqueDevice &a_device, 39 | AHardwareBuffer *a_buffer) : image_base{a_gpu, a_device} 40 | { 41 | AHardwareBuffer_Desc buffer_desc; 42 | AHardwareBuffer_describe(a_buffer, &buffer_desc); 43 | 44 | m_data_size = buffer_desc.width * buffer_desc.height * buffer_desc.layers; 45 | 46 | AndroidHardwareBufferFormatPropertiesANDROID format_info; 47 | AndroidHardwareBufferPropertiesANDROID properties_info; 48 | 49 | properties_info.pNext = &format_info; 50 | 51 | auto res = m_device.getAndroidHardwareBufferPropertiesANDROID(a_buffer, &properties_info); 52 | 53 | if(res != Result::eSuccess) 54 | throw std::runtime_error{"Error code: " + to_string(res) + ". Failed getting buffer properties."}; 55 | 56 | ExternalMemoryImageCreateInfo ext_mem_info; 57 | 58 | ext_mem_info.handleTypes = ExternalMemoryHandleTypeFlagBitsKHR::eAndroidHardwareBufferANDROID; 59 | 60 | ExternalFormatANDROID external_format; 61 | SamplerYcbcrConversionCreateInfo conv_info; 62 | 63 | if(format_info.format == Format::eUndefined) 64 | { 65 | external_format.externalFormat = format_info.externalFormat; 66 | conv_info.pNext = &external_format; 67 | conv_info.format = Format::eUndefined; 68 | conv_info.ycbcrModel = format_info.suggestedYcbcrModel; 69 | } 70 | else 71 | { 72 | conv_info.pNext = &external_format; 73 | conv_info.format = format_info.format; 74 | conv_info.ycbcrModel = SamplerYcbcrModelConversion::eYcbcr601; 75 | } 76 | 77 | conv_info.ycbcrRange = format_info.suggestedYcbcrRange; 78 | conv_info.components = format_info.samplerYcbcrConversionComponents; 79 | conv_info.xChromaOffset = format_info.suggestedXChromaOffset; 80 | conv_info.yChromaOffset = format_info.suggestedYChromaOffset; 81 | conv_info.chromaFilter = Filter::eNearest; 82 | conv_info.forceExplicitReconstruction = false; 83 | 84 | m_conversion = m_device.createSamplerYcbcrConversion(conv_info); 85 | 86 | SamplerYcbcrConversionInfo conv_sampler_info; 87 | 88 | conv_sampler_info.conversion = m_conversion; 89 | 90 | SamplerCreateInfo sampler_info; 91 | 92 | sampler_info.pNext = &conv_sampler_info; 93 | sampler_info.magFilter = Filter::eNearest; 94 | sampler_info.minFilter = Filter::eNearest; 95 | sampler_info.mipmapMode = SamplerMipmapMode::eNearest; 96 | sampler_info.addressModeU = SamplerAddressMode::eClampToEdge; 97 | sampler_info.addressModeV = SamplerAddressMode::eClampToEdge; 98 | sampler_info.addressModeW = SamplerAddressMode::eClampToEdge; 99 | sampler_info.mipLodBias = 0.0f; 100 | sampler_info.anisotropyEnable = false; 101 | sampler_info.maxAnisotropy = 1.0f; 102 | sampler_info.compareEnable = false; 103 | sampler_info.compareOp = CompareOp::eNever; 104 | sampler_info.minLod = 0.0f; 105 | sampler_info.maxLod = 0.0f; 106 | sampler_info.borderColor = BorderColor::eFloatOpaqueWhite; 107 | sampler_info.unnormalizedCoordinates = false; 108 | 109 | m_sampler = m_device.createSampler(sampler_info); 110 | } 111 | 112 | void image::destroy_resources() noexcept 113 | { 114 | if(!!m_sampler) 115 | m_device.destroySampler(m_sampler); 116 | if(!!m_conversion) 117 | m_device.destroySamplerYcbcrConversion(m_conversion); 118 | } 119 | 120 | void image::update(ImageUsageFlags a_usage, SharingMode a_sharing, 121 | AHardwareBuffer *a_buffer) 122 | { 123 | // No exception handling is required inside this body because resources are freed as soon as 124 | // control enters this function member. 125 | 126 | m_device.waitIdle(); 127 | image_base::destroy_resources(); 128 | 129 | AHardwareBuffer_Desc buffer_desc; 130 | AHardwareBuffer_describe(a_buffer, &buffer_desc); 131 | 132 | if(buffer_desc.width * buffer_desc.height * buffer_desc.layers != m_data_size) 133 | throw std::runtime_error{"Data size differs. Cannot update image."}; 134 | 135 | AndroidHardwareBufferFormatPropertiesANDROID format_info; 136 | AndroidHardwareBufferPropertiesANDROID properties_info; 137 | 138 | properties_info.pNext = &format_info; 139 | 140 | auto res = m_device.getAndroidHardwareBufferPropertiesANDROID(a_buffer, &properties_info); 141 | 142 | if(res != Result::eSuccess) 143 | throw std::runtime_error{"Result is: " + to_string(res) + "Couldn't get external buffer properties."}; 144 | 145 | ExternalMemoryImageCreateInfo ext_mem_info; 146 | 147 | ext_mem_info.handleTypes = ExternalMemoryHandleTypeFlagBitsKHR::eAndroidHardwareBufferANDROID; 148 | 149 | ExternalFormatANDROID external_format; 150 | 151 | external_format.pNext = &ext_mem_info; 152 | 153 | ImageCreateInfo image_info; 154 | 155 | if(format_info.format == Format::eUndefined) 156 | { 157 | external_format.externalFormat = format_info.externalFormat; 158 | image_info.pNext = &external_format; 159 | image_info.format = Format::eUndefined; 160 | } 161 | else 162 | { 163 | image_info.pNext = &external_format; 164 | image_info.format = format_info.format; 165 | } 166 | 167 | image_info.flags = ImageCreateFlags{0}; 168 | image_info.imageType = ImageType::e2D; 169 | image_info.extent = Extent3D{buffer_desc.width, buffer_desc.height, 1}; 170 | image_info.mipLevels = 1; 171 | image_info.arrayLayers = buffer_desc.layers; 172 | image_info.samples = SampleCountFlagBits::e1; 173 | image_info.tiling = ImageTiling::eOptimal; 174 | image_info.usage = a_usage; 175 | image_info.sharingMode = a_sharing; 176 | image_info.queueFamilyIndexCount = 0; 177 | image_info.pQueueFamilyIndices = nullptr; 178 | image_info.initialLayout = ImageLayout::eUndefined; 179 | 180 | m_image = m_device.createImage(image_info); 181 | 182 | ImportAndroidHardwareBufferInfoANDROID import_info; 183 | 184 | import_info.buffer = a_buffer; 185 | 186 | MemoryDedicatedAllocateInfo mem_ded_info; 187 | 188 | mem_ded_info.pNext = &import_info; 189 | mem_ded_info.image = m_image; 190 | mem_ded_info.buffer = nullptr; 191 | 192 | MemoryAllocateInfo mem_info; 193 | 194 | mem_info.pNext = &mem_ded_info; 195 | mem_info.allocationSize = properties_info.allocationSize; 196 | 197 | m_size = properties_info.allocationSize; 198 | 199 | mem_info.memoryTypeIndex = get_memory_index(properties_info.memoryTypeBits, 200 | memory_location::external); 201 | 202 | m_memory = m_device.allocateMemory(mem_info); 203 | 204 | BindImageMemoryInfo bind_info; 205 | 206 | bind_info.image = m_image; 207 | bind_info.memory = m_memory; 208 | bind_info.memoryOffset = 0; 209 | 210 | m_device.bindImageMemory2KHR(bind_info); 211 | 212 | ImageMemoryRequirementsInfo2 mem_reqs_info; 213 | 214 | mem_reqs_info.image = m_image; 215 | 216 | MemoryDedicatedRequirements ded_mem_reqs; 217 | MemoryRequirements2 mem_reqs2; 218 | 219 | mem_reqs2.pNext = &ded_mem_reqs; 220 | 221 | m_device.getImageMemoryRequirements2KHR(&mem_reqs_info, &mem_reqs2); 222 | 223 | if(!ded_mem_reqs.prefersDedicatedAllocation || !ded_mem_reqs.requiresDedicatedAllocation) 224 | return; 225 | 226 | SamplerYcbcrConversionInfo conv_sampler_info; 227 | 228 | conv_sampler_info.conversion = m_conversion; 229 | 230 | ImageViewCreateInfo img_view_info; 231 | 232 | img_view_info.pNext = &conv_sampler_info; 233 | img_view_info.format = format_info.format; 234 | img_view_info.image = m_image; 235 | img_view_info.viewType = ImageViewType::e2D; 236 | img_view_info.components = { 237 | VK_COMPONENT_SWIZZLE_IDENTITY, 238 | VK_COMPONENT_SWIZZLE_IDENTITY, 239 | VK_COMPONENT_SWIZZLE_IDENTITY, 240 | VK_COMPONENT_SWIZZLE_IDENTITY 241 | }; 242 | img_view_info.subresourceRange.aspectMask = ImageAspectFlagBits::eColor; 243 | img_view_info.subresourceRange.baseMipLevel = 0; 244 | img_view_info.subresourceRange.levelCount = 1; 245 | img_view_info.subresourceRange.baseArrayLayer = 0; 246 | img_view_info.subresourceRange.layerCount = 1; 247 | 248 | m_img_view = m_device.createImageView(img_view_info); 249 | } 250 | 251 | image::image(const PhysicalDevice &a_gpu, const UniqueDevice &a_device, 252 | ImageUsageFlags a_usage, SharingMode a_sharing, const Extent2D &a_extent) 253 | : image_base{a_gpu, a_device} 254 | { 255 | ImageCreateInfo image_info; 256 | 257 | //image_info.flags 258 | image_info.imageType = ImageType::e2D; 259 | image_info.format = Format::eD32Sfloat; 260 | image_info.extent = Extent3D(a_extent, 1); 261 | image_info.mipLevels = 1; 262 | image_info.arrayLayers = 1; 263 | image_info.samples = SampleCountFlagBits::e1; 264 | image_info.tiling = ImageTiling::eOptimal; 265 | image_info.usage = a_usage; 266 | image_info.sharingMode = a_sharing; 267 | image_info.queueFamilyIndexCount = 0; 268 | image_info.pQueueFamilyIndices = nullptr; 269 | image_info.initialLayout = ImageLayout::eUndefined; 270 | 271 | m_image = m_device.createImage(image_info); 272 | 273 | auto mem_reqs = m_device.getImageMemoryRequirements(m_image); 274 | 275 | MemoryAllocateInfo mem_info; 276 | 277 | mem_info.memoryTypeIndex = get_memory_index(mem_reqs.memoryTypeBits, memory_location::device); 278 | mem_info.allocationSize = mem_reqs.size; 279 | 280 | m_size = mem_reqs.size; 281 | m_data_size = static_cast(m_size); 282 | 283 | ImageViewCreateInfo img_view_info; 284 | 285 | img_view_info.image = m_image; 286 | img_view_info.viewType = ImageViewType::e2D; 287 | img_view_info.format = Format::eD32Sfloat; 288 | //img_view_info.components 289 | img_view_info.subresourceRange.aspectMask = ImageAspectFlagBits::eDepth; 290 | img_view_info.subresourceRange.baseMipLevel = 0; 291 | img_view_info.subresourceRange.levelCount = 1; 292 | img_view_info.subresourceRange.baseArrayLayer = 0; 293 | img_view_info.subresourceRange.layerCount = 1; 294 | 295 | try 296 | { 297 | m_memory = m_device.allocateMemory(mem_info); 298 | m_device.bindImageMemory(m_image, m_memory, 0); 299 | m_img_view = m_device.createImageView(img_view_info); 300 | } 301 | catch(std::exception const &e) 302 | { 303 | destroy_resources(); 304 | throw e; 305 | } 306 | } 307 | }} -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/resources/image.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_RESOURCES_IMAGE_HPP 19 | #define NCV_RESOURCES_IMAGE_HPP 20 | 21 | #include 22 | #include 23 | 24 | namespace graphics{ namespace resources{ 25 | 26 | class image_base : public base 27 | { 28 | public: 29 | 30 | image_base(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device) 31 | : base{a_gpu, a_device} 32 | {} 33 | 34 | virtual ~image_base() { destroy_resources(); } 35 | 36 | vk::Image& get() { return m_image; } 37 | vk::ImageView& get_img_view() { return m_img_view; } 38 | 39 | protected: 40 | 41 | virtual void destroy_resources() noexcept; 42 | 43 | vk::DeviceMemory m_memory = nullptr; 44 | vk::Image m_image = nullptr; 45 | vk::ImageView m_img_view = nullptr; 46 | }; 47 | 48 | template 49 | class image : public image_base 50 | {}; 51 | 52 | template<> 53 | class image : public image_base 54 | { 55 | public: 56 | image(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device, AHardwareBuffer* a_buffer); 57 | ~image() { destroy_resources(); } 58 | void update(vk::ImageUsageFlags a_usage, vk::SharingMode a_sharing, AHardwareBuffer* a_buffer); 59 | vk::Sampler& get_sampler() { return m_sampler; } 60 | private: 61 | 62 | void destroy_resources() noexcept override; 63 | 64 | vk::Sampler m_sampler = nullptr; 65 | vk::SamplerYcbcrConversion m_conversion = nullptr; 66 | }; 67 | 68 | template 69 | class image {}; 70 | 71 | template<> 72 | class image : public image_base 73 | { 74 | public: 75 | image(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device, 76 | vk::ImageUsageFlags a_usage, vk::SharingMode a_sharing, const vk::Extent2D& a_extent); 77 | }; 78 | 79 | template 80 | class image : public image_base 81 | { 82 | public: 83 | image(const vk::PhysicalDevice& a_gpu, const vk::UniqueDevice& a_device, 84 | vk::ImageUsageFlags a_usage, vk::SharingMode a_sharing, vk::Extent3D& a_extent, 85 | vk::Format a_format, const std::vector& a_data); 86 | ~image() { destroy_resources(); } 87 | void update_staging(const std::vector& a_data); 88 | vk::Buffer& get_staging() { return m_staging_buffer; } 89 | vk::DeviceSize size_staging() { return m_staging_size; } 90 | private: 91 | 92 | void destroy_resources() noexcept override; 93 | 94 | vk::DeviceSize m_staging_size = 0; 95 | vk::DeviceMemory m_staging_memory = nullptr; 96 | vk::Buffer m_staging_buffer = nullptr; 97 | }; 98 | 99 | template 100 | image::image(const vk::PhysicalDevice &a_gpu, 101 | const vk::UniqueDevice &a_device, vk::ImageUsageFlags a_usage, vk::SharingMode a_sharing, 102 | vk::Extent3D &a_extent, vk::Format a_format, const std::vector &a_data) 103 | : image_base{a_gpu, a_device} 104 | { 105 | using namespace ::vk; 106 | 107 | int num_channels; 108 | 109 | switch (a_format) 110 | { 111 | case vk::Format::eR8G8B8A8Srgb: 112 | case vk::Format::eB8G8R8A8Srgb: 113 | num_channels = 4; 114 | break; 115 | case vk::Format::eR8G8B8Srgb: 116 | case vk::Format::eB8G8R8Srgb: 117 | num_channels = 3; 118 | break; 119 | default: 120 | num_channels = -1; 121 | } 122 | 123 | if(num_channels == -1) 124 | throw std::runtime_error{"Format is not supported."}; 125 | 126 | m_data_size = a_extent.width * a_extent.height * num_channels; 127 | 128 | BufferCreateInfo staging_buffer_info; 129 | 130 | staging_buffer_info.usage = BufferUsageFlagBits::eTransferSrc; 131 | staging_buffer_info.size = m_data_size; 132 | staging_buffer_info.sharingMode = a_sharing; 133 | 134 | m_staging_buffer = m_device.createBuffer(staging_buffer_info); 135 | 136 | auto mem_reqs = m_device.getBufferMemoryRequirements(m_staging_buffer); 137 | 138 | m_staging_size = mem_reqs.size; 139 | 140 | MemoryAllocateInfo mem_info; 141 | 142 | mem_info.memoryTypeIndex = get_memory_index(mem_reqs.memoryTypeBits, memory_location::host); 143 | mem_info.allocationSize = mem_reqs.size; 144 | 145 | try 146 | { 147 | m_staging_memory = m_device.allocateMemory(mem_info); 148 | } 149 | catch (std::exception const &e) 150 | { 151 | destroy_resources(); 152 | throw e; 153 | } 154 | 155 | uint8_t* pt; 156 | MemoryMapFlags map_flags {0}; 157 | 158 | auto mresult = m_device.mapMemory(m_staging_memory, 0, mem_reqs.size, map_flags, 159 | reinterpret_cast(&pt)); 160 | 161 | if(mresult == Result::eSuccess) 162 | { 163 | memcpy(pt, a_data.data(), m_staging_size); 164 | } 165 | else 166 | { 167 | destroy_resources(); 168 | throw std::runtime_error{"Result is: " + to_string(mresult) + 169 | ". Could not copy image data to staging buffer."}; 170 | } 171 | 172 | m_device.unmapMemory(m_staging_memory); 173 | 174 | try 175 | { 176 | m_device.bindBufferMemory(m_staging_buffer, m_staging_memory, 0); 177 | } 178 | catch (std::exception const &e) 179 | { 180 | destroy_resources(); 181 | throw e; 182 | } 183 | 184 | ImageCreateInfo image_info; 185 | 186 | //image_info.flags 187 | image_info.imageType = ImageType::e2D; 188 | image_info.format = a_format; 189 | image_info.extent.width = a_extent.width; 190 | image_info.extent.height = a_extent.height; 191 | image_info.extent.depth = a_extent.depth; 192 | image_info.mipLevels = 1; 193 | image_info.arrayLayers = 1; 194 | image_info.samples = SampleCountFlagBits::e1; 195 | image_info.tiling = ImageTiling::eOptimal; 196 | image_info.usage = ImageUsageFlagBits::eTransferDst | a_usage; 197 | image_info.sharingMode = a_sharing; 198 | image_info.queueFamilyIndexCount = 0; 199 | image_info.pQueueFamilyIndices = nullptr; 200 | image_info.initialLayout = ImageLayout::eUndefined; 201 | 202 | m_image = m_device.createImage(image_info); 203 | 204 | mem_reqs = m_device.getImageMemoryRequirements(m_image); 205 | 206 | mem_info.memoryTypeIndex = get_memory_index(mem_reqs.memoryTypeBits, memory_location::device); 207 | mem_info.allocationSize = mem_reqs.size; 208 | 209 | m_size = mem_reqs.size; 210 | 211 | ImageViewCreateInfo img_view_info; 212 | 213 | img_view_info.image = m_image; 214 | img_view_info.viewType = ImageViewType::e2D; 215 | img_view_info.format = a_format; 216 | //img_view_info.components 217 | img_view_info.subresourceRange.aspectMask = ImageAspectFlagBits::eColor; 218 | img_view_info.subresourceRange.baseMipLevel = 0; 219 | img_view_info.subresourceRange.levelCount = 1; 220 | img_view_info.subresourceRange.baseArrayLayer = 0; 221 | img_view_info.subresourceRange.layerCount = 1; 222 | 223 | try 224 | { 225 | m_memory = m_device.allocateMemory(mem_info); 226 | m_device.bindImageMemory(m_image, m_memory, 0); 227 | m_img_view = m_device.createImageView(img_view_info); 228 | } 229 | catch(std::exception const &e) 230 | { 231 | destroy_resources(); 232 | throw e; 233 | } 234 | } 235 | 236 | template 237 | void image::destroy_resources() noexcept 238 | { 239 | if(!!m_staging_buffer) 240 | m_device.destroyBuffer(m_staging_buffer); 241 | if(!!m_staging_memory) 242 | m_device.freeMemory(m_staging_memory); 243 | } 244 | 245 | template 246 | void image::update_staging(const std::vector &a_data) 247 | { 248 | if(a_data.size() * sizeof(ImageDataFormat) != m_data_size) 249 | throw std::runtime_error{"Data size differs. Cannot update buffer."}; 250 | 251 | uint8_t* pt; 252 | vk::MemoryMapFlags map_flags {0}; 253 | 254 | auto result = m_device.mapMemory(m_staging_memory, 0, m_staging_size, map_flags, 255 | reinterpret_cast(&pt)); 256 | 257 | if(result == vk::Result::eSuccess) 258 | memcpy(pt, a_data.data(), m_staging_size); 259 | else 260 | throw std::runtime_error{"Result is: " + to_string(result) + ". Could not copy host data."}; 261 | 262 | m_device.unmapMemory(m_staging_memory); 263 | } 264 | }} 265 | 266 | #endif //NCV_RESOURCES_IMAGE_HPP 267 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/resources/types.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_RESOURCES_TYPES_HPP 19 | #define NCV_RESOURCES_TYPES_HPP 20 | 21 | namespace graphics{ namespace resources 22 | { 23 | struct host; 24 | struct device_upload; 25 | struct device; 26 | struct external; 27 | 28 | template 29 | class buffer; 30 | 31 | template 32 | class image; 33 | }} 34 | 35 | #endif //NCV_RESOURCES_TYPES_HPP 36 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/simple_context.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_GRAPHICS_SIMPLE_CONTEXT_HPP 19 | #define NCV_GRAPHICS_SIMPLE_CONTEXT_HPP 20 | 21 | #include 22 | #include 23 | 24 | class android_app; 25 | 26 | namespace graphics 27 | { 28 | class simple_context : public vulkan_context 29 | { 30 | public: 31 | 32 | explicit simple_context(const std::string& a_app_name); 33 | ~simple_context(); 34 | void initialize_graphics(android_app* a_app); 35 | void render_frame(const std::any& a_params); 36 | 37 | private: 38 | 39 | #ifdef NCV_VULKAN_VALIDATION_ENABLED 40 | const bool m_enable_validation = true; 41 | #else 42 | const bool m_enable_validation = false; 43 | #endif 44 | 45 | std::vector m_devices; 46 | 47 | vk::PhysicalDevice m_gpu; 48 | vk::PhysicalDeviceProperties m_gpu_props; 49 | vk::PhysicalDeviceFeatures m_gpu_features; 50 | vk::PhysicalDeviceMemoryProperties m_gpu_mem_props; 51 | 52 | ::vk_util::version m_api_version; 53 | ::vk_util::version m_driver_version; 54 | 55 | vk::UniqueInstance m_instance; 56 | vk::UniqueSurfaceKHR m_surface; 57 | vk::UniqueDevice m_device; 58 | vk::UniqueSemaphore m_semaphore; 59 | vk::UniqueSemaphore m_render_semaphore; 60 | vk::UniqueSwapchainKHR m_swap_chain; 61 | vk::UniqueCommandPool m_cmd_pool; 62 | 63 | std::vector m_cmd_buffers; 64 | std::vector m_images; 65 | 66 | vk::Queue m_pres_queue; 67 | int32_t m_selected_queue_family_index = -1; 68 | 69 | vk::DebugUtilsMessengerEXT m_debug_msg; 70 | 71 | android_app* m_app = nullptr; 72 | }; 73 | } 74 | 75 | #endif //NCV_GRAPHICS_SIMPLE_CONTEXT_HPP 76 | -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/vulkan_context.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | using namespace ::std; 21 | using namespace ::vk; 22 | using namespace ::utilities; 23 | 24 | namespace graphics 25 | { 26 | vulkan_context::vulkan_context() 27 | { 28 | // Setup dynamic dispatcher 29 | 30 | m_libvulkan = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); 31 | 32 | if constexpr(__ncv_logging_enabled) 33 | { 34 | if(!m_libvulkan) 35 | _log_android(log_level::error) << "Couldn't load shared vulkan library."; 36 | else 37 | _log_android(log_level::info) << "Vulkan library loaded with success."; 38 | } 39 | 40 | if(!m_libvulkan) 41 | throw runtime_error{string("Error is: ") + to_string(Result::eErrorInitializationFailed) 42 | + string(". No Appropriate Device Found.")}; 43 | 44 | PFN_vkGetInstanceProcAddr getInstanceProcAddr = 45 | reinterpret_cast(dlsym(m_libvulkan, "vkGetInstanceProcAddr")); 46 | 47 | VULKAN_HPP_DEFAULT_DISPATCHER.init(getInstanceProcAddr); 48 | 49 | // Get global information about available extensions and layers 50 | 51 | m_avail_extensions = enumerateInstanceExtensionProperties(nullptr); 52 | m_avail_layers = enumerateInstanceLayerProperties(); 53 | 54 | auto sort_extension = [](const auto& lhs, const auto& rhs) 55 | { return string(lhs.extensionName) < string(rhs.extensionName); }; 56 | auto sort_layer = [](const auto& lhs, const auto& rhs) 57 | { return string(lhs.layerName) < string(rhs.layerName); }; 58 | 59 | sort(m_avail_extensions.begin(),m_avail_extensions.end(), sort_extension); 60 | sort(m_avail_layers.begin(),m_avail_layers.end(), sort_layer); 61 | 62 | for (const auto &layer_prop : m_avail_layers) 63 | { 64 | m_avail_layer_extensions.push_back( 65 | enumerateInstanceExtensionProperties(string(layer_prop.layerName))); 66 | sort(m_avail_layer_extensions.back().begin(), m_avail_layer_extensions.back().end(), 67 | sort_extension); 68 | } 69 | 70 | if constexpr(__ncv_logging_enabled) 71 | log_system_info(); 72 | } 73 | 74 | vulkan_context::~vulkan_context() 75 | { 76 | if(m_libvulkan != nullptr) 77 | dlclose(m_libvulkan); 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /app/src/main/cpp/graphics/vulkan_context.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_VULKAN_CONTEXT_HPP 19 | #define NCV_VULKAN_CONTEXT_HPP 20 | 21 | #include 22 | #include 23 | 24 | namespace graphics 25 | { 26 | class vulkan_context 27 | { 28 | public: 29 | constexpr static uint32_t box_width = 70u; 30 | constexpr static uint32_t col_width = 11u; 31 | 32 | typedef ::vk_util::logger::align align; 33 | 34 | vulkan_context(); 35 | virtual ~vulkan_context(); 36 | 37 | protected: 38 | 39 | template 40 | void log_system_info() const; 41 | 42 | std::vector m_avail_layers; 43 | std::vector> m_avail_layer_extensions; 44 | std::vector m_avail_extensions; 45 | 46 | void* m_libvulkan = nullptr; 47 | }; 48 | 49 | template 50 | inline void vulkan_context::log_system_info() const 51 | { 52 | auto logger = ::vk_util::logger{box_width, col_width, ::utilities::log_level::debug}; 53 | auto cc = align::ccenter; 54 | 55 | logger.box_top(); 56 | logger.write_line("GENERAL VULKAN INFORMATION", cc); 57 | logger.box_separator(); 58 | 59 | if(m_avail_extensions.size() > 0) 60 | { 61 | logger.write_line("Available Extensions", cc); 62 | logger.write_line("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾", cc); 63 | 64 | for (auto &extension : m_avail_extensions) 65 | logger.write_line_2col((" " + std::string(extension.extensionName)).c_str(), 66 | ("v" + ::vk_util::version(extension.specVersion).to_string()).c_str()); 67 | } 68 | else 69 | logger.write_line("", cc); 70 | 71 | logger.box_separator(); 72 | 73 | if(m_avail_layers.size() > 0) 74 | { 75 | logger.write_line("Available Layers", cc); 76 | logger.write_line("‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾", cc); 77 | 78 | for(uint32_t i = 0; i < m_avail_layers.size(); ++i) 79 | { 80 | logger.write_line((" " + std::string(m_avail_layers[i].layerName)).c_str()); 81 | 82 | if(m_avail_layer_extensions[i].size() > 0) 83 | { 84 | for(auto& extension : m_avail_layer_extensions[i]) 85 | logger.write_line_2col( 86 | (" " + std::string(extension.extensionName)).c_str(), 87 | ("v" + ::vk_util::version(extension.specVersion).to_string()).c_str()); 88 | } 89 | else 90 | logger.write_line("", cc); 91 | } 92 | } 93 | else 94 | logger.write_line("", cc); 95 | 96 | logger.box_bottom(); 97 | } 98 | } 99 | 100 | #endif //NCV_VULKAN_CONTEXT_HPP -------------------------------------------------------------------------------- /app/src/main/cpp/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE 27 | 28 | #ifdef NCV_USE_VULKAN_SIMPLE 29 | typedef ::engine::vulkan<::graphics::simple_context> android_engine; 30 | #elif NCV_USE_VULKAN_COMPLETE 31 | typedef ::engine::vulkan<::graphics::complex_context> android_engine; 32 | #endif 33 | 34 | constexpr const char* PACKAGE_NAME = "com.ktzevani.nativecameravulkan"; 35 | constexpr const char* PROJECT_NAME = "native-camera-vulkan"; 36 | 37 | ::utilities::log_level __ncv_log_level = ::utilities::log_level::all; 38 | 39 | void android_main(android_app* a_Application) 40 | { 41 | using ::metadata::PROJECT_VERSION; 42 | using ::utilities::log_level; 43 | 44 | if constexpr(std::is_same>()) 45 | { 46 | ::core::android_permissions permissions; 47 | permissions.request_camera_permission(a_Application); 48 | } 49 | 50 | if constexpr(__ncv_logging_enabled) 51 | _log_android(log_level::info) << "Version is: " << PROJECT_VERSION.full_version(); 52 | 53 | auto engine = std::make_shared(a_Application, std::string(PACKAGE_NAME), 54 | std::string(PROJECT_NAME), PROJECT_VERSION.packed_version()); 55 | 56 | ::core::event_loop{a_Application, engine}.run(); 57 | } -------------------------------------------------------------------------------- /app/src/main/cpp/metadata/version.cpp: -------------------------------------------------------------------------------- 1 | extern const int PROJECT_VERSION_MAJOR=0; 2 | extern const int PROJECT_VERSION_MINOR=3; 3 | extern const int PROJECT_VERSION_PATCH=0; 4 | extern const int PROJECT_VERSION_BUILD_NUMBER=7; 5 | extern const int PROJECT_BUILD_NUMBER=1892; -------------------------------------------------------------------------------- /app/src/main/cpp/metadata/version.dat: -------------------------------------------------------------------------------- 1 | 12288;7;1892 -------------------------------------------------------------------------------- /app/src/main/cpp/metadata/version.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_VERSION_HPP 19 | #define NCV_VERSION_HPP 20 | 21 | #include 22 | #include 23 | 24 | extern const int PROJECT_VERSION_MAJOR; 25 | extern const int PROJECT_VERSION_MINOR; 26 | extern const int PROJECT_VERSION_PATCH; 27 | extern const int PROJECT_VERSION_BUILD_NUMBER; 28 | extern const int PROJECT_BUILD_NUMBER; 29 | 30 | namespace metadata 31 | { 32 | struct 33 | { 34 | const int major = PROJECT_VERSION_MAJOR; 35 | const int minor = PROJECT_VERSION_MINOR; 36 | const int patch = PROJECT_VERSION_PATCH; 37 | const int build_number = PROJECT_VERSION_BUILD_NUMBER; 38 | const int total_builds = PROJECT_BUILD_NUMBER; 39 | 40 | std::string full_version() const 41 | { 42 | std::ostringstream sstr; 43 | sstr << this->major << "." 44 | << this->minor << "." 45 | << this->patch << "-" 46 | << this->build_number << " (build." 47 | << this->total_builds << ")"; 48 | return sstr.str(); 49 | } 50 | 51 | std::string semver() const 52 | { 53 | std::ostringstream sstr; 54 | sstr << this->major << "." 55 | << this->minor << "." 56 | << this->patch; 57 | return sstr.str(); 58 | } 59 | 60 | uint32_t packed_version() const 61 | { 62 | return static_cast( 63 | PROJECT_VERSION_MAJOR << 22 | 64 | PROJECT_VERSION_MINOR << 12 | 65 | (PROJECT_VERSION_PATCH & 0xfff)); 66 | } 67 | 68 | } PROJECT_VERSION; 69 | } 70 | 71 | #endif //NCV_VERSION_HPP 72 | -------------------------------------------------------------------------------- /app/src/main/cpp/utilities/helpers.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_HELPERS_HPP 19 | #define NCV_HELPERS_HPP 20 | 21 | #include 22 | 23 | namespace utilities 24 | { 25 | template> 26 | class center_helper 27 | { 28 | public: 29 | 30 | explicit center_helper(std::basic_string a_str) : m_str(a_str) 31 | {} 32 | 33 | template 34 | friend std::basic_ostream<_Char_t, _Traits> &operator<<(std::basic_ostream<_Char_t, _Traits>& a_s, 35 | const center_helper<_Char_t, _Traits>& a_c); 36 | 37 | private: 38 | std::basic_string m_str; 39 | }; 40 | 41 | template 42 | inline std::basic_ostream &operator<<(std::basic_ostream& a_s, 43 | const center_helper& a_c) 44 | { 45 | auto w = a_s.width(); 46 | 47 | if (w > a_c.m_str.length()) 48 | { 49 | auto left = (w + a_c.m_str.length()) / 2; 50 | a_s.width(left); 51 | a_s << a_c.m_str; 52 | a_s.width(w - left); 53 | a_s << ""; 54 | } 55 | else 56 | a_s << a_c.m_str; 57 | 58 | return a_s; 59 | } 60 | 61 | template> 62 | inline center_helper centered(std::basic_string str) 63 | { 64 | return center_helper(str); 65 | } 66 | 67 | static center_helper 68 | inline centered(const std::string& str) 69 | { 70 | return center_helper(str); 71 | } 72 | } 73 | 74 | #endif //NCV_HELPERS_HPP 75 | -------------------------------------------------------------------------------- /app/src/main/cpp/utilities/log.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_LOG_HPP 19 | #define NCV_LOG_HPP 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef NCV_LOGGING_ENABLED 29 | constexpr bool __ncv_logging_enabled = true; 30 | #else 31 | constexpr bool __ncv_logging_enabled = false; 32 | #endif 33 | 34 | constexpr const char* TAG = "NativeActivity"; 35 | 36 | namespace utilities 37 | { 38 | enum class log_level 39 | { 40 | silent, 41 | unknown, 42 | fatal, 43 | error, 44 | warning, 45 | info, 46 | debug, 47 | verbose, 48 | trace_0, 49 | trace_1, 50 | trace_2, 51 | all 52 | }; 53 | } 54 | 55 | extern utilities::log_level __ncv_log_level; 56 | 57 | namespace utilities 58 | { 59 | struct log_2_android_console; 60 | 61 | struct log_2_clog; 62 | 63 | struct log_2_cerr; 64 | 65 | struct log_2_cout; 66 | 67 | struct log_2_file; 68 | 69 | class log_base 70 | { 71 | public: 72 | 73 | explicit log_base(log_level a_loglevel = log_level::error) : m_level{a_loglevel} 74 | { 75 | m_buffer << "Thread ID: " << std::hex << std::this_thread::get_id() << std::dec << " - "; 76 | 77 | switch(a_loglevel) 78 | { 79 | case log_level::unknown: m_buffer << "UNKNOWN: "; break; 80 | case log_level::fatal: m_buffer << "FATAL: "; break; 81 | case log_level::error: m_buffer << "ERROR: "; break; 82 | case log_level::warning: m_buffer << "WARNING: "; break; 83 | case log_level::info: m_buffer << "INFO: "; break; 84 | case log_level::debug: m_buffer << "DEBUG: "; break; 85 | case log_level::verbose: m_buffer << "VERBOSE: "; break; 86 | case log_level::trace_0: m_buffer << "TRACE-0: "; break; 87 | case log_level::trace_1: m_buffer << "TRACE-1: "; break; 88 | case log_level::trace_2: m_buffer << "TRACE-2: "; break; 89 | case log_level::all: m_buffer << "ALL: "; break; 90 | default: break; 91 | } 92 | } 93 | 94 | template 95 | log_base& operator<<(T const& a_val) 96 | { 97 | m_buffer << a_val; 98 | return *this; 99 | } 100 | 101 | template 102 | log_base& operator<<(std::vector const& a_val) 103 | { 104 | m_buffer << '['; 105 | if(!a_val.empty()) 106 | copy(a_val.begin(), a_val.end(), std::ostream_iterator(m_buffer, ", ")); 107 | m_buffer << ']'; 108 | return *this; 109 | } 110 | 111 | virtual ~log_base() 112 | {} 113 | 114 | protected: 115 | 116 | std::ostringstream m_buffer; 117 | log_level m_level; 118 | }; 119 | 120 | template 121 | class log : public log_base 122 | {}; 123 | 124 | template<> 125 | class log : public log_base 126 | { 127 | public: 128 | 129 | log(log_level a_level = log_level::error) : log_base{a_level} 130 | {} 131 | 132 | ~log() 133 | { 134 | m_buffer << '\n'; 135 | if(m_level != log_level::silent) 136 | std::clog << m_buffer.str(); 137 | } 138 | }; 139 | 140 | template<> 141 | class log : public log_base 142 | { 143 | public: 144 | 145 | log(log_level a_level = log_level::error) : log_base{a_level} 146 | {} 147 | 148 | ~log() 149 | { 150 | m_buffer << '\n'; 151 | if(m_level != log_level::silent) 152 | std::cerr << m_buffer.str(); 153 | } 154 | }; 155 | 156 | template<> 157 | class log : public log_base 158 | { 159 | public: 160 | 161 | log(log_level a_level = log_level::error) : log_base{a_level} 162 | {} 163 | 164 | ~log() 165 | { 166 | m_buffer << '\n'; 167 | if(m_level != log_level::silent) 168 | std::cout << m_buffer.str(); 169 | } 170 | }; 171 | 172 | template<> 173 | class log : public log_base 174 | { 175 | public: 176 | 177 | log(std::ofstream& a_filestream, log_level a_level = log_level::error) 178 | : log_base{a_level}, m_filestream{a_filestream} 179 | {} 180 | 181 | ~log() 182 | { 183 | m_buffer << '\n'; 184 | if(m_level != log_level::silent) 185 | m_filestream << m_buffer.str(); 186 | } 187 | 188 | private: 189 | 190 | std::ofstream& m_filestream; 191 | }; 192 | 193 | template<> 194 | class log : public log_base 195 | { 196 | public: 197 | 198 | log(log_level a_level = log_level::error) : log_base{a_level} 199 | {} 200 | 201 | ~log() 202 | { 203 | m_buffer << "\n"; 204 | switch(m_level) 205 | { 206 | case log_level::error: 207 | __android_log_print(ANDROID_LOG_ERROR, TAG, "%s", m_buffer.str().c_str()); 208 | break; 209 | case log_level::warning: 210 | __android_log_print(ANDROID_LOG_WARN, TAG, "%s", m_buffer.str().c_str()); 211 | break; 212 | case log_level::info: 213 | __android_log_print(ANDROID_LOG_INFO, TAG, "%s", m_buffer.str().c_str()); 214 | break; 215 | case log_level::debug: 216 | __android_log_print(ANDROID_LOG_DEBUG, TAG, "%s", m_buffer.str().c_str()); 217 | break; 218 | case log_level::verbose: 219 | __android_log_print(ANDROID_LOG_VERBOSE, TAG, "%s", m_buffer.str().c_str()); 220 | break; 221 | default: 222 | break; 223 | } 224 | } 225 | }; 226 | 227 | template 228 | inline static log log_to_sarg(log_level a_level) 229 | { 230 | if(static_cast(a_level) <= static_cast(::__ncv_log_level)) 231 | return log(a_level); 232 | else 233 | return log(log_level::silent); 234 | } 235 | 236 | template 237 | inline static log log_to_marg(log_level a_level, T2& a_arg) 238 | { 239 | if(static_cast(a_level) <= static_cast(::__ncv_log_level)) 240 | return log(a_arg, a_level); 241 | else 242 | return log(a_arg, log_level::silent); 243 | } 244 | 245 | inline static log _log_android(log_level a_level) 246 | { 247 | return log_to_sarg(a_level); 248 | } 249 | 250 | inline static log _log_file(log_level a_level, std::ofstream& a_fout) 251 | { 252 | return log_to_marg(a_level, a_fout); 253 | } 254 | 255 | inline static log _log_clog(log_level a_level) 256 | { 257 | return log_to_sarg(a_level); 258 | } 259 | 260 | inline static log _log_cerr(log_level a_level) 261 | { 262 | return log_to_sarg(a_level); 263 | } 264 | 265 | inline static log _log_cout(log_level a_level) 266 | { 267 | return log_to_sarg(a_level); 268 | } 269 | } 270 | 271 | #endif //NCV_LOG_HPP -------------------------------------------------------------------------------- /app/src/main/cpp/version.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 Konstantinos Tzevanidis 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # Bump semantic versioning by using one of the following (from inside current directory): 18 | # 19 | # >cmake -DBUMP_MAJOR:boolean=true -P version.cmake 20 | # >cmake -DBUMP_MINOR:boolean=true -P version.cmake 21 | # >cmake -DBUMP_PATCH:boolean=true -P version.cmake 22 | 23 | if(EXISTS metadata/version.dat) 24 | file(READ metadata/version.dat VERSION_LIST_) 25 | else() 26 | set(VERSION_LIST_ 0 0 0) 27 | endif() 28 | 29 | list(GET VERSION_LIST_ 0 VERSION_) 30 | list(GET VERSION_LIST_ 1 VERSION_BUILD_NUMBER_) 31 | list(GET VERSION_LIST_ 2 BUILD_NUMBER_) 32 | 33 | math(EXPR BUILD_NUMBER_ "${BUILD_NUMBER_}+1") 34 | math(EXPR VERSION_BUILD_NUMBER_ "${VERSION_BUILD_NUMBER_}+1") 35 | 36 | math(EXPR VERSION_MAJOR_ "${VERSION_} >> 22") 37 | math(EXPR VERSION_MINOR_ "(${VERSION_} >> 12) & 0x3ff") 38 | math(EXPR VERSION_PATCH_ "${VERSION_} & 0xfff") 39 | 40 | if(BUMP_MAJOR) 41 | math(EXPR VERSION_MAJOR_ "${VERSION_MAJOR_}+1") 42 | set(VERSION_MINOR_ 0) 43 | set(VERSION_PATCH_ 0) 44 | set(VERSION_BUILD_NUMBER_ 0) 45 | elseif(BUMP_MINOR) 46 | math(EXPR VERSION_MINOR_ "${VERSION_MINOR_}+1") 47 | set(VERSION_PATCH_ 0) 48 | set(VERSION_BUILD_NUMBER_ 0) 49 | elseif(BUMP_PATCH) 50 | math(EXPR VERSION_PATCH_ "${VERSION_PATCH_}+1") 51 | set(VERSION_BUILD_NUMBER_ 0) 52 | endif() 53 | 54 | math(EXPR VERSION_ "${VERSION_MAJOR_} << 22 | ${VERSION_MINOR_} << 12 | (${VERSION_PATCH_} & 0xfff)") 55 | 56 | set(VERSION_LIST_ ${VERSION_} ${VERSION_BUILD_NUMBER_} ${BUILD_NUMBER_}) 57 | file(WRITE metadata/version.dat "${VERSION_LIST_}") 58 | 59 | set(SEM_VERSION_ "extern const int PROJECT_VERSION_MAJOR=${VERSION_MAJOR_}; 60 | extern const int PROJECT_VERSION_MINOR=${VERSION_MINOR_}; 61 | extern const int PROJECT_VERSION_PATCH=${VERSION_PATCH_}; 62 | extern const int PROJECT_VERSION_BUILD_NUMBER=${VERSION_BUILD_NUMBER_}; 63 | extern const int PROJECT_BUILD_NUMBER=${BUILD_NUMBER_};") 64 | 65 | file(WRITE metadata/version.cpp "${SEM_VERSION_}") -------------------------------------------------------------------------------- /app/src/main/cpp/vk_util/vk_helpers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | using namespace ::std; 21 | using namespace ::vk; 22 | using namespace ::utilities; 23 | 24 | namespace vk_util 25 | { 26 | VKAPI_ATTR Bool32 VKAPI_CALL message_callback(DebugUtilsMessageSeverityFlagBitsEXT a_severity, 27 | DebugUtilsMessageTypeFlagsEXT a_msg_type, 28 | const DebugUtilsMessengerCallbackDataEXT *a_dbg_data, 29 | void* a_user_data) 30 | { 31 | string general_type = "General"; 32 | string performance_type = "Performance"; 33 | string validation_type = "Validation"; 34 | string msg_type; 35 | 36 | if(a_msg_type & DebugUtilsMessageTypeFlagBitsEXT::eGeneral) 37 | msg_type = general_type; 38 | else if(a_msg_type & DebugUtilsMessageTypeFlagBitsEXT::ePerformance) 39 | msg_type = performance_type; 40 | else if(a_msg_type & DebugUtilsMessageTypeFlagBitsEXT::eValidation) 41 | msg_type = validation_type; 42 | 43 | if(a_severity & DebugUtilsMessageSeverityFlagBitsEXT::eInfo) 44 | _log_android(log_level::info) << msg_type << " - " << a_dbg_data->pMessage; 45 | else if(a_severity & DebugUtilsMessageSeverityFlagBitsEXT::eWarning) 46 | _log_android(log_level::warning) << msg_type << " - " << a_dbg_data->pMessage; 47 | else if(a_severity & DebugUtilsMessageSeverityFlagBitsEXT::eVerbose) 48 | _log_android(log_level::debug) << msg_type << " - " << a_dbg_data->pMessage; 49 | else 50 | { 51 | // Special treatment for a specific validation error in order to avoid premature app exit 52 | // when validation layers are enabled. For an explanation read the following. 53 | // 54 | // It seems that for the camera-specific format (vulkan image resource external format = 506) 55 | // of the development device (Nokia 6.1, Adreno 508, Driver 512.415.0, Vulkan API Version 1.1.87), 56 | // the feature flag VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT is missing as reported by the hardware 57 | // buffer format properties. Although this external format seems to be lacking the mentioned 58 | // feature, the application works if the validation check is omitted. This is weird because 59 | // in order for an external image buffer of unknown to vulkan format, to be mapped in vulkan 60 | // space and consumed inside a vulkan context (via the use of a ycbcr sampler), its format 61 | // MUST support sampling feature. 62 | // 63 | // For more details see below: 64 | // - https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#samplers-YCbCr-conversion 65 | // - https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-VkImageViewCreateInfo-usage-02274 66 | // 67 | // Maybe this is an error in camera format definitions of the specific device. Don't have 68 | // the resources to test this in other devices (To be investigated). 69 | 70 | string msg_str(a_dbg_data->pMessage); 71 | 72 | array VUID_02274 = { 73 | "VUID-VkImageViewCreateInfo-usage-02274", 74 | "VK_FORMAT_UNDEFINED", 75 | "VK_IMAGE_TILING_OPTIMAL" 76 | }; 77 | 78 | auto ret_flag = VK_TRUE; 79 | 80 | if(msg_str.find(VUID_02274[0]) != string::npos) 81 | { 82 | if(msg_str.find(VUID_02274[1]) != string::npos && msg_str.find(VUID_02274[2]) != string::npos) 83 | ret_flag = VK_FALSE; 84 | } 85 | 86 | if(ret_flag) 87 | _log_android(log_level::error) << msg_type << " - " << a_dbg_data->pMessage; 88 | else 89 | _log_android(log_level::verbose) << msg_type << " - " << a_dbg_data->pMessage; 90 | 91 | return ret_flag; 92 | } 93 | 94 | return VK_FALSE; 95 | } 96 | 97 | string readable_size(size_t a_size) 98 | { 99 | static const vector suffixes{ { "B", "KB", "MB", "GB", "TB", "PB" } }; 100 | size_t suffixIndex = 0; 101 | while (suffixIndex < suffixes.size() - 1 && a_size > 1024) 102 | { 103 | a_size >>= 10; 104 | ++suffixIndex; 105 | } 106 | stringstream buffer; 107 | buffer << a_size << " " << suffixes[suffixIndex]; 108 | return buffer.str(); 109 | } 110 | 111 | perf_timer::perf_timer(const string &a_func) 112 | : m_func_name{a_func}, m_clock{std::chrono::high_resolution_clock::now()} 113 | {} 114 | 115 | perf_timer::~perf_timer() 116 | { 117 | using namespace std::chrono; 118 | auto ns = duration_cast(high_resolution_clock::now() - m_clock); 119 | _log_android(log_level::verbose) 120 | << "Function name: " << m_func_name << " - Time elapsed: " << ns.count() << " ns (" 121 | << 1.0e9 / static_cast(ns.count()) << " Hz)"; 122 | } 123 | 124 | u_long perf_timer::elapsed_ns() const 125 | { 126 | using namespace std::chrono; 127 | return (duration_cast(high_resolution_clock::now() - m_clock)).count(); 128 | } 129 | 130 | logger::logger(uint32_t a_box_width, uint32_t a_col_width, log_level a_log_level) 131 | : m_bw{a_box_width}, m_cw{a_col_width}, m_level{a_log_level} 132 | {} 133 | 134 | void logger::box_top() const 135 | { 136 | box_line("┌", "┐"); 137 | } 138 | 139 | void logger::box_bottom() const 140 | { 141 | box_line("└", "┘"); 142 | } 143 | 144 | void logger::box_separator() const 145 | { 146 | box_line(); 147 | } 148 | 149 | void logger::write_multiline(const char *a_str, const vector &a_vec, char a_fill) const 150 | { 151 | uint32_t char_count = 0, str_len = strlen(a_str); 152 | 153 | for(uint32_t i = 0; i < str_len; ++i) 154 | char_count += (a_str[i] & 0xC0) != 0x80; 155 | 156 | int w = m_bw - 1 + strlen(a_str) - char_count; 157 | auto l = m_level; 158 | 159 | vector lines; 160 | uint32_t cln {char_count}; 161 | stringstream sstr; 162 | 163 | for(auto& str : a_vec) 164 | { 165 | cln += str.length() + 3; 166 | if(cln > m_bw-2) 167 | { 168 | lines.push_back(sstr.str()); 169 | sstr.str(""); 170 | cln = char_count + str.length() + 3; 171 | } 172 | sstr << str << " | "; 173 | } 174 | 175 | auto str = sstr.str(); 176 | 177 | if(a_vec.size() < 1) 178 | str = "{}"; 179 | else 180 | str.resize(str.size()-3); 181 | 182 | lines.push_back(str); 183 | str = string(a_str); 184 | 185 | for(auto& wd : lines) 186 | { 187 | _log_android(l) 188 | << "|" << setfill(a_fill) << setw(w) << left << (str + wd).c_str() << "|"; 189 | str = string(char_count, ' '); 190 | } 191 | } 192 | 193 | void logger::write_line(const char *a_str, int a_align, char a_fill) const 194 | { 195 | uint32_t char_count = 0, str_len = strlen(a_str); 196 | 197 | for(uint32_t i = 0; i < str_len; ++i) 198 | char_count += (a_str[i] & 0xC0) != 0x80; 199 | 200 | int w = m_bw - 1 + strlen(a_str) - char_count; 201 | auto l = m_level; 202 | 203 | if (a_align == 0) 204 | _log_android(l) << "|" << setfill(a_fill) << setw(w) << left << a_str << "|"; 205 | else if (a_align == 1) 206 | _log_android(l) << "|" << setfill(a_fill) << setw(w) << centered(a_str) << "|"; 207 | else 208 | _log_android(l) << "|" << setfill(a_fill) << setw(w) << right << a_str << "|"; 209 | } 210 | 211 | void logger::write_line_2col(const char *a_lstr, const char *a_rstr, int a_align, char a_fill) const 212 | { 213 | uint32_t lchar_count = 0, rchar_count = 0, lstr_len = strlen(a_lstr), 214 | rstr_len = strlen(a_rstr); 215 | 216 | for(uint32_t i = 0; i < lstr_len; ++i) 217 | lchar_count += (a_lstr[i] & 0xC0) != 0x80; 218 | 219 | for(uint32_t i = 0; i < rstr_len; ++i) 220 | rchar_count += (a_rstr[i] & 0xC0) != 0x80; 221 | 222 | int sw = m_cw + strlen(a_rstr) - rchar_count, 223 | w = m_bw - m_cw - 1 + strlen(a_lstr) - lchar_count; 224 | auto l = m_level; 225 | char c = a_fill; 226 | 227 | if (a_align == 0) 228 | _log_android(l) << "|" << setfill(c) << setw(w) << left << a_lstr << setfill(c) 229 | << setw(sw) << left << a_rstr << "|"; 230 | else if (a_align == 1) 231 | _log_android(l) << "|" << setfill(c) << setw(w) << centered(a_lstr) << setfill(c) 232 | << setw(sw) << centered(a_rstr) << "|"; 233 | else 234 | _log_android(l) << "|" << setfill(c) << setw(w) << right << a_lstr << setfill(c) 235 | << setw(sw) << right << a_rstr << "|"; 236 | } 237 | 238 | void logger::box_line(const char *a_start, const char *a_end, char a_fill) const 239 | { 240 | int w = m_bw + strlen(a_end) - 1; 241 | auto l = m_level; 242 | _log_android(l) << a_start << setfill(a_fill) << setw(w) << a_end; 243 | } 244 | } -------------------------------------------------------------------------------- /app/src/main/cpp/vk_util/vk_helpers.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_VK_HELPERS_HPP 19 | #define NCV_VK_HELPERS_HPP 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #ifdef NCV_PROFILING_ENABLED 26 | constexpr bool __ncv_profiling_enabled = true; 27 | #else 28 | constexpr bool __ncv_profiling_enabled = false; 29 | #endif 30 | 31 | namespace vk_util 32 | { 33 | class perf_timer 34 | { 35 | public: 36 | 37 | perf_timer(const std::string& a_func); 38 | ~perf_timer(); 39 | u_long elapsed_ns() const; 40 | 41 | private: 42 | 43 | std::string m_func_name; 44 | std::chrono::time_point m_clock; 45 | }; 46 | 47 | class logger 48 | { 49 | public: 50 | 51 | enum align {cleft = 0, ccenter, cright}; 52 | 53 | logger(uint32_t a_box_width, uint32_t a_col_width, 54 | ::utilities::log_level a_log_level = ::utilities::log_level::debug); 55 | 56 | void box_top() const; 57 | void box_bottom() const; 58 | void box_separator() const; 59 | void write_multiline(const char* a_str, const std::vector& a_vec, char a_fill = ' ') const; 60 | void write_line(const char* a_str, int a_align = 0, char a_fill = ' ') const; 61 | void write_line_2col(const char* a_lstr, const char* a_rstr, int a_align = 0, char a_fill = ' ') const; 62 | 63 | private: 64 | 65 | void box_line(const char* a_start = "|", const char* a_end = "|", char a_fill = '-') const; 66 | 67 | uint32_t m_bw, m_cw; 68 | ::utilities::log_level m_level; 69 | }; 70 | 71 | VKAPI_ATTR vk::Bool32 VKAPI_CALL message_callback(vk::DebugUtilsMessageSeverityFlagBitsEXT a_severity, 72 | vk::DebugUtilsMessageTypeFlagsEXT a_msg_type, const vk::DebugUtilsMessengerCallbackDataEXT *a_dbg_data, 73 | void* a_user_data); 74 | 75 | std::string readable_size(size_t a_size); 76 | 77 | template 78 | inline std::vector split_to_vector(const T& a_vk_arg) 79 | { 80 | auto pos = std::string::npos; 81 | auto str = to_string(a_vk_arg); 82 | str = str.erase(0, str.find_first_not_of("{\t\n\v\f\r ")); 83 | str = str.erase(str.find_last_not_of("{\t\n\v\f\r ")); 84 | while((pos = str.find("| ")) != std::string::npos) 85 | str.erase(pos, 2); 86 | std::stringstream sstr(str); 87 | std::istream_iterator begin{sstr}, end; 88 | return std::vector(begin, end); 89 | } 90 | } 91 | 92 | #endif //NCV_VK_HELPERS_HPP 93 | -------------------------------------------------------------------------------- /app/src/main/cpp/vk_util/vk_version.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #ifndef NCV_VK_VERSION_HPP 19 | #define NCV_VK_VERSION_HPP 20 | 21 | #include 22 | 23 | namespace vk_util 24 | { 25 | struct version 26 | { 27 | version() : major{0}, minor{0}, patch{0} 28 | {} 29 | 30 | version(uint32_t version) : ::vk_util::version{} 31 | { 32 | *this = version; 33 | } 34 | 35 | version& operator=(uint32_t version) 36 | { 37 | memcpy(this, &version, sizeof(uint32_t)); 38 | return *this; 39 | } 40 | 41 | operator uint32_t() const 42 | { 43 | uint32_t result; 44 | memcpy(&result, this, sizeof(uint32_t)); 45 | return result; 46 | } 47 | 48 | bool operator>=(const version &other) const 49 | { 50 | return (operator uint32_t()) >= (other.operator uint32_t()); 51 | } 52 | 53 | std::string to_string() const 54 | { 55 | std::stringstream buffer; 56 | buffer << major << "." << minor << "." << patch; 57 | return buffer.str(); 58 | } 59 | 60 | const uint32_t patch: 12; 61 | const uint32_t minor: 10; 62 | const uint32_t major: 10; 63 | }; 64 | 65 | } 66 | 67 | #endif //NCV_VK_VERSION_HPP 68 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | native-camera-vulkan 3 | -------------------------------------------------------------------------------- /app/src/main/shaders/camera-mapping.frag: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #version 450 19 | #extension GL_ARB_separate_shader_objects : enable 20 | 21 | layout(binding = 1) uniform sampler2D cam_sampler; 22 | 23 | layout(location = 0) in vec3 i_color; 24 | layout(location = 1) in vec2 i_tex_coords; 25 | 26 | layout(location = 0) out vec4 o_color; 27 | 28 | void main() { 29 | o_color = texture(cam_sampler, i_tex_coords); 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/shaders/image-mapping.frag: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #version 450 19 | #extension GL_ARB_separate_shader_objects : enable 20 | 21 | layout(binding = 1) uniform sampler2D tex_sampler; 22 | 23 | layout(location = 0) in vec3 i_color; 24 | layout(location = 1) in vec2 i_tex_coords; 25 | 26 | layout(location = 0) out vec4 o_color; 27 | 28 | void main() { 29 | o_color = texture(tex_sampler, i_tex_coords) + 0.1f; 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/shaders/simple.vert: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #version 450 19 | #extension GL_ARB_separate_shader_objects : enable 20 | 21 | layout(binding = 0) uniform UniformBufferObject { 22 | mat4 model; 23 | mat4 view; 24 | mat4 proj; 25 | } ubo; 26 | 27 | layout(location = 0) in vec4 i_position; 28 | layout(location = 1) in vec4 i_color; 29 | layout(location = 2) in vec2 i_tex_coords; 30 | 31 | layout(location = 0) out vec3 o_color; 32 | layout(location = 1) out vec2 o_tex_coords; 33 | 34 | void main(){ 35 | gl_Position = ubo.proj * ubo.view * ubo.model * i_position; 36 | o_color = i_color.rgb; 37 | o_tex_coords = i_tex_coords; 38 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | buildscript { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | dependencies { 24 | classpath 'com.android.tools.build:gradle:4.1.1' 25 | } 26 | } 27 | 28 | allprojects { 29 | repositories { 30 | google() 31 | jcenter() 32 | } 33 | } 34 | 35 | task clean(type: Delete) { 36 | delete rootProject.buildDir 37 | } -------------------------------------------------------------------------------- /doc/res/android-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/res/cpp-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/res/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/doc/res/demo.gif -------------------------------------------------------------------------------- /doc/res/toc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /doc/res/vulkan-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ktzevani/native-camera-vulkan/b9c03c956f8e9c2bda05ae31060d09518fd5790b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Oct 24 16:11:57 EEST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https://services.gradle.org/distributions/gradle-6.5-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Konstantinos Tzevanidis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | include ':app' 19 | rootProject.name = "native-camera-vulkan" --------------------------------------------------------------------------------