├── .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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
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