├── 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 | 
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
--------------------------------------------------------------------------------