blob: dfedfdf026bb59475663ddec891ed47cefca2ea7 [file] [log] [blame]
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09001/*
2* Copyright (c) 2015-2016 The Khronos Group Inc.
3* Copyright (c) 2015-2016 Valve Corporation
4* Copyright (c) 2015-2016 LunarG, Inc.
5*
6* Licensed under the Apache License, Version 2.0 (the "License");
7* you may not use this file except in compliance with the License.
8* You may obtain a copy of the License at
9*
10* http://www.apache.org/licenses/LICENSE-2.0
11*
12* Unless required by applicable law or agreed to in writing, software
13* distributed under the License is distributed on an "AS IS" BASIS,
14* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15* See the License for the specific language governing permissions and
16* limitations under the License.
17*
18* Author: Chia-I Wu <olv@lunarg.com>
19* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
20* Author: Ian Elliott <ian@LunarG.com>
21* Author: Jon Ashburn <jon@lunarg.com>
22* Author: Gwan-gyeong Mun <elongbug@gmail.com>
23*/
Karl Schultze4dc75c2016-02-02 15:37:51 -070024
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -060025#define _GNU_SOURCE
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -060026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <stdbool.h>
30#include <assert.h>
Courtney Goeltzenleuchteraf1951c2015-12-01 14:11:38 -070031#include <signal.h>
Mun Gwan-gyeong22533892016-08-20 14:46:22 +090032#if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -060033#include <X11/Xutil.h>
34#endif
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -060035
Ian Elliott639ca472015-04-16 15:23:05 -060036#ifdef _WIN32
37#pragma comment(linker, "/subsystem:windows")
Ian Elliott639ca472015-04-16 15:23:05 -060038#define APP_NAME_STR_LEN 80
Ian Elliott639ca472015-04-16 15:23:05 -060039#endif // _WIN32
40
Cody Northrop8707a6e2016-04-26 19:59:19 -060041#ifdef ANDROID
42#include "vulkan_wrapper.h"
43#else
David Pinedoc5193c12015-11-06 12:54:48 -070044#include <vulkan/vulkan.h>
Cody Northrop8707a6e2016-04-26 19:59:19 -060045#endif
Ian Elliottb08e0d92015-11-20 11:55:46 -070046
David Pinedo541526f2015-11-24 09:00:24 -070047#include <vulkan/vk_sdk_platform.h>
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -060048#include "linmath.h"
49
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -060050#define DEMO_TEXTURE_COUNT 1
Ian Elliott44e33f72015-04-28 10:52:52 -060051#define APP_SHORT_NAME "cube"
52#define APP_LONG_NAME "The Vulkan Cube Demo Program"
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -060053
Courtney Goeltzenleuchter886f76c2015-07-06 17:46:11 -060054#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
55
Tony Barbourfdc2d352015-04-22 09:02:32 -060056#if defined(NDEBUG) && defined(__GNUC__)
57#define U_ASSERT_ONLY __attribute__((unused))
58#else
59#define U_ASSERT_ONLY
60#endif
61
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +090062#if defined(__GNUC__)
63#define UNUSED __attribute__((unused))
64#else
65#define UNUSED
66#endif
67
Ian Elliott07264132015-04-28 11:35:02 -060068#ifdef _WIN32
Tony Barbour602ca4f2016-09-12 14:02:43 -060069bool in_callback = false;
Karl Schultze4dc75c2016-02-02 15:37:51 -070070#define ERR_EXIT(err_msg, err_class) \
71 do { \
lenny-lunargfbe22392016-06-06 11:07:53 -060072 if (!demo->suppress_popups) \
73 MessageBox(NULL, err_msg, err_class, MB_OK); \
Karl Schultze4dc75c2016-02-02 15:37:51 -070074 exit(1); \
75 } while (0)
Ian Elliott07264132015-04-28 11:35:02 -060076
Michael Lentinec6cde4b2016-04-18 13:20:45 -050077#elif defined __ANDROID__
78#include <android/log.h>
79#define ERR_EXIT(err_msg, err_class) \
80 do { \
81 ((void)__android_log_print(ANDROID_LOG_INFO, "Cube", err_msg)); \
82 exit(1); \
83 } while (0)
84#else
Karl Schultze4dc75c2016-02-02 15:37:51 -070085#define ERR_EXIT(err_msg, err_class) \
86 do { \
87 printf(err_msg); \
88 fflush(stdout); \
89 exit(1); \
90 } while (0)
Michael Lentinec6cde4b2016-04-18 13:20:45 -050091#endif
Ian Elliott07264132015-04-28 11:35:02 -060092
Karl Schultze4dc75c2016-02-02 15:37:51 -070093#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
94 { \
95 demo->fp##entrypoint = \
96 (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
97 if (demo->fp##entrypoint == NULL) { \
98 ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint, \
99 "vkGetInstanceProcAddr Failure"); \
100 } \
101 }
Ian Elliottaaae5352015-07-06 14:27:58 -0600102
Jon Ashburn7d8342c2015-10-08 15:58:23 -0600103static PFN_vkGetDeviceProcAddr g_gdpa = NULL;
104
Karl Schultze4dc75c2016-02-02 15:37:51 -0700105#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
106 { \
107 if (!g_gdpa) \
108 g_gdpa = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr( \
109 demo->inst, "vkGetDeviceProcAddr"); \
110 demo->fp##entrypoint = \
111 (PFN_vk##entrypoint)g_gdpa(dev, "vk" #entrypoint); \
112 if (demo->fp##entrypoint == NULL) { \
113 ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint, \
114 "vkGetDeviceProcAddr Failure"); \
115 } \
116 }
Ian Elliott673898b2015-06-22 15:07:49 -0600117
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -0600118/*
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -0700119 * structure to track all objects related to a texture.
120 */
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600121struct texture_object {
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600122 VkSampler sampler;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -0700123
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600124 VkImage image;
125 VkImageLayout imageLayout;
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600126
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800127 VkMemoryAllocateInfo mem_alloc;
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -0500128 VkDeviceMemory mem;
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600129 VkImageView view;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -0700130 int32_t tex_width, tex_height;
131};
132
Karl Schultze4dc75c2016-02-02 15:37:51 -0700133static char *tex_files[] = {"lunarg.ppm"};
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600134
Karl Schultz0218c002016-03-22 17:06:13 -0600135static int validation_error = 0;
136
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600137struct vkcube_vs_uniform {
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600138 // Must start with MVP
Karl Schultze4dc75c2016-02-02 15:37:51 -0700139 float mvp[4][4];
140 float position[12 * 3][4];
141 float color[12 * 3][4];
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600142};
143
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600144struct vktexcube_vs_uniform {
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600145 // Must start with MVP
Karl Schultze4dc75c2016-02-02 15:37:51 -0700146 float mvp[4][4];
147 float position[12 * 3][4];
148 float attr[12 * 3][4];
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600149};
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -0600150
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600151//--------------------------------------------------------------------------------------
152// Mesh and VertexFormat Data
153//--------------------------------------------------------------------------------------
Karl Schultze4dc75c2016-02-02 15:37:51 -0700154// clang-format off
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -0600155static const float g_vertex_buffer_data[] = {
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800156 -1.0f,-1.0f,-1.0f, // -X side
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600157 -1.0f,-1.0f, 1.0f,
158 -1.0f, 1.0f, 1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800159 -1.0f, 1.0f, 1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600160 -1.0f, 1.0f,-1.0f,
161 -1.0f,-1.0f,-1.0f,
162
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800163 -1.0f,-1.0f,-1.0f, // -Z side
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600164 1.0f, 1.0f,-1.0f,
165 1.0f,-1.0f,-1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800166 -1.0f,-1.0f,-1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600167 -1.0f, 1.0f,-1.0f,
Mike Stroyan16b3d982015-03-19 14:29:04 -0600168 1.0f, 1.0f,-1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600169
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800170 -1.0f,-1.0f,-1.0f, // -Y side
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600171 1.0f,-1.0f,-1.0f,
Mike Stroyan16b3d982015-03-19 14:29:04 -0600172 1.0f,-1.0f, 1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800173 -1.0f,-1.0f,-1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600174 1.0f,-1.0f, 1.0f,
Mike Stroyan16b3d982015-03-19 14:29:04 -0600175 -1.0f,-1.0f, 1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600176
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800177 -1.0f, 1.0f,-1.0f, // +Y side
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600178 -1.0f, 1.0f, 1.0f,
179 1.0f, 1.0f, 1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800180 -1.0f, 1.0f,-1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600181 1.0f, 1.0f, 1.0f,
Mike Stroyan16b3d982015-03-19 14:29:04 -0600182 1.0f, 1.0f,-1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600183
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800184 1.0f, 1.0f,-1.0f, // +X side
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600185 1.0f, 1.0f, 1.0f,
186 1.0f,-1.0f, 1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800187 1.0f,-1.0f, 1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600188 1.0f,-1.0f,-1.0f,
189 1.0f, 1.0f,-1.0f,
190
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800191 -1.0f, 1.0f, 1.0f, // +Z side
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600192 -1.0f,-1.0f, 1.0f,
Mike Stroyan16b3d982015-03-19 14:29:04 -0600193 1.0f, 1.0f, 1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800194 -1.0f,-1.0f, 1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600195 1.0f,-1.0f, 1.0f,
196 1.0f, 1.0f, 1.0f,
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600197};
198
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -0600199static const float g_uv_buffer_data[] = {
Rene Lindsay76867e82016-07-29 10:49:11 -0700200 0.0f, 1.0f, // -X side
201 1.0f, 1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800202 1.0f, 0.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800203 1.0f, 0.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600204 0.0f, 0.0f,
205 0.0f, 1.0f,
206
Rene Lindsay76867e82016-07-29 10:49:11 -0700207 1.0f, 1.0f, // -Z side
208 0.0f, 0.0f,
209 0.0f, 1.0f,
210 1.0f, 1.0f,
211 1.0f, 0.0f,
212 0.0f, 0.0f,
213
214 1.0f, 0.0f, // -Y side
215 1.0f, 1.0f,
216 0.0f, 1.0f,
217 1.0f, 0.0f,
Courtney Goeltzenleuchter8879d3a2014-10-29 08:29:35 -0600218 0.0f, 1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800219 0.0f, 0.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600220
Rene Lindsay76867e82016-07-29 10:49:11 -0700221 1.0f, 0.0f, // +Y side
222 0.0f, 0.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800223 0.0f, 1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600224 1.0f, 0.0f,
Rene Lindsay76867e82016-07-29 10:49:11 -0700225 0.0f, 1.0f,
Mike Stroyan16b3d982015-03-19 14:29:04 -0600226 1.0f, 1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600227
Rene Lindsay76867e82016-07-29 10:49:11 -0700228 1.0f, 0.0f, // +X side
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800229 0.0f, 0.0f,
Rene Lindsay76867e82016-07-29 10:49:11 -0700230 0.0f, 1.0f,
231 0.0f, 1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600232 1.0f, 1.0f,
Chia-I Wuae3b55d2015-04-22 14:56:17 +0800233 1.0f, 0.0f,
Rene Lindsay76867e82016-07-29 10:49:11 -0700234
235 0.0f, 0.0f, // +Z side
236 0.0f, 1.0f,
237 1.0f, 0.0f,
238 0.0f, 1.0f,
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -0600239 1.0f, 1.0f,
Rene Lindsay76867e82016-07-29 10:49:11 -0700240 1.0f, 0.0f,
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600241};
Karl Schultze4dc75c2016-02-02 15:37:51 -0700242// clang-format on
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600243
Karl Schultze4dc75c2016-02-02 15:37:51 -0700244void dumpMatrix(const char *note, mat4x4 MVP) {
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600245 int i;
246
247 printf("%s: \n", note);
Karl Schultze4dc75c2016-02-02 15:37:51 -0700248 for (i = 0; i < 4; i++) {
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600249 printf("%f, %f, %f, %f\n", MVP[i][0], MVP[i][1], MVP[i][2], MVP[i][3]);
250 }
251 printf("\n");
252 fflush(stdout);
253}
254
Karl Schultze4dc75c2016-02-02 15:37:51 -0700255void dumpVec4(const char *note, vec4 vector) {
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600256 printf("%s: \n", note);
Karl Schultze4dc75c2016-02-02 15:37:51 -0700257 printf("%f, %f, %f, %f\n", vector[0], vector[1], vector[2], vector[3]);
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600258 printf("\n");
259 fflush(stdout);
260}
261
Karl Schultze4dc75c2016-02-02 15:37:51 -0700262VKAPI_ATTR VkBool32 VKAPI_CALL
Karl Schultz0c3c1512016-03-25 15:35:18 -0600263BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
264 uint64_t srcObject, size_t location, int32_t msgCode,
265 const char *pLayerPrefix, const char *pMsg,
266 void *pUserData) {
Courtney Goeltzenleuchteraf1951c2015-12-01 14:11:38 -0700267#ifndef WIN32
268 raise(SIGTRAP);
269#else
270 DebugBreak();
271#endif
272
273 return false;
274}
275
Mark Lobodzinski4c62d002016-05-19 17:22:25 -0600276typedef struct {
Ian Elliottaaae5352015-07-06 14:27:58 -0600277 VkImage image;
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800278 VkCommandBuffer cmd;
Tony Barbour22e06272016-09-07 16:07:56 -0600279 VkCommandBuffer graphics_to_present_cmd;
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -0600280 VkImageView view;
Ian Elliotta0781972015-08-21 15:09:33 -0600281} SwapchainBuffers;
Ian Elliottaaae5352015-07-06 14:27:58 -0600282
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600283struct demo {
Michael Lentinec6cde4b2016-04-18 13:20:45 -0500284#if defined(VK_USE_PLATFORM_WIN32_KHR)
Ian Elliott639ca472015-04-16 15:23:05 -0600285#define APP_NAME_STR_LEN 80
286 HINSTANCE connection; // hInstance - Windows Instance
287 char name[APP_NAME_STR_LEN]; // Name to put on the window/icon
Karl Schultze4dc75c2016-02-02 15:37:51 -0700288 HWND window; // hWnd - window handle
Rene Lindsayb9403da2016-07-01 18:00:30 -0600289 POINT minsize; // minimum window size
Tobin Ehlis43ed2982016-04-28 10:17:33 -0600290#elif defined(VK_USE_PLATFORM_XLIB_KHR) | defined(VK_USE_PLATFORM_XCB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -0600291 Display* display;
292 Window xlib_window;
293 Atom xlib_wm_delete_window;
Tobin Ehlis43ed2982016-04-28 10:17:33 -0600294
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600295 xcb_connection_t *connection;
296 xcb_screen_t *screen;
Tony Barbour2593b182016-04-19 10:57:58 -0600297 xcb_window_t xcb_window;
Chia-I Wucbb564e2015-04-16 22:02:10 +0800298 xcb_intern_atom_reply_t *atom_wm_delete_window;
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +0900299#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
300 struct wl_display *display;
301 struct wl_registry *registry;
302 struct wl_compositor *compositor;
303 struct wl_surface *window;
304 struct wl_shell *shell;
305 struct wl_shell_surface *shell_surface;
Michael Lentinec6cde4b2016-04-18 13:20:45 -0500306#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
307 ANativeWindow* window;
308#endif
Ian Elliottb08e0d92015-11-20 11:55:46 -0700309 VkSurfaceKHR surface;
Cody Northrop1fedb212015-05-28 11:27:16 -0600310 bool prepared;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -0700311 bool use_staging_buffer;
Tony Barbour2593b182016-04-19 10:57:58 -0600312 bool use_xlib;
Tony Barbour22e06272016-09-07 16:07:56 -0600313 bool separate_present_queue;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600314
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600315 VkInstance inst;
Tony Barbour72304ef2015-04-16 15:59:00 -0600316 VkPhysicalDevice gpu;
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600317 VkDevice device;
Tony Barboura2a67812016-07-18 13:21:06 -0600318 VkQueue graphics_queue;
319 VkQueue present_queue;
320 uint32_t graphics_queue_family_index;
321 uint32_t present_queue_family_index;
Tony Barbource7524e2016-07-28 12:01:45 -0600322 VkSemaphore image_acquired_semaphore;
323 VkSemaphore draw_complete_semaphore;
Tony Barbour22e06272016-09-07 16:07:56 -0600324 VkSemaphore image_ownership_semaphore;
Tony Barbourecf1b2b2015-06-24 16:06:58 -0600325 VkPhysicalDeviceProperties gpu_props;
Cody Northrop4d3c11d2015-08-03 17:04:53 -0600326 VkQueueFamilyProperties *queue_props;
Mark Lobodzinskieadf9982015-07-02 16:49:40 -0600327 VkPhysicalDeviceMemoryProperties memory_properties;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600328
Tony Barbourda2bad52016-01-22 14:36:40 -0700329 uint32_t enabled_extension_count;
330 uint32_t enabled_layer_count;
331 char *extension_names[64];
Karl Schultz5b423ea2016-06-20 19:08:43 -0600332 char *enabled_layers[64];
Tony Barbourda2bad52016-01-22 14:36:40 -0700333
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600334 int width, height;
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600335 VkFormat format;
Ian Elliotta0781972015-08-21 15:09:33 -0600336 VkColorSpaceKHR color_space;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600337
Karl Schultze4dc75c2016-02-02 15:37:51 -0700338 PFN_vkGetPhysicalDeviceSurfaceSupportKHR
339 fpGetPhysicalDeviceSurfaceSupportKHR;
340 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
341 fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
342 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
343 fpGetPhysicalDeviceSurfaceFormatsKHR;
344 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
345 fpGetPhysicalDeviceSurfacePresentModesKHR;
Ian Elliotta0781972015-08-21 15:09:33 -0600346 PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
347 PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
348 PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
349 PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR;
350 PFN_vkQueuePresentKHR fpQueuePresentKHR;
Ian Elliotta0781972015-08-21 15:09:33 -0600351 uint32_t swapchainImageCount;
Ian Elliottcf074d32015-10-16 18:02:43 -0600352 VkSwapchainKHR swapchain;
Ian Elliotta0781972015-08-21 15:09:33 -0600353 SwapchainBuffers *buffers;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600354
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800355 VkCommandPool cmd_pool;
Tony Barbour22e06272016-09-07 16:07:56 -0600356 VkCommandPool present_cmd_pool;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600357
358 struct {
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600359 VkFormat format;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600360
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600361 VkImage image;
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800362 VkMemoryAllocateInfo mem_alloc;
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -0500363 VkDeviceMemory mem;
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -0600364 VkImageView view;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600365 } depth;
366
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600367 struct texture_object textures[DEMO_TEXTURE_COUNT];
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600368
369 struct {
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600370 VkBuffer buf;
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800371 VkMemoryAllocateInfo mem_alloc;
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -0500372 VkDeviceMemory mem;
Courtney Goeltzenleuchterc3ad65e2015-10-23 13:38:14 -0600373 VkDescriptorBufferInfo buffer_info;
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -0600374 } uniform_data;
375
Karl Schultze4dc75c2016-02-02 15:37:51 -0700376 VkCommandBuffer cmd; // Buffer for initialization commands
Mark Lobodzinski1cfc7722015-04-17 14:11:39 -0500377 VkPipelineLayout pipeline_layout;
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600378 VkDescriptorSetLayout desc_layout;
Jon Ashburnc4ab7af2015-07-09 15:02:25 -0600379 VkPipelineCache pipelineCache;
Chia-I Wuf973e322015-07-08 13:34:24 +0800380 VkRenderPass render_pass;
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600381 VkPipeline pipeline;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600382
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -0600383 mat4x4 projection_matrix;
384 mat4x4 view_matrix;
385 mat4x4 model_matrix;
386
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -0600387 float spin_angle;
388 float spin_increment;
Courtney Goeltzenleuchter8879d3a2014-10-29 08:29:35 -0600389 bool pause;
390
Tony Barbourb6dba5c2015-07-21 09:04:41 -0600391 VkShaderModule vert_shader_module;
392 VkShaderModule frag_shader_module;
393
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600394 VkDescriptorPool desc_pool;
395 VkDescriptorSet desc_set;
Chia-I Wu6a3c8972015-01-04 16:27:24 +0800396
Tony Barbourd8e504f2015-10-08 14:26:24 -0600397 VkFramebuffer *framebuffers;
Chia-I Wuf973e322015-07-08 13:34:24 +0800398
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600399 bool quit;
David Pinedo2bb7c932015-06-18 17:03:14 -0600400 int32_t curFrame;
401 int32_t frameCount;
Tony Barbour3dddd5d2015-04-29 16:19:20 -0600402 bool validate;
Courtney Goeltzenleuchter03f4b772015-07-22 11:03:51 -0600403 bool use_break;
lenny-lunargfbe22392016-06-06 11:07:53 -0600404 bool suppress_popups;
Courtney Goeltzenleuchter0f060df2015-12-09 15:48:16 -0700405 PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
406 PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
407 VkDebugReportCallbackEXT msg_callback;
408 PFN_vkDebugReportMessageEXT DebugReportMessage;
Courtney Goeltzenleuchter922a0fa2015-06-10 17:39:03 -0600409
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -0600410 uint32_t current_buffer;
Tony Barbourab2a0362016-09-06 11:40:12 -0600411 uint32_t queue_family_count;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600412};
413
lenny-lunargfbe22392016-06-06 11:07:53 -0600414VKAPI_ATTR VkBool32 VKAPI_CALL
415dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
416 uint64_t srcObject, size_t location, int32_t msgCode,
417 const char *pLayerPrefix, const char *pMsg, void *pUserData) {
418 char *message = (char *)malloc(strlen(pMsg) + 100);
419
420 assert(message);
421
422 if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
423 sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
424 pMsg);
425 validation_error = 1;
426 } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
427 // We know that we're submitting queues without fences, ignore this
428 // warning
429 if (strstr(pMsg,
430 "vkQueueSubmit parameter, VkFence fence, is null pointer")) {
431 return false;
432 }
433 sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
434 pMsg);
435 validation_error = 1;
436 } else {
437 validation_error = 1;
438 return false;
439 }
440
441#ifdef _WIN32
Tony Barbour602ca4f2016-09-12 14:02:43 -0600442 in_callback = true;
lenny-lunargfbe22392016-06-06 11:07:53 -0600443 struct demo *demo = (struct demo*) pUserData;
444 if (!demo->suppress_popups)
445 MessageBox(NULL, message, "Alert", MB_OK);
Tony Barbour602ca4f2016-09-12 14:02:43 -0600446 in_callback = false;
lenny-lunargfbe22392016-06-06 11:07:53 -0600447#else
448 printf("%s\n", message);
449 fflush(stdout);
450#endif
451 free(message);
452
453 /*
454 * false indicates that layer should not bail-out of an
455 * API call that had validation failures. This may mean that the
456 * app dies inside the driver due to invalid parameter(s).
457 * That's what would happen without validation layers, so we'll
458 * keep that behavior here.
459 */
460 return false;
461}
462
Ian Elliottcf074d32015-10-16 18:02:43 -0600463// Forward declaration:
464static void demo_resize(struct demo *demo);
465
Karl Schultze4dc75c2016-02-02 15:37:51 -0700466static bool memory_type_from_properties(struct demo *demo, uint32_t typeBits,
467 VkFlags requirements_mask,
468 uint32_t *typeIndex) {
469 // Search memtypes to find first index with those properties
Alexandre BACQUART89eb8df2016-04-28 14:25:09 -0600470 for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
Karl Schultze4dc75c2016-02-02 15:37:51 -0700471 if ((typeBits & 1) == 1) {
472 // Type is available, does it match user properties?
473 if ((demo->memory_properties.memoryTypes[i].propertyFlags &
474 requirements_mask) == requirements_mask) {
475 *typeIndex = i;
476 return true;
477 }
478 }
479 typeBits >>= 1;
480 }
481 // No memory types matched, return failure
482 return false;
Mark Lobodzinskieadf9982015-07-02 16:49:40 -0600483}
484
Karl Schultze4dc75c2016-02-02 15:37:51 -0700485static void demo_flush_init_cmd(struct demo *demo) {
Tony Barbourfdc2d352015-04-22 09:02:32 -0600486 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600487
Tony Barbource7524e2016-07-28 12:01:45 -0600488 // This function could get called twice if the texture uses a staging buffer
489 // In that case the second call should be ignored
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600490 if (demo->cmd == VK_NULL_HANDLE)
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600491 return;
492
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600493 err = vkEndCommandBuffer(demo->cmd);
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600494 assert(!err);
495
Tony Barbource7524e2016-07-28 12:01:45 -0600496 VkFence fence;
497 VkFenceCreateInfo fence_ci = {.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
498 .pNext = NULL,
499 .flags = 0};
500 vkCreateFence(demo->device, &fence_ci, NULL, &fence);
Karl Schultze4dc75c2016-02-02 15:37:51 -0700501 const VkCommandBuffer cmd_bufs[] = {demo->cmd};
Karl Schultze4dc75c2016-02-02 15:37:51 -0700502 VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
503 .pNext = NULL,
504 .waitSemaphoreCount = 0,
505 .pWaitSemaphores = NULL,
506 .pWaitDstStageMask = NULL,
507 .commandBufferCount = 1,
508 .pCommandBuffers = cmd_bufs,
509 .signalSemaphoreCount = 0,
510 .pSignalSemaphores = NULL};
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600511
Tony Barbource7524e2016-07-28 12:01:45 -0600512 err = vkQueueSubmit(demo->graphics_queue, 1, &submit_info, fence);
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600513 assert(!err);
514
Tony Barbource7524e2016-07-28 12:01:45 -0600515 err = vkWaitForFences(demo->device, 1, &fence, VK_TRUE, UINT64_MAX);
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600516 assert(!err);
517
Courtney Goeltzenleuchter014ded82015-10-23 14:21:05 -0600518 vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, cmd_bufs);
Tony Barbource7524e2016-07-28 12:01:45 -0600519 vkDestroyFence(demo->device, fence, NULL);
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600520 demo->cmd = VK_NULL_HANDLE;
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600521}
522
Karl Schultze4dc75c2016-02-02 15:37:51 -0700523static void demo_set_image_layout(struct demo *demo, VkImage image,
524 VkImageAspectFlags aspectMask,
525 VkImageLayout old_image_layout,
Tobin Ehlisf07d9552016-02-11 17:49:23 -0700526 VkImageLayout new_image_layout,
527 VkAccessFlagBits srcAccessMask) {
Tony Barbourfdc2d352015-04-22 09:02:32 -0600528 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600529
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600530 if (demo->cmd == VK_NULL_HANDLE) {
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800531 const VkCommandBufferAllocateInfo cmd = {
Chia-I Wuf48700b2015-11-10 16:21:09 +0800532 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600533 .pNext = NULL,
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800534 .commandPool = demo->cmd_pool,
535 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
Jon Ashburn0bec67e2016-01-11 13:12:43 -0700536 .commandBufferCount = 1,
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600537 };
538
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800539 err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->cmd);
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600540 assert(!err);
Jon Ashburn0bec67e2016-01-11 13:12:43 -0700541 VkCommandBufferBeginInfo cmd_buf_info = {
542 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
543 .pNext = NULL,
544 .flags = 0,
Rene Lindsayd787e3a2016-07-07 16:00:14 -0700545 .pInheritanceInfo = NULL,
Jon Ashburn0bec67e2016-01-11 13:12:43 -0700546 };
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600547 err = vkBeginCommandBuffer(demo->cmd, &cmd_buf_info);
Tony Barbourcb59a5d2015-10-23 10:53:30 -0600548 assert(!err);
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600549 }
550
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600551 VkImageMemoryBarrier image_memory_barrier = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600552 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600553 .pNext = NULL,
Tobin Ehlisf07d9552016-02-11 17:49:23 -0700554 .srcAccessMask = srcAccessMask,
Chia-I Wu19574622015-10-27 19:54:37 +0800555 .dstAccessMask = 0,
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600556 .oldLayout = old_image_layout,
557 .newLayout = new_image_layout,
558 .image = image,
Karl Schultze4dc75c2016-02-02 15:37:51 -0700559 .subresourceRange = {aspectMask, 0, 1, 0, 1}};
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600560
Chia-I Wua8fe78a2015-10-27 18:04:07 +0800561 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600562 /* Make sure anything that was copying from this image has completed */
Chia-I Wu19574622015-10-27 19:54:37 +0800563 image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600564 }
565
Mark Lobodzinski9e0be702015-11-04 13:49:48 -0700566 if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
Karl Schultze4dc75c2016-02-02 15:37:51 -0700567 image_memory_barrier.dstAccessMask =
568 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
Mark Lobodzinski9e0be702015-11-04 13:49:48 -0700569 }
570
571 if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
Karl Schultze4dc75c2016-02-02 15:37:51 -0700572 image_memory_barrier.dstAccessMask =
573 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
Mark Lobodzinski9e0be702015-11-04 13:49:48 -0700574 }
575
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600576 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600577 /* Make sure any Copy or CPU writes to image are flushed */
Karl Schultze4dc75c2016-02-02 15:37:51 -0700578 image_memory_barrier.dstAccessMask =
579 VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600580 }
581
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -0600582 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600583
Tony Barbour50bbca42015-06-29 16:20:35 -0600584 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
585 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600586
Karl Schultze4dc75c2016-02-02 15:37:51 -0700587 vkCmdPipelineBarrier(demo->cmd, src_stages, dest_stages, 0, 0, NULL, 0,
588 NULL, 1, pmemory_barrier);
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -0600589}
590
Karl Schultze4dc75c2016-02-02 15:37:51 -0700591static void demo_draw_build_cmd(struct demo *demo, VkCommandBuffer cmd_buf) {
Jon Ashburn0bec67e2016-01-11 13:12:43 -0700592 const VkCommandBufferBeginInfo cmd_buf_info = {
593 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
594 .pNext = NULL,
Tony Barbource7524e2016-07-28 12:01:45 -0600595 .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
Rene Lindsayd787e3a2016-07-07 16:00:14 -0700596 .pInheritanceInfo = NULL,
Jon Ashburn0bec67e2016-01-11 13:12:43 -0700597 };
Chia-I Wua74c5b22015-07-07 11:50:03 +0800598 const VkClearValue clear_values[2] = {
Karl Schultze4dc75c2016-02-02 15:37:51 -0700599 [0] = {.color.float32 = {0.2f, 0.2f, 0.2f, 0.2f}},
600 [1] = {.depthStencil = {1.0f, 0}},
Chia-I Wua74c5b22015-07-07 11:50:03 +0800601 };
602 const VkRenderPassBeginInfo rp_begin = {
603 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
604 .pNext = NULL,
Chia-I Wuf973e322015-07-08 13:34:24 +0800605 .renderPass = demo->render_pass,
606 .framebuffer = demo->framebuffers[demo->current_buffer],
Chia-I Wua74c5b22015-07-07 11:50:03 +0800607 .renderArea.offset.x = 0,
608 .renderArea.offset.y = 0,
609 .renderArea.extent.width = demo->width,
610 .renderArea.extent.height = demo->height,
Cody Northrop372bbae2015-08-04 11:51:03 -0600611 .clearValueCount = 2,
612 .pClearValues = clear_values,
Jon Ashburn08f6eb92015-01-02 18:24:05 -0700613 };
Chia-I Wuf973e322015-07-08 13:34:24 +0800614 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600615
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600616 err = vkBeginCommandBuffer(cmd_buf, &cmd_buf_info);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600617 assert(!err);
618
Tony Barbour5c5b1632016-04-26 11:13:48 -0600619 VkImageMemoryBarrier image_memory_barrier = {
620 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
621 .pNext = NULL,
622 .srcAccessMask = 0,
623 .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
Tony Barbour22e06272016-09-07 16:07:56 -0600624 .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
Tony Barbour5c5b1632016-04-26 11:13:48 -0600625 .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
626 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
627 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
628 .image = demo->buffers[demo->current_buffer].image,
629 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
630
Tony Barbource7524e2016-07-28 12:01:45 -0600631 vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
632 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0,
633 NULL, 0, NULL, 1, &image_memory_barrier);
Tony Barbour5c5b1632016-04-26 11:13:48 -0600634
Chia-I Wuf051d262015-10-27 19:25:11 +0800635 vkCmdBeginRenderPass(cmd_buf, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
Chia-I Wua74c5b22015-07-07 11:50:03 +0800636
Karl Schultze4dc75c2016-02-02 15:37:51 -0700637 vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline);
638 vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS,
639 demo->pipeline_layout, 0, 1, &demo->desc_set, 0,
640 NULL);
Courtney Goeltzenleuchter4cbf78b2015-09-17 15:06:17 -0600641 VkViewport viewport;
642 memset(&viewport, 0, sizeof(viewport));
Karl Schultze4dc75c2016-02-02 15:37:51 -0700643 viewport.height = (float)demo->height;
644 viewport.width = (float)demo->width;
645 viewport.minDepth = (float)0.0f;
646 viewport.maxDepth = (float)1.0f;
Jon Ashburn19255f82015-12-30 14:06:55 -0700647 vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
Courtney Goeltzenleuchter4cbf78b2015-09-17 15:06:17 -0600648
649 VkRect2D scissor;
650 memset(&scissor, 0, sizeof(scissor));
651 scissor.extent.width = demo->width;
652 scissor.extent.height = demo->height;
653 scissor.offset.x = 0;
654 scissor.offset.y = 0;
Jon Ashburn19255f82015-12-30 14:06:55 -0700655 vkCmdSetScissor(cmd_buf, 0, 1, &scissor);
Courtney Goeltzenleuchter332a3672015-09-23 12:31:50 -0600656 vkCmdDraw(cmd_buf, 12 * 3, 1, 0, 0);
Tony Barbour98390392016-07-28 10:50:13 -0600657 // Note that ending the renderpass changes the image's layout from
Tony Barbour22e06272016-09-07 16:07:56 -0600658 // COLOR_ATTACHMENT_OPTIMAL to PRESENT_SRC_KHR
Chia-I Wu57b23b42015-06-26 15:34:39 +0800659 vkCmdEndRenderPass(cmd_buf);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600660
Tony Barbour22e06272016-09-07 16:07:56 -0600661 if (demo->separate_present_queue) {
662 // We have to transfer ownership from the graphics queue family to the
663 // present queue family to be able to present. Note that we don't have
664 // to transfer from present queue family back to graphics queue family at
665 // the start of the next frame because we don't care about the image's
666 // contents at that point.
667 VkImageMemoryBarrier image_ownership_barrier = {
668 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
669 .pNext = NULL,
670 .srcAccessMask = 0,
671 .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
672 .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
673 .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
674 .srcQueueFamilyIndex = demo->graphics_queue_family_index,
675 .dstQueueFamilyIndex = demo->present_queue_family_index,
676 .image = demo->buffers[demo->current_buffer].image,
677 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
678
679 vkCmdPipelineBarrier(cmd_buf,
680 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
681 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0,
682 0, NULL, 0, NULL, 1, &image_ownership_barrier);
683 }
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -0600684 err = vkEndCommandBuffer(cmd_buf);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600685 assert(!err);
686}
687
Tony Barbour22e06272016-09-07 16:07:56 -0600688void demo_build_image_ownership_cmd(struct demo *demo, int i) {
689 VkResult U_ASSERT_ONLY err;
690
691 const VkCommandBufferBeginInfo cmd_buf_info = {
692 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
693 .pNext = NULL,
694 .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
695 .pInheritanceInfo = NULL,
696 };
697 err = vkBeginCommandBuffer(demo->buffers[i].graphics_to_present_cmd,
698 &cmd_buf_info);
699 assert(!err);
700
701 VkImageMemoryBarrier image_ownership_barrier = {
702 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
703 .pNext = NULL,
704 .srcAccessMask = 0,
705 .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
706 .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
707 .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
708 .srcQueueFamilyIndex = demo->graphics_queue_family_index,
709 .dstQueueFamilyIndex = demo->present_queue_family_index,
710 .image = demo->buffers[i].image,
711 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
712
713 vkCmdPipelineBarrier(demo->buffers[i].graphics_to_present_cmd,
714 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
715 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0,
716 NULL, 0, NULL, 1, &image_ownership_barrier);
717 err = vkEndCommandBuffer(demo->buffers[i].graphics_to_present_cmd);
718 assert(!err);
719}
720
Karl Schultze4dc75c2016-02-02 15:37:51 -0700721void demo_update_data_buffer(struct demo *demo) {
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -0600722 mat4x4 MVP, Model, VP;
723 int matrixSize = sizeof(MVP);
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -0600724 uint8_t *pData;
Tony Barbourfdc2d352015-04-22 09:02:32 -0600725 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600726
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -0600727 mat4x4_mul(VP, demo->projection_matrix, demo->view_matrix);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600728
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -0600729 // Rotate 22.5 degrees around the Y axis
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600730 mat4x4_dup(Model, demo->model_matrix);
Karl Schultze4dc75c2016-02-02 15:37:51 -0700731 mat4x4_rotate(demo->model_matrix, Model, 0.0f, 1.0f, 0.0f,
732 (float)degreesToRadians(demo->spin_angle));
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -0600733 mat4x4_mul(MVP, VP, demo->model_matrix);
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -0600734
Karl Schultze4dc75c2016-02-02 15:37:51 -0700735 err = vkMapMemory(demo->device, demo->uniform_data.mem, 0,
736 demo->uniform_data.mem_alloc.allocationSize, 0,
737 (void **)&pData);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600738 assert(!err);
739
Karl Schultze4dc75c2016-02-02 15:37:51 -0700740 memcpy(pData, (const void *)&MVP[0][0], matrixSize);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600741
Mark Lobodzinskie4c92a62015-09-07 13:59:43 -0600742 vkUnmapMemory(demo->device, demo->uniform_data.mem);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600743}
744
Karl Schultze4dc75c2016-02-02 15:37:51 -0700745static void demo_draw(struct demo *demo) {
Tony Barbourfdc2d352015-04-22 09:02:32 -0600746 VkResult U_ASSERT_ONLY err;
Tony Barboure35e8aa2016-06-20 10:44:08 -0600747
Ian Elliottaaae5352015-07-06 14:27:58 -0600748 // Get the index of the next available swapchain image:
Karl Schultze4dc75c2016-02-02 15:37:51 -0700749 err = demo->fpAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX,
Tony Barbource7524e2016-07-28 12:01:45 -0600750 demo->image_acquired_semaphore, (VkFence)0,
Ian Elliottaaae5352015-07-06 14:27:58 -0600751 &demo->current_buffer);
Ian Elliottcf074d32015-10-16 18:02:43 -0600752 if (err == VK_ERROR_OUT_OF_DATE_KHR) {
753 // demo->swapchain is out of date (e.g. the window was resized) and
754 // must be recreated:
755 demo_resize(demo);
756 demo_draw(demo);
Ian Elliottcf074d32015-10-16 18:02:43 -0600757 return;
758 } else if (err == VK_SUBOPTIMAL_KHR) {
759 // demo->swapchain is not as optimal as it could be, but the platform's
760 // presentation engine will still present the image correctly.
761 } else {
762 assert(!err);
763 }
Tony Barbource7524e2016-07-28 12:01:45 -0600764 // Wait for the image acquired semaphore to be signaled to ensure
Courtney Goeltzenleuchter5fa898d2015-10-20 18:04:07 -0600765 // that the image won't be rendered to until the presentation
766 // engine has fully released ownership to the application, and it is
767 // okay to render to the image.
Ian Elliott3b55a122016-08-03 14:57:11 -0600768 VkFence nullFence = VK_NULL_HANDLE;
Tony Barbour22e06272016-09-07 16:07:56 -0600769 VkPipelineStageFlags pipe_stage_flags;
770 VkSubmitInfo submit_info;
771 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
772 submit_info.pNext = NULL;
773 submit_info.pWaitDstStageMask = &pipe_stage_flags;
774 pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
775 submit_info.waitSemaphoreCount = 1;
776 submit_info.pWaitSemaphores = &demo->image_acquired_semaphore;
777 submit_info.commandBufferCount = 1;
778 submit_info.pCommandBuffers = &demo->buffers[demo->current_buffer].cmd;
779 submit_info.signalSemaphoreCount = 1;
780 submit_info.pSignalSemaphores = &demo->draw_complete_semaphore;
Tony Barboura2a67812016-07-18 13:21:06 -0600781 err = vkQueueSubmit(demo->graphics_queue, 1, &submit_info, nullFence);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600782 assert(!err);
783
Tony Barbour22e06272016-09-07 16:07:56 -0600784 if (demo->separate_present_queue) {
785 // If we are using separate queues, change image ownership to the
786 // present queue before presenting, waiting for the draw complete
787 // semaphore and signalling the ownership released semaphore when finished
788 pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
789 submit_info.waitSemaphoreCount = 1;
790 submit_info.pWaitSemaphores = &demo->draw_complete_semaphore;
791 submit_info.commandBufferCount = 1;
792 submit_info.pCommandBuffers =
793 &demo->buffers[demo->current_buffer].graphics_to_present_cmd;
794 submit_info.signalSemaphoreCount = 1;
795 submit_info.pSignalSemaphores = &demo->image_ownership_semaphore;
796 err = vkQueueSubmit(demo->present_queue, 1, &submit_info, nullFence);
797 assert(!err);
798 }
799
800 // If we are using separate queues we have to wait for image ownership,
801 // otherwise wait for draw complete
Ian Elliotta0781972015-08-21 15:09:33 -0600802 VkPresentInfoKHR present = {
803 .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
Ian Elliottaaae5352015-07-06 14:27:58 -0600804 .pNext = NULL,
Ian Elliottcf7f7482016-08-19 03:46:58 -0600805 .waitSemaphoreCount = 1,
Tony Barbour22e06272016-09-07 16:07:56 -0600806 .pWaitSemaphores = (demo->separate_present_queue)
807 ? &demo->image_ownership_semaphore
808 : &demo->draw_complete_semaphore,
Ian Elliotta0781972015-08-21 15:09:33 -0600809 .swapchainCount = 1,
Ian Elliottb08e0d92015-11-20 11:55:46 -0700810 .pSwapchains = &demo->swapchain,
811 .pImageIndices = &demo->current_buffer,
Ian Elliottaaae5352015-07-06 14:27:58 -0600812 };
813
Tony Barboura2a67812016-07-18 13:21:06 -0600814 err = demo->fpQueuePresentKHR(demo->present_queue, &present);
Ian Elliottcf074d32015-10-16 18:02:43 -0600815 if (err == VK_ERROR_OUT_OF_DATE_KHR) {
816 // demo->swapchain is out of date (e.g. the window was resized) and
817 // must be recreated:
818 demo_resize(demo);
819 } else if (err == VK_SUBOPTIMAL_KHR) {
820 // demo->swapchain is not as optimal as it could be, but the platform's
821 // presentation engine will still present the image correctly.
822 } else {
823 assert(!err);
824 }
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600825}
826
Karl Schultze4dc75c2016-02-02 15:37:51 -0700827static void demo_prepare_buffers(struct demo *demo) {
Ian Elliottaaae5352015-07-06 14:27:58 -0600828 VkResult U_ASSERT_ONLY err;
Ian Elliottcf074d32015-10-16 18:02:43 -0600829 VkSwapchainKHR oldSwapchain = demo->swapchain;
Ian Elliottaaae5352015-07-06 14:27:58 -0600830
Ian Elliottb08e0d92015-11-20 11:55:46 -0700831 // Check the surface capabilities and formats
832 VkSurfaceCapabilitiesKHR surfCapabilities;
Karl Schultze4dc75c2016-02-02 15:37:51 -0700833 err = demo->fpGetPhysicalDeviceSurfaceCapabilitiesKHR(
834 demo->gpu, demo->surface, &surfCapabilities);
Ian Elliottaaae5352015-07-06 14:27:58 -0600835 assert(!err);
836
Ian Elliott8528eff2015-08-07 15:56:59 -0600837 uint32_t presentModeCount;
Karl Schultze4dc75c2016-02-02 15:37:51 -0700838 err = demo->fpGetPhysicalDeviceSurfacePresentModesKHR(
839 demo->gpu, demo->surface, &presentModeCount, NULL);
Ian Elliottaaae5352015-07-06 14:27:58 -0600840 assert(!err);
Ian Elliotta0781972015-08-21 15:09:33 -0600841 VkPresentModeKHR *presentModes =
842 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
Ian Elliott8528eff2015-08-07 15:56:59 -0600843 assert(presentModes);
Karl Schultze4dc75c2016-02-02 15:37:51 -0700844 err = demo->fpGetPhysicalDeviceSurfacePresentModesKHR(
845 demo->gpu, demo->surface, &presentModeCount, presentModes);
Ian Elliottaaae5352015-07-06 14:27:58 -0600846 assert(!err);
847
Ian Elliotta0781972015-08-21 15:09:33 -0600848 VkExtent2D swapchainExtent;
Ian Elliottcf7f7482016-08-19 03:46:58 -0600849 // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
850 if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) {
851 // If the surface size is undefined, the size is set to the size
852 // of the images requested, which must fit within the minimum and
853 // maximum values.
Ian Elliotta0781972015-08-21 15:09:33 -0600854 swapchainExtent.width = demo->width;
855 swapchainExtent.height = demo->height;
Ian Elliottcf7f7482016-08-19 03:46:58 -0600856
857 if (swapchainExtent.width < surfCapabilities.minImageExtent.width) {
858 swapchainExtent.width = surfCapabilities.minImageExtent.width;
859 } else if (swapchainExtent.width > surfCapabilities.maxImageExtent.width) {
860 swapchainExtent.width = surfCapabilities.maxImageExtent.width;
861 }
862
863 if (swapchainExtent.height < surfCapabilities.minImageExtent.height) {
864 swapchainExtent.height = surfCapabilities.minImageExtent.height;
865 } else if (swapchainExtent.height > surfCapabilities.maxImageExtent.height) {
866 swapchainExtent.height = surfCapabilities.maxImageExtent.height;
867 }
Karl Schultze4dc75c2016-02-02 15:37:51 -0700868 } else {
Ian Elliottaaae5352015-07-06 14:27:58 -0600869 // If the surface size is defined, the swap chain size must match
Ian Elliottb08e0d92015-11-20 11:55:46 -0700870 swapchainExtent = surfCapabilities.currentExtent;
871 demo->width = surfCapabilities.currentExtent.width;
872 demo->height = surfCapabilities.currentExtent.height;
Ian Elliottaaae5352015-07-06 14:27:58 -0600873 }
874
875 // If mailbox mode is available, use it, as is the lowest-latency non-
Ian Elliott3ebce342015-07-27 13:53:11 -0600876 // tearing mode. If not, try IMMEDIATE which will usually be available,
877 // and is fastest (though it tears). If not, fall back to FIFO which is
878 // always available.
Ian Elliotta0781972015-08-21 15:09:33 -0600879 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
Ian Elliottaaae5352015-07-06 14:27:58 -0600880 for (size_t i = 0; i < presentModeCount; i++) {
Ian Elliotta0781972015-08-21 15:09:33 -0600881 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
882 swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
Ian Elliottaaae5352015-07-06 14:27:58 -0600883 break;
884 }
Ian Elliotta0781972015-08-21 15:09:33 -0600885 if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
886 (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
887 swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
Ian Elliott3ebce342015-07-27 13:53:11 -0600888 }
Ian Elliottaaae5352015-07-06 14:27:58 -0600889 }
890
Ian Elliottcf7f7482016-08-19 03:46:58 -0600891 // Determine the number of VkImage's to use in the swap chain.
892 // Application desires to only acquire 1 image at a time (which is
893 // "surfCapabilities.minImageCount").
894 uint32_t desiredNumOfSwapchainImages = surfCapabilities.minImageCount;
895 // If maxImageCount is 0, we can ask for as many images as we want;
896 // otherwise we're limited to maxImageCount
Ian Elliottb08e0d92015-11-20 11:55:46 -0700897 if ((surfCapabilities.maxImageCount > 0) &&
Ian Elliottcf7f7482016-08-19 03:46:58 -0600898 (desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) {
Ian Elliottaaae5352015-07-06 14:27:58 -0600899 // Application must settle for fewer images than desired:
Ian Elliottcf7f7482016-08-19 03:46:58 -0600900 desiredNumOfSwapchainImages = surfCapabilities.maxImageCount;
Ian Elliottaaae5352015-07-06 14:27:58 -0600901 }
902
Tony Barbour9fd6d352015-09-16 15:01:32 -0600903 VkSurfaceTransformFlagsKHR preTransform;
Karl Schultze4dc75c2016-02-02 15:37:51 -0700904 if (surfCapabilities.supportedTransforms &
905 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
Ian Elliotta7a731c2015-12-11 15:52:12 -0700906 preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
Ian Elliottaaae5352015-07-06 14:27:58 -0600907 } else {
Ian Elliottb08e0d92015-11-20 11:55:46 -0700908 preTransform = surfCapabilities.currentTransform;
Ian Elliottaaae5352015-07-06 14:27:58 -0600909 }
910
Tony Barboura2a67812016-07-18 13:21:06 -0600911 VkSwapchainCreateInfoKHR swapchain_ci = {
Ian Elliott5b97eae2015-09-22 10:20:23 -0600912 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
Chia-I Wucbb564e2015-04-16 22:02:10 +0800913 .pNext = NULL,
Ian Elliottb08e0d92015-11-20 11:55:46 -0700914 .surface = demo->surface,
Ian Elliottcf7f7482016-08-19 03:46:58 -0600915 .minImageCount = desiredNumOfSwapchainImages,
Chia-I Wucbb564e2015-04-16 22:02:10 +0800916 .imageFormat = demo->format,
Ian Elliott8528eff2015-08-07 15:56:59 -0600917 .imageColorSpace = demo->color_space,
Karl Schultze4dc75c2016-02-02 15:37:51 -0700918 .imageExtent =
919 {
920 .width = swapchainExtent.width, .height = swapchainExtent.height,
921 },
Ian Elliottb08e0d92015-11-20 11:55:46 -0700922 .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
Ian Elliottaaae5352015-07-06 14:27:58 -0600923 .preTransform = preTransform,
Ian Elliott86f29a82015-12-28 15:25:33 -0700924 .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
Ian Elliottb08e0d92015-11-20 11:55:46 -0700925 .imageArrayLayers = 1,
926 .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
927 .queueFamilyIndexCount = 0,
Ian Elliott8528eff2015-08-07 15:56:59 -0600928 .pQueueFamilyIndices = NULL,
Ian Elliotta0781972015-08-21 15:09:33 -0600929 .presentMode = swapchainPresentMode,
Ian Elliottcf074d32015-10-16 18:02:43 -0600930 .oldSwapchain = oldSwapchain,
Ian Elliottaaae5352015-07-06 14:27:58 -0600931 .clipped = true,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600932 };
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -0600933 uint32_t i;
Tony Barboura2a67812016-07-18 13:21:06 -0600934 err = demo->fpCreateSwapchainKHR(demo->device, &swapchain_ci, NULL,
Karl Schultze4dc75c2016-02-02 15:37:51 -0700935 &demo->swapchain);
Chia-I Wucbb564e2015-04-16 22:02:10 +0800936 assert(!err);
937
Ian Elliottcf074d32015-10-16 18:02:43 -0600938 // If we just re-created an existing swapchain, we should destroy the old
939 // swapchain at this point.
940 // Note: destroying the swapchain also cleans up all its associated
941 // presentable images once the platform is done with them.
Chia-I Wu1c4086a2015-10-26 20:04:44 +0800942 if (oldSwapchain != VK_NULL_HANDLE) {
Ian Elliottb08e0d92015-11-20 11:55:46 -0700943 demo->fpDestroySwapchainKHR(demo->device, oldSwapchain, NULL);
Ian Elliottcf074d32015-10-16 18:02:43 -0600944 }
945
946 err = demo->fpGetSwapchainImagesKHR(demo->device, demo->swapchain,
Ian Elliotta0781972015-08-21 15:09:33 -0600947 &demo->swapchainImageCount, NULL);
Ian Elliottaaae5352015-07-06 14:27:58 -0600948 assert(!err);
Chia-I Wucbb564e2015-04-16 22:02:10 +0800949
Karl Schultze4dc75c2016-02-02 15:37:51 -0700950 VkImage *swapchainImages =
951 (VkImage *)malloc(demo->swapchainImageCount * sizeof(VkImage));
Ian Elliotta0781972015-08-21 15:09:33 -0600952 assert(swapchainImages);
Ian Elliottcf074d32015-10-16 18:02:43 -0600953 err = demo->fpGetSwapchainImagesKHR(demo->device, demo->swapchain,
Ian Elliotta0781972015-08-21 15:09:33 -0600954 &demo->swapchainImageCount,
955 swapchainImages);
Ian Elliottaaae5352015-07-06 14:27:58 -0600956 assert(!err);
Ian Elliottaaae5352015-07-06 14:27:58 -0600957
Karl Schultze4dc75c2016-02-02 15:37:51 -0700958 demo->buffers = (SwapchainBuffers *)malloc(sizeof(SwapchainBuffers) *
959 demo->swapchainImageCount);
Ian Elliottaaae5352015-07-06 14:27:58 -0600960 assert(demo->buffers);
961
Ian Elliotta0781972015-08-21 15:09:33 -0600962 for (i = 0; i < demo->swapchainImageCount; i++) {
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -0600963 VkImageViewCreateInfo color_image_view = {
964 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600965 .pNext = NULL,
966 .format = demo->format,
Karl Schultze4dc75c2016-02-02 15:37:51 -0700967 .components =
968 {
969 .r = VK_COMPONENT_SWIZZLE_R,
970 .g = VK_COMPONENT_SWIZZLE_G,
971 .b = VK_COMPONENT_SWIZZLE_B,
972 .a = VK_COMPONENT_SWIZZLE_A,
973 },
974 .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
975 .baseMipLevel = 0,
976 .levelCount = 1,
977 .baseArrayLayer = 0,
978 .layerCount = 1},
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -0600979 .viewType = VK_IMAGE_VIEW_TYPE_2D,
980 .flags = 0,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600981 };
982
Ian Elliotta0781972015-08-21 15:09:33 -0600983 demo->buffers[i].image = swapchainImages[i];
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600984
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -0600985 color_image_view.image = demo->buffers[i].image;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600986
Karl Schultze4dc75c2016-02-02 15:37:51 -0700987 err = vkCreateImageView(demo->device, &color_image_view, NULL,
988 &demo->buffers[i].view);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600989 assert(!err);
Tony Barbour22e06272016-09-07 16:07:56 -0600990
991 // The draw loop will be expecting the presentable images to be in
992 // LAYOUT_PRESENT_SRC_KHR
993 // since that's how they're left at the end of every frame.
994 demo_set_image_layout(
995 demo, demo->buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
996 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 0);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -0600997 }
Karl Schultze4dc75c2016-02-02 15:37:51 -0700998
Michael Lentinec6cde4b2016-04-18 13:20:45 -0500999
Mark Young04fd3d82016-01-25 14:43:50 -07001000 if (NULL != presentModes) {
1001 free(presentModes);
1002 }
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001003}
1004
Karl Schultze4dc75c2016-02-02 15:37:51 -07001005static void demo_prepare_depth(struct demo *demo) {
Tony Barbour72304ef2015-04-16 15:59:00 -06001006 const VkFormat depth_format = VK_FORMAT_D16_UNORM;
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001007 const VkImageCreateInfo image = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001008 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001009 .pNext = NULL,
Tony Barbour72304ef2015-04-16 15:59:00 -06001010 .imageType = VK_IMAGE_TYPE_2D,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001011 .format = depth_format,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001012 .extent = {demo->width, demo->height, 1},
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001013 .mipLevels = 1,
Courtney Goeltzenleuchterdff021f2015-10-21 17:57:31 -06001014 .arrayLayers = 1,
Chia-I Wu3ede9462015-10-31 00:31:16 +08001015 .samples = VK_SAMPLE_COUNT_1_BIT,
Tony Barbour72304ef2015-04-16 15:59:00 -06001016 .tiling = VK_IMAGE_TILING_OPTIMAL,
Courtney Goeltzenleuchter4e368ee2015-09-10 14:14:11 -06001017 .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001018 .flags = 0,
1019 };
Dominik Witczak2fe1c702015-09-22 18:25:33 +02001020
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -06001021 VkImageViewCreateInfo view = {
1022 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001023 .pNext = NULL,
Chia-I Wu1c4086a2015-10-26 20:04:44 +08001024 .image = VK_NULL_HANDLE,
Courtney Goeltzenleuchter556ee322015-07-15 17:41:38 -06001025 .format = depth_format,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001026 .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
1027 .baseMipLevel = 0,
1028 .levelCount = 1,
1029 .baseArrayLayer = 0,
1030 .layerCount = 1},
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001031 .flags = 0,
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -06001032 .viewType = VK_IMAGE_VIEW_TYPE_2D,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001033 };
Mike Stroyanebae8322015-04-17 12:36:38 -06001034
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001035 VkMemoryRequirements mem_reqs;
Tony Barbourfdc2d352015-04-22 09:02:32 -06001036 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter87a0ef02015-10-22 11:03:31 -06001037 bool U_ASSERT_ONLY pass;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001038
1039 demo->depth.format = depth_format;
1040
1041 /* create image */
Karl Schultze4dc75c2016-02-02 15:37:51 -07001042 err = vkCreateImage(demo->device, &image, NULL, &demo->depth.image);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001043 assert(!err);
1044
Karl Schultze4dc75c2016-02-02 15:37:51 -07001045 vkGetImageMemoryRequirements(demo->device, demo->depth.image, &mem_reqs);
Tony Barbourcb59a5d2015-10-23 10:53:30 -06001046 assert(!err);
Mark Lobodzinskieadf9982015-07-02 16:49:40 -06001047
Chia-I Wuf48700b2015-11-10 16:21:09 +08001048 demo->depth.mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
Dominik Witczak2fe1c702015-09-22 18:25:33 +02001049 demo->depth.mem_alloc.pNext = NULL;
1050 demo->depth.mem_alloc.allocationSize = mem_reqs.size;
1051 demo->depth.mem_alloc.memoryTypeIndex = 0;
1052
Karl Schultze4dc75c2016-02-02 15:37:51 -07001053 pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
1054 0, /* No requirements */
1055 &demo->depth.mem_alloc.memoryTypeIndex);
Courtney Goeltzenleuchter87a0ef02015-10-22 11:03:31 -06001056 assert(pass);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001057
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001058 /* allocate memory */
Karl Schultze4dc75c2016-02-02 15:37:51 -07001059 err = vkAllocateMemory(demo->device, &demo->depth.mem_alloc, NULL,
1060 &demo->depth.mem);
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001061 assert(!err);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001062
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001063 /* bind memory */
Karl Schultze4dc75c2016-02-02 15:37:51 -07001064 err =
1065 vkBindImageMemory(demo->device, demo->depth.image, demo->depth.mem, 0);
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001066 assert(!err);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001067
Karl Schultze4dc75c2016-02-02 15:37:51 -07001068 demo_set_image_layout(demo, demo->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT,
1069 VK_IMAGE_LAYOUT_UNDEFINED,
Tobin Ehlisf07d9552016-02-11 17:49:23 -07001070 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1071 0);
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001072
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001073 /* create image view */
1074 view.image = demo->depth.image;
Chia-I Wu63636062015-10-26 21:10:41 +08001075 err = vkCreateImageView(demo->device, &view, NULL, &demo->depth.view);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001076 assert(!err);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001077}
1078
Tony Barbour1a86d032015-09-21 15:17:33 -06001079/* Load a ppm file into memory */
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001080bool loadTexture(const char *filename, uint8_t *rgba_data,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001081 VkSubresourceLayout *layout, int32_t *width, int32_t *height) {
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001082#ifdef __ANDROID__
1083#include <lunarg.ppm.h>
1084 char *cPtr;
Mark Lobodzinski4c62d002016-05-19 17:22:25 -06001085 cPtr = (char*)lunarg_ppm;
1086 if ((unsigned char*)cPtr >= (lunarg_ppm + lunarg_ppm_len) || strncmp(cPtr, "P6\n", 3)) {
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001087 return false;
1088 }
1089 while(strncmp(cPtr++, "\n", 1));
Alexandre BACQUART9063e2a2016-06-17 11:30:32 -06001090 sscanf(cPtr, "%u %u", width, height);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001091 if (rgba_data == NULL) {
1092 return true;
1093 }
1094 while(strncmp(cPtr++, "\n", 1));
Mark Lobodzinski4c62d002016-05-19 17:22:25 -06001095 if ((unsigned char*)cPtr >= (lunarg_ppm + lunarg_ppm_len) || strncmp(cPtr, "255\n", 4)) {
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001096 return false;
1097 }
1098 while(strncmp(cPtr++, "\n", 1));
1099
1100 for (int y = 0; y < *height; y++) {
1101 uint8_t *rowPtr = rgba_data;
1102 for (int x = 0; x < *width; x++) {
1103 memcpy(rowPtr, cPtr, 3);
1104 rowPtr[3] = 255; /* Alpha of 1 */
1105 rowPtr += 4;
1106 cPtr += 3;
1107 }
1108 rgba_data += layout->rowPitch;
1109 }
1110
1111 return true;
1112#else
Karl Schultze4dc75c2016-02-02 15:37:51 -07001113 FILE *fPtr = fopen(filename, "rb");
Courtney Goeltzenleuchterd3cdaaf2015-12-17 09:53:29 -07001114 char header[256], *cPtr, *tmp;
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -06001115
Tony Barbour1a86d032015-09-21 15:17:33 -06001116 if (!fPtr)
1117 return false;
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -06001118
Tony Barbour1a86d032015-09-21 15:17:33 -06001119 cPtr = fgets(header, 256, fPtr); // P6
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001120 if (cPtr == NULL || strncmp(header, "P6\n", 3)) {
1121 fclose(fPtr);
Tony Barbour1a86d032015-09-21 15:17:33 -06001122 return false;
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001123 }
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -06001124
Tony Barbour1a86d032015-09-21 15:17:33 -06001125 do {
1126 cPtr = fgets(header, 256, fPtr);
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001127 if (cPtr == NULL) {
1128 fclose(fPtr);
Tony Barbour1a86d032015-09-21 15:17:33 -06001129 return false;
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001130 }
Karl Schultze4dc75c2016-02-02 15:37:51 -07001131 } while (!strncmp(header, "#", 1));
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -06001132
Alexandre BACQUART9063e2a2016-06-17 11:30:32 -06001133 sscanf(header, "%u %u", width, height);
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001134 if (rgba_data == NULL) {
1135 fclose(fPtr);
Tony Barbour1a86d032015-09-21 15:17:33 -06001136 return true;
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001137 }
Courtney Goeltzenleuchterd3cdaaf2015-12-17 09:53:29 -07001138 tmp = fgets(header, 256, fPtr); // Format
Karl Schultze4dc75c2016-02-02 15:37:51 -07001139 (void)tmp;
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001140 if (cPtr == NULL || strncmp(header, "255\n", 3)) {
1141 fclose(fPtr);
Tony Barbour1a86d032015-09-21 15:17:33 -06001142 return false;
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001143 }
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -06001144
Karl Schultze4dc75c2016-02-02 15:37:51 -07001145 for (int y = 0; y < *height; y++) {
Tony Barbour1a86d032015-09-21 15:17:33 -06001146 uint8_t *rowPtr = rgba_data;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001147 for (int x = 0; x < *width; x++) {
Courtney Goeltzenleuchterd3cdaaf2015-12-17 09:53:29 -07001148 size_t s = fread(rowPtr, 3, 1, fPtr);
Karl Schultze4dc75c2016-02-02 15:37:51 -07001149 (void)s;
Tony Barbour1a86d032015-09-21 15:17:33 -06001150 rowPtr[3] = 255; /* Alpha of 1 */
1151 rowPtr += 4;
1152 }
1153 rgba_data += layout->rowPitch;
1154 }
1155 fclose(fPtr);
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001156 return true;
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001157#endif
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -06001158}
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -06001159
Karl Schultze4dc75c2016-02-02 15:37:51 -07001160static void demo_prepare_texture_image(struct demo *demo, const char *filename,
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001161 struct texture_object *tex_obj,
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001162 VkImageTiling tiling,
Courtney Goeltzenleuchterc56c36a2015-04-21 09:31:23 -06001163 VkImageUsageFlags usage,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001164 VkFlags required_props) {
Mike Stroyan8b89e072015-06-15 14:21:03 -06001165 const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM;
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -06001166 int32_t tex_width;
1167 int32_t tex_height;
Tony Barbourfdc2d352015-04-22 09:02:32 -06001168 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter87a0ef02015-10-22 11:03:31 -06001169 bool U_ASSERT_ONLY pass;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001170
Karl Schultze4dc75c2016-02-02 15:37:51 -07001171 if (!loadTexture(filename, NULL, NULL, &tex_width, &tex_height)) {
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001172 ERR_EXIT("Failed to load textures", "Load Texture Failure");
David Pinedo30bd71d2015-04-23 08:16:57 -06001173 }
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001174
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001175 tex_obj->tex_width = tex_width;
1176 tex_obj->tex_height = tex_height;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001177
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001178 const VkImageCreateInfo image_create_info = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001179 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001180 .pNext = NULL,
Tony Barbour72304ef2015-04-16 15:59:00 -06001181 .imageType = VK_IMAGE_TYPE_2D,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001182 .format = tex_format,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001183 .extent = {tex_width, tex_height, 1},
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001184 .mipLevels = 1,
Courtney Goeltzenleuchterdff021f2015-10-21 17:57:31 -06001185 .arrayLayers = 1,
Chia-I Wu3ede9462015-10-31 00:31:16 +08001186 .samples = VK_SAMPLE_COUNT_1_BIT,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001187 .tiling = tiling,
Courtney Goeltzenleuchterc56c36a2015-04-21 09:31:23 -06001188 .usage = usage,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001189 .flags = 0,
Tobin Ehlisf07d9552016-02-11 17:49:23 -07001190 .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001191 };
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001192
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001193 VkMemoryRequirements mem_reqs;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001194
Karl Schultze4dc75c2016-02-02 15:37:51 -07001195 err =
1196 vkCreateImage(demo->device, &image_create_info, NULL, &tex_obj->image);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001197 assert(!err);
1198
Courtney Goeltzenleuchterbd5c1742015-10-20 16:40:38 -06001199 vkGetImageMemoryRequirements(demo->device, tex_obj->image, &mem_reqs);
Piers Daniell735ee532015-02-23 16:23:13 -07001200
Chia-I Wuf48700b2015-11-10 16:21:09 +08001201 tex_obj->mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
Dominik Witczak2fe1c702015-09-22 18:25:33 +02001202 tex_obj->mem_alloc.pNext = NULL;
1203 tex_obj->mem_alloc.allocationSize = mem_reqs.size;
1204 tex_obj->mem_alloc.memoryTypeIndex = 0;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001205
Karl Schultze4dc75c2016-02-02 15:37:51 -07001206 pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
1207 required_props,
1208 &tex_obj->mem_alloc.memoryTypeIndex);
Courtney Goeltzenleuchter87a0ef02015-10-22 11:03:31 -06001209 assert(pass);
Mark Lobodzinskieadf9982015-07-02 16:49:40 -06001210
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001211 /* allocate memory */
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001212 err = vkAllocateMemory(demo->device, &tex_obj->mem_alloc, NULL,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001213 &(tex_obj->mem));
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001214 assert(!err);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001215
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001216 /* bind memory */
Karl Schultze4dc75c2016-02-02 15:37:51 -07001217 err = vkBindImageMemory(demo->device, tex_obj->image, tex_obj->mem, 0);
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001218 assert(!err);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001219
Tony Barbour8a9f62a2015-10-15 12:42:56 -06001220 if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001221 const VkImageSubresource subres = {
Chia-I Wua0141432015-10-27 19:55:05 +08001222 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001223 .mipLevel = 0,
Courtney Goeltzenleuchterfc465b82015-09-10 16:38:41 -06001224 .arrayLayer = 0,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001225 };
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001226 VkSubresourceLayout layout;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001227 void *data;
1228
Karl Schultze4dc75c2016-02-02 15:37:51 -07001229 vkGetImageSubresourceLayout(demo->device, tex_obj->image, &subres,
1230 &layout);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001231
Karl Schultze4dc75c2016-02-02 15:37:51 -07001232 err = vkMapMemory(demo->device, tex_obj->mem, 0,
1233 tex_obj->mem_alloc.allocationSize, 0, &data);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001234 assert(!err);
1235
1236 if (!loadTexture(filename, data, &layout, &tex_width, &tex_height)) {
1237 fprintf(stderr, "Error loading texture: %s\n", filename);
1238 }
1239
Mark Lobodzinskie4c92a62015-09-07 13:59:43 -06001240 vkUnmapMemory(demo->device, tex_obj->mem);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001241 }
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001242
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001243 tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001244 demo_set_image_layout(demo, tex_obj->image, VK_IMAGE_ASPECT_COLOR_BIT,
Tobin Ehlisf07d9552016-02-11 17:49:23 -07001245 VK_IMAGE_LAYOUT_PREINITIALIZED, tex_obj->imageLayout,
1246 VK_ACCESS_HOST_WRITE_BIT);
Karl Schultze4dc75c2016-02-02 15:37:51 -07001247 /* setting the image layout does not reference the actual memory so no need
1248 * to add a mem ref */
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001249}
1250
Karl Schultze4dc75c2016-02-02 15:37:51 -07001251static void demo_destroy_texture_image(struct demo *demo,
1252 struct texture_object *tex_objs) {
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001253 /* clean up staging resources */
Chia-I Wu63636062015-10-26 21:10:41 +08001254 vkFreeMemory(demo->device, tex_objs->mem, NULL);
1255 vkDestroyImage(demo->device, tex_objs->image, NULL);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001256}
1257
Karl Schultze4dc75c2016-02-02 15:37:51 -07001258static void demo_prepare_textures(struct demo *demo) {
Tony Barbour72304ef2015-04-16 15:59:00 -06001259 const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM;
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001260 VkFormatProperties props;
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -06001261 uint32_t i;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001262
Courtney Goeltzenleuchterbd5c1742015-10-20 16:40:38 -06001263 vkGetPhysicalDeviceFormatProperties(demo->gpu, tex_format, &props);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001264
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001265 for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
Courtney Goeltzenleuchterbd5c1742015-10-20 16:40:38 -06001266 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001267
Karl Schultze4dc75c2016-02-02 15:37:51 -07001268 if ((props.linearTilingFeatures &
1269 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) &&
1270 !demo->use_staging_buffer) {
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001271 /* Device can texture using linear textures */
Tony Barbour5342ef52016-04-28 15:05:09 -06001272 demo_prepare_texture_image(
1273 demo, tex_files[i], &demo->textures[i], VK_IMAGE_TILING_LINEAR,
1274 VK_IMAGE_USAGE_SAMPLED_BIT,
1275 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1276 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Karl Schultze4dc75c2016-02-02 15:37:51 -07001277 } else if (props.optimalTilingFeatures &
1278 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001279 /* Must use staging buffer to copy linear texture to optimized */
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001280 struct texture_object staging_texture;
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001281
1282 memset(&staging_texture, 0, sizeof(staging_texture));
Tony Barbour5342ef52016-04-28 15:05:09 -06001283 demo_prepare_texture_image(
1284 demo, tex_files[i], &staging_texture, VK_IMAGE_TILING_LINEAR,
1285 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1286 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1287 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001288
Karl Schultze4dc75c2016-02-02 15:37:51 -07001289 demo_prepare_texture_image(
1290 demo, tex_files[i], &demo->textures[i], VK_IMAGE_TILING_OPTIMAL,
1291 (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
1292 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001293
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001294 demo_set_image_layout(demo, staging_texture.image,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001295 VK_IMAGE_ASPECT_COLOR_BIT,
1296 staging_texture.imageLayout,
Tobin Ehlisf07d9552016-02-11 17:49:23 -07001297 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1298 0);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001299
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001300 demo_set_image_layout(demo, demo->textures[i].image,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001301 VK_IMAGE_ASPECT_COLOR_BIT,
1302 demo->textures[i].imageLayout,
Tobin Ehlisf07d9552016-02-11 17:49:23 -07001303 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1304 0);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001305
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001306 VkImageCopy copy_region = {
Karl Schultze4dc75c2016-02-02 15:37:51 -07001307 .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
1308 .srcOffset = {0, 0, 0},
1309 .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
1310 .dstOffset = {0, 0, 0},
1311 .extent = {staging_texture.tex_width,
1312 staging_texture.tex_height, 1},
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001313 };
Karl Schultze4dc75c2016-02-02 15:37:51 -07001314 vkCmdCopyImage(
1315 demo->cmd, staging_texture.image,
1316 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, demo->textures[i].image,
1317 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_region);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001318
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001319 demo_set_image_layout(demo, demo->textures[i].image,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001320 VK_IMAGE_ASPECT_COLOR_BIT,
1321 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
Tobin Ehlisf07d9552016-02-11 17:49:23 -07001322 demo->textures[i].imageLayout,
1323 0);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001324
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001325 demo_flush_init_cmd(demo);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001326
Courtney Goeltzenleuchterf3aeb2b2015-04-21 09:30:03 -06001327 demo_destroy_texture_image(demo, &staging_texture);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001328 } else {
Mike Stroyan8b89e072015-06-15 14:21:03 -06001329 /* Can't support VK_FORMAT_R8G8B8A8_UNORM !? */
1330 assert(!"No support for R8G8B8A8_UNORM as texture image format");
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001331 }
1332
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001333 const VkSamplerCreateInfo sampler = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001334 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001335 .pNext = NULL,
Chia-I Wu6ef8c3b2015-10-26 16:49:32 +08001336 .magFilter = VK_FILTER_NEAREST,
1337 .minFilter = VK_FILTER_NEAREST,
Jon Ashburn0bec67e2016-01-11 13:12:43 -07001338 .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
Chia-I Wu6555f3f2015-10-26 17:32:47 +08001339 .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1340 .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1341 .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001342 .mipLodBias = 0.0f,
Jon Ashburn55e3fb02015-12-14 14:59:20 -07001343 .anisotropyEnable = VK_FALSE,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001344 .maxAnisotropy = 1,
Tony Barbour72304ef2015-04-16 15:59:00 -06001345 .compareOp = VK_COMPARE_OP_NEVER,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001346 .minLod = 0.0f,
1347 .maxLod = 0.0f,
Tony Barbourcb530c72015-06-25 16:56:44 -06001348 .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
Mark Lobodzinski644dc492015-09-01 15:42:56 -06001349 .unnormalizedCoordinates = VK_FALSE,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001350 };
Courtney Goeltzenleuchter68369392014-10-29 15:59:49 -06001351
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001352 VkImageViewCreateInfo view = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001353 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001354 .pNext = NULL,
Chia-I Wu1c4086a2015-10-26 20:04:44 +08001355 .image = VK_NULL_HANDLE,
Tony Barbour72304ef2015-04-16 15:59:00 -06001356 .viewType = VK_IMAGE_VIEW_TYPE_2D,
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07001357 .format = tex_format,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001358 .components =
1359 {
1360 VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
1361 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A,
1362 },
1363 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -06001364 .flags = 0,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001365 };
Jon Ashburnb2a66652015-01-16 09:37:43 -07001366
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001367 /* create sampler */
Chia-I Wu63636062015-10-26 21:10:41 +08001368 err = vkCreateSampler(demo->device, &sampler, NULL,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001369 &demo->textures[i].sampler);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001370 assert(!err);
1371
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001372 /* create image view */
1373 view.image = demo->textures[i].image;
Chia-I Wu63636062015-10-26 21:10:41 +08001374 err = vkCreateImageView(demo->device, &view, NULL,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001375 &demo->textures[i].view);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001376 assert(!err);
1377 }
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001378}
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001379
Karl Schultze4dc75c2016-02-02 15:37:51 -07001380void demo_prepare_cube_data_buffer(struct demo *demo) {
Courtney Goeltzenleuchter28c4d5f2015-04-14 18:48:46 -06001381 VkBufferCreateInfo buf_info;
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001382 VkMemoryRequirements mem_reqs;
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -06001383 uint8_t *pData;
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001384 int i;
1385 mat4x4 MVP, VP;
Tony Barbourfdc2d352015-04-22 09:02:32 -06001386 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter87a0ef02015-10-22 11:03:31 -06001387 bool U_ASSERT_ONLY pass;
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001388 struct vktexcube_vs_uniform data;
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001389
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001390 mat4x4_mul(VP, demo->projection_matrix, demo->view_matrix);
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001391 mat4x4_mul(MVP, VP, demo->model_matrix);
1392 memcpy(data.mvp, MVP, sizeof(MVP));
Karl Schultze4dc75c2016-02-02 15:37:51 -07001393 // dumpMatrix("MVP", MVP);
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001394
Karl Schultze4dc75c2016-02-02 15:37:51 -07001395 for (i = 0; i < 12 * 3; i++) {
1396 data.position[i][0] = g_vertex_buffer_data[i * 3];
1397 data.position[i][1] = g_vertex_buffer_data[i * 3 + 1];
1398 data.position[i][2] = g_vertex_buffer_data[i * 3 + 2];
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001399 data.position[i][3] = 1.0f;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001400 data.attr[i][0] = g_uv_buffer_data[2 * i];
1401 data.attr[i][1] = g_uv_buffer_data[2 * i + 1];
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001402 data.attr[i][2] = 0;
1403 data.attr[i][3] = 0;
1404 }
1405
Chia-I Wu8ea21c72015-01-01 07:55:04 +08001406 memset(&buf_info, 0, sizeof(buf_info));
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001407 buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
Courtney Goeltzenleuchter42a078d2015-04-15 15:29:59 -06001408 buf_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
Cody Northrop91807302015-07-16 10:29:32 -06001409 buf_info.size = sizeof(data);
Karl Schultze4dc75c2016-02-02 15:37:51 -07001410 err =
1411 vkCreateBuffer(demo->device, &buf_info, NULL, &demo->uniform_data.buf);
Chia-I Wu8ea21c72015-01-01 07:55:04 +08001412 assert(!err);
1413
Karl Schultze4dc75c2016-02-02 15:37:51 -07001414 vkGetBufferMemoryRequirements(demo->device, demo->uniform_data.buf,
1415 &mem_reqs);
Chia-I Wu8ea21c72015-01-01 07:55:04 +08001416
Chia-I Wuf48700b2015-11-10 16:21:09 +08001417 demo->uniform_data.mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
Dominik Witczak2fe1c702015-09-22 18:25:33 +02001418 demo->uniform_data.mem_alloc.pNext = NULL;
1419 demo->uniform_data.mem_alloc.allocationSize = mem_reqs.size;
1420 demo->uniform_data.mem_alloc.memoryTypeIndex = 0;
1421
Karl Schultze4dc75c2016-02-02 15:37:51 -07001422 pass = memory_type_from_properties(
Tony Barbour5342ef52016-04-28 15:05:09 -06001423 demo, mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1424 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001425 &demo->uniform_data.mem_alloc.memoryTypeIndex);
Courtney Goeltzenleuchter87a0ef02015-10-22 11:03:31 -06001426 assert(pass);
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001427
Karl Schultze4dc75c2016-02-02 15:37:51 -07001428 err = vkAllocateMemory(demo->device, &demo->uniform_data.mem_alloc, NULL,
1429 &(demo->uniform_data.mem));
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001430 assert(!err);
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001431
Karl Schultze4dc75c2016-02-02 15:37:51 -07001432 err = vkMapMemory(demo->device, demo->uniform_data.mem, 0,
1433 demo->uniform_data.mem_alloc.allocationSize, 0,
1434 (void **)&pData);
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001435 assert(!err);
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001436
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001437 memcpy(pData, &data, sizeof data);
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001438
Mark Lobodzinskie4c92a62015-09-07 13:59:43 -06001439 vkUnmapMemory(demo->device, demo->uniform_data.mem);
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001440
Karl Schultze4dc75c2016-02-02 15:37:51 -07001441 err = vkBindBufferMemory(demo->device, demo->uniform_data.buf,
1442 demo->uniform_data.mem, 0);
Mark Lobodzinski2dcdfd72015-05-29 09:32:35 -05001443 assert(!err);
Chia-I Wu8ea21c72015-01-01 07:55:04 +08001444
Courtney Goeltzenleuchterc3ad65e2015-10-23 13:38:14 -06001445 demo->uniform_data.buffer_info.buffer = demo->uniform_data.buf;
1446 demo->uniform_data.buffer_info.offset = 0;
1447 demo->uniform_data.buffer_info.range = sizeof(data);
Courtney Goeltzenleuchter4984d152014-10-28 14:50:30 -06001448}
1449
Karl Schultze4dc75c2016-02-02 15:37:51 -07001450static void demo_prepare_descriptor_layout(struct demo *demo) {
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001451 const VkDescriptorSetLayoutBinding layout_bindings[2] = {
Karl Schultze4dc75c2016-02-02 15:37:51 -07001452 [0] =
1453 {
1454 .binding = 0,
1455 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1456 .descriptorCount = 1,
1457 .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
1458 .pImmutableSamplers = NULL,
1459 },
1460 [1] =
1461 {
1462 .binding = 1,
1463 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1464 .descriptorCount = DEMO_TEXTURE_COUNT,
1465 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
1466 .pImmutableSamplers = NULL,
1467 },
Chia-I Wua2aa8632015-03-26 15:04:41 +08001468 };
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001469 const VkDescriptorSetLayoutCreateInfo descriptor_layout = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001470 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001471 .pNext = NULL,
Chia-I Wu3dfc1342015-10-26 20:48:51 +08001472 .bindingCount = 2,
Jon Ashburn238f3432015-12-30 18:01:16 -07001473 .pBindings = layout_bindings,
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001474 };
Tony Barbourfdc2d352015-04-22 09:02:32 -06001475 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001476
Karl Schultze4dc75c2016-02-02 15:37:51 -07001477 err = vkCreateDescriptorSetLayout(demo->device, &descriptor_layout, NULL,
1478 &demo->desc_layout);
Chia-I Wub58c24a2015-03-26 15:27:55 +08001479 assert(!err);
1480
Mark Lobodzinski1cfc7722015-04-17 14:11:39 -05001481 const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
Karl Schultze4dc75c2016-02-02 15:37:51 -07001482 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1483 .pNext = NULL,
Chia-I Wu3dfc1342015-10-26 20:48:51 +08001484 .setLayoutCount = 1,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001485 .pSetLayouts = &demo->desc_layout,
Mark Lobodzinski1cfc7722015-04-17 14:11:39 -05001486 };
1487
Karl Schultze4dc75c2016-02-02 15:37:51 -07001488 err = vkCreatePipelineLayout(demo->device, &pPipelineLayoutCreateInfo, NULL,
Mark Lobodzinski1cfc7722015-04-17 14:11:39 -05001489 &demo->pipeline_layout);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001490 assert(!err);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001491}
1492
Karl Schultze4dc75c2016-02-02 15:37:51 -07001493static void demo_prepare_render_pass(struct demo *demo) {
Chia-I Wua74c5b22015-07-07 11:50:03 +08001494 const VkAttachmentDescription attachments[2] = {
Karl Schultze4dc75c2016-02-02 15:37:51 -07001495 [0] =
1496 {
1497 .format = demo->format,
1498 .samples = VK_SAMPLE_COUNT_1_BIT,
1499 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
1500 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
1501 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1502 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1503 .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Tony Barbour98390392016-07-28 10:50:13 -06001504 .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001505 },
1506 [1] =
1507 {
1508 .format = demo->depth.format,
1509 .samples = VK_SAMPLE_COUNT_1_BIT,
1510 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
1511 .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1512 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1513 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1514 .initialLayout =
1515 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1516 .finalLayout =
1517 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1518 },
Chia-I Wuf973e322015-07-08 13:34:24 +08001519 };
Chia-I Wua74c5b22015-07-07 11:50:03 +08001520 const VkAttachmentReference color_reference = {
Karl Schultze4dc75c2016-02-02 15:37:51 -07001521 .attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Chia-I Wua74c5b22015-07-07 11:50:03 +08001522 };
Chia-I Wu6555f3f2015-10-26 17:32:47 +08001523 const VkAttachmentReference depth_reference = {
1524 .attachment = 1,
1525 .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1526 };
Chia-I Wua74c5b22015-07-07 11:50:03 +08001527 const VkSubpassDescription subpass = {
Chia-I Wua74c5b22015-07-07 11:50:03 +08001528 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
1529 .flags = 0,
Chia-I Wu3dfc1342015-10-26 20:48:51 +08001530 .inputAttachmentCount = 0,
Cody Northrop945bb832015-08-04 11:16:41 -06001531 .pInputAttachments = NULL,
Chia-I Wu3dfc1342015-10-26 20:48:51 +08001532 .colorAttachmentCount = 1,
Cody Northrop945bb832015-08-04 11:16:41 -06001533 .pColorAttachments = &color_reference,
1534 .pResolveAttachments = NULL,
Chia-I Wu6555f3f2015-10-26 17:32:47 +08001535 .pDepthStencilAttachment = &depth_reference,
Chia-I Wu3dfc1342015-10-26 20:48:51 +08001536 .preserveAttachmentCount = 0,
Cody Northrop945bb832015-08-04 11:16:41 -06001537 .pPreserveAttachments = NULL,
Chia-I Wua74c5b22015-07-07 11:50:03 +08001538 };
Chia-I Wuf973e322015-07-08 13:34:24 +08001539 const VkRenderPassCreateInfo rp_info = {
1540 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1541 .pNext = NULL,
Chia-I Wua74c5b22015-07-07 11:50:03 +08001542 .attachmentCount = 2,
1543 .pAttachments = attachments,
1544 .subpassCount = 1,
1545 .pSubpasses = &subpass,
1546 .dependencyCount = 0,
1547 .pDependencies = NULL,
Chia-I Wuf973e322015-07-08 13:34:24 +08001548 };
Chia-I Wua74c5b22015-07-07 11:50:03 +08001549 VkResult U_ASSERT_ONLY err;
Chia-I Wuf973e322015-07-08 13:34:24 +08001550
Chia-I Wu63636062015-10-26 21:10:41 +08001551 err = vkCreateRenderPass(demo->device, &rp_info, NULL, &demo->render_pass);
Chia-I Wuf973e322015-07-08 13:34:24 +08001552 assert(!err);
1553}
1554
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001555//TODO: Merge shader reading
1556#ifndef __ANDROID__
Karl Schultze4dc75c2016-02-02 15:37:51 -07001557static VkShaderModule
1558demo_prepare_shader_module(struct demo *demo, const void *code, size_t size) {
Chia-I Wu46176f12015-10-31 00:31:16 +08001559 VkShaderModule module;
Courtney Goeltzenleuchtera80a1a92015-06-24 18:24:19 -06001560 VkShaderModuleCreateInfo moduleCreateInfo;
Courtney Goeltzenleuchterd3cdaaf2015-12-17 09:53:29 -07001561 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001562
Courtney Goeltzenleuchtera80a1a92015-06-24 18:24:19 -06001563 moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1564 moduleCreateInfo.pNext = NULL;
1565
Courtney Goeltzenleuchtera95e3052015-10-30 15:19:27 -06001566 moduleCreateInfo.codeSize = size;
1567 moduleCreateInfo.pCode = code;
1568 moduleCreateInfo.flags = 0;
1569 err = vkCreateShaderModule(demo->device, &moduleCreateInfo, NULL, &module);
1570 assert(!err);
Chia-I Wu46176f12015-10-31 00:31:16 +08001571
1572 return module;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001573}
1574
Karl Schultze4dc75c2016-02-02 15:37:51 -07001575char *demo_read_spv(const char *filename, size_t *psize) {
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001576 long int size;
Tony Barbourf9921732015-04-22 11:36:22 -06001577 size_t U_ASSERT_ONLY retval;
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001578 void *shader_code;
1579
1580 FILE *fp = fopen(filename, "rb");
Karl Schultze4dc75c2016-02-02 15:37:51 -07001581 if (!fp)
1582 return NULL;
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001583
1584 fseek(fp, 0L, SEEK_END);
1585 size = ftell(fp);
1586
1587 fseek(fp, 0L, SEEK_SET);
1588
1589 shader_code = malloc(size);
Tony Barbourfdc2d352015-04-22 09:02:32 -06001590 retval = fread(shader_code, size, 1, fp);
1591 assert(retval == 1);
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001592
1593 *psize = size;
1594
Mike Stroyan9e9792a2015-10-28 11:15:46 -06001595 fclose(fp);
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001596 return shader_code;
1597}
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001598#endif
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001599
Karl Schultze4dc75c2016-02-02 15:37:51 -07001600static VkShaderModule demo_prepare_vs(struct demo *demo) {
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001601#ifdef __ANDROID__
1602 VkShaderModuleCreateInfo sh_info = {};
1603 sh_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1604
1605#include "cube.vert.h"
1606 sh_info.codeSize = sizeof(cube_vert);
1607 sh_info.pCode = cube_vert;
1608 VkResult U_ASSERT_ONLY err = vkCreateShaderModule(demo->device, &sh_info, NULL, &demo->vert_shader_module);
1609 assert(!err);
1610#else
Courtney Goeltzenleuchtera95e3052015-10-30 15:19:27 -06001611 void *vertShaderCode;
1612 size_t size;
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001613
Courtney Goeltzenleuchtera95e3052015-10-30 15:19:27 -06001614 vertShaderCode = demo_read_spv("cube-vert.spv", &size);
1615
Karl Schultze4dc75c2016-02-02 15:37:51 -07001616 demo->vert_shader_module =
1617 demo_prepare_shader_module(demo, vertShaderCode, size);
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -06001618
Courtney Goeltzenleuchtera95e3052015-10-30 15:19:27 -06001619 free(vertShaderCode);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001620#endif
Chia-I Wu46176f12015-10-31 00:31:16 +08001621
1622 return demo->vert_shader_module;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001623}
1624
Karl Schultze4dc75c2016-02-02 15:37:51 -07001625static VkShaderModule demo_prepare_fs(struct demo *demo) {
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001626#ifdef __ANDROID__
1627 VkShaderModuleCreateInfo sh_info = {};
1628 sh_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1629
1630#include "cube.frag.h"
1631 sh_info.codeSize = sizeof(cube_frag);
1632 sh_info.pCode = cube_frag;
1633 VkResult U_ASSERT_ONLY err = vkCreateShaderModule(demo->device, &sh_info, NULL, &demo->frag_shader_module);
1634 assert(!err);
1635#else
Courtney Goeltzenleuchtera95e3052015-10-30 15:19:27 -06001636 void *fragShaderCode;
1637 size_t size;
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001638
Courtney Goeltzenleuchtera95e3052015-10-30 15:19:27 -06001639 fragShaderCode = demo_read_spv("cube-frag.spv", &size);
Courtney Goeltzenleuchter97db1c12014-10-30 15:14:16 -06001640
Karl Schultze4dc75c2016-02-02 15:37:51 -07001641 demo->frag_shader_module =
1642 demo_prepare_shader_module(demo, fragShaderCode, size);
Courtney Goeltzenleuchterfc3b9532014-10-28 10:32:57 -06001643
Courtney Goeltzenleuchtera95e3052015-10-30 15:19:27 -06001644 free(fragShaderCode);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05001645#endif
Chia-I Wu46176f12015-10-31 00:31:16 +08001646
1647 return demo->frag_shader_module;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001648}
1649
Karl Schultze4dc75c2016-02-02 15:37:51 -07001650static void demo_prepare_pipeline(struct demo *demo) {
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001651 VkGraphicsPipelineCreateInfo pipeline;
Jon Ashburnc4ab7af2015-07-09 15:02:25 -06001652 VkPipelineCacheCreateInfo pipelineCache;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001653 VkPipelineVertexInputStateCreateInfo vi;
Tony Barbour194bf282015-07-10 15:29:03 -06001654 VkPipelineInputAssemblyStateCreateInfo ia;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001655 VkPipelineRasterizationStateCreateInfo rs;
1656 VkPipelineColorBlendStateCreateInfo cb;
1657 VkPipelineDepthStencilStateCreateInfo ds;
1658 VkPipelineViewportStateCreateInfo vp;
1659 VkPipelineMultisampleStateCreateInfo ms;
1660 VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE];
1661 VkPipelineDynamicStateCreateInfo dynamicState;
Tony Barbourfdc2d352015-04-22 09:02:32 -06001662 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001663
Piers Daniellba839d12015-09-29 13:01:09 -06001664 memset(dynamicStateEnables, 0, sizeof dynamicStateEnables);
1665 memset(&dynamicState, 0, sizeof dynamicState);
1666 dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1667 dynamicState.pDynamicStates = dynamicStateEnables;
1668
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001669 memset(&pipeline, 0, sizeof(pipeline));
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001670 pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
Mark Lobodzinski1cfc7722015-04-17 14:11:39 -05001671 pipeline.layout = demo->pipeline_layout;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001672
Jason Ekstrand515b7ae2015-10-15 17:15:25 -07001673 memset(&vi, 0, sizeof(vi));
1674 vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1675
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001676 memset(&ia, 0, sizeof(ia));
Tony Barbour194bf282015-07-10 15:29:03 -06001677 ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
Tony Barbour72304ef2015-04-16 15:59:00 -06001678 ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001679
1680 memset(&rs, 0, sizeof(rs));
Chia-I Wuf051d262015-10-27 19:25:11 +08001681 rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1682 rs.polygonMode = VK_POLYGON_MODE_FILL;
Chia-I Wu6555f3f2015-10-26 17:32:47 +08001683 rs.cullMode = VK_CULL_MODE_BACK_BIT;
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001684 rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
Courtney Goeltzenleuchter0db2c912015-10-15 12:57:38 -06001685 rs.depthClampEnable = VK_FALSE;
Cody Northrop709c1742015-08-17 11:10:49 -06001686 rs.rasterizerDiscardEnable = VK_FALSE;
1687 rs.depthBiasEnable = VK_FALSE;
Mark Young8749e2e2016-03-31 14:56:43 -06001688 rs.lineWidth = 1.0f;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001689
1690 memset(&cb, 0, sizeof(cb));
Tony Barbour194bf282015-07-10 15:29:03 -06001691 cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1692 VkPipelineColorBlendAttachmentState att_state[1];
Tony Barbour29645d02015-01-16 14:27:35 -07001693 memset(att_state, 0, sizeof(att_state));
Chia-I Wuf051d262015-10-27 19:25:11 +08001694 att_state[0].colorWriteMask = 0xf;
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001695 att_state[0].blendEnable = VK_FALSE;
Tony Barbour29645d02015-01-16 14:27:35 -07001696 cb.attachmentCount = 1;
1697 cb.pAttachments = att_state;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001698
Tony Barbour29645d02015-01-16 14:27:35 -07001699 memset(&vp, 0, sizeof(vp));
Tony Barbour194bf282015-07-10 15:29:03 -06001700 vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
Tony Barbour72304ef2015-04-16 15:59:00 -06001701 vp.viewportCount = 1;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001702 dynamicStateEnables[dynamicState.dynamicStateCount++] =
1703 VK_DYNAMIC_STATE_VIEWPORT;
Piers Daniellba839d12015-09-29 13:01:09 -06001704 vp.scissorCount = 1;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001705 dynamicStateEnables[dynamicState.dynamicStateCount++] =
1706 VK_DYNAMIC_STATE_SCISSOR;
Tony Barbour29645d02015-01-16 14:27:35 -07001707
1708 memset(&ds, 0, sizeof(ds));
Tony Barbour194bf282015-07-10 15:29:03 -06001709 ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001710 ds.depthTestEnable = VK_TRUE;
1711 ds.depthWriteEnable = VK_TRUE;
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001712 ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
Cody Northrop5e4125d2015-08-26 10:01:32 -06001713 ds.depthBoundsTestEnable = VK_FALSE;
Chia-I Wuf051d262015-10-27 19:25:11 +08001714 ds.back.failOp = VK_STENCIL_OP_KEEP;
1715 ds.back.passOp = VK_STENCIL_OP_KEEP;
1716 ds.back.compareOp = VK_COMPARE_OP_ALWAYS;
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001717 ds.stencilTestEnable = VK_FALSE;
Tony Barbour29645d02015-01-16 14:27:35 -07001718 ds.front = ds.back;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001719
Tony Barbour29645d02015-01-16 14:27:35 -07001720 memset(&ms, 0, sizeof(ms));
Tony Barbour194bf282015-07-10 15:29:03 -06001721 ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
Cody Northrop011546b2015-08-04 14:34:54 -06001722 ms.pSampleMask = NULL;
Chia-I Wu3ede9462015-10-31 00:31:16 +08001723 ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001724
Mark Lobodzinski521d7762015-06-23 15:11:57 -06001725 // Two stages: vs and fs
1726 pipeline.stageCount = 2;
1727 VkPipelineShaderStageCreateInfo shaderStages[2];
1728 memset(&shaderStages, 0, 2 * sizeof(VkPipelineShaderStageCreateInfo));
1729
Karl Schultze4dc75c2016-02-02 15:37:51 -07001730 shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1731 shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
Chia-I Wu46176f12015-10-31 00:31:16 +08001732 shaderStages[0].module = demo_prepare_vs(demo);
Karl Schultze4dc75c2016-02-02 15:37:51 -07001733 shaderStages[0].pName = "main";
Mark Lobodzinski521d7762015-06-23 15:11:57 -06001734
Karl Schultze4dc75c2016-02-02 15:37:51 -07001735 shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1736 shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
Chia-I Wu46176f12015-10-31 00:31:16 +08001737 shaderStages[1].module = demo_prepare_fs(demo);
Karl Schultze4dc75c2016-02-02 15:37:51 -07001738 shaderStages[1].pName = "main";
Mark Lobodzinski521d7762015-06-23 15:11:57 -06001739
Jon Ashburnc4ab7af2015-07-09 15:02:25 -06001740 memset(&pipelineCache, 0, sizeof(pipelineCache));
1741 pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001742
Karl Schultze4dc75c2016-02-02 15:37:51 -07001743 err = vkCreatePipelineCache(demo->device, &pipelineCache, NULL,
1744 &demo->pipelineCache);
Jon Ashburnc4ab7af2015-07-09 15:02:25 -06001745 assert(!err);
Tony Barbour194bf282015-07-10 15:29:03 -06001746
Karl Schultze4dc75c2016-02-02 15:37:51 -07001747 pipeline.pVertexInputState = &vi;
Tony Barbour194bf282015-07-10 15:29:03 -06001748 pipeline.pInputAssemblyState = &ia;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001749 pipeline.pRasterizationState = &rs;
1750 pipeline.pColorBlendState = &cb;
1751 pipeline.pMultisampleState = &ms;
1752 pipeline.pViewportState = &vp;
1753 pipeline.pDepthStencilState = &ds;
1754 pipeline.pStages = shaderStages;
1755 pipeline.renderPass = demo->render_pass;
1756 pipeline.pDynamicState = &dynamicState;
Tony Barbour194bf282015-07-10 15:29:03 -06001757
Courtney Goeltzenleuchterd311fd02015-08-13 16:55:04 -06001758 pipeline.renderPass = demo->render_pass;
1759
Karl Schultze4dc75c2016-02-02 15:37:51 -07001760 err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1,
1761 &pipeline, NULL, &demo->pipeline);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001762 assert(!err);
1763
Chia-I Wu63636062015-10-26 21:10:41 +08001764 vkDestroyShaderModule(demo->device, demo->frag_shader_module, NULL);
1765 vkDestroyShaderModule(demo->device, demo->vert_shader_module, NULL);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001766}
1767
Karl Schultze4dc75c2016-02-02 15:37:51 -07001768static void demo_prepare_descriptor_pool(struct demo *demo) {
Chia-I Wuf051d262015-10-27 19:25:11 +08001769 const VkDescriptorPoolSize type_counts[2] = {
Karl Schultze4dc75c2016-02-02 15:37:51 -07001770 [0] =
1771 {
1772 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1773 .descriptorCount = 1,
1774 },
1775 [1] =
1776 {
1777 .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1778 .descriptorCount = DEMO_TEXTURE_COUNT,
1779 },
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001780 };
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06001781 const VkDescriptorPoolCreateInfo descriptor_pool = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06001782 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001783 .pNext = NULL,
Courtney Goeltzenleuchtercf92aa42015-09-16 16:12:45 -06001784 .maxSets = 1,
Chia-I Wuf051d262015-10-27 19:25:11 +08001785 .poolSizeCount = 2,
1786 .pPoolSizes = type_counts,
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001787 };
Tony Barbourfdc2d352015-04-22 09:02:32 -06001788 VkResult U_ASSERT_ONLY err;
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001789
Karl Schultze4dc75c2016-02-02 15:37:51 -07001790 err = vkCreateDescriptorPool(demo->device, &descriptor_pool, NULL,
1791 &demo->desc_pool);
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001792 assert(!err);
1793}
1794
Karl Schultze4dc75c2016-02-02 15:37:51 -07001795static void demo_prepare_descriptor_set(struct demo *demo) {
Courtney Goeltzenleuchterc3ad65e2015-10-23 13:38:14 -06001796 VkDescriptorImageInfo tex_descs[DEMO_TEXTURE_COUNT];
Chia-I Wuae721ba2015-05-25 16:27:55 +08001797 VkWriteDescriptorSet writes[2];
Tony Barbourfdc2d352015-04-22 09:02:32 -06001798 VkResult U_ASSERT_ONLY err;
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -06001799 uint32_t i;
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001800
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001801 VkDescriptorSetAllocateInfo alloc_info = {
Chia-I Wuf48700b2015-11-10 16:21:09 +08001802 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
Courtney Goeltzenleuchter014ded82015-10-23 14:21:05 -06001803 .pNext = NULL,
1804 .descriptorPool = demo->desc_pool,
Jon Ashburn0bec67e2016-01-11 13:12:43 -07001805 .descriptorSetCount = 1,
Karl Schultze4dc75c2016-02-02 15:37:51 -07001806 .pSetLayouts = &demo->desc_layout};
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001807 err = vkAllocateDescriptorSets(demo->device, &alloc_info, &demo->desc_set);
Cody Northrop15954692015-08-03 12:47:29 -06001808 assert(!err);
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001809
Chia-I Wuae721ba2015-05-25 16:27:55 +08001810 memset(&tex_descs, 0, sizeof(tex_descs));
1811 for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
Courtney Goeltzenleuchterc3ad65e2015-10-23 13:38:14 -06001812 tex_descs[i].sampler = demo->textures[i].sampler;
1813 tex_descs[i].imageView = demo->textures[i].view;
1814 tex_descs[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
Chia-I Wuae721ba2015-05-25 16:27:55 +08001815 }
1816
1817 memset(&writes, 0, sizeof(writes));
1818
1819 writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001820 writes[0].dstSet = demo->desc_set;
Chia-I Wu3dfc1342015-10-26 20:48:51 +08001821 writes[0].descriptorCount = 1;
Chia-I Wuae721ba2015-05-25 16:27:55 +08001822 writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
Courtney Goeltzenleuchterc3ad65e2015-10-23 13:38:14 -06001823 writes[0].pBufferInfo = &demo->uniform_data.buffer_info;
Chia-I Wuae721ba2015-05-25 16:27:55 +08001824
1825 writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001826 writes[1].dstSet = demo->desc_set;
1827 writes[1].dstBinding = 1;
Chia-I Wu3dfc1342015-10-26 20:48:51 +08001828 writes[1].descriptorCount = DEMO_TEXTURE_COUNT;
Chia-I Wuae721ba2015-05-25 16:27:55 +08001829 writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
Courtney Goeltzenleuchterc3ad65e2015-10-23 13:38:14 -06001830 writes[1].pImageInfo = tex_descs;
Chia-I Wuae721ba2015-05-25 16:27:55 +08001831
Mark Lobodzinskie4c92a62015-09-07 13:59:43 -06001832 vkUpdateDescriptorSets(demo->device, 2, writes, 0, NULL);
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001833}
1834
Karl Schultze4dc75c2016-02-02 15:37:51 -07001835static void demo_prepare_framebuffers(struct demo *demo) {
Courtney Goeltzenleuchter41866db2015-09-01 17:30:39 -06001836 VkImageView attachments[2];
Cody Northrop2e11cad2015-08-04 10:47:08 -06001837 attachments[1] = demo->depth.view;
1838
Chia-I Wuf973e322015-07-08 13:34:24 +08001839 const VkFramebufferCreateInfo fb_info = {
Karl Schultze4dc75c2016-02-02 15:37:51 -07001840 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
1841 .pNext = NULL,
1842 .renderPass = demo->render_pass,
1843 .attachmentCount = 2,
1844 .pAttachments = attachments,
1845 .width = demo->width,
1846 .height = demo->height,
1847 .layers = 1,
Chia-I Wuf973e322015-07-08 13:34:24 +08001848 };
1849 VkResult U_ASSERT_ONLY err;
1850 uint32_t i;
1851
Karl Schultze4dc75c2016-02-02 15:37:51 -07001852 demo->framebuffers = (VkFramebuffer *)malloc(demo->swapchainImageCount *
1853 sizeof(VkFramebuffer));
Tony Barbourd8e504f2015-10-08 14:26:24 -06001854 assert(demo->framebuffers);
1855
1856 for (i = 0; i < demo->swapchainImageCount; i++) {
Cody Northrop2e11cad2015-08-04 10:47:08 -06001857 attachments[0] = demo->buffers[i].view;
Karl Schultze4dc75c2016-02-02 15:37:51 -07001858 err = vkCreateFramebuffer(demo->device, &fb_info, NULL,
1859 &demo->framebuffers[i]);
Chia-I Wuf973e322015-07-08 13:34:24 +08001860 assert(!err);
1861 }
1862}
1863
Karl Schultze4dc75c2016-02-02 15:37:51 -07001864static void demo_prepare(struct demo *demo) {
Cody Northrop91e221b2015-07-09 18:08:32 -06001865 VkResult U_ASSERT_ONLY err;
1866
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001867 const VkCommandPoolCreateInfo cmd_pool_info = {
1868 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
Cody Northrop91e221b2015-07-09 18:08:32 -06001869 .pNext = NULL,
Tony Barboura2a67812016-07-18 13:21:06 -06001870 .queueFamilyIndex = demo->graphics_queue_family_index,
Cody Northrop91e221b2015-07-09 18:08:32 -06001871 .flags = 0,
1872 };
Karl Schultze4dc75c2016-02-02 15:37:51 -07001873 err = vkCreateCommandPool(demo->device, &cmd_pool_info, NULL,
1874 &demo->cmd_pool);
Cody Northrop91e221b2015-07-09 18:08:32 -06001875 assert(!err);
1876
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001877 const VkCommandBufferAllocateInfo cmd = {
Chia-I Wuf48700b2015-11-10 16:21:09 +08001878 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001879 .pNext = NULL,
Chia-I Wua8fe78a2015-10-27 18:04:07 +08001880 .commandPool = demo->cmd_pool,
1881 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
Jon Ashburn0bec67e2016-01-11 13:12:43 -07001882 .commandBufferCount = 1,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001883 };
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001884
1885 demo_prepare_buffers(demo);
1886 demo_prepare_depth(demo);
1887 demo_prepare_textures(demo);
Courtney Goeltzenleuchter8879d3a2014-10-29 08:29:35 -06001888 demo_prepare_cube_data_buffer(demo);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001889
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001890 demo_prepare_descriptor_layout(demo);
Chia-I Wuf973e322015-07-08 13:34:24 +08001891 demo_prepare_render_pass(demo);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001892 demo_prepare_pipeline(demo);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001893
Ian Elliotta0781972015-08-21 15:09:33 -06001894 for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
Karl Schultze4dc75c2016-02-02 15:37:51 -07001895 err =
1896 vkAllocateCommandBuffers(demo->device, &cmd, &demo->buffers[i].cmd);
Courtney Goeltzenleuchterefc58ae2015-02-17 09:48:44 -07001897 assert(!err);
1898 }
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001899
Tony Barbour22e06272016-09-07 16:07:56 -06001900 if (demo->separate_present_queue) {
1901 const VkCommandPoolCreateInfo cmd_pool_info = {
1902 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
1903 .pNext = NULL,
1904 .queueFamilyIndex = demo->present_queue_family_index,
1905 .flags = 0,
1906 };
1907 err = vkCreateCommandPool(demo->device, &cmd_pool_info, NULL,
1908 &demo->present_cmd_pool);
1909 assert(!err);
1910 const VkCommandBufferAllocateInfo cmd = {
1911 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1912 .pNext = NULL,
1913 .commandPool = demo->present_cmd_pool,
1914 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1915 .commandBufferCount = 1,
1916 };
1917 for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
1918 err = vkAllocateCommandBuffers(
1919 demo->device, &cmd, &demo->buffers[i].graphics_to_present_cmd);
1920 assert(!err);
1921 demo_build_image_ownership_cmd(demo, i);
1922 }
1923 }
1924
Chia-I Wu63ea9262015-03-26 13:14:16 +08001925 demo_prepare_descriptor_pool(demo);
Chia-I Wu6a3c8972015-01-04 16:27:24 +08001926 demo_prepare_descriptor_set(demo);
Courtney Goeltzenleuchterefc58ae2015-02-17 09:48:44 -07001927
Chia-I Wuf973e322015-07-08 13:34:24 +08001928 demo_prepare_framebuffers(demo);
Courtney Goeltzenleuchterefc58ae2015-02-17 09:48:44 -07001929
Ian Elliotta0781972015-08-21 15:09:33 -06001930 for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
Courtney Goeltzenleuchterefc58ae2015-02-17 09:48:44 -07001931 demo->current_buffer = i;
1932 demo_draw_build_cmd(demo, demo->buffers[i].cmd);
1933 }
1934
Courtney Goeltzenleuchter752eb8e2015-03-25 13:36:41 -06001935 /*
1936 * Prepare functions above may generate pipeline commands
1937 * that need to be flushed before beginning the render loop.
1938 */
1939 demo_flush_init_cmd(demo);
1940
Courtney Goeltzenleuchterefc58ae2015-02-17 09:48:44 -07001941 demo->current_buffer = 0;
Mike Stroyanbb60b382015-10-28 09:46:57 -06001942 demo->prepared = true;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06001943}
1944
Karl Schultze4dc75c2016-02-02 15:37:51 -07001945static void demo_cleanup(struct demo *demo) {
David Pinedo2bb7c932015-06-18 17:03:14 -06001946 uint32_t i;
1947
1948 demo->prepared = false;
Tony Barbource7524e2016-07-28 12:01:45 -06001949 vkDeviceWaitIdle(demo->device);
David Pinedo2bb7c932015-06-18 17:03:14 -06001950
Tony Barbourd8e504f2015-10-08 14:26:24 -06001951 for (i = 0; i < demo->swapchainImageCount; i++) {
Chia-I Wu63636062015-10-26 21:10:41 +08001952 vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
Tony Barbour155cce82015-07-03 10:33:54 -06001953 }
Tony Barbourd8e504f2015-10-08 14:26:24 -06001954 free(demo->framebuffers);
Chia-I Wu63636062015-10-26 21:10:41 +08001955 vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
Chia-I Wuf973e322015-07-08 13:34:24 +08001956
Chia-I Wu63636062015-10-26 21:10:41 +08001957 vkDestroyPipeline(demo->device, demo->pipeline, NULL);
1958 vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
1959 vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
1960 vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
1961 vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
David Pinedo2bb7c932015-06-18 17:03:14 -06001962
1963 for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
Chia-I Wu63636062015-10-26 21:10:41 +08001964 vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
1965 vkDestroyImage(demo->device, demo->textures[i].image, NULL);
1966 vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
1967 vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
David Pinedo2bb7c932015-06-18 17:03:14 -06001968 }
Ian Elliottb08e0d92015-11-20 11:55:46 -07001969 demo->fpDestroySwapchainKHR(demo->device, demo->swapchain, NULL);
David Pinedo2bb7c932015-06-18 17:03:14 -06001970
Chia-I Wu63636062015-10-26 21:10:41 +08001971 vkDestroyImageView(demo->device, demo->depth.view, NULL);
1972 vkDestroyImage(demo->device, demo->depth.image, NULL);
1973 vkFreeMemory(demo->device, demo->depth.mem, NULL);
David Pinedo2bb7c932015-06-18 17:03:14 -06001974
Chia-I Wu63636062015-10-26 21:10:41 +08001975 vkDestroyBuffer(demo->device, demo->uniform_data.buf, NULL);
1976 vkFreeMemory(demo->device, demo->uniform_data.mem, NULL);
David Pinedo2bb7c932015-06-18 17:03:14 -06001977
Ian Elliotta0781972015-08-21 15:09:33 -06001978 for (i = 0; i < demo->swapchainImageCount; i++) {
Chia-I Wu63636062015-10-26 21:10:41 +08001979 vkDestroyImageView(demo->device, demo->buffers[i].view, NULL);
Karl Schultze4dc75c2016-02-02 15:37:51 -07001980 vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1,
1981 &demo->buffers[i].cmd);
David Pinedo2bb7c932015-06-18 17:03:14 -06001982 }
Ian Elliottaaae5352015-07-06 14:27:58 -06001983 free(demo->buffers);
David Pinedo2bb7c932015-06-18 17:03:14 -06001984
Courtney Goeltzenleuchter874eb8d2015-09-24 17:16:48 -06001985 free(demo->queue_props);
1986
Chia-I Wu63636062015-10-26 21:10:41 +08001987 vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
Tony Barbource7524e2016-07-28 12:01:45 -06001988 vkDestroySemaphore(demo->device, demo->image_acquired_semaphore, NULL);
1989 vkDestroySemaphore(demo->device, demo->draw_complete_semaphore, NULL);
Tony Barbour22e06272016-09-07 16:07:56 -06001990 if (demo->separate_present_queue) {
1991 vkDestroyCommandPool(demo->device, demo->present_cmd_pool, NULL);
1992 vkDestroySemaphore(demo->device, demo->image_ownership_semaphore, NULL);
1993 }
Chia-I Wu63636062015-10-26 21:10:41 +08001994 vkDestroyDevice(demo->device, NULL);
Tony Barbourd70b42c2015-06-30 14:14:19 -06001995 if (demo->validate) {
Courtney Goeltzenleuchter2dafae42015-11-30 12:13:14 -07001996 demo->DestroyDebugReportCallback(demo->inst, demo->msg_callback, NULL);
Tony Barbourd70b42c2015-06-30 14:14:19 -06001997 }
Ian Elliottb08e0d92015-11-20 11:55:46 -07001998 vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
Chia-I Wu63636062015-10-26 21:10:41 +08001999 vkDestroyInstance(demo->inst, NULL);
David Pinedo2bb7c932015-06-18 17:03:14 -06002000
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002001#if defined(VK_USE_PLATFORM_XLIB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06002002 if (demo->use_xlib) {
2003 XDestroyWindow(demo->display, demo->xlib_window);
2004 XCloseDisplay(demo->display);
2005 } else {
2006 xcb_destroy_window(demo->connection, demo->xcb_window);
2007 xcb_disconnect(demo->connection);
2008 }
Courtney Goeltzenleuchter874eb8d2015-09-24 17:16:48 -06002009 free(demo->atom_wm_delete_window);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002010#elif defined(VK_USE_PLATFORM_XCB_KHR)
Pavol Klacansky573a19d2016-05-10 03:08:19 -06002011 xcb_destroy_window(demo->connection, demo->xcb_window);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002012 xcb_disconnect(demo->connection);
2013 free(demo->atom_wm_delete_window);
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09002014#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
2015 wl_shell_surface_destroy(demo->shell_surface);
2016 wl_surface_destroy(demo->window);
2017 wl_shell_destroy(demo->shell);
2018 wl_compositor_destroy(demo->compositor);
2019 wl_registry_destroy(demo->registry);
2020 wl_display_disconnect(demo->display);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002021#endif
David Pinedo2bb7c932015-06-18 17:03:14 -06002022}
2023
Karl Schultze4dc75c2016-02-02 15:37:51 -07002024static void demo_resize(struct demo *demo) {
Ian Elliottcf074d32015-10-16 18:02:43 -06002025 uint32_t i;
2026
Mike Stroyanbb60b382015-10-28 09:46:57 -06002027 // Don't react to resize until after first initialization.
2028 if (!demo->prepared) {
2029 return;
2030 }
Ian Elliottcf074d32015-10-16 18:02:43 -06002031 // In order to properly resize the window, we must re-create the swapchain
2032 // AND redo the command buffers, etc.
2033 //
2034 // First, perform part of the demo_cleanup() function:
2035 demo->prepared = false;
Tony Barbource7524e2016-07-28 12:01:45 -06002036 vkDeviceWaitIdle(demo->device);
Ian Elliottcf074d32015-10-16 18:02:43 -06002037
2038 for (i = 0; i < demo->swapchainImageCount; i++) {
Chia-I Wu63636062015-10-26 21:10:41 +08002039 vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
Ian Elliottcf074d32015-10-16 18:02:43 -06002040 }
2041 free(demo->framebuffers);
Chia-I Wu63636062015-10-26 21:10:41 +08002042 vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
Ian Elliottcf074d32015-10-16 18:02:43 -06002043
Chia-I Wu63636062015-10-26 21:10:41 +08002044 vkDestroyPipeline(demo->device, demo->pipeline, NULL);
2045 vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
2046 vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
2047 vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
2048 vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
Ian Elliottcf074d32015-10-16 18:02:43 -06002049
2050 for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
Chia-I Wu63636062015-10-26 21:10:41 +08002051 vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
2052 vkDestroyImage(demo->device, demo->textures[i].image, NULL);
2053 vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
2054 vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
Ian Elliottcf074d32015-10-16 18:02:43 -06002055 }
Ian Elliottcf074d32015-10-16 18:02:43 -06002056
Chia-I Wu63636062015-10-26 21:10:41 +08002057 vkDestroyImageView(demo->device, demo->depth.view, NULL);
2058 vkDestroyImage(demo->device, demo->depth.image, NULL);
2059 vkFreeMemory(demo->device, demo->depth.mem, NULL);
Ian Elliottcf074d32015-10-16 18:02:43 -06002060
Chia-I Wu63636062015-10-26 21:10:41 +08002061 vkDestroyBuffer(demo->device, demo->uniform_data.buf, NULL);
2062 vkFreeMemory(demo->device, demo->uniform_data.mem, NULL);
Ian Elliottcf074d32015-10-16 18:02:43 -06002063
2064 for (i = 0; i < demo->swapchainImageCount; i++) {
Chia-I Wu63636062015-10-26 21:10:41 +08002065 vkDestroyImageView(demo->device, demo->buffers[i].view, NULL);
Karl Schultze4dc75c2016-02-02 15:37:51 -07002066 vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1,
2067 &demo->buffers[i].cmd);
Ian Elliottcf074d32015-10-16 18:02:43 -06002068 }
Chia-I Wu63636062015-10-26 21:10:41 +08002069 vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
Tony Barbour22e06272016-09-07 16:07:56 -06002070 if (demo->separate_present_queue) {
2071 vkDestroyCommandPool(demo->device, demo->present_cmd_pool, NULL);
2072 }
Ian Elliottcf074d32015-10-16 18:02:43 -06002073 free(demo->buffers);
2074
Ian Elliottcf074d32015-10-16 18:02:43 -06002075 // Second, re-perform the demo_prepare() function, which will re-create the
2076 // swapchain:
2077 demo_prepare(demo);
2078}
2079
David Pinedo2bb7c932015-06-18 17:03:14 -06002080// On MS-Windows, make this a global, so it's available to WndProc()
2081struct demo demo;
2082
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002083#if defined(VK_USE_PLATFORM_WIN32_KHR)
Karl Schultze4dc75c2016-02-02 15:37:51 -07002084static void demo_run(struct demo *demo) {
Courtney Goeltzenleuchterb7e22702015-04-27 14:56:34 -06002085 if (!demo->prepared)
2086 return;
Tony Barbource7524e2016-07-28 12:01:45 -06002087
Ian Elliott639ca472015-04-16 15:23:05 -06002088 demo_update_data_buffer(demo);
Ian Elliott639ca472015-04-16 15:23:05 -06002089 demo_draw(demo);
David Pinedo2bb7c932015-06-18 17:03:14 -06002090 demo->curFrame++;
Karl Schultze4dc75c2016-02-02 15:37:51 -07002091 if (demo->frameCount != INT_MAX && demo->curFrame == demo->frameCount) {
Karl Schultz8a663912016-03-24 18:43:41 -06002092 PostQuitMessage(validation_error);
David Pinedo2bb7c932015-06-18 17:03:14 -06002093 }
David Pinedo2bb7c932015-06-18 17:03:14 -06002094}
Ian Elliott639ca472015-04-16 15:23:05 -06002095
2096// MS-Windows event handling function:
Karl Schultze4dc75c2016-02-02 15:37:51 -07002097LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
2098 switch (uMsg) {
Ian Elliottaaae5352015-07-06 14:27:58 -06002099 case WM_CLOSE:
Karl Schultz0218c002016-03-22 17:06:13 -06002100 PostQuitMessage(validation_error);
Tony Barbour3dddd5d2015-04-29 16:19:20 -06002101 break;
Ian Elliottaaae5352015-07-06 14:27:58 -06002102 case WM_PAINT:
Tony Barbour602ca4f2016-09-12 14:02:43 -06002103 // The validation callback calls MessageBox which can generate paint
2104 // events - don't make more Vulkan calls if we got here from the
2105 // callback
2106 if (!in_callback) {
2107 demo_run(&demo);
2108 }
Tony Barbourc8a59892015-10-20 12:49:46 -06002109 break;
Rene Lindsayb9403da2016-07-01 18:00:30 -06002110 case WM_GETMINMAXINFO: // set window's minimum size
2111 ((MINMAXINFO*)lParam)->ptMinTrackSize = demo.minsize;
2112 return 0;
Ian Elliott5ef45e92015-10-21 15:14:07 -06002113 case WM_SIZE:
Piers Daniellc0b6e432016-02-18 10:54:15 -07002114 // Resize the application to the new window size, except when
2115 // it was minimized. Vulkan doesn't support images or swapchains
2116 // with width=0 and height=0.
2117 if (wParam != SIZE_MINIMIZED) {
2118 demo.width = lParam & 0xffff;
Tony Barbourb3237202016-08-10 13:39:36 -06002119 demo.height = (lParam & 0xffff0000) >> 16;
Piers Daniellc0b6e432016-02-18 10:54:15 -07002120 demo_resize(&demo);
2121 }
Ian Elliott5ef45e92015-10-21 15:14:07 -06002122 break;
Ian Elliott639ca472015-04-16 15:23:05 -06002123 default:
2124 break;
2125 }
2126 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
2127}
2128
Karl Schultze4dc75c2016-02-02 15:37:51 -07002129static void demo_create_window(struct demo *demo) {
2130 WNDCLASSEX win_class;
Ian Elliott639ca472015-04-16 15:23:05 -06002131
2132 // Initialize the window class structure:
2133 win_class.cbSize = sizeof(WNDCLASSEX);
2134 win_class.style = CS_HREDRAW | CS_VREDRAW;
2135 win_class.lpfnWndProc = WndProc;
2136 win_class.cbClsExtra = 0;
2137 win_class.cbWndExtra = 0;
2138 win_class.hInstance = demo->connection; // hInstance
2139 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
2140 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
2141 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
2142 win_class.lpszMenuName = NULL;
2143 win_class.lpszClassName = demo->name;
2144 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
2145 // Register window class:
2146 if (!RegisterClassEx(&win_class)) {
2147 // It didn't work, so try to give a useful error:
2148 printf("Unexpected error trying to start the application!\n");
2149 fflush(stdout);
2150 exit(1);
2151 }
2152 // Create window with the registered class:
Karl Schultze4dc75c2016-02-02 15:37:51 -07002153 RECT wr = {0, 0, demo->width, demo->height};
Mike Stroyanb46779e2015-06-15 14:20:13 -06002154 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
Ian Elliott639ca472015-04-16 15:23:05 -06002155 demo->window = CreateWindowEx(0,
2156 demo->name, // class name
2157 demo->name, // app name
2158 WS_OVERLAPPEDWINDOW | // window style
Karl Schultze4dc75c2016-02-02 15:37:51 -07002159 WS_VISIBLE | WS_SYSMENU,
2160 100, 100, // x/y coords
2161 wr.right - wr.left, // width
2162 wr.bottom - wr.top, // height
2163 NULL, // handle to parent
2164 NULL, // handle to menu
2165 demo->connection, // hInstance
2166 NULL); // no extra parameters
Ian Elliott639ca472015-04-16 15:23:05 -06002167 if (!demo->window) {
2168 // It didn't work, so try to give a useful error:
2169 printf("Cannot create a window in which to draw!\n");
2170 fflush(stdout);
2171 exit(1);
2172 }
Rene Lindsayb9403da2016-07-01 18:00:30 -06002173 // Window client area size must be at least 1 pixel high, to prevent crash.
2174 demo->minsize.x = GetSystemMetrics(SM_CXMINTRACK);
2175 demo->minsize.y = GetSystemMetrics(SM_CYMINTRACK)+1;
Ian Elliott639ca472015-04-16 15:23:05 -06002176}
Tony Barbour8295ac42016-08-08 11:04:17 -06002177#elif defined(VK_USE_PLATFORM_XLIB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06002178static void demo_create_xlib_window(struct demo *demo) {
2179
2180 demo->display = XOpenDisplay(NULL);
2181 long visualMask = VisualScreenMask;
2182 int numberOfVisuals;
Rene Lindsay11612722016-06-13 17:20:39 -06002183 XVisualInfo vInfoTemplate={};
Tony Barbour2593b182016-04-19 10:57:58 -06002184 vInfoTemplate.screen = DefaultScreen(demo->display);
2185 XVisualInfo *visualInfo = XGetVisualInfo(demo->display, visualMask,
2186 &vInfoTemplate, &numberOfVisuals);
2187
2188 Colormap colormap = XCreateColormap(
2189 demo->display, RootWindow(demo->display, vInfoTemplate.screen),
2190 visualInfo->visual, AllocNone);
2191
Rene Lindsay11612722016-06-13 17:20:39 -06002192 XSetWindowAttributes windowAttributes={};
Tony Barbour2593b182016-04-19 10:57:58 -06002193 windowAttributes.colormap = colormap;
2194 windowAttributes.background_pixel = 0xFFFFFFFF;
2195 windowAttributes.border_pixel = 0;
2196 windowAttributes.event_mask =
2197 KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask;
2198
2199 demo->xlib_window = XCreateWindow(
2200 demo->display, RootWindow(demo->display, vInfoTemplate.screen), 0, 0,
2201 demo->width, demo->height, 0, visualInfo->depth, InputOutput,
2202 visualInfo->visual,
2203 CWBackPixel | CWBorderPixel | CWEventMask | CWColormap, &windowAttributes);
2204
2205 XSelectInput(demo->display, demo->xlib_window, ExposureMask | KeyPressMask);
2206 XMapWindow(demo->display, demo->xlib_window);
2207 XFlush(demo->display);
2208 demo->xlib_wm_delete_window =
2209 XInternAtom(demo->display, "WM_DELETE_WINDOW", False);
2210}
2211static void demo_handle_xlib_event(struct demo *demo, const XEvent *event) {
2212 switch(event->type) {
2213 case ClientMessage:
2214 if ((Atom)event->xclient.data.l[0] == demo->xlib_wm_delete_window)
2215 demo->quit = true;
2216 break;
2217 case KeyPress:
2218 switch (event->xkey.keycode) {
2219 case 0x9: // Escape
2220 demo->quit = true;
2221 break;
2222 case 0x71: // left arrow key
2223 demo->spin_angle += demo->spin_increment;
2224 break;
2225 case 0x72: // right arrow key
2226 demo->spin_angle -= demo->spin_increment;
2227 break;
2228 case 0x41:
2229 demo->pause = !demo->pause;
2230 break;
2231 }
2232 break;
2233 case ConfigureNotify:
2234 if ((demo->width != event->xconfigure.width) ||
2235 (demo->height != event->xconfigure.height)) {
2236 demo->width = event->xconfigure.width;
2237 demo->height = event->xconfigure.height;
2238 demo_resize(demo);
2239 }
2240 break;
2241 default:
2242 break;
2243 }
2244
2245}
2246
2247static void demo_run_xlib(struct demo *demo) {
2248
2249 while (!demo->quit) {
2250 XEvent event;
2251
2252 if (demo->pause) {
2253 XNextEvent(demo->display, &event);
2254 demo_handle_xlib_event(demo, &event);
2255 } else {
2256 while (XPending(demo->display) > 0) {
2257 XNextEvent(demo->display, &event);
2258 demo_handle_xlib_event(demo, &event);
2259 }
2260 }
2261
Tony Barbour2593b182016-04-19 10:57:58 -06002262 demo_update_data_buffer(demo);
Tony Barbour2593b182016-04-19 10:57:58 -06002263 demo_draw(demo);
Tony Barbour2593b182016-04-19 10:57:58 -06002264 demo->curFrame++;
2265 if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
2266 demo->quit = true;
2267 }
2268}
Tony Barbour8295ac42016-08-08 11:04:17 -06002269#endif // VK_USE_PLATFORM_XLIB_KHR
2270#ifdef VK_USE_PLATFORM_XCB_KHR
Tony Barbour2593b182016-04-19 10:57:58 -06002271static void demo_handle_xcb_event(struct demo *demo,
Karl Schultze4dc75c2016-02-02 15:37:51 -07002272 const xcb_generic_event_t *event) {
Piers Daniell735ee532015-02-23 16:23:13 -07002273 uint8_t event_code = event->response_type & 0x7f;
Courtney Goeltzenleuchter98cb2cb2014-11-06 14:27:52 -07002274 switch (event_code) {
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002275 case XCB_EXPOSE:
Courtney Goeltzenleuchterc465d6c2014-11-18 11:28:09 -07002276 // TODO: Resize window
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002277 break;
Courtney Goeltzenleuchter98cb2cb2014-11-06 14:27:52 -07002278 case XCB_CLIENT_MESSAGE:
Karl Schultze4dc75c2016-02-02 15:37:51 -07002279 if ((*(xcb_client_message_event_t *)event).data.data32[0] ==
2280 (*demo->atom_wm_delete_window).atom) {
Courtney Goeltzenleuchter98cb2cb2014-11-06 14:27:52 -07002281 demo->quit = true;
2282 }
2283 break;
Karl Schultze4dc75c2016-02-02 15:37:51 -07002284 case XCB_KEY_RELEASE: {
2285 const xcb_key_release_event_t *key =
2286 (const xcb_key_release_event_t *)event;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002287
Karl Schultze4dc75c2016-02-02 15:37:51 -07002288 switch (key->detail) {
2289 case 0x9: // Escape
2290 demo->quit = true;
2291 break;
2292 case 0x71: // left arrow key
2293 demo->spin_angle += demo->spin_increment;
2294 break;
2295 case 0x72: // right arrow key
2296 demo->spin_angle -= demo->spin_increment;
2297 break;
2298 case 0x41:
2299 demo->pause = !demo->pause;
2300 break;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002301 }
Karl Schultze4dc75c2016-02-02 15:37:51 -07002302 } break;
2303 case XCB_CONFIGURE_NOTIFY: {
2304 const xcb_configure_notify_event_t *cfg =
2305 (const xcb_configure_notify_event_t *)event;
2306 if ((demo->width != cfg->width) || (demo->height != cfg->height)) {
Damien Leone745a0b42016-01-26 14:34:12 -08002307 demo->width = cfg->width;
2308 demo->height = cfg->height;
Karl Schultze4dc75c2016-02-02 15:37:51 -07002309 demo_resize(demo);
Ian Elliottcf074d32015-10-16 18:02:43 -06002310 }
Karl Schultze4dc75c2016-02-02 15:37:51 -07002311 } break;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002312 default:
2313 break;
2314 }
2315}
2316
Tony Barbour2593b182016-04-19 10:57:58 -06002317static void demo_run_xcb(struct demo *demo) {
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002318 xcb_flush(demo->connection);
2319
2320 while (!demo->quit) {
2321 xcb_generic_event_t *event;
2322
Courtney Goeltzenleuchterc465d6c2014-11-18 11:28:09 -07002323 if (demo->pause) {
2324 event = xcb_wait_for_event(demo->connection);
2325 } else {
2326 event = xcb_poll_for_event(demo->connection);
Tony Barbour9b26b5a2016-08-05 14:55:20 -06002327 while(event) {
2328 demo_handle_xcb_event(demo, event);
2329 free(event);
2330 event = xcb_poll_for_event(demo->connection);
2331 }
Courtney Goeltzenleuchter98085552014-11-10 11:13:13 -07002332 }
Courtney Goeltzenleuchterc465d6c2014-11-18 11:28:09 -07002333
Courtney Goeltzenleuchterc465d6c2014-11-18 11:28:09 -07002334 demo_update_data_buffer(demo);
Courtney Goeltzenleuchter98085552014-11-10 11:13:13 -07002335 demo_draw(demo);
David Pinedo2bb7c932015-06-18 17:03:14 -06002336 demo->curFrame++;
Tony Barbour1a86d032015-09-21 15:17:33 -06002337 if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
David Pinedo2bb7c932015-06-18 17:03:14 -06002338 demo->quit = true;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002339 }
2340}
2341
Tony Barbour2593b182016-04-19 10:57:58 -06002342static void demo_create_xcb_window(struct demo *demo) {
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002343 uint32_t value_mask, value_list[32];
2344
Tony Barbour2593b182016-04-19 10:57:58 -06002345 demo->xcb_window = xcb_generate_id(demo->connection);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002346
2347 value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
2348 value_list[0] = demo->screen->black_pixel;
Karl Schultze4dc75c2016-02-02 15:37:51 -07002349 value_list[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_EXPOSURE |
Ian Elliottcf074d32015-10-16 18:02:43 -06002350 XCB_EVENT_MASK_STRUCTURE_NOTIFY;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002351
Tony Barbour2593b182016-04-19 10:57:58 -06002352 xcb_create_window(demo->connection, XCB_COPY_FROM_PARENT, demo->xcb_window,
Karl Schultze4dc75c2016-02-02 15:37:51 -07002353 demo->screen->root, 0, 0, demo->width, demo->height, 0,
2354 XCB_WINDOW_CLASS_INPUT_OUTPUT, demo->screen->root_visual,
2355 value_mask, value_list);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002356
Courtney Goeltzenleuchter98cb2cb2014-11-06 14:27:52 -07002357 /* Magic code that will send notification when window is destroyed */
Karl Schultze4dc75c2016-02-02 15:37:51 -07002358 xcb_intern_atom_cookie_t cookie =
2359 xcb_intern_atom(demo->connection, 1, 12, "WM_PROTOCOLS");
2360 xcb_intern_atom_reply_t *reply =
2361 xcb_intern_atom_reply(demo->connection, cookie, 0);
Courtney Goeltzenleuchter98cb2cb2014-11-06 14:27:52 -07002362
Karl Schultze4dc75c2016-02-02 15:37:51 -07002363 xcb_intern_atom_cookie_t cookie2 =
2364 xcb_intern_atom(demo->connection, 0, 16, "WM_DELETE_WINDOW");
2365 demo->atom_wm_delete_window =
2366 xcb_intern_atom_reply(demo->connection, cookie2, 0);
Courtney Goeltzenleuchter98cb2cb2014-11-06 14:27:52 -07002367
Tony Barbour2593b182016-04-19 10:57:58 -06002368 xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE, demo->xcb_window,
Karl Schultze4dc75c2016-02-02 15:37:51 -07002369 (*reply).atom, 4, 32, 1,
Courtney Goeltzenleuchter98cb2cb2014-11-06 14:27:52 -07002370 &(*demo->atom_wm_delete_window).atom);
2371 free(reply);
2372
Tony Barbour2593b182016-04-19 10:57:58 -06002373 xcb_map_window(demo->connection, demo->xcb_window);
David Pinedo2bb7c932015-06-18 17:03:14 -06002374
Karl Schultze4dc75c2016-02-02 15:37:51 -07002375 // Force the x/y coordinates to 100,100 results are identical in consecutive
2376 // runs
2377 const uint32_t coords[] = {100, 100};
Tony Barbour2593b182016-04-19 10:57:58 -06002378 xcb_configure_window(demo->connection, demo->xcb_window,
David Pinedo2bb7c932015-06-18 17:03:14 -06002379 XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002380}
Tony Barbour6b131662016-08-25 13:14:45 -06002381// VK_USE_PLATFORM_XCB_KHR
2382#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09002383static void demo_run(struct demo *demo) {
2384 while (!demo->quit) {
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09002385 demo_update_data_buffer(demo);
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09002386 demo_draw(demo);
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09002387 demo->curFrame++;
2388 if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
2389 demo->quit = true;
2390 }
2391}
2392
2393static void handle_ping(void *data UNUSED,
2394 struct wl_shell_surface *shell_surface,
2395 uint32_t serial) {
2396 wl_shell_surface_pong(shell_surface, serial);
2397}
2398
2399static void handle_configure(void *data UNUSED,
2400 struct wl_shell_surface *shell_surface UNUSED,
2401 uint32_t edges UNUSED, int32_t width UNUSED,
2402 int32_t height UNUSED) {}
2403
2404static void handle_popup_done(void *data UNUSED,
2405 struct wl_shell_surface *shell_surface UNUSED) {}
2406
2407static const struct wl_shell_surface_listener shell_surface_listener = {
2408 handle_ping, handle_configure, handle_popup_done};
2409
2410static void demo_create_window(struct demo *demo) {
2411 demo->window = wl_compositor_create_surface(demo->compositor);
2412 if (!demo->window) {
2413 printf("Can not create wayland_surface from compositor!\n");
2414 fflush(stdout);
2415 exit(1);
2416 }
2417
2418 demo->shell_surface = wl_shell_get_shell_surface(demo->shell, demo->window);
2419 if (!demo->shell_surface) {
2420 printf("Can not get shell_surface from wayland_surface!\n");
2421 fflush(stdout);
2422 exit(1);
2423 }
2424 wl_shell_surface_add_listener(demo->shell_surface, &shell_surface_listener,
2425 demo);
2426 wl_shell_surface_set_toplevel(demo->shell_surface);
2427 wl_shell_surface_set_title(demo->shell_surface, APP_SHORT_NAME);
2428}
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002429#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
2430static void demo_run(struct demo *demo) {
2431 if (!demo->prepared)
2432 return;
2433
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002434 demo_update_data_buffer(demo);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002435 demo_draw(demo);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002436 demo->curFrame++;
2437}
2438#endif
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002439
Courtney Goeltzenleuchter886f76c2015-07-06 17:46:11 -06002440/*
2441 * Return 1 (true) if all layer names specified in check_names
2442 * can be found in given layer properties.
2443 */
Courtney Goeltzenleuchterc88ce512015-07-09 11:44:38 -06002444static VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
Karl Schultze4dc75c2016-02-02 15:37:51 -07002445 uint32_t layer_count,
2446 VkLayerProperties *layers) {
Courtney Goeltzenleuchter886f76c2015-07-06 17:46:11 -06002447 for (uint32_t i = 0; i < check_count; i++) {
Courtney Goeltzenleuchterc88ce512015-07-09 11:44:38 -06002448 VkBool32 found = 0;
Courtney Goeltzenleuchter886f76c2015-07-06 17:46:11 -06002449 for (uint32_t j = 0; j < layer_count; j++) {
2450 if (!strcmp(check_names[i], layers[j].layerName)) {
2451 found = 1;
Dustin Graves7c287352016-01-27 13:48:06 -07002452 break;
Courtney Goeltzenleuchter886f76c2015-07-06 17:46:11 -06002453 }
2454 }
2455 if (!found) {
2456 fprintf(stderr, "Cannot find layer: %s\n", check_names[i]);
2457 return 0;
2458 }
2459 }
2460 return 1;
2461}
2462
Karl Schultze4dc75c2016-02-02 15:37:51 -07002463static void demo_init_vk(struct demo *demo) {
Tobin Ehlis99239dc2015-04-16 18:04:57 -06002464 VkResult err;
Courtney Goeltzenleuchter922a0fa2015-06-10 17:39:03 -06002465 uint32_t instance_extension_count = 0;
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002466 uint32_t instance_layer_count = 0;
Karl Schultz5b423ea2016-06-20 19:08:43 -06002467 uint32_t validation_layer_count = 0;
Karl Schultz7c50ad62016-04-01 12:07:03 -06002468 char **instance_validation_layers = NULL;
2469 demo->enabled_extension_count = 0;
2470 demo->enabled_layer_count = 0;
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002471
Karl Schultz7c50ad62016-04-01 12:07:03 -06002472 char *instance_validation_layers_alt1[] = {
2473 "VK_LAYER_LUNARG_standard_validation"
2474 };
2475
2476 char *instance_validation_layers_alt2[] = {
Mark Lobodzinskia2afb382016-06-29 14:01:14 -06002477 "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
2478 "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_image",
2479 "VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain",
2480 "VK_LAYER_GOOGLE_unique_objects"
Courtney Goeltzenleuchter886f76c2015-07-06 17:46:11 -06002481 };
2482
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002483 /* Look for validation layers */
Courtney Goeltzenleuchterc88ce512015-07-09 11:44:38 -06002484 VkBool32 validation_found = 0;
Karl Schultz7c50ad62016-04-01 12:07:03 -06002485 if (demo->validate) {
Tobin Ehlis99239dc2015-04-16 18:04:57 -06002486
Karl Schultz7c50ad62016-04-01 12:07:03 -06002487 err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
Dustin Graves7c287352016-01-27 13:48:06 -07002488 assert(!err);
Courtney Goeltzenleuchter886f76c2015-07-06 17:46:11 -06002489
Karl Schultz7c50ad62016-04-01 12:07:03 -06002490 instance_validation_layers = instance_validation_layers_alt1;
2491 if (instance_layer_count > 0) {
2492 VkLayerProperties *instance_layers =
2493 malloc(sizeof (VkLayerProperties) * instance_layer_count);
2494 err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
2495 instance_layers);
2496 assert(!err);
Dustin Graves7c287352016-01-27 13:48:06 -07002497
Karl Schultz7c50ad62016-04-01 12:07:03 -06002498
2499 validation_found = demo_check_layers(
2500 ARRAY_SIZE(instance_validation_layers_alt1),
2501 instance_validation_layers, instance_layer_count,
2502 instance_layers);
2503 if (validation_found) {
2504 demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt1);
Karl Schultz5b423ea2016-06-20 19:08:43 -06002505 demo->enabled_layers[0] = "VK_LAYER_LUNARG_standard_validation";
2506 validation_layer_count = 1;
Karl Schultz7c50ad62016-04-01 12:07:03 -06002507 } else {
2508 // use alternative set of validation layers
2509 instance_validation_layers = instance_validation_layers_alt2;
2510 demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
2511 validation_found = demo_check_layers(
2512 ARRAY_SIZE(instance_validation_layers_alt2),
2513 instance_validation_layers, instance_layer_count,
2514 instance_layers);
Karl Schultz5b423ea2016-06-20 19:08:43 -06002515 validation_layer_count =
2516 ARRAY_SIZE(instance_validation_layers_alt2);
2517 for (uint32_t i = 0; i < validation_layer_count; i++) {
2518 demo->enabled_layers[i] = instance_validation_layers[i];
Karl Schultz7c50ad62016-04-01 12:07:03 -06002519 }
2520 }
2521 free(instance_layers);
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002522 }
Dustin Graves7c287352016-01-27 13:48:06 -07002523
Karl Schultz7c50ad62016-04-01 12:07:03 -06002524 if (!validation_found) {
Karl Schultzad7bf022016-04-07 09:40:30 -06002525 ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find "
Karl Schultz7c50ad62016-04-01 12:07:03 -06002526 "required validation layer.\n\n"
2527 "Please look at the Getting Started guide for additional "
2528 "information.\n",
2529 "vkCreateInstance Failure");
2530 }
Dustin Graves7c287352016-01-27 13:48:06 -07002531 }
2532
2533 /* Look for instance extensions */
2534 VkBool32 surfaceExtFound = 0;
2535 VkBool32 platformSurfaceExtFound = 0;
Pavol Klacansky573a19d2016-05-10 03:08:19 -06002536#if defined(VK_USE_PLATFORM_XLIB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06002537 VkBool32 xlibSurfaceExtFound = 0;
Tobin Ehlis43ed2982016-04-28 10:17:33 -06002538#endif
Karl Schultz7c50ad62016-04-01 12:07:03 -06002539 memset(demo->extension_names, 0, sizeof(demo->extension_names));
Dustin Graves7c287352016-01-27 13:48:06 -07002540
Karl Schultze4dc75c2016-02-02 15:37:51 -07002541 err = vkEnumerateInstanceExtensionProperties(
2542 NULL, &instance_extension_count, NULL);
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002543 assert(!err);
2544
Dustin Graves7c287352016-01-27 13:48:06 -07002545 if (instance_extension_count > 0) {
2546 VkExtensionProperties *instance_extensions =
2547 malloc(sizeof(VkExtensionProperties) * instance_extension_count);
2548 err = vkEnumerateInstanceExtensionProperties(
2549 NULL, &instance_extension_count, instance_extensions);
2550 assert(!err);
2551 for (uint32_t i = 0; i < instance_extension_count; i++) {
2552 if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,
2553 instance_extensions[i].extensionName)) {
2554 surfaceExtFound = 1;
Karl Schultz7c50ad62016-04-01 12:07:03 -06002555 demo->extension_names[demo->enabled_extension_count++] =
Dustin Graves7c287352016-01-27 13:48:06 -07002556 VK_KHR_SURFACE_EXTENSION_NAME;
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002557 }
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002558#if defined(VK_USE_PLATFORM_WIN32_KHR)
Dustin Graves7c287352016-01-27 13:48:06 -07002559 if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
2560 instance_extensions[i].extensionName)) {
2561 platformSurfaceExtFound = 1;
Karl Schultz7c50ad62016-04-01 12:07:03 -06002562 demo->extension_names[demo->enabled_extension_count++] =
Dustin Graves7c287352016-01-27 13:48:06 -07002563 VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
2564 }
Pavol Klacansky573a19d2016-05-10 03:08:19 -06002565#endif
2566#if defined(VK_USE_PLATFORM_XLIB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06002567 if (!strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
2568 instance_extensions[i].extensionName)) {
2569 platformSurfaceExtFound = 1;
2570 xlibSurfaceExtFound = 1;
2571 demo->extension_names[demo->enabled_extension_count++] =
2572 VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
2573 }
Pavol Klacansky573a19d2016-05-10 03:08:19 -06002574#endif
2575#if defined(VK_USE_PLATFORM_XCB_KHR)
Dustin Graves7c287352016-01-27 13:48:06 -07002576 if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME,
2577 instance_extensions[i].extensionName)) {
2578 platformSurfaceExtFound = 1;
Karl Schultz7c50ad62016-04-01 12:07:03 -06002579 demo->extension_names[demo->enabled_extension_count++] =
Dustin Graves7c287352016-01-27 13:48:06 -07002580 VK_KHR_XCB_SURFACE_EXTENSION_NAME;
2581 }
Pavol Klacansky573a19d2016-05-10 03:08:19 -06002582#endif
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09002583#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
2584 if (!strcmp(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
2585 instance_extensions[i].extensionName)) {
2586 platformSurfaceExtFound = 1;
2587 demo->extension_names[demo->enabled_extension_count++] =
2588 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
2589 }
2590#endif
Pavol Klacansky573a19d2016-05-10 03:08:19 -06002591#if defined(VK_USE_PLATFORM_ANDROID_KHR)
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002592 if (!strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
2593 instance_extensions[i].extensionName)) {
2594 platformSurfaceExtFound = 1;
2595 demo->extension_names[demo->enabled_extension_count++] =
2596 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
2597 }
2598#endif
Dustin Graves7c287352016-01-27 13:48:06 -07002599 if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
2600 instance_extensions[i].extensionName)) {
2601 if (demo->validate) {
Karl Schultz7c50ad62016-04-01 12:07:03 -06002602 demo->extension_names[demo->enabled_extension_count++] =
Dustin Graves7c287352016-01-27 13:48:06 -07002603 VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
2604 }
2605 }
Karl Schultz7c50ad62016-04-01 12:07:03 -06002606 assert(demo->enabled_extension_count < 64);
Courtney Goeltzenleuchter922a0fa2015-06-10 17:39:03 -06002607 }
Dustin Graves7c287352016-01-27 13:48:06 -07002608
2609 free(instance_extensions);
Tobin Ehlis99239dc2015-04-16 18:04:57 -06002610 }
Dustin Graves7c287352016-01-27 13:48:06 -07002611
Ian Elliottd3f7dcc2015-11-20 13:08:34 -07002612 if (!surfaceExtFound) {
Karl Schultze4dc75c2016-02-02 15:37:51 -07002613 ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2614 "the " VK_KHR_SURFACE_EXTENSION_NAME
2615 " extension.\n\nDo you have a compatible "
Ian Elliott65152912015-04-28 13:22:33 -06002616 "Vulkan installable client driver (ICD) installed?\nPlease "
2617 "look at the Getting Started guide for additional "
2618 "information.\n",
2619 "vkCreateInstance Failure");
2620 }
Ian Elliottd3f7dcc2015-11-20 13:08:34 -07002621 if (!platformSurfaceExtFound) {
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002622#if defined(VK_USE_PLATFORM_WIN32_KHR)
Karl Schultze4dc75c2016-02-02 15:37:51 -07002623 ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2624 "the " VK_KHR_WIN32_SURFACE_EXTENSION_NAME
2625 " extension.\n\nDo you have a compatible "
Ian Elliottd3f7dcc2015-11-20 13:08:34 -07002626 "Vulkan installable client driver (ICD) installed?\nPlease "
2627 "look at the Getting Started guide for additional "
2628 "information.\n",
2629 "vkCreateInstance Failure");
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002630#elif defined(VK_USE_PLATFORM_XCB_KHR)
Karl Schultze4dc75c2016-02-02 15:37:51 -07002631 ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2632 "the " VK_KHR_XCB_SURFACE_EXTENSION_NAME
2633 " extension.\n\nDo you have a compatible "
Mark Lobodzinski6f7a6032015-11-24 12:04:15 -07002634 "Vulkan installable client driver (ICD) installed?\nPlease "
2635 "look at the Getting Started guide for additional "
2636 "information.\n",
2637 "vkCreateInstance Failure");
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09002638#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
2639 ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2640 "the " VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
2641 " extension.\n\nDo you have a compatible "
2642 "Vulkan installable client driver (ICD) installed?\nPlease "
2643 "look at the Getting Started guide for additional "
2644 "information.\n",
2645 "vkCreateInstance Failure");
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002646#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
2647 ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2648 "the " VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
2649 " extension.\n\nDo you have a compatible "
2650 "Vulkan installable client driver (ICD) installed?\nPlease "
2651 "look at the Getting Started guide for additional "
2652 "information.\n",
2653 "vkCreateInstance Failure");
2654#endif
Ian Elliottd3f7dcc2015-11-20 13:08:34 -07002655 }
Tobin Ehlis43ed2982016-04-28 10:17:33 -06002656#if defined(VK_USE_PLATFORM_XLIB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06002657 if (demo->use_xlib && !xlibSurfaceExtFound) {
2658 ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2659 "the " VK_KHR_XLIB_SURFACE_EXTENSION_NAME
2660 " extension.\n\nDo you have a compatible "
2661 "Vulkan installable client driver (ICD) installed?\nPlease "
2662 "look at the Getting Started guide for additional "
2663 "information.\n",
2664 "vkCreateInstance Failure");
2665 }
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002666#endif
Courtney Goeltzenleuchter78351a62015-04-10 08:34:15 -06002667 const VkApplicationInfo app = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06002668 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002669 .pNext = NULL,
Chia-I Wua8fe78a2015-10-27 18:04:07 +08002670 .pApplicationName = APP_SHORT_NAME,
2671 .applicationVersion = 0,
Ian Elliott44e33f72015-04-28 10:52:52 -06002672 .pEngineName = APP_SHORT_NAME,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002673 .engineVersion = 0,
Jon Ashburn7f4bc2c2016-03-22 13:57:46 -06002674 .apiVersion = VK_API_VERSION_1_0,
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002675 };
Tony Barbour3dddd5d2015-04-29 16:19:20 -06002676 VkInstanceCreateInfo inst_info = {
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06002677 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
Jon Ashburnab46b362015-04-04 14:52:07 -06002678 .pNext = NULL,
Chia-I Wua8fe78a2015-10-27 18:04:07 +08002679 .pApplicationInfo = &app,
Karl Schultz7c50ad62016-04-01 12:07:03 -06002680 .enabledLayerCount = demo->enabled_layer_count,
2681 .ppEnabledLayerNames = (const char *const *)instance_validation_layers,
2682 .enabledExtensionCount = demo->enabled_extension_count,
2683 .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
Jon Ashburnab46b362015-04-04 14:52:07 -06002684 };
Karl Schultzcd9887d2016-03-25 14:25:16 -06002685
2686 /*
2687 * This is info for a temp callback to use during CreateInstance.
2688 * After the instance is created, we use the instance-based
2689 * function to register the final callback.
2690 */
Ian Elliott5959bbd2016-03-25 09:07:19 -06002691 VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
Ian Elliott5959bbd2016-03-25 09:07:19 -06002692 if (demo->validate) {
Ian Elliott5959bbd2016-03-25 09:07:19 -06002693 dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
2694 dbgCreateInfo.pNext = NULL;
Karl Schultzcd9887d2016-03-25 14:25:16 -06002695 dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc;
lenny-lunargfbe22392016-06-06 11:07:53 -06002696 dbgCreateInfo.pUserData = demo;
Ian Elliott5959bbd2016-03-25 09:07:19 -06002697 dbgCreateInfo.flags =
2698 VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
2699 inst_info.pNext = &dbgCreateInfo;
2700 }
Ian Elliott097d9f32015-04-28 11:35:02 -06002701
Mark Lobodzinskic4fffc72015-01-29 08:55:56 -06002702 uint32_t gpu_count;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002703
Chia-I Wu63636062015-10-26 21:10:41 +08002704 err = vkCreateInstance(&inst_info, NULL, &demo->inst);
Ian Elliott07264132015-04-28 11:35:02 -06002705 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
2706 ERR_EXIT("Cannot find a compatible Vulkan installable client driver "
Ian Elliott65152912015-04-28 13:22:33 -06002707 "(ICD).\n\nPlease look at the Getting Started guide for "
Ian Elliott07264132015-04-28 11:35:02 -06002708 "additional information.\n",
2709 "vkCreateInstance Failure");
Courtney Goeltzenleuchter1e47e4b2015-09-14 18:01:17 -06002710 } else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) {
Tony Barbour3dddd5d2015-04-29 16:19:20 -06002711 ERR_EXIT("Cannot find a specified extension library"
Dustin Graves7c287352016-01-27 13:48:06 -07002712 ".\nMake sure your layers path is set appropriately.\n",
Tony Barbour3dddd5d2015-04-29 16:19:20 -06002713 "vkCreateInstance Failure");
Ian Elliott07264132015-04-28 11:35:02 -06002714 } else if (err) {
Ian Elliott65152912015-04-28 13:22:33 -06002715 ERR_EXIT("vkCreateInstance failed.\n\nDo you have a compatible Vulkan "
2716 "installable client driver (ICD) installed?\nPlease look at "
Ian Elliott07264132015-04-28 11:35:02 -06002717 "the Getting Started guide for additional information.\n",
2718 "vkCreateInstance Failure");
Ian Elliott3979e282015-04-03 15:24:55 -06002719 }
Jon Ashburnab46b362015-04-04 14:52:07 -06002720
Tobin Ehlis8a724d82015-09-07 15:16:39 -06002721 /* Make initial call to query gpu_count, then second call for gpu info*/
2722 err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
2723 assert(!err && gpu_count > 0);
Dustin Graves7c287352016-01-27 13:48:06 -07002724
2725 if (gpu_count > 0) {
2726 VkPhysicalDevice *physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count);
2727 err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices);
2728 assert(!err);
2729 /* For cube demo we just grab the first physical device */
2730 demo->gpu = physical_devices[0];
2731 free(physical_devices);
2732 } else {
2733 ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices.\n\n"
2734 "Do you have a compatible Vulkan installable client driver (ICD) "
2735 "installed?\nPlease look at the Getting Started guide for "
2736 "additional information.\n",
2737 "vkEnumeratePhysicalDevices Failure");
2738 }
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002739
Dustin Graves7c287352016-01-27 13:48:06 -07002740 /* Look for device extensions */
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002741 uint32_t device_extension_count = 0;
Dustin Graves7c287352016-01-27 13:48:06 -07002742 VkBool32 swapchainExtFound = 0;
2743 demo->enabled_extension_count = 0;
Karl Schultz7c50ad62016-04-01 12:07:03 -06002744 memset(demo->extension_names, 0, sizeof(demo->extension_names));
Dustin Graves7c287352016-01-27 13:48:06 -07002745
Karl Schultze4dc75c2016-02-02 15:37:51 -07002746 err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL,
2747 &device_extension_count, NULL);
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002748 assert(!err);
2749
Dustin Graves7c287352016-01-27 13:48:06 -07002750 if (device_extension_count > 0) {
2751 VkExtensionProperties *device_extensions =
2752 malloc(sizeof(VkExtensionProperties) * device_extension_count);
2753 err = vkEnumerateDeviceExtensionProperties(
2754 demo->gpu, NULL, &device_extension_count, device_extensions);
2755 assert(!err);
Ian Elliottaaae5352015-07-06 14:27:58 -06002756
Dustin Graves7c287352016-01-27 13:48:06 -07002757 for (uint32_t i = 0; i < device_extension_count; i++) {
2758 if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
2759 device_extensions[i].extensionName)) {
2760 swapchainExtFound = 1;
2761 demo->extension_names[demo->enabled_extension_count++] =
2762 VK_KHR_SWAPCHAIN_EXTENSION_NAME;
2763 }
2764 assert(demo->enabled_extension_count < 64);
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002765 }
Dustin Graves7c287352016-01-27 13:48:06 -07002766
2767 free(device_extensions);
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002768 }
Dustin Graves7c287352016-01-27 13:48:06 -07002769
Tony Barbourcc69f452015-10-08 13:59:42 -06002770 if (!swapchainExtFound) {
Karl Schultze4dc75c2016-02-02 15:37:51 -07002771 ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find "
2772 "the " VK_KHR_SWAPCHAIN_EXTENSION_NAME
2773 " extension.\n\nDo you have a compatible "
Courtney Goeltzenleuchterbe103362015-06-29 15:39:26 -06002774 "Vulkan installable client driver (ICD) installed?\nPlease "
2775 "look at the Getting Started guide for additional "
2776 "information.\n",
2777 "vkCreateInstance Failure");
2778 }
2779
Tony Barbour3dddd5d2015-04-29 16:19:20 -06002780 if (demo->validate) {
Karl Schultze4dc75c2016-02-02 15:37:51 -07002781 demo->CreateDebugReportCallback =
2782 (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(
2783 demo->inst, "vkCreateDebugReportCallbackEXT");
2784 demo->DestroyDebugReportCallback =
2785 (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(
2786 demo->inst, "vkDestroyDebugReportCallbackEXT");
Courtney Goeltzenleuchter2dafae42015-11-30 12:13:14 -07002787 if (!demo->CreateDebugReportCallback) {
Karl Schultze4dc75c2016-02-02 15:37:51 -07002788 ERR_EXIT(
2789 "GetProcAddr: Unable to find vkCreateDebugReportCallbackEXT\n",
2790 "vkGetProcAddr Failure");
Courtney Goeltzenleuchter922a0fa2015-06-10 17:39:03 -06002791 }
Courtney Goeltzenleuchter2dafae42015-11-30 12:13:14 -07002792 if (!demo->DestroyDebugReportCallback) {
Karl Schultze4dc75c2016-02-02 15:37:51 -07002793 ERR_EXIT(
2794 "GetProcAddr: Unable to find vkDestroyDebugReportCallbackEXT\n",
2795 "vkGetProcAddr Failure");
Tony Barbourd70b42c2015-06-30 14:14:19 -06002796 }
Karl Schultze4dc75c2016-02-02 15:37:51 -07002797 demo->DebugReportMessage =
2798 (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(
2799 demo->inst, "vkDebugReportMessageEXT");
Courtney Goeltzenleuchteraf1951c2015-12-01 14:11:38 -07002800 if (!demo->DebugReportMessage) {
Courtney Goeltzenleuchter0f060df2015-12-09 15:48:16 -07002801 ERR_EXIT("GetProcAddr: Unable to find vkDebugReportMessageEXT\n",
Courtney Goeltzenleuchteraf1951c2015-12-01 14:11:38 -07002802 "vkGetProcAddr Failure");
2803 }
Jon Ashburn9549c8e2015-12-15 08:47:46 -07002804
Courtney Goeltzenleuchter0f060df2015-12-09 15:48:16 -07002805 VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
Karl Schultzcd9887d2016-03-25 14:25:16 -06002806 PFN_vkDebugReportCallbackEXT callback;
2807 callback = demo->use_break ? BreakCallback : dbgFunc;
Courtney Goeltzenleuchter0f060df2015-12-09 15:48:16 -07002808 dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter2dafae42015-11-30 12:13:14 -07002809 dbgCreateInfo.pNext = NULL;
2810 dbgCreateInfo.pfnCallback = callback;
lenny-lunargfbe22392016-06-06 11:07:53 -06002811 dbgCreateInfo.pUserData = demo;
Karl Schultze4dc75c2016-02-02 15:37:51 -07002812 dbgCreateInfo.flags =
Mark Lobodzinskicf9784e2016-02-11 09:26:16 -07002813 VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
Karl Schultze4dc75c2016-02-02 15:37:51 -07002814 err = demo->CreateDebugReportCallback(demo->inst, &dbgCreateInfo, NULL,
2815 &demo->msg_callback);
Courtney Goeltzenleuchter922a0fa2015-06-10 17:39:03 -06002816 switch (err) {
2817 case VK_SUCCESS:
2818 break;
Courtney Goeltzenleuchter922a0fa2015-06-10 17:39:03 -06002819 case VK_ERROR_OUT_OF_HOST_MEMORY:
Courtney Goeltzenleuchter2dafae42015-11-30 12:13:14 -07002820 ERR_EXIT("CreateDebugReportCallback: out of host memory\n",
2821 "CreateDebugReportCallback Failure");
Courtney Goeltzenleuchter922a0fa2015-06-10 17:39:03 -06002822 break;
2823 default:
Courtney Goeltzenleuchter2dafae42015-11-30 12:13:14 -07002824 ERR_EXIT("CreateDebugReportCallback: unknown failure\n",
2825 "CreateDebugReportCallback Failure");
Courtney Goeltzenleuchter922a0fa2015-06-10 17:39:03 -06002826 break;
2827 }
Tony Barbour3dddd5d2015-04-29 16:19:20 -06002828 }
Courtney Goeltzenleuchterbd5c1742015-10-20 16:40:38 -06002829 vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
Tobin Ehlis9626ba62015-09-22 13:52:37 -06002830
2831 /* Call with NULL data to get count */
Tony Barbourab2a0362016-09-06 11:40:12 -06002832 vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu,
2833 &demo->queue_family_count, NULL);
2834 assert(demo->queue_family_count >= 1);
Tobin Ehlis9626ba62015-09-22 13:52:37 -06002835
Karl Schultze4dc75c2016-02-02 15:37:51 -07002836 demo->queue_props = (VkQueueFamilyProperties *)malloc(
Tony Barbourab2a0362016-09-06 11:40:12 -06002837 demo->queue_family_count * sizeof(VkQueueFamilyProperties));
2838 vkGetPhysicalDeviceQueueFamilyProperties(
2839 demo->gpu, &demo->queue_family_count, demo->queue_props);
2840
Tobin Ehlisbf3020e2015-09-24 15:18:22 -06002841 // Query fine-grained feature support for this device.
Karl Schultze4dc75c2016-02-02 15:37:51 -07002842 // If app has specific feature requirements it should check supported
2843 // features based on this query
Tobin Ehlis8d03b7c2015-09-29 11:22:37 -06002844 VkPhysicalDeviceFeatures physDevFeatures;
Courtney Goeltzenleuchterbd5c1742015-10-20 16:40:38 -06002845 vkGetPhysicalDeviceFeatures(demo->gpu, &physDevFeatures);
Tobin Ehlisbf3020e2015-09-24 15:18:22 -06002846
Tony Barbourda2bad52016-01-22 14:36:40 -07002847 GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceSupportKHR);
2848 GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
2849 GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceFormatsKHR);
2850 GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfacePresentModesKHR);
2851 GET_INSTANCE_PROC_ADDR(demo->inst, GetSwapchainImagesKHR);
2852}
2853
Karl Schultze4dc75c2016-02-02 15:37:51 -07002854static void demo_create_device(struct demo *demo) {
Tony Barbourda2bad52016-01-22 14:36:40 -07002855 VkResult U_ASSERT_ONLY err;
Karl Schultze4dc75c2016-02-02 15:37:51 -07002856 float queue_priorities[1] = {0.0};
Tony Barbour22e06272016-09-07 16:07:56 -06002857 VkDeviceQueueCreateInfo queues[2];
2858 queues[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
2859 queues[0].pNext = NULL;
2860 queues[0].queueFamilyIndex = demo->graphics_queue_family_index;
2861 queues[0].queueCount = 1;
2862 queues[0].pQueuePriorities = queue_priorities;
2863 queues[0].flags = 0;
Tobin Ehlis9626ba62015-09-22 13:52:37 -06002864
2865 VkDeviceCreateInfo device = {
2866 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
2867 .pNext = NULL,
Chia-I Wu8b497442015-11-06 06:42:02 +08002868 .queueCreateInfoCount = 1,
Tony Barbour22e06272016-09-07 16:07:56 -06002869 .pQueueCreateInfos = queues,
Karl Schultz5b423ea2016-06-20 19:08:43 -06002870 .enabledLayerCount = 0,
2871 .ppEnabledLayerNames = NULL,
Tony Barbourda2bad52016-01-22 14:36:40 -07002872 .enabledExtensionCount = demo->enabled_extension_count,
Karl Schultze4dc75c2016-02-02 15:37:51 -07002873 .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
2874 .pEnabledFeatures =
2875 NULL, // If specific features are required, pass them in here
Tobin Ehlis9626ba62015-09-22 13:52:37 -06002876 };
Tony Barbour22e06272016-09-07 16:07:56 -06002877 if (demo->separate_present_queue) {
2878 queues[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
2879 queues[1].pNext = NULL;
2880 queues[1].queueFamilyIndex = demo->present_queue_family_index;
2881 queues[1].queueCount = 1;
2882 queues[1].pQueuePriorities = queue_priorities;
2883 queues[1].flags = 0;
2884 device.queueCreateInfoCount = 2;
2885 }
Chia-I Wu63636062015-10-26 21:10:41 +08002886 err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06002887 assert(!err);
Courtney Goeltzenleuchter3a35c822015-07-15 17:45:38 -06002888}
2889
Karl Schultze4dc75c2016-02-02 15:37:51 -07002890static void demo_init_vk_swapchain(struct demo *demo) {
Courtney Goeltzenleuchterd3cdaaf2015-12-17 09:53:29 -07002891 VkResult U_ASSERT_ONLY err;
Courtney Goeltzenleuchter3a35c822015-07-15 17:45:38 -06002892 uint32_t i;
Courtney Goeltzenleuchtered667a52015-03-05 18:09:39 -07002893
Karl Schultze4dc75c2016-02-02 15:37:51 -07002894// Create a WSI surface for the window:
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002895#if defined(VK_USE_PLATFORM_WIN32_KHR)
Ian Elliotta7a731c2015-12-11 15:52:12 -07002896 VkWin32SurfaceCreateInfoKHR createInfo;
2897 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
2898 createInfo.pNext = NULL;
2899 createInfo.flags = 0;
Jon Ashburnb90f50d2015-12-24 17:08:01 -07002900 createInfo.hinstance = demo->connection;
2901 createInfo.hwnd = demo->window;
Ian Elliotta7a731c2015-12-11 15:52:12 -07002902
Karl Schultze4dc75c2016-02-02 15:37:51 -07002903 err =
2904 vkCreateWin32SurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface);
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09002905#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) && !defined(VK_USE_PLATFORM_XCB_KHR)
2906 VkWaylandSurfaceCreateInfoKHR createInfo;
2907 createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
2908 createInfo.pNext = NULL;
2909 createInfo.flags = 0;
2910 createInfo.display = demo->display;
2911 createInfo.surface = demo->window;
2912
2913 err = vkCreateWaylandSurfaceKHR(demo->inst, &createInfo, NULL,
2914 &demo->surface);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002915#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
2916 VkAndroidSurfaceCreateInfoKHR createInfo;
2917 createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
2918 createInfo.pNext = NULL;
2919 createInfo.flags = 0;
2920 createInfo.window = (ANativeWindow*)(demo->window);
Ian Elliottb08e0d92015-11-20 11:55:46 -07002921
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002922 err = vkCreateAndroidSurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface);
2923#endif
Tony Barbour2593b182016-04-19 10:57:58 -06002924 if (demo->use_xlib) {
Tobin Ehlis43ed2982016-04-28 10:17:33 -06002925#if defined(VK_USE_PLATFORM_XLIB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06002926 VkXlibSurfaceCreateInfoKHR createInfo;
2927 createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
2928 createInfo.pNext = NULL;
2929 createInfo.flags = 0;
2930 createInfo.dpy = demo->display;
2931 createInfo.window = demo->xlib_window;
Ian Elliotta7a731c2015-12-11 15:52:12 -07002932
Tony Barbour2593b182016-04-19 10:57:58 -06002933 err = vkCreateXlibSurfaceKHR(demo->inst, &createInfo, NULL,
2934 &demo->surface);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002935#endif
Tony Barbour2593b182016-04-19 10:57:58 -06002936 }
2937 else {
Tobin Ehlis43ed2982016-04-28 10:17:33 -06002938#if defined(VK_USE_PLATFORM_XCB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06002939 VkXcbSurfaceCreateInfoKHR createInfo;
2940 createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
2941 createInfo.pNext = NULL;
2942 createInfo.flags = 0;
2943 createInfo.connection = demo->connection;
2944 createInfo.window = demo->xcb_window;
2945
2946 err = vkCreateXcbSurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05002947#endif
Tony Barbour2593b182016-04-19 10:57:58 -06002948 }
Tony Barbour2593b182016-04-19 10:57:58 -06002949 assert(!err);
Ian Elliottaaae5352015-07-06 14:27:58 -06002950
Tony Barbourcc69f452015-10-08 13:59:42 -06002951 // Iterate over each queue to learn whether it supports presenting:
Karl Schultze4dc75c2016-02-02 15:37:51 -07002952 VkBool32 *supportsPresent =
Tony Barbourab2a0362016-09-06 11:40:12 -06002953 (VkBool32 *)malloc(demo->queue_family_count * sizeof(VkBool32));
2954 for (i = 0; i < demo->queue_family_count; i++) {
Karl Schultze4dc75c2016-02-02 15:37:51 -07002955 demo->fpGetPhysicalDeviceSurfaceSupportKHR(demo->gpu, i, demo->surface,
Ian Elliottaaae5352015-07-06 14:27:58 -06002956 &supportsPresent[i]);
Courtney Goeltzenleuchtered667a52015-03-05 18:09:39 -07002957 }
Ian Elliottaaae5352015-07-06 14:27:58 -06002958
2959 // Search for a graphics and a present queue in the array of queue
2960 // families, try to find one that supports both
Tony Barbourab2a0362016-09-06 11:40:12 -06002961 uint32_t graphicsQueueFamilyIndex = UINT32_MAX;
2962 uint32_t presentQueueFamilyIndex = UINT32_MAX;
2963 for (i = 0; i < demo->queue_family_count; i++) {
2964 if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
2965 if (graphicsQueueFamilyIndex == UINT32_MAX) {
2966 graphicsQueueFamilyIndex = i;
2967 }
Karl Schultze4dc75c2016-02-02 15:37:51 -07002968
Tony Barbourab2a0362016-09-06 11:40:12 -06002969 if (supportsPresent[i] == VK_TRUE) {
2970 graphicsQueueFamilyIndex = i;
2971 presentQueueFamilyIndex = i;
2972 break;
2973 }
2974 }
2975 }
2976
2977 if (presentQueueFamilyIndex == UINT32_MAX) {
2978 // If didn't find a queue that supports both graphics and present, then
2979 // find a separate present queue.
2980 for (size_t i = 0; i < demo->queue_family_count; ++i) {
2981 if (supportsPresent[i] == VK_TRUE) {
2982 presentQueueFamilyIndex = i;
2983 break;
2984 }
Ian Elliottaaae5352015-07-06 14:27:58 -06002985 }
2986 }
Ian Elliottaaae5352015-07-06 14:27:58 -06002987
2988 // Generate error if could not find both a graphics and a present queue
Tony Barbourab2a0362016-09-06 11:40:12 -06002989 if (graphicsQueueFamilyIndex == UINT32_MAX ||
2990 presentQueueFamilyIndex == UINT32_MAX) {
Tony Barboura2a67812016-07-18 13:21:06 -06002991 ERR_EXIT("Could not find both graphics and present queues\n",
Tony Barbourcc69f452015-10-08 13:59:42 -06002992 "Swapchain Initialization Failure");
Ian Elliottaaae5352015-07-06 14:27:58 -06002993 }
2994
Tony Barbourab2a0362016-09-06 11:40:12 -06002995 demo->graphics_queue_family_index = graphicsQueueFamilyIndex;
2996 demo->present_queue_family_index = presentQueueFamilyIndex;
Tony Barbour22e06272016-09-07 16:07:56 -06002997 demo->separate_present_queue =
2998 (demo->graphics_queue_family_index != demo->present_queue_family_index);
Tony Barbourab2a0362016-09-06 11:40:12 -06002999 free(supportsPresent);
Courtney Goeltzenleuchtered667a52015-03-05 18:09:39 -07003000
Tony Barbourda2bad52016-01-22 14:36:40 -07003001 demo_create_device(demo);
3002
3003 GET_DEVICE_PROC_ADDR(demo->device, CreateSwapchainKHR);
3004 GET_DEVICE_PROC_ADDR(demo->device, DestroySwapchainKHR);
3005 GET_DEVICE_PROC_ADDR(demo->device, GetSwapchainImagesKHR);
3006 GET_DEVICE_PROC_ADDR(demo->device, AcquireNextImageKHR);
3007 GET_DEVICE_PROC_ADDR(demo->device, QueuePresentKHR);
3008
Tony Barboura2a67812016-07-18 13:21:06 -06003009 vkGetDeviceQueue(demo->device, demo->graphics_queue_family_index, 0,
3010 &demo->graphics_queue);
3011
Tony Barbour22e06272016-09-07 16:07:56 -06003012 if (!demo->separate_present_queue) {
Tony Barboura2a67812016-07-18 13:21:06 -06003013 demo->present_queue = demo->graphics_queue;
3014 } else {
3015 vkGetDeviceQueue(demo->device, demo->present_queue_family_index, 0,
3016 &demo->present_queue);
3017 }
Tony Barbour3dddd5d2015-04-29 16:19:20 -06003018
Ian Elliottaaae5352015-07-06 14:27:58 -06003019 // Get the list of VkFormat's that are supported:
Ian Elliott8528eff2015-08-07 15:56:59 -06003020 uint32_t formatCount;
Karl Schultze4dc75c2016-02-02 15:37:51 -07003021 err = demo->fpGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface,
Ian Elliottf2ff8022015-11-23 12:48:15 -07003022 &formatCount, NULL);
Ian Elliottaaae5352015-07-06 14:27:58 -06003023 assert(!err);
Ian Elliotta0781972015-08-21 15:09:33 -06003024 VkSurfaceFormatKHR *surfFormats =
3025 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
Karl Schultze4dc75c2016-02-02 15:37:51 -07003026 err = demo->fpGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface,
Ian Elliottf2ff8022015-11-23 12:48:15 -07003027 &formatCount, surfFormats);
Ian Elliottaaae5352015-07-06 14:27:58 -06003028 assert(!err);
3029 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
3030 // the surface has no preferred format. Otherwise, at least one
3031 // supported format will be returned.
Karl Schultze4dc75c2016-02-02 15:37:51 -07003032 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) {
Ian Elliottaaae5352015-07-06 14:27:58 -06003033 demo->format = VK_FORMAT_B8G8R8A8_UNORM;
Karl Schultze4dc75c2016-02-02 15:37:51 -07003034 } else {
Ian Elliottaaae5352015-07-06 14:27:58 -06003035 assert(formatCount >= 1);
3036 demo->format = surfFormats[0].format;
3037 }
Ian Elliott8528eff2015-08-07 15:56:59 -06003038 demo->color_space = surfFormats[0].colorSpace;
Ian Elliotte4602cd2015-04-21 16:41:02 -06003039
David Pinedo2bb7c932015-06-18 17:03:14 -06003040 demo->quit = false;
3041 demo->curFrame = 0;
Mark Lobodzinskieadf9982015-07-02 16:49:40 -06003042
Tony Barbource7524e2016-07-28 12:01:45 -06003043 // Create semaphores to synchronize acquiring presentable buffers before
3044 // rendering and waiting for drawing to be complete before presenting
3045 VkSemaphoreCreateInfo semaphoreCreateInfo = {
3046 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3047 .pNext = NULL,
3048 .flags = 0,
3049 };
3050 err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, NULL,
3051 &demo->image_acquired_semaphore);
3052 assert(!err);
3053
3054 err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, NULL,
3055 &demo->draw_complete_semaphore);
3056 assert(!err);
3057
Tony Barbour22e06272016-09-07 16:07:56 -06003058 if (demo->separate_present_queue) {
3059 err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, NULL,
3060 &demo->image_ownership_semaphore);
3061 assert(!err);
3062 }
3063
Mark Lobodzinskieadf9982015-07-02 16:49:40 -06003064 // Get Memory information and properties
Courtney Goeltzenleuchterbd5c1742015-10-20 16:40:38 -06003065 vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_properties);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003066}
3067
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09003068#if defined(VK_USE_PLATFORM_WAYLAND_KHR) && !defined(VK_USE_PLATFORM_XCB_KHR)
3069static void registry_handle_global(void *data, struct wl_registry *registry,
3070 uint32_t name, const char *interface,
3071 uint32_t version UNUSED) {
3072 struct demo *demo = data;
3073 if (strcmp(interface, "wl_compositor") == 0) {
3074 demo->compositor =
3075 wl_registry_bind(registry, name, &wl_compositor_interface, 3);
3076 /* Todo: When xdg_shell protocol has stablized, we should move wl_shell
3077 * tp xdg_shell */
3078 } else if (strcmp(interface, "wl_shell") == 0) {
3079 demo->shell = wl_registry_bind(registry, name, &wl_shell_interface, 1);
3080 }
3081}
3082
3083static void registry_handle_global_remove(void *data UNUSED,
3084 struct wl_registry *registry UNUSED,
3085 uint32_t name UNUSED) {}
3086
3087static const struct wl_registry_listener registry_listener = {
3088 registry_handle_global, registry_handle_global_remove};
3089#endif
3090
Karl Schultze4dc75c2016-02-02 15:37:51 -07003091static void demo_init_connection(struct demo *demo) {
Michael Lentinec6cde4b2016-04-18 13:20:45 -05003092#if defined(VK_USE_PLATFORM_XCB_KHR)
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003093 const xcb_setup_t *setup;
3094 xcb_screen_iterator_t iter;
3095 int scr;
3096
3097 demo->connection = xcb_connect(NULL, &scr);
Lenny Komow022bc2a2016-08-11 10:57:38 -06003098 if (xcb_connection_has_error(demo->connection) > 0) {
Ian Elliott3979e282015-04-03 15:24:55 -06003099 printf("Cannot find a compatible Vulkan installable client driver "
3100 "(ICD).\nExiting ...\n");
3101 fflush(stdout);
3102 exit(1);
3103 }
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003104
3105 setup = xcb_get_setup(demo->connection);
3106 iter = xcb_setup_roots_iterator(setup);
3107 while (scr-- > 0)
3108 xcb_screen_next(&iter);
3109
3110 demo->screen = iter.data;
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09003111#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
3112 demo->display = wl_display_connect(NULL);
3113
3114 if (demo->display == NULL) {
3115 printf("Cannot find a compatible Vulkan installable client driver "
3116 "(ICD).\nExiting ...\n");
3117 fflush(stdout);
3118 exit(1);
3119 }
3120
3121 demo->registry = wl_display_get_registry(demo->display);
3122 wl_registry_add_listener(demo->registry, &registry_listener, demo);
3123 wl_display_dispatch(demo->display);
Michael Lentinec6cde4b2016-04-18 13:20:45 -05003124#endif
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003125}
3126
Karl Schultze4dc75c2016-02-02 15:37:51 -07003127static void demo_init(struct demo *demo, int argc, char **argv) {
Courtney Goeltzenleuchter8879d3a2014-10-29 08:29:35 -06003128 vec3 eye = {0.0f, 3.0f, 5.0f};
3129 vec3 origin = {0, 0, 0};
Chia-I Wuae3b55d2015-04-22 14:56:17 +08003130 vec3 up = {0.0f, 1.0f, 0.0};
Courtney Goeltzenleuchter8879d3a2014-10-29 08:29:35 -06003131
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003132 memset(demo, 0, sizeof(*demo));
Tony Barbour1a86d032015-09-21 15:17:33 -06003133 demo->frameCount = INT32_MAX;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003134
Piers Daniell735ee532015-02-23 16:23:13 -07003135 for (int i = 1; i < argc; i++) {
Tony Barbour3dddd5d2015-04-29 16:19:20 -06003136 if (strcmp(argv[i], "--use_staging") == 0) {
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07003137 demo->use_staging_buffer = true;
Tony Barbour3dddd5d2015-04-29 16:19:20 -06003138 continue;
Ian Elliott639ca472015-04-16 15:23:05 -06003139 }
Courtney Goeltzenleuchter03f4b772015-07-22 11:03:51 -06003140 if (strcmp(argv[i], "--break") == 0) {
3141 demo->use_break = true;
3142 continue;
3143 }
Tony Barbour3dddd5d2015-04-29 16:19:20 -06003144 if (strcmp(argv[i], "--validate") == 0) {
3145 demo->validate = true;
3146 continue;
3147 }
Tony Barbour8295ac42016-08-08 11:04:17 -06003148#if defined(VK_USE_PLATFORM_XLIB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06003149 if (strcmp(argv[i], "--xlib") == 0) {
3150 demo->use_xlib = true;
3151 continue;
3152 }
Tony Barbour8295ac42016-08-08 11:04:17 -06003153#endif
Karl Schultze4dc75c2016-02-02 15:37:51 -07003154 if (strcmp(argv[i], "--c") == 0 && demo->frameCount == INT32_MAX &&
3155 i < argc - 1 && sscanf(argv[i + 1], "%d", &demo->frameCount) == 1 &&
3156 demo->frameCount >= 0) {
David Pinedo2bb7c932015-06-18 17:03:14 -06003157 i++;
3158 continue;
3159 }
lenny-lunargfbe22392016-06-06 11:07:53 -06003160 if (strcmp(argv[i], "--suppress_popups") == 0) {
3161 demo->suppress_popups = true;
3162 continue;
3163 }
Tony Barbour3dddd5d2015-04-29 16:19:20 -06003164
Karl Schultze4dc75c2016-02-02 15:37:51 -07003165 fprintf(stderr, "Usage:\n %s [--use_staging] [--validate] [--break] "
Tony Barbour8295ac42016-08-08 11:04:17 -06003166#if defined(VK_USE_PLATFORM_XLIB_KHR)
3167 "[--xlib] "
3168#endif
lenny-lunargfbe22392016-06-06 11:07:53 -06003169 "[--c <framecount>] [--suppress_popups]\n",
Karl Schultze4dc75c2016-02-02 15:37:51 -07003170 APP_SHORT_NAME);
Ian Elliott639ca472015-04-16 15:23:05 -06003171 fflush(stderr);
3172 exit(1);
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07003173 }
3174
Tony Barbour2593b182016-04-19 10:57:58 -06003175 if (!demo->use_xlib)
3176 demo_init_connection(demo);
3177
Courtney Goeltzenleuchtera4131c42015-04-08 15:36:08 -06003178 demo_init_vk(demo);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003179
Courtney Goeltzenleuchter8879d3a2014-10-29 08:29:35 -06003180 demo->width = 500;
3181 demo->height = 500;
Courtney Goeltzenleuchter8879d3a2014-10-29 08:29:35 -06003182
3183 demo->spin_angle = 0.01f;
3184 demo->spin_increment = 0.01f;
3185 demo->pause = false;
3186
Karl Schultze4dc75c2016-02-02 15:37:51 -07003187 mat4x4_perspective(demo->projection_matrix, (float)degreesToRadians(45.0f),
3188 1.0f, 0.1f, 100.0f);
Courtney Goeltzenleuchter8879d3a2014-10-29 08:29:35 -06003189 mat4x4_look_at(demo->view_matrix, eye, origin, up);
3190 mat4x4_identity(demo->model_matrix);
Rene Lindsaybcccdea2016-08-12 17:56:09 -06003191
3192 demo->projection_matrix[1][1]*=-1; //Flip projection matrix from GL to Vulkan orientation.
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003193}
3194
Michael Lentinec6cde4b2016-04-18 13:20:45 -05003195#if defined(VK_USE_PLATFORM_WIN32_KHR)
Mark Young418b9d12016-01-06 14:26:04 -07003196// Include header required for parsing the command line options.
3197#include <shellapi.h>
Ian Elliottf9cf78c2015-04-28 10:33:11 -06003198
Karl Schultze4dc75c2016-02-02 15:37:51 -07003199int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine,
3200 int nCmdShow) {
3201 MSG msg; // message
3202 bool done; // flag saying when app is complete
Tony Barbour3dddd5d2015-04-29 16:19:20 -06003203 int argc;
Karl Schultze4dc75c2016-02-02 15:37:51 -07003204 char **argv;
Ian Elliott639ca472015-04-16 15:23:05 -06003205
Karl Schultze4dc75c2016-02-02 15:37:51 -07003206 // Use the CommandLine functions to get the command line arguments.
3207 // Unfortunately, Microsoft outputs
3208 // this information as wide characters for Unicode, and we simply want the
3209 // Ascii version to be compatible
3210 // with the non-Windows side. So, we have to convert the information to
3211 // Ascii character strings.
3212 LPWSTR *commandLineArgs = CommandLineToArgvW(GetCommandLineW(), &argc);
3213 if (NULL == commandLineArgs) {
Mark Young418b9d12016-01-06 14:26:04 -07003214 argc = 0;
3215 }
3216
Karl Schultze4dc75c2016-02-02 15:37:51 -07003217 if (argc > 0) {
3218 argv = (char **)malloc(sizeof(char *) * argc);
3219 if (argv == NULL) {
Mark Young418b9d12016-01-06 14:26:04 -07003220 argc = 0;
Karl Schultze4dc75c2016-02-02 15:37:51 -07003221 } else {
3222 for (int iii = 0; iii < argc; iii++) {
3223 size_t wideCharLen = wcslen(commandLineArgs[iii]);
Mark Young418b9d12016-01-06 14:26:04 -07003224 size_t numConverted = 0;
3225
Karl Schultze4dc75c2016-02-02 15:37:51 -07003226 argv[iii] = (char *)malloc(sizeof(char) * (wideCharLen + 1));
3227 if (argv[iii] != NULL) {
3228 wcstombs_s(&numConverted, argv[iii], wideCharLen + 1,
3229 commandLineArgs[iii], wideCharLen + 1);
Mark Young418b9d12016-01-06 14:26:04 -07003230 }
3231 }
3232 }
Karl Schultze4dc75c2016-02-02 15:37:51 -07003233 } else {
Mark Young418b9d12016-01-06 14:26:04 -07003234 argv = NULL;
3235 }
Tony Barbour3dddd5d2015-04-29 16:19:20 -06003236
3237 demo_init(&demo, argc, argv);
Mark Young418b9d12016-01-06 14:26:04 -07003238
3239 // Free up the items we had to allocate for the command line arguments.
Karl Schultze4dc75c2016-02-02 15:37:51 -07003240 if (argc > 0 && argv != NULL) {
3241 for (int iii = 0; iii < argc; iii++) {
3242 if (argv[iii] != NULL) {
Mark Young418b9d12016-01-06 14:26:04 -07003243 free(argv[iii]);
3244 }
3245 }
3246 free(argv);
3247 }
3248
Tony Barbour3dddd5d2015-04-29 16:19:20 -06003249 demo.connection = hInstance;
3250 strncpy(demo.name, "cube", APP_NAME_STR_LEN);
Ian Elliott639ca472015-04-16 15:23:05 -06003251 demo_create_window(&demo);
Tony Barbourcc69f452015-10-08 13:59:42 -06003252 demo_init_vk_swapchain(&demo);
Ian Elliott639ca472015-04-16 15:23:05 -06003253
3254 demo_prepare(&demo);
3255
Karl Schultze4dc75c2016-02-02 15:37:51 -07003256 done = false; // initialize loop condition variable
Mark Young418b9d12016-01-06 14:26:04 -07003257
3258 // main message loop
Karl Schultze4dc75c2016-02-02 15:37:51 -07003259 while (!done) {
Ian Elliotta748eaf2015-04-28 15:50:36 -06003260 PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
Karl Schultze4dc75c2016-02-02 15:37:51 -07003261 if (msg.message == WM_QUIT) // check for a quit message
Ian Elliott639ca472015-04-16 15:23:05 -06003262 {
Karl Schultze4dc75c2016-02-02 15:37:51 -07003263 done = true; // if found, quit app
3264 } else {
Ian Elliott639ca472015-04-16 15:23:05 -06003265 /* Translate and dispatch to event queue*/
Karl Schultze4dc75c2016-02-02 15:37:51 -07003266 TranslateMessage(&msg);
Ian Elliott639ca472015-04-16 15:23:05 -06003267 DispatchMessage(&msg);
3268 }
Tony Barbourc8a59892015-10-20 12:49:46 -06003269 RedrawWindow(demo.window, NULL, NULL, RDW_INTERNALPAINT);
Ian Elliott639ca472015-04-16 15:23:05 -06003270 }
3271
3272 demo_cleanup(&demo);
3273
Karl Schultze4dc75c2016-02-02 15:37:51 -07003274 return (int)msg.wParam;
Ian Elliott639ca472015-04-16 15:23:05 -06003275}
Michael Lentinec6cde4b2016-04-18 13:20:45 -05003276#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
3277#include <android/log.h>
3278#include <android_native_app_glue.h>
3279static bool initialized = false;
3280static bool active = false;
3281struct demo demo;
3282
3283static int32_t processInput(struct android_app* app, AInputEvent* event) {
3284 return 0;
3285}
3286
3287static void processCommand(struct android_app* app, int32_t cmd) {
3288 switch(cmd) {
3289 case APP_CMD_INIT_WINDOW: {
3290 if (app->window) {
Ian Elliottf05d5d12016-05-17 12:03:35 -06003291 // We're getting a new window. If the app is starting up, we
3292 // need to initialize. If the app has already been
3293 // initialized, that means that we lost our previous window,
3294 // which means that we have a lot of work to do. At a minimum,
3295 // we need to destroy the swapchain and surface associated with
3296 // the old window, and create a new surface and swapchain.
3297 // However, since there are a lot of other objects/state that
3298 // is tied to the swapchain, it's easiest to simply cleanup and
3299 // start over (i.e. use a brute-force approach of re-starting
3300 // the app)
3301 if (demo.prepared) {
3302 demo_cleanup(&demo);
3303 }
Michael Lentinec6cde4b2016-04-18 13:20:45 -05003304 demo_init(&demo, 0, NULL);
3305 demo.window = (void*)app->window;
3306 demo_init_vk_swapchain(&demo);
3307 demo_prepare(&demo);
3308 initialized = true;
3309 }
3310 break;
3311 }
3312 case APP_CMD_GAINED_FOCUS: {
3313 active = true;
3314 break;
3315 }
3316 case APP_CMD_LOST_FOCUS: {
3317 active = false;
3318 break;
3319 }
3320 }
3321}
3322
3323void android_main(struct android_app *app)
3324{
3325 app_dummy();
3326
Cody Northrop8707a6e2016-04-26 19:59:19 -06003327#ifdef ANDROID
3328 int vulkanSupport = InitVulkan();
3329 if (vulkanSupport == 0)
3330 return;
3331#endif
3332
Ian Elliottf05d5d12016-05-17 12:03:35 -06003333 demo.prepared = false;
3334
Michael Lentinec6cde4b2016-04-18 13:20:45 -05003335 app->onAppCmd = processCommand;
3336 app->onInputEvent = processInput;
3337
3338 while(1) {
3339 int events;
3340 struct android_poll_source* source;
3341 while (ALooper_pollAll(active ? 0 : -1, NULL, &events, (void**)&source) >= 0) {
3342 if (source) {
3343 source->process(app, source);
3344 }
3345
3346 if (app->destroyRequested != 0) {
3347 demo_cleanup(&demo);
3348 return;
3349 }
3350 }
3351 if (initialized && active) {
3352 demo_run(&demo);
3353 }
3354 }
3355
3356}
Tobin Ehlis43ed2982016-04-28 10:17:33 -06003357#else
Karl Schultze4dc75c2016-02-02 15:37:51 -07003358int main(int argc, char **argv) {
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003359 struct demo demo;
3360
Courtney Goeltzenleuchterb4fc0072015-02-17 12:54:31 -07003361 demo_init(&demo, argc, argv);
Tony Barbour8295ac42016-08-08 11:04:17 -06003362#if defined(VK_USE_PLATFORM_XLIB_KHR) && defined(VK_USE_PLATFORM_XCB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06003363 if (demo.use_xlib)
3364 demo_create_xlib_window(&demo);
3365 else
3366 demo_create_xcb_window(&demo);
Tony Barbour8295ac42016-08-08 11:04:17 -06003367#elif defined(VK_USE_PLATFORM_XCB_KHR)
3368 demo_create_xcb_window(&demo);
3369#elif defined(VK_USE_PLATFORM_XLIB_KHR)
3370 demo_create_xlib_window(&demo);
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09003371#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
3372 demo_create_window(&demo);
3373#endif
Tony Barbour2593b182016-04-19 10:57:58 -06003374
Tony Barbourcc69f452015-10-08 13:59:42 -06003375 demo_init_vk_swapchain(&demo);
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003376
3377 demo_prepare(&demo);
Tony Barbour2593b182016-04-19 10:57:58 -06003378
Tony Barbour8295ac42016-08-08 11:04:17 -06003379#if defined(VK_USE_PLATFORM_XLIB_KHR) && defined(VK_USE_PLATFORM_XCB_KHR)
Tony Barbour2593b182016-04-19 10:57:58 -06003380 if (demo.use_xlib)
3381 demo_run_xlib(&demo);
3382 else
3383 demo_run_xcb(&demo);
Tony Barbour8295ac42016-08-08 11:04:17 -06003384#elif defined(VK_USE_PLATFORM_XCB_KHR)
3385 demo_run_xcb(&demo);
3386#elif defined(VK_USE_PLATFORM_XLIB_KHR)
3387 demo_run_xlib(&demo);
Mun Gwan-gyeong6f01c552016-06-27 05:34:44 +09003388#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
3389 demo_run(&demo);
3390#endif
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003391
3392 demo_cleanup(&demo);
3393
Karl Schultz0218c002016-03-22 17:06:13 -06003394 return validation_error;
Courtney Goeltzenleuchter7be88a82014-10-23 13:16:59 -06003395}
Michael Lentinec6cde4b2016-04-18 13:20:45 -05003396#endif