cube.c revision 3825f87dc62f910827b1b842213fc68b22302e23
1a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong/*
2a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Copyright (c) 2015-2016 The Khronos Group Inc.
3a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Copyright (c) 2015-2016 Valve Corporation
4a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Copyright (c) 2015-2016 LunarG, Inc.
5a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong*
6a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Licensed under the Apache License, Version 2.0 (the "License");
7a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* you may not use this file except in compliance with the License.
8a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* You may obtain a copy of the License at
9a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong*
10a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong*     http://www.apache.org/licenses/LICENSE-2.0
11a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong*
12a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Unless required by applicable law or agreed to in writing, software
13a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* distributed under the License is distributed on an "AS IS" BASIS,
14a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* See the License for the specific language governing permissions and
16a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* limitations under the License.
17a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong*
18a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Author: Chia-I Wu <olv@lunarg.com>
19a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
20a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Author: Ian Elliott <ian@LunarG.com>
21a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Author: Jon Ashburn <jon@lunarg.com>
22a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong* Author: Gwan-gyeong Mun <elongbug@gmail.com>
236b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour* Author: Tony Barbour <tony@LunarG.com>
24a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong*/
25481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz
261722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter#define _GNU_SOURCE
274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <stdio.h>
284e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <stdlib.h>
294e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <string.h>
304e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <stdbool.h>
314e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <assert.h>
32ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter#include <signal.h>
33787b627282489b56b4ed111f152008fe66d33488Mun Gwan-gyeong#if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR)
34a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour#include <X11/Xutil.h>
35a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour#endif
364e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
37e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#ifdef _WIN32
38e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#pragma comment(linker, "/subsystem:windows")
39e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#define APP_NAME_STR_LEN 80
40e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#endif // _WIN32
41e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
42e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop#ifdef ANDROID
43e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop#include "vulkan_wrapper.h"
44e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop#else
45329ca9eb16cdbee7a7644fb08ade7b3d3bb32e23David Pinedo#include <vulkan/vulkan.h>
46e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop#endif
47b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott
48a31fe0bdb3bd5ce67f8bb330264941b196c22677David Pinedo#include <vulkan/vk_sdk_platform.h>
496f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter#include "linmath.h"
506f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
514e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#define DEMO_TEXTURE_COUNT 1
524e19ed0ed322e45993bac7917a1a253dbaaf88f9Ian Elliott#define APP_SHORT_NAME "cube"
534e19ed0ed322e45993bac7917a1a253dbaaf88f9Ian Elliott#define APP_LONG_NAME "The Vulkan Cube Demo Program"
544e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
556b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour// Allow a maximum of two outstanding presentation operations.
566b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour#define FRAME_LAG 2
576b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour
588c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
598c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
6022a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#if defined(NDEBUG) && defined(__GNUC__)
6122a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#define U_ASSERT_ONLY __attribute__((unused))
6222a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#else
6322a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#define U_ASSERT_ONLY
6422a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#endif
6522a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour
66a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#if defined(__GNUC__)
67a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#define UNUSED __attribute__((unused))
68a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#else
69a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#define UNUSED
70a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#endif
71a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
72caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott#ifdef _WIN32
7345c0906c01533675d27207ff07212adf80ab5187Tony Barbourbool in_callback = false;
74481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz#define ERR_EXIT(err_msg, err_class)                                           \
75481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    do {                                                                       \
7620a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        if (!demo->suppress_popups)                                            \
7720a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg            MessageBox(NULL, err_msg, err_class, MB_OK);                       \
78481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        exit(1);                                                               \
79481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    } while (0)
80481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz
8171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#elif defined __ANDROID__
8271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#include <android/log.h>
8371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#define ERR_EXIT(err_msg, err_class)                                           \
8471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    do {                                                                       \
8571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        ((void)__android_log_print(ANDROID_LOG_INFO, "Cube", err_msg));        \
8671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        exit(1);                                                               \
8771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    } while (0)
8871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#else
89481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz#define ERR_EXIT(err_msg, err_class)                                           \
90481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    do {                                                                       \
91481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        printf(err_msg);                                                       \
92481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        fflush(stdout);                                                        \
93481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        exit(1);                                                               \
94481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    } while (0)
9571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
96caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott
97481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz#define GET_INSTANCE_PROC_ADDR(inst, entrypoint)                               \
98481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    {                                                                          \
99481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->fp##entrypoint =                                                 \
100481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
101481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if (demo->fp##entrypoint == NULL) {                                    \
102481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint,    \
103481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                     "vkGetInstanceProcAddr Failure");                         \
104481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        }                                                                      \
105481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    }
106e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
107ccfa841bf1082aa33479ab7691c3042bf57b9c4bJon Ashburnstatic PFN_vkGetDeviceProcAddr g_gdpa = NULL;
108ccfa841bf1082aa33479ab7691c3042bf57b9c4bJon Ashburn
109481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz#define GET_DEVICE_PROC_ADDR(dev, entrypoint)                                  \
110481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    {                                                                          \
111481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if (!g_gdpa)                                                           \
112481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            g_gdpa = (PFN_vkGetDeviceProcAddr)vkGetInstanceProcAddr(           \
113481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                demo->inst, "vkGetDeviceProcAddr");                            \
114481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->fp##entrypoint =                                                 \
115481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (PFN_vk##entrypoint)g_gdpa(dev, "vk" #entrypoint);                 \
116481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if (demo->fp##entrypoint == NULL) {                                    \
117481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint,      \
118481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                     "vkGetDeviceProcAddr Failure");                           \
119481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        }                                                                      \
120481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    }
1211b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott
1227e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter/*
12340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter * structure to track all objects related to a texture.
12440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter */
125bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchterstruct texture_object {
126382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkSampler sampler;
12740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
128382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImage image;
129382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImageLayout imageLayout;
130bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
1311f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    VkMemoryAllocateInfo mem_alloc;
1322318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    VkDeviceMemory mem;
133382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImageView view;
13440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    int32_t tex_width, tex_height;
13540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter};
13640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
137481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic char *tex_files[] = {"lunarg.ppm"};
1381722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
13951940e40346835ebbf3a3fb8c06c07a3eb518e7bKarl Schultzstatic int validation_error = 0;
14051940e40346835ebbf3a3fb8c06c07a3eb518e7bKarl Schultz
1419cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchterstruct vkcube_vs_uniform {
142e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    // Must start with MVP
143481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    float mvp[4][4];
144481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    float position[12 * 3][4];
145481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    float color[12 * 3][4];
146e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
147e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1489cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchterstruct vktexcube_vs_uniform {
149e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    // Must start with MVP
150481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    float mvp[4][4];
151481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    float position[12 * 3][4];
152481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    float attr[12 * 3][4];
153e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
1546f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
1554e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter//--------------------------------------------------------------------------------------
1564e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter// Mesh and VertexFormat Data
1574e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter//--------------------------------------------------------------------------------------
158481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz// clang-format off
159e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinskistatic const float g_vertex_buffer_data[] = {
160c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,  // -X side
1611722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f,-1.0f, 1.0f,
1621722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f, 1.0f, 1.0f,
163c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f, 1.0f, 1.0f,
1641722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f, 1.0f,-1.0f,
1651722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f,-1.0f,-1.0f,
1661722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
167c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,  // -Z side
1681722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f,-1.0f,
1691722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f,-1.0f,
170c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,
1711722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f, 1.0f,-1.0f,
172ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan     1.0f, 1.0f,-1.0f,
1731722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
174c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,  // -Y side
1751722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f,-1.0f,
176ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan     1.0f,-1.0f, 1.0f,
177c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,
1781722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f, 1.0f,
179ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    -1.0f,-1.0f, 1.0f,
1801722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
181c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f, 1.0f,-1.0f,  // +Y side
1821722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f, 1.0f, 1.0f,
1831722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f, 1.0f,
184c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f, 1.0f,-1.0f,
1851722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f, 1.0f,
186ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan     1.0f, 1.0f,-1.0f,
1871722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
188c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu     1.0f, 1.0f,-1.0f,  // +X side
1891722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f, 1.0f,
1901722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f, 1.0f,
191c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu     1.0f,-1.0f, 1.0f,
1921722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f,-1.0f,
1931722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f,-1.0f,
1941722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
195c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f, 1.0f, 1.0f,  // +Z side
1961722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f,-1.0f, 1.0f,
197ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan     1.0f, 1.0f, 1.0f,
198c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f, 1.0f,
1991722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f, 1.0f,
2001722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f, 1.0f,
201e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
202e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
203e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinskistatic const float g_uv_buffer_data[] = {
204cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,  // -X side
205ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    1.0f, 1.0f,
2061722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    1.0f, 0.0f,
2071722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    1.0f, 0.0f,
208ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    0.0f, 0.0f,
2091722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    0.0f, 1.0f,
2101722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
211cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    1.0f, 1.0f,  // -Z side
212c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
213cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,
214c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,
2151722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    1.0f, 0.0f,
216cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 0.0f,
217c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu
218cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    1.0f, 0.0f,  // -Y side
219cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    1.0f, 1.0f,
220cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,
221cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    1.0f, 0.0f,
222ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    0.0f, 1.0f,
223c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
224cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay
225cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    1.0f, 0.0f,  // +Y side
226c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
227cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,
228c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 0.0f,
229cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,
230c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,
2313eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
232cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    1.0f, 0.0f,  // +X side
2333eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    0.0f, 0.0f,
234cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,
235cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,
236c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,
237c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 0.0f,
238cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay
239cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 0.0f,  // +Z side
240cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,
241cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    1.0f, 0.0f,
242cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    0.0f, 1.0f,
243c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,
244cb7f374bc05ba8c0a04aa11557d392ed417ad8e8Rene Lindsay    1.0f, 0.0f,
245e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
246481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz// clang-format on
247e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
248481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzvoid dumpMatrix(const char *note, mat4x4 MVP) {
249e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    int i;
250e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
251e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    printf("%s: \n", note);
252481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    for (i = 0; i < 4; i++) {
253e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        printf("%f, %f, %f, %f\n", MVP[i][0], MVP[i][1], MVP[i][2], MVP[i][3]);
254e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    }
255e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    printf("\n");
256e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    fflush(stdout);
257e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter}
258e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
259481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzvoid dumpVec4(const char *note, vec4 vector) {
260e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    printf("%s: \n", note);
261481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    printf("%f, %f, %f, %f\n", vector[0], vector[1], vector[2], vector[3]);
262e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    printf("\n");
263e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    fflush(stdout);
264e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter}
265e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
266481756e168555e1bf150d3b8f1b81edca1d98c43Karl SchultzVKAPI_ATTR VkBool32 VKAPI_CALL
2675b10b81affa94305e139702a9e239218d039754aKarl SchultzBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
2685b10b81affa94305e139702a9e239218d039754aKarl Schultz              uint64_t srcObject, size_t location, int32_t msgCode,
2695b10b81affa94305e139702a9e239218d039754aKarl Schultz              const char *pLayerPrefix, const char *pMsg,
2705b10b81affa94305e139702a9e239218d039754aKarl Schultz              void *pUserData) {
271ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter#ifndef WIN32
272ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter    raise(SIGTRAP);
273ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter#else
274ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter    DebugBreak();
275ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter#endif
276ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter
277ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter    return false;
278ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter}
279ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter
280788a43f8e47fb32cf12aef25c5eab274a016aef3Mark Lobodzinskitypedef struct {
281e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkImage image;
2821f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    VkCommandBuffer cmd;
2831ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    VkCommandBuffer graphics_to_present_cmd;
2841856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter    VkImageView view;
285338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott} SwapchainBuffers;
286e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
2874e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstruct demo {
28871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#if defined(VK_USE_PLATFORM_WIN32_KHR)
289e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#define APP_NAME_STR_LEN 80
290e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    HINSTANCE connection;        // hInstance - Windows Instance
291e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    char name[APP_NAME_STR_LEN]; // Name to put on the window/icon
292481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    HWND window;                 // hWnd - window handle
293f47577419de04adea60ce9bb6ace9dae668f88d9Rene Lindsay    POINT minsize;               // minimum window size
2944bd81e481fdac06ba3af343dd29bae841d6fff82Tobin Ehlis#elif defined(VK_USE_PLATFORM_XLIB_KHR) | defined(VK_USE_PLATFORM_XCB_KHR)
295a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    Display* display;
296a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    Window xlib_window;
297a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    Atom xlib_wm_delete_window;
2984bd81e481fdac06ba3af343dd29bae841d6fff82Tobin Ehlis
2994e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_connection_t *connection;
3004e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_screen_t *screen;
301a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    xcb_window_t xcb_window;
3025b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu    xcb_intern_atom_reply_t *atom_wm_delete_window;
303a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
304a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    struct wl_display *display;
305a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    struct wl_registry *registry;
306a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    struct wl_compositor *compositor;
307a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    struct wl_surface *window;
308a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    struct wl_shell *shell;
309a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    struct wl_shell_surface *shell_surface;
31071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
31171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    ANativeWindow* window;
31271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
313b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott    VkSurfaceKHR surface;
31475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    bool prepared;
31540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    bool use_staging_buffer;
316a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    bool use_xlib;
3171ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    bool separate_present_queue;
3184e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
319382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkInstance inst;
3208205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    VkPhysicalDevice gpu;
321382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkDevice device;
322755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    VkQueue graphics_queue;
323755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    VkQueue present_queue;
324755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    uint32_t graphics_queue_family_index;
325755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    uint32_t present_queue_family_index;
3266b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    VkSemaphore image_acquired_semaphores[FRAME_LAG];
3276b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    VkSemaphore draw_complete_semaphores[FRAME_LAG];
3286b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    VkSemaphore image_ownership_semaphores[FRAME_LAG];
329426b90566abae5716741aade41184dc4dafe4aa4Tony Barbour    VkPhysicalDeviceProperties gpu_props;
330ef72e2a7cf4fa5708fdbfbc1c972a24ad0dbf809Cody Northrop    VkQueueFamilyProperties *queue_props;
331723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    VkPhysicalDeviceMemoryProperties memory_properties;
3324e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3333d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    uint32_t enabled_extension_count;
3343d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    uint32_t enabled_layer_count;
3353d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    char *extension_names[64];
33697dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz    char *enabled_layers[64];
3373d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour
3384e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    int width, height;
339382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkFormat format;
340338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkColorSpaceKHR color_space;
341338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott
342481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    PFN_vkGetPhysicalDeviceSurfaceSupportKHR
343481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        fpGetPhysicalDeviceSurfaceSupportKHR;
344481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
345481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
346481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
347481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        fpGetPhysicalDeviceSurfaceFormatsKHR;
348481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
349481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        fpGetPhysicalDeviceSurfacePresentModesKHR;
350338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
351338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
352338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
353338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR;
354338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkQueuePresentKHR fpQueuePresentKHR;
355338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    uint32_t swapchainImageCount;
356e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    VkSwapchainKHR swapchain;
357338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    SwapchainBuffers *buffers;
3586b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    VkFence fences[FRAME_LAG];
3596b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    int frame_index;
3604e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3611f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    VkCommandPool cmd_pool;
3621ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    VkCommandPool present_cmd_pool;
3634e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3644e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    struct {
365382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkFormat format;
3664e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
367382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkImage image;
3681f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu        VkMemoryAllocateInfo mem_alloc;
3692318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski        VkDeviceMemory mem;
3701856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        VkImageView view;
3714e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    } depth;
3724e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
373bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    struct texture_object textures[DEMO_TEXTURE_COUNT];
3744e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3754e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    struct {
376382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkBuffer buf;
3771f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu        VkMemoryAllocateInfo mem_alloc;
3782318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski        VkDeviceMemory mem;
37934aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter        VkDescriptorBufferInfo buffer_info;
3806f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    } uniform_data;
3816f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
382481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkCommandBuffer cmd; // Buffer for initialization commands
383556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    VkPipelineLayout pipeline_layout;
384382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkDescriptorSetLayout desc_layout;
3850d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    VkPipelineCache pipelineCache;
38676cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    VkRenderPass render_pass;
387382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkPipeline pipeline;
3884e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3896f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4 projection_matrix;
3906f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4 view_matrix;
3916f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4 model_matrix;
3926f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
393e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float spin_angle;
394e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float spin_increment;
3953eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    bool pause;
3963eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
3979400f09d3b3369554146ce070eb49d2fea00222cTony Barbour    VkShaderModule vert_shader_module;
3989400f09d3b3369554146ce070eb49d2fea00222cTony Barbour    VkShaderModule frag_shader_module;
3999400f09d3b3369554146ce070eb49d2fea00222cTony Barbour
400382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkDescriptorPool desc_pool;
401382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkDescriptorSet desc_set;
402f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
4035aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    VkFramebuffer *framebuffers;
40476cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
4054e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    bool quit;
406eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    int32_t curFrame;
407eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    int32_t frameCount;
4085685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    bool validate;
4093230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter    bool use_break;
41020a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    bool suppress_popups;
411acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter    PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
412acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter    PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
413acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter    VkDebugReportCallbackEXT msg_callback;
414acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter    PFN_vkDebugReportMessageEXT DebugReportMessage;
4151c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
416e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t current_buffer;
41737a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    uint32_t queue_family_count;
4184e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter};
4194e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
42020a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunargVKAPI_ATTR VkBool32 VKAPI_CALL
42120a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunargdbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
42220a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    uint64_t srcObject, size_t location, int32_t msgCode,
42320a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    const char *pLayerPrefix, const char *pMsg, void *pUserData) {
42481fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
42581fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop    // clang-format off
42620a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    char *message = (char *)malloc(strlen(pMsg) + 100);
42720a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg
42820a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    assert(message);
42920a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg
43081fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop    // We know we're submitting queues without fences, ignore this
43181fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop    if (strstr(pMsg, "vkQueueSubmit parameter, VkFence fence, is null pointer"))
43281fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        return false;
43381fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
43481fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop    if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
43581fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        sprintf(message, "INFORMATION: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
43620a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        validation_error = 1;
43720a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
43881fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
43981fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        validation_error = 1;
44081fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop    } else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
441a0508c7a27d892907dbd5fb16b488eba2cd914f1Mike Weiblen        sprintf(message, "PERFORMANCE WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
44281fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        validation_error = 1;
44381fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop    } else if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
44481fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
44581fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        validation_error = 1;
44681fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop    } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
44781fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        sprintf(message, "DEBUG: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
44820a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        validation_error = 1;
44920a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    } else {
45081fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        sprintf(message, "INFORMATION: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
45120a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        validation_error = 1;
45220a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    }
45320a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg
45420a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg#ifdef _WIN32
45581fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
45645c0906c01533675d27207ff07212adf80ab5187Tony Barbour    in_callback = true;
45720a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    struct demo *demo = (struct demo*) pUserData;
45820a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    if (!demo->suppress_popups)
45920a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        MessageBox(NULL, message, "Alert", MB_OK);
46045c0906c01533675d27207ff07212adf80ab5187Tony Barbour    in_callback = false;
46181fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
46248a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop#elif defined(ANDROID)
46381fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
46448a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop    if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
46581fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        __android_log_print(ANDROID_LOG_INFO,  APP_SHORT_NAME, "%s", message);
46648a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop    } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
46781fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        __android_log_print(ANDROID_LOG_WARN,  APP_SHORT_NAME, "%s", message);
46848a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop    } else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
46981fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        __android_log_print(ANDROID_LOG_WARN,  APP_SHORT_NAME, "%s", message);
47048a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop    } else if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
47181fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        __android_log_print(ANDROID_LOG_ERROR, APP_SHORT_NAME, "%s", message);
47248a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop    } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
47381fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        __android_log_print(ANDROID_LOG_DEBUG, APP_SHORT_NAME, "%s", message);
47448a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop    } else {
47581fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        __android_log_print(ANDROID_LOG_INFO,  APP_SHORT_NAME, "%s", message);
47648a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop    }
47781fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
47820a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg#else
47981fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
48020a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    printf("%s\n", message);
48120a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    fflush(stdout);
48281fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
48320a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg#endif
48481fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
48520a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    free(message);
48620a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg
48781fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop    //clang-format on
48881fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop
48920a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    /*
49020a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    * false indicates that layer should not bail-out of an
49120a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    * API call that had validation failures. This may mean that the
49220a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    * app dies inside the driver due to invalid parameter(s).
49320a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    * That's what would happen without validation layers, so we'll
49420a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    * keep that behavior here.
49520a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    */
49620a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg    return false;
49720a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg}
49820a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg
499e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott// Forward declaration:
500e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliottstatic void demo_resize(struct demo *demo);
501e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
502481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic bool memory_type_from_properties(struct demo *demo, uint32_t typeBits,
503481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                        VkFlags requirements_mask,
504481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                        uint32_t *typeIndex) {
505481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // Search memtypes to find first index with those properties
5067a9f75412934c8300e18e3a1c0dd2513f098a361Alexandre BACQUART    for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
507481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if ((typeBits & 1) == 1) {
508481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            // Type is available, does it match user properties?
509481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            if ((demo->memory_properties.memoryTypes[i].propertyFlags &
510481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 requirements_mask) == requirements_mask) {
511481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                *typeIndex = i;
512481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                return true;
513481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            }
514481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        }
515481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        typeBits >>= 1;
516481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    }
517481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // No memory types matched, return failure
518481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    return false;
519723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski}
520723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski
521481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_flush_init_cmd(struct demo *demo) {
52222a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
523bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
524a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    // This function could get called twice if the texture uses a staging buffer
525a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    // In that case the second call should be ignored
5269cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    if (demo->cmd == VK_NULL_HANDLE)
527bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        return;
528bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
5299cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkEndCommandBuffer(demo->cmd);
530bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    assert(!err);
531bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
532a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    VkFence fence;
533a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    VkFenceCreateInfo fence_ci = {.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
534a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour                                  .pNext = NULL,
535a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour                                  .flags = 0};
536a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    vkCreateFence(demo->device, &fence_ci, NULL, &fence);
537481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    const VkCommandBuffer cmd_bufs[] = {demo->cmd};
538481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
539481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                .pNext = NULL,
540481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                .waitSemaphoreCount = 0,
541481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                .pWaitSemaphores = NULL,
542481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                .pWaitDstStageMask = NULL,
543481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                .commandBufferCount = 1,
544481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                .pCommandBuffers = cmd_bufs,
545481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                .signalSemaphoreCount = 0,
546481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                .pSignalSemaphores = NULL};
547bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
548a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    err = vkQueueSubmit(demo->graphics_queue, 1, &submit_info, fence);
549bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    assert(!err);
550bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
551a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    err = vkWaitForFences(demo->device, 1, &fence, VK_TRUE, UINT64_MAX);
552bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    assert(!err);
553bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
554831c183417705004ea225726d450b7259e7384c7Courtney Goeltzenleuchter    vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, cmd_bufs);
555a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    vkDestroyFence(demo->device, fence, NULL);
5569cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    demo->cmd = VK_NULL_HANDLE;
557bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter}
558bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
559481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_set_image_layout(struct demo *demo, VkImage image,
560481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  VkImageAspectFlags aspectMask,
561481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  VkImageLayout old_image_layout,
562866af6ca38e3bcde21ea9235de1b7a044279e6b8Tobin Ehlis                                  VkImageLayout new_image_layout,
563df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VkAccessFlagBits srcAccessMask,
564df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VkPipelineStageFlags src_stages,
565df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VkPipelineStageFlags dest_stages) {
5663825f87dc62f910827b1b842213fc68b22302e23Tony Barbour    assert(demo->cmd);
567bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
568382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImageMemoryBarrier image_memory_barrier = {
5699cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
570bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .pNext = NULL,
571866af6ca38e3bcde21ea9235de1b7a044279e6b8Tobin Ehlis        .srcAccessMask = srcAccessMask,
572989de845e6627fecee8dceef882955149b7538baChia-I Wu        .dstAccessMask = 0,
573bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .oldLayout = old_image_layout,
574bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .newLayout = new_image_layout,
575bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .image = image,
576481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .subresourceRange = {aspectMask, 0, 1, 0, 1}};
577bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
578e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour    switch (new_image_layout) {
579e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
580bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        /* Make sure anything that was copying from this image has completed */
581e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
582e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        break;
583bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
584e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
585481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        image_memory_barrier.dstAccessMask =
586481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
587e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        break;
588fd61894f0ee23900127d320440cb251aa19d0fcbMark Lobodzinski
589e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
590481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        image_memory_barrier.dstAccessMask =
591481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
592e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        break;
593fd61894f0ee23900127d320440cb251aa19d0fcbMark Lobodzinski
594e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
595481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        image_memory_barrier.dstAccessMask =
596481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
597e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        break;
598bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
599e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
600e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
601e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        break;
602e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour
603e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
6043d7b1e39e7763ee8d60c8fae7a65a8c22ae3b6d1Tony Barbour        image_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
605e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        break;
606e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour
607e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour    default:
608e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        image_memory_barrier.dstAccessMask = 0;
609e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour        break;
6103d7b1e39e7763ee8d60c8fae7a65a8c22ae3b6d1Tony Barbour    }
6113d7b1e39e7763ee8d60c8fae7a65a8c22ae3b6d1Tony Barbour
612e4dd74afb4dc6f9701f9bf19c23574adae816ed3Tony Barbour
613382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
614bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
615481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    vkCmdPipelineBarrier(demo->cmd, src_stages, dest_stages, 0, 0, NULL, 0,
616481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                         NULL, 1, pmemory_barrier);
617bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter}
618bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
619481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_draw_build_cmd(struct demo *demo, VkCommandBuffer cmd_buf) {
620a4ae48bfd6f2e2a80e1f92e054a007cf90a4e218Jon Ashburn    const VkCommandBufferBeginInfo cmd_buf_info = {
621a4ae48bfd6f2e2a80e1f92e054a007cf90a4e218Jon Ashburn        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
622a4ae48bfd6f2e2a80e1f92e054a007cf90a4e218Jon Ashburn        .pNext = NULL,
623a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour        .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
6241213c570f44b1314c96eafccad4b09f1d2707f24Rene Lindsay        .pInheritanceInfo = NULL,
625a4ae48bfd6f2e2a80e1f92e054a007cf90a4e218Jon Ashburn    };
626c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkClearValue clear_values[2] = {
627481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            [0] = {.color.float32 = {0.2f, 0.2f, 0.2f, 0.2f}},
628481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            [1] = {.depthStencil = {1.0f, 0}},
629c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    };
630c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkRenderPassBeginInfo rp_begin = {
631c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
632c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pNext = NULL,
63376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        .renderPass = demo->render_pass,
63476cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        .framebuffer = demo->framebuffers[demo->current_buffer],
635c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .renderArea.offset.x = 0,
636c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .renderArea.offset.y = 0,
637c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .renderArea.extent.width = demo->width,
638c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .renderArea.extent.height = demo->height,
639c332eefa3e8b7e97ca70abd8cfaa0d4f4e1b0fc2Cody Northrop        .clearValueCount = 2,
640c332eefa3e8b7e97ca70abd8cfaa0d4f4e1b0fc2Cody Northrop        .pClearValues = clear_values,
6413325d6b8ffdef53d826177f16c84d4d8ee752c11Jon Ashburn    };
64276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    VkResult U_ASSERT_ONLY err;
6434e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6449cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkBeginCommandBuffer(cmd_buf, &cmd_buf_info);
6454e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
646c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu    vkCmdBeginRenderPass(cmd_buf, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
647481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline);
648481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS,
649481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                            demo->pipeline_layout, 0, 1, &demo->desc_set, 0,
650481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                            NULL);
65109772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    VkViewport viewport;
65209772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    memset(&viewport, 0, sizeof(viewport));
653481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    viewport.height = (float)demo->height;
654481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    viewport.width = (float)demo->width;
655481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    viewport.minDepth = (float)0.0f;
656481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    viewport.maxDepth = (float)1.0f;
657f25165255ccfd9bce7c80b77942fc4f2132947a2Jon Ashburn    vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
65809772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter
65909772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    VkRect2D scissor;
66009772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    memset(&scissor, 0, sizeof(scissor));
66109772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    scissor.extent.width = demo->width;
66209772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    scissor.extent.height = demo->height;
66309772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    scissor.offset.x = 0;
66409772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    scissor.offset.y = 0;
665f25165255ccfd9bce7c80b77942fc4f2132947a2Jon Ashburn    vkCmdSetScissor(cmd_buf, 0, 1, &scissor);
6664ff11cc681bf32052b69573eb1418173f6b0262bCourtney Goeltzenleuchter    vkCmdDraw(cmd_buf, 12 * 3, 1, 0, 0);
667a5b04f44d06af86b917f3866f8e05404ff3aa052Tony Barbour    // Note that ending the renderpass changes the image's layout from
6681ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    // COLOR_ATTACHMENT_OPTIMAL to PRESENT_SRC_KHR
66988eaa3bf0c7874f8b62cf35e3b649201ecc47c36Chia-I Wu    vkCmdEndRenderPass(cmd_buf);
6704e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6711ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    if (demo->separate_present_queue) {
6721ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        // We have to transfer ownership from the graphics queue family to the
6731ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        // present queue family to be able to present.  Note that we don't have
6741ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        // to transfer from present queue family back to graphics queue family at
6751ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        // the start of the next frame because we don't care about the image's
6761ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        // contents at that point.
6771ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        VkImageMemoryBarrier image_ownership_barrier = {
6781ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
6791ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .pNext = NULL,
6801ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .srcAccessMask = 0,
6811ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
6821ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
6831ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
6841ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .srcQueueFamilyIndex = demo->graphics_queue_family_index,
6851ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .dstQueueFamilyIndex = demo->present_queue_family_index,
6861ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .image = demo->buffers[demo->current_buffer].image,
6871ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
6881ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
6891ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        vkCmdPipelineBarrier(cmd_buf,
6901ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour                             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
691746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour                             VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
6921ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour                             0, NULL, 0, NULL, 1, &image_ownership_barrier);
6931ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    }
6949cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkEndCommandBuffer(cmd_buf);
6954e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
6964e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
6974e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6981ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbourvoid demo_build_image_ownership_cmd(struct demo *demo, int i) {
6991ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    VkResult U_ASSERT_ONLY err;
7001ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
7011ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    const VkCommandBufferBeginInfo cmd_buf_info = {
7021ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
7031ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .pNext = NULL,
7041ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
7051ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .pInheritanceInfo = NULL,
7061ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    };
7071ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    err = vkBeginCommandBuffer(demo->buffers[i].graphics_to_present_cmd,
7081ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour                               &cmd_buf_info);
7091ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    assert(!err);
7101ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
7111ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    VkImageMemoryBarrier image_ownership_barrier = {
7121ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
7131ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .pNext = NULL,
7141ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .srcAccessMask = 0,
7151ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
7161ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
7171ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
7181ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .srcQueueFamilyIndex = demo->graphics_queue_family_index,
7191ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .dstQueueFamilyIndex = demo->present_queue_family_index,
7201ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .image = demo->buffers[i].image,
7211ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
7221ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
7231ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    vkCmdPipelineBarrier(demo->buffers[i].graphics_to_present_cmd,
7241ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
7251ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0,
7261ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour                         NULL, 0, NULL, 1, &image_ownership_barrier);
7271ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    err = vkEndCommandBuffer(demo->buffers[i].graphics_to_present_cmd);
7281ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    assert(!err);
7291ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour}
7301ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
731481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzvoid demo_update_data_buffer(struct demo *demo) {
7326f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4 MVP, Model, VP;
7336f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    int matrixSize = sizeof(MVP);
734e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint8_t *pData;
73522a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
7364e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
7376f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4_mul(VP, demo->projection_matrix, demo->view_matrix);
7384e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
7396f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    // Rotate 22.5 degrees around the Y axis
740e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4_dup(Model, demo->model_matrix);
741481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    mat4x4_rotate(demo->model_matrix, Model, 0.0f, 1.0f, 0.0f,
742481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                  (float)degreesToRadians(demo->spin_angle));
743e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4_mul(MVP, VP, demo->model_matrix);
7444e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
745481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkMapMemory(demo->device, demo->uniform_data.mem, 0,
746481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                      demo->uniform_data.mem_alloc.allocationSize, 0,
747481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                      (void **)&pData);
7486f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    assert(!err);
7494e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
750481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    memcpy(pData, (const void *)&MVP[0][0], matrixSize);
7514e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
75267b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski    vkUnmapMemory(demo->device, demo->uniform_data.mem);
7534e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
7544e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
755481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_draw(struct demo *demo) {
756e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkResult U_ASSERT_ONLY err;
7579e816866fc9593792a6b88ebff456697018aa547Tony Barbour
758ed0cd2f95c18b3d3f267c45b149ba435b7d3a0eeszdarkhack    // Ensure no more than FRAME_LAG presentations are outstanding
759ed0cd2f95c18b3d3f267c45b149ba435b7d3a0eeszdarkhack    vkWaitForFences(demo->device, 1, &demo->fences[demo->frame_index], VK_TRUE, UINT64_MAX);
760ed0cd2f95c18b3d3f267c45b149ba435b7d3a0eeszdarkhack    vkResetFences(demo->device, 1, &demo->fences[demo->frame_index]);
7616b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour
762e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Get the index of the next available swapchain image:
763481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = demo->fpAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX,
7646b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour                                      demo->image_acquired_semaphores[demo->frame_index], demo->fences[demo->frame_index],
765e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                                      &demo->current_buffer);
7666b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour
767e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    if (err == VK_ERROR_OUT_OF_DATE_KHR) {
768e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        // demo->swapchain is out of date (e.g. the window was resized) and
769e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        // must be recreated:
7706b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        demo->frame_index += 1;
7716b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        demo->frame_index %= FRAME_LAG;
7726b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour
773e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        demo_resize(demo);
774e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        demo_draw(demo);
775e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        return;
776e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    } else if (err == VK_SUBOPTIMAL_KHR) {
777e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        // demo->swapchain is not as optimal as it could be, but the platform's
778e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        // presentation engine will still present the image correctly.
779e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    } else {
780e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        assert(!err);
781e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    }
782a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    // Wait for the image acquired semaphore to be signaled to ensure
7833ec31629900b5a52fa112d6670ffb6771fe9adcaCourtney Goeltzenleuchter    // that the image won't be rendered to until the presentation
7843ec31629900b5a52fa112d6670ffb6771fe9adcaCourtney Goeltzenleuchter    // engine has fully released ownership to the application, and it is
7853ec31629900b5a52fa112d6670ffb6771fe9adcaCourtney Goeltzenleuchter    // okay to render to the image.
786235dfbb4c5b31c8c26a5cefdd96cedbc82d428ceIan Elliott    VkFence nullFence = VK_NULL_HANDLE;
7871ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    VkPipelineStageFlags pipe_stage_flags;
7881ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    VkSubmitInfo submit_info;
7891ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
7901ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    submit_info.pNext = NULL;
7911ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    submit_info.pWaitDstStageMask = &pipe_stage_flags;
7921ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
7931ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    submit_info.waitSemaphoreCount = 1;
7946b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    submit_info.pWaitSemaphores = &demo->image_acquired_semaphores[demo->frame_index];
7951ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    submit_info.commandBufferCount = 1;
7961ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    submit_info.pCommandBuffers = &demo->buffers[demo->current_buffer].cmd;
7971ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    submit_info.signalSemaphoreCount = 1;
7986b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    submit_info.pSignalSemaphores = &demo->draw_complete_semaphores[demo->frame_index];
799755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    err = vkQueueSubmit(demo->graphics_queue, 1, &submit_info, nullFence);
8004e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
8014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
8021ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    if (demo->separate_present_queue) {
8031ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        // If we are using separate queues, change image ownership to the
8041ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        // present queue before presenting, waiting for the draw complete
8051ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        // semaphore and signalling the ownership released semaphore when finished
8061ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
8071ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        submit_info.waitSemaphoreCount = 1;
8086b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        submit_info.pWaitSemaphores = &demo->draw_complete_semaphores[demo->frame_index];
8091ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        submit_info.commandBufferCount = 1;
8101ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        submit_info.pCommandBuffers =
8111ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            &demo->buffers[demo->current_buffer].graphics_to_present_cmd;
8121ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        submit_info.signalSemaphoreCount = 1;
8136b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        submit_info.pSignalSemaphores = &demo->image_ownership_semaphores[demo->frame_index];
8141ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        err = vkQueueSubmit(demo->present_queue, 1, &submit_info, nullFence);
8151ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        assert(!err);
8161ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    }
8171ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
8181ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    // If we are using separate queues we have to wait for image ownership,
8191ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    // otherwise wait for draw complete
820338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkPresentInfoKHR present = {
821338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
822e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        .pNext = NULL,
823b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        .waitSemaphoreCount = 1,
8241ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .pWaitSemaphores = (demo->separate_present_queue)
8256b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour                               ? &demo->image_ownership_semaphores[demo->frame_index]
8266b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour                               : &demo->draw_complete_semaphores[demo->frame_index],
827338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .swapchainCount = 1,
828b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        .pSwapchains = &demo->swapchain,
829b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        .pImageIndices = &demo->current_buffer,
830e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    };
831e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
832755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    err = demo->fpQueuePresentKHR(demo->present_queue, &present);
8336b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    demo->frame_index += 1;
8346b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    demo->frame_index %= FRAME_LAG;
8356b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour
836e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    if (err == VK_ERROR_OUT_OF_DATE_KHR) {
837e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        // demo->swapchain is out of date (e.g. the window was resized) and
838e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        // must be recreated:
839e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        demo_resize(demo);
840e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    } else if (err == VK_SUBOPTIMAL_KHR) {
841e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        // demo->swapchain is not as optimal as it could be, but the platform's
842e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        // presentation engine will still present the image correctly.
843e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    } else {
844e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        assert(!err);
845e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    }
8464e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
8474e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
848481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_buffers(struct demo *demo) {
849e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkResult U_ASSERT_ONLY err;
850e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    VkSwapchainKHR oldSwapchain = demo->swapchain;
851e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
852b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott    // Check the surface capabilities and formats
853b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott    VkSurfaceCapabilitiesKHR surfCapabilities;
854481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = demo->fpGetPhysicalDeviceSurfaceCapabilitiesKHR(
855481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->gpu, demo->surface, &surfCapabilities);
856e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
857e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
8587fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    uint32_t presentModeCount;
859481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = demo->fpGetPhysicalDeviceSurfacePresentModesKHR(
860481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->gpu, demo->surface, &presentModeCount, NULL);
861e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
862338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkPresentModeKHR *presentModes =
863338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
8647fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    assert(presentModes);
865481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = demo->fpGetPhysicalDeviceSurfacePresentModesKHR(
866481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->gpu, demo->surface, &presentModeCount, presentModes);
867e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
868e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
869338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkExtent2D swapchainExtent;
870b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott    // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
871b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott    if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) {
872b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        // If the surface size is undefined, the size is set to the size
873b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        // of the images requested, which must fit within the minimum and
874b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        // maximum values.
875338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        swapchainExtent.width = demo->width;
876338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        swapchainExtent.height = demo->height;
877b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott
878b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        if (swapchainExtent.width < surfCapabilities.minImageExtent.width) {
879b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott            swapchainExtent.width = surfCapabilities.minImageExtent.width;
880b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        } else if (swapchainExtent.width > surfCapabilities.maxImageExtent.width) {
881b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott            swapchainExtent.width = surfCapabilities.maxImageExtent.width;
882b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        }
883b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott
884b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        if (swapchainExtent.height < surfCapabilities.minImageExtent.height) {
885b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott            swapchainExtent.height = surfCapabilities.minImageExtent.height;
886b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        } else if (swapchainExtent.height > surfCapabilities.maxImageExtent.height) {
887b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott            swapchainExtent.height = surfCapabilities.maxImageExtent.height;
888b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        }
889481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    } else {
890e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        // If the surface size is defined, the swap chain size must match
891b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        swapchainExtent = surfCapabilities.currentExtent;
892b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        demo->width = surfCapabilities.currentExtent.width;
893b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        demo->height = surfCapabilities.currentExtent.height;
894e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
895e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
8966b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    // The FIFO present mode is guaranteed by the spec to be supported
8976455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // and to have no tearing.  It's a great default present mode to use.
898338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
8996455efbcfbea3117d3eaded354318126a1252927Ian Elliott    //  There are times when you may wish to use another present mode.  The
9006455efbcfbea3117d3eaded354318126a1252927Ian Elliott    //  following code shows how to select them, and the comments provide some
9016455efbcfbea3117d3eaded354318126a1252927Ian Elliott    //  reasons you may wish to use them.
9026455efbcfbea3117d3eaded354318126a1252927Ian Elliott    //
9036455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // It should be noted that Vulkan 1.0 doesn't provide a method for
9046455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // synchronizing rendering with the presentation engine's display.  There
9056455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // is a method provided for throttling rendering with the display, but
9066455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // there are some presentation engines for which this method will not work.
9076455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // If an application doesn't throttle its rendering, and if it renders much
9086455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // faster than the refresh rate of the display, this can waste power on
9096455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // mobile devices.  That is because power is being spent rendering images
9106455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // that may never be seen.
9116455efbcfbea3117d3eaded354318126a1252927Ian Elliott//#define DESIRE_VK_PRESENT_MODE_IMMEDIATE_KHR
9126455efbcfbea3117d3eaded354318126a1252927Ian Elliott//#define DESIRE_VK_PRESENT_MODE_MAILBOX_KHR
9136455efbcfbea3117d3eaded354318126a1252927Ian Elliott//#define DESIRE_VK_PRESENT_MODE_FIFO_RELAXED_KHR
9146455efbcfbea3117d3eaded354318126a1252927Ian Elliott#if defined(DESIRE_VK_PRESENT_MODE_IMMEDIATE_KHR)
9156455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // VK_PRESENT_MODE_IMMEDIATE_KHR is for applications that don't care about
9166455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // tearing, or have some way of synchronizing their rendering with the
9176455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // display.
9186455efbcfbea3117d3eaded354318126a1252927Ian Elliott    for (size_t i = 0; i < presentModeCount; ++i) {
9196455efbcfbea3117d3eaded354318126a1252927Ian Elliott        if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) {
9206455efbcfbea3117d3eaded354318126a1252927Ian Elliott            swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
9216455efbcfbea3117d3eaded354318126a1252927Ian Elliott            break;
9226455efbcfbea3117d3eaded354318126a1252927Ian Elliott        }
9236455efbcfbea3117d3eaded354318126a1252927Ian Elliott    }
9246455efbcfbea3117d3eaded354318126a1252927Ian Elliott#elif defined(DESIRE_VK_PRESENT_MODE_MAILBOX_KHR)
9256455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // VK_PRESENT_MODE_MAILBOX_KHR may be useful for applications that
9266455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // generally render a new presentable image every refresh cycle, but are
9276455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // occasionally early.  In this case, the application wants the new image
9286455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // to be displayed instead of the previously-queued-for-presentation image
9296455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // that has not yet been displayed.
9306455efbcfbea3117d3eaded354318126a1252927Ian Elliott    for (size_t i = 0; i < presentModeCount; ++i) {
9316455efbcfbea3117d3eaded354318126a1252927Ian Elliott        if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
9326455efbcfbea3117d3eaded354318126a1252927Ian Elliott            swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
9336455efbcfbea3117d3eaded354318126a1252927Ian Elliott            break;
9346455efbcfbea3117d3eaded354318126a1252927Ian Elliott        }
9356455efbcfbea3117d3eaded354318126a1252927Ian Elliott    }
9366455efbcfbea3117d3eaded354318126a1252927Ian Elliott#elif defined(DESIRE_VK_PRESENT_MODE_FIFO_RELAXED_KHR)
9376455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // VK_PRESENT_MODE_FIFO_RELAXED_KHR is for applications that generally
9386455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // render a new presentable image every refresh cycle, but are occasionally
9396455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // late.  In this case (perhaps because of stuttering/latency concerns),
9406455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // the application wants the late image to be immediately displayed, even
9416455efbcfbea3117d3eaded354318126a1252927Ian Elliott    // though that may mean some tearing.
9426455efbcfbea3117d3eaded354318126a1252927Ian Elliott    for (size_t i = 0; i < presentModeCount; ++i) {
9436455efbcfbea3117d3eaded354318126a1252927Ian Elliott        if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
9446455efbcfbea3117d3eaded354318126a1252927Ian Elliott            swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
9456455efbcfbea3117d3eaded354318126a1252927Ian Elliott            break;
9466455efbcfbea3117d3eaded354318126a1252927Ian Elliott        }
9476455efbcfbea3117d3eaded354318126a1252927Ian Elliott    }
9486455efbcfbea3117d3eaded354318126a1252927Ian Elliott#endif
949e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
950b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott    // Determine the number of VkImage's to use in the swap chain.
951b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott    // Application desires to only acquire 1 image at a time (which is
952b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott    // "surfCapabilities.minImageCount").
953b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott    uint32_t desiredNumOfSwapchainImages = surfCapabilities.minImageCount;
954b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott    // If maxImageCount is 0, we can ask for as many images as we want;
955b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott    // otherwise we're limited to maxImageCount
956b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott    if ((surfCapabilities.maxImageCount > 0) &&
957b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        (desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) {
958e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        // Application must settle for fewer images than desired:
959b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        desiredNumOfSwapchainImages = surfCapabilities.maxImageCount;
960e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
961e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
962d161c54f8fc84e3447cb1162a3a7fd6d94ffc6ceTony Barbour    VkSurfaceTransformFlagsKHR preTransform;
963481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    if (surfCapabilities.supportedTransforms &
964481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
965da44dfef7703f795e9de97fe6bda17b68864bc24Ian Elliott        preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
966e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    } else {
967b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        preTransform = surfCapabilities.currentTransform;
968e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
969e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
970755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    VkSwapchainCreateInfoKHR swapchain_ci = {
971434d222a014e1ac8cf656ef8fc17faa1d224ad2fIan Elliott        .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
9725b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu        .pNext = NULL,
973b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        .surface = demo->surface,
974b3cc6ce5cccdb1e47e1766e4faa39683b33eca53Ian Elliott        .minImageCount = desiredNumOfSwapchainImages,
9755b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu        .imageFormat = demo->format,
9767fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        .imageColorSpace = demo->color_space,
977481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .imageExtent =
978481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            {
979481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz             .width = swapchainExtent.width, .height = swapchainExtent.height,
980481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            },
981b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
982e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        .preTransform = preTransform,
9833f07ab67336dcacfa0ac62f7987e9c26cd33ba6eIan Elliott        .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
984b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        .imageArrayLayers = 1,
985b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
986b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        .queueFamilyIndexCount = 0,
9877fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        .pQueueFamilyIndices = NULL,
988338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .presentMode = swapchainPresentMode,
989e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        .oldSwapchain = oldSwapchain,
990e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        .clipped = true,
99168040a41017a2e9e81a86af2d083a3079e882b96Chia-I Wu    };
992e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t i;
993755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    err = demo->fpCreateSwapchainKHR(demo->device, &swapchain_ci, NULL,
994481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                     &demo->swapchain);
9955b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu    assert(!err);
9965b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu
997e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // If we just re-created an existing swapchain, we should destroy the old
998e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // swapchain at this point.
999e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // Note: destroying the swapchain also cleans up all its associated
1000e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // presentable images once the platform is done with them.
1001e420a33ff7bdcf67b8a487592af78a3ca2f29ee6Chia-I Wu    if (oldSwapchain != VK_NULL_HANDLE) {
1002b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott        demo->fpDestroySwapchainKHR(demo->device, oldSwapchain, NULL);
1003e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    }
1004e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
1005e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    err = demo->fpGetSwapchainImagesKHR(demo->device, demo->swapchain,
1006338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                        &demo->swapchainImageCount, NULL);
1007e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
10085b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu
1009481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkImage *swapchainImages =
1010481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        (VkImage *)malloc(demo->swapchainImageCount * sizeof(VkImage));
1011338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    assert(swapchainImages);
1012e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    err = demo->fpGetSwapchainImagesKHR(demo->device, demo->swapchain,
1013338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                        &demo->swapchainImageCount,
1014338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                        swapchainImages);
1015e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
1016e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
1017481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    demo->buffers = (SwapchainBuffers *)malloc(sizeof(SwapchainBuffers) *
1018481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                               demo->swapchainImageCount);
1019e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(demo->buffers);
1020e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
1021338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    for (i = 0; i < demo->swapchainImageCount; i++) {
10221856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        VkImageViewCreateInfo color_image_view = {
10231856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
10244e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .pNext = NULL,
10254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .format = demo->format,
1026481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            .components =
1027481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                {
1028481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .r = VK_COMPONENT_SWIZZLE_R,
1029481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .g = VK_COMPONENT_SWIZZLE_G,
1030481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .b = VK_COMPONENT_SWIZZLE_B,
1031481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .a = VK_COMPONENT_SWIZZLE_A,
1032481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                },
1033481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1034481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                 .baseMipLevel = 0,
1035481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                 .levelCount = 1,
1036481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                 .baseArrayLayer = 0,
1037481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                 .layerCount = 1},
10381856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .viewType = VK_IMAGE_VIEW_TYPE_2D,
10391856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .flags = 0,
10404e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        };
10414e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1042338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        demo->buffers[i].image = swapchainImages[i];
10434e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
10441856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        color_image_view.image = demo->buffers[i].image;
10454e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1046481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        err = vkCreateImageView(demo->device, &color_image_view, NULL,
1047481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                &demo->buffers[i].view);
10484e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        assert(!err);
10491ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
10504e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
1051481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz
1052842f94166580a40cfcd631a11681db600ed42821Mark Young    if (NULL != presentModes) {
1053842f94166580a40cfcd631a11681db600ed42821Mark Young        free(presentModes);
1054842f94166580a40cfcd631a11681db600ed42821Mark Young    }
10554e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
10564e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1057481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_depth(struct demo *demo) {
10588205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    const VkFormat depth_format = VK_FORMAT_D16_UNORM;
1059382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkImageCreateInfo image = {
10609cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
10614e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .pNext = NULL,
10628205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour        .imageType = VK_IMAGE_TYPE_2D,
10634e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .format = depth_format,
1064481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .extent = {demo->width, demo->height, 1},
10654e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .mipLevels = 1,
10662ebc234580f41270585dfbbe2925358dd41b125eCourtney Goeltzenleuchter        .arrayLayers = 1,
10673138d6a7fafb314644a22a854267258769c6d6a0Chia-I Wu        .samples = VK_SAMPLE_COUNT_1_BIT,
10688205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour        .tiling = VK_IMAGE_TILING_OPTIMAL,
1069c3b8eea2f5e66db11651068575f4712cf195f542Courtney Goeltzenleuchter        .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
10704e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .flags = 0,
10714e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
1072e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak
10731856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter    VkImageViewCreateInfo view = {
10741856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
10754e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .pNext = NULL,
1076e420a33ff7bdcf67b8a487592af78a3ca2f29ee6Chia-I Wu        .image = VK_NULL_HANDLE,
10774ab40c4acb0e4c17283a889dfe4fff9f29ff2ec3Courtney Goeltzenleuchter        .format = depth_format,
1078481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
1079481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                             .baseMipLevel = 0,
1080481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                             .levelCount = 1,
1081481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                             .baseArrayLayer = 0,
1082481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                             .layerCount = 1},
10834e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .flags = 0,
10841856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        .viewType = VK_IMAGE_VIEW_TYPE_2D,
10854e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
1086230e62505478ab0d9b05003e0e48baa5f090c6a0Mike Stroyan
10872318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    VkMemoryRequirements mem_reqs;
108822a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
108937a43a64af08599b5fe5429c6c331f42f765fca9Courtney Goeltzenleuchter    bool U_ASSERT_ONLY pass;
10904e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
10914e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo->depth.format = depth_format;
10924e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
10934e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    /* create image */
1094481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkCreateImage(demo->device, &image, NULL, &demo->depth.image);
10954e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
10964e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1097481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    vkGetImageMemoryRequirements(demo->device, demo->depth.image, &mem_reqs);
1098c109827920fd0991102d4979728eee74b6ac15fbTony Barbour    assert(!err);
1099723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski
1100c1f5e4068eab0504d4b68f78f88c55312ef96328Chia-I Wu    demo->depth.mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1101e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->depth.mem_alloc.pNext = NULL;
1102e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->depth.mem_alloc.allocationSize = mem_reqs.size;
1103e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->depth.mem_alloc.memoryTypeIndex = 0;
1104e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak
1105481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
1106481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                       0, /* No requirements */
1107481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                       &demo->depth.mem_alloc.memoryTypeIndex);
110837a43a64af08599b5fe5429c6c331f42f765fca9Courtney Goeltzenleuchter    assert(pass);
11094e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
11102318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    /* allocate memory */
1111481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkAllocateMemory(demo->device, &demo->depth.mem_alloc, NULL,
1112481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                           &demo->depth.mem);
11132318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
11142318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski
11152318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    /* bind memory */
1116481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err =
1117481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        vkBindImageMemory(demo->device, demo->depth.image, demo->depth.mem, 0);
11182318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
11194e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
11204e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    /* create image view */
11214e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    view.image = demo->depth.image;
112269f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    err = vkCreateImageView(demo->device, &view, NULL, &demo->depth.view);
11234e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
11244e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
11254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1126a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour/* Load a ppm file into memory */
112740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchterbool loadTexture(const char *filename, uint8_t *rgba_data,
1128481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 VkSubresourceLayout *layout, int32_t *width, int32_t *height) {
112971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#ifdef __ANDROID__
113071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#include <lunarg.ppm.h>
113171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    char *cPtr;
1132788a43f8e47fb32cf12aef25c5eab274a016aef3Mark Lobodzinski    cPtr = (char*)lunarg_ppm;
1133788a43f8e47fb32cf12aef25c5eab274a016aef3Mark Lobodzinski    if ((unsigned char*)cPtr >= (lunarg_ppm + lunarg_ppm_len) || strncmp(cPtr, "P6\n", 3)) {
113471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        return false;
113571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    }
113671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    while(strncmp(cPtr++, "\n", 1));
11373d20e26455a6f01b405373ebc6991be78b94fd1cAlexandre BACQUART    sscanf(cPtr, "%u %u", width, height);
113871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    if (rgba_data == NULL) {
113971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        return true;
114071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    }
114171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    while(strncmp(cPtr++, "\n", 1));
1142788a43f8e47fb32cf12aef25c5eab274a016aef3Mark Lobodzinski    if ((unsigned char*)cPtr >= (lunarg_ppm + lunarg_ppm_len) || strncmp(cPtr, "255\n", 4)) {
114371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        return false;
114471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    }
114571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    while(strncmp(cPtr++, "\n", 1));
114671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
114771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    for (int y = 0; y < *height; y++) {
114871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        uint8_t *rowPtr = rgba_data;
114971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        for (int x = 0; x < *width; x++) {
115071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            memcpy(rowPtr, cPtr, 3);
115171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            rowPtr[3] = 255; /* Alpha of 1 */
115271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            rowPtr += 4;
115371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            cPtr += 3;
115471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        }
115571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        rgba_data += layout->rowPitch;
115671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    }
115771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
115871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    return true;
115971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#else
1160481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    FILE *fPtr = fopen(filename, "rb");
1161e92af7e35e235faf650de0ffd413aa2e8417fd2dCourtney Goeltzenleuchter    char header[256], *cPtr, *tmp;
11621722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
1163a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    if (!fPtr)
1164a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        return false;
11651722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
1166a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    cPtr = fgets(header, 256, fPtr); // P6
116785180252441dad59e6967261a0a744af29e87968Mike Stroyan    if (cPtr == NULL || strncmp(header, "P6\n", 3)) {
116885180252441dad59e6967261a0a744af29e87968Mike Stroyan        fclose(fPtr);
1169a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        return false;
117085180252441dad59e6967261a0a744af29e87968Mike Stroyan    }
1171a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour
1172a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    do {
1173a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        cPtr = fgets(header, 256, fPtr);
117485180252441dad59e6967261a0a744af29e87968Mike Stroyan        if (cPtr == NULL) {
117585180252441dad59e6967261a0a744af29e87968Mike Stroyan            fclose(fPtr);
1176a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour            return false;
117785180252441dad59e6967261a0a744af29e87968Mike Stroyan        }
1178481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    } while (!strncmp(header, "#", 1));
1179a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour
11803d20e26455a6f01b405373ebc6991be78b94fd1cAlexandre BACQUART    sscanf(header, "%u %u", width, height);
118185180252441dad59e6967261a0a744af29e87968Mike Stroyan    if (rgba_data == NULL) {
118285180252441dad59e6967261a0a744af29e87968Mike Stroyan        fclose(fPtr);
1183a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        return true;
118485180252441dad59e6967261a0a744af29e87968Mike Stroyan    }
1185e92af7e35e235faf650de0ffd413aa2e8417fd2dCourtney Goeltzenleuchter    tmp = fgets(header, 256, fPtr); // Format
1186481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    (void)tmp;
118785180252441dad59e6967261a0a744af29e87968Mike Stroyan    if (cPtr == NULL || strncmp(header, "255\n", 3)) {
118885180252441dad59e6967261a0a744af29e87968Mike Stroyan        fclose(fPtr);
1189a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        return false;
119085180252441dad59e6967261a0a744af29e87968Mike Stroyan    }
11911722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
1192481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    for (int y = 0; y < *height; y++) {
1193a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        uint8_t *rowPtr = rgba_data;
1194481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        for (int x = 0; x < *width; x++) {
1195e92af7e35e235faf650de0ffd413aa2e8417fd2dCourtney Goeltzenleuchter            size_t s = fread(rowPtr, 3, 1, fPtr);
1196481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (void)s;
1197a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour            rowPtr[3] = 255; /* Alpha of 1 */
1198a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour            rowPtr += 4;
1199a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        }
1200a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        rgba_data += layout->rowPitch;
1201a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    }
1202a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    fclose(fPtr);
120385180252441dad59e6967261a0a744af29e87968Mike Stroyan    return true;
120471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
12051722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter}
12061722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
1207481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_texture_image(struct demo *demo, const char *filename,
1208bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter                                       struct texture_object *tex_obj,
1209382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter                                       VkImageTiling tiling,
1210cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter                                       VkImageUsageFlags usage,
1211481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                       VkFlags required_props) {
1212de24a6fa4333020ee03b8024b4c1d12196ade31fMike Stroyan    const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM;
1213e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    int32_t tex_width;
1214e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    int32_t tex_height;
121522a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
121637a43a64af08599b5fe5429c6c331f42f765fca9Courtney Goeltzenleuchter    bool U_ASSERT_ONLY pass;
121740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1218481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    if (!loadTexture(filename, NULL, NULL, &tex_width, &tex_height)) {
121971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        ERR_EXIT("Failed to load textures", "Load Texture Failure");
122061e773861568e3cadefba8effeb4e7e12e36e6ddDavid Pinedo    }
122140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1222bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    tex_obj->tex_width = tex_width;
1223bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    tex_obj->tex_height = tex_height;
122440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1225382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkImageCreateInfo image_create_info = {
12269cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
122740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .pNext = NULL,
12288205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour        .imageType = VK_IMAGE_TYPE_2D,
122940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .format = tex_format,
1230481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .extent = {tex_width, tex_height, 1},
123140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .mipLevels = 1,
12322ebc234580f41270585dfbbe2925358dd41b125eCourtney Goeltzenleuchter        .arrayLayers = 1,
12333138d6a7fafb314644a22a854267258769c6d6a0Chia-I Wu        .samples = VK_SAMPLE_COUNT_1_BIT,
123440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .tiling = tiling,
1235cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter        .usage = usage,
123640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .flags = 0,
1237866af6ca38e3bcde21ea9235de1b7a044279e6b8Tobin Ehlis        .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
123840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    };
123940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
12402318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    VkMemoryRequirements mem_reqs;
124140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1242481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err =
1243481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        vkCreateImage(demo->device, &image_create_info, NULL, &tex_obj->image);
124440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    assert(!err);
124540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
124601d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetImageMemoryRequirements(demo->device, tex_obj->image, &mem_reqs);
124740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1248c1f5e4068eab0504d4b68f78f88c55312ef96328Chia-I Wu    tex_obj->mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1249e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    tex_obj->mem_alloc.pNext = NULL;
1250e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    tex_obj->mem_alloc.allocationSize = mem_reqs.size;
1251e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    tex_obj->mem_alloc.memoryTypeIndex = 0;
12522318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski
1253481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
1254481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                       required_props,
1255481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                       &tex_obj->mem_alloc.memoryTypeIndex);
125637a43a64af08599b5fe5429c6c331f42f765fca9Courtney Goeltzenleuchter    assert(pass);
1257723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski
12582318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    /* allocate memory */
12591f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    err = vkAllocateMemory(demo->device, &tex_obj->mem_alloc, NULL,
1260481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                           &(tex_obj->mem));
12612318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
126240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
12632318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    /* bind memory */
1264481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkBindImageMemory(demo->device, tex_obj->image, tex_obj->mem, 0);
12652318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
126640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1267f1eceb98219334d5540106fd024d6aee9e397802Tony Barbour    if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1268382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        const VkImageSubresource subres = {
1269195c9e1571bc33a143af6a1adf7f6083a3b41f8dChia-I Wu            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
127040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            .mipLevel = 0,
12713dee8087999562e0637326175a3cf6cab858158eCourtney Goeltzenleuchter            .arrayLayer = 0,
127240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        };
1273382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkSubresourceLayout layout;
127440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        void *data;
127540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1276481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        vkGetImageSubresourceLayout(demo->device, tex_obj->image, &subres,
1277481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                    &layout);
127840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1279481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        err = vkMapMemory(demo->device, tex_obj->mem, 0,
1280481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                          tex_obj->mem_alloc.allocationSize, 0, &data);
128140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        assert(!err);
128240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
128340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        if (!loadTexture(filename, data, &layout, &tex_width, &tex_height)) {
128440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            fprintf(stderr, "Error loading texture: %s\n", filename);
128540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        }
128640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
128767b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski        vkUnmapMemory(demo->device, tex_obj->mem);
128840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    }
1289bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
12909cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
129140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter}
129240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1293481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_destroy_texture_image(struct demo *demo,
1294481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                       struct texture_object *tex_objs) {
129540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    /* clean up staging resources */
129669f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkFreeMemory(demo->device, tex_objs->mem, NULL);
129769f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyImage(demo->device, tex_objs->image, NULL);
129840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter}
129940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1300481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_textures(struct demo *demo) {
13018205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM;
1302382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkFormatProperties props;
1303e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t i;
13044e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
130501d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceFormatProperties(demo->gpu, tex_format, &props);
130640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
13074e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
130801d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter        VkResult U_ASSERT_ONLY err;
130940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1310481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if ((props.linearTilingFeatures &
1311481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz             VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) &&
1312481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            !demo->use_staging_buffer) {
131340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            /* Device can texture using linear textures */
131447bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour            demo_prepare_texture_image(
131547bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                demo, tex_files[i], &demo->textures[i], VK_IMAGE_TILING_LINEAR,
131647bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                VK_IMAGE_USAGE_SAMPLED_BIT,
131747bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
131847bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
1319df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour            // Nothing in the pipeline needs to be complete to start, and don't allow fragment
1320df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour            // shader to run until layout transition completes
1321df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour            demo_set_image_layout(demo, demo->textures[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
1322df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_IMAGE_LAYOUT_PREINITIALIZED, demo->textures[i].imageLayout,
1323df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_ACCESS_HOST_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1324df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
1325481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        } else if (props.optimalTilingFeatures &
1326481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                   VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
132740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            /* Must use staging buffer to copy linear texture to optimized */
1328bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            struct texture_object staging_texture;
132940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
133040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            memset(&staging_texture, 0, sizeof(staging_texture));
133147bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour            demo_prepare_texture_image(
133247bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                demo, tex_files[i], &staging_texture, VK_IMAGE_TILING_LINEAR,
133347bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
133447bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
133547bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
133640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1337481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            demo_prepare_texture_image(
1338481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                demo, tex_files[i], &demo->textures[i], VK_IMAGE_TILING_OPTIMAL,
1339481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
1340481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
134140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1342bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            demo_set_image_layout(demo, staging_texture.image,
1343481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  VK_IMAGE_ASPECT_COLOR_BIT,
1344df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_IMAGE_LAYOUT_PREINITIALIZED,
1345866af6ca38e3bcde21ea9235de1b7a044279e6b8Tobin Ehlis                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1346df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_ACCESS_HOST_WRITE_BIT,
1347df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1348df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_PIPELINE_STAGE_TRANSFER_BIT);
134940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1350bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            demo_set_image_layout(demo, demo->textures[i].image,
1351481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  VK_IMAGE_ASPECT_COLOR_BIT,
1352df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_IMAGE_LAYOUT_PREINITIALIZED,
1353866af6ca38e3bcde21ea9235de1b7a044279e6b8Tobin Ehlis                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1354df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_ACCESS_HOST_WRITE_BIT,
1355df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1356df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_PIPELINE_STAGE_TRANSFER_BIT);
135740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1358382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter            VkImageCopy copy_region = {
1359481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
1360481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                .srcOffset = {0, 0, 0},
1361481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
1362481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                .dstOffset = {0, 0, 0},
1363481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                .extent = {staging_texture.tex_width,
1364481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                           staging_texture.tex_height, 1},
136540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            };
1366481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            vkCmdCopyImage(
1367481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                demo->cmd, staging_texture.image,
1368481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, demo->textures[i].image,
1369481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_region);
137040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1371bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            demo_set_image_layout(demo, demo->textures[i].image,
1372481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  VK_IMAGE_ASPECT_COLOR_BIT,
1373481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1374866af6ca38e3bcde21ea9235de1b7a044279e6b8Tobin Ehlis                                  demo->textures[i].imageLayout,
1375df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_ACCESS_TRANSFER_WRITE_BIT,
1376df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_PIPELINE_STAGE_TRANSFER_BIT,
1377df48463191cc6b75a02c1a3c2d505977e992e370Tony Barbour                                  VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
137840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1379bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            demo_flush_init_cmd(demo);
138040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1381876629f092977a81cae0f2d483c8b6838bdd54c4Courtney Goeltzenleuchter            demo_destroy_texture_image(demo, &staging_texture);
138240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        } else {
1383de24a6fa4333020ee03b8024b4c1d12196ade31fMike Stroyan            /* Can't support VK_FORMAT_R8G8B8A8_UNORM !? */
1384de24a6fa4333020ee03b8024b4c1d12196ade31fMike Stroyan            assert(!"No support for R8G8B8A8_UNORM as texture image format");
138540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        }
138640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1387382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        const VkSamplerCreateInfo sampler = {
13889cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
13894e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .pNext = NULL,
13903603b0843e868bd46b11eaf1d64ccdb260599609Chia-I Wu            .magFilter = VK_FILTER_NEAREST,
13913603b0843e868bd46b11eaf1d64ccdb260599609Chia-I Wu            .minFilter = VK_FILTER_NEAREST,
1392a4ae48bfd6f2e2a80e1f92e054a007cf90a4e218Jon Ashburn            .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
1393ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu            .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1394ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu            .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1395ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu            .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
13964e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .mipLodBias = 0.0f,
13970717ed5c31632fcc0f7fc1e553b1e67ca03df2abJon Ashburn            .anisotropyEnable = VK_FALSE,
139840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            .maxAnisotropy = 1,
13998205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour            .compareOp = VK_COMPARE_OP_NEVER,
14004e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .minLod = 0.0f,
14014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .maxLod = 0.0f,
14022c4e7c76b02d4ad0c09ff14bf9026dfcc0b9fa0cTony Barbour            .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
1403513acdfaef018860ab57d945d5df881e3d50c068Mark Lobodzinski            .unnormalizedCoordinates = VK_FALSE,
14044e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        };
14051722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
1406382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkImageViewCreateInfo view = {
14079cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
14084e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .pNext = NULL,
1409e420a33ff7bdcf67b8a487592af78a3ca2f29ee6Chia-I Wu            .image = VK_NULL_HANDLE,
14108205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour            .viewType = VK_IMAGE_VIEW_TYPE_2D,
141140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            .format = tex_format,
1412481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            .components =
1413481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                {
1414481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
1415481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A,
1416481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                },
1417481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
14181856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .flags = 0,
14194e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        };
1420a9ae38392fd4359242fda1d2961f8347dbe970f7Jon Ashburn
14214e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        /* create sampler */
142269f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        err = vkCreateSampler(demo->device, &sampler, NULL,
1423481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                              &demo->textures[i].sampler);
14244e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        assert(!err);
14254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
14264e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        /* create image view */
14274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        view.image = demo->textures[i].image;
142869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        err = vkCreateImageView(demo->device, &view, NULL,
1429481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                &demo->textures[i].view);
14304e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        assert(!err);
14314e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
14324e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
14334e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1434481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzvoid demo_prepare_cube_data_buffer(struct demo *demo) {
1435ddcb6192458d696a106f48eeb12fd0390a3ca63fCourtney Goeltzenleuchter    VkBufferCreateInfo buf_info;
14362318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    VkMemoryRequirements mem_reqs;
1437e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint8_t *pData;
1438e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    int i;
1439e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4 MVP, VP;
144022a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
144137a43a64af08599b5fe5429c6c331f42f765fca9Courtney Goeltzenleuchter    bool U_ASSERT_ONLY pass;
14429cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    struct vktexcube_vs_uniform data;
1443e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1444e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4_mul(VP, demo->projection_matrix, demo->view_matrix);
1445e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4_mul(MVP, VP, demo->model_matrix);
1446e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    memcpy(data.mvp, MVP, sizeof(MVP));
1447481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    //    dumpMatrix("MVP", MVP);
1448e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1449481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    for (i = 0; i < 12 * 3; i++) {
1450481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        data.position[i][0] = g_vertex_buffer_data[i * 3];
1451481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        data.position[i][1] = g_vertex_buffer_data[i * 3 + 1];
1452481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        data.position[i][2] = g_vertex_buffer_data[i * 3 + 2];
1453e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.position[i][3] = 1.0f;
1454481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        data.attr[i][0] = g_uv_buffer_data[2 * i];
1455481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        data.attr[i][1] = g_uv_buffer_data[2 * i + 1];
1456e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.attr[i][2] = 0;
1457e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.attr[i][3] = 0;
1458e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    }
1459e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1460714df45f6733792374ad4fcb6e0fef3b47fbeb89Chia-I Wu    memset(&buf_info, 0, sizeof(buf_info));
14619cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1462ad870818fc61ad8dccc8af2c4992f15efa9c4c7fCourtney Goeltzenleuchter    buf_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
14638604939f334616555e35ef5771bd61e4a9160c88Cody Northrop    buf_info.size = sizeof(data);
1464481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err =
1465481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        vkCreateBuffer(demo->device, &buf_info, NULL, &demo->uniform_data.buf);
1466714df45f6733792374ad4fcb6e0fef3b47fbeb89Chia-I Wu    assert(!err);
1467714df45f6733792374ad4fcb6e0fef3b47fbeb89Chia-I Wu
1468481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    vkGetBufferMemoryRequirements(demo->device, demo->uniform_data.buf,
1469481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  &mem_reqs);
1470e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1471c1f5e4068eab0504d4b68f78f88c55312ef96328Chia-I Wu    demo->uniform_data.mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1472e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->uniform_data.mem_alloc.pNext = NULL;
1473e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->uniform_data.mem_alloc.allocationSize = mem_reqs.size;
1474e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->uniform_data.mem_alloc.memoryTypeIndex = 0;
1475e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak
1476481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pass = memory_type_from_properties(
147747bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour        demo, mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
147847bb7bcca3e51dd2d74b534e53a0003f1a6b863bTony Barbour                                           VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
1479481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        &demo->uniform_data.mem_alloc.memoryTypeIndex);
148037a43a64af08599b5fe5429c6c331f42f765fca9Courtney Goeltzenleuchter    assert(pass);
1481e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1482481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkAllocateMemory(demo->device, &demo->uniform_data.mem_alloc, NULL,
1483481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                           &(demo->uniform_data.mem));
14842318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
1485e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1486481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkMapMemory(demo->device, demo->uniform_data.mem, 0,
1487481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                      demo->uniform_data.mem_alloc.allocationSize, 0,
1488481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                      (void **)&pData);
14892318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
1490e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
14912318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    memcpy(pData, &data, sizeof data);
1492c6ae13d46c9c8a6651bf3809e2a12c69dda8a428Jon Ashburn
149367b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski    vkUnmapMemory(demo->device, demo->uniform_data.mem);
14942318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski
1495481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkBindBufferMemory(demo->device, demo->uniform_data.buf,
1496481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                             demo->uniform_data.mem, 0);
14972318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
1498714df45f6733792374ad4fcb6e0fef3b47fbeb89Chia-I Wu
149934aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter    demo->uniform_data.buffer_info.buffer = demo->uniform_data.buf;
150034aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter    demo->uniform_data.buffer_info.offset = 0;
150134aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter    demo->uniform_data.buffer_info.range = sizeof(data);
1502e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter}
1503e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1504481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_descriptor_layout(struct demo *demo) {
1505382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkDescriptorSetLayoutBinding layout_bindings[2] = {
1506481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            [0] =
1507481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                {
1508481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .binding = 0,
1509481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1510481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .descriptorCount = 1,
1511481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
1512481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .pImmutableSamplers = NULL,
1513481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                },
1514481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            [1] =
1515481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                {
1516481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .binding = 1,
1517481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1518481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .descriptorCount = DEMO_TEXTURE_COUNT,
1519481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
1520481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .pImmutableSamplers = NULL,
1521481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                },
1522f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    };
1523382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkDescriptorSetLayoutCreateInfo descriptor_layout = {
15249cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1525fc9d913ebe3461e4374d4264dfd5c9bad99df63dChia-I Wu        .pNext = NULL,
1526763a749795bb4827efbbf19cbc87b959511496ddChia-I Wu        .bindingCount = 2,
1527adb61352bcf8a9c9080c562e7bca5d43230dd316Jon Ashburn        .pBindings = layout_bindings,
15286e68a893f0364c1157789d260cdf84365cb58cf7Chia-I Wu    };
152922a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
15304e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1531481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkCreateDescriptorSetLayout(demo->device, &descriptor_layout, NULL,
1532481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                      &demo->desc_layout);
15337732cb2481328c1e94a0f308b315cc48df530dc2Chia-I Wu    assert(!err);
15347732cb2481328c1e94a0f308b315cc48df530dc2Chia-I Wu
1535556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
1536481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1537481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .pNext = NULL,
1538763a749795bb4827efbbf19cbc87b959511496ddChia-I Wu        .setLayoutCount = 1,
1539481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .pSetLayouts = &demo->desc_layout,
1540556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    };
1541556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski
1542481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkCreatePipelineLayout(demo->device, &pPipelineLayoutCreateInfo, NULL,
1543556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski                                 &demo->pipeline_layout);
15444e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
15454e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
15464e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1547481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_render_pass(struct demo *demo) {
1548746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour    // The initial layout for the color and depth attachments will be LAYOUT_UNDEFINED
1549746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour    // because at the start of the renderpass, we don't care about their contents.
1550746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour    // At the start of the subpass, the color attachment's layout will be transitioned
1551746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour    // to LAYOUT_COLOR_ATTACHMENT_OPTIMAL and the depth stencil attachment's layout
1552746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour    // will be transitioned to LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL.  At the end of
1553746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour    // the renderpass, the color attachment's layout will be transitioned to
1554746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour    // LAYOUT_PRESENT_SRC_KHR to be ready to present.  This is all done as part of
1555746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour    // the renderpass, no barriers are necessary.
1556c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkAttachmentDescription attachments[2] = {
1557481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            [0] =
1558481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                {
1559481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .format = demo->format,
1560481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .samples = VK_SAMPLE_COUNT_1_BIT,
1561481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
1562481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
1563481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1564481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1565746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour                 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1566a5b04f44d06af86b917f3866f8e05404ff3aa052Tony Barbour                 .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
1567481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                },
1568481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            [1] =
1569481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                {
1570481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .format = demo->depth.format,
1571481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .samples = VK_SAMPLE_COUNT_1_BIT,
1572481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
1573481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1574481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1575481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1576481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .initialLayout =
1577746da8ab2a40b2ce6db5a7747f786c64ee23f68bTony Barbour                     VK_IMAGE_LAYOUT_UNDEFINED,
1578481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .finalLayout =
1579481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1580481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                },
1581c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    };
1582c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkAttachmentReference color_reference = {
1583481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1584c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    };
1585ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu    const VkAttachmentReference depth_reference = {
1586ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu        .attachment = 1,
1587ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu        .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1588ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu    };
1589c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkSubpassDescription subpass = {
1590c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
1591c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .flags = 0,
1592763a749795bb4827efbbf19cbc87b959511496ddChia-I Wu        .inputAttachmentCount = 0,
15936de6b0b93a1704d673c42fea1f0e3e4e720a14ffCody Northrop        .pInputAttachments = NULL,
1594763a749795bb4827efbbf19cbc87b959511496ddChia-I Wu        .colorAttachmentCount = 1,
15956de6b0b93a1704d673c42fea1f0e3e4e720a14ffCody Northrop        .pColorAttachments = &color_reference,
15966de6b0b93a1704d673c42fea1f0e3e4e720a14ffCody Northrop        .pResolveAttachments = NULL,
1597ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu        .pDepthStencilAttachment = &depth_reference,
1598763a749795bb4827efbbf19cbc87b959511496ddChia-I Wu        .preserveAttachmentCount = 0,
15996de6b0b93a1704d673c42fea1f0e3e4e720a14ffCody Northrop        .pPreserveAttachments = NULL,
160076cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    };
160176cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    const VkRenderPassCreateInfo rp_info = {
160276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
160376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        .pNext = NULL,
1604c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .attachmentCount = 2,
1605c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pAttachments = attachments,
1606c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .subpassCount = 1,
1607c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pSubpasses = &subpass,
1608c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .dependencyCount = 0,
1609c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pDependencies = NULL,
161076cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    };
1611c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    VkResult U_ASSERT_ONLY err;
161276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
161369f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    err = vkCreateRenderPass(demo->device, &rp_info, NULL, &demo->render_pass);
161476cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    assert(!err);
161576cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu}
161676cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
161771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine//TODO: Merge shader reading
161871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#ifndef __ANDROID__
1619481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic VkShaderModule
1620481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzdemo_prepare_shader_module(struct demo *demo, const void *code, size_t size) {
1621062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu    VkShaderModule module;
16220b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    VkShaderModuleCreateInfo moduleCreateInfo;
1623e92af7e35e235faf650de0ffd413aa2e8417fd2dCourtney Goeltzenleuchter    VkResult U_ASSERT_ONLY err;
16244e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
16250b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
16260b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    moduleCreateInfo.pNext = NULL;
16274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
16288961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    moduleCreateInfo.codeSize = size;
16298961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    moduleCreateInfo.pCode = code;
16308961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    moduleCreateInfo.flags = 0;
16318961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    err = vkCreateShaderModule(demo->device, &moduleCreateInfo, NULL, &module);
16328961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    assert(!err);
1633062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu
1634062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu    return module;
16354e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
16364e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1637481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzchar *demo_read_spv(const char *filename, size_t *psize) {
16387e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    long int size;
1639a938abb9d45b990819e37f09c3d107a461114c8eTony Barbour    size_t U_ASSERT_ONLY retval;
16407e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    void *shader_code;
16417e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
16427e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    FILE *fp = fopen(filename, "rb");
1643481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    if (!fp)
1644481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        return NULL;
16457e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
16467e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    fseek(fp, 0L, SEEK_END);
16477e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    size = ftell(fp);
16487e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
16497e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    fseek(fp, 0L, SEEK_SET);
16507e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
16517e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    shader_code = malloc(size);
165222a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    retval = fread(shader_code, size, 1, fp);
165322a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    assert(retval == 1);
16547e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
16557e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    *psize = size;
16567e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
165785180252441dad59e6967261a0a744af29e87968Mike Stroyan    fclose(fp);
16587e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    return shader_code;
16597e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter}
166071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
16617e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
1662481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic VkShaderModule demo_prepare_vs(struct demo *demo) {
166371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#ifdef __ANDROID__
166471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    VkShaderModuleCreateInfo sh_info = {};
166571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    sh_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
166671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
166771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#include "cube.vert.h"
166871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    sh_info.codeSize = sizeof(cube_vert);
166971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    sh_info.pCode = cube_vert;
167071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    VkResult U_ASSERT_ONLY err = vkCreateShaderModule(demo->device, &sh_info, NULL, &demo->vert_shader_module);
167171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    assert(!err);
167271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#else
16738961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    void *vertShaderCode;
16748961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    size_t size;
16757e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
16768961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    vertShaderCode = demo_read_spv("cube-vert.spv", &size);
16778961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter
1678481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    demo->vert_shader_module =
1679481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo_prepare_shader_module(demo, vertShaderCode, size);
16808961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter
16818961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    free(vertShaderCode);
168271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
1683062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu
1684062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu    return demo->vert_shader_module;
16854e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
16864e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1687481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic VkShaderModule demo_prepare_fs(struct demo *demo) {
168871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#ifdef __ANDROID__
168971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    VkShaderModuleCreateInfo sh_info = {};
169071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    sh_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
169171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
169271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#include "cube.frag.h"
169371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    sh_info.codeSize = sizeof(cube_frag);
169471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    sh_info.pCode = cube_frag;
169571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    VkResult U_ASSERT_ONLY err = vkCreateShaderModule(demo->device, &sh_info, NULL, &demo->frag_shader_module);
169671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    assert(!err);
169771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#else
16988961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    void *fragShaderCode;
16998961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    size_t size;
17007e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
17018961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    fragShaderCode = demo_read_spv("cube-frag.spv", &size);
17027e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
1703481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    demo->frag_shader_module =
1704481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo_prepare_shader_module(demo, fragShaderCode, size);
17058961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter
17068961c984fc7337f83d3c1b7c720a2f37c8d57afdCourtney Goeltzenleuchter    free(fragShaderCode);
170771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
1708062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu
1709062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu    return demo->frag_shader_module;
17104e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
17114e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1712481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_pipeline(struct demo *demo) {
1713382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkGraphicsPipelineCreateInfo pipeline;
17140d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    VkPipelineCacheCreateInfo pipelineCache;
1715481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkPipelineVertexInputStateCreateInfo vi;
1716e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineInputAssemblyStateCreateInfo ia;
1717481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkPipelineRasterizationStateCreateInfo rs;
1718481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkPipelineColorBlendStateCreateInfo cb;
1719481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkPipelineDepthStencilStateCreateInfo ds;
1720481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkPipelineViewportStateCreateInfo vp;
1721481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkPipelineMultisampleStateCreateInfo ms;
1722481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE];
1723481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkPipelineDynamicStateCreateInfo dynamicState;
172422a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
17254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1726811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    memset(dynamicStateEnables, 0, sizeof dynamicStateEnables);
1727811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    memset(&dynamicState, 0, sizeof dynamicState);
1728811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1729811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    dynamicState.pDynamicStates = dynamicStateEnables;
1730811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell
17314e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(&pipeline, 0, sizeof(pipeline));
17329cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1733556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    pipeline.layout = demo->pipeline_layout;
17344e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1735009e865a05e0c50620497a382124cd19129eb522Jason Ekstrand    memset(&vi, 0, sizeof(vi));
1736009e865a05e0c50620497a382124cd19129eb522Jason Ekstrand    vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1737009e865a05e0c50620497a382124cd19129eb522Jason Ekstrand
17384e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(&ia, 0, sizeof(ia));
1739e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
17408205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
17414e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
17424e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(&rs, 0, sizeof(rs));
1743c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu    rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1744c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu    rs.polygonMode = VK_POLYGON_MODE_FILL;
1745ce532f7eb8ce347a0bc2c7d848d5017fa31d2533Chia-I Wu    rs.cullMode = VK_CULL_MODE_BACK_BIT;
17461f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
1747c0f9fa7f4a5e44878c491476e2ece1bacd3223c2Courtney Goeltzenleuchter    rs.depthClampEnable = VK_FALSE;
1748f5bd2253ff4114ac446f8eb820e78d56f711020fCody Northrop    rs.rasterizerDiscardEnable = VK_FALSE;
1749f5bd2253ff4114ac446f8eb820e78d56f711020fCody Northrop    rs.depthBiasEnable = VK_FALSE;
1750a27508babf63d50aea75883a3702979193c23683Mark Young    rs.lineWidth = 1.0f;
17514e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
17524e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(&cb, 0, sizeof(cb));
1753e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1754e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineColorBlendAttachmentState att_state[1];
1755fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    memset(att_state, 0, sizeof(att_state));
1756c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu    att_state[0].colorWriteMask = 0xf;
17579cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    att_state[0].blendEnable = VK_FALSE;
1758fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    cb.attachmentCount = 1;
1759fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    cb.pAttachments = att_state;
1760fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour
1761fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    memset(&vp, 0, sizeof(vp));
1762e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
17638205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    vp.viewportCount = 1;
1764481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    dynamicStateEnables[dynamicState.dynamicStateCount++] =
1765481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        VK_DYNAMIC_STATE_VIEWPORT;
1766811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    vp.scissorCount = 1;
1767481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    dynamicStateEnables[dynamicState.dynamicStateCount++] =
1768481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        VK_DYNAMIC_STATE_SCISSOR;
1769fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour
1770fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    memset(&ds, 0, sizeof(ds));
1771e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
17729cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    ds.depthTestEnable = VK_TRUE;
17739cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    ds.depthWriteEnable = VK_TRUE;
17741f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
1775e4bc6948ada94c7fe0b35a89dbc2542ec4f791a2Cody Northrop    ds.depthBoundsTestEnable = VK_FALSE;
1776c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu    ds.back.failOp = VK_STENCIL_OP_KEEP;
1777c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu    ds.back.passOp = VK_STENCIL_OP_KEEP;
1778c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu    ds.back.compareOp = VK_COMPARE_OP_ALWAYS;
17799cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    ds.stencilTestEnable = VK_FALSE;
1780fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    ds.front = ds.back;
17814e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1782fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    memset(&ms, 0, sizeof(ms));
1783e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1784e9825b7a5f81e02cdb76851ed18c8ce404cb3deeCody Northrop    ms.pSampleMask = NULL;
17853138d6a7fafb314644a22a854267258769c6d6a0Chia-I Wu    ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
17864e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
17870e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    // Two stages: vs and fs
17880e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    pipeline.stageCount = 2;
17890e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    VkPipelineShaderStageCreateInfo shaderStages[2];
17900e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    memset(&shaderStages, 0, 2 * sizeof(VkPipelineShaderStageCreateInfo));
17910e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski
1792481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1793481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
1794062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu    shaderStages[0].module = demo_prepare_vs(demo);
1795481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    shaderStages[0].pName = "main";
17960e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski
1797481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1798481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
1799062ad15850af42c5e45ec9dfb961ff243a6e8923Chia-I Wu    shaderStages[1].module = demo_prepare_fs(demo);
1800481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    shaderStages[1].pName = "main";
18010e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski
18020d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    memset(&pipelineCache, 0, sizeof(pipelineCache));
18030d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
18044e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1805481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkCreatePipelineCache(demo->device, &pipelineCache, NULL,
1806481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                &demo->pipelineCache);
18070d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    assert(!err);
1808e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour
1809481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.pVertexInputState = &vi;
1810e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pInputAssemblyState = &ia;
1811481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.pRasterizationState = &rs;
1812481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.pColorBlendState = &cb;
1813481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.pMultisampleState = &ms;
1814481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.pViewportState = &vp;
1815481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.pDepthStencilState = &ds;
1816481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.pStages = shaderStages;
1817481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.renderPass = demo->render_pass;
1818481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    pipeline.pDynamicState = &dynamicState;
1819e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour
182014eb5eac6d11950c8cc9fa98f075fabc35bbc00fCourtney Goeltzenleuchter    pipeline.renderPass = demo->render_pass;
182114eb5eac6d11950c8cc9fa98f075fabc35bbc00fCourtney Goeltzenleuchter
1822481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1,
1823481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                    &pipeline, NULL, &demo->pipeline);
18244e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
18254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
182669f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyShaderModule(demo->device, demo->frag_shader_module, NULL);
182769f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyShaderModule(demo->device, demo->vert_shader_module, NULL);
18284e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
18294e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1830481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_descriptor_pool(struct demo *demo) {
1831c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu    const VkDescriptorPoolSize type_counts[2] = {
1832481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            [0] =
1833481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                {
1834481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1835481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .descriptorCount = 1,
1836481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                },
1837481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            [1] =
1838481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                {
1839481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1840481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 .descriptorCount = DEMO_TEXTURE_COUNT,
1841481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                },
1842f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    };
1843382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkDescriptorPoolCreateInfo descriptor_pool = {
18449cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1845f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu        .pNext = NULL,
1846d9e966aac83c28e7f6ac6535f695c9a7c06f667dCourtney Goeltzenleuchter        .maxSets = 1,
1847c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu        .poolSizeCount = 2,
1848c51b121913d6f21ccefb3f7595178d3c87e11de4Chia-I Wu        .pPoolSizes = type_counts,
1849f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    };
185022a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
1851f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
1852481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkCreateDescriptorPool(demo->device, &descriptor_pool, NULL,
1853481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                 &demo->desc_pool);
1854f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    assert(!err);
1855f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu}
1856f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
1857481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_descriptor_set(struct demo *demo) {
185834aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter    VkDescriptorImageInfo tex_descs[DEMO_TEXTURE_COUNT];
18598cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    VkWriteDescriptorSet writes[2];
186022a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
1861e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t i;
1862f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
18631f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    VkDescriptorSetAllocateInfo alloc_info = {
1864c1f5e4068eab0504d4b68f78f88c55312ef96328Chia-I Wu        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1865831c183417705004ea225726d450b7259e7384c7Courtney Goeltzenleuchter        .pNext = NULL,
1866831c183417705004ea225726d450b7259e7384c7Courtney Goeltzenleuchter        .descriptorPool = demo->desc_pool,
1867a4ae48bfd6f2e2a80e1f92e054a007cf90a4e218Jon Ashburn        .descriptorSetCount = 1,
1868481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .pSetLayouts = &demo->desc_layout};
18691f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    err = vkAllocateDescriptorSets(demo->device, &alloc_info, &demo->desc_set);
1870c8aa4a5cf5902e22b99d0107164ac43c6c7c4e5dCody Northrop    assert(!err);
1871f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
18728cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    memset(&tex_descs, 0, sizeof(tex_descs));
18738cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
187434aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter        tex_descs[i].sampler = demo->textures[i].sampler;
187534aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter        tex_descs[i].imageView = demo->textures[i].view;
187634aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter        tex_descs[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
18778cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    }
18788cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu
18798cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    memset(&writes, 0, sizeof(writes));
18808cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu
18818cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
18821f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    writes[0].dstSet = demo->desc_set;
1883763a749795bb4827efbbf19cbc87b959511496ddChia-I Wu    writes[0].descriptorCount = 1;
18848cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
188534aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter    writes[0].pBufferInfo = &demo->uniform_data.buffer_info;
18868cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu
18878cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
18881f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    writes[1].dstSet = demo->desc_set;
18891f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    writes[1].dstBinding = 1;
1890763a749795bb4827efbbf19cbc87b959511496ddChia-I Wu    writes[1].descriptorCount = DEMO_TEXTURE_COUNT;
18918cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
189234aa5c8bb02340240969d574d69dad0f68dbcb42Courtney Goeltzenleuchter    writes[1].pImageInfo = tex_descs;
18938cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu
189467b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski    vkUpdateDescriptorSets(demo->device, 2, writes, 0, NULL);
1895f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu}
1896f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
1897481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare_framebuffers(struct demo *demo) {
18981856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter    VkImageView attachments[2];
1899f110c6ea46391b57f30588bbda17e7183e8c5bd7Cody Northrop    attachments[1] = demo->depth.view;
1900f110c6ea46391b57f30588bbda17e7183e8c5bd7Cody Northrop
190176cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    const VkFramebufferCreateInfo fb_info = {
1902481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
1903481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .pNext = NULL,
1904481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .renderPass = demo->render_pass,
1905481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .attachmentCount = 2,
1906481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .pAttachments = attachments,
1907481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .width = demo->width,
1908481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .height = demo->height,
1909481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .layers = 1,
191076cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    };
191176cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    VkResult U_ASSERT_ONLY err;
191276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    uint32_t i;
191376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
1914481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    demo->framebuffers = (VkFramebuffer *)malloc(demo->swapchainImageCount *
1915481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                                 sizeof(VkFramebuffer));
19165aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    assert(demo->framebuffers);
19175aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour
19185aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    for (i = 0; i < demo->swapchainImageCount; i++) {
1919f110c6ea46391b57f30588bbda17e7183e8c5bd7Cody Northrop        attachments[0] = demo->buffers[i].view;
1920481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        err = vkCreateFramebuffer(demo->device, &fb_info, NULL,
1921481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  &demo->framebuffers[i]);
192276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        assert(!err);
192376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    }
192476cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu}
192576cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
1926481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_prepare(struct demo *demo) {
192718ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    VkResult U_ASSERT_ONLY err;
192818ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop
19291f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    const VkCommandPoolCreateInfo cmd_pool_info = {
19301f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu        .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
193118ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop        .pNext = NULL,
1932755151776f6b9a0ab34095b980819e4318a86529Tony Barbour        .queueFamilyIndex = demo->graphics_queue_family_index,
193318ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop        .flags = 0,
193418ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    };
1935481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkCreateCommandPool(demo->device, &cmd_pool_info, NULL,
1936481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                              &demo->cmd_pool);
193718ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    assert(!err);
193818ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop
19391f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu    const VkCommandBufferAllocateInfo cmd = {
1940c1f5e4068eab0504d4b68f78f88c55312ef96328Chia-I Wu        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
19414e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .pNext = NULL,
19421f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu        .commandPool = demo->cmd_pool,
19431f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu        .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1944a4ae48bfd6f2e2a80e1f92e054a007cf90a4e218Jon Ashburn        .commandBufferCount = 1,
19454e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
19463825f87dc62f910827b1b842213fc68b22302e23Tony Barbour    err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->cmd);
19473825f87dc62f910827b1b842213fc68b22302e23Tony Barbour    assert(!err);
19483825f87dc62f910827b1b842213fc68b22302e23Tony Barbour    VkCommandBufferBeginInfo cmd_buf_info = {
19493825f87dc62f910827b1b842213fc68b22302e23Tony Barbour        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
19503825f87dc62f910827b1b842213fc68b22302e23Tony Barbour        .pNext = NULL,
19513825f87dc62f910827b1b842213fc68b22302e23Tony Barbour        .flags = 0,
19523825f87dc62f910827b1b842213fc68b22302e23Tony Barbour        .pInheritanceInfo = NULL,
19533825f87dc62f910827b1b842213fc68b22302e23Tony Barbour    };
19543825f87dc62f910827b1b842213fc68b22302e23Tony Barbour    err = vkBeginCommandBuffer(demo->cmd, &cmd_buf_info);
19553825f87dc62f910827b1b842213fc68b22302e23Tony Barbour    assert(!err);
19564e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
19574e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare_buffers(demo);
19584e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare_depth(demo);
19594e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare_textures(demo);
19603eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo_prepare_cube_data_buffer(demo);
19614e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1962f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    demo_prepare_descriptor_layout(demo);
196376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    demo_prepare_render_pass(demo);
19644e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare_pipeline(demo);
19654e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1966338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
1967481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        err =
1968481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            vkAllocateCommandBuffers(demo->device, &cmd, &demo->buffers[i].cmd);
1969bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter        assert(!err);
1970bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter    }
1971f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
19721ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    if (demo->separate_present_queue) {
19731ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        const VkCommandPoolCreateInfo cmd_pool_info = {
19741ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
19751ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .pNext = NULL,
19761ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .queueFamilyIndex = demo->present_queue_family_index,
19771ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .flags = 0,
19781ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        };
19791ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        err = vkCreateCommandPool(demo->device, &cmd_pool_info, NULL,
19801ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour                                  &demo->present_cmd_pool);
19811ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        assert(!err);
19821ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        const VkCommandBufferAllocateInfo cmd = {
19831ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
19841ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .pNext = NULL,
19851ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .commandPool = demo->present_cmd_pool,
19861ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
19871ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            .commandBufferCount = 1,
19881ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        };
19891ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
19901ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            err = vkAllocateCommandBuffers(
19911ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour                demo->device, &cmd, &demo->buffers[i].graphics_to_present_cmd);
19921ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            assert(!err);
19931ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour            demo_build_image_ownership_cmd(demo, i);
19941ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        }
19951ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    }
19961ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
19978d24b3bada572c64ef4f86f782e1f5136976f31dChia-I Wu    demo_prepare_descriptor_pool(demo);
1998f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    demo_prepare_descriptor_set(demo);
1999bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter
200076cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    demo_prepare_framebuffers(demo);
2001bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter
2002338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
2003bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter        demo->current_buffer = i;
2004bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter        demo_draw_build_cmd(demo, demo->buffers[i].cmd);
2005bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter    }
2006bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter
2007bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    /*
2008bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter     * Prepare functions above may generate pipeline commands
2009bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter     * that need to be flushed before beginning the render loop.
2010bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter     */
2011bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    demo_flush_init_cmd(demo);
2012bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
2013bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter    demo->current_buffer = 0;
2014b194be6cb3e30bb904364f6ffebaf6ecb343dd71Mike Stroyan    demo->prepared = true;
20154e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
20164e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2017481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_cleanup(struct demo *demo) {
2018eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    uint32_t i;
2019eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
2020eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    demo->prepared = false;
2021a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    vkDeviceWaitIdle(demo->device);
2022eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
20236b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    // Wait for fences from present operations
20246b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    for (i = 0; i < FRAME_LAG; i++) {
2025ed0cd2f95c18b3d3f267c45b149ba435b7d3a0eeszdarkhack        vkWaitForFences(demo->device, 1, &demo->fences[i], VK_TRUE, UINT64_MAX);
20266b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        vkDestroyFence(demo->device, demo->fences[i], NULL);
20276b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        vkDestroySemaphore(demo->device, demo->image_acquired_semaphores[i], NULL);
20286b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        vkDestroySemaphore(demo->device, demo->draw_complete_semaphores[i], NULL);
20296b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        if (demo->separate_present_queue) {
20306b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour            vkDestroySemaphore(demo->device, demo->image_ownership_semaphores[i], NULL);
20316b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        }
20326b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    }
20336b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour
20345aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    for (i = 0; i < demo->swapchainImageCount; i++) {
203569f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
2036de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    }
20375aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    free(demo->framebuffers);
203869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
2039eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
204069f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyPipeline(demo->device, demo->pipeline, NULL);
204169f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
204269f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
204369f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
204469f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
2045eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
2046eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
204769f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
204869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroyImage(demo->device, demo->textures[i].image, NULL);
204969f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
205069f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
2051eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    }
2052b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott    demo->fpDestroySwapchainKHR(demo->device, demo->swapchain, NULL);
2053eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
205469f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyImageView(demo->device, demo->depth.view, NULL);
205569f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyImage(demo->device, demo->depth.image, NULL);
205669f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkFreeMemory(demo->device, demo->depth.mem, NULL);
2057eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
205869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyBuffer(demo->device, demo->uniform_data.buf, NULL);
205969f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkFreeMemory(demo->device, demo->uniform_data.mem, NULL);
2060eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
2061338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    for (i = 0; i < demo->swapchainImageCount; i++) {
206269f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroyImageView(demo->device, demo->buffers[i].view, NULL);
2063481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1,
2064481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                             &demo->buffers[i].cmd);
2065eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    }
2066e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    free(demo->buffers);
2067283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter    free(demo->queue_props);
206869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
20696b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour
20701ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    if (demo->separate_present_queue) {
20711ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        vkDestroyCommandPool(demo->device, demo->present_cmd_pool, NULL);
20721ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    }
207369f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyDevice(demo->device, NULL);
2074a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour    if (demo->validate) {
2075f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter        demo->DestroyDebugReportCallback(demo->inst, demo->msg_callback, NULL);
2076a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour    }
2077b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott    vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
207869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyInstance(demo->inst, NULL);
2079eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
208071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#if defined(VK_USE_PLATFORM_XLIB_KHR)
2081a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    if (demo->use_xlib) {
2082a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        XDestroyWindow(demo->display, demo->xlib_window);
2083a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        XCloseDisplay(demo->display);
2084a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    } else {
2085a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        xcb_destroy_window(demo->connection, demo->xcb_window);
2086a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        xcb_disconnect(demo->connection);
2087a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    }
2088283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter    free(demo->atom_wm_delete_window);
208971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#elif defined(VK_USE_PLATFORM_XCB_KHR)
2090e95075ff904b270aea5084c1ef3fd4453eea1d73Pavol Klacansky    xcb_destroy_window(demo->connection, demo->xcb_window);
209171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    xcb_disconnect(demo->connection);
209271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    free(demo->atom_wm_delete_window);
2093a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
2094a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_shell_surface_destroy(demo->shell_surface);
2095a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_surface_destroy(demo->window);
2096a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_shell_destroy(demo->shell);
2097a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_compositor_destroy(demo->compositor);
2098a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_registry_destroy(demo->registry);
2099a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_display_disconnect(demo->display);
210071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
2101eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo}
2102eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
2103481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_resize(struct demo *demo) {
2104e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    uint32_t i;
2105e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
2106b194be6cb3e30bb904364f6ffebaf6ecb343dd71Mike Stroyan    // Don't react to resize until after first initialization.
2107b194be6cb3e30bb904364f6ffebaf6ecb343dd71Mike Stroyan    if (!demo->prepared) {
2108b194be6cb3e30bb904364f6ffebaf6ecb343dd71Mike Stroyan        return;
2109b194be6cb3e30bb904364f6ffebaf6ecb343dd71Mike Stroyan    }
2110e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // In order to properly resize the window, we must re-create the swapchain
2111e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // AND redo the command buffers, etc.
2112e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    //
2113e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // First, perform part of the demo_cleanup() function:
2114e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    demo->prepared = false;
2115a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    vkDeviceWaitIdle(demo->device);
2116e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
2117e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    for (i = 0; i < demo->swapchainImageCount; i++) {
211869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
2119e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    }
2120e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    free(demo->framebuffers);
212169f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
2122e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
212369f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyPipeline(demo->device, demo->pipeline, NULL);
212469f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
212569f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
212669f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
212769f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
2128e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
2129e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
213069f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
213169f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroyImage(demo->device, demo->textures[i].image, NULL);
213269f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
213369f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
2134e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    }
2135e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
213669f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyImageView(demo->device, demo->depth.view, NULL);
213769f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyImage(demo->device, demo->depth.image, NULL);
213869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkFreeMemory(demo->device, demo->depth.mem, NULL);
2139e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
214069f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyBuffer(demo->device, demo->uniform_data.buf, NULL);
214169f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkFreeMemory(demo->device, demo->uniform_data.mem, NULL);
2142e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
2143e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    for (i = 0; i < demo->swapchainImageCount; i++) {
214469f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu        vkDestroyImageView(demo->device, demo->buffers[i].view, NULL);
2145481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1,
2146481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                             &demo->buffers[i].cmd);
2147e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    }
214869f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
21491ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    if (demo->separate_present_queue) {
21501ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        vkDestroyCommandPool(demo->device, demo->present_cmd_pool, NULL);
21511ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    }
2152e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    free(demo->buffers);
2153e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
2154e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // Second, re-perform the demo_prepare() function, which will re-create the
2155e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    // swapchain:
2156e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott    demo_prepare(demo);
2157e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott}
2158e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott
2159eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo// On MS-Windows, make this a global, so it's available to WndProc()
2160eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedostruct demo demo;
2161eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
216271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#if defined(VK_USE_PLATFORM_WIN32_KHR)
2163481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_run(struct demo *demo) {
2164857542bbc273de949d23515e9a36d4478ccd82e4Courtney Goeltzenleuchter    if (!demo->prepared)
2165857542bbc273de949d23515e9a36d4478ccd82e4Courtney Goeltzenleuchter        return;
2166e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
2167a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    demo_update_data_buffer(demo);
2168e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_draw(demo);
2169eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    demo->curFrame++;
2170481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    if (demo->frameCount != INT_MAX && demo->curFrame == demo->frameCount) {
2171501fdc2af7c60c923f2b1b0cc44187728d27b9f8Karl Schultz        PostQuitMessage(validation_error);
2172eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    }
2173eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo}
2174e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
2175e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott// MS-Windows event handling function:
2176481756e168555e1bf150d3b8f1b81edca1d98c43Karl SchultzLRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
2177481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    switch (uMsg) {
2178e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    case WM_CLOSE:
217951940e40346835ebbf3a3fb8c06c07a3eb518e7bKarl Schultz        PostQuitMessage(validation_error);
21805685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        break;
2181e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    case WM_PAINT:
218245c0906c01533675d27207ff07212adf80ab5187Tony Barbour        // The validation callback calls MessageBox which can generate paint
218345c0906c01533675d27207ff07212adf80ab5187Tony Barbour        // events - don't make more Vulkan calls if we got here from the
218445c0906c01533675d27207ff07212adf80ab5187Tony Barbour        // callback
218545c0906c01533675d27207ff07212adf80ab5187Tony Barbour        if (!in_callback) {
218645c0906c01533675d27207ff07212adf80ab5187Tony Barbour            demo_run(&demo);
218745c0906c01533675d27207ff07212adf80ab5187Tony Barbour        }
218818b53e792aad08d1d95210c372e1326bb952ef9aTony Barbour        break;
2189f47577419de04adea60ce9bb6ace9dae668f88d9Rene Lindsay    case WM_GETMINMAXINFO:     // set window's minimum size
2190f47577419de04adea60ce9bb6ace9dae668f88d9Rene Lindsay        ((MINMAXINFO*)lParam)->ptMinTrackSize = demo.minsize;
2191f47577419de04adea60ce9bb6ace9dae668f88d9Rene Lindsay        return 0;
2192f3f8082b8cc52a5bca59e2a8713d64ee5b9df74eIan Elliott    case WM_SIZE:
2193fdd5af6a3d8cac9fd228eb0da773bdc54f1f90ccPiers Daniell        // Resize the application to the new window size, except when
2194fdd5af6a3d8cac9fd228eb0da773bdc54f1f90ccPiers Daniell        // it was minimized. Vulkan doesn't support images or swapchains
2195fdd5af6a3d8cac9fd228eb0da773bdc54f1f90ccPiers Daniell        // with width=0 and height=0.
2196fdd5af6a3d8cac9fd228eb0da773bdc54f1f90ccPiers Daniell        if (wParam != SIZE_MINIMIZED) {
2197fdd5af6a3d8cac9fd228eb0da773bdc54f1f90ccPiers Daniell            demo.width = lParam & 0xffff;
2198de4760bab32374c471de1afadfbf99d0ac19ca32Tony Barbour            demo.height = (lParam & 0xffff0000) >> 16;
2199fdd5af6a3d8cac9fd228eb0da773bdc54f1f90ccPiers Daniell            demo_resize(&demo);
2200fdd5af6a3d8cac9fd228eb0da773bdc54f1f90ccPiers Daniell        }
2201f3f8082b8cc52a5bca59e2a8713d64ee5b9df74eIan Elliott        break;
2202e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    default:
2203e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        break;
2204e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    }
2205e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    return (DefWindowProc(hWnd, uMsg, wParam, lParam));
2206e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott}
2207e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
2208481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_create_window(struct demo *demo) {
2209481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    WNDCLASSEX win_class;
2210e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
2211e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    // Initialize the window class structure:
2212e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.cbSize = sizeof(WNDCLASSEX);
2213e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.style = CS_HREDRAW | CS_VREDRAW;
2214e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.lpfnWndProc = WndProc;
2215e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.cbClsExtra = 0;
2216e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.cbWndExtra = 0;
2217e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hInstance = demo->connection; // hInstance
2218e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
2219e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
2220e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
2221e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.lpszMenuName = NULL;
2222e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.lpszClassName = demo->name;
2223e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
2224e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    // Register window class:
2225e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    if (!RegisterClassEx(&win_class)) {
2226e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        // It didn't work, so try to give a useful error:
2227e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        printf("Unexpected error trying to start the application!\n");
2228e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        fflush(stdout);
2229e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        exit(1);
2230e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    }
2231e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    // Create window with the registered class:
2232481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    RECT wr = {0, 0, demo->width, demo->height};
2233f585629f8c7ad03f2128aa90dca75d698cb1eb4bMike Stroyan    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
2234e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo->window = CreateWindowEx(0,
2235e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  demo->name,           // class name
2236e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  demo->name,           // app name
2237e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  WS_OVERLAPPEDWINDOW | // window style
2238481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                      WS_VISIBLE | WS_SYSMENU,
2239481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  100, 100,           // x/y coords
2240481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  wr.right - wr.left, // width
2241481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  wr.bottom - wr.top, // height
2242481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  NULL,               // handle to parent
2243481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  NULL,               // handle to menu
2244481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  demo->connection,   // hInstance
2245481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  NULL);              // no extra parameters
2246e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    if (!demo->window) {
2247e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        // It didn't work, so try to give a useful error:
2248e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        printf("Cannot create a window in which to draw!\n");
2249e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        fflush(stdout);
2250e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        exit(1);
2251e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    }
2252f47577419de04adea60ce9bb6ace9dae668f88d9Rene Lindsay    // Window client area size must be at least 1 pixel high, to prevent crash.
2253f47577419de04adea60ce9bb6ace9dae668f88d9Rene Lindsay    demo->minsize.x = GetSystemMetrics(SM_CXMINTRACK);
2254f47577419de04adea60ce9bb6ace9dae668f88d9Rene Lindsay    demo->minsize.y = GetSystemMetrics(SM_CYMINTRACK)+1;
2255e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott}
22564b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#elif defined(VK_USE_PLATFORM_XLIB_KHR)
2257a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbourstatic void demo_create_xlib_window(struct demo *demo) {
2258a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2259a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    demo->display = XOpenDisplay(NULL);
2260a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    long visualMask = VisualScreenMask;
2261a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    int numberOfVisuals;
226254cf48a48c9e593f96d20a9abbdda0d48be906deRene Lindsay    XVisualInfo vInfoTemplate={};
2263a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    vInfoTemplate.screen = DefaultScreen(demo->display);
2264a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    XVisualInfo *visualInfo = XGetVisualInfo(demo->display, visualMask,
2265a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                                             &vInfoTemplate, &numberOfVisuals);
2266a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2267a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    Colormap colormap = XCreateColormap(
2268a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                demo->display, RootWindow(demo->display, vInfoTemplate.screen),
2269a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                visualInfo->visual, AllocNone);
2270a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
227154cf48a48c9e593f96d20a9abbdda0d48be906deRene Lindsay    XSetWindowAttributes windowAttributes={};
2272a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    windowAttributes.colormap = colormap;
2273a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    windowAttributes.background_pixel = 0xFFFFFFFF;
2274a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    windowAttributes.border_pixel = 0;
2275a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    windowAttributes.event_mask =
2276a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask;
2277a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2278a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    demo->xlib_window = XCreateWindow(
2279a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                demo->display, RootWindow(demo->display, vInfoTemplate.screen), 0, 0,
2280a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                demo->width, demo->height, 0, visualInfo->depth, InputOutput,
2281a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                visualInfo->visual,
2282a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                CWBackPixel | CWBorderPixel | CWEventMask | CWColormap, &windowAttributes);
2283a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2284a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    XSelectInput(demo->display, demo->xlib_window, ExposureMask | KeyPressMask);
2285a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    XMapWindow(demo->display, demo->xlib_window);
2286a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    XFlush(demo->display);
2287a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    demo->xlib_wm_delete_window =
2288a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            XInternAtom(demo->display, "WM_DELETE_WINDOW", False);
2289a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour}
2290a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbourstatic void demo_handle_xlib_event(struct demo *demo, const XEvent *event) {
2291a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    switch(event->type) {
2292a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    case ClientMessage:
2293a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        if ((Atom)event->xclient.data.l[0] == demo->xlib_wm_delete_window)
2294a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->quit = true;
2295a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        break;
2296a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    case KeyPress:
2297a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        switch (event->xkey.keycode) {
2298a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        case 0x9: // Escape
2299a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->quit = true;
2300a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            break;
2301a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        case 0x71: // left arrow key
2302a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->spin_angle += demo->spin_increment;
2303a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            break;
2304a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        case 0x72: // right arrow key
2305a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->spin_angle -= demo->spin_increment;
2306a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            break;
2307a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        case 0x41:
2308a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->pause = !demo->pause;
2309a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            break;
2310a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        }
2311a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        break;
2312a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    case ConfigureNotify:
2313a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        if ((demo->width != event->xconfigure.width) ||
2314a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            (demo->height != event->xconfigure.height)) {
2315a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->width = event->xconfigure.width;
2316a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->height = event->xconfigure.height;
2317a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo_resize(demo);
2318a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        }
2319a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        break;
2320a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    default:
2321a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        break;
2322a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    }
2323a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2324a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour}
2325a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2326a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbourstatic void demo_run_xlib(struct demo *demo) {
2327a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2328a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    while (!demo->quit) {
2329a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        XEvent event;
2330a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2331a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        if (demo->pause) {
2332a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            XNextEvent(demo->display, &event);
2333a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo_handle_xlib_event(demo, &event);
2334a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        } else {
2335a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            while (XPending(demo->display) > 0) {
2336a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                XNextEvent(demo->display, &event);
2337a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                demo_handle_xlib_event(demo, &event);
2338a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            }
2339a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        }
2340a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
2341a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        demo_update_data_buffer(demo);
2342a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        demo_draw(demo);
2343a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        demo->curFrame++;
2344a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
2345a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->quit = true;
2346a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    }
2347a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour}
23484b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#endif // VK_USE_PLATFORM_XLIB_KHR
23494b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#ifdef VK_USE_PLATFORM_XCB_KHR
2350a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbourstatic void demo_handle_xcb_event(struct demo *demo,
2351481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                              const xcb_generic_event_t *event) {
2352886be472ea5f6fc366d2e20156396e17d0947816Piers Daniell    uint8_t event_code = event->response_type & 0x7f;
2353ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    switch (event_code) {
23544e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    case XCB_EXPOSE:
2355546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        // TODO: Resize window
23564e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        break;
2357ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    case XCB_CLIENT_MESSAGE:
2358481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if ((*(xcb_client_message_event_t *)event).data.data32[0] ==
2359481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (*demo->atom_wm_delete_window).atom) {
2360ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter            demo->quit = true;
2361ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter        }
2362ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter        break;
2363481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    case XCB_KEY_RELEASE: {
2364481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        const xcb_key_release_event_t *key =
2365481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (const xcb_key_release_event_t *)event;
23664e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2367481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        switch (key->detail) {
2368481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        case 0x9: // Escape
2369481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            demo->quit = true;
2370481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            break;
2371481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        case 0x71: // left arrow key
2372481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            demo->spin_angle += demo->spin_increment;
2373481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            break;
2374481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        case 0x72: // right arrow key
2375481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            demo->spin_angle -= demo->spin_increment;
2376481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            break;
2377481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        case 0x41:
2378481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            demo->pause = !demo->pause;
2379481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            break;
23804e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        }
2381481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    } break;
2382481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    case XCB_CONFIGURE_NOTIFY: {
2383481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        const xcb_configure_notify_event_t *cfg =
2384481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (const xcb_configure_notify_event_t *)event;
2385481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if ((demo->width != cfg->width) || (demo->height != cfg->height)) {
23863d77c303a9ea1b9e380569af811392c56cd9d055Damien Leone            demo->width = cfg->width;
23873d77c303a9ea1b9e380569af811392c56cd9d055Damien Leone            demo->height = cfg->height;
2388481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            demo_resize(demo);
2389e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott        }
2390481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    } break;
23914e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    default:
23924e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        break;
23934e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
23944e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
23954e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2396a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbourstatic void demo_run_xcb(struct demo *demo) {
23974e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_flush(demo->connection);
23984e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
23994e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    while (!demo->quit) {
24004e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        xcb_generic_event_t *event;
24014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2402546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        if (demo->pause) {
2403546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter            event = xcb_wait_for_event(demo->connection);
2404546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        } else {
2405546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter            event = xcb_poll_for_event(demo->connection);
2406111f7b1e913ebc843e8fd741140648ae8d87cc8aTony Barbour            while(event) {
2407111f7b1e913ebc843e8fd741140648ae8d87cc8aTony Barbour                demo_handle_xcb_event(demo, event);
2408111f7b1e913ebc843e8fd741140648ae8d87cc8aTony Barbour                free(event);
2409111f7b1e913ebc843e8fd741140648ae8d87cc8aTony Barbour                event = xcb_poll_for_event(demo->connection);
2410111f7b1e913ebc843e8fd741140648ae8d87cc8aTony Barbour            }
2411bb3e1312f9d8151ed996962332b814b68a2b4956Courtney Goeltzenleuchter        }
24123eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
2413546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        demo_update_data_buffer(demo);
2414bb3e1312f9d8151ed996962332b814b68a2b4956Courtney Goeltzenleuchter        demo_draw(demo);
2415eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        demo->curFrame++;
2416a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
2417eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            demo->quit = true;
24184e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
24194e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
24204e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2421a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbourstatic void demo_create_xcb_window(struct demo *demo) {
24224e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    uint32_t value_mask, value_list[32];
24234e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2424a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    demo->xcb_window = xcb_generate_id(demo->connection);
24254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
24264e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
24274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    value_list[0] = demo->screen->black_pixel;
2428481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    value_list[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_EXPOSURE |
2429e2688a5f45a9a9638c5863c95a0521e00030db37Ian Elliott                    XCB_EVENT_MASK_STRUCTURE_NOTIFY;
24304e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2431a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    xcb_create_window(demo->connection, XCB_COPY_FROM_PARENT, demo->xcb_window,
2432481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                      demo->screen->root, 0, 0, demo->width, demo->height, 0,
2433481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                      XCB_WINDOW_CLASS_INPUT_OUTPUT, demo->screen->root_visual,
2434481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                      value_mask, value_list);
24354e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2436ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    /* Magic code that will send notification when window is destroyed */
2437481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    xcb_intern_atom_cookie_t cookie =
2438481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        xcb_intern_atom(demo->connection, 1, 12, "WM_PROTOCOLS");
2439481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    xcb_intern_atom_reply_t *reply =
2440481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        xcb_intern_atom_reply(demo->connection, cookie, 0);
2441481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz
2442481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    xcb_intern_atom_cookie_t cookie2 =
2443481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        xcb_intern_atom(demo->connection, 0, 16, "WM_DELETE_WINDOW");
2444481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    demo->atom_wm_delete_window =
2445481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        xcb_intern_atom_reply(demo->connection, cookie2, 0);
2446481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz
2447a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE, demo->xcb_window,
2448481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                        (*reply).atom, 4, 32, 1,
2449ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter                        &(*demo->atom_wm_delete_window).atom);
2450ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    free(reply);
2451ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter
2452a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    xcb_map_window(demo->connection, demo->xcb_window);
2453eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
2454481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // Force the x/y coordinates to 100,100 results are identical in consecutive
2455481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // runs
2456481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    const uint32_t coords[] = {100, 100};
2457a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    xcb_configure_window(demo->connection, demo->xcb_window,
2458eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo                         XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords);
24594e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
2460930cd2e549552276db828b6b296601f8c074a21dTony Barbour// VK_USE_PLATFORM_XCB_KHR
2461930cd2e549552276db828b6b296601f8c074a21dTony Barbour#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
2462a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic void demo_run(struct demo *demo) {
2463a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    while (!demo->quit) {
2464a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        demo_update_data_buffer(demo);
2465a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        demo_draw(demo);
2466a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        demo->curFrame++;
2467a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
2468a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong            demo->quit = true;
2469a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    }
2470a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong}
2471a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
2472a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic void handle_ping(void *data UNUSED,
2473a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                        struct wl_shell_surface *shell_surface,
2474a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                        uint32_t serial) {
2475a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_shell_surface_pong(shell_surface, serial);
2476a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong}
2477a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
2478a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic void handle_configure(void *data UNUSED,
2479a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                             struct wl_shell_surface *shell_surface UNUSED,
2480a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                             uint32_t edges UNUSED, int32_t width UNUSED,
2481a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                             int32_t height UNUSED) {}
2482a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
2483a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic void handle_popup_done(void *data UNUSED,
2484a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                              struct wl_shell_surface *shell_surface UNUSED) {}
2485a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
2486a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic const struct wl_shell_surface_listener shell_surface_listener = {
2487a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    handle_ping, handle_configure, handle_popup_done};
2488a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
2489a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic void demo_create_window(struct demo *demo) {
2490a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    demo->window = wl_compositor_create_surface(demo->compositor);
2491a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    if (!demo->window) {
2492a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        printf("Can not create wayland_surface from compositor!\n");
2493a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        fflush(stdout);
2494a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        exit(1);
2495a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    }
2496a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
2497a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    demo->shell_surface = wl_shell_get_shell_surface(demo->shell, demo->window);
2498a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    if (!demo->shell_surface) {
2499a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        printf("Can not get shell_surface from wayland_surface!\n");
2500a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        fflush(stdout);
2501a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        exit(1);
2502a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    }
2503a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_shell_surface_add_listener(demo->shell_surface, &shell_surface_listener,
2504a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                                  demo);
2505a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_shell_surface_set_toplevel(demo->shell_surface);
2506a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_shell_surface_set_title(demo->shell_surface, APP_SHORT_NAME);
2507a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong}
250871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
250971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentinestatic void demo_run(struct demo *demo) {
251071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    if (!demo->prepared)
251171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        return;
251271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
251371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    demo_update_data_buffer(demo);
251471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    demo_draw(demo);
251571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    demo->curFrame++;
251671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine}
251771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
25184e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
25198c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter/*
25208c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter * Return 1 (true) if all layer names specified in check_names
25218c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter * can be found in given layer properties.
25228c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter */
25231f41f54bc20d57faed702aec3074eacdfc34680dCourtney Goeltzenleuchterstatic VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
2524481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  uint32_t layer_count,
2525481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                  VkLayerProperties *layers) {
25268c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    for (uint32_t i = 0; i < check_count; i++) {
25271f41f54bc20d57faed702aec3074eacdfc34680dCourtney Goeltzenleuchter        VkBool32 found = 0;
25288c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        for (uint32_t j = 0; j < layer_count; j++) {
25298c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter            if (!strcmp(check_names[i], layers[j].layerName)) {
25308c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                found = 1;
2531beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                break;
25328c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter            }
25338c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        }
25348c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        if (!found) {
25358c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter            fprintf(stderr, "Cannot find layer: %s\n", check_names[i]);
25368c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter            return 0;
25378c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        }
25388c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    }
25398c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    return 1;
25408c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter}
25418c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
2542481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_init_vk(struct demo *demo) {
25433536b44d5d907e6ce3d97c40366f12a988c8036dTobin Ehlis    VkResult err;
25441c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    uint32_t instance_extension_count = 0;
254518061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    uint32_t instance_layer_count = 0;
254697dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz    uint32_t validation_layer_count = 0;
254750f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    char **instance_validation_layers = NULL;
254850f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    demo->enabled_extension_count = 0;
254950f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    demo->enabled_layer_count = 0;
255018061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
255150f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    char *instance_validation_layers_alt1[] = {
255250f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        "VK_LAYER_LUNARG_standard_validation"
255350f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    };
255450f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz
255550f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    char *instance_validation_layers_alt2[] = {
255637a36016819655e67b25780c535afa8413c50f3fMark Lobodzinski        "VK_LAYER_GOOGLE_threading",       "VK_LAYER_LUNARG_parameter_validation",
255737a36016819655e67b25780c535afa8413c50f3fMark Lobodzinski        "VK_LAYER_LUNARG_object_tracker",  "VK_LAYER_LUNARG_image",
255837a36016819655e67b25780c535afa8413c50f3fMark Lobodzinski        "VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain",
255937a36016819655e67b25780c535afa8413c50f3fMark Lobodzinski        "VK_LAYER_GOOGLE_unique_objects"
25608c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    };
25618c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
256218061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    /* Look for validation layers */
25631f41f54bc20d57faed702aec3074eacdfc34680dCourtney Goeltzenleuchter    VkBool32 validation_found = 0;
256450f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    if (demo->validate) {
256518061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
256650f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
2567beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        assert(!err);
25688c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
256950f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        instance_validation_layers = instance_validation_layers_alt1;
257050f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        if (instance_layer_count > 0) {
257150f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            VkLayerProperties *instance_layers =
257250f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    malloc(sizeof (VkLayerProperties) * instance_layer_count);
257350f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
257450f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    instance_layers);
257550f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            assert(!err);
2576beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2577beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
257850f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            validation_found = demo_check_layers(
257950f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    ARRAY_SIZE(instance_validation_layers_alt1),
258050f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    instance_validation_layers, instance_layer_count,
258150f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    instance_layers);
258250f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            if (validation_found) {
258350f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt1);
258497dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz                demo->enabled_layers[0] = "VK_LAYER_LUNARG_standard_validation";
258597dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz                validation_layer_count = 1;
258650f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            } else {
258750f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                // use alternative set of validation layers
258850f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                instance_validation_layers = instance_validation_layers_alt2;
258950f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
259050f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                validation_found = demo_check_layers(
259150f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    ARRAY_SIZE(instance_validation_layers_alt2),
259250f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    instance_validation_layers, instance_layer_count,
259350f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    instance_layers);
259497dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz                validation_layer_count =
259597dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz                    ARRAY_SIZE(instance_validation_layers_alt2);
259697dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz                for (uint32_t i = 0; i < validation_layer_count; i++) {
259797dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz                    demo->enabled_layers[i] = instance_validation_layers[i];
259850f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                }
259950f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            }
260050f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            free(instance_layers);
260150f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        }
260218061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
260350f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        if (!validation_found) {
26042a5eaf00906107deae34a407f0e0db902e496d20Karl Schultz            ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find "
260550f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    "required validation layer.\n\n"
260650f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    "Please look at the Getting Started guide for additional "
260750f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    "information.\n",
260850f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    "vkCreateInstance Failure");
260950f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        }
2610beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    }
26113536b44d5d907e6ce3d97c40366f12a988c8036dTobin Ehlis
2612beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    /* Look for instance extensions */
2613f1d90139557362249b96f5331c587ad1134edb99Ian Elliott    VkBool32 surfaceExtFound = 0;
2614f1d90139557362249b96f5331c587ad1134edb99Ian Elliott    VkBool32 platformSurfaceExtFound = 0;
2615e95075ff904b270aea5084c1ef3fd4453eea1d73Pavol Klacansky#if defined(VK_USE_PLATFORM_XLIB_KHR)
2616a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    VkBool32 xlibSurfaceExtFound = 0;
26174bd81e481fdac06ba3af343dd29bae841d6fff82Tobin Ehlis#endif
261850f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    memset(demo->extension_names, 0, sizeof(demo->extension_names));
2619beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2620481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = vkEnumerateInstanceExtensionProperties(
2621beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        NULL, &instance_extension_count, NULL);
262218061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
2623beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2624beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    if (instance_extension_count > 0) {
2625beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        VkExtensionProperties *instance_extensions =
2626beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            malloc(sizeof(VkExtensionProperties) * instance_extension_count);
2627beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        err = vkEnumerateInstanceExtensionProperties(
2628beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            NULL, &instance_extension_count, instance_extensions);
2629beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        assert(!err);
2630beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        for (uint32_t i = 0; i < instance_extension_count; i++) {
2631beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,
2632beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                        instance_extensions[i].extensionName)) {
2633beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                surfaceExtFound = 1;
263450f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                demo->extension_names[demo->enabled_extension_count++] =
2635beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                    VK_KHR_SURFACE_EXTENSION_NAME;
2636beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            }
263771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#if defined(VK_USE_PLATFORM_WIN32_KHR)
2638beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
2639beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                        instance_extensions[i].extensionName)) {
2640beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                platformSurfaceExtFound = 1;
264150f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                demo->extension_names[demo->enabled_extension_count++] =
2642beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                    VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
2643beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            }
2644e95075ff904b270aea5084c1ef3fd4453eea1d73Pavol Klacansky#endif
2645e95075ff904b270aea5084c1ef3fd4453eea1d73Pavol Klacansky#if defined(VK_USE_PLATFORM_XLIB_KHR)
2646a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            if (!strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
2647a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                        instance_extensions[i].extensionName)) {
2648a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                platformSurfaceExtFound = 1;
2649a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                xlibSurfaceExtFound = 1;
2650a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                demo->extension_names[demo->enabled_extension_count++] =
2651a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                    VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
2652a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            }
2653e95075ff904b270aea5084c1ef3fd4453eea1d73Pavol Klacansky#endif
2654e95075ff904b270aea5084c1ef3fd4453eea1d73Pavol Klacansky#if defined(VK_USE_PLATFORM_XCB_KHR)
2655beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME,
2656beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                        instance_extensions[i].extensionName)) {
2657beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                platformSurfaceExtFound = 1;
265850f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                demo->extension_names[demo->enabled_extension_count++] =
2659beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                    VK_KHR_XCB_SURFACE_EXTENSION_NAME;
2660beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            }
2661e95075ff904b270aea5084c1ef3fd4453eea1d73Pavol Klacansky#endif
2662a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
2663a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong            if (!strcmp(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
2664a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                        instance_extensions[i].extensionName)) {
2665a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                platformSurfaceExtFound = 1;
2666a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                demo->extension_names[demo->enabled_extension_count++] =
2667a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                    VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
2668a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong            }
2669a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#endif
2670e95075ff904b270aea5084c1ef3fd4453eea1d73Pavol Klacansky#if defined(VK_USE_PLATFORM_ANDROID_KHR)
267171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            if (!strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
267271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                        instance_extensions[i].extensionName)) {
267371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                platformSurfaceExtFound = 1;
267471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                demo->extension_names[demo->enabled_extension_count++] =
267571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                    VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
267671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            }
267771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
2678beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
2679beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                        instance_extensions[i].extensionName)) {
2680beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                if (demo->validate) {
268150f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz                    demo->extension_names[demo->enabled_extension_count++] =
2682beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                        VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
2683beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                }
268418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter            }
268550f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz            assert(demo->enabled_extension_count < 64);
2686a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        }
2687beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2688beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        free(instance_extensions);
26893536b44d5d907e6ce3d97c40366f12a988c8036dTobin Ehlis    }
2690beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2691f1d90139557362249b96f5331c587ad1134edb99Ian Elliott    if (!surfaceExtFound) {
2692481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2693481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 "the " VK_KHR_SURFACE_EXTENSION_NAME
2694481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 " extension.\n\nDo you have a compatible "
26953b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "Vulkan installable client driver (ICD) installed?\nPlease "
26963b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "look at the Getting Started guide for additional "
26973b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "information.\n",
26983b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "vkCreateInstance Failure");
26993b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott    }
2700f1d90139557362249b96f5331c587ad1134edb99Ian Elliott    if (!platformSurfaceExtFound) {
270171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#if defined(VK_USE_PLATFORM_WIN32_KHR)
2702481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2703481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 "the " VK_KHR_WIN32_SURFACE_EXTENSION_NAME
2704481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 " extension.\n\nDo you have a compatible "
2705051ae4bd4545590437d46268ac6992358cb48c13Mark Lobodzinski                 "Vulkan installable client driver (ICD) installed?\nPlease "
2706051ae4bd4545590437d46268ac6992358cb48c13Mark Lobodzinski                 "look at the Getting Started guide for additional "
2707051ae4bd4545590437d46268ac6992358cb48c13Mark Lobodzinski                 "information.\n",
2708051ae4bd4545590437d46268ac6992358cb48c13Mark Lobodzinski                 "vkCreateInstance Failure");
270971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#elif defined(VK_USE_PLATFORM_XCB_KHR)
2710481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2711481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 "the " VK_KHR_XCB_SURFACE_EXTENSION_NAME
2712481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 " extension.\n\nDo you have a compatible "
2713f1d90139557362249b96f5331c587ad1134edb99Ian Elliott                 "Vulkan installable client driver (ICD) installed?\nPlease "
2714f1d90139557362249b96f5331c587ad1134edb99Ian Elliott                 "look at the Getting Started guide for additional "
2715f1d90139557362249b96f5331c587ad1134edb99Ian Elliott                 "information.\n",
2716f1d90139557362249b96f5331c587ad1134edb99Ian Elliott                 "vkCreateInstance Failure");
2717a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
2718a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2719a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                 "the " VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
2720a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                 " extension.\n\nDo you have a compatible "
2721a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                 "Vulkan installable client driver (ICD) installed?\nPlease "
2722a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                 "look at the Getting Started guide for additional "
2723a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                 "information.\n",
2724a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                 "vkCreateInstance Failure");
272571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
272671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
272771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                 "the " VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
272871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                 " extension.\n\nDo you have a compatible "
272971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                 "Vulkan installable client driver (ICD) installed?\nPlease "
273071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                 "look at the Getting Started guide for additional "
273171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                 "information.\n",
273271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                 "vkCreateInstance Failure");
273371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
2734f1d90139557362249b96f5331c587ad1134edb99Ian Elliott    }
27354bd81e481fdac06ba3af343dd29bae841d6fff82Tobin Ehlis#if defined(VK_USE_PLATFORM_XLIB_KHR)
2736a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    if (demo->use_xlib && !xlibSurfaceExtFound) {
2737a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
2738a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                 "the " VK_KHR_XLIB_SURFACE_EXTENSION_NAME
2739a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                 " extension.\n\nDo you have a compatible "
2740a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                 "Vulkan installable client driver (ICD) installed?\nPlease "
2741a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                 "look at the Getting Started guide for additional "
2742a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                 "information.\n",
2743a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                 "vkCreateInstance Failure");
2744a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    }
274571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
2746382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkApplicationInfo app = {
27479cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
27484e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .pNext = NULL,
27491f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu        .pApplicationName = APP_SHORT_NAME,
27501f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu        .applicationVersion = 0,
27514e19ed0ed322e45993bac7917a1a253dbaaf88f9Ian Elliott        .pEngineName = APP_SHORT_NAME,
27524e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .engineVersion = 0,
2753d3995c987ba7e47700ceb54535880e782c6b04c1Jon Ashburn        .apiVersion = VK_API_VERSION_1_0,
27544e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
27555685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    VkInstanceCreateInfo inst_info = {
27569cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
275729669a43755f6caa97c4c1d447f494514ba343d9Jon Ashburn        .pNext = NULL,
27581f85191a3a8479194ecb7b937aee284cf80cf08fChia-I Wu        .pApplicationInfo = &app,
275950f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        .enabledLayerCount = demo->enabled_layer_count,
276050f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        .ppEnabledLayerNames = (const char *const *)instance_validation_layers,
276150f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        .enabledExtensionCount = demo->enabled_extension_count,
276250f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz        .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
276329669a43755f6caa97c4c1d447f494514ba343d9Jon Ashburn    };
27647c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz
27657c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz    /*
27667c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz     * This is info for a temp callback to use during CreateInstance.
27677c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz     * After the instance is created, we use the instance-based
27687c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz     * function to register the final callback.
27697c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz     */
2770d9fac52a86bcf49f1a6c0c00ba57166bd2540e24Ian Elliott    VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
2771d9fac52a86bcf49f1a6c0c00ba57166bd2540e24Ian Elliott    if (demo->validate) {
2772d9fac52a86bcf49f1a6c0c00ba57166bd2540e24Ian Elliott        dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
2773d9fac52a86bcf49f1a6c0c00ba57166bd2540e24Ian Elliott        dbgCreateInfo.pNext = NULL;
27747c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz        dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc;
277520a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        dbgCreateInfo.pUserData = demo;
2776d9fac52a86bcf49f1a6c0c00ba57166bd2540e24Ian Elliott        dbgCreateInfo.flags =
2777d9fac52a86bcf49f1a6c0c00ba57166bd2540e24Ian Elliott            VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
2778d9fac52a86bcf49f1a6c0c00ba57166bd2540e24Ian Elliott        inst_info.pNext = &dbgCreateInfo;
2779d9fac52a86bcf49f1a6c0c00ba57166bd2540e24Ian Elliott    }
2780ff6dab510e7a43155926704eee930c9ed5b9d5efIan Elliott
2781e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t gpu_count;
27824e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
278369f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    err = vkCreateInstance(&inst_info, NULL, &demo->inst);
2784caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott    if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
2785caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott        ERR_EXIT("Cannot find a compatible Vulkan installable client driver "
27863b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "(ICD).\n\nPlease look at the Getting Started guide for "
2787caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott                 "additional information.\n",
2788caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott                 "vkCreateInstance Failure");
2789ac544f3737b45a5b35251100a3396aa8be397d8dCourtney Goeltzenleuchter    } else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) {
27905685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        ERR_EXIT("Cannot find a specified extension library"
2791beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                 ".\nMake sure your layers path is set appropriately.\n",
27925685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour                 "vkCreateInstance Failure");
2793caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott    } else if (err) {
27943b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott        ERR_EXIT("vkCreateInstance failed.\n\nDo you have a compatible Vulkan "
27953b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "installable client driver (ICD) installed?\nPlease look at "
2796caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott                 "the Getting Started guide for additional information.\n",
2797caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott                 "vkCreateInstance Failure");
2798dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott    }
279929669a43755f6caa97c4c1d447f494514ba343d9Jon Ashburn
28004f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    /* Make initial call to query gpu_count, then second call for gpu info*/
28014f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
28024f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    assert(!err && gpu_count > 0);
2803beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2804beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    if (gpu_count > 0) {
2805beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        VkPhysicalDevice *physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count);
2806beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices);
2807beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        assert(!err);
2808beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        /* For cube demo we just grab the first physical device */
2809beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        demo->gpu = physical_devices[0];
2810beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        free(physical_devices);
2811beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    } else {
2812beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices.\n\n"
2813beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                 "Do you have a compatible Vulkan installable client driver (ICD) "
2814beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                 "installed?\nPlease look at the Getting Started guide for "
2815beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                 "additional information.\n",
2816beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                 "vkEnumeratePhysicalDevices Failure");
2817beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    }
28184e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2819beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    /* Look for device extensions */
2820beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    uint32_t device_extension_count = 0;
2821f1d90139557362249b96f5331c587ad1134edb99Ian Elliott    VkBool32 swapchainExtFound = 0;
28223d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    demo->enabled_extension_count = 0;
282350f9bc7014544e04fb737221471e4fdbb3e57cb0Karl Schultz    memset(demo->extension_names, 0, sizeof(demo->extension_names));
2824beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2825beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL,
2826beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                                               &device_extension_count, NULL);
282718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
2828e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
2829beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves    if (device_extension_count > 0) {
2830beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        VkExtensionProperties *device_extensions =
2831beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            malloc(sizeof(VkExtensionProperties) * device_extension_count);
2832beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        err = vkEnumerateDeviceExtensionProperties(
2833beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            demo->gpu, NULL, &device_extension_count, device_extensions);
2834beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        assert(!err);
2835beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2836beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        for (uint32_t i = 0; i < device_extension_count; i++) {
2837beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
2838beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                        device_extensions[i].extensionName)) {
2839beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                swapchainExtFound = 1;
2840beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                demo->extension_names[demo->enabled_extension_count++] =
2841beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves                    VK_KHR_SWAPCHAIN_EXTENSION_NAME;
2842beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            }
2843beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves            assert(demo->enabled_extension_count < 64);
284418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        }
2845beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2846beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves        free(device_extensions);
284718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    }
2848beebf7d6163262eceb61ac1ca145a179383717dbDustin Graves
2849d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    if (!swapchainExtFound) {
2850481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find "
2851481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 "the " VK_KHR_SWAPCHAIN_EXTENSION_NAME
2852481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                 " extension.\n\nDo you have a compatible "
285318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter                 "Vulkan installable client driver (ICD) installed?\nPlease "
285418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter                 "look at the Getting Started guide for additional "
285518061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter                 "information.\n",
285618061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter                 "vkCreateInstance Failure");
285718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    }
285818061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
28595685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    if (demo->validate) {
2860481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->CreateDebugReportCallback =
2861481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(
2862481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                demo->inst, "vkCreateDebugReportCallbackEXT");
2863481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->DestroyDebugReportCallback =
2864481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(
2865481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                demo->inst, "vkDestroyDebugReportCallbackEXT");
2866f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter        if (!demo->CreateDebugReportCallback) {
2867481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            ERR_EXIT(
2868481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                "GetProcAddr: Unable to find vkCreateDebugReportCallbackEXT\n",
2869481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                "vkGetProcAddr Failure");
28701c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
2871f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter        if (!demo->DestroyDebugReportCallback) {
2872481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            ERR_EXIT(
2873481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                "GetProcAddr: Unable to find vkDestroyDebugReportCallbackEXT\n",
2874481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                "vkGetProcAddr Failure");
2875a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        }
2876481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->DebugReportMessage =
2877481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(
2878481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                demo->inst, "vkDebugReportMessageEXT");
2879ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter        if (!demo->DebugReportMessage) {
2880acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter            ERR_EXIT("GetProcAddr: Unable to find vkDebugReportMessageEXT\n",
2881ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter                     "vkGetProcAddr Failure");
2882ea026a691de468b4187d7f821314f867f1a7fb6dCourtney Goeltzenleuchter        }
288369d4893b673bd552e445ba999ad0e73463d35007Jon Ashburn
2884acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter        VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
28857c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz        PFN_vkDebugReportCallbackEXT callback;
28867c5f63efbdf1b13464664623d6d2f46bd2f405e1Karl Schultz        callback = demo->use_break ? BreakCallback : dbgFunc;
2887acb1359c8e1528e5d67bb0101c94c48a07785098Courtney Goeltzenleuchter        dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
2888f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter        dbgCreateInfo.pNext = NULL;
2889f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter        dbgCreateInfo.pfnCallback = callback;
289020a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        dbgCreateInfo.pUserData = demo;
2891481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        dbgCreateInfo.flags =
28925c13d4d87fd0356003a3441e887a172b991e880fMark Lobodzinski            VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
2893481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        err = demo->CreateDebugReportCallback(demo->inst, &dbgCreateInfo, NULL,
2894481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                                              &demo->msg_callback);
28951c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        switch (err) {
28961c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        case VK_SUCCESS:
28971c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            break;
28981c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        case VK_ERROR_OUT_OF_HOST_MEMORY:
2899f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter            ERR_EXIT("CreateDebugReportCallback: out of host memory\n",
2900f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter                     "CreateDebugReportCallback Failure");
29011c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            break;
29021c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        default:
2903f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter            ERR_EXIT("CreateDebugReportCallback: unknown failure\n",
2904f6a6e223b7ca92b5e3c8b05331b500ab8f01116aCourtney Goeltzenleuchter                     "CreateDebugReportCallback Failure");
29051c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            break;
29061c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
29075685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    }
290801d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
29093bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis
29103bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    /* Call with NULL data to get count */
291137a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu,
291237a5db39edf36de91652ded72b88d33eec9db3deTony Barbour                                             &demo->queue_family_count, NULL);
291337a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    assert(demo->queue_family_count >= 1);
29143bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis
2915481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    demo->queue_props = (VkQueueFamilyProperties *)malloc(
291637a5db39edf36de91652ded72b88d33eec9db3deTony Barbour        demo->queue_family_count * sizeof(VkQueueFamilyProperties));
291737a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    vkGetPhysicalDeviceQueueFamilyProperties(
291837a5db39edf36de91652ded72b88d33eec9db3deTony Barbour        demo->gpu, &demo->queue_family_count, demo->queue_props);
291937a5db39edf36de91652ded72b88d33eec9db3deTony Barbour
2920795460a0578a501c1e8d15ee4156a5fd1c13310cTobin Ehlis    // Query fine-grained feature support for this device.
2921481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    //  If app has specific feature requirements it should check supported
2922481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    //  features based on this query
29236454cd96df644d51bd4d71bfb5067345e8d2dd47Tobin Ehlis    VkPhysicalDeviceFeatures physDevFeatures;
292401d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceFeatures(demo->gpu, &physDevFeatures);
2925795460a0578a501c1e8d15ee4156a5fd1c13310cTobin Ehlis
29263d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceSupportKHR);
29273d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
29283d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceFormatsKHR);
29293d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfacePresentModesKHR);
29303d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_INSTANCE_PROC_ADDR(demo->inst, GetSwapchainImagesKHR);
29313d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour}
29323d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour
2933481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_create_device(struct demo *demo) {
29343d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    VkResult U_ASSERT_ONLY err;
2935481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    float queue_priorities[1] = {0.0};
29361ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    VkDeviceQueueCreateInfo queues[2];
29371ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    queues[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
29381ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    queues[0].pNext = NULL;
29391ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    queues[0].queueFamilyIndex = demo->graphics_queue_family_index;
29401ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    queues[0].queueCount = 1;
29411ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    queues[0].pQueuePriorities = queue_priorities;
29421ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    queues[0].flags = 0;
29433bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis
29443bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    VkDeviceCreateInfo device = {
29453bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
29463bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .pNext = NULL,
2947045654f003fa47a4a15cba6709222c75b5e72e41Chia-I Wu        .queueCreateInfoCount = 1,
29481ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        .pQueueCreateInfos = queues,
294997dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz        .enabledLayerCount = 0,
295097dc22bdc2e5e96e79f0d8ca4326701e0ce9fcffKarl Schultz        .ppEnabledLayerNames = NULL,
29513d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour        .enabledExtensionCount = demo->enabled_extension_count,
2952481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
2953481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        .pEnabledFeatures =
2954481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            NULL, // If specific features are required, pass them in here
29553bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    };
29561ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    if (demo->separate_present_queue) {
29571ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        queues[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
29581ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        queues[1].pNext = NULL;
29591ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        queues[1].queueFamilyIndex = demo->present_queue_family_index;
29601ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        queues[1].queueCount = 1;
29611ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        queues[1].pQueuePriorities = queue_priorities;
29621ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        queues[1].flags = 0;
29631ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        device.queueCreateInfoCount = 2;
29641ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    }
296569f40128cce0970d10aaa30ea8c6b56a7dda3f36Chia-I Wu    err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device);
29664e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
296789147b4c6e540869f2a8c1a43aa54c44848cde4cCourtney Goeltzenleuchter}
296889147b4c6e540869f2a8c1a43aa54c44848cde4cCourtney Goeltzenleuchter
2969481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_init_vk_swapchain(struct demo *demo) {
2970e92af7e35e235faf650de0ffd413aa2e8417fd2dCourtney Goeltzenleuchter    VkResult U_ASSERT_ONLY err;
297189147b4c6e540869f2a8c1a43aa54c44848cde4cCourtney Goeltzenleuchter    uint32_t i;
2972f316806ced61ba68efb7be2335bd1d1138e5234dCourtney Goeltzenleuchter
2973481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz// Create a WSI surface for the window:
297471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#if defined(VK_USE_PLATFORM_WIN32_KHR)
2975da44dfef7703f795e9de97fe6bda17b68864bc24Ian Elliott    VkWin32SurfaceCreateInfoKHR createInfo;
2976da44dfef7703f795e9de97fe6bda17b68864bc24Ian Elliott    createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
2977da44dfef7703f795e9de97fe6bda17b68864bc24Ian Elliott    createInfo.pNext = NULL;
2978da44dfef7703f795e9de97fe6bda17b68864bc24Ian Elliott    createInfo.flags = 0;
297909338b5ff0968d9a40cd0e26e3cfb947add33354Jon Ashburn    createInfo.hinstance = demo->connection;
298009338b5ff0968d9a40cd0e26e3cfb947add33354Jon Ashburn    createInfo.hwnd = demo->window;
2981da44dfef7703f795e9de97fe6bda17b68864bc24Ian Elliott
2982481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err =
2983481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        vkCreateWin32SurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface);
2984a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) && !defined(VK_USE_PLATFORM_XCB_KHR)
2985a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    VkWaylandSurfaceCreateInfoKHR createInfo;
2986a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
2987a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    createInfo.pNext = NULL;
2988a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    createInfo.flags = 0;
2989a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    createInfo.display = demo->display;
2990a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    createInfo.surface = demo->window;
2991a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
2992a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    err = vkCreateWaylandSurfaceKHR(demo->inst, &createInfo, NULL,
2993a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                                    &demo->surface);
299471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
299571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    VkAndroidSurfaceCreateInfoKHR createInfo;
299671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
299771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    createInfo.pNext = NULL;
299871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    createInfo.flags = 0;
299971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    createInfo.window = (ANativeWindow*)(demo->window);
3000b5fad79e4bb8089a6a9519d248c378079822d2c6Ian Elliott
300171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    err = vkCreateAndroidSurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface);
300271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
3003a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    if (demo->use_xlib) {
30044bd81e481fdac06ba3af343dd29bae841d6fff82Tobin Ehlis#if defined(VK_USE_PLATFORM_XLIB_KHR)
3005a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        VkXlibSurfaceCreateInfoKHR createInfo;
3006a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
3007a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.pNext = NULL;
3008a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.flags = 0;
3009a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.dpy = demo->display;
3010a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.window = demo->xlib_window;
3011da44dfef7703f795e9de97fe6bda17b68864bc24Ian Elliott
3012a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        err = vkCreateXlibSurfaceKHR(demo->inst, &createInfo, NULL,
3013a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour                                     &demo->surface);
301471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
3015a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    }
3016a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    else {
30174bd81e481fdac06ba3af343dd29bae841d6fff82Tobin Ehlis#if defined(VK_USE_PLATFORM_XCB_KHR)
3018a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        VkXcbSurfaceCreateInfoKHR createInfo;
3019a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
3020a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.pNext = NULL;
3021a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.flags = 0;
3022a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.connection = demo->connection;
3023a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        createInfo.window = demo->xcb_window;
3024a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
3025a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        err = vkCreateXcbSurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface);
302671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
3027a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    }
3028a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    assert(!err);
3029e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
3030d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    // Iterate over each queue to learn whether it supports presenting:
3031481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    VkBool32 *supportsPresent =
303237a5db39edf36de91652ded72b88d33eec9db3deTony Barbour        (VkBool32 *)malloc(demo->queue_family_count * sizeof(VkBool32));
303337a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    for (i = 0; i < demo->queue_family_count; i++) {
3034481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        demo->fpGetPhysicalDeviceSurfaceSupportKHR(demo->gpu, i, demo->surface,
3035e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                                                   &supportsPresent[i]);
3036f316806ced61ba68efb7be2335bd1d1138e5234dCourtney Goeltzenleuchter    }
3037e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
3038e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Search for a graphics and a present queue in the array of queue
3039e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // families, try to find one that supports both
304037a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    uint32_t graphicsQueueFamilyIndex = UINT32_MAX;
304137a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    uint32_t presentQueueFamilyIndex = UINT32_MAX;
304237a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    for (i = 0; i < demo->queue_family_count; i++) {
304337a5db39edf36de91652ded72b88d33eec9db3deTony Barbour        if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
304437a5db39edf36de91652ded72b88d33eec9db3deTony Barbour            if (graphicsQueueFamilyIndex == UINT32_MAX) {
304537a5db39edf36de91652ded72b88d33eec9db3deTony Barbour                graphicsQueueFamilyIndex = i;
304637a5db39edf36de91652ded72b88d33eec9db3deTony Barbour            }
304737a5db39edf36de91652ded72b88d33eec9db3deTony Barbour
304837a5db39edf36de91652ded72b88d33eec9db3deTony Barbour            if (supportsPresent[i] == VK_TRUE) {
304937a5db39edf36de91652ded72b88d33eec9db3deTony Barbour                graphicsQueueFamilyIndex = i;
305037a5db39edf36de91652ded72b88d33eec9db3deTony Barbour                presentQueueFamilyIndex = i;
305137a5db39edf36de91652ded72b88d33eec9db3deTony Barbour                break;
305237a5db39edf36de91652ded72b88d33eec9db3deTony Barbour            }
3053e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        }
305437a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    }
3055755151776f6b9a0ab34095b980819e4318a86529Tony Barbour
305637a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    if (presentQueueFamilyIndex == UINT32_MAX) {
305737a5db39edf36de91652ded72b88d33eec9db3deTony Barbour        // If didn't find a queue that supports both graphics and present, then
305837a5db39edf36de91652ded72b88d33eec9db3deTony Barbour        // find a separate present queue.
30595f19ded8618f826c44367cfc9bd17a6010e71cf0Mark Lobodzinski        for (i = 0; i < demo->queue_family_count; ++i) {
306037a5db39edf36de91652ded72b88d33eec9db3deTony Barbour            if (supportsPresent[i] == VK_TRUE) {
306137a5db39edf36de91652ded72b88d33eec9db3deTony Barbour                presentQueueFamilyIndex = i;
306237a5db39edf36de91652ded72b88d33eec9db3deTony Barbour                break;
306337a5db39edf36de91652ded72b88d33eec9db3deTony Barbour            }
3064e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        }
3065e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
3066e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
3067e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Generate error if could not find both a graphics and a present queue
306837a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    if (graphicsQueueFamilyIndex == UINT32_MAX ||
306937a5db39edf36de91652ded72b88d33eec9db3deTony Barbour        presentQueueFamilyIndex == UINT32_MAX) {
3070755151776f6b9a0ab34095b980819e4318a86529Tony Barbour        ERR_EXIT("Could not find both graphics and present queues\n",
3071d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour                 "Swapchain Initialization Failure");
3072e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
3073e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
307437a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    demo->graphics_queue_family_index = graphicsQueueFamilyIndex;
307537a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    demo->present_queue_family_index = presentQueueFamilyIndex;
30761ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    demo->separate_present_queue =
30771ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        (demo->graphics_queue_family_index != demo->present_queue_family_index);
307837a5db39edf36de91652ded72b88d33eec9db3deTony Barbour    free(supportsPresent);
3079f316806ced61ba68efb7be2335bd1d1138e5234dCourtney Goeltzenleuchter
30803d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    demo_create_device(demo);
30813d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour
30823d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_DEVICE_PROC_ADDR(demo->device, CreateSwapchainKHR);
30833d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_DEVICE_PROC_ADDR(demo->device, DestroySwapchainKHR);
30843d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_DEVICE_PROC_ADDR(demo->device, GetSwapchainImagesKHR);
30853d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_DEVICE_PROC_ADDR(demo->device, AcquireNextImageKHR);
30863d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour    GET_DEVICE_PROC_ADDR(demo->device, QueuePresentKHR);
30873d03a4a1c4f3b90cb2923f1f0a1aacdf91d9692eTony Barbour
3088755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    vkGetDeviceQueue(demo->device, demo->graphics_queue_family_index, 0,
3089755151776f6b9a0ab34095b980819e4318a86529Tony Barbour                     &demo->graphics_queue);
3090755151776f6b9a0ab34095b980819e4318a86529Tony Barbour
30911ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    if (!demo->separate_present_queue) {
3092755151776f6b9a0ab34095b980819e4318a86529Tony Barbour        demo->present_queue = demo->graphics_queue;
3093755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    } else {
3094755151776f6b9a0ab34095b980819e4318a86529Tony Barbour        vkGetDeviceQueue(demo->device, demo->present_queue_family_index, 0,
3095755151776f6b9a0ab34095b980819e4318a86529Tony Barbour                         &demo->present_queue);
3096755151776f6b9a0ab34095b980819e4318a86529Tony Barbour    }
30975685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
3098e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Get the list of VkFormat's that are supported:
30997fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    uint32_t formatCount;
3100481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = demo->fpGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface,
31018d2a2eb5eff6a7c53a9239017d8327020467fbb6Ian Elliott                                                     &formatCount, NULL);
3102e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
3103338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkSurfaceFormatKHR *surfFormats =
3104338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
3105481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    err = demo->fpGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface,
31068d2a2eb5eff6a7c53a9239017d8327020467fbb6Ian Elliott                                                     &formatCount, surfFormats);
3107e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
3108e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
3109e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // the surface has no preferred format.  Otherwise, at least one
3110e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // supported format will be returned.
3111481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) {
3112e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        demo->format = VK_FORMAT_B8G8R8A8_UNORM;
3113481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    } else {
3114e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        assert(formatCount >= 1);
3115e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        demo->format = surfFormats[0].format;
3116e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
31177fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    demo->color_space = surfFormats[0].colorSpace;
311832536f966d1b2d9034a467b36e398545ef54e9d1Ian Elliott
3119eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    demo->quit = false;
3120eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    demo->curFrame = 0;
3121723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski
3122a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    // Create semaphores to synchronize acquiring presentable buffers before
3123a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    // rendering and waiting for drawing to be complete before presenting
3124a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    VkSemaphoreCreateInfo semaphoreCreateInfo = {
3125a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3126a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour        .pNext = NULL,
3127a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour        .flags = 0,
3128a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour    };
3129a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour
31306b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    // Create fences that we can use to throttle if we get too far
31316b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    // ahead of the image presents
31326b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    VkFenceCreateInfo fence_ci = {
31336b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
31346b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        .pNext = NULL,
3135ed0cd2f95c18b3d3f267c45b149ba435b7d3a0eeszdarkhack        .flags = VK_FENCE_CREATE_SIGNALED_BIT
31366b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    };
31376b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    for (uint32_t i = 0; i < FRAME_LAG; i++) {
31386b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        vkCreateFence(demo->device, &fence_ci, NULL, &demo->fences[i]);
31396b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, NULL,
31406b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour                                &demo->image_acquired_semaphores[i]);
31416b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        assert(!err);
3142a2a90bea4b1cf8d45e5f9ca4caeb759ccc02fdfeTony Barbour
31431ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, NULL,
31446b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour                                &demo->draw_complete_semaphores[i]);
31451ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour        assert(!err);
31466b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour
31476b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        if (demo->separate_present_queue) {
31486b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour            err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, NULL,
31496b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour                                    &demo->image_ownership_semaphores[i]);
31506b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour            assert(!err);
31516b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour        }
31521ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour    }
31536b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    demo->frame_index = 0;
31541ba48968162b1c49e5708d5ef4ef01a4786baa09Tony Barbour
3155723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    // Get Memory information and properties
315601d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_properties);
31574e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
31584e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3159a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#if defined(VK_USE_PLATFORM_WAYLAND_KHR) && !defined(VK_USE_PLATFORM_XCB_KHR)
3160a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic void registry_handle_global(void *data, struct wl_registry *registry,
3161a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                                   uint32_t name, const char *interface,
3162a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                                   uint32_t version UNUSED) {
3163a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    struct demo *demo = data;
3164a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    if (strcmp(interface, "wl_compositor") == 0) {
3165a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        demo->compositor =
3166a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong            wl_registry_bind(registry, name, &wl_compositor_interface, 3);
3167a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        /* Todo: When xdg_shell protocol has stablized, we should move wl_shell
3168a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong         * tp xdg_shell */
3169a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    } else if (strcmp(interface, "wl_shell") == 0) {
3170a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        demo->shell = wl_registry_bind(registry, name, &wl_shell_interface, 1);
3171a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    }
3172a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong}
3173a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
3174a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic void registry_handle_global_remove(void *data UNUSED,
3175a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                                          struct wl_registry *registry UNUSED,
3176a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong                                          uint32_t name UNUSED) {}
3177a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
3178a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeongstatic const struct wl_registry_listener registry_listener = {
3179a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    registry_handle_global, registry_handle_global_remove};
3180a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#endif
3181a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
3182481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_init_connection(struct demo *demo) {
318371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#if defined(VK_USE_PLATFORM_XCB_KHR)
31844e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    const xcb_setup_t *setup;
31854e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_screen_iterator_t iter;
31864e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    int scr;
31874e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
31884e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo->connection = xcb_connect(NULL, &scr);
31890c9d488562f4b6c16806bbd182c6e7181c18da3eLenny Komow    if (xcb_connection_has_error(demo->connection) > 0) {
3190dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott        printf("Cannot find a compatible Vulkan installable client driver "
3191dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott               "(ICD).\nExiting ...\n");
3192dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott        fflush(stdout);
3193dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott        exit(1);
3194dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott    }
31954e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
31964e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    setup = xcb_get_setup(demo->connection);
31974e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    iter = xcb_setup_roots_iterator(setup);
31984e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    while (scr-- > 0)
31994e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        xcb_screen_next(&iter);
32004e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
32014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo->screen = iter.data;
3202a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
3203a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    demo->display = wl_display_connect(NULL);
3204a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
3205a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    if (demo->display == NULL) {
3206a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        printf("Cannot find a compatible Vulkan installable client driver "
3207a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong               "(ICD).\nExiting ...\n");
3208a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        fflush(stdout);
3209a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong        exit(1);
3210a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    }
3211a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong
3212a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    demo->registry = wl_display_get_registry(demo->display);
3213a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_registry_add_listener(demo->registry, &registry_listener, demo);
3214a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    wl_display_dispatch(demo->display);
321571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
32164e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
32174e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3218481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzstatic void demo_init(struct demo *demo, int argc, char **argv) {
32193eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    vec3 eye = {0.0f, 3.0f, 5.0f};
32203eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    vec3 origin = {0, 0, 0};
3221c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    vec3 up = {0.0f, 1.0f, 0.0};
32223eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
32234e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(demo, 0, sizeof(*demo));
3224a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    demo->frameCount = INT32_MAX;
32254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3226886be472ea5f6fc366d2e20156396e17d0947816Piers Daniell    for (int i = 1; i < argc; i++) {
32275685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        if (strcmp(argv[i], "--use_staging") == 0) {
322840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            demo->use_staging_buffer = true;
32295685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour            continue;
3230e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        }
32313230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        if (strcmp(argv[i], "--break") == 0) {
32323230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter            demo->use_break = true;
32333230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter            continue;
32343230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        }
32355685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        if (strcmp(argv[i], "--validate") == 0) {
32365685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour            demo->validate = true;
32375685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour            continue;
32385685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        }
32394b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#if defined(VK_USE_PLATFORM_XLIB_KHR)
3240a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        if (strcmp(argv[i], "--xlib") == 0) {
3241a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            demo->use_xlib = true;
3242a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour            continue;
3243a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        }
32444b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#endif
3245481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if (strcmp(argv[i], "--c") == 0 && demo->frameCount == INT32_MAX &&
3246481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            i < argc - 1 && sscanf(argv[i + 1], "%d", &demo->frameCount) == 1 &&
3247481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            demo->frameCount >= 0) {
3248eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            i++;
3249eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            continue;
3250eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        }
325120a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        if (strcmp(argv[i], "--suppress_popups") == 0) {
325220a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg            demo->suppress_popups = true;
325320a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg            continue;
325420a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg        }
32555685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
325681fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop#if defined(ANDROID)
325781fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop        ERR_EXIT("Usage: cube [--validate]\n", "Usage");
325881fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop#else
3259481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        fprintf(stderr, "Usage:\n  %s [--use_staging] [--validate] [--break] "
32604b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#if defined(VK_USE_PLATFORM_XLIB_KHR)
32614b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour                        "[--xlib] "
32624b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#endif
326320a497b97273bbbc0f853f12c0cf6db57a2aef9dlenny-lunarg                        "[--c <framecount>] [--suppress_popups]\n",
3264481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                APP_SHORT_NAME);
3265e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        fflush(stderr);
3266e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        exit(1);
326781fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop#endif
326840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    }
326940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
3270a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    if (!demo->use_xlib)
3271a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        demo_init_connection(demo);
3272a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
32739cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    demo_init_vk(demo);
32744e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
32753eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo->width = 500;
32763eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo->height = 500;
32773eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
32786b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    demo->spin_angle = 4.0f;
32796b7e78663bec13ba8e66568a47a111f6adf592cdTony Barbour    demo->spin_increment = 0.2f;
32803eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo->pause = false;
32813eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
3282481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    mat4x4_perspective(demo->projection_matrix, (float)degreesToRadians(45.0f),
3283481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                       1.0f, 0.1f, 100.0f);
32843eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    mat4x4_look_at(demo->view_matrix, eye, origin, up);
32853eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    mat4x4_identity(demo->model_matrix);
3286d0b68068c4002b26e53e22aabce93c6948d0b507Rene Lindsay
3287d0b68068c4002b26e53e22aabce93c6948d0b507Rene Lindsay    demo->projection_matrix[1][1]*=-1;  //Flip projection matrix from GL to Vulkan orientation.
32884e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
32894e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
329071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#if defined(VK_USE_PLATFORM_WIN32_KHR)
3291cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark// Include header required for parsing the command line options.
3292cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark#include <shellapi.h>
32937595eeeb9f9d0b0568df04e19c442ed22f7d7b5fIan Elliott
3294481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine,
3295481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                   int nCmdShow) {
3296481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    MSG msg;   // message
3297481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    bool done; // flag saying when app is complete
32985685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    int argc;
3299481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    char **argv;
3300481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz
3301481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // Use the CommandLine functions to get the command line arguments.
3302481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // Unfortunately, Microsoft outputs
3303481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // this information as wide characters for Unicode, and we simply want the
3304481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // Ascii version to be compatible
3305481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // with the non-Windows side.  So, we have to convert the information to
3306481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    // Ascii character strings.
3307481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    LPWSTR *commandLineArgs = CommandLineToArgvW(GetCommandLineW(), &argc);
3308481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    if (NULL == commandLineArgs) {
3309cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark        argc = 0;
3310cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark    }
3311cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark
3312481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    if (argc > 0) {
3313481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        argv = (char **)malloc(sizeof(char *) * argc);
3314481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if (argv == NULL) {
3315cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark            argc = 0;
3316481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        } else {
3317481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            for (int iii = 0; iii < argc; iii++) {
3318481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                size_t wideCharLen = wcslen(commandLineArgs[iii]);
3319cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark                size_t numConverted = 0;
3320cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark
3321481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                argv[iii] = (char *)malloc(sizeof(char) * (wideCharLen + 1));
3322481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                if (argv[iii] != NULL) {
3323481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                    wcstombs_s(&numConverted, argv[iii], wideCharLen + 1,
3324481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz                               commandLineArgs[iii], wideCharLen + 1);
3325cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark                }
3326cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark            }
3327cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark        }
3328481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    } else {
3329cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark        argv = NULL;
3330cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark    }
33315685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
33325685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    demo_init(&demo, argc, argv);
3333cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark
3334cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark    // Free up the items we had to allocate for the command line arguments.
3335481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    if (argc > 0 && argv != NULL) {
3336481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        for (int iii = 0; iii < argc; iii++) {
3337481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            if (argv[iii] != NULL) {
3338cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark                free(argv[iii]);
3339cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark            }
3340cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark        }
3341cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark        free(argv);
3342cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark    }
3343cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark
33445685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    demo.connection = hInstance;
33455685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    strncpy(demo.name, "cube", APP_NAME_STR_LEN);
3346e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_create_window(&demo);
3347d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    demo_init_vk_swapchain(&demo);
3348e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
3349e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_prepare(&demo);
3350e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
3351481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    done = false; // initialize loop condition variable
3352cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark
3353cbd7c6be558f81a398521400e7c4991e2f2da129Mark Young <Mark    // main message loop
3354481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    while (!done) {
3355421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott        PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
3356481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        if (msg.message == WM_QUIT) // check for a quit message
3357e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        {
3358481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            done = true; // if found, quit app
3359481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz        } else {
3360e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott            /* Translate and dispatch to event queue*/
3361481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz            TranslateMessage(&msg);
3362e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott            DispatchMessage(&msg);
3363e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        }
336418b53e792aad08d1d95210c372e1326bb952ef9aTony Barbour        RedrawWindow(demo.window, NULL, NULL, RDW_INTERNALPAINT);
3365e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    }
3366e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
3367e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_cleanup(&demo);
3368e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
3369481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultz    return (int)msg.wParam;
3370e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott}
337171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
337271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#include <android/log.h>
337371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#include <android_native_app_glue.h>
337448a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop#include "android_util.h"
337548a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop
337671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentinestatic bool initialized = false;
337771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentinestatic bool active = false;
337871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentinestruct demo demo;
337971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
338071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentinestatic int32_t processInput(struct android_app* app, AInputEvent* event) {
338171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    return 0;
338271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine}
338371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
338471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentinestatic void processCommand(struct android_app* app, int32_t cmd) {
338571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    switch(cmd) {
338671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        case APP_CMD_INIT_WINDOW: {
338771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            if (app->window) {
3388815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // We're getting a new window.  If the app is starting up, we
3389815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // need to initialize.  If the app has already been
3390815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // initialized, that means that we lost our previous window,
3391815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // which means that we have a lot of work to do.  At a minimum,
3392815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // we need to destroy the swapchain and surface associated with
3393815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // the old window, and create a new surface and swapchain.
3394815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // However, since there are a lot of other objects/state that
3395815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // is tied to the swapchain, it's easiest to simply cleanup and
3396815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // start over (i.e. use a brute-force approach of re-starting
3397815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                // the app)
3398815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                if (demo.prepared) {
3399815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                    demo_cleanup(&demo);
3400815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott                }
340148a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop
340248a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                // Parse Intents into argc, argv
340348a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                // Use the following key to send arguments, i.e.
340448a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                // --es args "--validate"
340548a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                const char key[] = "args";
340681fddbbf55ec04a4355c99434784d8f6764d0787Cody Northrop                char* appTag = (char*) APP_SHORT_NAME;
340748a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                int argc = 0;
340848a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                char** argv = get_args(app, key, appTag, &argc);
340948a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop
341048a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                __android_log_print(ANDROID_LOG_INFO, appTag, "argc = %i", argc);
341148a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                for (int i = 0; i < argc; i++)
341248a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                    __android_log_print(ANDROID_LOG_INFO, appTag, "argv[%i] = %s", i, argv[i]);
341348a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop
341448a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                demo_init(&demo, argc, argv);
341548a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop
341648a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                // Free the argv malloc'd by get_args
341748a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                for (int i = 0; i < argc; i++)
341848a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop                    free(argv[i]);
341948a557e62b3516f4c02d6ca9af31139a98dfa649Cody Northrop
342071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                demo.window = (void*)app->window;
342171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                demo_init_vk_swapchain(&demo);
342271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                demo_prepare(&demo);
342371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                initialized = true;
342471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            }
342571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            break;
342671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        }
342771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        case APP_CMD_GAINED_FOCUS: {
342871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            active = true;
342971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            break;
343071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        }
343171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        case APP_CMD_LOST_FOCUS: {
343271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            active = false;
343371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            break;
343471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        }
343571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    }
343671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine}
343771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
343871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentinevoid android_main(struct android_app *app)
343971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine{
344071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    app_dummy();
344171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
3442e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop#ifdef ANDROID
3443e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop    int vulkanSupport = InitVulkan();
3444e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop    if (vulkanSupport == 0)
3445e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop        return;
3446e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop#endif
3447e4c5dafc896460806200e46bb8d1e9ee899796c2Cody Northrop
3448815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott    demo.prepared = false;
3449815e2a9d4a27f5d831d8e97659fe7094f2e5fc1cIan Elliott
345071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    app->onAppCmd = processCommand;
345171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    app->onInputEvent = processInput;
345271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
345371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    while(1) {
345471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        int events;
345571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        struct android_poll_source* source;
345671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        while (ALooper_pollAll(active ? 0 : -1, NULL, &events, (void**)&source) >= 0) {
345771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            if (source) {
345871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                source->process(app, source);
345971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            }
346071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
346171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            if (app->destroyRequested != 0) {
346271ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                demo_cleanup(&demo);
346371ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine                return;
346471ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            }
346571ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        }
346671ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        if (initialized && active) {
346771ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine            demo_run(&demo);
346871ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine        }
346971ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine    }
347071ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine
347171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine}
34724bd81e481fdac06ba3af343dd29bae841d6fff82Tobin Ehlis#else
3473481756e168555e1bf150d3b8f1b81edca1d98c43Karl Schultzint main(int argc, char **argv) {
34744e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    struct demo demo;
34754e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
347640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    demo_init(&demo, argc, argv);
34774b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#if defined(VK_USE_PLATFORM_XLIB_KHR) && defined(VK_USE_PLATFORM_XCB_KHR)
3478a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    if (demo.use_xlib)
3479a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        demo_create_xlib_window(&demo);
3480a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    else
3481a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        demo_create_xcb_window(&demo);
34824b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#elif defined(VK_USE_PLATFORM_XCB_KHR)
34834b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour    demo_create_xcb_window(&demo);
34844b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#elif defined(VK_USE_PLATFORM_XLIB_KHR)
34854b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour    demo_create_xlib_window(&demo);
3486a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
3487a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    demo_create_window(&demo);
3488a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#endif
3489a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
3490d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    demo_init_vk_swapchain(&demo);
34914e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
34924e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare(&demo);
3493a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour
34944b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#if defined(VK_USE_PLATFORM_XLIB_KHR) && defined(VK_USE_PLATFORM_XCB_KHR)
3495a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    if (demo.use_xlib)
3496a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        demo_run_xlib(&demo);
3497a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour    else
3498a24c4b45fb177077f8f54cd3ea5866e248f68e4fTony Barbour        demo_run_xcb(&demo);
34994b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#elif defined(VK_USE_PLATFORM_XCB_KHR)
35004b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour    demo_run_xcb(&demo);
35014b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour#elif defined(VK_USE_PLATFORM_XLIB_KHR)
35024b6ebbc03cd137b6e7edc667755c4d9c68dcfef8Tony Barbour    demo_run_xlib(&demo);
3503a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
3504a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong    demo_run(&demo);
3505a7aac33cb2cf14e75f6c9c7f6651f0085174f817Mun Gwan-gyeong#endif
35064e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
35074e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_cleanup(&demo);
35084e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
350951940e40346835ebbf3a3fb8c06c07a3eb518e7bKarl Schultz    return validation_error;
35104e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
351171ed0bbee1985e6fe3c47e043bc1f66cc59b437bMichael Lentine#endif
3512