├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── CMakeLists.txt ├── build.gradle ├── conanfile.txt ├── debug.keystore ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── sample_tex.png │ ├── cpp │ ├── vulkan_tutorial.cpp │ ├── vulkan_tutorial.h │ ├── vulkan_tutorial_jni.cpp │ └── vulkan_wrapper │ │ ├── vulkan_wrapper.cpp │ │ └── vulkan_wrapper.h │ ├── java │ └── com │ │ └── github │ │ └── piasy │ │ └── vulkantutorial │ │ ├── MainActivity.java │ │ └── VulkanTutorialApplication.java │ ├── res │ ├── layout │ │ └── activity_main.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 │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── shaders │ ├── triangle.frag │ └── triangle.vert ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | **.iml 2 | .gradle 3 | /local.properties 4 | /.idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | /app/conan_build/ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Piasy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VulkanTutorial-Android 2 | 3 | Step by step tutorial of Vulkan on Android, follow https://vulkan-tutorial.com. 4 | 5 | + We need [`vulkan_wrapper`](https://developer.android.com/ndk/guides/graphics/getting-started.html#using) on Android, which could be [download from GitHub](https://github.com/LunarG/VulkanSamples/tree/master/common). 6 | + In Android Studio, just put shader code under `src/main/shaders` folder, they will be compiled into `.spv` files, and packaged as assets. 7 | 8 | ## Conan package manager 9 | 10 | Conan support is setup according to [this tutorial](https://docs.conan.io/en/latest/integrations/android_studio.html), to install conan, run `pip install conan`. 11 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | include(${CMAKE_CURRENT_SOURCE_DIR}/conan_build/conanbuildinfo.cmake) 9 | set(CMAKE_CXX_COMPILER_VERSION "5.0") # Unknown miss-detection of the compiler by CMake 10 | conan_basic_setup(TARGETS) 11 | 12 | # Creates and names a library, sets it as either STATIC 13 | # or SHARED, and provides the relative paths to its source code. 14 | # You can define multiple libraries, and CMake builds them for you. 15 | # Gradle automatically packages shared libraries with your APK. 16 | 17 | # build vulkan app 18 | set(SRC_DIR src/main/cpp) 19 | set(VK_WRAPPER_DIR src/main/cpp/vulkan_wrapper) 20 | set(VK_VAL_LAYER_SRC_DIR ${ANDROID_NDK}/sources/third_party/vulkan/src) 21 | 22 | add_library( # Sets the name of the library. 23 | vulkan-tutorial 24 | 25 | # Sets the library as a shared library. 26 | SHARED 27 | 28 | # Provides a relative path to your source file(s). 29 | ${VK_WRAPPER_DIR}/vulkan_wrapper.cpp 30 | ${SRC_DIR}/vulkan_tutorial.cpp 31 | ${SRC_DIR}/vulkan_tutorial_jni.cpp 32 | ) 33 | 34 | include_directories(${VK_WRAPPER_DIR} ${VK_VAL_LAYER_SRC_DIR}/include ${CONAN_INCLUDE_DIRS}) 35 | 36 | # Searches for a specified prebuilt library and stores the path as a 37 | # variable. Because CMake includes system libraries in the search path by 38 | # default, you only need to specify the name of the public NDK library 39 | # you want to add. CMake verifies that the library exists before 40 | # completing its build. 41 | 42 | find_library( # Sets the name of the path variable. 43 | log-lib 44 | 45 | # Specifies the name of the NDK library that 46 | # you want CMake to locate. 47 | log ) 48 | 49 | # Specifies libraries CMake should link to your target library. You 50 | # can link multiple libraries, such as libraries you define in this 51 | # build script, prebuilt third-party libraries, or system libraries. 52 | 53 | target_link_libraries( # Specifies the target library. 54 | vulkan-tutorial 55 | 56 | ${CONAN_LIBS} 57 | 58 | # Links the target library to the log library 59 | # included in the NDK. 60 | ${log-lib} 61 | android) 62 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | Properties properties = new Properties() 4 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 5 | def ndkDir = properties.getProperty('ndk.dir') 6 | def valLayerBinDir = "${ndkDir}/sources/third_party/vulkan/src/build-android/jniLibs" 7 | 8 | android { 9 | compileSdkVersion 27 10 | buildToolsVersion "27.0.3" 11 | defaultConfig { 12 | applicationId "com.github.piasy.vulkantutorial" 13 | minSdkVersion 24 14 | targetSdkVersion 27 15 | versionCode 1 16 | versionName "1.0" 17 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 18 | 19 | externalNativeBuild { 20 | cmake { 21 | cppFlags "-frtti -fexceptions -std=c++11 -Werror -Wno-unused-variable" 22 | } 23 | } 24 | 25 | ndk.abiFilters = ['armeabi-v7a'] 26 | } 27 | 28 | sourceSets { 29 | debug { 30 | ndkDir = 'src/main/cpp' 31 | jniLibs { 32 | // Must have ndk-r12 or better which including layer binaries 33 | srcDirs = ["${valLayerBinDir}"] 34 | } 35 | } 36 | } 37 | 38 | signingConfigs { 39 | debug { 40 | storeFile file('debug.keystore') 41 | } 42 | } 43 | 44 | buildTypes { 45 | debug { 46 | debuggable true 47 | minifyEnabled false 48 | signingConfig signingConfigs.debug 49 | 50 | externalNativeBuild { 51 | cmake { 52 | cppFlags "-DUSE_DEBUG_EXTENTIONS -DVK_USE_PLATFORM_ANDROID_KHR" 53 | } 54 | } 55 | } 56 | release { 57 | minifyEnabled false 58 | signingConfig signingConfigs.debug 59 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 60 | 61 | externalNativeBuild { 62 | cmake { 63 | cppFlags "-DVK_USE_PLATFORM_ANDROID_KHR" 64 | } 65 | } 66 | } 67 | } 68 | 69 | externalNativeBuild { 70 | cmake { 71 | path "CMakeLists.txt" 72 | } 73 | } 74 | } 75 | 76 | task conanInstall { 77 | def buildDir = new File("app/conan_build") 78 | buildDir.mkdirs() 79 | // if you have problems running the command try to specify the absolute 80 | // path to conan (Known problem in MacOSX) /usr/local/bin/conan 81 | def cmd = "conan install ../conanfile.txt --profile android_21_arm_clang --build missing" 82 | print(">> ${cmd} \n") 83 | 84 | def sout = new StringBuilder(), serr = new StringBuilder() 85 | def proc = cmd.execute(null, buildDir) 86 | proc.consumeProcessOutput(sout, serr) 87 | proc.waitFor() 88 | println "$sout $serr" 89 | if (proc.exitValue() != 0) { 90 | throw new Exception("out> $sout err> $serr" + "\nCommand: ${cmd}") 91 | } 92 | } 93 | 94 | dependencies { 95 | implementation 'com.android.support:appcompat-v7:27.1.1' 96 | } 97 | -------------------------------------------------------------------------------- /app/conanfile.txt: -------------------------------------------------------------------------------- 1 | [requires] 2 | glm/0.9.8.5@g-truc/stable 3 | stb/20180214@conan/stable 4 | 5 | [generators] 6 | cmake 7 | -------------------------------------------------------------------------------- /app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Piasy/VulkanTutorial-Android/7c295c1acb052acfa901a61b896b617aa273e817/app/debug.keystore -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/piasy/tools/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/assets/sample_tex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Piasy/VulkanTutorial-Android/7c295c1acb052acfa901a61b896b617aa273e817/app/src/main/assets/sample_tex.png -------------------------------------------------------------------------------- /app/src/main/cpp/vulkan_tutorial.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Piasy on 26/06/2017. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define GLM_FORCE_RADIANS 11 | #include 12 | 13 | #define STB_IMAGE_IMPLEMENTATION 14 | #include 15 | 16 | #include "vulkan_tutorial.h" 17 | 18 | const int WIDTH = 800; 19 | const int HEIGHT = 448; 20 | 21 | const std::vector validationLayers = { 22 | "VK_LAYER_LUNARG_image", 23 | "VK_LAYER_GOOGLE_threading", 24 | "VK_LAYER_LUNARG_core_validation", 25 | "VK_LAYER_LUNARG_object_tracker", 26 | "VK_LAYER_LUNARG_swapchain", 27 | "VK_LAYER_LUNARG_parameter_validation", 28 | "VK_LAYER_GOOGLE_unique_objects", 29 | }; 30 | 31 | const std::vector deviceExtensions = { 32 | VK_KHR_SWAPCHAIN_EXTENSION_NAME 33 | }; 34 | 35 | const std::vector vertices = { 36 | {{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}}, 37 | {{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}}, 38 | {{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, 39 | {{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}} 40 | }; 41 | const std::vector indices = { 42 | 0, 1, 2, 2, 3, 0 43 | }; 44 | 45 | const std::string IMAGE_PATH = "sample_tex.png"; 46 | 47 | #ifdef USE_DEBUG_EXTENTIONS 48 | const bool enableValidationLayers = true; 49 | #else 50 | const bool enableValidationLayers = false; 51 | #endif 52 | 53 | VkResult CreateDebugReportCallbackEXT( 54 | VkInstance instance, 55 | const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 56 | const VkAllocationCallbacks *pAllocator, 57 | VkDebugReportCallbackEXT *pCallback) { 58 | auto func = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, 59 | "vkCreateDebugReportCallbackEXT"); 60 | if (func != nullptr) { 61 | return func(instance, pCreateInfo, pAllocator, pCallback); 62 | } else { 63 | return VK_ERROR_EXTENSION_NOT_PRESENT; 64 | } 65 | } 66 | 67 | void DestroyDebugReportCallbackEXT( 68 | VkInstance instance, 69 | VkDebugReportCallbackEXT callback, 70 | const VkAllocationCallbacks *pAllocator) { 71 | auto func = (PFN_vkDestroyDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, 72 | "vkDestroyDebugReportCallbackEXT"); 73 | if (func != nullptr) { 74 | func(instance, callback, pAllocator); 75 | } 76 | } 77 | 78 | static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( 79 | VkDebugReportFlagsEXT flags, 80 | VkDebugReportObjectTypeEXT objType, 81 | uint64_t obj, 82 | size_t location, 83 | int32_t code, 84 | const char *layerPrefix, 85 | const char *msg, 86 | void *userData) { 87 | if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { 88 | __android_log_print(ANDROID_LOG_ERROR, 89 | APP_NAME, 90 | "ERROR: [%s] Code %i : %s", 91 | layerPrefix, code, msg); 92 | } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { 93 | __android_log_print(ANDROID_LOG_WARN, 94 | APP_NAME, 95 | "WARNING: [%s] Code %i : %s", 96 | layerPrefix, code, msg); 97 | } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { 98 | __android_log_print(ANDROID_LOG_WARN, 99 | APP_NAME, 100 | "PERFORMANCE WARNING: [%s] Code %i : %s", 101 | layerPrefix, code, msg); 102 | } else if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { 103 | __android_log_print(ANDROID_LOG_INFO, 104 | APP_NAME, 105 | "INFO: [%s] Code %i : %s", 106 | layerPrefix, code, msg); 107 | } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { 108 | __android_log_print(ANDROID_LOG_VERBOSE, 109 | APP_NAME, 110 | "DEBUG: [%s] Code %i : %s", 111 | layerPrefix, code, msg); 112 | } 113 | 114 | // Returning false tells the layer not to stop when the event occurs, so 115 | // they see the same behavior with and without validation layers enabled. 116 | return VK_FALSE; 117 | } 118 | 119 | VkSurfaceFormatKHR chooseSwapSurfaceFormat( 120 | const std::vector &availableFormats) { 121 | if (availableFormats.size() == 1 && availableFormats[0].format == VK_FORMAT_UNDEFINED) { 122 | return {VK_FORMAT_B8G8R8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; 123 | } 124 | 125 | for (const auto &format : availableFormats) { 126 | if (format.format == VK_FORMAT_B8G8R8_UNORM 127 | && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { 128 | return format; 129 | } 130 | } 131 | 132 | return availableFormats[0]; 133 | } 134 | 135 | VkPresentModeKHR chooseSwapPresentMode( 136 | const std::vector &availablePresentModes) { 137 | VkPresentModeKHR bestMode = VK_PRESENT_MODE_FIFO_KHR; 138 | 139 | for (const auto &mode : availablePresentModes) { 140 | if (mode == VK_PRESENT_MODE_MAILBOX_KHR) { 141 | return mode; 142 | } else if (mode == VK_PRESENT_MODE_IMMEDIATE_KHR) { 143 | bestMode = mode; 144 | } 145 | } 146 | 147 | return bestMode; 148 | } 149 | 150 | VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities) { 151 | if (capabilities.currentExtent.width != std::numeric_limits::max()) { 152 | return capabilities.currentExtent; 153 | } 154 | 155 | VkExtent2D actualExtent = {WIDTH, HEIGHT}; 156 | actualExtent.width = std::max( 157 | capabilities.minImageExtent.width, 158 | std::min(capabilities.maxImageExtent.width, actualExtent.width) 159 | ); 160 | actualExtent.height = std::max( 161 | capabilities.minImageExtent.height, 162 | std::min(capabilities.maxImageExtent.height, actualExtent.height) 163 | ); 164 | 165 | return actualExtent; 166 | } 167 | 168 | bool supportValidationLayers() { 169 | uint32_t layerCount = 0; 170 | vkEnumerateInstanceLayerProperties(&layerCount, nullptr); 171 | 172 | LOGI("layer count: %d", layerCount); 173 | 174 | std::vector availableLayers(layerCount); 175 | vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); 176 | 177 | for (const auto &layer : availableLayers) { 178 | LOGI("\t layer: %s", layer.layerName); 179 | } 180 | 181 | for (const char *layerName : validationLayers) { 182 | bool found = false; 183 | for (const auto &layer : availableLayers) { 184 | if (strcmp(layerName, layer.layerName) == 0) { 185 | found = true; 186 | break; 187 | } 188 | } 189 | 190 | if (!found) { 191 | return false; 192 | } 193 | } 194 | 195 | return true; 196 | } 197 | 198 | std::vector requiredExtensions() { 199 | std::vector extensionNames; 200 | uint32_t extensionCount = 0; 201 | vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); 202 | 203 | LOGI("extension count: %d", extensionCount); 204 | 205 | std::vector extensions(extensionCount); 206 | vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); 207 | 208 | for (const auto &extension : extensions) { 209 | if (strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, extension.extensionName) == 0) { 210 | if (enableValidationLayers) { 211 | extensionNames.push_back(extension.extensionName); 212 | } 213 | } else { 214 | extensionNames.push_back(extension.extensionName); 215 | } 216 | 217 | LOGI("\t extension: %s", extension.extensionName); 218 | } 219 | return extensionNames; 220 | } 221 | 222 | void VulkanTutorialApplication::run(ANativeWindow *window) { 223 | initWindow(window); 224 | initVulkan(); 225 | mainLoop(); 226 | cleanUp(); 227 | } 228 | 229 | void VulkanTutorialApplication::pause() { 230 | state = STATE_PAUSED; 231 | vkDeviceWaitIdle(device); 232 | } 233 | 234 | void VulkanTutorialApplication::surfaceChanged() { 235 | state = STATE_PAUSED; 236 | recreateSwapchain(); 237 | state = STATE_RUNNING; 238 | } 239 | 240 | void VulkanTutorialApplication::initVulkan() { 241 | if (!InitVulkan()) { 242 | throw std::runtime_error("InitVulkan fail!"); 243 | } 244 | 245 | createInstance(); 246 | setUpDebugCallback(); 247 | createSurface(); 248 | 249 | pickPhysicalDevice(); 250 | createLogicalDevice(); 251 | 252 | createSwapchain(); 253 | createImageViews(); 254 | createRenderPass(); 255 | createDescriptorSetLayout(); 256 | createGraphicsPipeline(); 257 | createFramebuffers(); 258 | 259 | createCommandPool(); 260 | createTextureImage(); 261 | createTextureImageView(); 262 | createTextureSampler(); 263 | 264 | createVertexBuffer(); 265 | createIndexBuffer(); 266 | createUniformBuffer(); 267 | createDescriptorPool(); 268 | createDescriptorSet(); 269 | createCommandBuffers(); 270 | 271 | createSemaphores(); 272 | } 273 | 274 | void VulkanTutorialApplication::mainLoop() { 275 | LOGI("mainLoop start"); 276 | 277 | while (state != STATE_EXIT) { 278 | if (state == STATE_RUNNING) { 279 | updateUniformBuffer(); 280 | drawFrame(); 281 | } 282 | } 283 | 284 | vkDeviceWaitIdle(device); 285 | 286 | LOGI("mainLoop exit"); 287 | } 288 | 289 | void VulkanTutorialApplication::cleanUp() { 290 | cleanupSwapchain(); 291 | 292 | vkDestroyDescriptorPool(device, descriptorPool, nullptr); 293 | vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); 294 | vkDestroyBuffer(device, uniformBuffer, nullptr); 295 | vkFreeMemory(device, uniformBufferMemory, nullptr); 296 | 297 | vkDestroyBuffer(device, indexBuffer, nullptr); 298 | vkFreeMemory(device, indexBufferMemory, nullptr); 299 | 300 | vkDestroyBuffer(device, vertexBuffer, nullptr); 301 | vkFreeMemory(device, vertexBufferMemory, nullptr); 302 | 303 | vkDestroySemaphore(device, renderFinishedSemaphore, nullptr); 304 | vkDestroySemaphore(device, imageAvailableSemaphore, nullptr); 305 | 306 | vkDestroyCommandPool(device, commandPool, nullptr); 307 | 308 | vkDestroyDevice(device, nullptr); 309 | DestroyDebugReportCallbackEXT(instance, callback, nullptr); 310 | vkDestroySurfaceKHR(instance, surface, nullptr); 311 | vkDestroyInstance(instance, nullptr); 312 | 313 | ANativeWindow_release(window); 314 | } 315 | 316 | void VulkanTutorialApplication::createInstance() { 317 | if (enableValidationLayers && !supportValidationLayers()) { 318 | throw std::runtime_error("validation layers requested, but not available!"); 319 | } 320 | 321 | VkApplicationInfo appInfo = { 322 | .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 323 | .pApplicationName = "Hello Triangle", 324 | .applicationVersion = VK_MAKE_VERSION(1, 0, 0), 325 | .pEngineName = "No Engine", 326 | .engineVersion = VK_MAKE_VERSION(1, 0, 0), 327 | .apiVersion = VK_API_VERSION_1_0, 328 | }; 329 | 330 | auto extensions = requiredExtensions(); 331 | VkInstanceCreateInfo createInfo = { 332 | .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 333 | .pApplicationInfo = &appInfo, 334 | .enabledExtensionCount = static_cast(extensions.size()), 335 | .ppEnabledExtensionNames = extensions.data(), 336 | }; 337 | if (enableValidationLayers) { 338 | createInfo.enabledLayerCount = static_cast(validationLayers.size()); 339 | createInfo.ppEnabledLayerNames = validationLayers.data(); 340 | } else { 341 | createInfo.enabledLayerCount = 0; 342 | } 343 | 344 | if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { 345 | throw std::runtime_error("create instance fail!"); 346 | } 347 | 348 | LOGI("createInstance success :)"); 349 | } 350 | 351 | void VulkanTutorialApplication::setUpDebugCallback() { 352 | if (!enableValidationLayers) { 353 | return; 354 | } 355 | 356 | VkDebugReportCallbackCreateInfoEXT createInfo = {}; 357 | createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; 358 | createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT 359 | | VK_DEBUG_REPORT_WARNING_BIT_EXT 360 | | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 361 | createInfo.pfnCallback = debugCallback; 362 | 363 | if (CreateDebugReportCallbackEXT(instance, &createInfo, nullptr, &callback) != VK_SUCCESS) { 364 | throw std::runtime_error("failed to set up debug callback!"); 365 | } 366 | } 367 | 368 | void VulkanTutorialApplication::createSurface() { 369 | VkAndroidSurfaceCreateInfoKHR createInfo = {}; 370 | createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; 371 | createInfo.window = window; 372 | 373 | if (vkCreateAndroidSurfaceKHR(instance, &createInfo, nullptr, &surface) != VK_SUCCESS) { 374 | throw std::runtime_error("failed to create window surface!"); 375 | } 376 | } 377 | 378 | void VulkanTutorialApplication::pickPhysicalDevice() { 379 | uint32_t deviceCount = 0; 380 | vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); 381 | 382 | LOGI("device count: %d", deviceCount); 383 | 384 | if (deviceCount == 0) { 385 | throw std::runtime_error("failed to find GPUs with Vulkan support!"); 386 | } 387 | 388 | std::vector devices(deviceCount); 389 | vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); 390 | 391 | for (const auto &device : devices) { 392 | if (isDeviceSuitable(device)) { 393 | physicalDevice = device; 394 | break; 395 | } 396 | } 397 | 398 | if (physicalDevice == VK_NULL_HANDLE) { 399 | throw std::runtime_error("failed to find a suitable GPU!"); 400 | } 401 | } 402 | 403 | void VulkanTutorialApplication::createLogicalDevice() { 404 | QueueFamilyIndices indices = findQueueFamilies(physicalDevice); 405 | 406 | std::vector queueCreateInfos; 407 | std::set uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily}; 408 | float queuePriority = 1.0F; 409 | 410 | for (int queueFamily : uniqueQueueFamilies) { 411 | VkDeviceQueueCreateInfo queueCreateInfo = {}; 412 | queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 413 | queueCreateInfo.queueFamilyIndex = queueFamily; 414 | queueCreateInfo.queueCount = 1; 415 | queueCreateInfo.pQueuePriorities = &queuePriority; 416 | 417 | queueCreateInfos.push_back(queueCreateInfo); 418 | } 419 | 420 | VkPhysicalDeviceFeatures deviceFeatures = {}; 421 | 422 | VkDeviceCreateInfo createInfo = {}; 423 | createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 424 | createInfo.pQueueCreateInfos = queueCreateInfos.data(); 425 | createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); 426 | createInfo.pEnabledFeatures = &deviceFeatures; 427 | createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); 428 | createInfo.ppEnabledExtensionNames = deviceExtensions.data(); 429 | 430 | if (enableValidationLayers) { 431 | createInfo.enabledLayerCount = static_cast(validationLayers.size()); 432 | createInfo.ppEnabledLayerNames = validationLayers.data(); 433 | } else { 434 | createInfo.enabledLayerCount = 0; 435 | } 436 | 437 | if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { 438 | throw std::runtime_error("failed to create logical device!"); 439 | } 440 | 441 | vkGetDeviceQueue(device, indices.graphicsFamily, 0, &graphicsQueue); 442 | vkGetDeviceQueue(device, indices.presentFamily, 0, &presentQueue); 443 | } 444 | 445 | void VulkanTutorialApplication::createSwapchain() { 446 | SwapchainSupportDetails swapchainSupport = querySwapchainSupport(physicalDevice); 447 | VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapchainSupport.formats); 448 | VkPresentModeKHR presentMode = chooseSwapPresentMode(swapchainSupport.presentModes); 449 | VkExtent2D extent = chooseSwapExtent(swapchainSupport.capabilities); 450 | 451 | uint32_t imageCount = swapchainSupport.capabilities.minImageCount + 1; 452 | if (swapchainSupport.capabilities.maxImageCount > 0 453 | && imageCount > swapchainSupport.capabilities.maxImageCount) { 454 | imageCount = swapchainSupport.capabilities.maxImageCount; 455 | } 456 | 457 | VkSwapchainCreateInfoKHR createInfo = {}; 458 | createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 459 | createInfo.surface = surface; 460 | createInfo.minImageCount = imageCount; 461 | createInfo.imageFormat = surfaceFormat.format; 462 | createInfo.imageColorSpace = surfaceFormat.colorSpace; 463 | createInfo.imageExtent = extent; 464 | createInfo.imageArrayLayers = 1; 465 | createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 466 | 467 | QueueFamilyIndices indices = findQueueFamilies(physicalDevice); 468 | if (indices.graphicsFamily != indices.presentFamily) { 469 | uint32_t queueFamilyIndices[] = { 470 | (uint32_t) indices.graphicsFamily, (uint32_t) indices.presentFamily 471 | }; 472 | createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; 473 | createInfo.queueFamilyIndexCount = 2; 474 | createInfo.pQueueFamilyIndices = queueFamilyIndices; 475 | } else { 476 | createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 477 | } 478 | 479 | createInfo.preTransform = swapchainSupport.capabilities.currentTransform; 480 | createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; 481 | createInfo.presentMode = presentMode; 482 | createInfo.clipped = VK_TRUE; 483 | createInfo.oldSwapchain = VK_NULL_HANDLE; 484 | 485 | if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapchain) != VK_SUCCESS) { 486 | throw std::runtime_error("failed to create swap chain!"); 487 | } 488 | 489 | vkGetSwapchainImagesKHR(device, swapchain, &imageCount, nullptr); 490 | swapchainImages.resize(imageCount); 491 | vkGetSwapchainImagesKHR(device, swapchain, &imageCount, swapchainImages.data()); 492 | 493 | swapchainImageFormat = surfaceFormat.format; 494 | swapchainExtent = extent; 495 | } 496 | 497 | void VulkanTutorialApplication::createImageViews() { 498 | swapchainImageViews.resize(swapchainImages.size()); 499 | for (size_t i = 0; i < swapchainImages.size(); i++) { 500 | VkImageViewCreateInfo createInfo = {}; 501 | createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 502 | createInfo.image = swapchainImages[i]; 503 | 504 | createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; 505 | createInfo.format = swapchainImageFormat; 506 | 507 | createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; 508 | createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; 509 | createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; 510 | createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; 511 | 512 | createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 513 | createInfo.subresourceRange.baseMipLevel = 0; 514 | createInfo.subresourceRange.levelCount = 1; 515 | createInfo.subresourceRange.baseArrayLayer = 0; 516 | createInfo.subresourceRange.layerCount = 1; 517 | 518 | if (vkCreateImageView(device, &createInfo, nullptr, &swapchainImageViews[i]) != 519 | VK_SUCCESS) { 520 | throw std::runtime_error("failed to create image views!"); 521 | } 522 | } 523 | } 524 | 525 | void VulkanTutorialApplication::createRenderPass() { 526 | VkAttachmentDescription colorAttachment = {}; 527 | colorAttachment.format = swapchainImageFormat; 528 | colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; 529 | colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 530 | colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 531 | colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 532 | colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 533 | colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 534 | colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 535 | 536 | VkAttachmentReference colorAttachmentRef = {}; 537 | colorAttachmentRef.attachment = 0; 538 | colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 539 | 540 | VkSubpassDescription subpass = {}; 541 | subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 542 | subpass.colorAttachmentCount = 1; 543 | subpass.pColorAttachments = &colorAttachmentRef; 544 | 545 | VkRenderPassCreateInfo renderPassInfo = {}; 546 | renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 547 | renderPassInfo.attachmentCount = 1; 548 | renderPassInfo.pAttachments = &colorAttachment; 549 | renderPassInfo.subpassCount = 1; 550 | renderPassInfo.pSubpasses = &subpass; 551 | 552 | if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { 553 | throw std::runtime_error("failed to create render pass!"); 554 | } 555 | } 556 | 557 | void VulkanTutorialApplication::createDescriptorSetLayout() { 558 | VkDescriptorSetLayoutBinding uboLayoutBinding = { 559 | .binding = 0, 560 | .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 561 | .descriptorCount = 1, 562 | .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, 563 | .pImmutableSamplers = nullptr, 564 | }; 565 | 566 | VkDescriptorSetLayoutBinding samplerLayoutBinding = { 567 | .binding = 1, 568 | .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 569 | .descriptorCount = 1, 570 | .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, 571 | .pImmutableSamplers = nullptr, 572 | }; 573 | 574 | std::array bindings = {uboLayoutBinding,samplerLayoutBinding}; 575 | 576 | VkDescriptorSetLayoutCreateInfo layoutInfo = { 577 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 578 | .bindingCount = static_cast(bindings.size()), 579 | .pBindings = bindings.data(), 580 | }; 581 | 582 | if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) 583 | != VK_SUCCESS) { 584 | throw std::runtime_error("failed to create descriptor set layout!"); 585 | } 586 | } 587 | 588 | void VulkanTutorialApplication::createGraphicsPipeline() { 589 | auto vertexShaderCode = readAsset(vertexShader); 590 | auto fragmentShaderCode = readAsset(fragmentShader); 591 | VkShaderModule vertexShaderModule = createShaderModule(vertexShaderCode); 592 | VkShaderModule fragmentShaderModule = createShaderModule(fragmentShaderCode); 593 | VkPipelineShaderStageCreateInfo vertexShaderStageInfo = { 594 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 595 | .stage = VK_SHADER_STAGE_VERTEX_BIT, 596 | .module = vertexShaderModule, 597 | .pName = "main", 598 | }; 599 | VkPipelineShaderStageCreateInfo fragmentShaderStageInfo = { 600 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 601 | .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 602 | .module = fragmentShaderModule, 603 | .pName = "main", 604 | }; 605 | VkPipelineShaderStageCreateInfo shaderStages[] = { 606 | vertexShaderStageInfo, fragmentShaderStageInfo 607 | }; 608 | 609 | auto bindingDesc = Vertex::getBindingDescription(); 610 | auto attrDesc = Vertex::getAttributeDescriptions(); 611 | VkPipelineVertexInputStateCreateInfo vertexInputInfo = { 612 | .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 613 | .vertexBindingDescriptionCount = 1, 614 | .vertexAttributeDescriptionCount = static_cast(attrDesc.size()), 615 | .pVertexBindingDescriptions = &bindingDesc, 616 | .pVertexAttributeDescriptions = attrDesc.data(), 617 | }; 618 | 619 | VkPipelineInputAssemblyStateCreateInfo inputAssembly = { 620 | .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 621 | .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 622 | .primitiveRestartEnable = VK_FALSE, 623 | }; 624 | 625 | VkViewport viewport = { 626 | .x = 0.0f, 627 | .y = 0.0f, 628 | .width = (float) swapchainExtent.width, 629 | .height = (float) swapchainExtent.height, 630 | .minDepth = 0.0f, 631 | .maxDepth = 1.0f, 632 | }; 633 | 634 | VkRect2D scissor = { 635 | .offset = {0, 0}, 636 | .extent = swapchainExtent, 637 | }; 638 | 639 | VkPipelineViewportStateCreateInfo viewportState = { 640 | .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 641 | .viewportCount = 1, 642 | .pViewports = &viewport, 643 | .scissorCount = 1, 644 | .pScissors = &scissor, 645 | }; 646 | 647 | VkPipelineRasterizationStateCreateInfo rasterizer = { 648 | .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 649 | .depthClampEnable = VK_FALSE, 650 | .rasterizerDiscardEnable = VK_FALSE, 651 | .polygonMode = VK_POLYGON_MODE_FILL, 652 | .lineWidth = 1.0f, 653 | .cullMode = VK_CULL_MODE_BACK_BIT, 654 | .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, 655 | .depthBiasEnable = VK_FALSE, 656 | }; 657 | 658 | VkPipelineMultisampleStateCreateInfo multisampling = { 659 | .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 660 | .sampleShadingEnable = VK_FALSE, 661 | .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, 662 | }; 663 | 664 | VkPipelineColorBlendAttachmentState colorBlendAttachment = { 665 | .colorWriteMask = VK_COLOR_COMPONENT_R_BIT 666 | | VK_COLOR_COMPONENT_G_BIT 667 | | VK_COLOR_COMPONENT_B_BIT 668 | | VK_COLOR_COMPONENT_A_BIT, 669 | .blendEnable = VK_FALSE, 670 | }; 671 | VkPipelineColorBlendStateCreateInfo colorBlending = { 672 | .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 673 | .logicOpEnable = VK_FALSE, 674 | .logicOp = VK_LOGIC_OP_COPY, 675 | .attachmentCount = 1, 676 | .pAttachments = &colorBlendAttachment, 677 | .blendConstants[0] = 0.0f, 678 | .blendConstants[1] = 0.0f, 679 | .blendConstants[2] = 0.0f, 680 | .blendConstants[3] = 0.0f, 681 | }; 682 | 683 | VkPipelineLayoutCreateInfo pipelineLayoutInfo = { 684 | .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 685 | .setLayoutCount = 1, 686 | .pSetLayouts = &descriptorSetLayout, 687 | }; 688 | if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) 689 | != VK_SUCCESS) { 690 | throw std::runtime_error("failed to create pipeline layout!"); 691 | } 692 | 693 | VkGraphicsPipelineCreateInfo pipelineInfo = { 694 | .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 695 | .stageCount = 2, 696 | .pStages = shaderStages, 697 | .pVertexInputState = &vertexInputInfo, 698 | .pInputAssemblyState = &inputAssembly, 699 | .pViewportState = &viewportState, 700 | .pRasterizationState = &rasterizer, 701 | .pMultisampleState = &multisampling, 702 | .pColorBlendState = &colorBlending, 703 | .layout = pipelineLayout, 704 | .renderPass = renderPass, 705 | .subpass = 0, 706 | .basePipelineHandle = VK_NULL_HANDLE, 707 | }; 708 | 709 | if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, 710 | &graphicsPipeline) != VK_SUCCESS) { 711 | throw std::runtime_error("failed to create graphics pipeline!"); 712 | } 713 | 714 | vkDestroyShaderModule(device, vertexShaderModule, nullptr); 715 | vkDestroyShaderModule(device, fragmentShaderModule, nullptr); 716 | } 717 | 718 | void VulkanTutorialApplication::createFramebuffers() { 719 | swapchainFramebuffers.resize(swapchainImageViews.size()); 720 | 721 | for (size_t i = 0; i < swapchainImageViews.size(); i++) { 722 | VkImageView attachments[] = { 723 | swapchainImageViews[i] 724 | }; 725 | 726 | VkFramebufferCreateInfo framebufferInfo = {}; 727 | framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 728 | framebufferInfo.renderPass = renderPass; 729 | framebufferInfo.attachmentCount = 1; 730 | framebufferInfo.pAttachments = attachments; 731 | framebufferInfo.width = swapchainExtent.width; 732 | framebufferInfo.height = swapchainExtent.height; 733 | framebufferInfo.layers = 1; 734 | 735 | if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapchainFramebuffers[i]) 736 | != VK_SUCCESS) { 737 | throw std::runtime_error("failed to create framebuffer!"); 738 | } 739 | } 740 | } 741 | 742 | void VulkanTutorialApplication::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, 743 | VkMemoryPropertyFlags properties, VkBuffer &buffer, 744 | VkDeviceMemory &bufferMemory) { 745 | VkBufferCreateInfo bufferInfo = { 746 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 747 | .size = size, 748 | .usage = usage, 749 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 750 | }; 751 | if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) { 752 | throw std::runtime_error("failed to create buffer!"); 753 | } 754 | 755 | VkMemoryRequirements memRequirements; 756 | vkGetBufferMemoryRequirements(device, buffer, &memRequirements); 757 | 758 | VkMemoryAllocateInfo allocInfo = { 759 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 760 | .allocationSize = memRequirements.size, 761 | .memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties), 762 | }; 763 | 764 | if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) { 765 | throw std::runtime_error("failed to allocate buffer memory!"); 766 | } 767 | 768 | vkBindBufferMemory(device, buffer, bufferMemory, 0); 769 | } 770 | 771 | void VulkanTutorialApplication::createImage(uint32_t width, uint32_t height, VkFormat format, 772 | VkImageTiling tiling, VkImageUsageFlags usage, 773 | VkMemoryPropertyFlags properties, VkImage &image, 774 | VkDeviceMemory &imageMemory) { 775 | VkImageCreateInfo imageInfo = {}; 776 | imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 777 | imageInfo.imageType = VK_IMAGE_TYPE_2D; 778 | imageInfo.extent.width = width; 779 | imageInfo.extent.height = height; 780 | imageInfo.extent.depth = 1; 781 | imageInfo.mipLevels = 1; 782 | imageInfo.arrayLayers = 1; 783 | imageInfo.format = format; 784 | imageInfo.tiling = tiling; 785 | imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 786 | imageInfo.usage = usage; 787 | imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; 788 | imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 789 | 790 | if (vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) { 791 | throw std::runtime_error("failed to create image!"); 792 | } 793 | 794 | VkMemoryRequirements memRequirements; 795 | vkGetImageMemoryRequirements(device, image, &memRequirements); 796 | 797 | VkMemoryAllocateInfo allocInfo = {}; 798 | allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 799 | allocInfo.allocationSize = memRequirements.size; 800 | allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); 801 | 802 | if (vkAllocateMemory(device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) { 803 | throw std::runtime_error("failed to allocate image memory!"); 804 | } 805 | 806 | vkBindImageMemory(device, image, imageMemory, 0); 807 | } 808 | 809 | void VulkanTutorialApplication::transitionImageLayout(VkImage image, VkFormat format, 810 | VkImageLayout oldLayout, 811 | VkImageLayout newLayout) { 812 | VkCommandBuffer commandBuffer = beginSingleTimeCommands(); 813 | 814 | VkImageMemoryBarrier barrier = {}; 815 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 816 | barrier.oldLayout = oldLayout; 817 | barrier.newLayout = newLayout; 818 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 819 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 820 | barrier.image = image; 821 | barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 822 | barrier.subresourceRange.baseMipLevel = 0; 823 | barrier.subresourceRange.levelCount = 1; 824 | barrier.subresourceRange.baseArrayLayer = 0; 825 | barrier.subresourceRange.layerCount = 1; 826 | 827 | VkPipelineStageFlags sourceStage; 828 | VkPipelineStageFlags destinationStage; 829 | 830 | if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { 831 | barrier.srcAccessMask = 0; 832 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 833 | 834 | sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 835 | destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 836 | } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { 837 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 838 | barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 839 | 840 | sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; 841 | destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 842 | } else { 843 | throw std::invalid_argument("unsupported layout transition!"); 844 | } 845 | 846 | vkCmdPipelineBarrier( 847 | commandBuffer, 848 | sourceStage, destinationStage, 849 | 0, 850 | 0, nullptr, 851 | 0, nullptr, 852 | 1, &barrier 853 | ); 854 | 855 | endSingleTimeCommands(commandBuffer); 856 | } 857 | 858 | VkCommandBuffer VulkanTutorialApplication::beginSingleTimeCommands() { 859 | VkCommandBufferAllocateInfo allocInfo = {}; 860 | allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 861 | allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 862 | allocInfo.commandPool = commandPool; 863 | allocInfo.commandBufferCount = 1; 864 | 865 | VkCommandBuffer commandBuffer; 866 | vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer); 867 | 868 | VkCommandBufferBeginInfo beginInfo = {}; 869 | beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 870 | beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 871 | 872 | vkBeginCommandBuffer(commandBuffer, &beginInfo); 873 | 874 | return commandBuffer; 875 | } 876 | 877 | void VulkanTutorialApplication::endSingleTimeCommands(VkCommandBuffer commandBuffer) { 878 | vkEndCommandBuffer(commandBuffer); 879 | 880 | VkSubmitInfo submitInfo = {}; 881 | submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 882 | submitInfo.commandBufferCount = 1; 883 | submitInfo.pCommandBuffers = &commandBuffer; 884 | 885 | vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); 886 | vkQueueWaitIdle(graphicsQueue); 887 | 888 | vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); 889 | } 890 | 891 | void VulkanTutorialApplication::copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, 892 | uint32_t height) { 893 | VkCommandBuffer commandBuffer = beginSingleTimeCommands(); 894 | 895 | VkBufferImageCopy region = {}; 896 | region.bufferOffset = 0; 897 | region.bufferRowLength = 0; 898 | region.bufferImageHeight = 0; 899 | region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 900 | region.imageSubresource.mipLevel = 0; 901 | region.imageSubresource.baseArrayLayer = 0; 902 | region.imageSubresource.layerCount = 1; 903 | region.imageOffset = {0, 0, 0}; 904 | region.imageExtent = { 905 | width, 906 | height, 907 | 1 908 | }; 909 | 910 | vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); 911 | 912 | endSingleTimeCommands(commandBuffer); 913 | } 914 | 915 | VkImageView VulkanTutorialApplication::createImageView(VkImage image, VkFormat format) { 916 | VkImageViewCreateInfo viewInfo = {}; 917 | viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 918 | viewInfo.image = image; 919 | viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; 920 | viewInfo.format = format; 921 | viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 922 | viewInfo.subresourceRange.baseMipLevel = 0; 923 | viewInfo.subresourceRange.levelCount = 1; 924 | viewInfo.subresourceRange.baseArrayLayer = 0; 925 | viewInfo.subresourceRange.layerCount = 1; 926 | 927 | VkImageView imageView; 928 | if (vkCreateImageView(device, &viewInfo, nullptr, &imageView) != VK_SUCCESS) { 929 | throw std::runtime_error("failed to create texture image view!"); 930 | } 931 | 932 | return imageView; 933 | } 934 | 935 | void VulkanTutorialApplication::createTextureImage() { 936 | AAsset* file = AAssetManager_open(assetManager, IMAGE_PATH.c_str(), AASSET_MODE_BUFFER); 937 | size_t fileLength = AAsset_getLength(file); 938 | stbi_uc* fileContent = new unsigned char[fileLength]; 939 | AAsset_read(file, fileContent, fileLength); 940 | 941 | int texWidth, texHeight, texChannels; 942 | stbi_uc* pixels = stbi_load_from_memory(fileContent,fileLength,&texWidth,&texHeight,&texChannels,STBI_rgb_alpha); 943 | VkDeviceSize imageSize = texWidth * texHeight * 4; 944 | 945 | if (!pixels) { 946 | throw std::runtime_error("failed to load texture image!"); 947 | } 948 | 949 | VkBuffer stagingBuffer; 950 | VkDeviceMemory stagingBufferMemory; 951 | createBuffer(imageSize,VK_BUFFER_USAGE_TRANSFER_SRC_BIT,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 952 | stagingBuffer,stagingBufferMemory); 953 | 954 | void* data; 955 | vkMapMemory(device,stagingBufferMemory,0,imageSize,0,&data); 956 | memcpy(data,pixels, static_cast(imageSize)); 957 | vkUnmapMemory(device,stagingBufferMemory); 958 | 959 | stbi_image_free(pixels); 960 | 961 | createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 962 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory); 963 | transitionImageLayout(textureImage,VK_FORMAT_R8G8B8A8_UNORM,VK_IMAGE_LAYOUT_UNDEFINED,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); 964 | copyBufferToImage(stagingBuffer, textureImage, static_cast(texWidth), static_cast(texHeight)); 965 | transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 966 | 967 | vkDestroyBuffer(device, stagingBuffer, nullptr); 968 | vkFreeMemory(device, stagingBufferMemory, nullptr); 969 | } 970 | 971 | void VulkanTutorialApplication::createTextureImageView() { 972 | textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_UNORM); 973 | } 974 | 975 | void VulkanTutorialApplication::createTextureSampler() { 976 | VkSamplerCreateInfo samplerInfo = {}; 977 | samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 978 | samplerInfo.magFilter = VK_FILTER_LINEAR; 979 | samplerInfo.minFilter = VK_FILTER_LINEAR; 980 | samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; 981 | samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; 982 | samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; 983 | samplerInfo.anisotropyEnable = VK_TRUE; 984 | samplerInfo.maxAnisotropy = 16; 985 | samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; 986 | samplerInfo.unnormalizedCoordinates = VK_FALSE; 987 | samplerInfo.compareEnable = VK_FALSE; 988 | samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; 989 | samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 990 | 991 | if (vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) { 992 | throw std::runtime_error("failed to create texture sampler!"); 993 | } 994 | } 995 | 996 | void VulkanTutorialApplication::createVertexBuffer() { 997 | VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size(); 998 | 999 | VkBuffer stagingBuffer; 1000 | VkDeviceMemory stagingBufferMemory; 1001 | createBuffer(bufferSize, 1002 | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 1003 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 1004 | stagingBuffer, 1005 | stagingBufferMemory); 1006 | 1007 | void *data; 1008 | vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data); 1009 | memcpy(data, vertices.data(), (size_t) bufferSize); 1010 | vkUnmapMemory(device, stagingBufferMemory); 1011 | 1012 | createBuffer(bufferSize, 1013 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 1014 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 1015 | vertexBuffer, 1016 | vertexBufferMemory); 1017 | 1018 | copyBuffer(stagingBuffer, vertexBuffer, bufferSize); 1019 | 1020 | vkDestroyBuffer(device, stagingBuffer, nullptr); 1021 | vkFreeMemory(device, stagingBufferMemory, nullptr); 1022 | } 1023 | 1024 | void VulkanTutorialApplication::createIndexBuffer() { 1025 | VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size(); 1026 | 1027 | VkBuffer stagingBuffer; 1028 | VkDeviceMemory stagingBufferMemory; 1029 | createBuffer(bufferSize, 1030 | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 1031 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 1032 | stagingBuffer, 1033 | stagingBufferMemory); 1034 | 1035 | void *data; 1036 | vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data); 1037 | memcpy(data, indices.data(), (size_t) bufferSize); 1038 | vkUnmapMemory(device, stagingBufferMemory); 1039 | 1040 | createBuffer(bufferSize, 1041 | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 1042 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 1043 | indexBuffer, 1044 | indexBufferMemory); 1045 | 1046 | copyBuffer(stagingBuffer, indexBuffer, bufferSize); 1047 | 1048 | vkDestroyBuffer(device, stagingBuffer, nullptr); 1049 | vkFreeMemory(device, stagingBufferMemory, nullptr); 1050 | } 1051 | 1052 | void VulkanTutorialApplication::createUniformBuffer() { 1053 | VkDeviceSize bufferSize = sizeof(UniformBufferObject); 1054 | createBuffer(bufferSize, 1055 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 1056 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 1057 | uniformBuffer, 1058 | uniformBufferMemory); 1059 | } 1060 | 1061 | void VulkanTutorialApplication::createDescriptorPool() { 1062 | std::array poolSizes = {}; 1063 | poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 1064 | poolSizes[0].descriptorCount = 1; 1065 | poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 1066 | poolSizes[1].descriptorCount = 1; 1067 | 1068 | VkDescriptorPoolCreateInfo poolInfo = { 1069 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 1070 | .poolSizeCount = static_cast(poolSizes.size()), 1071 | .pPoolSizes = poolSizes.data(), 1072 | .maxSets = 1, 1073 | }; 1074 | if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) { 1075 | throw std::runtime_error("failed to create descriptor pool!"); 1076 | } 1077 | } 1078 | 1079 | void VulkanTutorialApplication::createDescriptorSet() { 1080 | VkDescriptorSetLayout layouts[] = {descriptorSetLayout}; 1081 | VkDescriptorSetAllocateInfo allocInfo = { 1082 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1083 | .descriptorPool = descriptorPool, 1084 | .descriptorSetCount = 1, 1085 | .pSetLayouts = layouts, 1086 | }; 1087 | if (vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet) != VK_SUCCESS) { 1088 | throw std::runtime_error("failed to allocate descriptor set!"); 1089 | } 1090 | 1091 | VkDescriptorBufferInfo bufferInfo = { 1092 | .buffer = uniformBuffer, 1093 | .offset = 0, 1094 | .range = sizeof(UniformBufferObject), 1095 | }; 1096 | 1097 | VkDescriptorImageInfo imageInfo = { 1098 | .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1099 | .imageView = textureImageView, 1100 | .sampler = textureSampler, 1101 | }; 1102 | 1103 | std::array descriptorWrites = {}; 1104 | 1105 | descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 1106 | descriptorWrites[0].dstSet = descriptorSet; 1107 | descriptorWrites[0].dstBinding = 0; 1108 | descriptorWrites[0].dstArrayElement = 0; 1109 | descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 1110 | descriptorWrites[0].descriptorCount = 1; 1111 | descriptorWrites[0].pBufferInfo = &bufferInfo; 1112 | 1113 | descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 1114 | descriptorWrites[1].dstSet = descriptorSet; 1115 | descriptorWrites[1].dstBinding = 1; 1116 | descriptorWrites[1].dstArrayElement = 0; 1117 | descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 1118 | descriptorWrites[1].descriptorCount = 1; 1119 | descriptorWrites[1].pImageInfo = &imageInfo; 1120 | 1121 | vkUpdateDescriptorSets(device, static_cast(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); 1122 | } 1123 | 1124 | void VulkanTutorialApplication::copyBuffer( 1125 | VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { 1126 | VkCommandBufferAllocateInfo allocInfo = { 1127 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 1128 | .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1129 | .commandPool = commandPool, 1130 | .commandBufferCount = 1, 1131 | }; 1132 | 1133 | VkCommandBuffer commandBuffer; 1134 | vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer); 1135 | 1136 | VkCommandBufferBeginInfo beginInfo = { 1137 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 1138 | .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 1139 | }; 1140 | vkBeginCommandBuffer(commandBuffer, &beginInfo); 1141 | 1142 | VkBufferCopy copyRegion = { 1143 | .size = size 1144 | }; 1145 | vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); 1146 | 1147 | vkEndCommandBuffer(commandBuffer); 1148 | 1149 | VkSubmitInfo submitInfo = { 1150 | .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 1151 | .commandBufferCount = 1, 1152 | .pCommandBuffers = &commandBuffer, 1153 | }; 1154 | vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); 1155 | vkQueueWaitIdle(graphicsQueue); 1156 | 1157 | vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); 1158 | } 1159 | 1160 | uint32_t VulkanTutorialApplication::findMemoryType( 1161 | uint32_t typeFilter, VkMemoryPropertyFlags properties) { 1162 | VkPhysicalDeviceMemoryProperties memProperties; 1163 | vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); 1164 | 1165 | for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { 1166 | if ((typeFilter & (1 << i)) 1167 | && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { 1168 | return i; 1169 | } 1170 | } 1171 | 1172 | throw std::runtime_error("failed to find suitable memory type!"); 1173 | } 1174 | 1175 | void VulkanTutorialApplication::createCommandBuffers() { 1176 | commandBuffers.resize(swapchainFramebuffers.size()); 1177 | 1178 | VkCommandBufferAllocateInfo allocInfo = {}; 1179 | allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 1180 | allocInfo.commandPool = commandPool; 1181 | allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 1182 | allocInfo.commandBufferCount = (uint32_t) commandBuffers.size(); 1183 | 1184 | if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) { 1185 | throw std::runtime_error("failed to allocate command buffers!"); 1186 | } 1187 | 1188 | for (size_t i = 0; i < commandBuffers.size(); i++) { 1189 | VkCommandBufferBeginInfo beginInfo = {}; 1190 | beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 1191 | beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 1192 | beginInfo.pInheritanceInfo = nullptr; // Optional 1193 | 1194 | vkBeginCommandBuffer(commandBuffers[i], &beginInfo); 1195 | 1196 | VkRenderPassBeginInfo renderPassInfo = {}; 1197 | renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 1198 | renderPassInfo.renderPass = renderPass; 1199 | renderPassInfo.framebuffer = swapchainFramebuffers[i]; 1200 | renderPassInfo.renderArea.offset = {0, 0}; 1201 | renderPassInfo.renderArea.extent = swapchainExtent; 1202 | 1203 | VkClearValue clearColor = {0.0f, 0.0f, 0.0f, 1.0f}; 1204 | renderPassInfo.clearValueCount = 1; 1205 | renderPassInfo.pClearValues = &clearColor; 1206 | 1207 | vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); 1208 | 1209 | vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); 1210 | 1211 | VkBuffer vertexBuffers[] = {vertexBuffer}; 1212 | VkDeviceSize offsets[] = {0}; 1213 | vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets); 1214 | 1215 | vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16); 1216 | 1217 | vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1218 | 0, 1, &descriptorSet, 0, nullptr); 1219 | 1220 | vkCmdDrawIndexed(commandBuffers[i], static_cast(indices.size()), 1, 0, 0, 0); 1221 | 1222 | vkCmdEndRenderPass(commandBuffers[i]); 1223 | 1224 | if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) { 1225 | throw std::runtime_error("failed to record command buffer!"); 1226 | } 1227 | } 1228 | } 1229 | 1230 | void VulkanTutorialApplication::createSemaphores() { 1231 | VkSemaphoreCreateInfo semaphoreInfo = {}; 1232 | semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 1233 | 1234 | if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphore) != VK_SUCCESS 1235 | || vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) 1236 | != VK_SUCCESS) { 1237 | throw std::runtime_error("failed to create semaphores!"); 1238 | } 1239 | } 1240 | 1241 | void VulkanTutorialApplication::updateUniformBuffer() { 1242 | static auto startTime = std::chrono::high_resolution_clock::now(); 1243 | 1244 | auto currentTime = std::chrono::high_resolution_clock::now(); 1245 | float time = 1246 | std::chrono::duration_cast(currentTime - startTime).count() 1247 | / 1e3f; 1248 | 1249 | UniformBufferObject ubo = { 1250 | .model = glm::rotate(glm::mat4(), time * glm::radians(90.0f), 1251 | glm::vec3(0.0f, 0.0f, 1.0f)), 1252 | .view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), 1253 | glm::vec3(0.0f, 0.0f, 1.0f)), 1254 | .proj = glm::perspective(glm::radians(45.0f), 1255 | swapchainExtent.width / (float) swapchainExtent.height, 0.1f, 1256 | 10.0f), 1257 | }; 1258 | ubo.proj[1][1] *= -1; 1259 | 1260 | void *data; 1261 | vkMapMemory(device, uniformBufferMemory, 0, sizeof(ubo), 0, &data); 1262 | memcpy(data, &ubo, sizeof(ubo)); 1263 | vkUnmapMemory(device, uniformBufferMemory); 1264 | } 1265 | 1266 | void VulkanTutorialApplication::drawFrame() { 1267 | uint32_t imageIndex = 0; 1268 | VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits::max(), 1269 | imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); 1270 | 1271 | if (result == VK_ERROR_OUT_OF_DATE_KHR) { 1272 | recreateSwapchain(); 1273 | return; 1274 | } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { 1275 | throw std::runtime_error("failed to acquire swap chain image!"); 1276 | } 1277 | 1278 | VkSubmitInfo submitInfo = {}; 1279 | submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 1280 | 1281 | VkSemaphore waitSemaphores[] = {imageAvailableSemaphore}; 1282 | VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; 1283 | submitInfo.waitSemaphoreCount = 1; 1284 | submitInfo.pWaitSemaphores = waitSemaphores; 1285 | submitInfo.pWaitDstStageMask = waitStages; 1286 | submitInfo.commandBufferCount = 1; 1287 | submitInfo.pCommandBuffers = &commandBuffers[imageIndex]; 1288 | 1289 | VkSemaphore signalSemaphores[] = {renderFinishedSemaphore}; 1290 | submitInfo.signalSemaphoreCount = 1; 1291 | submitInfo.pSignalSemaphores = signalSemaphores; 1292 | 1293 | if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS) { 1294 | throw std::runtime_error("failed to submit draw command buffer!"); 1295 | } 1296 | 1297 | VkPresentInfoKHR presentInfo = {}; 1298 | presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 1299 | 1300 | presentInfo.waitSemaphoreCount = 1; 1301 | presentInfo.pWaitSemaphores = signalSemaphores; 1302 | 1303 | VkSwapchainKHR swapChains[] = {swapchain}; 1304 | presentInfo.swapchainCount = 1; 1305 | presentInfo.pSwapchains = swapChains; 1306 | 1307 | presentInfo.pImageIndices = &imageIndex; 1308 | 1309 | result = vkQueuePresentKHR(presentQueue, &presentInfo); 1310 | 1311 | if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { 1312 | recreateSwapchain(); 1313 | } else if (result != VK_SUCCESS) { 1314 | throw std::runtime_error("failed to present swap chain image!"); 1315 | } 1316 | 1317 | vkQueueWaitIdle(presentQueue); 1318 | } 1319 | 1320 | void VulkanTutorialApplication::recreateSwapchain() { 1321 | LOGI("recreateSwapchain"); 1322 | 1323 | vkDeviceWaitIdle(device); 1324 | 1325 | cleanupSwapchain(); 1326 | 1327 | createSwapchain(); 1328 | createImageViews(); 1329 | createRenderPass(); 1330 | createGraphicsPipeline(); 1331 | createFramebuffers(); 1332 | createCommandBuffers(); 1333 | } 1334 | 1335 | void VulkanTutorialApplication::cleanupSwapchain() { 1336 | for (size_t i = 0; i < swapchainFramebuffers.size(); i++) { 1337 | vkDestroyFramebuffer(device, swapchainFramebuffers[i], nullptr); 1338 | } 1339 | 1340 | vkFreeCommandBuffers(device, commandPool, static_cast(commandBuffers.size()), 1341 | commandBuffers.data()); 1342 | 1343 | vkDestroyPipeline(device, graphicsPipeline, nullptr); 1344 | vkDestroyPipelineLayout(device, pipelineLayout, nullptr); 1345 | vkDestroyRenderPass(device, renderPass, nullptr); 1346 | 1347 | for (size_t i = 0; i < swapchainImageViews.size(); i++) { 1348 | vkDestroyImageView(device, swapchainImageViews[i], nullptr); 1349 | } 1350 | 1351 | vkDestroySwapchainKHR(device, swapchain, nullptr); 1352 | } 1353 | 1354 | std::vector VulkanTutorialApplication::readAsset(std::string name) { 1355 | AAsset *file = AAssetManager_open(assetManager, name.c_str(), AASSET_MODE_BUFFER); 1356 | size_t len = AAsset_getLength(file); 1357 | std::vector buffer(len); 1358 | 1359 | AAsset_read(file, buffer.data(), len); 1360 | 1361 | AAsset_close(file); 1362 | 1363 | LOGI("read asset %s, length %d", name.c_str(), len); 1364 | 1365 | return buffer; 1366 | } 1367 | 1368 | void VulkanTutorialApplication::createCommandPool() { 1369 | QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); 1370 | 1371 | VkCommandPoolCreateInfo poolInfo = {}; 1372 | poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 1373 | poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily; 1374 | poolInfo.flags = 0; // Optional 1375 | 1376 | if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) { 1377 | throw std::runtime_error("failed to create command pool!"); 1378 | } 1379 | } 1380 | 1381 | VkShaderModule VulkanTutorialApplication::createShaderModule(const std::vector &code) { 1382 | VkShaderModuleCreateInfo createInfo = {}; 1383 | createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 1384 | createInfo.codeSize = code.size(); 1385 | createInfo.pCode = reinterpret_cast(code.data()); 1386 | 1387 | VkShaderModule shaderModule; 1388 | if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { 1389 | throw std::runtime_error("failed to create shader module!"); 1390 | } 1391 | 1392 | return shaderModule; 1393 | } 1394 | 1395 | bool VulkanTutorialApplication::isDeviceSuitable(VkPhysicalDevice device) { 1396 | bool extensionsSupported = checkDeviceExtensionSupport(device); 1397 | 1398 | bool swapchainAdequate = false; 1399 | if (extensionsSupported) { 1400 | SwapchainSupportDetails swapChainSupport = querySwapchainSupport(device); 1401 | swapchainAdequate = 1402 | !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); 1403 | } 1404 | 1405 | QueueFamilyIndices indices = findQueueFamilies(device); 1406 | 1407 | return indices.isComplete() && extensionsSupported && swapchainAdequate; 1408 | } 1409 | 1410 | 1411 | bool VulkanTutorialApplication::checkDeviceExtensionSupport(VkPhysicalDevice device) { 1412 | uint32_t extensionCount = 0; 1413 | vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); 1414 | 1415 | std::vector availableExtensions(extensionCount); 1416 | vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, 1417 | availableExtensions.data()); 1418 | 1419 | std::set requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); 1420 | 1421 | for (const auto &extension : availableExtensions) { 1422 | requiredExtensions.erase(extension.extensionName); 1423 | } 1424 | 1425 | return requiredExtensions.empty(); 1426 | } 1427 | 1428 | VulkanTutorialApplication::QueueFamilyIndices 1429 | VulkanTutorialApplication::findQueueFamilies(VkPhysicalDevice device) { 1430 | QueueFamilyIndices indices; 1431 | 1432 | uint32_t queueFamilyCount = 0; 1433 | vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); 1434 | 1435 | std::vector queueFamilies(queueFamilyCount); 1436 | vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); 1437 | 1438 | int i = 0; 1439 | for (const auto &queueFamily : queueFamilies) { 1440 | if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1441 | indices.graphicsFamily = i; 1442 | } 1443 | 1444 | VkBool32 presentSupport = false; 1445 | vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); 1446 | if (queueFamily.queueCount > 0 && presentSupport) { 1447 | indices.presentFamily = i; 1448 | } 1449 | 1450 | if (indices.isComplete()) { 1451 | break; 1452 | } 1453 | 1454 | i++; 1455 | } 1456 | 1457 | return indices; 1458 | } 1459 | 1460 | VulkanTutorialApplication::SwapchainSupportDetails 1461 | VulkanTutorialApplication::querySwapchainSupport(VkPhysicalDevice device) { 1462 | SwapchainSupportDetails details; 1463 | 1464 | vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); 1465 | 1466 | uint32_t formatCount = 0; 1467 | vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); 1468 | if (formatCount > 0) { 1469 | details.formats.resize(formatCount); 1470 | vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, 1471 | details.formats.data()); 1472 | } 1473 | 1474 | uint32_t presentModeCount = 0; 1475 | vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr); 1476 | if (presentModeCount > 0) { 1477 | details.presentModes.resize(presentModeCount); 1478 | vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, 1479 | details.presentModes.data()); 1480 | } 1481 | 1482 | return details; 1483 | } 1484 | -------------------------------------------------------------------------------- /app/src/main/cpp/vulkan_tutorial.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Piasy on 29/06/2017. 3 | // 4 | 5 | #ifndef VULKANTUTORIAL_ANDROID_VULKAN_TRIANGLE_H 6 | #define VULKANTUTORIAL_ANDROID_VULKAN_TRIANGLE_H 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #define APP_NAME "VK-TUTORIAL" 19 | #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__)) 20 | #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__)) 21 | 22 | #define STATE_RUNNING 1 23 | #define STATE_PAUSED 2 24 | #define STATE_EXIT 3 25 | 26 | class VulkanTutorialApplication { 27 | public: 28 | struct QueueFamilyIndices { 29 | int graphicsFamily = -1; 30 | int presentFamily = -1; 31 | 32 | bool isComplete() { 33 | return graphicsFamily >= 0 && presentFamily >= 0; 34 | } 35 | }; 36 | 37 | struct SwapchainSupportDetails { 38 | VkSurfaceCapabilitiesKHR capabilities; 39 | std::vector formats; 40 | std::vector presentModes; 41 | }; 42 | 43 | struct Vertex { 44 | glm::vec2 pos; 45 | glm::vec3 color; 46 | glm::vec2 texCoord; 47 | 48 | static VkVertexInputBindingDescription getBindingDescription() { 49 | VkVertexInputBindingDescription bindingDescription = {}; 50 | bindingDescription.binding = 0; 51 | bindingDescription.stride = sizeof(Vertex); 52 | bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 53 | 54 | return bindingDescription; 55 | } 56 | 57 | static std::array getAttributeDescriptions() { 58 | std::array attributeDescriptions = {}; 59 | 60 | attributeDescriptions[0].binding = 0; 61 | attributeDescriptions[0].location = 0; 62 | attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT; 63 | attributeDescriptions[0].offset = offsetof(Vertex, pos); 64 | 65 | attributeDescriptions[1].binding = 0; 66 | attributeDescriptions[1].location = 1; 67 | attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; 68 | attributeDescriptions[1].offset = offsetof(Vertex, color); 69 | 70 | attributeDescriptions[2].binding = 0; 71 | attributeDescriptions[2].location = 2; 72 | attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT; 73 | attributeDescriptions[2].offset = offsetof(Vertex, texCoord); 74 | 75 | return attributeDescriptions; 76 | } 77 | }; 78 | 79 | struct UniformBufferObject { 80 | glm::mat4 model; 81 | glm::mat4 view; 82 | glm::mat4 proj; 83 | }; 84 | 85 | VulkanTutorialApplication( 86 | AAssetManager *assetManager, 87 | const char *vertexShader, 88 | const char *fragmentShader) : 89 | assetManager(assetManager), 90 | vertexShader(std::string(vertexShader)), 91 | fragmentShader(std::string(fragmentShader)), 92 | state(STATE_RUNNING) { 93 | } 94 | 95 | void run(ANativeWindow *window); 96 | 97 | void pause(); 98 | 99 | inline void resume() { 100 | state = STATE_RUNNING; 101 | } 102 | 103 | void surfaceChanged(); 104 | 105 | inline void stop() { 106 | state = STATE_EXIT; 107 | } 108 | 109 | private: 110 | inline void initWindow(ANativeWindow *window) { 111 | this->window = window; 112 | } 113 | 114 | void initVulkan(); 115 | 116 | void mainLoop(); 117 | 118 | void cleanUp(); 119 | 120 | void createInstance(); 121 | 122 | void setUpDebugCallback(); 123 | 124 | void createSurface(); 125 | 126 | void pickPhysicalDevice(); 127 | 128 | void createLogicalDevice(); 129 | 130 | void createSwapchain(); 131 | 132 | void createImageViews(); 133 | 134 | void createRenderPass(); 135 | 136 | void createDescriptorSetLayout(); 137 | 138 | void createGraphicsPipeline(); 139 | 140 | void createFramebuffers(); 141 | 142 | void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, 143 | VkBuffer &buffer, VkDeviceMemory &bufferMemory); 144 | 145 | void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, 146 | VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory); 147 | 148 | void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout); 149 | 150 | VkCommandBuffer beginSingleTimeCommands(); 151 | 152 | void endSingleTimeCommands(VkCommandBuffer commandBuffer); 153 | 154 | void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height); 155 | 156 | VkImageView createImageView(VkImage image, VkFormat format); 157 | 158 | void createCommandPool(); 159 | 160 | void createTextureImage(); 161 | 162 | void createTextureSampler(); 163 | 164 | void createTextureImageView(); 165 | 166 | void createVertexBuffer(); 167 | 168 | void createIndexBuffer(); 169 | 170 | void createUniformBuffer(); 171 | 172 | void createDescriptorPool(); 173 | 174 | void createDescriptorSet(); 175 | 176 | void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); 177 | 178 | uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); 179 | 180 | void createCommandBuffers(); 181 | 182 | void createSemaphores(); 183 | 184 | void updateUniformBuffer(); 185 | 186 | void drawFrame(); 187 | 188 | void recreateSwapchain(); 189 | 190 | void cleanupSwapchain(); 191 | 192 | std::vector readAsset(std::string name); 193 | 194 | VkShaderModule createShaderModule(const std::vector &code); 195 | 196 | bool isDeviceSuitable(VkPhysicalDevice device); 197 | 198 | bool checkDeviceExtensionSupport(VkPhysicalDevice device); 199 | 200 | QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device); 201 | 202 | SwapchainSupportDetails querySwapchainSupport(VkPhysicalDevice device); 203 | 204 | AAssetManager *assetManager; 205 | std::string vertexShader; 206 | std::string fragmentShader; 207 | int state; 208 | 209 | VkInstance instance; 210 | VkDebugReportCallbackEXT callback; 211 | ANativeWindow *window; 212 | VkSurfaceKHR surface; 213 | 214 | VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; 215 | VkDevice device; 216 | 217 | VkQueue graphicsQueue; 218 | VkQueue presentQueue; 219 | 220 | VkSwapchainKHR swapchain; 221 | VkRenderPass renderPass; 222 | VkDescriptorSetLayout descriptorSetLayout; 223 | VkDescriptorPool descriptorPool; 224 | VkDescriptorSet descriptorSet; 225 | VkPipelineLayout pipelineLayout; 226 | VkPipeline graphicsPipeline; 227 | VkCommandPool commandPool; 228 | 229 | VkFormat swapchainImageFormat; 230 | VkExtent2D swapchainExtent; 231 | std::vector swapchainImages; 232 | std::vector swapchainImageViews; 233 | std::vector swapchainFramebuffers; 234 | std::vector commandBuffers; 235 | 236 | VkBuffer vertexBuffer; 237 | VkDeviceMemory vertexBufferMemory; 238 | VkBuffer indexBuffer; 239 | VkDeviceMemory indexBufferMemory; 240 | VkBuffer uniformBuffer; 241 | VkDeviceMemory uniformBufferMemory; 242 | 243 | VkImage textureImage; 244 | VkDeviceMemory textureImageMemory; 245 | VkImageView textureImageView; 246 | VkSampler textureSampler; 247 | 248 | VkSemaphore imageAvailableSemaphore; 249 | VkSemaphore renderFinishedSemaphore; 250 | }; 251 | 252 | #endif //VULKANTUTORIAL_ANDROID_VULKAN_TRIANGLE_H 253 | -------------------------------------------------------------------------------- /app/src/main/cpp/vulkan_tutorial_jni.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Piasy on 29/06/2017. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "vulkan_tutorial.h" 10 | 11 | extern "C" { 12 | 13 | JNIEXPORT jlong JNICALL 14 | Java_com_github_piasy_vulkantutorial_VulkanTutorialApplication_create( 15 | JNIEnv *env, jclass type, jobject assetManager_, jstring vertexShader_, 16 | jstring fragmentShader_) { 17 | 18 | AAssetManager *assetManager = AAssetManager_fromJava(env, assetManager_); 19 | if (assetManager == nullptr) { 20 | LOGE("get assetManager fail!"); 21 | return 0; 22 | } 23 | 24 | const char *vertexShader = env->GetStringUTFChars(vertexShader_, 0); 25 | const char *fragmentShader = env->GetStringUTFChars(fragmentShader_, 0); 26 | 27 | VulkanTutorialApplication *app = new VulkanTutorialApplication(assetManager, vertexShader, 28 | fragmentShader); 29 | 30 | env->ReleaseStringUTFChars(vertexShader_, vertexShader); 31 | env->ReleaseStringUTFChars(fragmentShader_, fragmentShader); 32 | 33 | return (jlong) app; 34 | } 35 | 36 | JNIEXPORT void JNICALL 37 | Java_com_github_piasy_vulkantutorial_VulkanTutorialApplication_run__JLandroid_view_Surface_2( 38 | JNIEnv *env, jclass type, jlong nativeHandle, jobject surface) { 39 | ANativeWindow *window = ANativeWindow_fromSurface(env, surface); 40 | if (window == nullptr) { 41 | LOGE("get window from surface fail!"); 42 | return; 43 | } 44 | 45 | VulkanTutorialApplication *app = reinterpret_cast(nativeHandle); 46 | app->run(window); 47 | } 48 | 49 | JNIEXPORT void JNICALL 50 | Java_com_github_piasy_vulkantutorial_VulkanTutorialApplication_pause__J(JNIEnv *env, jclass type, 51 | jlong nativeHandle) { 52 | VulkanTutorialApplication *app = reinterpret_cast(nativeHandle); 53 | app->pause(); 54 | } 55 | 56 | JNIEXPORT void JNICALL 57 | Java_com_github_piasy_vulkantutorial_VulkanTutorialApplication_resume__J(JNIEnv *env, jclass type, 58 | jlong nativeHandle) { 59 | VulkanTutorialApplication *app = reinterpret_cast(nativeHandle); 60 | app->resume(); 61 | } 62 | 63 | JNIEXPORT void JNICALL 64 | Java_com_github_piasy_vulkantutorial_VulkanTutorialApplication_surfaceChanged__J( 65 | JNIEnv *env, jclass type, jlong nativeHandle) { 66 | VulkanTutorialApplication *app = reinterpret_cast(nativeHandle); 67 | app->surfaceChanged(); 68 | } 69 | 70 | JNIEXPORT void JNICALL 71 | Java_com_github_piasy_vulkantutorial_VulkanTutorialApplication_stop__J(JNIEnv *env, jclass type, 72 | jlong nativeHandle) { 73 | VulkanTutorialApplication *app = reinterpret_cast(nativeHandle); 74 | app->stop(); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/cpp/vulkan_wrapper/vulkan_wrapper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Android Open Source Project 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 | // This file is generated. 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include "vulkan_wrapper.h" 22 | #include 23 | 24 | int InitVulkan(void) { 25 | void *libvulkan = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); 26 | if (!libvulkan) return 0; 27 | 28 | // Vulkan supported, set function addresses 29 | vkCreateInstance = reinterpret_cast(dlsym(libvulkan, "vkCreateInstance")); 30 | vkDestroyInstance = reinterpret_cast(dlsym(libvulkan, "vkDestroyInstance")); 31 | vkEnumeratePhysicalDevices = reinterpret_cast(dlsym(libvulkan, "vkEnumeratePhysicalDevices")); 32 | vkGetPhysicalDeviceFeatures = 33 | reinterpret_cast(dlsym(libvulkan, "vkGetPhysicalDeviceFeatures")); 34 | vkGetPhysicalDeviceFormatProperties = 35 | reinterpret_cast(dlsym(libvulkan, "vkGetPhysicalDeviceFormatProperties")); 36 | vkGetPhysicalDeviceImageFormatProperties = reinterpret_cast( 37 | dlsym(libvulkan, "vkGetPhysicalDeviceImageFormatProperties")); 38 | vkGetPhysicalDeviceProperties = 39 | reinterpret_cast(dlsym(libvulkan, "vkGetPhysicalDeviceProperties")); 40 | vkGetPhysicalDeviceQueueFamilyProperties = reinterpret_cast( 41 | dlsym(libvulkan, "vkGetPhysicalDeviceQueueFamilyProperties")); 42 | vkGetPhysicalDeviceMemoryProperties = 43 | reinterpret_cast(dlsym(libvulkan, "vkGetPhysicalDeviceMemoryProperties")); 44 | vkGetInstanceProcAddr = reinterpret_cast(dlsym(libvulkan, "vkGetInstanceProcAddr")); 45 | vkGetDeviceProcAddr = reinterpret_cast(dlsym(libvulkan, "vkGetDeviceProcAddr")); 46 | vkCreateDevice = reinterpret_cast(dlsym(libvulkan, "vkCreateDevice")); 47 | vkDestroyDevice = reinterpret_cast(dlsym(libvulkan, "vkDestroyDevice")); 48 | vkEnumerateInstanceExtensionProperties = 49 | reinterpret_cast(dlsym(libvulkan, "vkEnumerateInstanceExtensionProperties")); 50 | vkEnumerateDeviceExtensionProperties = 51 | reinterpret_cast(dlsym(libvulkan, "vkEnumerateDeviceExtensionProperties")); 52 | vkEnumerateInstanceLayerProperties = 53 | reinterpret_cast(dlsym(libvulkan, "vkEnumerateInstanceLayerProperties")); 54 | vkEnumerateDeviceLayerProperties = 55 | reinterpret_cast(dlsym(libvulkan, "vkEnumerateDeviceLayerProperties")); 56 | vkGetDeviceQueue = reinterpret_cast(dlsym(libvulkan, "vkGetDeviceQueue")); 57 | vkQueueSubmit = reinterpret_cast(dlsym(libvulkan, "vkQueueSubmit")); 58 | vkQueueWaitIdle = reinterpret_cast(dlsym(libvulkan, "vkQueueWaitIdle")); 59 | vkDeviceWaitIdle = reinterpret_cast(dlsym(libvulkan, "vkDeviceWaitIdle")); 60 | vkAllocateMemory = reinterpret_cast(dlsym(libvulkan, "vkAllocateMemory")); 61 | vkFreeMemory = reinterpret_cast(dlsym(libvulkan, "vkFreeMemory")); 62 | vkMapMemory = reinterpret_cast(dlsym(libvulkan, "vkMapMemory")); 63 | vkUnmapMemory = reinterpret_cast(dlsym(libvulkan, "vkUnmapMemory")); 64 | vkFlushMappedMemoryRanges = reinterpret_cast(dlsym(libvulkan, "vkFlushMappedMemoryRanges")); 65 | vkInvalidateMappedMemoryRanges = 66 | reinterpret_cast(dlsym(libvulkan, "vkInvalidateMappedMemoryRanges")); 67 | vkGetDeviceMemoryCommitment = 68 | reinterpret_cast(dlsym(libvulkan, "vkGetDeviceMemoryCommitment")); 69 | vkBindBufferMemory = reinterpret_cast(dlsym(libvulkan, "vkBindBufferMemory")); 70 | vkBindImageMemory = reinterpret_cast(dlsym(libvulkan, "vkBindImageMemory")); 71 | vkGetBufferMemoryRequirements = 72 | reinterpret_cast(dlsym(libvulkan, "vkGetBufferMemoryRequirements")); 73 | vkGetImageMemoryRequirements = 74 | reinterpret_cast(dlsym(libvulkan, "vkGetImageMemoryRequirements")); 75 | vkGetImageSparseMemoryRequirements = 76 | reinterpret_cast(dlsym(libvulkan, "vkGetImageSparseMemoryRequirements")); 77 | vkGetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast( 78 | dlsym(libvulkan, "vkGetPhysicalDeviceSparseImageFormatProperties")); 79 | vkQueueBindSparse = reinterpret_cast(dlsym(libvulkan, "vkQueueBindSparse")); 80 | vkCreateFence = reinterpret_cast(dlsym(libvulkan, "vkCreateFence")); 81 | vkDestroyFence = reinterpret_cast(dlsym(libvulkan, "vkDestroyFence")); 82 | vkResetFences = reinterpret_cast(dlsym(libvulkan, "vkResetFences")); 83 | vkGetFenceStatus = reinterpret_cast(dlsym(libvulkan, "vkGetFenceStatus")); 84 | vkWaitForFences = reinterpret_cast(dlsym(libvulkan, "vkWaitForFences")); 85 | vkCreateSemaphore = reinterpret_cast(dlsym(libvulkan, "vkCreateSemaphore")); 86 | vkDestroySemaphore = reinterpret_cast(dlsym(libvulkan, "vkDestroySemaphore")); 87 | vkCreateEvent = reinterpret_cast(dlsym(libvulkan, "vkCreateEvent")); 88 | vkDestroyEvent = reinterpret_cast(dlsym(libvulkan, "vkDestroyEvent")); 89 | vkGetEventStatus = reinterpret_cast(dlsym(libvulkan, "vkGetEventStatus")); 90 | vkSetEvent = reinterpret_cast(dlsym(libvulkan, "vkSetEvent")); 91 | vkResetEvent = reinterpret_cast(dlsym(libvulkan, "vkResetEvent")); 92 | vkCreateQueryPool = reinterpret_cast(dlsym(libvulkan, "vkCreateQueryPool")); 93 | vkDestroyQueryPool = reinterpret_cast(dlsym(libvulkan, "vkDestroyQueryPool")); 94 | vkGetQueryPoolResults = reinterpret_cast(dlsym(libvulkan, "vkGetQueryPoolResults")); 95 | vkCreateBuffer = reinterpret_cast(dlsym(libvulkan, "vkCreateBuffer")); 96 | vkDestroyBuffer = reinterpret_cast(dlsym(libvulkan, "vkDestroyBuffer")); 97 | vkCreateBufferView = reinterpret_cast(dlsym(libvulkan, "vkCreateBufferView")); 98 | vkDestroyBufferView = reinterpret_cast(dlsym(libvulkan, "vkDestroyBufferView")); 99 | vkCreateImage = reinterpret_cast(dlsym(libvulkan, "vkCreateImage")); 100 | vkDestroyImage = reinterpret_cast(dlsym(libvulkan, "vkDestroyImage")); 101 | vkGetImageSubresourceLayout = 102 | reinterpret_cast(dlsym(libvulkan, "vkGetImageSubresourceLayout")); 103 | vkCreateImageView = reinterpret_cast(dlsym(libvulkan, "vkCreateImageView")); 104 | vkDestroyImageView = reinterpret_cast(dlsym(libvulkan, "vkDestroyImageView")); 105 | vkCreateShaderModule = reinterpret_cast(dlsym(libvulkan, "vkCreateShaderModule")); 106 | vkDestroyShaderModule = reinterpret_cast(dlsym(libvulkan, "vkDestroyShaderModule")); 107 | vkCreatePipelineCache = reinterpret_cast(dlsym(libvulkan, "vkCreatePipelineCache")); 108 | vkDestroyPipelineCache = reinterpret_cast(dlsym(libvulkan, "vkDestroyPipelineCache")); 109 | vkGetPipelineCacheData = reinterpret_cast(dlsym(libvulkan, "vkGetPipelineCacheData")); 110 | vkMergePipelineCaches = reinterpret_cast(dlsym(libvulkan, "vkMergePipelineCaches")); 111 | vkCreateGraphicsPipelines = reinterpret_cast(dlsym(libvulkan, "vkCreateGraphicsPipelines")); 112 | vkCreateComputePipelines = reinterpret_cast(dlsym(libvulkan, "vkCreateComputePipelines")); 113 | vkDestroyPipeline = reinterpret_cast(dlsym(libvulkan, "vkDestroyPipeline")); 114 | vkCreatePipelineLayout = reinterpret_cast(dlsym(libvulkan, "vkCreatePipelineLayout")); 115 | vkDestroyPipelineLayout = reinterpret_cast(dlsym(libvulkan, "vkDestroyPipelineLayout")); 116 | vkCreateSampler = reinterpret_cast(dlsym(libvulkan, "vkCreateSampler")); 117 | vkDestroySampler = reinterpret_cast(dlsym(libvulkan, "vkDestroySampler")); 118 | vkCreateDescriptorSetLayout = 119 | reinterpret_cast(dlsym(libvulkan, "vkCreateDescriptorSetLayout")); 120 | vkDestroyDescriptorSetLayout = 121 | reinterpret_cast(dlsym(libvulkan, "vkDestroyDescriptorSetLayout")); 122 | vkCreateDescriptorPool = reinterpret_cast(dlsym(libvulkan, "vkCreateDescriptorPool")); 123 | vkDestroyDescriptorPool = reinterpret_cast(dlsym(libvulkan, "vkDestroyDescriptorPool")); 124 | vkResetDescriptorPool = reinterpret_cast(dlsym(libvulkan, "vkResetDescriptorPool")); 125 | vkAllocateDescriptorSets = reinterpret_cast(dlsym(libvulkan, "vkAllocateDescriptorSets")); 126 | vkFreeDescriptorSets = reinterpret_cast(dlsym(libvulkan, "vkFreeDescriptorSets")); 127 | vkUpdateDescriptorSets = reinterpret_cast(dlsym(libvulkan, "vkUpdateDescriptorSets")); 128 | vkCreateFramebuffer = reinterpret_cast(dlsym(libvulkan, "vkCreateFramebuffer")); 129 | vkDestroyFramebuffer = reinterpret_cast(dlsym(libvulkan, "vkDestroyFramebuffer")); 130 | vkCreateRenderPass = reinterpret_cast(dlsym(libvulkan, "vkCreateRenderPass")); 131 | vkDestroyRenderPass = reinterpret_cast(dlsym(libvulkan, "vkDestroyRenderPass")); 132 | vkGetRenderAreaGranularity = reinterpret_cast(dlsym(libvulkan, "vkGetRenderAreaGranularity")); 133 | vkCreateCommandPool = reinterpret_cast(dlsym(libvulkan, "vkCreateCommandPool")); 134 | vkDestroyCommandPool = reinterpret_cast(dlsym(libvulkan, "vkDestroyCommandPool")); 135 | vkResetCommandPool = reinterpret_cast(dlsym(libvulkan, "vkResetCommandPool")); 136 | vkAllocateCommandBuffers = reinterpret_cast(dlsym(libvulkan, "vkAllocateCommandBuffers")); 137 | vkFreeCommandBuffers = reinterpret_cast(dlsym(libvulkan, "vkFreeCommandBuffers")); 138 | vkBeginCommandBuffer = reinterpret_cast(dlsym(libvulkan, "vkBeginCommandBuffer")); 139 | vkEndCommandBuffer = reinterpret_cast(dlsym(libvulkan, "vkEndCommandBuffer")); 140 | vkResetCommandBuffer = reinterpret_cast(dlsym(libvulkan, "vkResetCommandBuffer")); 141 | vkCmdBindPipeline = reinterpret_cast(dlsym(libvulkan, "vkCmdBindPipeline")); 142 | vkCmdSetViewport = reinterpret_cast(dlsym(libvulkan, "vkCmdSetViewport")); 143 | vkCmdSetScissor = reinterpret_cast(dlsym(libvulkan, "vkCmdSetScissor")); 144 | vkCmdSetLineWidth = reinterpret_cast(dlsym(libvulkan, "vkCmdSetLineWidth")); 145 | vkCmdSetDepthBias = reinterpret_cast(dlsym(libvulkan, "vkCmdSetDepthBias")); 146 | vkCmdSetBlendConstants = reinterpret_cast(dlsym(libvulkan, "vkCmdSetBlendConstants")); 147 | vkCmdSetDepthBounds = reinterpret_cast(dlsym(libvulkan, "vkCmdSetDepthBounds")); 148 | vkCmdSetStencilCompareMask = reinterpret_cast(dlsym(libvulkan, "vkCmdSetStencilCompareMask")); 149 | vkCmdSetStencilWriteMask = reinterpret_cast(dlsym(libvulkan, "vkCmdSetStencilWriteMask")); 150 | vkCmdSetStencilReference = reinterpret_cast(dlsym(libvulkan, "vkCmdSetStencilReference")); 151 | vkCmdBindDescriptorSets = reinterpret_cast(dlsym(libvulkan, "vkCmdBindDescriptorSets")); 152 | vkCmdBindIndexBuffer = reinterpret_cast(dlsym(libvulkan, "vkCmdBindIndexBuffer")); 153 | vkCmdBindVertexBuffers = reinterpret_cast(dlsym(libvulkan, "vkCmdBindVertexBuffers")); 154 | vkCmdDraw = reinterpret_cast(dlsym(libvulkan, "vkCmdDraw")); 155 | vkCmdDrawIndexed = reinterpret_cast(dlsym(libvulkan, "vkCmdDrawIndexed")); 156 | vkCmdDrawIndirect = reinterpret_cast(dlsym(libvulkan, "vkCmdDrawIndirect")); 157 | vkCmdDrawIndexedIndirect = reinterpret_cast(dlsym(libvulkan, "vkCmdDrawIndexedIndirect")); 158 | vkCmdDispatch = reinterpret_cast(dlsym(libvulkan, "vkCmdDispatch")); 159 | vkCmdDispatchIndirect = reinterpret_cast(dlsym(libvulkan, "vkCmdDispatchIndirect")); 160 | vkCmdCopyBuffer = reinterpret_cast(dlsym(libvulkan, "vkCmdCopyBuffer")); 161 | vkCmdCopyImage = reinterpret_cast(dlsym(libvulkan, "vkCmdCopyImage")); 162 | vkCmdBlitImage = reinterpret_cast(dlsym(libvulkan, "vkCmdBlitImage")); 163 | vkCmdCopyBufferToImage = reinterpret_cast(dlsym(libvulkan, "vkCmdCopyBufferToImage")); 164 | vkCmdCopyImageToBuffer = reinterpret_cast(dlsym(libvulkan, "vkCmdCopyImageToBuffer")); 165 | vkCmdUpdateBuffer = reinterpret_cast(dlsym(libvulkan, "vkCmdUpdateBuffer")); 166 | vkCmdFillBuffer = reinterpret_cast(dlsym(libvulkan, "vkCmdFillBuffer")); 167 | vkCmdClearColorImage = reinterpret_cast(dlsym(libvulkan, "vkCmdClearColorImage")); 168 | vkCmdClearDepthStencilImage = 169 | reinterpret_cast(dlsym(libvulkan, "vkCmdClearDepthStencilImage")); 170 | vkCmdClearAttachments = reinterpret_cast(dlsym(libvulkan, "vkCmdClearAttachments")); 171 | vkCmdResolveImage = reinterpret_cast(dlsym(libvulkan, "vkCmdResolveImage")); 172 | vkCmdSetEvent = reinterpret_cast(dlsym(libvulkan, "vkCmdSetEvent")); 173 | vkCmdResetEvent = reinterpret_cast(dlsym(libvulkan, "vkCmdResetEvent")); 174 | vkCmdWaitEvents = reinterpret_cast(dlsym(libvulkan, "vkCmdWaitEvents")); 175 | vkCmdPipelineBarrier = reinterpret_cast(dlsym(libvulkan, "vkCmdPipelineBarrier")); 176 | vkCmdBeginQuery = reinterpret_cast(dlsym(libvulkan, "vkCmdBeginQuery")); 177 | vkCmdEndQuery = reinterpret_cast(dlsym(libvulkan, "vkCmdEndQuery")); 178 | vkCmdResetQueryPool = reinterpret_cast(dlsym(libvulkan, "vkCmdResetQueryPool")); 179 | vkCmdWriteTimestamp = reinterpret_cast(dlsym(libvulkan, "vkCmdWriteTimestamp")); 180 | vkCmdCopyQueryPoolResults = reinterpret_cast(dlsym(libvulkan, "vkCmdCopyQueryPoolResults")); 181 | vkCmdPushConstants = reinterpret_cast(dlsym(libvulkan, "vkCmdPushConstants")); 182 | vkCmdBeginRenderPass = reinterpret_cast(dlsym(libvulkan, "vkCmdBeginRenderPass")); 183 | vkCmdNextSubpass = reinterpret_cast(dlsym(libvulkan, "vkCmdNextSubpass")); 184 | vkCmdEndRenderPass = reinterpret_cast(dlsym(libvulkan, "vkCmdEndRenderPass")); 185 | vkCmdExecuteCommands = reinterpret_cast(dlsym(libvulkan, "vkCmdExecuteCommands")); 186 | vkDestroySurfaceKHR = reinterpret_cast(dlsym(libvulkan, "vkDestroySurfaceKHR")); 187 | vkGetPhysicalDeviceSurfaceSupportKHR = 188 | reinterpret_cast(dlsym(libvulkan, "vkGetPhysicalDeviceSurfaceSupportKHR")); 189 | vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast( 190 | dlsym(libvulkan, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR")); 191 | vkGetPhysicalDeviceSurfaceFormatsKHR = 192 | reinterpret_cast(dlsym(libvulkan, "vkGetPhysicalDeviceSurfaceFormatsKHR")); 193 | vkGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast( 194 | dlsym(libvulkan, "vkGetPhysicalDeviceSurfacePresentModesKHR")); 195 | vkCreateSwapchainKHR = reinterpret_cast(dlsym(libvulkan, "vkCreateSwapchainKHR")); 196 | vkDestroySwapchainKHR = reinterpret_cast(dlsym(libvulkan, "vkDestroySwapchainKHR")); 197 | vkGetSwapchainImagesKHR = reinterpret_cast(dlsym(libvulkan, "vkGetSwapchainImagesKHR")); 198 | vkAcquireNextImageKHR = reinterpret_cast(dlsym(libvulkan, "vkAcquireNextImageKHR")); 199 | vkQueuePresentKHR = reinterpret_cast(dlsym(libvulkan, "vkQueuePresentKHR")); 200 | vkGetPhysicalDeviceDisplayPropertiesKHR = 201 | reinterpret_cast(dlsym(libvulkan, "vkGetPhysicalDeviceDisplayPropertiesKHR")); 202 | vkGetPhysicalDeviceDisplayPlanePropertiesKHR = reinterpret_cast( 203 | dlsym(libvulkan, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR")); 204 | vkGetDisplayPlaneSupportedDisplaysKHR = 205 | reinterpret_cast(dlsym(libvulkan, "vkGetDisplayPlaneSupportedDisplaysKHR")); 206 | vkGetDisplayModePropertiesKHR = 207 | reinterpret_cast(dlsym(libvulkan, "vkGetDisplayModePropertiesKHR")); 208 | vkCreateDisplayModeKHR = reinterpret_cast(dlsym(libvulkan, "vkCreateDisplayModeKHR")); 209 | vkGetDisplayPlaneCapabilitiesKHR = 210 | reinterpret_cast(dlsym(libvulkan, "vkGetDisplayPlaneCapabilitiesKHR")); 211 | vkCreateDisplayPlaneSurfaceKHR = 212 | reinterpret_cast(dlsym(libvulkan, "vkCreateDisplayPlaneSurfaceKHR")); 213 | vkCreateSharedSwapchainsKHR = 214 | reinterpret_cast(dlsym(libvulkan, "vkCreateSharedSwapchainsKHR")); 215 | 216 | #ifdef VK_USE_PLATFORM_XLIB_KHR 217 | vkCreateXlibSurfaceKHR = reinterpret_cast(dlsym(libvulkan, "vkCreateXlibSurfaceKHR")); 218 | vkGetPhysicalDeviceXlibPresentationSupportKHR = reinterpret_cast( 219 | dlsym(libvulkan, "vkGetPhysicalDeviceXlibPresentationSupportKHR")); 220 | #endif 221 | 222 | #ifdef VK_USE_PLATFORM_XCB_KHR 223 | vkCreateXcbSurfaceKHR = reinterpret_cast(dlsym(libvulkan, "vkCreateXcbSurfaceKHR")); 224 | vkGetPhysicalDeviceXcbPresentationSupportKHR = reinterpret_cast( 225 | dlsym(libvulkan, "vkGetPhysicalDeviceXcbPresentationSupportKHR")); 226 | #endif 227 | 228 | #ifdef VK_USE_PLATFORM_WAYLAND_KHR 229 | vkCreateWaylandSurfaceKHR = reinterpret_cast(dlsym(libvulkan, "vkCreateWaylandSurfaceKHR")); 230 | vkGetPhysicalDeviceWaylandPresentationSupportKHR = reinterpret_cast( 231 | dlsym(libvulkan, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")); 232 | #endif 233 | 234 | #ifdef VK_USE_PLATFORM_MIR_KHR 235 | vkCreateMirSurfaceKHR = reinterpret_cast(dlsym(libvulkan, "vkCreateMirSurfaceKHR")); 236 | vkGetPhysicalDeviceMirPresentationSupportKHR = reinterpret_cast( 237 | dlsym(libvulkan, "vkGetPhysicalDeviceMirPresentationSupportKHR")); 238 | #endif 239 | 240 | #ifdef VK_USE_PLATFORM_ANDROID_KHR 241 | vkCreateAndroidSurfaceKHR = reinterpret_cast(dlsym(libvulkan, "vkCreateAndroidSurfaceKHR")); 242 | #endif 243 | 244 | #ifdef VK_USE_PLATFORM_WIN32_KHR 245 | vkCreateWin32SurfaceKHR = reinterpret_cast(dlsym(libvulkan, "vkCreateWin32SurfaceKHR")); 246 | vkGetPhysicalDeviceWin32PresentationSupportKHR = reinterpret_cast( 247 | dlsym(libvulkan, "vkGetPhysicalDeviceWin32PresentationSupportKHR")); 248 | #endif 249 | return 1; 250 | } 251 | 252 | // No Vulkan support, do not set function addresses 253 | PFN_vkCreateInstance vkCreateInstance; 254 | PFN_vkDestroyInstance vkDestroyInstance; 255 | PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; 256 | PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; 257 | PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; 258 | PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; 259 | PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; 260 | PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; 261 | PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; 262 | PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; 263 | PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; 264 | PFN_vkCreateDevice vkCreateDevice; 265 | PFN_vkDestroyDevice vkDestroyDevice; 266 | PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; 267 | PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; 268 | PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; 269 | PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; 270 | PFN_vkGetDeviceQueue vkGetDeviceQueue; 271 | PFN_vkQueueSubmit vkQueueSubmit; 272 | PFN_vkQueueWaitIdle vkQueueWaitIdle; 273 | PFN_vkDeviceWaitIdle vkDeviceWaitIdle; 274 | PFN_vkAllocateMemory vkAllocateMemory; 275 | PFN_vkFreeMemory vkFreeMemory; 276 | PFN_vkMapMemory vkMapMemory; 277 | PFN_vkUnmapMemory vkUnmapMemory; 278 | PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; 279 | PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; 280 | PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment; 281 | PFN_vkBindBufferMemory vkBindBufferMemory; 282 | PFN_vkBindImageMemory vkBindImageMemory; 283 | PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; 284 | PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; 285 | PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements; 286 | PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; 287 | PFN_vkQueueBindSparse vkQueueBindSparse; 288 | PFN_vkCreateFence vkCreateFence; 289 | PFN_vkDestroyFence vkDestroyFence; 290 | PFN_vkResetFences vkResetFences; 291 | PFN_vkGetFenceStatus vkGetFenceStatus; 292 | PFN_vkWaitForFences vkWaitForFences; 293 | PFN_vkCreateSemaphore vkCreateSemaphore; 294 | PFN_vkDestroySemaphore vkDestroySemaphore; 295 | PFN_vkCreateEvent vkCreateEvent; 296 | PFN_vkDestroyEvent vkDestroyEvent; 297 | PFN_vkGetEventStatus vkGetEventStatus; 298 | PFN_vkSetEvent vkSetEvent; 299 | PFN_vkResetEvent vkResetEvent; 300 | PFN_vkCreateQueryPool vkCreateQueryPool; 301 | PFN_vkDestroyQueryPool vkDestroyQueryPool; 302 | PFN_vkGetQueryPoolResults vkGetQueryPoolResults; 303 | PFN_vkCreateBuffer vkCreateBuffer; 304 | PFN_vkDestroyBuffer vkDestroyBuffer; 305 | PFN_vkCreateBufferView vkCreateBufferView; 306 | PFN_vkDestroyBufferView vkDestroyBufferView; 307 | PFN_vkCreateImage vkCreateImage; 308 | PFN_vkDestroyImage vkDestroyImage; 309 | PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout; 310 | PFN_vkCreateImageView vkCreateImageView; 311 | PFN_vkDestroyImageView vkDestroyImageView; 312 | PFN_vkCreateShaderModule vkCreateShaderModule; 313 | PFN_vkDestroyShaderModule vkDestroyShaderModule; 314 | PFN_vkCreatePipelineCache vkCreatePipelineCache; 315 | PFN_vkDestroyPipelineCache vkDestroyPipelineCache; 316 | PFN_vkGetPipelineCacheData vkGetPipelineCacheData; 317 | PFN_vkMergePipelineCaches vkMergePipelineCaches; 318 | PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; 319 | PFN_vkCreateComputePipelines vkCreateComputePipelines; 320 | PFN_vkDestroyPipeline vkDestroyPipeline; 321 | PFN_vkCreatePipelineLayout vkCreatePipelineLayout; 322 | PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; 323 | PFN_vkCreateSampler vkCreateSampler; 324 | PFN_vkDestroySampler vkDestroySampler; 325 | PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; 326 | PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout; 327 | PFN_vkCreateDescriptorPool vkCreateDescriptorPool; 328 | PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool; 329 | PFN_vkResetDescriptorPool vkResetDescriptorPool; 330 | PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; 331 | PFN_vkFreeDescriptorSets vkFreeDescriptorSets; 332 | PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; 333 | PFN_vkCreateFramebuffer vkCreateFramebuffer; 334 | PFN_vkDestroyFramebuffer vkDestroyFramebuffer; 335 | PFN_vkCreateRenderPass vkCreateRenderPass; 336 | PFN_vkDestroyRenderPass vkDestroyRenderPass; 337 | PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity; 338 | PFN_vkCreateCommandPool vkCreateCommandPool; 339 | PFN_vkDestroyCommandPool vkDestroyCommandPool; 340 | PFN_vkResetCommandPool vkResetCommandPool; 341 | PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; 342 | PFN_vkFreeCommandBuffers vkFreeCommandBuffers; 343 | PFN_vkBeginCommandBuffer vkBeginCommandBuffer; 344 | PFN_vkEndCommandBuffer vkEndCommandBuffer; 345 | PFN_vkResetCommandBuffer vkResetCommandBuffer; 346 | PFN_vkCmdBindPipeline vkCmdBindPipeline; 347 | PFN_vkCmdSetViewport vkCmdSetViewport; 348 | PFN_vkCmdSetScissor vkCmdSetScissor; 349 | PFN_vkCmdSetLineWidth vkCmdSetLineWidth; 350 | PFN_vkCmdSetDepthBias vkCmdSetDepthBias; 351 | PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants; 352 | PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds; 353 | PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask; 354 | PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask; 355 | PFN_vkCmdSetStencilReference vkCmdSetStencilReference; 356 | PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets; 357 | PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; 358 | PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; 359 | PFN_vkCmdDraw vkCmdDraw; 360 | PFN_vkCmdDrawIndexed vkCmdDrawIndexed; 361 | PFN_vkCmdDrawIndirect vkCmdDrawIndirect; 362 | PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; 363 | PFN_vkCmdDispatch vkCmdDispatch; 364 | PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect; 365 | PFN_vkCmdCopyBuffer vkCmdCopyBuffer; 366 | PFN_vkCmdCopyImage vkCmdCopyImage; 367 | PFN_vkCmdBlitImage vkCmdBlitImage; 368 | PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; 369 | PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer; 370 | PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer; 371 | PFN_vkCmdFillBuffer vkCmdFillBuffer; 372 | PFN_vkCmdClearColorImage vkCmdClearColorImage; 373 | PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage; 374 | PFN_vkCmdClearAttachments vkCmdClearAttachments; 375 | PFN_vkCmdResolveImage vkCmdResolveImage; 376 | PFN_vkCmdSetEvent vkCmdSetEvent; 377 | PFN_vkCmdResetEvent vkCmdResetEvent; 378 | PFN_vkCmdWaitEvents vkCmdWaitEvents; 379 | PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; 380 | PFN_vkCmdBeginQuery vkCmdBeginQuery; 381 | PFN_vkCmdEndQuery vkCmdEndQuery; 382 | PFN_vkCmdResetQueryPool vkCmdResetQueryPool; 383 | PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp; 384 | PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults; 385 | PFN_vkCmdPushConstants vkCmdPushConstants; 386 | PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; 387 | PFN_vkCmdNextSubpass vkCmdNextSubpass; 388 | PFN_vkCmdEndRenderPass vkCmdEndRenderPass; 389 | PFN_vkCmdExecuteCommands vkCmdExecuteCommands; 390 | PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; 391 | PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; 392 | PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; 393 | PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; 394 | PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; 395 | PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; 396 | PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; 397 | PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; 398 | PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; 399 | PFN_vkQueuePresentKHR vkQueuePresentKHR; 400 | PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; 401 | PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; 402 | PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; 403 | PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; 404 | PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR; 405 | PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; 406 | PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; 407 | PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; 408 | 409 | #ifdef VK_USE_PLATFORM_XLIB_KHR 410 | PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; 411 | PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR; 412 | #endif 413 | 414 | #ifdef VK_USE_PLATFORM_XCB_KHR 415 | PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; 416 | PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR; 417 | #endif 418 | 419 | #ifdef VK_USE_PLATFORM_WAYLAND_KHR 420 | PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; 421 | PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; 422 | #endif 423 | 424 | #ifdef VK_USE_PLATFORM_MIR_KHR 425 | PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR; 426 | PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR; 427 | #endif 428 | 429 | #ifdef VK_USE_PLATFORM_ANDROID_KHR 430 | PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; 431 | #endif 432 | 433 | #ifdef VK_USE_PLATFORM_WIN32_KHR 434 | PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; 435 | PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR; 436 | #endif 437 | PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT; 438 | PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; 439 | PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT; 440 | 441 | #ifdef __cplusplus 442 | } 443 | #endif 444 | -------------------------------------------------------------------------------- /app/src/main/cpp/vulkan_wrapper/vulkan_wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The Android Open Source Project 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 | // This file is generated. 17 | #ifndef VULKAN_WRAPPER_H 18 | #define VULKAN_WRAPPER_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #define VK_NO_PROTOTYPES 1 25 | #include 26 | 27 | /* Initialize the Vulkan function pointer variables declared in this header. 28 | * Returns 0 if vulkan is not available, non-zero if it is available. 29 | */ 30 | int InitVulkan(void); 31 | 32 | // VK_core 33 | extern PFN_vkCreateInstance vkCreateInstance; 34 | extern PFN_vkDestroyInstance vkDestroyInstance; 35 | extern PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; 36 | extern PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures; 37 | extern PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties; 38 | extern PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties; 39 | extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; 40 | extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties; 41 | extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; 42 | extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; 43 | extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; 44 | extern PFN_vkCreateDevice vkCreateDevice; 45 | extern PFN_vkDestroyDevice vkDestroyDevice; 46 | extern PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; 47 | extern PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties; 48 | extern PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties; 49 | extern PFN_vkEnumerateDeviceLayerProperties vkEnumerateDeviceLayerProperties; 50 | extern PFN_vkGetDeviceQueue vkGetDeviceQueue; 51 | extern PFN_vkQueueSubmit vkQueueSubmit; 52 | extern PFN_vkQueueWaitIdle vkQueueWaitIdle; 53 | extern PFN_vkDeviceWaitIdle vkDeviceWaitIdle; 54 | extern PFN_vkAllocateMemory vkAllocateMemory; 55 | extern PFN_vkFreeMemory vkFreeMemory; 56 | extern PFN_vkMapMemory vkMapMemory; 57 | extern PFN_vkUnmapMemory vkUnmapMemory; 58 | extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; 59 | extern PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; 60 | extern PFN_vkGetDeviceMemoryCommitment vkGetDeviceMemoryCommitment; 61 | extern PFN_vkBindBufferMemory vkBindBufferMemory; 62 | extern PFN_vkBindImageMemory vkBindImageMemory; 63 | extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; 64 | extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; 65 | extern PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements; 66 | extern PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImageFormatProperties; 67 | extern PFN_vkQueueBindSparse vkQueueBindSparse; 68 | extern PFN_vkCreateFence vkCreateFence; 69 | extern PFN_vkDestroyFence vkDestroyFence; 70 | extern PFN_vkResetFences vkResetFences; 71 | extern PFN_vkGetFenceStatus vkGetFenceStatus; 72 | extern PFN_vkWaitForFences vkWaitForFences; 73 | extern PFN_vkCreateSemaphore vkCreateSemaphore; 74 | extern PFN_vkDestroySemaphore vkDestroySemaphore; 75 | extern PFN_vkCreateEvent vkCreateEvent; 76 | extern PFN_vkDestroyEvent vkDestroyEvent; 77 | extern PFN_vkGetEventStatus vkGetEventStatus; 78 | extern PFN_vkSetEvent vkSetEvent; 79 | extern PFN_vkResetEvent vkResetEvent; 80 | extern PFN_vkCreateQueryPool vkCreateQueryPool; 81 | extern PFN_vkDestroyQueryPool vkDestroyQueryPool; 82 | extern PFN_vkGetQueryPoolResults vkGetQueryPoolResults; 83 | extern PFN_vkCreateBuffer vkCreateBuffer; 84 | extern PFN_vkDestroyBuffer vkDestroyBuffer; 85 | extern PFN_vkCreateBufferView vkCreateBufferView; 86 | extern PFN_vkDestroyBufferView vkDestroyBufferView; 87 | extern PFN_vkCreateImage vkCreateImage; 88 | extern PFN_vkDestroyImage vkDestroyImage; 89 | extern PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout; 90 | extern PFN_vkCreateImageView vkCreateImageView; 91 | extern PFN_vkDestroyImageView vkDestroyImageView; 92 | extern PFN_vkCreateShaderModule vkCreateShaderModule; 93 | extern PFN_vkDestroyShaderModule vkDestroyShaderModule; 94 | extern PFN_vkCreatePipelineCache vkCreatePipelineCache; 95 | extern PFN_vkDestroyPipelineCache vkDestroyPipelineCache; 96 | extern PFN_vkGetPipelineCacheData vkGetPipelineCacheData; 97 | extern PFN_vkMergePipelineCaches vkMergePipelineCaches; 98 | extern PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines; 99 | extern PFN_vkCreateComputePipelines vkCreateComputePipelines; 100 | extern PFN_vkDestroyPipeline vkDestroyPipeline; 101 | extern PFN_vkCreatePipelineLayout vkCreatePipelineLayout; 102 | extern PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout; 103 | extern PFN_vkCreateSampler vkCreateSampler; 104 | extern PFN_vkDestroySampler vkDestroySampler; 105 | extern PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout; 106 | extern PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout; 107 | extern PFN_vkCreateDescriptorPool vkCreateDescriptorPool; 108 | extern PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool; 109 | extern PFN_vkResetDescriptorPool vkResetDescriptorPool; 110 | extern PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets; 111 | extern PFN_vkFreeDescriptorSets vkFreeDescriptorSets; 112 | extern PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets; 113 | extern PFN_vkCreateFramebuffer vkCreateFramebuffer; 114 | extern PFN_vkDestroyFramebuffer vkDestroyFramebuffer; 115 | extern PFN_vkCreateRenderPass vkCreateRenderPass; 116 | extern PFN_vkDestroyRenderPass vkDestroyRenderPass; 117 | extern PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity; 118 | extern PFN_vkCreateCommandPool vkCreateCommandPool; 119 | extern PFN_vkDestroyCommandPool vkDestroyCommandPool; 120 | extern PFN_vkResetCommandPool vkResetCommandPool; 121 | extern PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; 122 | extern PFN_vkFreeCommandBuffers vkFreeCommandBuffers; 123 | extern PFN_vkBeginCommandBuffer vkBeginCommandBuffer; 124 | extern PFN_vkEndCommandBuffer vkEndCommandBuffer; 125 | extern PFN_vkResetCommandBuffer vkResetCommandBuffer; 126 | extern PFN_vkCmdBindPipeline vkCmdBindPipeline; 127 | extern PFN_vkCmdSetViewport vkCmdSetViewport; 128 | extern PFN_vkCmdSetScissor vkCmdSetScissor; 129 | extern PFN_vkCmdSetLineWidth vkCmdSetLineWidth; 130 | extern PFN_vkCmdSetDepthBias vkCmdSetDepthBias; 131 | extern PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants; 132 | extern PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds; 133 | extern PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask; 134 | extern PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask; 135 | extern PFN_vkCmdSetStencilReference vkCmdSetStencilReference; 136 | extern PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets; 137 | extern PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; 138 | extern PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; 139 | extern PFN_vkCmdDraw vkCmdDraw; 140 | extern PFN_vkCmdDrawIndexed vkCmdDrawIndexed; 141 | extern PFN_vkCmdDrawIndirect vkCmdDrawIndirect; 142 | extern PFN_vkCmdDrawIndexedIndirect vkCmdDrawIndexedIndirect; 143 | extern PFN_vkCmdDispatch vkCmdDispatch; 144 | extern PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect; 145 | extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer; 146 | extern PFN_vkCmdCopyImage vkCmdCopyImage; 147 | extern PFN_vkCmdBlitImage vkCmdBlitImage; 148 | extern PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; 149 | extern PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer; 150 | extern PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer; 151 | extern PFN_vkCmdFillBuffer vkCmdFillBuffer; 152 | extern PFN_vkCmdClearColorImage vkCmdClearColorImage; 153 | extern PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage; 154 | extern PFN_vkCmdClearAttachments vkCmdClearAttachments; 155 | extern PFN_vkCmdResolveImage vkCmdResolveImage; 156 | extern PFN_vkCmdSetEvent vkCmdSetEvent; 157 | extern PFN_vkCmdResetEvent vkCmdResetEvent; 158 | extern PFN_vkCmdWaitEvents vkCmdWaitEvents; 159 | extern PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; 160 | extern PFN_vkCmdBeginQuery vkCmdBeginQuery; 161 | extern PFN_vkCmdEndQuery vkCmdEndQuery; 162 | extern PFN_vkCmdResetQueryPool vkCmdResetQueryPool; 163 | extern PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp; 164 | extern PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults; 165 | extern PFN_vkCmdPushConstants vkCmdPushConstants; 166 | extern PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass; 167 | extern PFN_vkCmdNextSubpass vkCmdNextSubpass; 168 | extern PFN_vkCmdEndRenderPass vkCmdEndRenderPass; 169 | extern PFN_vkCmdExecuteCommands vkCmdExecuteCommands; 170 | 171 | // VK_KHR_surface 172 | extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; 173 | extern PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; 174 | extern PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; 175 | extern PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; 176 | extern PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; 177 | 178 | // VK_KHR_swapchain 179 | extern PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; 180 | extern PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; 181 | extern PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; 182 | extern PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; 183 | extern PFN_vkQueuePresentKHR vkQueuePresentKHR; 184 | 185 | // VK_KHR_display 186 | extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; 187 | extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; 188 | extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; 189 | extern PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; 190 | extern PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR; 191 | extern PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; 192 | extern PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; 193 | 194 | // VK_KHR_display_swapchain 195 | extern PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR; 196 | 197 | #ifdef VK_USE_PLATFORM_XLIB_KHR 198 | // VK_KHR_xlib_surface 199 | extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR; 200 | extern PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR; 201 | #endif 202 | 203 | #ifdef VK_USE_PLATFORM_XCB_KHR 204 | // VK_KHR_xcb_surface 205 | extern PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR; 206 | extern PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR; 207 | #endif 208 | 209 | #ifdef VK_USE_PLATFORM_WAYLAND_KHR 210 | // VK_KHR_wayland_surface 211 | extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; 212 | extern PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR; 213 | #endif 214 | 215 | #ifdef VK_USE_PLATFORM_MIR_KHR 216 | // VK_KHR_mir_surface 217 | extern PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR; 218 | extern PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR; 219 | #endif 220 | 221 | #ifdef VK_USE_PLATFORM_ANDROID_KHR 222 | // VK_KHR_android_surface 223 | extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR; 224 | #endif 225 | 226 | #ifdef VK_USE_PLATFORM_WIN32_KHR 227 | // VK_KHR_win32_surface 228 | extern PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; 229 | extern PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR; 230 | #endif 231 | 232 | // VK_KHR_sampler_mirror_clamp_to_edge 233 | 234 | #ifdef __cplusplus 235 | } 236 | #endif 237 | 238 | #endif // VULKAN_WRAPPER_H 239 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/piasy/vulkantutorial/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.piasy.vulkantutorial; 2 | 3 | import android.content.res.AssetManager; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.SurfaceHolder; 7 | import android.view.SurfaceView; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback { 12 | 13 | private static final String VERTEX_SHADER = "shaders/triangle.vert.spv"; 14 | private static final String FRAGMENT_SHADER = "shaders/triangle.frag.spv"; 15 | 16 | private VulkanTutorialApplication mTriangleApplication; 17 | private AssetManager mAssetManager; 18 | private boolean mFirstSurfaceChange; 19 | private boolean mFullscreen = true; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | 26 | mAssetManager = getAssets(); 27 | 28 | mTriangleApplication = new VulkanTutorialApplication(mAssetManager, VERTEX_SHADER, 29 | FRAGMENT_SHADER); 30 | 31 | final SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surface); 32 | surfaceView.getHolder().addCallback(this); 33 | 34 | findViewById(R.id.mBtnResize).setOnClickListener(new View.OnClickListener() { 35 | @Override 36 | public void onClick(final View v) { 37 | mFullscreen = !mFullscreen; 38 | 39 | ViewGroup.LayoutParams params = surfaceView.getLayoutParams(); 40 | 41 | if (mFullscreen) { 42 | params.width = ViewGroup.LayoutParams.MATCH_PARENT; 43 | params.height = ViewGroup.LayoutParams.MATCH_PARENT; 44 | } else { 45 | params.width = 180; 46 | params.height = 320; 47 | } 48 | 49 | surfaceView.setLayoutParams(params); 50 | } 51 | }); 52 | } 53 | 54 | @Override 55 | protected void onResume() { 56 | super.onResume(); 57 | 58 | mTriangleApplication.resume(); 59 | } 60 | 61 | @Override 62 | protected void onPause() { 63 | super.onPause(); 64 | 65 | mTriangleApplication.pause(); 66 | } 67 | 68 | @Override 69 | protected void onDestroy() { 70 | super.onDestroy(); 71 | 72 | mTriangleApplication.stop(); 73 | } 74 | 75 | @Override 76 | public void surfaceCreated(final SurfaceHolder holder) { 77 | mTriangleApplication.run(holder.getSurface()); 78 | mFirstSurfaceChange = true; 79 | } 80 | 81 | @Override 82 | public void surfaceChanged(final SurfaceHolder holder, final int format, final int width, 83 | final int height) { 84 | if (!mFirstSurfaceChange) { 85 | mTriangleApplication.surfaceChanged(); 86 | } 87 | mFirstSurfaceChange = false; 88 | } 89 | 90 | @Override 91 | public void surfaceDestroyed(final SurfaceHolder holder) { 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/piasy/vulkantutorial/VulkanTutorialApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.piasy.vulkantutorial; 2 | 3 | import android.content.res.AssetManager; 4 | import android.view.Surface; 5 | 6 | /** 7 | * Created by Piasy{github.com/Piasy} on 30/06/2017. 8 | */ 9 | 10 | public class VulkanTutorialApplication { 11 | 12 | static { 13 | System.loadLibrary("vulkan"); 14 | System.loadLibrary("vulkan-tutorial"); 15 | } 16 | 17 | private long mNativeHandle; 18 | 19 | public VulkanTutorialApplication(AssetManager assetManager, String vertexShader, 20 | String fragmentShader) { 21 | mNativeHandle = create(assetManager, vertexShader, fragmentShader); 22 | } 23 | 24 | private static native long create(AssetManager assetManager, String vertexShader, 25 | String fragmentShader); 26 | 27 | private static native void run(long nativeHandle, Surface surface); 28 | 29 | private static native void pause(long nativeHandle); 30 | 31 | private static native void resume(long nativeHandle); 32 | 33 | private static native void surfaceChanged(long nativeHandle); 34 | 35 | private static native void stop(long nativeHandle); 36 | 37 | public void run(final Surface surface) { 38 | new Thread(new Runnable() { 39 | @Override 40 | public void run() { 41 | VulkanTutorialApplication.run(mNativeHandle, surface); 42 | } 43 | }).start(); 44 | } 45 | 46 | public void pause() { 47 | pause(mNativeHandle); 48 | } 49 | 50 | public void resume() { 51 | resume(mNativeHandle); 52 | } 53 | 54 | public void surfaceChanged() { 55 | surfaceChanged(mNativeHandle); 56 | } 57 | 58 | public void stop() { 59 | stop(mNativeHandle); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 |