├── README.md ├── ScreenShot.png ├── app ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── shaders │ │ ├── blend.frag.spv │ │ ├── blend.vert.spv │ │ ├── peel.frag.spv │ │ ├── peel.vert.spv │ │ ├── trad.frag.spv │ │ └── trad.vert.spv │ ├── jni │ ├── CMakeLists.txt │ ├── Simulation.cpp │ ├── Simulation.h │ ├── btQuickprof.cpp │ ├── btQuickprof.h │ ├── log.h │ ├── main.cpp │ ├── matrix.h │ ├── models.h │ └── stdredirect.h │ └── res │ ├── drawable-xhdpi │ └── banner.png │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ └── values │ └── strings.xml ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── local.properties ├── nativeactivity ├── build.gradle └── src │ └── main │ └── AndroidManifest.xml ├── settings.gradle └── shaders ├── blend ├── frag.spv ├── test.frag ├── test.vert └── vert.spv ├── peel ├── frag.spv ├── test.frag ├── test.vert └── vert.spv └── trad ├── frag.spv ├── test.frag ├── test.vert └── vert.spv /README.md: -------------------------------------------------------------------------------- 1 | # Vulkan depth peel demo 2 | Demonstrates order independent transparency on Vulkan using depth peeling. This code accompanies the blog post [Depth Peeling Order Independent Transparency in Vulkan] (https://matthewwellings.com/blog/depth-peeling-order-independent-transparency-in-vulkan/). 3 | 4 | This demo will run on Linux (XCB) and Android. It makes use of subpasses, input attachments and reusable command buffers. 5 | 6 | Keys (on Linux): 7 | - Space to toggle split-screen (left is traditional order dependent right is depth peeled) 8 | - Up and down to change number of layers used. 9 | - Left and right to change number of objects rendered. 10 | - W and S to display only one of the peeled layers and to select the currently displayed layer. 11 | 12 | ![Screenshot](https://github.com/openforeveryone/VulkanDepthPeel/blob/master/ScreenShot.png "Screenshot") 13 | 14 | All blocks are the same size and rendered in arbitrary order in separate draw calls. 15 | -------------------------------------------------------------------------------- /ScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/ScreenShot.png -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.model.application' 2 | 3 | model { 4 | android { 5 | compileSdkVersion = 23 6 | buildToolsVersion = '23.0.2' 7 | 8 | defaultConfig { 9 | applicationId = 'com.example.vulkandepthpeel' 10 | minSdkVersion.apiLevel = 9 11 | targetSdkVersion.apiLevel = 23 12 | } 13 | ndk { 14 | platformVersion = 23 15 | moduleName ='native-activity' 16 | toolchain = 'clang' 17 | stl = 'gnustl_static' 18 | cppFlags.add('-std=c++11') 19 | ldLibs.addAll(['log', 'android']) 20 | abiFilters.addAll(['x86', 'armeabi-v7a']) 21 | } 22 | sources { 23 | main { 24 | jni { 25 | dependencies { 26 | project ':nativeactivity' linkage 'static' 27 | } 28 | } 29 | } 30 | } 31 | buildTypes { 32 | release { 33 | minifyEnabled = false 34 | proguardFiles.add(file('proguard-rules.txt')) 35 | ndk { 36 | debuggable true 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 9 | 10 | 11 | 17 | 19 | 20 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/assets/shaders/blend.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/assets/shaders/blend.frag.spv -------------------------------------------------------------------------------- /app/src/main/assets/shaders/blend.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/assets/shaders/blend.vert.spv -------------------------------------------------------------------------------- /app/src/main/assets/shaders/peel.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/assets/shaders/peel.frag.spv -------------------------------------------------------------------------------- /app/src/main/assets/shaders/peel.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/assets/shaders/peel.vert.spv -------------------------------------------------------------------------------- /app/src/main/assets/shaders/trad.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/assets/shaders/trad.frag.spv -------------------------------------------------------------------------------- /app/src/main/assets/shaders/trad.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/assets/shaders/trad.vert.spv -------------------------------------------------------------------------------- /app/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | project (VulkanDemos) 3 | 4 | set(VULKAN_SDK_PATH /home/matt/Downloads/VulkanSDK/1.0.13.0/x86_64/) 5 | include_directories(${VULKAN_SDK_PATH}/include) 6 | link_directories(${VULKAN_SDK_PATH}/lib) 7 | 8 | add_executable(vulkanDepthPeel main.cpp Simulation.cpp btQuickprof.cpp) 9 | 10 | target_compile_features(vulkanDepthPeel PRIVATE cxx_range_for) 11 | target_link_libraries(vulkanDepthPeel vulkan xcb xcb-icccm m) 12 | -------------------------------------------------------------------------------- /app/src/main/jni/Simulation.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by matt on 5/28/16. 3 | // 4 | 5 | #include 6 | #include 7 | #include "Simulation.h" 8 | #include "log.h" 9 | 10 | Simulation::Simulation() { 11 | LOGI("Simulation()"); 12 | paused=false; 13 | for (int i = 0; i < MAX_BOXES*3; i++) 14 | colours[i] = (float) rand() / (float) (RAND_MAX); 15 | float identityMatrix[16]={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; 16 | for(int i=0; i 30 || transforms[i * 16 + 13] < -20 || transforms[i * 16 + 13] > 20) 31 | { 32 | transforms[i*16+12]=(float)rand()/(float)(RAND_MAX) * 40.0f - 20.0f; 33 | transforms[i*16+13]=(float)rand()/(float)(RAND_MAX) * 30.0f - 15.0f; 34 | velocities[i*2]=(float)rand()/(float)(RAND_MAX) / 8.0f -(1.0/16.0f); 35 | velocities[i*2+1]=(float)rand()/(float)(RAND_MAX) / 8.0f -(1.0f/16.0f); 36 | // LOGI("Reset cube %d (%f, %f, %f)", i, transforms[i*16+12], transforms[i*16+13], transforms[i*16+14]); 37 | } 38 | transforms[i*16+12]+=velocities[i*2]; 39 | transforms[i*16+13]+=velocities[i*2+1]; 40 | } 41 | } 42 | 43 | void Simulation::write(uint8_t *buffer, int offset) { 44 | for (int i=0; i 9 | 10 | #define MAX_BOXES 500 11 | 12 | class Simulation { 13 | public: 14 | Simulation(); 15 | void step(); 16 | void write(uint8_t *buffer, int offset); 17 | // float positions[100*3]; 18 | float velocities[MAX_BOXES*2]; 19 | float transforms[MAX_BOXES*16]; 20 | float colours[MAX_BOXES*3]; 21 | bool paused; 22 | }; 23 | 24 | 25 | #endif //VULKAN_DEPTHPEEL_SIMULATION_H 26 | -------------------------------------------------------------------------------- /app/src/main/jni/btQuickprof.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | *************************************************************************************************** 4 | ** 5 | ** profile.cpp 6 | ** 7 | ** Real-Time Hierarchical Profiling for Game Programming Gems 3 8 | ** 9 | ** by Greg Hjelstrom & Byon Garrabrant 10 | ** 11 | ***************************************************************************************************/ 12 | 13 | // Credits: The Clock class was inspired by the Timer classes in 14 | // Ogre (www.ogre3d.org). 15 | 16 | #include "btQuickprof.h" 17 | 18 | 19 | #ifdef __CELLOS_LV2__ 20 | #include 21 | #include 22 | #include 23 | #endif 24 | 25 | #if defined (SUNOS) || defined (__SUNOS__) 26 | #include 27 | #endif 28 | 29 | #if defined(WIN32) || defined(_WIN32) 30 | 31 | #define BT_USE_WINDOWS_TIMERS 32 | #define WIN32_LEAN_AND_MEAN 33 | #define NOWINRES 34 | #define NOMCX 35 | #define NOIME 36 | 37 | #ifdef _XBOX 38 | #include 39 | #else //_XBOX 40 | #include 41 | #endif //_XBOX 42 | 43 | #include 44 | 45 | 46 | #else //_WIN32 47 | #include 48 | #endif //_WIN32 49 | 50 | #define mymin(a,b) (a > b ? a : b) 51 | 52 | struct btClockData 53 | { 54 | 55 | #ifdef BT_USE_WINDOWS_TIMERS 56 | LARGE_INTEGER mClockFrequency; 57 | DWORD mStartTick; 58 | LONGLONG mPrevElapsedTime; 59 | LARGE_INTEGER mStartTime; 60 | #else 61 | #ifdef __CELLOS_LV2__ 62 | uint64_t mStartTime; 63 | #else 64 | struct timeval mStartTime; 65 | #endif 66 | #endif //__CELLOS_LV2__ 67 | 68 | }; 69 | 70 | ///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. 71 | btClock::btClock() 72 | { 73 | m_data = new btClockData; 74 | #ifdef BT_USE_WINDOWS_TIMERS 75 | QueryPerformanceFrequency(&m_data->mClockFrequency); 76 | #endif 77 | reset(); 78 | } 79 | 80 | btClock::~btClock() 81 | { 82 | delete m_data; 83 | } 84 | 85 | btClock::btClock(const btClock& other) 86 | { 87 | 88 | m_data = new btClockData; 89 | *m_data = *other.m_data; 90 | } 91 | 92 | btClock& btClock::operator=(const btClock& other) 93 | { 94 | *m_data = *other.m_data; 95 | return *this; 96 | } 97 | 98 | 99 | /// Resets the initial reference time. 100 | void btClock::reset() 101 | { 102 | #ifdef BT_USE_WINDOWS_TIMERS 103 | QueryPerformanceCounter(&m_data->mStartTime); 104 | m_data->mStartTick = GetTickCount(); 105 | m_data->mPrevElapsedTime = 0; 106 | #else 107 | #ifdef __CELLOS_LV2__ 108 | 109 | typedef uint64_t ClockSize; 110 | ClockSize newTime; 111 | //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); 112 | SYS_TIMEBASE_GET( newTime ); 113 | m_data->mStartTime = newTime; 114 | #else 115 | gettimeofday(&m_data->mStartTime, 0); 116 | #endif 117 | #endif 118 | } 119 | 120 | /// Returns the time in ms since the last call to reset or since 121 | /// the btClock was created. 122 | unsigned long int btClock::getTimeMilliseconds() 123 | { 124 | #ifdef BT_USE_WINDOWS_TIMERS 125 | LARGE_INTEGER currentTime; 126 | QueryPerformanceCounter(¤tTime); 127 | LONGLONG elapsedTime = currentTime.QuadPart - 128 | m_data->mStartTime.QuadPart; 129 | // Compute the number of millisecond ticks elapsed. 130 | unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 131 | m_data->mClockFrequency.QuadPart); 132 | // Check for unexpected leaps in the Win32 performance counter. 133 | // (This is caused by unexpected data across the PCI to ISA 134 | // bridge, aka south bridge. See Microsoft KB274323.) 135 | unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick; 136 | signed long msecOff = (signed long)(msecTicks - elapsedTicks); 137 | if (msecOff < -100 || msecOff > 100) 138 | { 139 | // Adjust the starting time forwards. 140 | LONGLONG msecAdjustment = mymin(msecOff * 141 | m_data->mClockFrequency.QuadPart / 1000, elapsedTime - 142 | m_data->mPrevElapsedTime); 143 | m_data->mStartTime.QuadPart += msecAdjustment; 144 | elapsedTime -= msecAdjustment; 145 | 146 | // Recompute the number of millisecond ticks elapsed. 147 | msecTicks = (unsigned long)(1000 * elapsedTime / 148 | m_data->mClockFrequency.QuadPart); 149 | } 150 | 151 | // Store the current elapsed time for adjustments next time. 152 | m_data->mPrevElapsedTime = elapsedTime; 153 | 154 | return msecTicks; 155 | #else 156 | 157 | #ifdef __CELLOS_LV2__ 158 | uint64_t freq=sys_time_get_timebase_frequency(); 159 | double dFreq=((double) freq) / 1000.0; 160 | typedef uint64_t ClockSize; 161 | ClockSize newTime; 162 | SYS_TIMEBASE_GET( newTime ); 163 | //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); 164 | 165 | return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq); 166 | #else 167 | 168 | struct timeval currentTime; 169 | gettimeofday(¤tTime, 0); 170 | return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 + 171 | (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000; 172 | #endif //__CELLOS_LV2__ 173 | #endif 174 | } 175 | 176 | /// Returns the time in us since the last call to reset or since 177 | /// the Clock was created. 178 | unsigned long int btClock::getTimeMicroseconds() 179 | { 180 | #ifdef BT_USE_WINDOWS_TIMERS 181 | LARGE_INTEGER currentTime; 182 | QueryPerformanceCounter(¤tTime); 183 | LONGLONG elapsedTime = currentTime.QuadPart - 184 | m_data->mStartTime.QuadPart; 185 | 186 | // Compute the number of millisecond ticks elapsed. 187 | unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 188 | m_data->mClockFrequency.QuadPart); 189 | 190 | // Check for unexpected leaps in the Win32 performance counter. 191 | // (This is caused by unexpected data across the PCI to ISA 192 | // bridge, aka south bridge. See Microsoft KB274323.) 193 | unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick; 194 | signed long msecOff = (signed long)(msecTicks - elapsedTicks); 195 | if (msecOff < -100 || msecOff > 100) 196 | { 197 | // Adjust the starting time forwards. 198 | LONGLONG msecAdjustment = mymin(msecOff * 199 | m_data->mClockFrequency.QuadPart / 1000, elapsedTime - 200 | m_data->mPrevElapsedTime); 201 | m_data->mStartTime.QuadPart += msecAdjustment; 202 | elapsedTime -= msecAdjustment; 203 | } 204 | 205 | // Store the current elapsed time for adjustments next time. 206 | m_data->mPrevElapsedTime = elapsedTime; 207 | 208 | // Convert to microseconds. 209 | unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / 210 | m_data->mClockFrequency.QuadPart); 211 | 212 | return usecTicks; 213 | #else 214 | 215 | #ifdef __CELLOS_LV2__ 216 | uint64_t freq=sys_time_get_timebase_frequency(); 217 | double dFreq=((double) freq)/ 1000000.0; 218 | typedef uint64_t ClockSize; 219 | ClockSize newTime; 220 | //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); 221 | SYS_TIMEBASE_GET( newTime ); 222 | 223 | return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq); 224 | #else 225 | 226 | struct timeval currentTime; 227 | gettimeofday(¤tTime, 0); 228 | return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 + 229 | (currentTime.tv_usec - m_data->mStartTime.tv_usec); 230 | #endif//__CELLOS_LV2__ 231 | #endif 232 | } 233 | -------------------------------------------------------------------------------- /app/src/main/jni/btQuickprof.h: -------------------------------------------------------------------------------- 1 | 2 | /*************************************************************************************************** 3 | ** 4 | ** Real-Time Hierarchical Profiling for Game Programming Gems 3 5 | ** 6 | ** by Greg Hjelstrom & Byon Garrabrant 7 | ** 8 | ***************************************************************************************************/ 9 | 10 | // Credits: The Clock class was inspired by the Timer classes in 11 | // Ogre (www.ogre3d.org). 12 | 13 | 14 | 15 | #ifndef BT_QUICK_PROF_H 16 | #define BT_QUICK_PROF_H 17 | 18 | #include //@todo remove this, backwards compatibility 19 | #include 20 | 21 | ///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. 22 | class btClock 23 | { 24 | public: 25 | btClock(); 26 | 27 | btClock(const btClock& other); 28 | btClock& operator=(const btClock& other); 29 | 30 | ~btClock(); 31 | 32 | /// Resets the initial reference time. 33 | void reset(); 34 | 35 | /// Returns the time in ms since the last call to reset or since 36 | /// the btClock was created. 37 | unsigned long int getTimeMilliseconds(); 38 | 39 | /// Returns the time in us since the last call to reset or since 40 | /// the Clock was created. 41 | unsigned long int getTimeMicroseconds(); 42 | private: 43 | struct btClockData* m_data; 44 | }; 45 | 46 | #endif //BT_QUICK_PROF_H 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/jni/log.h: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __ANDROID__ 3 | #include 4 | #else 5 | #include 6 | #endif 7 | 8 | #ifdef __ANDROID__ 9 | #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__)) 10 | #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__)) 11 | #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", __VA_ARGS__)) 12 | #else 13 | #define LOGI(...) ({fprintf(stdout, "LOGI: ");fprintf(stdout, __VA_ARGS__);fprintf(stdout, "\n");fflush(stdout);}) 14 | #define LOGW(...) ({fprintf(stderr, "LOGW: ");fprintf(stderr, __VA_ARGS__);fprintf(stderr, "\n");fflush(stderr);}) 15 | #define LOGE(...) ({fprintf(stderr, "LOGE: ");fprintf(stderr, __VA_ARGS__);fprintf(stderr, "\n");fflush(stderr);}) 16 | #endif // !ANDROID 17 | -------------------------------------------------------------------------------- /app/src/main/jni/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Matthew Wellings 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #define MAX_LAYERS 8 19 | //#define FORCE_VALIDATION 20 | //#define NO_SURFACE_EXTENSIONS //Usefull for mali devices that report no surface extentions. 21 | 22 | //BEGIN_INCLUDE(all) 23 | #include 24 | //#include 25 | //#include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include "matrix.h" 34 | #include "models.h" 35 | #include "btQuickprof.h" 36 | #include "Simulation.h" 37 | #include "log.h" 38 | 39 | #ifdef __ANDROID__ 40 | #include 41 | #include 42 | #include "stdredirect.h" 43 | #define VK_USE_PLATFORM_ANDROID_KHR 44 | #include "vulkan_wrapper.h" 45 | #else 46 | #include 47 | #include 48 | #define VK_USE_PLATFORM_XCB_KHR 49 | #include 50 | #include 51 | #endif 52 | 53 | void createSecondaryBuffers(struct engine* engine); 54 | int setupUniforms(struct engine* engine); 55 | int setupTraditionalBlendPipeline(struct engine* engine); 56 | int setupBlendPipeline(struct engine* engine); 57 | int setupPeelPipeline(struct engine* engine); 58 | 59 | /** 60 | * Our saved state data. 61 | */ 62 | struct saved_state { 63 | float angle; 64 | int32_t x; 65 | int32_t y; 66 | }; 67 | 68 | /** 69 | * Shared state for our app. 70 | */ 71 | struct engine { 72 | struct android_app* app; 73 | 74 | #ifdef __ANDROID__ 75 | ASensorManager* sensorManager; 76 | const ASensor* accelerometerSensor; 77 | ASensorEventQueue* sensorEventQueue; 78 | #else 79 | xcb_connection_t *xcbConnection; 80 | uint32_t window; 81 | #endif 82 | int animating = 1; 83 | VkInstance vkInstance; 84 | VkDevice vkDevice; 85 | VkPhysicalDevice physicalDevice; 86 | VkPhysicalDeviceProperties deviceProperties; 87 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 88 | VkCommandBuffer setupCommandBuffer; 89 | VkCommandBuffer renderCommandBuffer[2]; 90 | VkCommandBuffer *secondaryCommandBuffers; 91 | VkImage depthImage[2]; 92 | VkImageView depthView[2]; 93 | VkDeviceMemory depthMemory; 94 | VkImage peelImage; 95 | VkImageView peelView; 96 | VkDeviceMemory peelMemory; 97 | uint32_t swapchainImageCount = 0; 98 | VkSwapchainKHR swapchain; 99 | VkImage *swapChainImages; 100 | VkImageView *swapChainViews; 101 | VkFramebuffer *framebuffers; 102 | uint8_t *uniformMappedMemory; 103 | VkSemaphore presentCompleteSemaphore; 104 | VkRenderPass renderPass; 105 | VkPipelineLayout pipelineLayout; 106 | VkPipelineLayout blendPeelPipelineLayout; 107 | VkDescriptorSetLayout *descriptorSetLayouts; 108 | VkDescriptorSet sceneDescriptorSet; 109 | VkDescriptorSet *modelDescriptorSets; 110 | VkDescriptorSet identityModelDescriptorSet; 111 | VkDescriptorSet identitySceneDescriptorSet; 112 | VkDescriptorSet colourInputAttachmentDescriptorSet; 113 | VkDescriptorSet depthInputAttachmentDescriptorSets[2]; 114 | uint32_t modelBufferValsOffset; 115 | VkBuffer vertexBuffer; 116 | VkQueue queue; 117 | bool vulkanSetupOK; 118 | int frame = 0; 119 | int32_t width; 120 | int32_t height; 121 | struct saved_state state; 122 | VkPipeline traditionalBlendPipeline; 123 | VkPipeline peelPipeline; 124 | VkPipeline firstPeelPipeline; 125 | VkPipeline blendPipeline; 126 | btClock *frameRateClock; 127 | Simulation *simulation; 128 | bool splitscreen; 129 | bool rebuildCommadBuffersRequired; 130 | VkVertexInputBindingDescription vertexInputBindingDescription; 131 | VkVertexInputAttributeDescription vertexInputAttributeDescription[2]; 132 | VkShaderModule shdermodules[6]; 133 | int displayLayer; 134 | int layerCount; 135 | int boxCount; 136 | 137 | const int NUM_SAMPLES = 1; 138 | }; 139 | 140 | char* loadAsset(const char* filename, struct engine *pEngine, bool &ok, size_t &size) 141 | { 142 | ok=false; 143 | #ifdef __ANDROID__ 144 | char *buffer = NULL; 145 | AAsset* asset = AAssetManager_open(pEngine->app->activity->assetManager, filename, AASSET_MODE_STREAMING); 146 | if (!asset) { 147 | LOGE("Cannot open asset %s", filename); 148 | return NULL; 149 | } 150 | size = AAsset_getLength(asset); 151 | if (size==0) 152 | { 153 | LOGE("Cannot open asset %s (file empty)", filename); 154 | return NULL; 155 | } 156 | buffer = (char*)malloc(size); 157 | int bytesRead = AAsset_read(asset, buffer, size); 158 | if (bytesRead < 0) { 159 | LOGE("Cannot read asset %s", filename); 160 | return NULL; 161 | } 162 | AAsset_close(asset); 163 | ok=true; 164 | LOGI("File %s read %d bytes.", filename, bytesRead); 165 | return buffer; 166 | #else 167 | char path[100]; 168 | strcpy(path, "../assets/"); 169 | strcat(path, filename); 170 | size_t retval; 171 | void *fileContents; 172 | 173 | FILE *fileHandle = fopen(path, "rb"); 174 | if (!fileHandle) return NULL; 175 | 176 | fseek(fileHandle, 0L, SEEK_END); 177 | size = ftell(fileHandle); 178 | 179 | fseek(fileHandle, 0L, SEEK_SET); 180 | 181 | fileContents = malloc(size); 182 | retval = fread(fileContents, size, 1, fileHandle); 183 | assert(retval == 1); 184 | 185 | ok=true; 186 | return (char*)fileContents; 187 | #endif 188 | } 189 | 190 | 191 | /** 192 | * Initialize an EGL context for the current display. 193 | */ 194 | static int engine_init_display(struct engine* engine) { 195 | // initialize Vulkan 196 | 197 | LOGI ("Initializing Vulkan\n"); 198 | 199 | #ifdef __ANDROID__ 200 | #ifdef FORCE_VALIDATION 201 | //Redirect stdio to android log so vulkan validation layer output is not lost (should use the vulkan extension for this but some drivers don't support it). 202 | //Redirect code from https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/ 203 | /* make stdout line-buffered and stderr unbuffered */ 204 | redirectStdIO(); 205 | { 206 | //Copy vk_layer_settings.txt to a place where it can be found by the Vulkan loader. 207 | bool ok; 208 | size_t size; 209 | char *vk_layer_settings = loadAsset("vk_layer_settings.txt", engine, ok, size); 210 | if (ok) { 211 | char filenamepath[1024] = ""; 212 | char *filename= "/vk_layer_settings.txt"; 213 | strcat(filenamepath, engine->app->activity->internalDataPath); 214 | strcat(filenamepath, filename); 215 | LOGI("filenamepath: %s\n", filenamepath); 216 | FILE *write_ptr; 217 | write_ptr = fopen(filenamepath,"wb"); 218 | fwrite(vk_layer_settings, size, 1, write_ptr); 219 | } 220 | } 221 | 222 | //Set the working directory to where we just put the vk_layer_settings.txt file. 223 | char oldcwd[1024]; 224 | char cwd[1024]; 225 | if (getcwd(oldcwd, sizeof(oldcwd)) != NULL) 226 | LOGI("Current working dir: %s\n", oldcwd); 227 | 228 | LOGI("internalDataPath: %s\n", engine->app->activity->internalDataPath); 229 | 230 | chdir(engine->app->activity->internalDataPath); 231 | 232 | if (getcwd(cwd, sizeof(cwd)) != NULL) 233 | LOGI("Current working dir: %s\n", cwd); 234 | #endif 235 | 236 | //We will put the working directory back to oldcwd later. 237 | //Use glload to load the vulkan loader and setup funcitions. 238 | if (InitVulkan()==0) 239 | { 240 | LOGI("InitVulkan() failed"); 241 | return -1; 242 | } 243 | #endif 244 | 245 | VkResult res; 246 | 247 | uint32_t availableLayerCount =0; 248 | res = vkEnumerateInstanceLayerProperties(&availableLayerCount, NULL); 249 | LOGI("There are %d instance layers avalible\n", availableLayerCount); 250 | VkLayerProperties availableLayers[availableLayerCount]; 251 | res = vkEnumerateInstanceLayerProperties(&availableLayerCount, availableLayers); 252 | for (int i =0; i < availableLayerCount; i++) 253 | { 254 | LOGI("%s: %s\n", availableLayers[i].layerName, availableLayers[i].description); 255 | } 256 | 257 | const char *enabledLayerNames[] = { 258 | //List any layers you want to enable here. 259 | "VK_LAYER_LUNARG_core_validation", 260 | "VK_LAYER_LUNARG_swapchain", 261 | "VK_LAYER_LUNARG_device_limits", 262 | "VK_LAYER_LUNARG_image", 263 | "VK_LAYER_LUNARG_object_tracker", 264 | "VK_LAYER_LUNARG_parameter_validation", 265 | "VK_LAYER_GOOGLE_threading", 266 | "VK_LAYER_GOOGLE_unique_objects" 267 | }; 268 | 269 | const char *enabledInstanceExtensionNames[] = { 270 | VK_KHR_SURFACE_EXTENSION_NAME, 271 | #ifdef __ANDROID__ 272 | VK_KHR_ANDROID_SURFACE_EXTENSION_NAME 273 | #else 274 | VK_KHR_XCB_SURFACE_EXTENSION_NAME 275 | #endif 276 | }; 277 | 278 | VkApplicationInfo app_info; 279 | app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 280 | app_info.pNext = NULL; 281 | app_info.pApplicationName = "My Test App"; 282 | app_info.applicationVersion = 1; 283 | app_info.pEngineName = "My Test App Engine"; 284 | app_info.engineVersion = 1; 285 | app_info.apiVersion = VK_MAKE_VERSION(1, 0, 2); 286 | 287 | //Initialize the VkInstanceCreateInfo structure 288 | VkInstanceCreateInfo inst_info; 289 | inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 290 | inst_info.pNext = NULL; 291 | inst_info.flags = 0; 292 | inst_info.pApplicationInfo = &app_info; 293 | inst_info.enabledExtensionCount = 2; 294 | #ifdef NO_SURFACE_EXTENSIONS 295 | inst_info.enabledExtensionCount = 0; 296 | #endif 297 | inst_info.ppEnabledExtensionNames = enabledInstanceExtensionNames; 298 | #ifdef FORCE_VALIDATION 299 | inst_info.enabledLayerCount = 8; 300 | #else 301 | inst_info.enabledLayerCount = 0; 302 | #endif 303 | inst_info.ppEnabledLayerNames = enabledLayerNames; 304 | 305 | res = vkCreateInstance(&inst_info, NULL, &engine->vkInstance); 306 | if (res == VK_ERROR_INCOMPATIBLE_DRIVER) { 307 | LOGE ("vkCreateInstance returned VK_ERROR_INCOMPATIBLE_DRIVER\n"); 308 | return -1; 309 | } else if (res != VK_SUCCESS) { 310 | LOGE ("vkCreateInstance returned error %d\n", res); 311 | return -1; 312 | } 313 | LOGI ("Vulkan instance created\n"); 314 | 315 | uint32_t deviceBufferSize=0; 316 | res = vkEnumeratePhysicalDevices(engine->vkInstance, &deviceBufferSize, NULL); 317 | LOGI ("GPU Count: %i\n", deviceBufferSize); 318 | if (deviceBufferSize==0) 319 | { 320 | LOGE("No Vulkan device"); 321 | #ifdef __ANDROID__ 322 | ANativeActivity_finish(engine->app->activity); 323 | #endif 324 | return -1; 325 | } 326 | VkPhysicalDevice physicalDevices[deviceBufferSize]; 327 | res = vkEnumeratePhysicalDevices(engine->vkInstance, &deviceBufferSize, physicalDevices); 328 | if (res == VK_ERROR_INITIALIZATION_FAILED) { 329 | LOGE ("vkEnumeratePhysicalDevices returned VK_ERROR_INITIALIZATION_FAILED for GPU 0.\n"); 330 | return -1; 331 | }else if (res != VK_SUCCESS) { 332 | LOGE ("vkEnumeratePhysicalDevices returned error.\n"); 333 | return -1; 334 | } 335 | engine->physicalDevice=physicalDevices[0]; 336 | 337 | VkSurfaceKHR surface; 338 | #ifdef __ANDROID__ 339 | VkAndroidSurfaceCreateInfoKHR instInfo; 340 | instInfo.sType=VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; 341 | instInfo.pNext=NULL; 342 | instInfo.window=engine->app->window; 343 | 344 | res = vkCreateAndroidSurfaceKHR(engine->vkInstance, &instInfo, NULL, &surface); 345 | if (res != VK_SUCCESS) { 346 | LOGE ("vkCreateAndroidSurfaceKHR returned error.\n"); 347 | return -1; 348 | } 349 | #else 350 | VkXcbSurfaceCreateInfoKHR createInfo = {}; 351 | createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; 352 | createInfo.pNext = NULL; 353 | createInfo.connection = engine->xcbConnection; 354 | createInfo.window = engine->window; 355 | res = vkCreateXcbSurfaceKHR(engine->vkInstance, &createInfo, NULL, &surface); 356 | if (res != VK_SUCCESS) { 357 | printf ("vkCreateXcbSurfaceKHR returned error.\n"); 358 | return -1; 359 | } 360 | #endif 361 | 362 | 363 | LOGI ("Vulkan surface created\n"); 364 | 365 | vkGetPhysicalDeviceMemoryProperties(engine->physicalDevice, &engine->physicalDeviceMemoryProperties); 366 | LOGI ("There are %d memory types.\n", engine->physicalDeviceMemoryProperties.memoryTypeCount); 367 | 368 | VkDeviceQueueCreateInfo deviceQueueCreateInfo; 369 | deviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 370 | deviceQueueCreateInfo.flags = 0; 371 | deviceQueueCreateInfo.pNext = NULL; 372 | deviceQueueCreateInfo.queueCount = 1; 373 | float queuePriorities[1] = {1.0}; 374 | deviceQueueCreateInfo.pQueuePriorities = queuePriorities; 375 | 376 | uint32_t queueCount=0; 377 | //We are only using the first physical device: 378 | vkGetPhysicalDeviceQueueFamilyProperties(engine->physicalDevice, &queueCount, NULL); 379 | LOGI ("%i PhysicalDeviceQueueFamily(ies).\n", queueCount); 380 | 381 | VkQueueFamilyProperties queueFamilyProperties[queueCount]; 382 | vkGetPhysicalDeviceQueueFamilyProperties(engine->physicalDevice, &queueCount, queueFamilyProperties); 383 | int found = 0; 384 | unsigned int i = 0; 385 | VkBool32 supportsPresent; 386 | for (; i < queueCount; i++) { 387 | if (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 388 | LOGI ("PhysicalDeviceQueueFamily %i has property VK_QUEUE_GRAPHICS_BIT.\n", i); 389 | vkGetPhysicalDeviceSurfaceSupportKHR(engine->physicalDevice, i, surface, &supportsPresent); 390 | if (supportsPresent) { 391 | deviceQueueCreateInfo.queueFamilyIndex = i; 392 | found = 1; 393 | break; 394 | } 395 | } 396 | } 397 | if (found==0) { 398 | LOGE ("Error: A suitable queue family has not been found.\n"); 399 | return -1; 400 | } 401 | 402 | availableLayerCount =0; 403 | res = vkEnumerateDeviceLayerProperties(engine->physicalDevice, &availableLayerCount, NULL); 404 | LOGI("There are %d device layers avalible\n", availableLayerCount); 405 | availableLayers[availableLayerCount]; 406 | if (availableLayerCount>0) 407 | res = vkEnumerateDeviceLayerProperties(engine->physicalDevice, &availableLayerCount, 408 | availableLayers); 409 | for (int i =0; i < availableLayerCount; i++) 410 | { 411 | LOGI("%s: %s\n", availableLayers[i].layerName, availableLayers[i].description); 412 | } 413 | 414 | const char *enabledDeviceExtensionNames[] = { 415 | VK_KHR_SWAPCHAIN_EXTENSION_NAME 416 | }; 417 | 418 | VkDeviceCreateInfo dci = {}; 419 | dci.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 420 | dci.pNext = NULL; 421 | dci.queueCreateInfoCount = 1; 422 | dci.pQueueCreateInfos = &deviceQueueCreateInfo; 423 | dci.enabledExtensionCount = 1; 424 | #ifdef NO_SURFACE_EXTENSIONS 425 | dci.enabledExtensionCount = 0; 426 | #endif 427 | dci.ppEnabledExtensionNames = enabledDeviceExtensionNames; 428 | dci.pEnabledFeatures = NULL; 429 | #ifdef FORCE_VALIDATION 430 | dci.enabledLayerCount = 8; 431 | #else 432 | dci.enabledLayerCount = 0; 433 | #endif 434 | dci.ppEnabledLayerNames = enabledLayerNames; 435 | 436 | res = vkCreateDevice(engine->physicalDevice, &dci, NULL, &engine->vkDevice); 437 | if (res == VK_ERROR_INITIALIZATION_FAILED) { 438 | LOGE ("vkCreateDevice returned VK_ERROR_INITIALIZATION_FAILED for GPU 0.\n"); 439 | return -1; 440 | }else if (res != VK_SUCCESS) { 441 | LOGE ("vkCreateDevice returned error %d.\n", res); 442 | return -1; 443 | } 444 | LOGI("vkCreateDevice successful"); 445 | 446 | 447 | 448 | //Setup the swapchain 449 | uint32_t formatCount; 450 | vkGetPhysicalDeviceSurfaceFormatsKHR(engine->physicalDevice, surface, &formatCount, NULL); 451 | VkSurfaceFormatKHR formats[formatCount]; 452 | vkGetPhysicalDeviceSurfaceFormatsKHR(engine->physicalDevice, surface, &formatCount, formats); 453 | 454 | uint32_t presentModeCount; 455 | vkGetPhysicalDeviceSurfacePresentModesKHR(engine->physicalDevice, surface, &presentModeCount, NULL); 456 | VkPresentModeKHR presentModes[presentModeCount]; 457 | vkGetPhysicalDeviceSurfacePresentModesKHR(engine->physicalDevice, surface, &presentModeCount, presentModes); 458 | 459 | VkSurfaceCapabilitiesKHR surfCapabilities; 460 | res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(engine->physicalDevice, surface, &surfCapabilities); 461 | 462 | VkExtent2D swapChainExtent; 463 | // width and height are either both -1, or both not -1. 464 | if (surfCapabilities.currentExtent.width == (uint32_t)-1) { 465 | // If the surface size is undefined, the size is set to 466 | // the size of the images requested. 467 | // swapChainExtent.width = 800; 468 | // swapChainExtent.height = 600; 469 | LOGE("Swapchain size is (-1, -1)\n"); 470 | return -1; 471 | } else { 472 | // If the surface size is defined, the swap chain size must match 473 | swapChainExtent = surfCapabilities.currentExtent; 474 | LOGI("Swapchain size is (%d, %d)\n", swapChainExtent.width, swapChainExtent.height); 475 | engine->width=swapChainExtent.width; 476 | engine->height=swapChainExtent.height; 477 | } 478 | 479 | // If the format list includes just one entry of VK_FORMAT_UNDEFINED, 480 | // the surface has no preferred format. Otherwise, at least one 481 | // supported format will be returned. 482 | VkFormat format; 483 | if (formatCount == 1 && formats[0].format == VK_FORMAT_UNDEFINED) { 484 | format = VK_FORMAT_R8G8B8A8_UNORM; 485 | } else { 486 | assert(formatCount >= 1); 487 | format = formats[0].format; 488 | } 489 | LOGI("Using format %d\n", format); 490 | 491 | uint32_t desiredNumberOfSwapChainImages = surfCapabilities.minImageCount + 1; 492 | if ((surfCapabilities.maxImageCount > 0) && 493 | (desiredNumberOfSwapChainImages > surfCapabilities.maxImageCount)) { 494 | // Application must settle for fewer images than desired: 495 | desiredNumberOfSwapChainImages = surfCapabilities.maxImageCount; 496 | } 497 | LOGI("Asking for %d SwapChainImages\n", desiredNumberOfSwapChainImages); 498 | 499 | VkSurfaceTransformFlagBitsKHR preTransform; 500 | if (surfCapabilities.supportedTransforms & 501 | VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { 502 | preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 503 | } else { 504 | preTransform = surfCapabilities.currentTransform; 505 | } 506 | LOGI("Using preTransform %d\n", preTransform); 507 | 508 | VkSwapchainCreateInfoKHR swapCreateInfo; 509 | swapCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 510 | swapCreateInfo.pNext = NULL; 511 | swapCreateInfo.surface = surface; 512 | swapCreateInfo.minImageCount = desiredNumberOfSwapChainImages; 513 | swapCreateInfo.imageFormat = format; 514 | swapCreateInfo.imageExtent=swapChainExtent; 515 | //swapCreateInfo.imageExtent.width = width; //Should match window size 516 | //swapCreateInfo.imageExtent.height = height; 517 | swapCreateInfo.preTransform = preTransform; 518 | swapCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; 519 | swapCreateInfo.imageArrayLayers = 1; 520 | swapCreateInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; 521 | swapCreateInfo.oldSwapchain = VK_NULL_HANDLE; 522 | swapCreateInfo.clipped = VK_TRUE; 523 | swapCreateInfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 524 | swapCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 525 | swapCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 526 | swapCreateInfo.queueFamilyIndexCount = 0; 527 | swapCreateInfo.pQueueFamilyIndices = NULL; 528 | 529 | vkCreateSwapchainKHR(engine->vkDevice, &swapCreateInfo, NULL, &engine->swapchain); 530 | if (res != VK_SUCCESS) { 531 | LOGE ("vkCreateSwapchainKHR returned error.\n"); 532 | return -1; 533 | } 534 | LOGI("Swapchain created"); 535 | 536 | //Setup Command buffers 537 | VkCommandPool commandPool; 538 | VkCommandPoolCreateInfo commandPoolCreateInfo = {}; 539 | commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 540 | commandPoolCreateInfo.pNext = NULL; 541 | commandPoolCreateInfo.queueFamilyIndex = deviceQueueCreateInfo.queueFamilyIndex; 542 | commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; 543 | res = vkCreateCommandPool(engine->vkDevice, &commandPoolCreateInfo, NULL, &commandPool); 544 | if (res != VK_SUCCESS) { 545 | LOGE ("vkCreateCommandPool returned error.\n"); 546 | return -1; 547 | } 548 | 549 | VkCommandBufferAllocateInfo commandBufferAllocateInfo = {}; 550 | commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 551 | commandBufferAllocateInfo.pNext = NULL; 552 | commandBufferAllocateInfo.commandPool = commandPool; 553 | commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 554 | commandBufferAllocateInfo.commandBufferCount = 3; 555 | 556 | VkCommandBuffer commandBuffers[3]; 557 | res = vkAllocateCommandBuffers(engine->vkDevice, &commandBufferAllocateInfo, commandBuffers); 558 | if (res != VK_SUCCESS) { 559 | LOGE ("vkAllocateCommandBuffers returned error.\n"); 560 | return -1; 561 | } 562 | 563 | engine->setupCommandBuffer=commandBuffers[0]; 564 | engine->renderCommandBuffer[0]=commandBuffers[1]; 565 | engine->renderCommandBuffer[1]=commandBuffers[2]; 566 | 567 | LOGI("Command buffers created"); 568 | 569 | VkCommandBufferBeginInfo commandBufferBeginInfo = {}; 570 | commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 571 | commandBufferBeginInfo.pNext = NULL; 572 | commandBufferBeginInfo.flags = 0; 573 | commandBufferBeginInfo.pInheritanceInfo = NULL; 574 | 575 | res = vkBeginCommandBuffer(engine->setupCommandBuffer, &commandBufferBeginInfo); 576 | if (res != VK_SUCCESS) { 577 | LOGE ("vkBeginCommandBuffer returned error.\n"); 578 | return -1; 579 | } 580 | 581 | vkGetDeviceQueue(engine->vkDevice, deviceQueueCreateInfo.queueFamilyIndex, 0, &engine->queue); 582 | 583 | vkGetSwapchainImagesKHR(engine->vkDevice, engine->swapchain, &engine->swapchainImageCount, NULL); 584 | engine->swapChainImages = new VkImage[engine->swapchainImageCount]; 585 | res = vkGetSwapchainImagesKHR(engine->vkDevice, engine->swapchain, &engine->swapchainImageCount, engine->swapChainImages); 586 | if (res != VK_SUCCESS) { 587 | LOGE ("vkCreateSwapchainKHR returned error.\n"); 588 | return -1; 589 | } 590 | printf ("swapchainImageCount %d.\n",engine->swapchainImageCount); 591 | 592 | engine->swapChainViews=(VkImageView*)malloc(sizeof (VkImageView) *engine->swapchainImageCount); 593 | for (uint32_t i = 0; i < engine->swapchainImageCount; i++) { 594 | LOGI ("Setting up swapChainView %d.\n",i); 595 | VkImageViewCreateInfo color_image_view = {}; 596 | color_image_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 597 | color_image_view.pNext = NULL; 598 | color_image_view.format = format; 599 | color_image_view.components.r = VK_COMPONENT_SWIZZLE_R; 600 | color_image_view.components.g = VK_COMPONENT_SWIZZLE_G; 601 | color_image_view.components.b = VK_COMPONENT_SWIZZLE_B; 602 | color_image_view.components.a = VK_COMPONENT_SWIZZLE_A; 603 | color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 604 | color_image_view.subresourceRange.baseMipLevel = 0; 605 | color_image_view.subresourceRange.levelCount = 1; 606 | color_image_view.subresourceRange.baseArrayLayer = 0; 607 | color_image_view.subresourceRange.layerCount = 1; 608 | color_image_view.viewType = VK_IMAGE_VIEW_TYPE_2D; 609 | color_image_view.flags = 0; 610 | color_image_view.image = engine->swapChainImages[i]; 611 | 612 | VkImageMemoryBarrier imageMemoryBarrier; 613 | imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 614 | imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 615 | imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 616 | imageMemoryBarrier.pNext = NULL; 617 | imageMemoryBarrier.image = engine->swapChainImages[i]; 618 | imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 619 | imageMemoryBarrier.subresourceRange.baseMipLevel = 0; 620 | imageMemoryBarrier.subresourceRange.levelCount = 1; 621 | imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; 622 | imageMemoryBarrier.subresourceRange.layerCount = 1; 623 | imageMemoryBarrier.srcQueueFamilyIndex=0; 624 | imageMemoryBarrier.dstQueueFamilyIndex=0; 625 | //imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; 626 | //imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 627 | //imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 628 | imageMemoryBarrier.srcAccessMask = 0; 629 | imageMemoryBarrier.dstAccessMask = 0; 630 | 631 | // Put barrier on top 632 | VkPipelineStageFlags srcStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 633 | VkPipelineStageFlags destStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 634 | 635 | // Put barrier inside setup command buffer 636 | vkCmdPipelineBarrier(engine->setupCommandBuffer, srcStageFlags, destStageFlags, 0, 637 | 0, NULL, 0, NULL, 1, &imageMemoryBarrier); 638 | 639 | res = vkCreateImageView(engine->vkDevice, &color_image_view, NULL, &engine->swapChainViews[i]); 640 | if (res != VK_SUCCESS) { 641 | LOGE ("vkCreateImageView returned error.\n"); 642 | return -1; 643 | } 644 | } 645 | LOGI ("swapchainImageCount %d.\n", engine->swapchainImageCount); 646 | 647 | //Setup the depth buffer: 648 | const VkFormat depth_format = VK_FORMAT_D24_UNORM_S8_UINT; 649 | 650 | VkImageCreateInfo imageCreateInfo; 651 | VkFormatProperties props; 652 | vkGetPhysicalDeviceFormatProperties(engine->physicalDevice, depth_format, &props); 653 | if (! (props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) { 654 | LOGE ("depth_format %d Unsupported.\n", depth_format); 655 | return -1; 656 | } 657 | 658 | imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 659 | imageCreateInfo.pNext = NULL; 660 | imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; 661 | imageCreateInfo.format = depth_format; 662 | imageCreateInfo.extent.width = swapChainExtent.width; 663 | imageCreateInfo.extent.height = swapChainExtent.height; 664 | imageCreateInfo.extent.depth = 1; 665 | imageCreateInfo.mipLevels = 1; 666 | imageCreateInfo.arrayLayers = 1; 667 | imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; 668 | imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; 669 | imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 670 | imageCreateInfo.queueFamilyIndexCount = 0; 671 | imageCreateInfo.pQueueFamilyIndices = NULL; 672 | imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 673 | imageCreateInfo.flags = 0; 674 | 675 | //First try using lazy memory: 676 | imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; 677 | 678 | VkMemoryRequirements memoryRequirements; 679 | //Create images for depth buffers 680 | for (int i=0; i<2; i++) 681 | { 682 | res = vkCreateImage(engine->vkDevice, &imageCreateInfo, NULL, &engine->depthImage[i]); 683 | if (res != VK_SUCCESS) { 684 | LOGE ("vkCreateImage returned error while creating depth buffer.\n"); 685 | return -1; 686 | } 687 | } 688 | 689 | vkGetImageMemoryRequirements(engine->vkDevice, engine->depthImage[0], &memoryRequirements); 690 | 691 | found = false; 692 | uint32_t typeBits = memoryRequirements.memoryTypeBits; 693 | uint32_t typeIndex; 694 | VkFlags requirements_mask = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; 695 | for (typeIndex = 0; typeIndex < engine->physicalDeviceMemoryProperties.memoryTypeCount; typeIndex++) { 696 | if ((typeBits & 1) == 1)//Check last bit; 697 | { 698 | if ((engine->physicalDeviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & requirements_mask) == requirements_mask) 699 | { 700 | found=true; 701 | break; 702 | } 703 | } 704 | typeBits >>= 1; 705 | } 706 | if (found) 707 | LOGI("Using lazily allocated memory & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT for the depth buffers."); 708 | else 709 | { 710 | LOGI("Not using lazily allocated memory for the depth buffers."); 711 | //Either there was no lazily allocated memory or it cannot be used for the depth buffers (because no memory type with VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT was in the memoryTypeBits mask). 712 | imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 713 | for (int i=0; i<2; i++) 714 | vkDestroyImage(engine->vkDevice, engine->depthImage[i], NULL); 715 | //Create new images for depth buffers 716 | for (int i=0; i<2; i++) 717 | { 718 | res = vkCreateImage(engine->vkDevice, &imageCreateInfo, NULL, &engine->depthImage[i]); 719 | if (res != VK_SUCCESS) { 720 | LOGE ("vkCreateImage returned error while creating depth buffer.\n"); 721 | return -1; 722 | } 723 | } 724 | vkGetImageMemoryRequirements(engine->vkDevice, engine->depthImage[0], &memoryRequirements); 725 | typeBits = memoryRequirements.memoryTypeBits; 726 | VkFlags requirements_mask = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 727 | for (typeIndex = 0; typeIndex < engine->physicalDeviceMemoryProperties.memoryTypeCount; typeIndex++) { 728 | if ((typeBits & 1) == 1)//Check last bit; 729 | { 730 | if ((engine->physicalDeviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & requirements_mask) == requirements_mask) 731 | { 732 | found=true; 733 | break; 734 | } 735 | } 736 | typeBits >>= 1; 737 | } 738 | } 739 | 740 | VkDeviceSize imageoffset = 0; 741 | if (memoryRequirements.alignment > 1 && memoryRequirements.size % memoryRequirements.alignment != 0) 742 | imageoffset = memoryRequirements.size + (memoryRequirements.alignment-(memoryRequirements.size % memoryRequirements.alignment)); 743 | else 744 | imageoffset = memoryRequirements.size; 745 | 746 | LOGI("MemoryRequirements.size: %" PRIu64 " memoryRequirements.alignment: %" PRIu64 " imageoffset: %" PRIu64 ".", memoryRequirements.size, memoryRequirements.alignment, imageoffset); 747 | VkMemoryAllocateInfo memAllocInfo; 748 | memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 749 | memAllocInfo.pNext = NULL; 750 | memAllocInfo.allocationSize = imageoffset + memoryRequirements.size; 751 | memAllocInfo.memoryTypeIndex = typeIndex; 752 | 753 | //Allocate memory 754 | res = vkAllocateMemory(engine->vkDevice, &memAllocInfo, NULL, &engine->depthMemory); 755 | if (res != VK_SUCCESS) { 756 | LOGE ("vkAllocateMemory returned error while creating depth buffer.\n"); 757 | return -1; 758 | } 759 | 760 | for (int i=0; i<2; i++) 761 | { 762 | //Bind memory 763 | res = vkBindImageMemory(engine->vkDevice, engine->depthImage[i], engine->depthMemory, imageoffset*i); 764 | if (res != VK_SUCCESS) { 765 | LOGE ("vkBindImageMemory returned error while creating depth buffer. %d\n", res); 766 | return -1; 767 | } 768 | 769 | VkImageMemoryBarrier imageMemoryBarrier; 770 | imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 771 | imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 772 | imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 773 | imageMemoryBarrier.pNext = NULL; 774 | imageMemoryBarrier.image = engine->depthImage[i]; 775 | imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; 776 | imageMemoryBarrier.subresourceRange.baseMipLevel = 0; 777 | imageMemoryBarrier.subresourceRange.levelCount = 1; 778 | imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; 779 | imageMemoryBarrier.subresourceRange.layerCount = 1; 780 | imageMemoryBarrier.srcQueueFamilyIndex=0; 781 | imageMemoryBarrier.dstQueueFamilyIndex=0; 782 | imageMemoryBarrier.srcAccessMask = 0; 783 | imageMemoryBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; 784 | 785 | // Put barrier on top 786 | VkPipelineStageFlags srcStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 787 | VkPipelineStageFlags destStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 788 | 789 | // Put barrier inside setup command buffer 790 | vkCmdPipelineBarrier(engine->setupCommandBuffer, srcStageFlags, destStageFlags, 0, 791 | 0, NULL, 0, NULL, 1, &imageMemoryBarrier); 792 | 793 | 794 | //Create image view 795 | VkImageViewCreateInfo view_info; 796 | view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 797 | view_info.pNext = NULL; 798 | view_info.image = engine->depthImage[i]; 799 | view_info.format = depth_format; 800 | view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; 801 | view_info.components.r = VK_COMPONENT_SWIZZLE_R; 802 | view_info.components.g = VK_COMPONENT_SWIZZLE_G; 803 | view_info.components.b = VK_COMPONENT_SWIZZLE_B; 804 | view_info.components.a = VK_COMPONENT_SWIZZLE_A; 805 | view_info.subresourceRange.baseMipLevel = 0; 806 | view_info.subresourceRange.levelCount = 1; 807 | view_info.subresourceRange.baseArrayLayer = 0; 808 | view_info.subresourceRange.layerCount = 1; 809 | view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 810 | view_info.flags = 0; 811 | 812 | res = vkCreateImageView(engine->vkDevice, &view_info, NULL, &engine->depthView[i]); 813 | if (res != VK_SUCCESS) { 814 | LOGE ("vkCreateImageView returned error while creating depth buffer. %d\n", res); 815 | return -1; 816 | } 817 | } 818 | LOGI("Depth buffers created"); 819 | 820 | //Setup the peel buffer: 821 | { 822 | imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 823 | imageCreateInfo.pNext = NULL; 824 | imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; 825 | imageCreateInfo.format = format; 826 | imageCreateInfo.extent.width = swapChainExtent.width; 827 | imageCreateInfo.extent.height = swapChainExtent.height; 828 | imageCreateInfo.extent.depth = 1; 829 | imageCreateInfo.mipLevels = 1; 830 | imageCreateInfo.arrayLayers = 1; 831 | imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; 832 | imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; 833 | imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 834 | imageCreateInfo.queueFamilyIndexCount = 0; 835 | imageCreateInfo.pQueueFamilyIndices = NULL; 836 | imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 837 | imageCreateInfo.flags = 0; 838 | 839 | //First try using lazy memory: 840 | imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; 841 | 842 | //Create image for peel buffer 843 | res = vkCreateImage(engine->vkDevice, &imageCreateInfo, NULL, &engine->peelImage); 844 | if (res != VK_SUCCESS) { 845 | LOGE ("vkCreateImage returned error while creating peel buffer.\n"); 846 | return -1; 847 | } 848 | 849 | VkMemoryRequirements memoryRequirements; 850 | vkGetImageMemoryRequirements(engine->vkDevice, engine->peelImage, &memoryRequirements); 851 | 852 | found = false; 853 | uint32_t typeBits = memoryRequirements.memoryTypeBits; 854 | uint32_t typeIndex; 855 | VkFlags requirements_mask = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; 856 | for (typeIndex = 0; typeIndex < engine->physicalDeviceMemoryProperties.memoryTypeCount; typeIndex++) { 857 | if ((typeBits & 1) == 1)//Check last bit; 858 | { 859 | if ((engine->physicalDeviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & requirements_mask) == requirements_mask) 860 | { 861 | found=true; 862 | break; 863 | } 864 | } 865 | typeBits >>= 1; 866 | } 867 | if (found) 868 | LOGI("Using lazily allocated memory & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT for the peel buffer."); 869 | else 870 | { 871 | LOGI("Not using lazily allocated memory for the peel buffer."); 872 | imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 873 | 874 | vkDestroyImage(engine->vkDevice, engine->peelImage, NULL); 875 | //Create image for peel buffer 876 | res = vkCreateImage(engine->vkDevice, &imageCreateInfo, NULL, &engine->peelImage); 877 | if (res != VK_SUCCESS) { 878 | LOGE ("vkCreateImage returned error while creating peel buffer.\n"); 879 | return -1; 880 | } 881 | vkGetImageMemoryRequirements(engine->vkDevice, engine->peelImage, &memoryRequirements); 882 | typeBits = memoryRequirements.memoryTypeBits; 883 | VkFlags requirements_mask = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 884 | for (typeIndex = 0; typeIndex < engine->physicalDeviceMemoryProperties.memoryTypeCount; typeIndex++) { 885 | if ((typeBits & 1) == 1)//Check last bit; 886 | { 887 | if ((engine->physicalDeviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & requirements_mask) == requirements_mask) 888 | { 889 | found=true; 890 | break; 891 | } 892 | } 893 | typeBits >>= 1; 894 | } 895 | } 896 | 897 | VkMemoryAllocateInfo memAllocInfo; 898 | memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 899 | memAllocInfo.pNext = NULL; 900 | memAllocInfo.allocationSize = memoryRequirements.size; 901 | memAllocInfo.memoryTypeIndex = typeIndex; 902 | 903 | //Allocate memory 904 | res = vkAllocateMemory(engine->vkDevice, &memAllocInfo, NULL, &engine->peelMemory); 905 | if (res != VK_SUCCESS) { 906 | LOGE ("vkAllocateMemory returned error while creating peel buffer.\n"); 907 | return -1; 908 | } 909 | 910 | //Bind memory 911 | res = vkBindImageMemory(engine->vkDevice, engine->peelImage, engine->peelMemory, 0); 912 | if (res != VK_SUCCESS) { 913 | LOGE ("vkBindImageMemory returned error while creating peel buffer. %d\n", res); 914 | return -1; 915 | } 916 | 917 | VkImageMemoryBarrier imageMemoryBarrier; 918 | imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 919 | imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 920 | imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 921 | imageMemoryBarrier.pNext = NULL; 922 | imageMemoryBarrier.image = engine->peelImage; 923 | imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 924 | imageMemoryBarrier.subresourceRange.baseMipLevel = 0; 925 | imageMemoryBarrier.subresourceRange.levelCount = 1; 926 | imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; 927 | imageMemoryBarrier.subresourceRange.layerCount = 1; 928 | imageMemoryBarrier.srcQueueFamilyIndex = 0; 929 | imageMemoryBarrier.dstQueueFamilyIndex = 0; 930 | imageMemoryBarrier.srcAccessMask = 0; 931 | imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 932 | 933 | // Put barrier on top 934 | VkPipelineStageFlags srcStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 935 | VkPipelineStageFlags destStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 936 | 937 | // Put barrier inside setup command buffer 938 | vkCmdPipelineBarrier(engine->setupCommandBuffer, srcStageFlags, destStageFlags, 0, 939 | 0, NULL, 0, NULL, 1, &imageMemoryBarrier); 940 | 941 | 942 | //Create image view 943 | VkImageViewCreateInfo view_info; 944 | view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 945 | view_info.pNext = NULL; 946 | view_info.image = engine->peelImage; 947 | view_info.format = format; 948 | view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 949 | view_info.components.r = VK_COMPONENT_SWIZZLE_R; 950 | view_info.components.g = VK_COMPONENT_SWIZZLE_G; 951 | view_info.components.b = VK_COMPONENT_SWIZZLE_B; 952 | view_info.components.a = VK_COMPONENT_SWIZZLE_A; 953 | view_info.subresourceRange.baseMipLevel = 0; 954 | view_info.subresourceRange.levelCount = 1; 955 | view_info.subresourceRange.baseArrayLayer = 0; 956 | view_info.subresourceRange.layerCount = 1; 957 | view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 958 | view_info.flags = 0; 959 | 960 | res = vkCreateImageView(engine->vkDevice, &view_info, NULL, &engine->peelView); 961 | if (res != VK_SUCCESS) { 962 | LOGE ("vkCreateImageView returned error while creating peel buffer. %d\n", res); 963 | return -1; 964 | } 965 | LOGI("Peel image created"); 966 | } 967 | res = vkEndCommandBuffer(engine->setupCommandBuffer); 968 | if (res != VK_SUCCESS) { 969 | LOGE ("vkEndCommandBuffer returned error %d.\n", res); 970 | return -1; 971 | } 972 | //Submit the setup command buffer 973 | VkSubmitInfo submitInfo[1]; 974 | submitInfo[0].pNext = NULL; 975 | submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 976 | submitInfo[0].waitSemaphoreCount = 0; 977 | submitInfo[0].pWaitSemaphores = NULL; 978 | submitInfo[0].pWaitDstStageMask = NULL; 979 | submitInfo[0].commandBufferCount = 1; 980 | submitInfo[0].pCommandBuffers = &engine->setupCommandBuffer; 981 | submitInfo[0].signalSemaphoreCount = 0; 982 | submitInfo[0].pSignalSemaphores = NULL; 983 | 984 | res = vkQueueSubmit(engine->queue, 1, submitInfo, VK_NULL_HANDLE); 985 | if (res != VK_SUCCESS) { 986 | LOGE ("vkQueueSubmit returned error %d.\n", res); 987 | return -1; 988 | } 989 | 990 | res = vkQueueWaitIdle(engine->queue); 991 | if (res != VK_SUCCESS) { 992 | LOGE ("vkQueueWaitIdle returned error %d.\n", res); 993 | return -1; 994 | } 995 | 996 | engine->secondaryCommandBuffers=new VkCommandBuffer[engine->swapchainImageCount*(MAX_LAYERS*2+1)]; 997 | commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; 998 | commandBufferAllocateInfo.commandBufferCount = engine->swapchainImageCount*(MAX_LAYERS*2+1); 999 | 1000 | LOGI ("Creating %d secondary command buffers.\n", engine->swapchainImageCount*(MAX_LAYERS*2+1)); 1001 | res = vkAllocateCommandBuffers(engine->vkDevice, &commandBufferAllocateInfo, engine->secondaryCommandBuffers); 1002 | if (res != VK_SUCCESS) { 1003 | LOGE ("vkAllocateCommandBuffers returned error.\n"); 1004 | return -1; 1005 | } 1006 | 1007 | //Setup the renderpass: 1008 | VkAttachmentDescription attachments[4]; 1009 | attachments[0].format = format; 1010 | attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; 1011 | attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 1012 | attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; 1013 | attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1014 | attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1015 | attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1016 | attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1017 | attachments[0].flags = 0; 1018 | attachments[1].format = depth_format; 1019 | attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; 1020 | attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1021 | attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1022 | attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1023 | attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1024 | attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 1025 | attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 1026 | attachments[1].flags = 0; 1027 | attachments[2].format = format; 1028 | attachments[2].samples = VK_SAMPLE_COUNT_1_BIT; 1029 | attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1030 | attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1031 | attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1032 | attachments[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1033 | attachments[2].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1034 | attachments[2].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1035 | attachments[2].flags = 0; 1036 | attachments[3].format = depth_format; 1037 | attachments[3].samples = VK_SAMPLE_COUNT_1_BIT; 1038 | attachments[3].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1039 | attachments[3].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1040 | attachments[3].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1041 | attachments[3].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1042 | attachments[3].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 1043 | attachments[3].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 1044 | attachments[3].flags = 0; 1045 | 1046 | VkAttachmentReference color_reference; 1047 | color_reference.attachment = 0; 1048 | color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1049 | 1050 | VkAttachmentReference depth_attachment_reference[2]; 1051 | depth_attachment_reference[0].attachment = 1; 1052 | depth_attachment_reference[0].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 1053 | depth_attachment_reference[1].attachment = 3; 1054 | depth_attachment_reference[1].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 1055 | VkAttachmentReference depth_inputattachment_reference[2]; 1056 | depth_inputattachment_reference[0].attachment = 1; 1057 | depth_inputattachment_reference[0].layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 1058 | depth_inputattachment_reference[1].attachment = 3; 1059 | depth_inputattachment_reference[1].layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 1060 | 1061 | VkAttachmentReference peelcolor_attachment_reference; 1062 | peelcolor_attachment_reference.attachment = 2; 1063 | peelcolor_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1064 | VkAttachmentReference peelcolor_inputattachment_reference; 1065 | peelcolor_inputattachment_reference.attachment = 2; 1066 | peelcolor_inputattachment_reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 1067 | 1068 | uint32_t colour_attachment = 0; 1069 | uint32_t depth_attachment[2] = {1, 3}; 1070 | uint32_t peel_attachment = 2; 1071 | 1072 | uint subpassCount = MAX_LAYERS*2+1; 1073 | uint subpassDependencyCount=(subpassCount*(subpassCount-1))/2; 1074 | VkSubpassDependency subpassDependencies[subpassDependencyCount]; 1075 | VkSubpassDescription subpasses[subpassCount]; 1076 | subpasses[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 1077 | subpasses[0].flags = 0; 1078 | subpasses[0].inputAttachmentCount = 0; 1079 | subpasses[0].pInputAttachments = NULL; 1080 | subpasses[0].colorAttachmentCount = 1; 1081 | subpasses[0].pColorAttachments = &color_reference; 1082 | subpasses[0].pResolveAttachments = NULL; 1083 | subpasses[0].pDepthStencilAttachment = &depth_attachment_reference[0]; 1084 | subpasses[0].preserveAttachmentCount = 2; 1085 | uint32_t PreserveAttachments[2] = {peel_attachment, depth_attachment[1]}; 1086 | subpasses[0].pPreserveAttachments = PreserveAttachments; 1087 | 1088 | for (int i =0; ivkDevice, &rp_info, NULL, &engine->renderPass); 1154 | if (res != VK_SUCCESS) { 1155 | LOGE ("vkCreateRenderPass returned error. %d\n", res); 1156 | return -1; 1157 | } 1158 | 1159 | LOGI("Renderpass created"); 1160 | 1161 | vkGetPhysicalDeviceProperties(engine->physicalDevice, &engine->deviceProperties); 1162 | if (res != VK_SUCCESS) { 1163 | printf ("vkGetPhysicalDeviceProperties returned error %d.\n", res); 1164 | return -1; 1165 | } 1166 | 1167 | LOGI("vkGetPhysicalDeviceProperties"); 1168 | 1169 | setupUniforms(engine); 1170 | 1171 | //Now use the descriptor layout to create a pipeline layout 1172 | VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo; 1173 | pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 1174 | pPipelineLayoutCreateInfo.flags = 0; 1175 | pPipelineLayoutCreateInfo.pNext = NULL; 1176 | pPipelineLayoutCreateInfo.pushConstantRangeCount = 0; 1177 | pPipelineLayoutCreateInfo.pPushConstantRanges = NULL; 1178 | pPipelineLayoutCreateInfo.setLayoutCount = 2; 1179 | pPipelineLayoutCreateInfo.pSetLayouts = engine->descriptorSetLayouts; 1180 | 1181 | res = vkCreatePipelineLayout(engine->vkDevice, &pPipelineLayoutCreateInfo, NULL, &engine->pipelineLayout); 1182 | if (res != VK_SUCCESS) { 1183 | LOGE ("vkCreatePipelineLayout returned error.\n"); 1184 | return -1; 1185 | } 1186 | 1187 | pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 1188 | pPipelineLayoutCreateInfo.pNext = NULL; 1189 | pPipelineLayoutCreateInfo.pushConstantRangeCount = 0; 1190 | pPipelineLayoutCreateInfo.pPushConstantRanges = NULL; 1191 | pPipelineLayoutCreateInfo.setLayoutCount = 3; 1192 | pPipelineLayoutCreateInfo.pSetLayouts = engine->descriptorSetLayouts; 1193 | 1194 | res = vkCreatePipelineLayout(engine->vkDevice, &pPipelineLayoutCreateInfo, NULL, &engine->blendPeelPipelineLayout); 1195 | if (res != VK_SUCCESS) { 1196 | LOGE ("vkCreatePipelineLayout returned error.\n"); 1197 | return -1; 1198 | } 1199 | 1200 | LOGI("Pipeline layout created"); 1201 | 1202 | //load shaders 1203 | 1204 | VkShaderModuleCreateInfo moduleCreateInfo; 1205 | moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 1206 | moduleCreateInfo.pNext = NULL; 1207 | moduleCreateInfo.flags = 0; 1208 | bool ok; 1209 | { 1210 | size_t vertexShaderSize=0; 1211 | char *vertexShader = loadAsset("shaders/trad.vert.spv", engine, ok, vertexShaderSize); 1212 | size_t fragmentShaderSize=0; 1213 | char *fragmentShader = loadAsset("shaders/trad.frag.spv", engine, ok, fragmentShaderSize); 1214 | if (vertexShaderSize==0 || fragmentShaderSize==0){ 1215 | LOGE ("Colud not load shader file.\n"); 1216 | return -1; 1217 | } 1218 | 1219 | 1220 | moduleCreateInfo.codeSize = vertexShaderSize; 1221 | moduleCreateInfo.pCode = (uint32_t*)vertexShader; //This may not work with big-endian systems. 1222 | res = vkCreateShaderModule(engine->vkDevice, &moduleCreateInfo, NULL, &engine->shdermodules[0]); 1223 | if (res != VK_SUCCESS) { 1224 | LOGE ("vkCreateShaderModule returned error %d.\n", res); 1225 | return -1; 1226 | } 1227 | 1228 | moduleCreateInfo.codeSize = fragmentShaderSize; 1229 | moduleCreateInfo.pCode = (uint32_t*)fragmentShader; 1230 | res = vkCreateShaderModule(engine->vkDevice, &moduleCreateInfo, NULL, &engine->shdermodules[1]); 1231 | if (res != VK_SUCCESS) { 1232 | LOGE ("vkCreateShaderModule returned error %d.\n", res); 1233 | return -1; 1234 | } 1235 | } 1236 | { 1237 | size_t vertexShaderSize=0; 1238 | char *vertexShader = loadAsset("shaders/peel.vert.spv", engine, ok, vertexShaderSize); 1239 | size_t fragmentShaderSize=0; 1240 | char *fragmentShader = loadAsset("shaders/peel.frag.spv", engine, ok, fragmentShaderSize); 1241 | if (vertexShaderSize==0 || fragmentShaderSize==0){ 1242 | LOGE ("Colud not load shader file.\n"); 1243 | return -1; 1244 | } 1245 | 1246 | moduleCreateInfo.codeSize = vertexShaderSize; 1247 | moduleCreateInfo.pCode = (uint32_t*)vertexShader; //This may not work with big-endian systems. 1248 | res = vkCreateShaderModule(engine->vkDevice, &moduleCreateInfo, NULL, &engine->shdermodules[2]); 1249 | if (res != VK_SUCCESS) { 1250 | LOGE ("vkCreateShaderModule returned error %d.\n", res); 1251 | return -1; 1252 | } 1253 | 1254 | moduleCreateInfo.codeSize = fragmentShaderSize; 1255 | moduleCreateInfo.pCode = (uint32_t*)fragmentShader; 1256 | res = vkCreateShaderModule(engine->vkDevice, &moduleCreateInfo, NULL, &engine->shdermodules[3]); 1257 | if (res != VK_SUCCESS) { 1258 | LOGE ("vkCreateShaderModule returned error %d.\n", res); 1259 | return -1; 1260 | } 1261 | } 1262 | { 1263 | size_t vertexShaderSize=0; 1264 | char *vertexShader = loadAsset("shaders/blend.vert.spv", engine, ok, vertexShaderSize); 1265 | size_t fragmentShaderSize=0; 1266 | char *fragmentShader = loadAsset("shaders/blend.frag.spv", engine, ok, fragmentShaderSize); 1267 | if (vertexShaderSize==0 || fragmentShaderSize==0){ 1268 | LOGE ("Colud not load shader file.\n"); 1269 | return -1; 1270 | } 1271 | 1272 | moduleCreateInfo.codeSize = vertexShaderSize; 1273 | moduleCreateInfo.pCode = (uint32_t*)vertexShader; //This may not work with big-endian systems. 1274 | res = vkCreateShaderModule(engine->vkDevice, &moduleCreateInfo, NULL, &engine->shdermodules[4]); 1275 | if (res != VK_SUCCESS) { 1276 | LOGE ("vkCreateShaderModule returned error %d.\n", res); 1277 | return -1; 1278 | } 1279 | 1280 | moduleCreateInfo.codeSize = fragmentShaderSize; 1281 | moduleCreateInfo.pCode = (uint32_t*)fragmentShader; 1282 | res = vkCreateShaderModule(engine->vkDevice, &moduleCreateInfo, NULL, &engine->shdermodules[5]); 1283 | if (res != VK_SUCCESS) { 1284 | LOGE ("vkCreateShaderModule returned error %d.\n", res); 1285 | return -1; 1286 | } 1287 | } 1288 | LOGI("Shaders Loaded"); 1289 | 1290 | //Create the framebuffers 1291 | engine->framebuffers=new VkFramebuffer[engine->swapchainImageCount]; 1292 | 1293 | for (i = 0; i < engine->swapchainImageCount; i++) { 1294 | 1295 | VkImageView imageViewAttachments[4]; 1296 | 1297 | //Attach the correct swapchain colourbuffer 1298 | imageViewAttachments[0] = engine->swapChainViews[i]; 1299 | //We only have one depth buffer which we attach to all framebuffers 1300 | imageViewAttachments[1] = engine->depthView[0]; 1301 | imageViewAttachments[2] = engine->peelView; 1302 | imageViewAttachments[3] = engine->depthView[1]; 1303 | 1304 | VkFramebufferCreateInfo fb_info; 1305 | fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 1306 | fb_info.pNext = NULL; 1307 | fb_info.renderPass = engine->renderPass; 1308 | fb_info.attachmentCount = 4; 1309 | fb_info.pAttachments = imageViewAttachments; 1310 | fb_info.width = swapChainExtent.width; 1311 | fb_info.height = swapChainExtent.height; 1312 | fb_info.layers = 1; 1313 | fb_info.flags = 0; 1314 | 1315 | res = vkCreateFramebuffer(engine->vkDevice, &fb_info, NULL, &engine->framebuffers[i]); 1316 | if (res != VK_SUCCESS) { 1317 | LOGE ("vkCreateFramebuffer returned error %d.\n", res); 1318 | return -1; 1319 | } 1320 | } 1321 | 1322 | LOGI("%d framebuffers created", engine->swapchainImageCount); 1323 | 1324 | //Create Vertex buffers: 1325 | VkBufferCreateInfo vertexBufferCreateInfo; 1326 | vertexBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 1327 | vertexBufferCreateInfo.pNext = NULL; 1328 | vertexBufferCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; 1329 | vertexBufferCreateInfo.size = sizeof(vertexData); 1330 | vertexBufferCreateInfo.queueFamilyIndexCount = 0; 1331 | vertexBufferCreateInfo.pQueueFamilyIndices = NULL; 1332 | vertexBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 1333 | vertexBufferCreateInfo.flags = 0; 1334 | 1335 | res = vkCreateBuffer(engine->vkDevice, &vertexBufferCreateInfo, NULL, &engine->vertexBuffer); 1336 | if (res != VK_SUCCESS) { 1337 | LOGE ("vkCreateBuffer returned error %d.\n", res); 1338 | return -1; 1339 | } 1340 | 1341 | found = 0; 1342 | vkGetBufferMemoryRequirements(engine->vkDevice, engine->vertexBuffer, &memoryRequirements); 1343 | typeBits = memoryRequirements.memoryTypeBits; 1344 | requirements_mask = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 1345 | for (typeIndex = 0; typeIndex < engine->physicalDeviceMemoryProperties.memoryTypeCount; typeIndex++) { 1346 | if ((typeBits & 1) == 1)//Check last bit; 1347 | { 1348 | if ((engine->physicalDeviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & requirements_mask) == requirements_mask) 1349 | { 1350 | found=1; 1351 | break; 1352 | } 1353 | } 1354 | typeBits >>= 1; 1355 | } 1356 | 1357 | if (!found) 1358 | { 1359 | LOGE ("Did not find a suitible memory type.\n"); 1360 | return -1; 1361 | }else 1362 | LOGI ("Using memory type %d.\n", typeIndex); 1363 | 1364 | memAllocInfo.pNext = NULL; 1365 | memAllocInfo.allocationSize = memoryRequirements.size; 1366 | memAllocInfo.memoryTypeIndex = typeIndex; 1367 | 1368 | VkDeviceMemory vertexMemory; 1369 | res = vkAllocateMemory(engine->vkDevice, &memAllocInfo, NULL, &vertexMemory); 1370 | if (res != VK_SUCCESS) { 1371 | LOGE ("vkAllocateMemory returned error %d.\n", res); 1372 | return -1; 1373 | } 1374 | 1375 | uint8_t *vertexMappedMemory; 1376 | res = vkMapMemory(engine->vkDevice, vertexMemory, 0, memoryRequirements.size, 0, (void **)&vertexMappedMemory); 1377 | if (res != VK_SUCCESS) { 1378 | LOGE ("vkMapMemory returned error %d.\n", res); 1379 | return -1; 1380 | } 1381 | 1382 | memcpy(vertexMappedMemory, vertexData, sizeof(vertexData)); 1383 | 1384 | vkUnmapMemory(engine->vkDevice, vertexMemory); 1385 | 1386 | res = vkBindBufferMemory(engine->vkDevice, engine->vertexBuffer, vertexMemory, 0); 1387 | if (res != VK_SUCCESS) { 1388 | LOGE ("vkBindBufferMemory returned error %d.\n", res); 1389 | return -1; 1390 | } 1391 | engine->vertexInputBindingDescription.binding = 0; 1392 | engine->vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 1393 | engine->vertexInputBindingDescription.stride = sizeof(vertexData[0]); 1394 | 1395 | engine->vertexInputAttributeDescription[0].binding = 0; 1396 | engine->vertexInputAttributeDescription[0].location = 0; 1397 | engine->vertexInputAttributeDescription[0].format = VK_FORMAT_R32G32B32A32_SFLOAT; 1398 | engine->vertexInputAttributeDescription[0].offset = 0; 1399 | engine->vertexInputAttributeDescription[1].binding = 0; 1400 | engine->vertexInputAttributeDescription[1].location = 1; 1401 | engine->vertexInputAttributeDescription[1].format = VK_FORMAT_R32G32B32A32_SFLOAT; 1402 | engine->vertexInputAttributeDescription[1].offset = 16; 1403 | 1404 | setupTraditionalBlendPipeline(engine); 1405 | setupPeelPipeline(engine); 1406 | setupBlendPipeline(engine); 1407 | 1408 | VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo; 1409 | presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 1410 | presentCompleteSemaphoreCreateInfo.pNext = NULL; 1411 | presentCompleteSemaphoreCreateInfo.flags = 0; 1412 | 1413 | res = vkCreateSemaphore(engine->vkDevice, &presentCompleteSemaphoreCreateInfo, NULL, &engine->presentCompleteSemaphore); 1414 | if (res != VK_SUCCESS) { 1415 | printf ("vkCreateSemaphore returned error.\n"); 1416 | return -1; 1417 | } 1418 | 1419 | createSecondaryBuffers(engine); 1420 | 1421 | engine->vulkanSetupOK=true; 1422 | 1423 | #ifdef __ANDROID__ 1424 | #ifdef FORCE_VALIDATION 1425 | LOGI("Restoring working directory"); 1426 | chdir(oldcwd); 1427 | 1428 | if (getcwd(cwd, sizeof(cwd)) != NULL) 1429 | LOGI("Current working dir: %s\n", cwd); 1430 | #endif 1431 | #endif 1432 | 1433 | LOGI ("Vulkan setup complete"); 1434 | 1435 | return 0; 1436 | } 1437 | 1438 | int setupTraditionalBlendPipeline(struct engine* engine) 1439 | { 1440 | 1441 | LOGI("Setting up trad blend pipeline"); 1442 | 1443 | VkRect2D scissor; 1444 | scissor.extent.width = engine->width / 2; 1445 | scissor.extent.height = engine->height; 1446 | scissor.offset.x = 0; 1447 | scissor.offset.y = 0; 1448 | 1449 | VkViewport viewport; 1450 | viewport.height = (float)engine->height; 1451 | viewport.width = (float)engine->width; 1452 | viewport.minDepth = (float)0.0f; 1453 | viewport.maxDepth = (float)1.0f; 1454 | viewport.x = 0; 1455 | viewport.y = 0; 1456 | 1457 | //Create a pipeline object 1458 | VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE]; 1459 | VkPipelineDynamicStateCreateInfo dynamicState; 1460 | //No dynamic state: 1461 | memset(dynamicStateEnables, 0, sizeof dynamicStateEnables); 1462 | dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 1463 | dynamicState.flags = 0; 1464 | dynamicState.pNext = NULL; 1465 | dynamicState.pDynamicStates = dynamicStateEnables; 1466 | dynamicState.dynamicStateCount = 0; 1467 | 1468 | VkPipelineVertexInputStateCreateInfo vi; 1469 | vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 1470 | vi.pNext = NULL; 1471 | vi.flags = 0; 1472 | vi.vertexBindingDescriptionCount = 1; 1473 | vi.pVertexBindingDescriptions = &engine->vertexInputBindingDescription; 1474 | vi.vertexAttributeDescriptionCount = 2; 1475 | vi.pVertexAttributeDescriptions = engine->vertexInputAttributeDescription; 1476 | 1477 | VkPipelineInputAssemblyStateCreateInfo ia; 1478 | ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 1479 | ia.pNext = NULL; 1480 | ia.flags = 0; 1481 | ia.primitiveRestartEnable = VK_FALSE; 1482 | ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1483 | 1484 | VkPipelineRasterizationStateCreateInfo rs; 1485 | rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 1486 | rs.pNext = NULL; 1487 | rs.flags = 0; 1488 | rs.polygonMode = VK_POLYGON_MODE_FILL; 1489 | rs.cullMode = VK_CULL_MODE_NONE; 1490 | rs.frontFace = VK_FRONT_FACE_CLOCKWISE; 1491 | rs.depthClampEnable = VK_TRUE; 1492 | rs.rasterizerDiscardEnable = VK_FALSE; 1493 | rs.depthBiasEnable = VK_FALSE; 1494 | rs.depthBiasConstantFactor = 0; 1495 | rs.depthBiasClamp = 0; 1496 | rs.depthBiasSlopeFactor = 0; 1497 | rs.lineWidth = 1; 1498 | 1499 | VkPipelineColorBlendStateCreateInfo cb; 1500 | cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 1501 | cb.flags = 0; 1502 | cb.pNext = NULL; 1503 | VkPipelineColorBlendAttachmentState att_state[1]; 1504 | att_state[0].colorWriteMask = 0xf; 1505 | att_state[0].blendEnable = VK_TRUE; 1506 | att_state[0].alphaBlendOp = VK_BLEND_OP_ADD; 1507 | att_state[0].colorBlendOp = VK_BLEND_OP_ADD; 1508 | att_state[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 1509 | att_state[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 1510 | att_state[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 1511 | att_state[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 1512 | cb.attachmentCount = 1; 1513 | cb.pAttachments = att_state; 1514 | cb.logicOpEnable = VK_FALSE; 1515 | cb.logicOp = VK_LOGIC_OP_NO_OP; 1516 | cb.blendConstants[0] = 1.0f; 1517 | cb.blendConstants[1] = 1.0f; 1518 | cb.blendConstants[2] = 1.0f; 1519 | cb.blendConstants[3] = 1.0f; 1520 | 1521 | VkPipelineViewportStateCreateInfo vp = {}; 1522 | vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 1523 | vp.pNext = NULL; 1524 | vp.flags = 0; 1525 | vp.viewportCount = 1; 1526 | // dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT; 1527 | vp.pViewports = &viewport; 1528 | vp.scissorCount = 1; 1529 | // dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR; 1530 | vp.pScissors = &scissor; 1531 | 1532 | VkPipelineDepthStencilStateCreateInfo ds; 1533 | ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 1534 | ds.pNext = NULL; 1535 | ds.flags = 0; 1536 | ds.depthTestEnable = VK_FALSE; 1537 | ds.depthWriteEnable = VK_TRUE; 1538 | ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 1539 | ds.depthBoundsTestEnable = VK_FALSE; 1540 | ds.stencilTestEnable = VK_FALSE; 1541 | ds.back.failOp = VK_STENCIL_OP_KEEP; 1542 | ds.back.passOp = VK_STENCIL_OP_KEEP; 1543 | ds.back.compareOp = VK_COMPARE_OP_ALWAYS; 1544 | ds.back.compareMask = 0; 1545 | ds.back.reference = 0; 1546 | ds.back.depthFailOp = VK_STENCIL_OP_KEEP; 1547 | ds.back.writeMask = 0; 1548 | ds.minDepthBounds = 0; 1549 | ds.maxDepthBounds = 0; 1550 | ds.stencilTestEnable = VK_FALSE; 1551 | ds.front = ds.back; 1552 | 1553 | VkPipelineMultisampleStateCreateInfo ms; 1554 | ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 1555 | ms.pNext = NULL; 1556 | ms.flags = 0; 1557 | ms.pSampleMask = NULL; 1558 | ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 1559 | ms.sampleShadingEnable = VK_FALSE; 1560 | ms.alphaToCoverageEnable = VK_FALSE; 1561 | ms.alphaToOneEnable = VK_FALSE; 1562 | ms.minSampleShading = 0.0; 1563 | 1564 | VkPipelineShaderStageCreateInfo shaderStages[2]; 1565 | shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1566 | shaderStages[0].pNext = NULL; 1567 | shaderStages[0].pSpecializationInfo = NULL; 1568 | shaderStages[0].flags = 0; 1569 | shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 1570 | shaderStages[0].pName = "main"; 1571 | shaderStages[0].module = engine->shdermodules[0]; 1572 | shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1573 | shaderStages[1].pNext = NULL; 1574 | shaderStages[1].pSpecializationInfo = NULL; 1575 | shaderStages[1].flags = 0; 1576 | shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 1577 | shaderStages[1].pName = "main"; 1578 | shaderStages[1].module = engine->shdermodules[1]; 1579 | 1580 | VkGraphicsPipelineCreateInfo pipelineInfo; 1581 | pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 1582 | pipelineInfo.pNext = NULL; 1583 | pipelineInfo.layout = engine->pipelineLayout; 1584 | pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; 1585 | pipelineInfo.basePipelineIndex = 0; 1586 | pipelineInfo.flags = 0; 1587 | pipelineInfo.pVertexInputState = &vi; 1588 | pipelineInfo.pInputAssemblyState = &ia; 1589 | pipelineInfo.pRasterizationState = &rs; 1590 | pipelineInfo.pColorBlendState = &cb; 1591 | pipelineInfo.pTessellationState = NULL; 1592 | pipelineInfo.pMultisampleState = &ms; 1593 | pipelineInfo.pDynamicState = &dynamicState; 1594 | if (dynamicState.dynamicStateCount==0) 1595 | pipelineInfo.pDynamicState=NULL; 1596 | pipelineInfo.pViewportState = &vp; 1597 | pipelineInfo.pDepthStencilState = &ds; 1598 | pipelineInfo.pStages = shaderStages; 1599 | pipelineInfo.stageCount = 2; 1600 | pipelineInfo.renderPass = engine->renderPass; 1601 | pipelineInfo.subpass = 0; 1602 | 1603 | VkResult res; 1604 | res = vkCreateGraphicsPipelines(engine->vkDevice, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &engine->traditionalBlendPipeline); 1605 | if (res != VK_SUCCESS) { 1606 | LOGE ("vkCreateGraphicsPipelines returned error %d.\n", res); 1607 | return -1; 1608 | } 1609 | return 0; 1610 | } 1611 | 1612 | 1613 | int setupPeelPipeline(struct engine* engine) { 1614 | 1615 | LOGI("Setting up peel pipeline"); 1616 | 1617 | VkViewport viewport; 1618 | viewport.height = (float) engine->height; 1619 | viewport.width = (float) engine->width; 1620 | viewport.minDepth = (float) 0.0f; 1621 | viewport.maxDepth = (float) 1.0f; 1622 | viewport.x = 0; 1623 | viewport.y = 0; 1624 | 1625 | //Create a pipeline object 1626 | VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE]; 1627 | VkPipelineDynamicStateCreateInfo dynamicState; 1628 | //No dynamic state: 1629 | memset(dynamicStateEnables, 0, sizeof dynamicStateEnables); 1630 | dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 1631 | dynamicState.flags = 0; 1632 | dynamicState.pNext = NULL; 1633 | dynamicState.pDynamicStates = dynamicStateEnables; 1634 | dynamicState.dynamicStateCount = 0; 1635 | 1636 | VkPipelineVertexInputStateCreateInfo vi; 1637 | vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 1638 | vi.pNext = NULL; 1639 | vi.flags = 0; 1640 | vi.vertexBindingDescriptionCount = 1; 1641 | vi.pVertexBindingDescriptions = &engine->vertexInputBindingDescription; 1642 | vi.vertexAttributeDescriptionCount = 2; 1643 | vi.pVertexAttributeDescriptions = engine->vertexInputAttributeDescription; 1644 | 1645 | VkPipelineInputAssemblyStateCreateInfo ia; 1646 | ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 1647 | ia.pNext = NULL; 1648 | ia.flags = 0; 1649 | ia.primitiveRestartEnable = VK_FALSE; 1650 | ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1651 | 1652 | VkPipelineRasterizationStateCreateInfo rs; 1653 | rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 1654 | rs.pNext = NULL; 1655 | rs.flags = 0; 1656 | rs.polygonMode = VK_POLYGON_MODE_FILL; 1657 | rs.cullMode = VK_CULL_MODE_NONE; 1658 | rs.frontFace = VK_FRONT_FACE_CLOCKWISE; 1659 | rs.depthClampEnable = VK_TRUE; 1660 | rs.rasterizerDiscardEnable = VK_FALSE; 1661 | rs.depthBiasEnable = VK_FALSE; 1662 | rs.depthBiasConstantFactor = 0; 1663 | rs.depthBiasClamp = 0; 1664 | rs.depthBiasSlopeFactor = 0; 1665 | rs.lineWidth = 1; 1666 | 1667 | VkPipelineColorBlendStateCreateInfo cb; 1668 | cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 1669 | cb.flags = 0; 1670 | cb.pNext = NULL; 1671 | VkPipelineColorBlendAttachmentState att_state[1] = {}; 1672 | att_state[0].colorWriteMask = 0xf; 1673 | att_state[0].blendEnable = VK_FALSE; 1674 | cb.attachmentCount = 1; 1675 | cb.pAttachments = att_state; 1676 | cb.logicOpEnable = VK_FALSE; 1677 | cb.logicOp = VK_LOGIC_OP_NO_OP; 1678 | cb.blendConstants[0] = 1.0f; 1679 | cb.blendConstants[1] = 1.0f; 1680 | cb.blendConstants[2] = 1.0f; 1681 | cb.blendConstants[3] = 1.0f; 1682 | 1683 | VkPipelineViewportStateCreateInfo vp = {}; 1684 | vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 1685 | vp.pNext = NULL; 1686 | vp.flags = 0; 1687 | vp.viewportCount = 1; 1688 | // dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT; 1689 | vp.pViewports = &viewport; 1690 | vp.scissorCount = 1; 1691 | dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR; 1692 | // vp.pScissors = &scissor; 1693 | 1694 | VkPipelineDepthStencilStateCreateInfo ds; 1695 | ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 1696 | ds.pNext = NULL; 1697 | ds.flags = 0; 1698 | ds.depthTestEnable = VK_TRUE; 1699 | ds.depthWriteEnable = VK_TRUE; 1700 | ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 1701 | ds.depthBoundsTestEnable = VK_FALSE; 1702 | ds.stencilTestEnable = VK_FALSE; 1703 | ds.back.failOp = VK_STENCIL_OP_KEEP; 1704 | ds.back.passOp = VK_STENCIL_OP_KEEP; 1705 | ds.back.compareOp = VK_COMPARE_OP_ALWAYS; 1706 | ds.back.compareMask = 0; 1707 | ds.back.reference = 0; 1708 | ds.back.depthFailOp = VK_STENCIL_OP_KEEP; 1709 | ds.back.writeMask = 0; 1710 | ds.minDepthBounds = 0; 1711 | ds.maxDepthBounds = 1; 1712 | ds.stencilTestEnable = VK_FALSE; 1713 | ds.front = ds.back; 1714 | 1715 | VkPipelineMultisampleStateCreateInfo ms; 1716 | ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 1717 | ms.pNext = NULL; 1718 | ms.flags = 0; 1719 | ms.pSampleMask = NULL; 1720 | ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 1721 | ms.sampleShadingEnable = VK_FALSE; 1722 | ms.alphaToCoverageEnable = VK_FALSE; 1723 | ms.alphaToOneEnable = VK_FALSE; 1724 | ms.minSampleShading = 0.0; 1725 | 1726 | VkPipelineShaderStageCreateInfo peelShaderStages[2]; 1727 | peelShaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1728 | peelShaderStages[0].pNext = NULL; 1729 | peelShaderStages[0].pSpecializationInfo = NULL; 1730 | peelShaderStages[0].flags = 0; 1731 | peelShaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 1732 | peelShaderStages[0].pName = "main"; 1733 | peelShaderStages[0].module = engine->shdermodules[2]; 1734 | peelShaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1735 | peelShaderStages[1].pNext = NULL; 1736 | peelShaderStages[1].pSpecializationInfo = NULL; 1737 | peelShaderStages[1].flags = 0; 1738 | peelShaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 1739 | peelShaderStages[1].pName = "main"; 1740 | peelShaderStages[1].module = engine->shdermodules[3]; 1741 | 1742 | VkPipelineShaderStageCreateInfo firstPeelShaderStages[2]; 1743 | firstPeelShaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1744 | firstPeelShaderStages[0].pNext = NULL; 1745 | firstPeelShaderStages[0].pSpecializationInfo = NULL; 1746 | firstPeelShaderStages[0].flags = 0; 1747 | firstPeelShaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 1748 | firstPeelShaderStages[0].pName = "main"; 1749 | firstPeelShaderStages[0].module = engine->shdermodules[2]; 1750 | firstPeelShaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1751 | firstPeelShaderStages[1].pNext = NULL; 1752 | firstPeelShaderStages[1].pSpecializationInfo = NULL; 1753 | firstPeelShaderStages[1].flags = 0; 1754 | firstPeelShaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 1755 | firstPeelShaderStages[1].pName = "main"; 1756 | firstPeelShaderStages[1].module = engine->shdermodules[1]; 1757 | 1758 | VkGraphicsPipelineCreateInfo pipelineInfo; 1759 | pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 1760 | pipelineInfo.pNext = NULL; 1761 | pipelineInfo.layout = engine->blendPeelPipelineLayout; 1762 | pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; 1763 | pipelineInfo.basePipelineIndex = 0; 1764 | pipelineInfo.flags = 0; 1765 | pipelineInfo.pVertexInputState = &vi; 1766 | pipelineInfo.pInputAssemblyState = &ia; 1767 | pipelineInfo.pRasterizationState = &rs; 1768 | pipelineInfo.pColorBlendState = &cb; 1769 | pipelineInfo.pTessellationState = NULL; 1770 | pipelineInfo.pMultisampleState = &ms; 1771 | pipelineInfo.pDynamicState = &dynamicState; 1772 | if (dynamicState.dynamicStateCount==0) 1773 | pipelineInfo.pDynamicState=NULL; 1774 | pipelineInfo.pViewportState = &vp; 1775 | pipelineInfo.pDepthStencilState = &ds; 1776 | pipelineInfo.pStages = peelShaderStages; 1777 | pipelineInfo.stageCount = 2; 1778 | pipelineInfo.renderPass = engine->renderPass; 1779 | pipelineInfo.subpass = 3; 1780 | 1781 | LOGI("Creating peel pipeline"); 1782 | VkResult res; 1783 | res = vkCreateGraphicsPipelines(engine->vkDevice, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, 1784 | &engine->peelPipeline); 1785 | if (res != VK_SUCCESS) { 1786 | LOGE("vkCreateGraphicsPipelines returned error %d.\n", res); 1787 | return -1; 1788 | } 1789 | 1790 | LOGI("Creating first peel pipeline"); 1791 | pipelineInfo.layout = engine->pipelineLayout; 1792 | pipelineInfo.pStages = firstPeelShaderStages; 1793 | pipelineInfo.subpass = 1; 1794 | 1795 | res = vkCreateGraphicsPipelines(engine->vkDevice, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, 1796 | &engine->firstPeelPipeline); 1797 | if (res != VK_SUCCESS) { 1798 | LOGE("vkCreateGraphicsPipelines returned error %d.\n", res); 1799 | return -1; 1800 | } 1801 | 1802 | return 0; 1803 | } 1804 | 1805 | int setupBlendPipeline(struct engine* engine) { 1806 | 1807 | LOGI("Setting up blend pipeline"); 1808 | VkViewport viewport; 1809 | viewport.height = (float) engine->height; 1810 | viewport.width = (float) engine->width; 1811 | viewport.minDepth = (float) 0.0f; 1812 | viewport.maxDepth = (float) 1.0f; 1813 | viewport.x = 0; 1814 | viewport.y = 0; 1815 | 1816 | //Create a pipeline object 1817 | VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE]; 1818 | VkPipelineDynamicStateCreateInfo dynamicState; 1819 | //No dynamic state: 1820 | memset(dynamicStateEnables, 0, sizeof dynamicStateEnables); 1821 | dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 1822 | dynamicState.flags = 0; 1823 | dynamicState.pNext = NULL; 1824 | dynamicState.pDynamicStates = dynamicStateEnables; 1825 | dynamicState.dynamicStateCount = 0; 1826 | 1827 | VkPipelineVertexInputStateCreateInfo vi; 1828 | vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 1829 | vi.pNext = NULL; 1830 | vi.flags = 0; 1831 | vi.vertexBindingDescriptionCount = 1; 1832 | vi.pVertexBindingDescriptions = &engine->vertexInputBindingDescription; 1833 | vi.vertexAttributeDescriptionCount = 1; 1834 | vi.pVertexAttributeDescriptions = engine->vertexInputAttributeDescription; 1835 | 1836 | VkPipelineInputAssemblyStateCreateInfo ia; 1837 | ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 1838 | ia.pNext = NULL; 1839 | ia.flags = 0; 1840 | ia.primitiveRestartEnable = VK_FALSE; 1841 | ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1842 | 1843 | VkPipelineRasterizationStateCreateInfo rs; 1844 | rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 1845 | rs.pNext = NULL; 1846 | rs.flags = 0; 1847 | rs.polygonMode = VK_POLYGON_MODE_FILL; 1848 | rs.cullMode = VK_CULL_MODE_BACK_BIT; 1849 | rs.frontFace = VK_FRONT_FACE_CLOCKWISE; 1850 | rs.depthClampEnable = VK_TRUE; 1851 | rs.rasterizerDiscardEnable = VK_FALSE; 1852 | rs.depthBiasEnable = VK_FALSE; 1853 | rs.depthBiasConstantFactor = 0; 1854 | rs.depthBiasClamp = 0; 1855 | rs.depthBiasSlopeFactor = 0; 1856 | rs.lineWidth = 1; 1857 | 1858 | VkPipelineColorBlendStateCreateInfo cb; 1859 | cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 1860 | cb.flags = 0; 1861 | cb.pNext = NULL; 1862 | VkPipelineColorBlendAttachmentState att_state[1]; 1863 | att_state[0].colorWriteMask = 0xf; 1864 | att_state[0].blendEnable = VK_TRUE; 1865 | att_state[0].alphaBlendOp = VK_BLEND_OP_ADD; 1866 | att_state[0].colorBlendOp = VK_BLEND_OP_ADD; 1867 | att_state[0].srcColorBlendFactor = VK_BLEND_FACTOR_DST_ALPHA; 1868 | att_state[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE; 1869 | att_state[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 1870 | att_state[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 1871 | cb.attachmentCount = 1; 1872 | cb.pAttachments = att_state; 1873 | cb.logicOpEnable = VK_FALSE; 1874 | cb.logicOp = VK_LOGIC_OP_NO_OP; 1875 | cb.blendConstants[0] = 1.0f; 1876 | cb.blendConstants[1] = 1.0f; 1877 | cb.blendConstants[2] = 1.0f; 1878 | cb.blendConstants[3] = 1.0f; 1879 | 1880 | VkPipelineViewportStateCreateInfo vp = {}; 1881 | vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 1882 | vp.pNext = NULL; 1883 | vp.flags = 0; 1884 | vp.viewportCount = 1; 1885 | // dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT; 1886 | vp.pViewports = &viewport; 1887 | vp.scissorCount = 1; 1888 | dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR; 1889 | // vp.pScissors = &scissor; 1890 | 1891 | VkPipelineDepthStencilStateCreateInfo ds; 1892 | ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 1893 | ds.pNext = NULL; 1894 | ds.flags = 0; 1895 | ds.depthTestEnable = VK_FALSE; 1896 | ds.depthWriteEnable = VK_FALSE; 1897 | ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 1898 | ds.depthBoundsTestEnable = VK_FALSE; 1899 | ds.stencilTestEnable = VK_FALSE; 1900 | ds.back.failOp = VK_STENCIL_OP_KEEP; 1901 | ds.back.passOp = VK_STENCIL_OP_KEEP; 1902 | ds.back.compareOp = VK_COMPARE_OP_ALWAYS; 1903 | ds.back.compareMask = 0; 1904 | ds.back.reference = 0; 1905 | ds.back.depthFailOp = VK_STENCIL_OP_KEEP; 1906 | ds.back.writeMask = 0; 1907 | ds.minDepthBounds = 0; 1908 | ds.maxDepthBounds = 0; 1909 | ds.stencilTestEnable = VK_FALSE; 1910 | ds.front = ds.back; 1911 | 1912 | VkPipelineMultisampleStateCreateInfo ms; 1913 | ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 1914 | ms.pNext = NULL; 1915 | ms.flags = 0; 1916 | ms.pSampleMask = NULL; 1917 | ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 1918 | ms.sampleShadingEnable = VK_FALSE; 1919 | ms.alphaToCoverageEnable = VK_FALSE; 1920 | ms.alphaToOneEnable = VK_FALSE; 1921 | ms.minSampleShading = 0.0; 1922 | 1923 | VkPipelineShaderStageCreateInfo shaderStages[2]; 1924 | shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1925 | shaderStages[0].pNext = NULL; 1926 | shaderStages[0].pSpecializationInfo = NULL; 1927 | shaderStages[0].flags = 0; 1928 | shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 1929 | shaderStages[0].pName = "main"; 1930 | shaderStages[0].module = engine->shdermodules[4]; 1931 | shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1932 | shaderStages[1].pNext = NULL; 1933 | shaderStages[1].pSpecializationInfo = NULL; 1934 | shaderStages[1].flags = 0; 1935 | shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 1936 | shaderStages[1].pName = "main"; 1937 | shaderStages[1].module = engine->shdermodules[5]; 1938 | 1939 | VkGraphicsPipelineCreateInfo pipelineInfo; 1940 | pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 1941 | pipelineInfo.pNext = NULL; 1942 | pipelineInfo.layout = engine->blendPeelPipelineLayout; 1943 | pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; 1944 | pipelineInfo.basePipelineIndex = 0; 1945 | pipelineInfo.flags = 0; 1946 | pipelineInfo.pVertexInputState = &vi; 1947 | pipelineInfo.pInputAssemblyState = &ia; 1948 | pipelineInfo.pRasterizationState = &rs; 1949 | pipelineInfo.pColorBlendState = &cb; 1950 | pipelineInfo.pTessellationState = NULL; 1951 | pipelineInfo.pMultisampleState = &ms; 1952 | pipelineInfo.pDynamicState = &dynamicState; 1953 | if (dynamicState.dynamicStateCount==0) 1954 | pipelineInfo.pDynamicState=NULL; 1955 | pipelineInfo.pViewportState = &vp; 1956 | pipelineInfo.pDepthStencilState = &ds; 1957 | pipelineInfo.pStages = shaderStages; 1958 | pipelineInfo.stageCount = 2; 1959 | pipelineInfo.renderPass = engine->renderPass; 1960 | pipelineInfo.subpass = 2; 1961 | 1962 | VkResult res; 1963 | res = vkCreateGraphicsPipelines(engine->vkDevice, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, 1964 | &engine->blendPipeline); 1965 | if (res != VK_SUCCESS) { 1966 | LOGE("vkCreateGraphicsPipelines returned error %d.\n", res); 1967 | return -1; 1968 | } 1969 | return 0; 1970 | } 1971 | 1972 | int setupUniforms(struct engine* engine) 1973 | { 1974 | VkResult res; 1975 | 1976 | //Create a descriptor pool 1977 | VkDescriptorPoolSize typeCounts[2]; 1978 | typeCounts[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 1979 | typeCounts[0].descriptorCount = MAX_BOXES+3; 1980 | typeCounts[1].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 1981 | typeCounts[1].descriptorCount = 3; 1982 | 1983 | VkDescriptorPoolCreateInfo descriptorPoolInfo; 1984 | descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 1985 | descriptorPoolInfo.flags = 0; 1986 | descriptorPoolInfo.pNext = NULL; 1987 | descriptorPoolInfo.maxSets = MAX_BOXES+6; 1988 | descriptorPoolInfo.poolSizeCount = 2; 1989 | descriptorPoolInfo.pPoolSizes = typeCounts; 1990 | 1991 | VkDescriptorPool descriptorPool; 1992 | res = vkCreateDescriptorPool(engine->vkDevice, &descriptorPoolInfo, NULL, &descriptorPool); 1993 | if (res != VK_SUCCESS) { 1994 | printf ("vkCreateDescriptorPool returned error %d.\n", res); 1995 | return -1; 1996 | } 1997 | 1998 | printf ("minUniformBufferOffsetAlignment %d.\n", (int)engine->deviceProperties.limits.minUniformBufferOffsetAlignment); 1999 | engine->modelBufferValsOffset = sizeof(float)*16; 2000 | if (engine->modelBufferValsOffset < engine->deviceProperties.limits.minUniformBufferOffsetAlignment) 2001 | engine->modelBufferValsOffset = engine->deviceProperties.limits.minUniformBufferOffsetAlignment; 2002 | printf ("modelBufferValsOffset %d.\n", engine->modelBufferValsOffset); 2003 | 2004 | VkBufferCreateInfo uniformBufferCreateInfo; 2005 | uniformBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 2006 | uniformBufferCreateInfo.pNext = NULL; 2007 | uniformBufferCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; 2008 | uniformBufferCreateInfo.size = engine->modelBufferValsOffset*(MAX_BOXES+3); //Enough to store MAX_BOXES+3 matricies. 2009 | uniformBufferCreateInfo.queueFamilyIndexCount = 0; 2010 | uniformBufferCreateInfo.pQueueFamilyIndices = NULL; 2011 | uniformBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 2012 | uniformBufferCreateInfo.flags = 0; 2013 | 2014 | VkBuffer uniformBuffer; 2015 | res = vkCreateBuffer(engine->vkDevice, &uniformBufferCreateInfo, NULL, &uniformBuffer); 2016 | if (res != VK_SUCCESS) { 2017 | LOGE ("vkCreateBuffer returned error %d.\n", res); 2018 | return -1; 2019 | } 2020 | 2021 | VkMemoryRequirements memoryRequirements; 2022 | vkGetBufferMemoryRequirements(engine->vkDevice, uniformBuffer, &memoryRequirements); 2023 | uint8_t found = 0; 2024 | uint32_t typeBits = memoryRequirements.memoryTypeBits; 2025 | LOGI("Uniform memory types %d", typeBits); 2026 | VkFlags requirements_mask = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 2027 | uint32_t typeIndex; 2028 | for (typeIndex = 0; typeIndex < engine->physicalDeviceMemoryProperties.memoryTypeCount; typeIndex++) { 2029 | if ((typeBits & 1) == 1)//Check last bit; 2030 | { 2031 | if ((engine->physicalDeviceMemoryProperties.memoryTypes[typeIndex].propertyFlags & requirements_mask) == requirements_mask) 2032 | { 2033 | found=1; 2034 | break; 2035 | } 2036 | } 2037 | typeBits >>= 1; 2038 | } 2039 | 2040 | if (!found) 2041 | { 2042 | LOGE ("Did not find a suitable memory type.\n"); 2043 | return -1; 2044 | }else 2045 | LOGI ("Using memory type %d.\n", typeIndex); 2046 | 2047 | VkMemoryAllocateInfo memAllocInfo; 2048 | memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 2049 | memAllocInfo.pNext = NULL; 2050 | memAllocInfo.allocationSize = memoryRequirements.size; 2051 | memAllocInfo.memoryTypeIndex = typeIndex; 2052 | // 2053 | VkDeviceMemory uniformMemory; 2054 | res = vkAllocateMemory(engine->vkDevice, &memAllocInfo, NULL, &uniformMemory); 2055 | if (res != VK_SUCCESS) { 2056 | LOGE ("vkCreateBuffer returned error %d.\n", res); 2057 | return -1; 2058 | } 2059 | 2060 | res = vkMapMemory(engine->vkDevice, uniformMemory, 0, memoryRequirements.size, 0, (void **)&engine->uniformMappedMemory); 2061 | if (res != VK_SUCCESS) { 2062 | LOGE ("vkMapMemory returned error %d.\n", res); 2063 | return -1; 2064 | } 2065 | 2066 | res = vkBindBufferMemory(engine->vkDevice, uniformBuffer, uniformMemory, 0); 2067 | if (res != VK_SUCCESS) { 2068 | LOGE ("vkBindBufferMemory returned error %d.\n", res); 2069 | return -1; 2070 | } 2071 | 2072 | engine->descriptorSetLayouts = new VkDescriptorSetLayout[3]; 2073 | 2074 | for (int i = 0; i <3; i++) { 2075 | VkDescriptorSetLayoutBinding layout_bindings[1]; 2076 | layout_bindings[0].binding = 0; 2077 | layout_bindings[0].descriptorType = (i<2) ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 2078 | layout_bindings[0].descriptorCount = 1; 2079 | layout_bindings[0].stageFlags = (i<2) ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT; 2080 | layout_bindings[0].pImmutableSamplers = NULL; 2081 | 2082 | //Next take layout bindings and use them to create a descriptor set layout 2083 | VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo; 2084 | descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 2085 | descriptorSetLayoutCreateInfo.flags = 0; 2086 | descriptorSetLayoutCreateInfo.pNext = NULL; 2087 | descriptorSetLayoutCreateInfo.bindingCount = 1; 2088 | descriptorSetLayoutCreateInfo.pBindings = layout_bindings; 2089 | 2090 | res = vkCreateDescriptorSetLayout(engine->vkDevice, &descriptorSetLayoutCreateInfo, NULL, 2091 | &engine->descriptorSetLayouts[i]); 2092 | if (res != VK_SUCCESS) { 2093 | LOGE ("vkCreateDescriptorSetLayout returned error.\n"); 2094 | return -1; 2095 | } 2096 | } 2097 | 2098 | //Create the descriptor sets 2099 | 2100 | VkDescriptorSetAllocateInfo descriptorSetAllocateInfo; 2101 | descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 2102 | descriptorSetAllocateInfo.pNext = NULL; 2103 | descriptorSetAllocateInfo.descriptorPool = descriptorPool; 2104 | descriptorSetAllocateInfo.descriptorSetCount = 1; 2105 | descriptorSetAllocateInfo.pSetLayouts = &engine->descriptorSetLayouts[0]; 2106 | 2107 | res = vkAllocateDescriptorSets(engine->vkDevice, &descriptorSetAllocateInfo, &engine->sceneDescriptorSet); 2108 | if (res != VK_SUCCESS) { 2109 | printf ("vkAllocateDescriptorSets returned error %d.\n", res); 2110 | return -1; 2111 | } 2112 | 2113 | res = vkAllocateDescriptorSets(engine->vkDevice, &descriptorSetAllocateInfo, &engine->identitySceneDescriptorSet); 2114 | if (res != VK_SUCCESS) { 2115 | printf ("vkAllocateDescriptorSets returned error %d.\n", res); 2116 | return -1; 2117 | } 2118 | 2119 | engine->modelDescriptorSets = new VkDescriptorSet[MAX_BOXES]; 2120 | VkDescriptorSetLayout sceneLayouts[MAX_BOXES]; 2121 | for (int i=0; idescriptorSetLayouts[1]; 2123 | 2124 | descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 2125 | descriptorSetAllocateInfo.pNext = NULL; 2126 | descriptorSetAllocateInfo.descriptorPool = descriptorPool; 2127 | descriptorSetAllocateInfo.descriptorSetCount = MAX_BOXES; 2128 | descriptorSetAllocateInfo.pSetLayouts = sceneLayouts; 2129 | 2130 | res = vkAllocateDescriptorSets(engine->vkDevice, &descriptorSetAllocateInfo, engine->modelDescriptorSets); 2131 | if (res != VK_SUCCESS) { 2132 | printf ("vkAllocateDescriptorSets returned error %d.\n", res); 2133 | return -1; 2134 | } 2135 | 2136 | descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 2137 | descriptorSetAllocateInfo.pNext = NULL; 2138 | descriptorSetAllocateInfo.descriptorPool = descriptorPool; 2139 | descriptorSetAllocateInfo.descriptorSetCount = 1; 2140 | descriptorSetAllocateInfo.pSetLayouts = engine->descriptorSetLayouts; 2141 | 2142 | res = vkAllocateDescriptorSets(engine->vkDevice, &descriptorSetAllocateInfo, &engine->identityModelDescriptorSet); 2143 | if (res != VK_SUCCESS) { 2144 | printf ("vkAllocateDescriptorSets returned error %d.\n", res); 2145 | return -1; 2146 | } 2147 | 2148 | //The input attachments: 2149 | descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 2150 | descriptorSetAllocateInfo.pNext = NULL; 2151 | descriptorSetAllocateInfo.descriptorPool = descriptorPool; 2152 | descriptorSetAllocateInfo.descriptorSetCount = 1; 2153 | descriptorSetAllocateInfo.pSetLayouts = &engine->descriptorSetLayouts[2]; 2154 | res = vkAllocateDescriptorSets(engine->vkDevice, &descriptorSetAllocateInfo, &engine->colourInputAttachmentDescriptorSet); 2155 | if (res != VK_SUCCESS) { 2156 | printf ("vkAllocateDescriptorSets returned error %d.\n", res); 2157 | return -1; 2158 | } 2159 | 2160 | descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 2161 | descriptorSetAllocateInfo.pNext = NULL; 2162 | descriptorSetAllocateInfo.descriptorPool = descriptorPool; 2163 | descriptorSetAllocateInfo.descriptorSetCount = 1; 2164 | descriptorSetAllocateInfo.pSetLayouts = &engine->descriptorSetLayouts[2]; 2165 | res = vkAllocateDescriptorSets(engine->vkDevice, &descriptorSetAllocateInfo, &engine->depthInputAttachmentDescriptorSets[0]); 2166 | if (res != VK_SUCCESS) { 2167 | printf ("vkAllocateDescriptorSets returned error %d.\n", res); 2168 | return -1; 2169 | } 2170 | 2171 | descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 2172 | descriptorSetAllocateInfo.pNext = NULL; 2173 | descriptorSetAllocateInfo.descriptorPool = descriptorPool; 2174 | descriptorSetAllocateInfo.descriptorSetCount = 1; 2175 | descriptorSetAllocateInfo.pSetLayouts = &engine->descriptorSetLayouts[2]; 2176 | res = vkAllocateDescriptorSets(engine->vkDevice, &descriptorSetAllocateInfo, &engine->depthInputAttachmentDescriptorSets[1]); 2177 | if (res != VK_SUCCESS) { 2178 | printf ("vkAllocateDescriptorSets returned error %d.\n", res); 2179 | return -1; 2180 | } 2181 | 2182 | 2183 | VkDescriptorBufferInfo uniformBufferInfo[MAX_BOXES+3]; 2184 | VkWriteDescriptorSet writes[MAX_BOXES+6]; 2185 | for (int i = 0; imodelBufferValsOffset*i; 2188 | uniformBufferInfo[i].range = sizeof(float) * 16; 2189 | } 2190 | for (int i = 0; imodelDescriptorSets[i]; 2194 | writes[i].descriptorCount = 1; 2195 | writes[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 2196 | writes[i].pBufferInfo = &uniformBufferInfo[i]; 2197 | writes[i].dstArrayElement = 0; 2198 | writes[i].dstBinding = 0; 2199 | } 2200 | 2201 | //Scene data 2202 | writes[MAX_BOXES].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 2203 | writes[MAX_BOXES].pNext = NULL; 2204 | writes[MAX_BOXES].dstSet = engine->sceneDescriptorSet; 2205 | writes[MAX_BOXES].descriptorCount = 1; 2206 | writes[MAX_BOXES].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 2207 | writes[MAX_BOXES].pBufferInfo = &uniformBufferInfo[MAX_BOXES]; 2208 | writes[MAX_BOXES].dstArrayElement = 0; 2209 | writes[MAX_BOXES].dstBinding = 0; 2210 | 2211 | //Identity model matrix 2212 | writes[MAX_BOXES+1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 2213 | writes[MAX_BOXES+1].pNext = NULL; 2214 | writes[MAX_BOXES+1].dstSet = engine->identityModelDescriptorSet; 2215 | writes[MAX_BOXES+1].descriptorCount = 1; 2216 | writes[MAX_BOXES+1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 2217 | writes[MAX_BOXES+1].pBufferInfo = &uniformBufferInfo[MAX_BOXES+1]; 2218 | writes[MAX_BOXES+1].dstArrayElement = 0; 2219 | writes[MAX_BOXES+1].dstBinding = 0; 2220 | 2221 | //Identity scene matrix 2222 | writes[MAX_BOXES+2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 2223 | writes[MAX_BOXES+2].pNext = NULL; 2224 | writes[MAX_BOXES+2].dstSet = engine->identitySceneDescriptorSet; 2225 | writes[MAX_BOXES+2].descriptorCount = 1; 2226 | writes[MAX_BOXES+2].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 2227 | writes[MAX_BOXES+2].pBufferInfo = &uniformBufferInfo[MAX_BOXES+2]; 2228 | writes[MAX_BOXES+2].dstArrayElement = 0; 2229 | writes[MAX_BOXES+2].dstBinding = 0; 2230 | 2231 | //The input attachment: 2232 | VkDescriptorImageInfo uniformImageInfo; 2233 | uniformImageInfo.imageLayout=VK_IMAGE_LAYOUT_GENERAL; 2234 | uniformImageInfo.imageView=engine->peelView; 2235 | uniformImageInfo.sampler=NULL; 2236 | writes[MAX_BOXES+3].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 2237 | writes[MAX_BOXES+3].pNext = NULL; 2238 | writes[MAX_BOXES+3].dstSet = engine->colourInputAttachmentDescriptorSet; 2239 | writes[MAX_BOXES+3].descriptorCount = 1; 2240 | writes[MAX_BOXES+3].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 2241 | writes[MAX_BOXES+3].pImageInfo=&uniformImageInfo; 2242 | writes[MAX_BOXES+3].dstArrayElement = 0; 2243 | writes[MAX_BOXES+3].dstBinding = 0; 2244 | 2245 | VkDescriptorImageInfo depthuniformImageInfo[2]; 2246 | depthuniformImageInfo[0].imageLayout=VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 2247 | depthuniformImageInfo[0].imageView=engine->depthView[0]; 2248 | depthuniformImageInfo[0].sampler=NULL; 2249 | writes[MAX_BOXES+4].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 2250 | writes[MAX_BOXES+4].pNext = NULL; 2251 | writes[MAX_BOXES+4].dstSet = engine->depthInputAttachmentDescriptorSets[0]; 2252 | writes[MAX_BOXES+4].descriptorCount = 1; 2253 | writes[MAX_BOXES+4].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 2254 | writes[MAX_BOXES+4].pImageInfo=&depthuniformImageInfo[0]; 2255 | writes[MAX_BOXES+4].dstArrayElement = 0; 2256 | writes[MAX_BOXES+4].dstBinding = 0; 2257 | 2258 | depthuniformImageInfo[1].imageLayout=VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 2259 | depthuniformImageInfo[1].imageView=engine->depthView[1]; 2260 | depthuniformImageInfo[1].sampler=NULL; 2261 | writes[MAX_BOXES+5].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 2262 | writes[MAX_BOXES+5].pNext = NULL; 2263 | writes[MAX_BOXES+5].dstSet = engine->depthInputAttachmentDescriptorSets[1]; 2264 | writes[MAX_BOXES+5].descriptorCount = 1; 2265 | writes[MAX_BOXES+5].descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 2266 | writes[MAX_BOXES+5].pImageInfo=&depthuniformImageInfo[1]; 2267 | writes[MAX_BOXES+5].dstArrayElement = 0; 2268 | writes[MAX_BOXES+5].dstBinding = 0; 2269 | 2270 | vkUpdateDescriptorSets(engine->vkDevice, MAX_BOXES+6, writes, 0, NULL); 2271 | 2272 | LOGI ("Descriptor sets updated %d.\n", res); 2273 | return 0; 2274 | } 2275 | 2276 | void createSecondaryBuffers(struct engine* engine) 2277 | { 2278 | LOGI("Creating Secondary Buffers"); 2279 | LOGI("Creating trad blend buffers"); 2280 | engine->rebuildCommadBuffersRequired=false; 2281 | for (int i = 0; i< engine->swapchainImageCount; i++) { 2282 | VkResult res; 2283 | VkCommandBufferInheritanceInfo commandBufferInheritanceInfo; 2284 | commandBufferInheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; 2285 | commandBufferInheritanceInfo.pNext = 0; 2286 | commandBufferInheritanceInfo.renderPass = engine->renderPass; 2287 | commandBufferInheritanceInfo.subpass = 0; 2288 | commandBufferInheritanceInfo.framebuffer = engine->framebuffers[i]; 2289 | commandBufferInheritanceInfo.occlusionQueryEnable = 0; 2290 | commandBufferInheritanceInfo.queryFlags = 0; 2291 | commandBufferInheritanceInfo.pipelineStatistics = 0; 2292 | 2293 | VkCommandBufferBeginInfo commandBufferBeginInfo = {}; 2294 | commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 2295 | commandBufferBeginInfo.pNext = NULL; 2296 | commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; 2297 | commandBufferBeginInfo.pInheritanceInfo = &commandBufferInheritanceInfo; 2298 | LOGI("Creating Secondary Buffer %d using subpass %d (%d boxes)", i, 0, engine->boxCount); 2299 | res = vkBeginCommandBuffer(engine->secondaryCommandBuffers[i], &commandBufferBeginInfo); 2300 | if (res != VK_SUCCESS) { 2301 | printf("vkBeginCommandBuffer returned error.\n"); 2302 | return; 2303 | } 2304 | 2305 | vkCmdBindPipeline(engine->secondaryCommandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, 2306 | engine->traditionalBlendPipeline); 2307 | 2308 | vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[i], 2309 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2310 | engine->pipelineLayout, 1, 1, 2311 | &engine->sceneDescriptorSet, 0, NULL); 2312 | VkDeviceSize offsets[1] = {0}; 2313 | vkCmdBindVertexBuffers(engine->secondaryCommandBuffers[i], 0, 1, &engine->vertexBuffer, 2314 | offsets); 2315 | for (int object = 0; object < engine->boxCount; object++) { 2316 | vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[i], 2317 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2318 | engine->pipelineLayout, 0, 1, 2319 | &engine->modelDescriptorSets[object], 0, NULL); 2320 | 2321 | vkCmdDraw(engine->secondaryCommandBuffers[i], 12 * 3, 1, 0, 0); 2322 | } 2323 | 2324 | res = vkEndCommandBuffer(engine->secondaryCommandBuffers[i]); 2325 | if (res != VK_SUCCESS) { 2326 | printf("vkBeginCommandBuffer returned error.\n"); 2327 | return; 2328 | } 2329 | } 2330 | LOGI("Creating peel stage buffers"); 2331 | for (int layer = 0; layer < MAX_LAYERS; layer++) { 2332 | for (int i = 0; i < engine->swapchainImageCount; i++) { 2333 | int cmdBuffIndex = engine->swapchainImageCount + layer * engine->swapchainImageCount * 2 + i; 2334 | VkResult res; 2335 | VkCommandBufferInheritanceInfo commandBufferInheritanceInfo; 2336 | commandBufferInheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; 2337 | commandBufferInheritanceInfo.pNext = 0; 2338 | commandBufferInheritanceInfo.renderPass = engine->renderPass; 2339 | commandBufferInheritanceInfo.subpass = layer*2+1; 2340 | commandBufferInheritanceInfo.framebuffer = engine->framebuffers[i]; 2341 | commandBufferInheritanceInfo.occlusionQueryEnable = 0; 2342 | commandBufferInheritanceInfo.queryFlags = 0; 2343 | commandBufferInheritanceInfo.pipelineStatistics = 0; 2344 | 2345 | VkCommandBufferBeginInfo commandBufferBeginInfo = {}; 2346 | commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 2347 | commandBufferBeginInfo.pNext = NULL; 2348 | commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; 2349 | commandBufferBeginInfo.pInheritanceInfo = &commandBufferInheritanceInfo; 2350 | LOGI("Creating Secondary Buffer %d using subpass %d (layer %d, swapchainImage %d)", cmdBuffIndex, commandBufferInheritanceInfo.subpass, layer, i); 2351 | res = vkBeginCommandBuffer(engine->secondaryCommandBuffers[cmdBuffIndex], 2352 | &commandBufferBeginInfo); 2353 | if (res != VK_SUCCESS) { 2354 | printf("vkBeginCommandBuffer returned error.\n"); 2355 | return; 2356 | } 2357 | 2358 | //Clear the peel colour buffer 2359 | { 2360 | VkClearAttachment clear[2]; 2361 | clear[0].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 2362 | clear[0].clearValue.color.float32[0] = 0.0f; 2363 | clear[0].clearValue.color.float32[1] = 0.0f; 2364 | clear[0].clearValue.color.float32[2] = 0.0f; 2365 | clear[0].clearValue.color.float32[3] = 0.0f; 2366 | clear[0].colorAttachment=0; 2367 | clear[1].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; 2368 | clear[1].clearValue.depthStencil.depth = 1.0f; 2369 | clear[1].clearValue.depthStencil.stencil = 0; 2370 | VkClearRect clearRect; 2371 | clearRect.baseArrayLayer=0; 2372 | clearRect.layerCount=1; 2373 | clearRect.rect.extent.height=engine->height; 2374 | clearRect.rect.extent.width=engine->width; 2375 | clearRect.rect.offset.x=0; 2376 | clearRect.rect.offset.y=0; 2377 | vkCmdClearAttachments(engine->secondaryCommandBuffers[cmdBuffIndex], 2, clear, 1, &clearRect); 2378 | } 2379 | 2380 | vkCmdBindPipeline(engine->secondaryCommandBuffers[cmdBuffIndex], 2381 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2382 | (layer==0) ? engine->firstPeelPipeline : engine->peelPipeline); 2383 | 2384 | VkRect2D scissor; 2385 | if (engine->splitscreen) 2386 | scissor.extent.width = engine->width / 2; 2387 | else 2388 | scissor.extent.width = engine->width; 2389 | scissor.extent.height = engine->height; 2390 | if (engine->splitscreen) 2391 | scissor.offset.x = scissor.extent.width; 2392 | else 2393 | scissor.offset.x = 0; 2394 | scissor.offset.y = 0; 2395 | 2396 | vkCmdSetScissor(engine->secondaryCommandBuffers[cmdBuffIndex], 0, 1, &scissor); 2397 | 2398 | vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[cmdBuffIndex], 2399 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2400 | (layer==0) ? engine->pipelineLayout : engine->blendPeelPipelineLayout, 1, 1, 2401 | &engine->sceneDescriptorSet, 0, NULL); 2402 | VkDeviceSize offsets[1] = {0}; 2403 | vkCmdBindVertexBuffers(engine->secondaryCommandBuffers[cmdBuffIndex], 0, 1, 2404 | &engine->vertexBuffer, 2405 | offsets); 2406 | 2407 | if (layer>0) 2408 | { 2409 | vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[cmdBuffIndex], 2410 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2411 | engine->blendPeelPipelineLayout, 2, 1, 2412 | &engine->depthInputAttachmentDescriptorSets[!(layer%2)], 0, NULL); 2413 | } 2414 | 2415 | for (int object = 0; object < engine->boxCount; object++) { 2416 | vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[cmdBuffIndex], 2417 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2418 | (layer==0) ? engine->pipelineLayout : engine->blendPeelPipelineLayout, 0, 1, 2419 | &engine->modelDescriptorSets[object], 0, NULL); 2420 | 2421 | vkCmdDraw(engine->secondaryCommandBuffers[cmdBuffIndex], 12 * 3, 1, 0, 0); 2422 | } 2423 | 2424 | 2425 | //Test clearing depth buffer at end 2426 | VkClearAttachment clear; 2427 | clear.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; 2428 | clear.clearValue.depthStencil.depth = 0.0f; 2429 | clear.clearValue.depthStencil.stencil = 0; 2430 | VkClearRect clearRect; 2431 | clearRect.baseArrayLayer=0; 2432 | clearRect.layerCount=1; 2433 | clearRect.rect.extent.height=engine->height/4*2; 2434 | clearRect.rect.extent.width=engine->width/4*2; 2435 | clearRect.rect.offset.x=engine->height/4; 2436 | clearRect.rect.offset.y=engine->width/4; 2437 | //vkCmdClearAttachments(engine->secondaryCommandBuffers[cmdBuffIndex], 1, &clear, 1, &clearRect); 2438 | 2439 | res = vkEndCommandBuffer(engine->secondaryCommandBuffers[cmdBuffIndex]); 2440 | if (res != VK_SUCCESS) { 2441 | printf("vkBeginCommandBuffer returned error.\n"); 2442 | return; 2443 | } 2444 | } 2445 | } 2446 | LOGI("Creating blend stage buffers"); 2447 | for (int layer = 0; layer < MAX_LAYERS; layer++) { 2448 | for (int i = 0; i < engine->swapchainImageCount; i++) { 2449 | int cmdBuffIndex = engine->swapchainImageCount + engine->swapchainImageCount * layer * 2 + i + engine->swapchainImageCount; 2450 | VkResult res; 2451 | VkCommandBufferInheritanceInfo commandBufferInheritanceInfo; 2452 | commandBufferInheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; 2453 | commandBufferInheritanceInfo.pNext = 0; 2454 | commandBufferInheritanceInfo.renderPass = engine->renderPass; 2455 | commandBufferInheritanceInfo.subpass = layer*2+2; 2456 | commandBufferInheritanceInfo.framebuffer = engine->framebuffers[i]; 2457 | commandBufferInheritanceInfo.occlusionQueryEnable = 0; 2458 | commandBufferInheritanceInfo.queryFlags = 0; 2459 | commandBufferInheritanceInfo.pipelineStatistics = 0; 2460 | 2461 | VkCommandBufferBeginInfo commandBufferBeginInfo = {}; 2462 | commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 2463 | commandBufferBeginInfo.pNext = NULL; 2464 | commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; 2465 | commandBufferBeginInfo.pInheritanceInfo = &commandBufferInheritanceInfo; 2466 | 2467 | LOGI("Creating secondaryCommandBuffer %d using subpass %d (layer %d, swapchainImage %d)", cmdBuffIndex, layer*2+2, layer, i); 2468 | res = vkBeginCommandBuffer(engine->secondaryCommandBuffers[cmdBuffIndex], 2469 | &commandBufferBeginInfo); 2470 | if (res != VK_SUCCESS) { 2471 | printf("vkBeginCommandBuffer returned error.\n"); 2472 | return; 2473 | } 2474 | 2475 | vkCmdBindPipeline(engine->secondaryCommandBuffers[cmdBuffIndex], 2476 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2477 | engine->blendPipeline); 2478 | 2479 | VkRect2D scissor; 2480 | if (engine->splitscreen) 2481 | scissor.extent.width = engine->width / 2; 2482 | else 2483 | scissor.extent.width = engine->width; 2484 | scissor.extent.height = engine->height; 2485 | if (engine->splitscreen) 2486 | scissor.offset.x = scissor.extent.width; 2487 | else 2488 | scissor.offset.x = 0; 2489 | scissor.offset.y = 0; 2490 | 2491 | vkCmdSetScissor(engine->secondaryCommandBuffers[cmdBuffIndex], 0, 1, &scissor); 2492 | 2493 | vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[cmdBuffIndex], 2494 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2495 | engine->blendPeelPipelineLayout, 1, 1, 2496 | &engine->identitySceneDescriptorSet, 0, NULL); 2497 | 2498 | VkDeviceSize offsets[1] = {0}; 2499 | vkCmdBindVertexBuffers(engine->secondaryCommandBuffers[cmdBuffIndex], 0, 1, 2500 | &engine->vertexBuffer, 2501 | offsets); 2502 | 2503 | vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[cmdBuffIndex], 2504 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2505 | engine->blendPeelPipelineLayout, 0, 1, 2506 | &engine->identityModelDescriptorSet, 0, NULL); 2507 | 2508 | vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[cmdBuffIndex], 2509 | VK_PIPELINE_BIND_POINT_GRAPHICS, 2510 | engine->blendPeelPipelineLayout, 2, 1, 2511 | &engine->colourInputAttachmentDescriptorSet, 0, NULL); 2512 | 2513 | 2514 | vkCmdDraw(engine->secondaryCommandBuffers[cmdBuffIndex], 12 * 3, 1, 0, 0); 2515 | // for (int object = 0; object < MAX_BOXES; object++) { 2516 | // vkCmdBindDescriptorSets(engine->secondaryCommandBuffers[cmdBuffIndex], 2517 | // VK_PIPELINE_BIND_POINT_GRAPHICS, 2518 | // engine->blendPipelineLayout, 0, 1, 2519 | // &engine->modelDescriptorSets[object], 0, NULL); 2520 | // 2521 | // vkCmdDraw(engine->secondaryCommandBuffers[cmdBuffIndex], 12 * 3, 1, 0, 0); 2522 | // } 2523 | 2524 | res = vkEndCommandBuffer(engine->secondaryCommandBuffers[cmdBuffIndex]); 2525 | if (res != VK_SUCCESS) { 2526 | printf("vkBeginCommandBuffer returned error.\n"); 2527 | return; 2528 | } 2529 | } 2530 | } 2531 | } 2532 | 2533 | void updateUniforms(struct engine* engine) 2534 | { 2535 | perspective_matrix(0.7853 /* 45deg */, (float)engine->width/(float)engine->height, 0.1f, 50.0f, (float*)(engine->uniformMappedMemory + engine->modelBufferValsOffset*MAX_BOXES)); 2536 | identity_matrix((float*)(engine->uniformMappedMemory + engine->modelBufferValsOffset*(MAX_BOXES+1))); 2537 | identity_matrix((float*)(engine->uniformMappedMemory + engine->modelBufferValsOffset*(MAX_BOXES+2))); 2538 | engine->simulation->write(engine->uniformMappedMemory, engine->modelBufferValsOffset); 2539 | } 2540 | 2541 | /** 2542 | * Just the current frame in the display. 2543 | */ 2544 | static void engine_draw_frame(struct engine* engine) { 2545 | 2546 | if (!engine->vulkanSetupOK) { 2547 | // LOGI("engine_draw_frame %d", engine->frame); 2548 | // LOGI("Vulkan not ready"); 2549 | return; 2550 | } 2551 | 2552 | // if (engine->frame>0) 2553 | // return; 2554 | 2555 | // sleep(1); 2556 | 2557 | VkClearValue clearValues[1]; 2558 | clearValues[0].color.float32[0] = 0.0f; 2559 | clearValues[0].color.float32[1] = 0.0f; 2560 | clearValues[0].color.float32[2] = 0.0f; 2561 | clearValues[0].color.float32[3] = 1.0f; 2562 | 2563 | //The queue is idle, now is a good time to update the bound memory. 2564 | updateUniforms(engine); 2565 | 2566 | if (engine->rebuildCommadBuffersRequired) 2567 | createSecondaryBuffers(engine); 2568 | 2569 | uint32_t currentBuffer; 2570 | VkResult res; 2571 | 2572 | // Get next image in the swap chain (back/front buffer) 2573 | res = vkAcquireNextImageKHR(engine->vkDevice, engine->swapchain, UINT64_MAX, 2574 | engine->presentCompleteSemaphore, NULL, ¤tBuffer); 2575 | if (res != VK_SUCCESS) { 2576 | LOGE ("vkAcquireNextImageKHR returned error.\n"); 2577 | return; 2578 | } 2579 | 2580 | // LOGI("Using buffer %d", currentBuffer); 2581 | 2582 | //Now record the primary command buffer: 2583 | VkRenderPassBeginInfo renderPassBeginInfo; 2584 | renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 2585 | renderPassBeginInfo.pNext = NULL; 2586 | renderPassBeginInfo.renderPass = engine->renderPass; 2587 | renderPassBeginInfo.framebuffer = engine->framebuffers[currentBuffer]; 2588 | renderPassBeginInfo.renderArea.offset.x = 0; 2589 | renderPassBeginInfo.renderArea.offset.y = 0; 2590 | renderPassBeginInfo.renderArea.extent.width = engine->width; 2591 | renderPassBeginInfo.renderArea.extent.height = engine->height; 2592 | renderPassBeginInfo.clearValueCount = 1; 2593 | renderPassBeginInfo.pClearValues = clearValues;// + (i*2); 2594 | 2595 | VkCommandBufferBeginInfo commandBufferBeginInfo = {}; 2596 | commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 2597 | commandBufferBeginInfo.pNext = NULL; 2598 | commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 2599 | commandBufferBeginInfo.pInheritanceInfo = NULL; 2600 | res = vkBeginCommandBuffer(engine->renderCommandBuffer[0], &commandBufferBeginInfo); 2601 | if (res != VK_SUCCESS) { 2602 | printf("vkBeginCommandBuffer returned error.\n"); 2603 | return; 2604 | } 2605 | 2606 | VkImageMemoryBarrier imageMemoryBarrier; 2607 | imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 2608 | imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 2609 | imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 2610 | imageMemoryBarrier.pNext = NULL; 2611 | imageMemoryBarrier.image = engine->swapChainImages[currentBuffer]; 2612 | imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 2613 | imageMemoryBarrier.subresourceRange.baseMipLevel = 0; 2614 | imageMemoryBarrier.subresourceRange.levelCount = 1; 2615 | imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; 2616 | imageMemoryBarrier.subresourceRange.layerCount = 1; 2617 | imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 2618 | imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 2619 | imageMemoryBarrier.srcAccessMask = 0; 2620 | imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 2621 | VkPipelineStageFlags srcStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 2622 | VkPipelineStageFlags destStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 2623 | vkCmdPipelineBarrier(engine->renderCommandBuffer[0], srcStageFlags, destStageFlags, 0, 2624 | 0, NULL, 0, NULL, 1, &imageMemoryBarrier); 2625 | 2626 | vkCmdBeginRenderPass(engine->renderCommandBuffer[0], &renderPassBeginInfo, 2627 | VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 2628 | 2629 | if (engine->splitscreen) { 2630 | //Draw using traditional depth dependent transparency: 2631 | // LOGI("Trad: Executing secondaryCommandBuffer %d", currentBuffer); 2632 | vkCmdExecuteCommands(engine->renderCommandBuffer[0], 1, 2633 | &engine->secondaryCommandBuffers[currentBuffer]); 2634 | } 2635 | 2636 | for (int layer = 0; layer < engine->layerCount; layer++) { 2637 | int cmdBuffIndex = engine->swapchainImageCount + layer * engine->swapchainImageCount*2 + currentBuffer; 2638 | //Peel 2639 | vkCmdNextSubpass(engine->renderCommandBuffer[0], 2640 | VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 2641 | // LOGI("Peel: Executing secondaryCommandBuffer %d", cmdBuffIndex); 2642 | vkCmdExecuteCommands(engine->renderCommandBuffer[0], 1, 2643 | &engine->secondaryCommandBuffers[cmdBuffIndex]); 2644 | //Blend 2645 | vkCmdNextSubpass(engine->renderCommandBuffer[0], 2646 | VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 2647 | if (engine->displayLayer < 0 || layer==engine->displayLayer) 2648 | { 2649 | // LOGI("Blend: Executing secondaryCommandBuffer %d", cmdBuffIndex + engine->swapchainImageCount); 2650 | vkCmdExecuteCommands(engine->renderCommandBuffer[0], 1, 2651 | &engine->secondaryCommandBuffers[cmdBuffIndex + engine->swapchainImageCount]); 2652 | } 2653 | } 2654 | 2655 | vkCmdEndRenderPass(engine->renderCommandBuffer[0]); 2656 | 2657 | VkImageMemoryBarrier prePresentBarrier; 2658 | prePresentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 2659 | prePresentBarrier.pNext = NULL; 2660 | prePresentBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 2661 | prePresentBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; 2662 | prePresentBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 2663 | prePresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 2664 | prePresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 2665 | prePresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 2666 | prePresentBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 2667 | prePresentBarrier.subresourceRange.baseMipLevel = 0; 2668 | prePresentBarrier.subresourceRange.levelCount = 1; 2669 | prePresentBarrier.subresourceRange.baseArrayLayer = 0; 2670 | prePresentBarrier.subresourceRange.layerCount = 1; 2671 | prePresentBarrier.image = engine->swapChainImages[currentBuffer]; 2672 | vkCmdPipelineBarrier(engine->renderCommandBuffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 2673 | VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0, 2674 | NULL, 1, &prePresentBarrier); 2675 | 2676 | res = vkEndCommandBuffer(engine->renderCommandBuffer[0]); 2677 | if (res != VK_SUCCESS) { 2678 | LOGE ("vkEndCommandBuffer returned error %d.\n", res); 2679 | return; 2680 | } 2681 | 2682 | VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; 2683 | VkSubmitInfo submitInfo[2]; 2684 | submitInfo[0].pNext = NULL; 2685 | submitInfo[0].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 2686 | submitInfo[0].waitSemaphoreCount = 1; //Only the first command buffer should wait on a semaphore, 2687 | submitInfo[0].pWaitSemaphores = &engine->presentCompleteSemaphore; 2688 | submitInfo[0].pWaitDstStageMask = &pipe_stage_flags; 2689 | submitInfo[0].commandBufferCount = 1; 2690 | submitInfo[0].pCommandBuffers = engine->renderCommandBuffer; 2691 | submitInfo[0].signalSemaphoreCount = 0; 2692 | submitInfo[0].pSignalSemaphores = NULL; 2693 | 2694 | 2695 | res = vkQueueSubmit(engine->queue, 1, submitInfo, VK_NULL_HANDLE); 2696 | if (res != VK_SUCCESS) { 2697 | LOGE ("vkQueueSubmit returned error %d.\n", res); 2698 | return; 2699 | } 2700 | 2701 | // LOGI ("Waiting.\n"); 2702 | 2703 | res = vkQueueWaitIdle(engine->queue); 2704 | if (res != VK_SUCCESS) { 2705 | LOGE ("vkQueueSubmit returned error %d.\n", res); 2706 | return; 2707 | } 2708 | 2709 | // LOGI ("Presentng.\n"); 2710 | 2711 | VkPresentInfoKHR presentInfo; 2712 | presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 2713 | presentInfo.pNext = NULL; 2714 | presentInfo.swapchainCount = 1; 2715 | presentInfo.pSwapchains = &engine->swapchain; 2716 | presentInfo.pImageIndices = ¤tBuffer; 2717 | presentInfo.pWaitSemaphores = NULL; 2718 | presentInfo.waitSemaphoreCount = 0; 2719 | presentInfo.pResults = NULL; 2720 | res = vkQueuePresentKHR(engine->queue, &presentInfo); 2721 | if (res != VK_SUCCESS) { 2722 | LOGE ("vkQueuePresentKHR returned error %d.\n", res); 2723 | return; 2724 | } 2725 | 2726 | // LOGI ("Finished frame %d.\n", engine->frame); 2727 | engine->frame++; 2728 | if (engine->frame % 120 == 0) { 2729 | float frameRate = (120.0f/((float)(engine->frameRateClock->getTimeMilliseconds())/1000.0f)); 2730 | LOGI("Framerate: %f", frameRate); 2731 | engine->frameRateClock->reset(); 2732 | } 2733 | } 2734 | 2735 | /** 2736 | * Tear down the EGL context currently associated with the display. 2737 | */ 2738 | static void engine_term_display(struct engine* engine) { 2739 | LOGI("engine_term_display"); 2740 | // vkDestroyImageView(engine->vkDevice, engine->depthView, NULL); 2741 | // vkDestroyImage(engine->vkDevice, engine->depthImage, NULL); 2742 | // vkFreeMemory(engine->vkDevice, engine->depthMemory, NULL); 2743 | // if (engine->display != EGL_NO_DISPLAY) { 2744 | // eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 2745 | // if (engine->context != EGL_NO_CONTEXT) { 2746 | // eglDestroyContext(engine->display, engine->context); 2747 | // } 2748 | // if (engine->surface != EGL_NO_SURFACE) { 2749 | // eglDestroySurface(engine->display, engine->surface); 2750 | // } 2751 | // eglTerminate(engine->display); 2752 | // } 2753 | // engine->animating = 0; 2754 | // engine->display = EGL_NO_DISPLAY; 2755 | // engine->context = EGL_NO_CONTEXT; 2756 | // engine->surface = EGL_NO_SURFACE; 2757 | } 2758 | 2759 | #ifdef __ANDROID__ 2760 | /** 2761 | * Process the next input event. 2762 | */ 2763 | static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { 2764 | struct engine* engine = (struct engine*)app->userData; 2765 | if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { 2766 | LOGI("engine_handle_input"); 2767 | engine->animating = 1; 2768 | engine->state.x = AMotionEvent_getX(event, 0); 2769 | engine->state.y = AMotionEvent_getY(event, 0); 2770 | return 1; 2771 | } 2772 | else if( AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY ) { 2773 | int32_t keycode = AKeyEvent_getKeyCode(event); 2774 | int32_t repeatCount = AKeyEvent_getRepeatCount(event); 2775 | int32_t action = AKeyEvent_getAction(event); 2776 | int32_t metaState = AKeyEvent_getMetaState(event); 2777 | int32_t devId = AInputEvent_getDeviceId(event); 2778 | // LOGI("Key pressed %d, %s", keycode, (action == AKEY_EVENT_ACTION_DOWN) ? "Down" : "Up"); 2779 | if (keycode==AKEYCODE_DPAD_CENTER && action == AKEY_EVENT_ACTION_DOWN) { 2780 | engine->splitscreen = !engine->splitscreen; 2781 | engine->rebuildCommadBuffersRequired=true; 2782 | } 2783 | if ((keycode==AKEYCODE_DPAD_DOWN || keycode==AKEYCODE_DPAD_UP) && action == AKEY_EVENT_ACTION_DOWN) { 2784 | if (keycode==AKEYCODE_DPAD_UP) 2785 | engine->layerCount++; 2786 | else 2787 | engine->layerCount--; 2788 | if (engine->layerCount<1) 2789 | engine->layerCount=1; 2790 | else if (engine->layerCount>MAX_LAYERS) 2791 | engine->layerCount=MAX_LAYERS; 2792 | LOGI("Using %d layers", engine->layerCount); 2793 | } 2794 | // if ((keycode==AKEYCODE_DPAD_LEFT || keycode==AKEYCODE_DPAD_RIGHT) && action == AKEY_EVENT_ACTION_DOWN) { 2795 | // if (keycode == AKEYCODE_DPAD_RIGHT) 2796 | // engine->boxCount+=50; 2797 | // else 2798 | // engine->boxCount-=50; 2799 | // if (engine->boxCount<50) 2800 | // engine->boxCount=50; 2801 | // else if (engine->boxCount>MAX_BOXES) 2802 | // engine->boxCount=MAX_BOXES; 2803 | // LOGI("Drawing %d boxes", engine->boxCount); 2804 | // engine->rebuildCommadBuffersRequired=true; 2805 | // } 2806 | if ((keycode==AKEYCODE_DPAD_LEFT || keycode==AKEYCODE_DPAD_RIGHT) && action == AKEY_EVENT_ACTION_DOWN) { 2807 | if (keycode == AKEYCODE_DPAD_RIGHT) 2808 | engine->displayLayer++; 2809 | else 2810 | engine->displayLayer--; 2811 | if (engine->displayLayer<0) 2812 | { 2813 | engine->displayLayer=-1; 2814 | LOGI("Displaying all layers"); 2815 | } 2816 | else 2817 | LOGI("Displaying only layer %d", engine->displayLayer); 2818 | } 2819 | if (keycode==AKEYCODE_BACK && action == AKEY_EVENT_ACTION_UP) { 2820 | ANativeActivity_finish(engine->app->activity); 2821 | } 2822 | return 1; 2823 | } 2824 | return 0; 2825 | } 2826 | 2827 | /** 2828 | * Process the next main command. 2829 | */ 2830 | static void engine_handle_cmd(struct android_app* app, int32_t cmd) { 2831 | struct engine* engine = (struct engine*)app->userData; 2832 | switch (cmd) { 2833 | case APP_CMD_SAVE_STATE: 2834 | // The system has asked us to save our current state. Do so. 2835 | engine->app->savedState = malloc(sizeof(struct saved_state)); 2836 | *((struct saved_state*)engine->app->savedState) = engine->state; 2837 | engine->app->savedStateSize = sizeof(struct saved_state); 2838 | break; 2839 | case APP_CMD_INIT_WINDOW: 2840 | // The window is being shown, get it ready. 2841 | if (engine->app->window != NULL) { 2842 | engine_init_display(engine); 2843 | engine_draw_frame(engine); 2844 | } 2845 | break; 2846 | case APP_CMD_TERM_WINDOW: 2847 | // The window is being hidden or closed, clean it up. 2848 | engine_term_display(engine); 2849 | break; 2850 | case APP_CMD_GAINED_FOCUS: 2851 | LOGI("APP_CMD_GAINED_FOCUS"); 2852 | // When our app gains focus, we start monitoring the accelerometer. 2853 | // if (engine->accelerometerSensor != NULL) { 2854 | // ASensorEventQueue_enableSensor(engine->sensorEventQueue, 2855 | // engine->accelerometerSensor); 2856 | // // We'd like to get 60 events per second (in us). 2857 | // ASensorEventQueue_setEventRate(engine->sensorEventQueue, 2858 | // engine->accelerometerSensor, 2859 | // (1000L/60)*1000); 2860 | // } 2861 | engine->animating = 1; 2862 | break; 2863 | case APP_CMD_LOST_FOCUS: 2864 | // When our app loses focus, we stop monitoring the accelerometer. 2865 | // This is to avoid consuming battery while not being used. 2866 | if (engine->accelerometerSensor != NULL) { 2867 | ASensorEventQueue_disableSensor(engine->sensorEventQueue, 2868 | engine->accelerometerSensor); 2869 | } 2870 | // Also stop animating. 2871 | LOGI("APP_CMD_LOST_FOCUS"); 2872 | engine->animating = 0; 2873 | engine_draw_frame(engine); 2874 | break; 2875 | } 2876 | } 2877 | 2878 | /** 2879 | * This is the main entry point of a native application that is using 2880 | * android_native_app_glue. It runs in its own thread, with its own 2881 | * event loop for receiving input events and doing other things. 2882 | */ 2883 | void android_main(struct android_app* state) { 2884 | struct engine engine; 2885 | 2886 | // Make sure glue isn't stripped. 2887 | app_dummy(); 2888 | 2889 | memset(&engine, 0, sizeof(engine)); 2890 | state->userData = &engine; 2891 | state->onAppCmd = engine_handle_cmd; 2892 | state->onInputEvent = engine_handle_input; 2893 | engine.app = state; 2894 | engine.animating=1; 2895 | engine.vulkanSetupOK=false; 2896 | engine.frameRateClock=new btClock; 2897 | engine.frameRateClock->reset(); 2898 | engine.simulation = new Simulation; 2899 | engine.simulation->step(); 2900 | engine.splitscreen = true; 2901 | engine.rebuildCommadBuffersRequired = false; 2902 | engine.displayLayer=-1; 2903 | engine.layerCount=4; 2904 | engine.boxCount=100; 2905 | 2906 | 2907 | // Prepare to monitor accelerometer 2908 | // engine.sensorManager = ASensorManager_getInstance(); 2909 | // engine.accelerometerSensor = ASensorManager_getDefaultSensor( 2910 | // engine.sensorManager, 2911 | // ASENSOR_TYPE_ACCELEROMETER); 2912 | // engine.sensorEventQueue = ASensorManager_createEventQueue( 2913 | // engine.sensorManager, 2914 | // state->looper, LOOPER_ID_USER, 2915 | // NULL, NULL); 2916 | 2917 | if (state->savedState != NULL) { 2918 | // We are starting with a previous saved state; restore from it. 2919 | engine.state = *(struct saved_state*)state->savedState; 2920 | } 2921 | 2922 | // loop waiting for stuff to do. 2923 | 2924 | while (1) { 2925 | // Read all pending events. 2926 | int ident; 2927 | int events; 2928 | struct android_poll_source* source; 2929 | 2930 | // If not animating, we will block forever waiting for events. 2931 | // If animating, we loop until all events are read, then continue 2932 | // to draw the next frame of animation. 2933 | // LOGI("Polling. animating: %s", engine.animating ? "true" : "false"); 2934 | while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, 2935 | (void**)&source)) >= 0) { 2936 | // LOGI("Poll returned. animating: %s", engine.animating ? "true" : "false"); 2937 | 2938 | // Process this event. 2939 | if (source != NULL) { 2940 | source->process(state, source); 2941 | } 2942 | 2943 | // If a sensor has data, process it now. 2944 | // if (ident == LOOPER_ID_USER) { 2945 | // if (engine.accelerometerSensor != NULL) { 2946 | // ASensorEvent event; 2947 | // while (ASensorEventQueue_getEvents(engine.sensorEventQueue, 2948 | // &event, 1) > 0) { 2949 | // LOGI("accelerometer: x=%f y=%f z=%f", 2950 | // event.acceleration.x, event.acceleration.y, 2951 | // event.acceleration.z); 2952 | // } 2953 | // } 2954 | // } 2955 | 2956 | // Check if we are exiting. 2957 | if (state->destroyRequested != 0) { 2958 | engine_term_display(&engine); 2959 | return; 2960 | } 2961 | } 2962 | // LOGI("Cont"); 2963 | 2964 | if (engine.animating) { 2965 | // Done with events; draw next animation frame. 2966 | engine.state.angle += .01f; 2967 | if (engine.state.angle > 1) { 2968 | engine.state.angle = 0; 2969 | } 2970 | 2971 | // Drawing is throttled to the screen update rate, so there 2972 | // is no need to do timing here. 2973 | // LOGI("calling engine_draw_frame"); 2974 | engine_draw_frame(&engine); 2975 | engine.simulation->step(); 2976 | } 2977 | } 2978 | } 2979 | #endif 2980 | //END_INCLUDE(all) 2981 | 2982 | #ifndef __ANDROID__ 2983 | int main() 2984 | { 2985 | struct engine engine; 2986 | engine.width=800; 2987 | engine.height=600; 2988 | // engine.width=1920; 2989 | // engine.height=1080; 2990 | // engine.width=4096; 2991 | // engine.height=2160; 2992 | engine.animating=1; 2993 | engine.vulkanSetupOK=false; 2994 | engine.frameRateClock=new btClock; 2995 | engine.frameRateClock->reset(); 2996 | engine.simulation = new Simulation; 2997 | engine.simulation->step(); 2998 | engine.splitscreen = false; 2999 | engine.rebuildCommadBuffersRequired = false; 3000 | engine.displayLayer=-1; 3001 | engine.layerCount=4; 3002 | engine.boxCount=100; 3003 | 3004 | //Setup XCB Connection: 3005 | const xcb_setup_t *setup; 3006 | xcb_screen_iterator_t iter; 3007 | int scr; 3008 | engine.xcbConnection= xcb_connect(NULL, &scr); 3009 | if (engine.xcbConnection == NULL) { 3010 | printf("Cannot find a compatible Vulkan ICD.\n"); 3011 | return -1; 3012 | } 3013 | 3014 | setup = xcb_get_setup(engine.xcbConnection); 3015 | iter = xcb_setup_roots_iterator(setup); 3016 | while (scr-- > 0) 3017 | xcb_screen_next(&iter); 3018 | xcb_screen_t *screen = iter.data; 3019 | 3020 | //Create an xcb window: 3021 | uint32_t value_mask, value_list[32]; 3022 | 3023 | engine.window = xcb_generate_id(engine.xcbConnection); 3024 | 3025 | value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; 3026 | value_list[0] = screen->black_pixel; 3027 | value_list[1] = XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS; 3028 | 3029 | xcb_create_window(engine.xcbConnection, XCB_COPY_FROM_PARENT, engine.window, 3030 | screen->root, 0, 0, engine.width, engine.height, 0, 3031 | XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, 3032 | value_mask, value_list); 3033 | 3034 | //We want to know when the user presses the close button: 3035 | xcb_intern_atom_cookie_t cookie = xcb_intern_atom(engine.xcbConnection, 1, 12, "WM_PROTOCOLS"); 3036 | xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(engine.xcbConnection, cookie, 0); 3037 | 3038 | xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(engine.xcbConnection, 0, 16, "WM_DELETE_WINDOW"); 3039 | xcb_intern_atom_reply_t* delete_window_reply = xcb_intern_atom_reply(engine.xcbConnection, cookie2, 0); 3040 | 3041 | xcb_change_property(engine.xcbConnection, XCB_PROP_MODE_REPLACE, engine.window, (*reply).atom, 4, 32, 1, &(*delete_window_reply).atom); 3042 | char const* windowTitle="Vulkan depth peel demo"; 3043 | xcb_change_property(engine.xcbConnection, XCB_PROP_MODE_REPLACE, engine.window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(windowTitle), windowTitle); 3044 | 3045 | //This demo does not include the code necessary to handle resizing the framebuffers 3046 | //so lets ask the window manager to disable window resizing. 3047 | xcb_size_hints_t hints; 3048 | hints.flags=0; 3049 | xcb_icccm_size_hints_set_min_size(&hints, engine.width, engine.height); 3050 | xcb_icccm_size_hints_set_max_size(&hints, engine.width, engine.height); 3051 | xcb_icccm_set_wm_size_hints(engine.xcbConnection, engine.window, XCB_ATOM_WM_NORMAL_HINTS, &hints); 3052 | 3053 | xcb_map_window(engine.xcbConnection, engine.window); 3054 | xcb_flush(engine.xcbConnection); 3055 | 3056 | //Wait until the window has been exposed: 3057 | xcb_generic_event_t *e; 3058 | while ((e = xcb_wait_for_event(engine.xcbConnection))) { 3059 | if ((e->response_type & ~0x80) == XCB_EXPOSE) 3060 | break; 3061 | } 3062 | 3063 | engine_init_display(&engine); 3064 | bool done=false; 3065 | // for (int i=0; i<4; i++) { 3066 | while (!(done==1)) { 3067 | while (1==1) { 3068 | e = xcb_poll_for_event(engine.xcbConnection); 3069 | if (!e) break; 3070 | printf("Event: "); 3071 | switch(e->response_type & ~0x80) 3072 | { 3073 | case XCB_EXPOSE: 3074 | break; 3075 | case XCB_EVENT_MASK_BUTTON_PRESS: 3076 | done=1; 3077 | break; 3078 | case XCB_KEY_PRESS: 3079 | { 3080 | xcb_keycode_t key = ((xcb_key_press_event_t*)e)->detail; 3081 | // LOGI("Key pressed %d", key); 3082 | if (key == 9) 3083 | done=1; 3084 | if (key == 25 || key == 39) 3085 | { 3086 | if (key == 25) 3087 | engine.displayLayer++; 3088 | else 3089 | engine.displayLayer--; 3090 | if (engine.displayLayer<0) 3091 | { 3092 | engine.displayLayer=-1; 3093 | LOGI("Displaying all layers"); 3094 | } 3095 | else 3096 | LOGI("Displaying only layer %d", engine.displayLayer); 3097 | } 3098 | else if (key == 111 || key == 116) 3099 | { 3100 | if (key == 111) 3101 | engine.layerCount++; 3102 | else 3103 | engine.layerCount--; 3104 | if (engine.layerCount<1) 3105 | engine.layerCount=1; 3106 | else if (engine.layerCount>MAX_LAYERS) 3107 | engine.layerCount=MAX_LAYERS; 3108 | LOGI("Using %d layers", engine.layerCount); 3109 | } 3110 | else if (key == 113 || key == 114) 3111 | { 3112 | if (key == 114) 3113 | engine.boxCount+=50; 3114 | else 3115 | engine.boxCount-=50; 3116 | if (engine.boxCount<50) 3117 | engine.boxCount=50; 3118 | else if (engine.boxCount>MAX_BOXES) 3119 | engine.boxCount=MAX_BOXES; 3120 | LOGI("Drawing %d boxes", engine.boxCount); 3121 | engine.rebuildCommadBuffersRequired=true; 3122 | } 3123 | else if (key == 33) 3124 | engine.simulation->paused= !engine.simulation->paused; 3125 | else if(key == 65) 3126 | { 3127 | engine.splitscreen = !engine.splitscreen; 3128 | engine.rebuildCommadBuffersRequired=true; 3129 | } 3130 | } 3131 | break; 3132 | default: 3133 | printf ("Unknown XCB Event %d\n", (e->response_type & ~0x80)); 3134 | } 3135 | if ((e->response_type & ~0x80)==XCB_CLIENT_MESSAGE) 3136 | { 3137 | printf("XCB_CLIENT_MESSAGE"); 3138 | if(((xcb_client_message_event_t*)e)->data.data32[0] == delete_window_reply->atom) 3139 | done=1; 3140 | } 3141 | free(e); 3142 | } 3143 | if (done) 3144 | printf("done\n"); 3145 | engine_draw_frame(&engine); 3146 | engine.simulation->step(); 3147 | } 3148 | return 0; 3149 | } 3150 | 3151 | #endif 3152 | -------------------------------------------------------------------------------- /app/src/main/jni/matrix.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * Simulates desktop's glRotatef. The matrix is returned in column-major 6 | * order. 7 | */ 8 | void rotate_matrix(double angle, double x, double y, double z, float *R) { 9 | double radians, c, s, c1, u[3], length; 10 | int i, j; 11 | 12 | radians = (angle * M_PI) / 180.0; 13 | 14 | c = cos(radians); 15 | s = sin(radians); 16 | 17 | c1 = 1.0 - cos(radians); 18 | 19 | length = sqrt(x * x + y * y + z * z); 20 | 21 | u[0] = x / length; 22 | u[1] = y / length; 23 | u[2] = z / length; 24 | 25 | for (i = 0; i < 16; i++) { 26 | R[i] = 0.0; 27 | } 28 | 29 | R[15] = 1.0; 30 | 31 | for (i = 0; i < 3; i++) { 32 | R[i * 4 + (i + 1) % 3] = u[(i + 2) % 3] * s; 33 | R[i * 4 + (i + 2) % 3] = -u[(i + 1) % 3] * s; 34 | } 35 | 36 | for (i = 0; i < 3; i++) { 37 | for (j = 0; j < 3; j++) { 38 | R[i * 4 + j] += c1 * u[i] * u[j] + (i == j ? c : 0.0); 39 | } 40 | } 41 | } 42 | 43 | /* 44 | * Simulates gluPerspectiveMatrix 45 | */ 46 | void perspective_matrix(double fovy, double aspect, double znear, double zfar, float *P) { 47 | int i; 48 | double f; 49 | 50 | f = 1.0/tan(fovy * 0.5); 51 | 52 | for (i = 0; i < 16; i++) { 53 | P[i] = 0.0; 54 | } 55 | 56 | P[0] = f / aspect; 57 | P[5] = f; 58 | P[10] = (znear + zfar) / (znear - zfar); 59 | P[11] = -1.0; 60 | P[14] = (2.0 * znear * zfar) / (znear - zfar); 61 | P[15] = 0.0; 62 | } 63 | /* 64 | * Multiplies A by B and writes out to C. All matrices are 4x4 and column 65 | * major. In-place multiplication is supported. 66 | */ 67 | void multiply_matrix(float *A, float *B, float *C) { 68 | int i, j, k; 69 | float aTmp[16]; 70 | 71 | for (i = 0; i < 4; i++) { 72 | for (j = 0; j < 4; j++) { 73 | aTmp[j * 4 + i] = 0.0; 74 | 75 | for (k = 0; k < 4; k++) { 76 | aTmp[j * 4 + i] += A[k * 4 + i] * B[j * 4 + k]; 77 | } 78 | } 79 | } 80 | 81 | memcpy(C, aTmp, sizeof(aTmp)); 82 | } 83 | 84 | void identity_matrix(float *matrix) { 85 | float aTmp[16]={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; 86 | memcpy(matrix, aTmp, sizeof(aTmp)); 87 | } 88 | 89 | void translate_matrix(double x, double y, double z, float *matrix) { 90 | identity_matrix(matrix); 91 | matrix[12]=x; 92 | matrix[13]=y; 93 | matrix[14]=z; 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/jni/models.h: -------------------------------------------------------------------------------- 1 | 2 | struct Vertex{ 3 | float posX, posY, posZ, posW; // Position data 4 | float r, g, b, a; // Color 5 | }; 6 | 7 | #define XYZ1(_x_, _y_, _z_) (_x_), (_y_), (_z_), 1.f 8 | #define XYZp5(_x_, _y_, _z_) (_x_), (_y_), (_z_), 0.6 9 | 10 | static const struct Vertex vertexData[] = { 11 | {XYZ1(-1, -1, -1), XYZp5(0.f, 0.f, 0.f)}, 12 | {XYZ1(1, -1, -1), XYZp5(1.f, 0.f, 0.f)}, 13 | {XYZ1(-1, 1, -1), XYZp5(0.f, 1.f, 0.f)}, 14 | {XYZ1(-1, 1, -1), XYZp5(0.f, 1.f, 0.f)}, 15 | {XYZ1(1, -1, -1), XYZp5(1.f, 0.f, 0.f)}, 16 | {XYZ1(1, 1, -1), XYZp5(1.f, 1.f, 0.f)}, 17 | 18 | {XYZ1(-1, -1, 1), XYZp5(0.f, 0.f, 1.f)}, 19 | {XYZ1(-1, 1, 1), XYZp5(0.f, 1.f, 1.f)}, 20 | {XYZ1(1, -1, 1), XYZp5(1.f, 0.f, 1.f)}, 21 | {XYZ1(1, -1, 1), XYZp5(1.f, 0.f, 1.f)}, 22 | {XYZ1(-1, 1, 1), XYZp5(0.f, 1.f, 1.f)}, 23 | {XYZ1(1, 1, 1), XYZp5(1.f, 1.f, 1.f)}, 24 | 25 | {XYZ1(1, 1, 1), XYZp5(1.f, 1.f, 1.f)}, 26 | {XYZ1(1, 1, -1), XYZp5(1.f, 1.f, 0.f)}, 27 | {XYZ1(1, -1, 1), XYZp5(1.f, 0.f, 1.f)}, 28 | {XYZ1(1, -1, 1), XYZp5(1.f, 0.f, 1.f)}, 29 | {XYZ1(1, 1, -1), XYZp5(1.f, 1.f, 0.f)}, 30 | {XYZ1(1, -1, -1), XYZp5(1.f, 0.f, 0.f)}, 31 | 32 | {XYZ1(-1, 1, 1), XYZp5(0.f, 1.f, 1.f)}, 33 | {XYZ1(-1, -1, 1), XYZp5(0.f, 0.f, 1.f)}, 34 | {XYZ1(-1, 1, -1), XYZp5(0.f, 1.f, 0.f)}, 35 | {XYZ1(-1, 1, -1), XYZp5(0.f, 1.f, 0.f)}, 36 | {XYZ1(-1, -1, 1), XYZp5(0.f, 0.f, 1.f)}, 37 | {XYZ1(-1, -1, -1), XYZp5(0.f, 0.f, 0.f)}, 38 | 39 | {XYZ1(1, 1, 1), XYZp5(1.f, 1.f, 1.f)}, 40 | {XYZ1(-1, 1, 1), XYZp5(0.f, 1.f, 1.f)}, 41 | {XYZ1(1, 1, -1), XYZp5(1.f, 1.f, 0.f)}, 42 | {XYZ1(1, 1, -1), XYZp5(1.f, 1.f, 0.f)}, 43 | {XYZ1(-1, 1, 1), XYZp5(0.f, 1.f, 1.f)}, 44 | {XYZ1(-1, 1, -1), XYZp5(0.f, 1.f, 0.f)}, 45 | 46 | {XYZ1(1, -1, 1), XYZp5(1.f, 0.f, 1.f)}, 47 | {XYZ1(1, -1, -1), XYZp5(1.f, 0.f, 0.f)}, 48 | {XYZ1(-1, -1, 1), XYZp5(0.f, 0.f, 1.f)}, 49 | {XYZ1(-1, -1, 1), XYZp5(0.f, 0.f, 1.f)}, 50 | {XYZ1(1, -1, -1), XYZp5(1.f, 0.f, 0.f)}, 51 | {XYZ1(-1, -1, -1), XYZp5(0.f, 0.f, 0.f)}, 52 | }; 53 | -------------------------------------------------------------------------------- /app/src/main/jni/stdredirect.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static int stdoutpfd[2]; 7 | static int stderrpfd[2]; 8 | static pthread_t stdoutthr; 9 | static pthread_t stderrthr; 10 | 11 | static void *stdout_log_thread_main(void*) 12 | { 13 | ssize_t bytesRead; 14 | char buf[128]; 15 | while((bytesRead = read(stdoutpfd[0], buf, sizeof buf - 1)) > 0) 16 | { 17 | buf[bytesRead] = '\0'; 18 | __android_log_write(ANDROID_LOG_DEBUG, "native-activity-stdout", buf); 19 | } 20 | return 0; 21 | } 22 | 23 | static void *stderr_log_thread_main(void*) 24 | { 25 | ssize_t bytesRead; 26 | char buf[128]; 27 | while((bytesRead = read(stderrpfd[0], buf, sizeof buf - 1)) > 0) 28 | { 29 | buf[bytesRead] = '\0'; 30 | __android_log_write(ANDROID_LOG_ERROR, "native-activity-stderr", buf); 31 | } 32 | return 0; 33 | } 34 | 35 | void redirectStdIO() 36 | { 37 | 38 | pipe(stdoutpfd); 39 | pipe(stderrpfd); 40 | dup2(stdoutpfd[1], STDOUT_FILENO); 41 | dup2(stderrpfd[1], STDERR_FILENO); 42 | 43 | setvbuf(stdout, 0, _IONBF, 0); 44 | setvbuf(stderr, 0, _IONBF, 0); 45 | 46 | if(pthread_create(&stdoutthr, 0, stdout_log_thread_main, 0) == -1) 47 | return; 48 | pthread_detach(stdoutthr); 49 | printf("Stdout Redirected"); 50 | 51 | if(pthread_create(&stderrthr, 0, stderr_log_thread_main, 0) == -1) 52 | return; 53 | pthread_detach(stderrthr); 54 | fprintf(stderr, "Stderr Redirected"); 55 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/res/drawable-xhdpi/banner.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Vulkan Depth Peel 4 | 5 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle-experimental:0.7.0' 8 | } 9 | } 10 | 11 | allprojects { 12 | repositories { 13 | jcenter() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip 7 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file is automatically generated by Android Studio. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | # 7 | # Location of the SDK. This is only used by Gradle. 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | #Fri May 20 15:08:46 BST 2016 11 | ndk.dir=/home/matt/android/adt-bundle-linux-x86_64-20140624/android-ndk-r12-beta2 12 | sdk.dir=/home/matt/android/adt-bundle-linux-x86_64-20140624/sdk 13 | -------------------------------------------------------------------------------- /nativeactivity/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.model.library' 2 | 3 | def ndkDir = System.getenv("ANDROID_NDK_HOME") 4 | def propertiesFile = project.rootProject.file('local.properties') 5 | if (propertiesFile.exists()) { 6 | Properties properties = new Properties() 7 | properties.load(propertiesFile.newDataInputStream()) 8 | ndkDir = properties.getProperty('ndk.dir') 9 | } 10 | 11 | model { 12 | android { 13 | compileSdkVersion = 23 14 | buildToolsVersion = "23.0.2" 15 | defaultConfig.with { 16 | minSdkVersion.apiLevel = 9 17 | targetSdkVersion.apiLevel = 23 18 | versionCode = 1 19 | versionName = "0.0.1" 20 | } 21 | ndk { 22 | platformVersion = 24 23 | moduleName = 'native-activity' 24 | ldLibs.addAll(['log', 'android']) 25 | ldFlags.add("-c") 26 | } 27 | sources { 28 | main { 29 | jni { 30 | source { 31 | srcDir "${ndkDir}/sources/android/native_app_glue" 32 | } 33 | exportedHeaders { 34 | srcDir "${ndkDir}/sources/android/native_app_glue" 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /nativeactivity/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | include ':nativeactivity' 3 | -------------------------------------------------------------------------------- /shaders/blend/frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/shaders/blend/frag.spv -------------------------------------------------------------------------------- /shaders/blend/test.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | 5 | //layout (location = 0) in vec4 color; 6 | layout (input_attachment_index=0, set=2, binding=0) uniform subpassInput subpass; 7 | layout (location = 0) out vec4 outColor; 8 | 9 | void main() { 10 | vec4 color = subpassLoad(subpass); 11 | outColor = vec4(color.r*color.a, color.g*color.a, color.b*color.a, color.a); 12 | // outColor = color; 13 | } 14 | -------------------------------------------------------------------------------- /shaders/blend/test.vert: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | 5 | layout (set = 0, binding = 0) uniform bufferVals { 6 | mat4 mv; 7 | } myBufferVals; 8 | 9 | layout (std140, set = 1, binding = 0) uniform bufferVals1 { 10 | mat4 p; 11 | } myBufferVals1; 12 | 13 | layout (location = 0) in vec4 pos; 14 | //layout (location = 1) in vec4 inColor; 15 | //layout (location = 0) out vec4 outColor; 16 | 17 | out gl_PerVertex { 18 | vec4 gl_Position; 19 | }; 20 | 21 | void main() { 22 | //outColor = inColor; 23 | mat4 mvp = myBufferVals1.p * myBufferVals.mv; 24 | gl_Position = mvp * pos; 25 | 26 | // GL->VK conventions 27 | gl_Position.y = -gl_Position.y; 28 | gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0; 29 | } 30 | -------------------------------------------------------------------------------- /shaders/blend/vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/shaders/blend/vert.spv -------------------------------------------------------------------------------- /shaders/peel/frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/shaders/peel/frag.spv -------------------------------------------------------------------------------- /shaders/peel/test.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | 5 | layout (input_attachment_index=0, set=2, binding=0) uniform subpassInput subpass; 6 | layout (location = 0) in vec4 color; 7 | layout (location = 0) out vec4 outColor; 8 | 9 | void main() { 10 | float depth = subpassLoad(subpass).r; 11 | if (gl_FragCoord.z <= depth) 12 | discard; 13 | outColor = color; 14 | } 15 | -------------------------------------------------------------------------------- /shaders/peel/test.vert: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | 5 | layout (set = 0, binding = 0) uniform bufferVals { 6 | mat4 mv; 7 | } myBufferVals; 8 | 9 | layout (std140, set = 1, binding = 0) uniform bufferVals1 { 10 | mat4 p; 11 | } myBufferVals1; 12 | 13 | layout (location = 0) in vec4 pos; 14 | layout (location = 1) in vec4 inColor; 15 | layout (location = 0) out vec4 outColor; 16 | 17 | out gl_PerVertex { 18 | vec4 gl_Position; 19 | }; 20 | 21 | void main() { 22 | outColor = inColor; 23 | mat4 mvp = myBufferVals1.p * myBufferVals.mv; 24 | gl_Position = mvp * pos; 25 | 26 | // GL->VK conventions 27 | gl_Position.y = -gl_Position.y; 28 | gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0; 29 | } 30 | -------------------------------------------------------------------------------- /shaders/peel/vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/shaders/peel/vert.spv -------------------------------------------------------------------------------- /shaders/trad/frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/shaders/trad/frag.spv -------------------------------------------------------------------------------- /shaders/trad/test.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | 5 | layout (location = 0) in vec4 color; 6 | layout (location = 0) out vec4 outColor; 7 | 8 | void main() { 9 | outColor = color; 10 | } -------------------------------------------------------------------------------- /shaders/trad/test.vert: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | 5 | layout (set = 0, binding = 0) uniform bufferVals { 6 | mat4 mv; 7 | } myBufferVals; 8 | 9 | layout (std140, set = 1, binding = 0) uniform bufferVals1 { 10 | mat4 p; 11 | } myBufferVals1; 12 | 13 | layout (location = 0) in vec4 pos; 14 | layout (location = 1) in vec4 inColor; 15 | layout (location = 0) out vec4 outColor; 16 | 17 | out gl_PerVertex { 18 | vec4 gl_Position; 19 | }; 20 | 21 | void main() { 22 | outColor = inColor; 23 | mat4 mvp = myBufferVals1.p * myBufferVals.mv; 24 | gl_Position = mvp * pos; 25 | 26 | // GL->VK conventions 27 | gl_Position.y = -gl_Position.y; 28 | gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0; 29 | } 30 | -------------------------------------------------------------------------------- /shaders/trad/vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openforeveryone/VulkanDepthPeel/56d5687ed448c0fcb8be84df962b507387a5f4f5/shaders/trad/vert.spv --------------------------------------------------------------------------------