cube.c revision 01d2ae18f05184e04eb29a2ab30480f8d4660d25
1421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott/*
2421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * Vulkan
3421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott *
4421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * Copyright (C) 2014-2015 LunarG, Inc.
5421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott *
6421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * Permission is hereby granted, free of charge, to any person obtaining a
7421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * copy of this software and associated documentation files (the "Software"),
8421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * to deal in the Software without restriction, including without limitation
9421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * and/or sell copies of the Software, and to permit persons to whom the
11421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * Software is furnished to do so, subject to the following conditions:
12421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott *
13421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * The above copyright notice and this permission notice shall be included
14421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * in all copies or substantial portions of the Software.
15421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott *
16421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott * DEALINGS IN THE SOFTWARE.
23421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott */
241722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter#define _GNU_SOURCE
254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <stdio.h>
264e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <stdlib.h>
274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <string.h>
284e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <stdbool.h>
294e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <assert.h>
304e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
31e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#ifdef _WIN32
32e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#pragma comment(linker, "/subsystem:windows")
33e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#include <windows.h>
34e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#define APP_NAME_STR_LEN 80
35e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#else  // _WIN32
364e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#include <xcb/xcb.h>
37e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#endif // _WIN32
38e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
399cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter#include <vulkan.h>
40338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott#include <vk_ext_khr_swapchain.h>
41338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott#include <vk_ext_khr_device_swapchain.h>
421c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter#include "vk_debug_report_lunarg.h"
434e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
44d4e020aa1921643b14a3a546f6807afbafa7629eCody Northrop#include "icd-spv.h"
454e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
46eccbb37d3e11632ca38f587c01c056fe52dbd7b9Mark Lobodzinski#include "vk_sdk_platform.h"
476f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter#include "linmath.h"
486f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
494e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#define DEMO_TEXTURE_COUNT 1
504e19ed0ed322e45993bac7917a1a253dbaaf88f9Ian Elliott#define APP_SHORT_NAME "cube"
514e19ed0ed322e45993bac7917a1a253dbaaf88f9Ian Elliott#define APP_LONG_NAME "The Vulkan Cube Demo Program"
524e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
538c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
548c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
5522a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#if defined(NDEBUG) && defined(__GNUC__)
5622a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#define U_ASSERT_ONLY __attribute__((unused))
5722a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#else
5822a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#define U_ASSERT_ONLY
5922a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour#endif
6022a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour
61caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott#ifdef _WIN32
62caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott#define ERR_EXIT(err_msg, err_class)                    \
63caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott    do {                                                \
64caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott        MessageBox(NULL, err_msg, err_class, MB_OK);    \
65caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott        exit(1);                                        \
66caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott   } while (0)
67caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott
68caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott#else  // _WIN32
69caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott
70caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott#define ERR_EXIT(err_msg, err_class)                    \
71caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott    do {                                                \
72caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott        printf(err_msg);                                \
73caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott        fflush(stdout);                                 \
74caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott        exit(1);                                        \
75caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott   } while (0)
76caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott#endif // _WIN32
77caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott
78e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott#define GET_INSTANCE_PROC_ADDR(inst, entrypoint)                        \
79e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott{                                                                       \
80e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
81e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    if (demo->fp##entrypoint == NULL) {                                 \
82e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint,  \
83e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                 "vkGetInstanceProcAddr Failure");                      \
84e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }                                                                   \
85e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott}
86e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
87ccfa841bf1082aa33479ab7691c3042bf57b9c4bJon Ashburnstatic PFN_vkGetDeviceProcAddr g_gdpa = NULL;
88ccfa841bf1082aa33479ab7691c3042bf57b9c4bJon Ashburn
891b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott#define GET_DEVICE_PROC_ADDR(dev, entrypoint)                           \
901b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott{                                                                       \
91ccfa841bf1082aa33479ab7691c3042bf57b9c4bJon Ashburn    if(!g_gdpa)                                                         \
92ccfa841bf1082aa33479ab7691c3042bf57b9c4bJon Ashburn       g_gdpa = (PFN_vkGetDeviceProcAddr) vkGetInstanceProcAddr(demo->inst, "vkGetDeviceProcAddr"); \
93ccfa841bf1082aa33479ab7691c3042bf57b9c4bJon Ashburn    demo->fp##entrypoint = (PFN_vk##entrypoint) g_gdpa(dev, "vk"#entrypoint);   \
941b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott    if (demo->fp##entrypoint == NULL) {                                 \
951b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott        ERR_EXIT("vkGetDeviceProcAddr failed to find vk"#entrypoint,    \
961b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott                 "vkGetDeviceProcAddr Failure");                        \
971b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott    }                                                                   \
981b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott}
991b6de09a29e07051d5d097fdb7879f6909ec2d77Ian Elliott
1007e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter/*
10140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter * structure to track all objects related to a texture.
10240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter */
103bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchterstruct texture_object {
104382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkSampler sampler;
10540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
106382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImage image;
107382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImageLayout imageLayout;
108bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
109e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    VkMemoryAllocInfo mem_alloc;
1102318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    VkDeviceMemory mem;
111382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImageView view;
11240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    int32_t tex_width, tex_height;
11340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter};
11440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1151722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchterstatic char *tex_files[] = {
116a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    "lunarg.ppm"
1171722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter};
1181722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
1199cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchterstruct vkcube_vs_uniform {
120e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    // Must start with MVP
121e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float       mvp[4][4];
122e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float       position[12*3][4];
123e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float       color[12*3][4];
124e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
125e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1269cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchterstruct vktexcube_vs_uniform {
127e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    // Must start with MVP
128e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float       mvp[4][4];
129e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float       position[12*3][4];
130e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float       attr[12*3][4];
131e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
1326f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
1334e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter//--------------------------------------------------------------------------------------
1344e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter// Mesh and VertexFormat Data
1354e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter//--------------------------------------------------------------------------------------
1364e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstruct Vertex
1374e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
138e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float     posX, posY, posZ, posW;    // Position data
139e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float     r, g, b, a;                // Color
1404e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter};
1414e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
142e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchterstruct VertexPosTex
143e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter{
144e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float     posX, posY, posZ, posW;    // Position data
145e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float     u, v, s, t;                // Texcoord
146e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
147e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1484e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter#define XYZ1(_x_, _y_, _z_)         (_x_), (_y_), (_z_), 1.f
149e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter#define UV(_u_, _v_)                (_u_), (_v_), 0.f, 1.f
1504e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
151e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinskistatic const float g_vertex_buffer_data[] = {
152c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,  // -X side
1531722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f,-1.0f, 1.0f,
1541722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f, 1.0f, 1.0f,
155c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f, 1.0f, 1.0f,
1561722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f, 1.0f,-1.0f,
1571722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f,-1.0f,-1.0f,
1581722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
159c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,  // -Z side
1601722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f,-1.0f,
1611722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f,-1.0f,
162c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,
1631722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f, 1.0f,-1.0f,
164ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan     1.0f, 1.0f,-1.0f,
1651722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
166c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,  // -Y side
1671722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f,-1.0f,
168ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan     1.0f,-1.0f, 1.0f,
169c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f,-1.0f,
1701722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f, 1.0f,
171ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    -1.0f,-1.0f, 1.0f,
1721722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
173c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f, 1.0f,-1.0f,  // +Y side
1741722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f, 1.0f, 1.0f,
1751722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f, 1.0f,
176c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f, 1.0f,-1.0f,
1771722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f, 1.0f,
178ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan     1.0f, 1.0f,-1.0f,
1791722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
180c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu     1.0f, 1.0f,-1.0f,  // +X side
1811722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f, 1.0f,
1821722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f, 1.0f,
183c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu     1.0f,-1.0f, 1.0f,
1841722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f,-1.0f,
1851722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f,-1.0f,
1861722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
187c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f, 1.0f, 1.0f,  // +Z side
1881722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    -1.0f,-1.0f, 1.0f,
189ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan     1.0f, 1.0f, 1.0f,
190c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    -1.0f,-1.0f, 1.0f,
1911722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f,-1.0f, 1.0f,
1921722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter     1.0f, 1.0f, 1.0f,
193e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
194e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
195e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinskistatic const float g_uv_buffer_data[] = {
196c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,  // -X side
1971722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    1.0f, 0.0f,
1983eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    1.0f, 1.0f,
199ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    1.0f, 1.0f,
200c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 1.0f,
2011722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    0.0f, 0.0f,
2021722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
203c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 0.0f,  // -Z side
204c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 1.0f,
205c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
2061722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    1.0f, 0.0f,
207ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    1.0f, 1.0f,
208c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 1.0f,
2091722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
210c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,  // -Y side
2111722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    1.0f, 0.0f,
212ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    0.0f, 0.0f,
2131722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    1.0f, 1.0f,
2143eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    0.0f, 0.0f,
2151722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    0.0f, 1.0f,
2161722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
217c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,  // +Y side
218c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 1.0f,
219c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
220c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,
221c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
2221722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter    1.0f, 0.0f,
223c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu
224c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,  // +X side
225ea3945cf2368b89cb47346576a7bc18435090348Mike Stroyan    0.0f, 1.0f,
226c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
227c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
228c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 0.0f,
229c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,
2303eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
231c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 1.0f,  // +Z side
2323eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    0.0f, 0.0f,
233c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,
234c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    0.0f, 0.0f,
235c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 0.0f,
236c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    1.0f, 1.0f,
237e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter};
238e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
239e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchtervoid dumpMatrix(const char *note, mat4x4 MVP)
240e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter{
241e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    int i;
242e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
243e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    printf("%s: \n", note);
244e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    for (i=0; i<4; i++) {
245e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        printf("%f, %f, %f, %f\n", MVP[i][0], MVP[i][1], MVP[i][2], MVP[i][3]);
246e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    }
247e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    printf("\n");
248e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    fflush(stdout);
249e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter}
250e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
251e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchtervoid dumpVec4(const char *note, vec4 vector)
252e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter{
253e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    printf("%s: \n", note);
254e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        printf("%f, %f, %f, %f\n", vector[0], vector[1], vector[2], vector[3]);
255e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    printf("\n");
256e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    fflush(stdout);
257e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter}
258e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
2590d6857f05625037c8b48ec8883f3b6cf94adee29Courtney GoeltzenleuchterVkBool32 dbgFunc(
260de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    VkFlags                             msgFlags,
261de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    VkDbgObjectType                     objType,
262de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    uint64_t                            srcObject,
2631c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    size_t                              location,
2641c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    int32_t                             msgCode,
2651c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    const char*                         pLayerPrefix,
2661c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    const char*                         pMsg,
2671c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    void*                               pUserData)
2685685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour{
2695685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    char *message = (char *) malloc(strlen(pMsg)+100);
2705685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
2715685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    assert (message);
2725685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
2731c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    if (msgFlags & VK_DBG_REPORT_ERROR_BIT) {
2741c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        sprintf(message,"ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
2751c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    } else if (msgFlags & VK_DBG_REPORT_WARN_BIT) {
276a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        // We know that we're submitting queues without fences, ignore this warning
277a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        if (strstr(pMsg, "vkQueueSubmit parameter, VkFence fence, is null pointer")){
2780d6857f05625037c8b48ec8883f3b6cf94adee29Courtney Goeltzenleuchter            return false;
279a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        }
2801c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        sprintf(message,"WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
2815685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    } else {
2820d6857f05625037c8b48ec8883f3b6cf94adee29Courtney Goeltzenleuchter        return false;
2835685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    }
2845685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
2855685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour#ifdef _WIN32
2865685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    MessageBox(NULL, message, "Alert", MB_OK);
2875685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour#else
2885685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    printf("%s\n",message);
2895685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    fflush(stdout);
2905685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour#endif
2915685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    free(message);
2920d6857f05625037c8b48ec8883f3b6cf94adee29Courtney Goeltzenleuchter
293e4c4313799b6da886ced041d1515dd8fdfc35fd1Courtney Goeltzenleuchter    /*
294e4c4313799b6da886ced041d1515dd8fdfc35fd1Courtney Goeltzenleuchter     * false indicates that layer should not bail-out of an
295e4c4313799b6da886ced041d1515dd8fdfc35fd1Courtney Goeltzenleuchter     * API call that had validation failures. This may mean that the
296e4c4313799b6da886ced041d1515dd8fdfc35fd1Courtney Goeltzenleuchter     * app dies inside the driver due to invalid parameter(s).
297e4c4313799b6da886ced041d1515dd8fdfc35fd1Courtney Goeltzenleuchter     * That's what would happen without validation layers, so we'll
298e4c4313799b6da886ced041d1515dd8fdfc35fd1Courtney Goeltzenleuchter     * keep that behavior here.
299e4c4313799b6da886ced041d1515dd8fdfc35fd1Courtney Goeltzenleuchter     */
300e4c4313799b6da886ced041d1515dd8fdfc35fd1Courtney Goeltzenleuchter    return false;
3015685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour}
3025685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
303338dedb8c82676fded0ab72e32d029292875ce71Ian Elliotttypedef struct _SwapchainBuffers {
304e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkImage image;
305e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkCmdBuffer cmd;
3061856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter    VkImageView view;
307338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott} SwapchainBuffers;
308e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
3094e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstruct demo {
310e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#ifdef _WIN32
311e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#define APP_NAME_STR_LEN 80
312e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    HINSTANCE connection;        // hInstance - Windows Instance
313e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    char name[APP_NAME_STR_LEN]; // Name to put on the window/icon
314e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    HWND        window;          // hWnd - window handle
315e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#else  // _WIN32
3164e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_connection_t *connection;
3174e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_screen_t *screen;
3185b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu    xcb_window_t window;
3195b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu    xcb_intern_atom_reply_t *atom_wm_delete_window;
320338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkPlatformHandleXcbKHR platform_handle_xcb;
3217910de721b0c167a4921a33ce2f16432243c8d43Tony Barbour#endif // _WIN32
32275db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    bool prepared;
32340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    bool use_staging_buffer;
32475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    bool use_glsl;
3254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
326382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkInstance inst;
3278205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    VkPhysicalDevice gpu;
328382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkDevice device;
329382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkQueue queue;
330f316806ced61ba68efb7be2335bd1d1138e5234dCourtney Goeltzenleuchter    uint32_t graphics_queue_node_index;
331426b90566abae5716741aade41184dc4dafe4aa4Tony Barbour    VkPhysicalDeviceProperties gpu_props;
332ef72e2a7cf4fa5708fdbfbc1c972a24ad0dbf809Cody Northrop    VkQueueFamilyProperties *queue_props;
333723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    VkPhysicalDeviceMemoryProperties memory_properties;
3344e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3354e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    int width, height;
336382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkFormat format;
337338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkColorSpaceKHR color_space;
338338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott
339338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR;
340338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkGetSurfacePropertiesKHR fpGetSurfacePropertiesKHR;
341338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkGetSurfaceFormatsKHR fpGetSurfaceFormatsKHR;
342338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkGetSurfacePresentModesKHR fpGetSurfacePresentModesKHR;
343338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
344338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
345338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
346338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR;
347338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    PFN_vkQueuePresentKHR fpQueuePresentKHR;
348338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkSurfaceDescriptionWindowKHR surface_description;
349338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    uint32_t swapchainImageCount;
350338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkSwapchainKHR swap_chain;
351338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    SwapchainBuffers *buffers;
3524e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
353e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkCmdPool cmd_pool;
3544e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3554e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    struct {
356382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkFormat format;
3574e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
358382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkImage image;
359e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak        VkMemoryAllocInfo mem_alloc;
3602318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski        VkDeviceMemory mem;
3611856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        VkImageView view;
3624e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    } depth;
3634e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
364bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    struct texture_object textures[DEMO_TEXTURE_COUNT];
3654e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3664e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    struct {
367382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkBuffer buf;
368e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak        VkMemoryAllocInfo mem_alloc;
3692318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski        VkDeviceMemory mem;
3708cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu        VkDescriptorInfo desc;
3716f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    } uniform_data;
3726f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
373382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkCmdBuffer cmd;  // Buffer for initialization commands
374556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    VkPipelineLayout pipeline_layout;
375382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkDescriptorSetLayout desc_layout;
3760d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    VkPipelineCache pipelineCache;
37776cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    VkRenderPass render_pass;
378382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkPipeline pipeline;
3794e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
3806f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4 projection_matrix;
3816f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4 view_matrix;
3826f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4 model_matrix;
3836f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
384e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float spin_angle;
385e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    float spin_increment;
3863eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    bool pause;
3873eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
3889400f09d3b3369554146ce070eb49d2fea00222cTony Barbour    VkShaderModule vert_shader_module;
3899400f09d3b3369554146ce070eb49d2fea00222cTony Barbour    VkShaderModule frag_shader_module;
3909400f09d3b3369554146ce070eb49d2fea00222cTony Barbour
391382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkDescriptorPool desc_pool;
392382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkDescriptorSet desc_set;
393f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
3945aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    VkFramebuffer *framebuffers;
39576cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
3964e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    bool quit;
397eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    int32_t curFrame;
398eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    int32_t frameCount;
3995685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    bool validate;
4003230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter    bool use_break;
4011c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    PFN_vkDbgCreateMsgCallback dbgCreateMsgCallback;
402a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour    PFN_vkDbgDestroyMsgCallback dbgDestroyMsgCallback;
4033230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter    PFN_vkDbgMsgCallback dbgBreakCallback;
4041c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    VkDbgMsgCallback msg_callback;
4051c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter
406e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t current_buffer;
407b787a8eab825c09f299865b7e77ad00bc8196bbbCourtney Goeltzenleuchter    uint32_t queue_count;
4084e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter};
4094e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
410f1eceb98219334d5540106fd024d6aee9e397802Tony Barbourstatic VkResult memory_type_from_properties(struct demo *demo, uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex)
411723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski{
412723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski     // Search memtypes to find first index with those properties
413723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski     for (uint32_t i = 0; i < 32; i++) {
414723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski         if ((typeBits & 1) == 1) {
415723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski             // Type is available, does it match user properties?
416f1eceb98219334d5540106fd024d6aee9e397802Tony Barbour             if ((demo->memory_properties.memoryTypes[i].propertyFlags & requirements_mask) == requirements_mask) {
417723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski                 *typeIndex = i;
418723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski                 return VK_SUCCESS;
419723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski             }
420723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski         }
421723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski         typeBits >>= 1;
422723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski     }
423723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski     // No memory types matched, return failure
424723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski     return VK_UNSUPPORTED;
425723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski}
426723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski
427bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchterstatic void demo_flush_init_cmd(struct demo *demo)
428bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter{
42922a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
430bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
4319cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    if (demo->cmd == VK_NULL_HANDLE)
432bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        return;
433bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
4349cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkEndCommandBuffer(demo->cmd);
435bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    assert(!err);
436bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
437382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkCmdBuffer cmd_bufs[] = { demo->cmd };
438de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    VkFence nullFence = { VK_NULL_HANDLE };
439bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
440de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    err = vkQueueSubmit(demo->queue, 1, cmd_bufs, nullFence);
441bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    assert(!err);
442bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
4439cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkQueueWaitIdle(demo->queue);
444bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    assert(!err);
445bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
446de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyCommandBuffer(demo->device, demo->cmd);
4479cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    demo->cmd = VK_NULL_HANDLE;
448bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter}
449bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
450bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchterstatic void demo_set_image_layout(
451bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        struct demo *demo,
452382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkImage image,
45395b8bb3810e626be6e997a4a40e5f6cfc24ca7b0Cody Northrop        VkImageAspectFlags aspectMask,
454382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkImageLayout old_image_layout,
455382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkImageLayout new_image_layout)
456bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter{
45722a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
458bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
4599cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    if (demo->cmd == VK_NULL_HANDLE) {
460382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        const VkCmdBufferCreateInfo cmd = {
4619cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .sType = VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
462bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            .pNext = NULL,
46318ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop            .cmdPool = demo->cmd_pool,
46488eaa3bf0c7874f8b62cf35e3b649201ecc47c36Chia-I Wu            .level = VK_CMD_BUFFER_LEVEL_PRIMARY,
465bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            .flags = 0,
466bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        };
467bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
4689cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        err = vkCreateCommandBuffer(demo->device, &cmd, &demo->cmd);
469bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        assert(!err);
470bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
471382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkCmdBufferBeginInfo cmd_buf_info = {
4729cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .sType = VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
473bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            .pNext = NULL,
4748205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour            .flags = VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT |
4759cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,
47621b5b313b4e5cf190bf2a4128a7a953750d012e0Courtney Goeltzenleuchter            .renderPass = { VK_NULL_HANDLE },
47716898b0623ba827be207417b6397b3353e11e794Cody Northrop            .subpass = 0,
47821b5b313b4e5cf190bf2a4128a7a953750d012e0Courtney Goeltzenleuchter            .framebuffer = { VK_NULL_HANDLE },
479bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        };
4809cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        err = vkBeginCommandBuffer(demo->cmd, &cmd_buf_info);
481c109827920fd0991102d4979728eee74b6ac15fbTony Barbour        assert(!err);
482bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    }
483bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
484382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImageMemoryBarrier image_memory_barrier = {
4859cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
486bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .pNext = NULL,
487bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .outputMask = 0,
488bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .inputMask = 0,
489bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .oldLayout = old_image_layout,
490bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .newLayout = new_image_layout,
491bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        .image = image,
49295b8bb3810e626be6e997a4a40e5f6cfc24ca7b0Cody Northrop        .subresourceRange = { aspectMask, 0, 1, 0, 0 }
493bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    };
494bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
4959cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL) {
496bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        /* Make sure anything that was copying from this image has completed */
497ad870818fc61ad8dccc8af2c4992f15efa9c4c7fCourtney Goeltzenleuchter        image_memory_barrier.inputMask = VK_MEMORY_INPUT_TRANSFER_BIT;
498bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    }
499bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
5009cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
501bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        /* Make sure any Copy or CPU writes to image are flushed */
502a569a50e85d51b0dff1b16cfd2c64222f921b6daCourtney Goeltzenleuchter        image_memory_barrier.outputMask = VK_MEMORY_OUTPUT_HOST_WRITE_BIT | VK_MEMORY_OUTPUT_TRANSFER_BIT;
503bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    }
504bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
505382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
506bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
507c2e987e09f0a47232d337e79d301ed94abc66cb5Tony Barbour    VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
508c2e987e09f0a47232d337e79d301ed94abc66cb5Tony Barbour    VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
509bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
51082b348f920f7be3cd791979ec3dbacf349e320caCourtney Goeltzenleuchter    vkCmdPipelineBarrier(demo->cmd, src_stages, dest_stages, false, 1, (const void * const*)&pmemory_barrier);
511bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter}
512bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
513382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchterstatic void demo_draw_build_cmd(struct demo *demo, VkCmdBuffer cmd_buf)
5144e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
51576cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    const VkCmdBufferBeginInfo cmd_buf_info = {
5169cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
517e3b0f3a139301c1bb37a8ef28a64e012e70f0406Courtney Goeltzenleuchter        .pNext = NULL,
5186d4b7526a79a8360ebfe0b1a8cebc14e881d5694Courtney Goeltzenleuchter        .flags = VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT,
51921b5b313b4e5cf190bf2a4128a7a953750d012e0Courtney Goeltzenleuchter        .renderPass = { VK_NULL_HANDLE },
52016898b0623ba827be207417b6397b3353e11e794Cody Northrop        .subpass = 0,
52121b5b313b4e5cf190bf2a4128a7a953750d012e0Courtney Goeltzenleuchter        .framebuffer = { VK_NULL_HANDLE },
52253d27af0473ff748846bb39c09e335ac43f98e3dJon Ashburn    };
523c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkClearValue clear_values[2] = {
5242563a03d13cd5293bdd57b02779f3b225da6787bCody Northrop        [0] = { .color.float32 = { 0.2f, 0.2f, 0.2f, 0.2f } },
5252563a03d13cd5293bdd57b02779f3b225da6787bCody Northrop        [1] = { .depthStencil = { 1.0f, 0 } },
526c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    };
527c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkRenderPassBeginInfo rp_begin = {
528c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
529c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pNext = NULL,
53076cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        .renderPass = demo->render_pass,
53176cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        .framebuffer = demo->framebuffers[demo->current_buffer],
532c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .renderArea.offset.x = 0,
533c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .renderArea.offset.y = 0,
534c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .renderArea.extent.width = demo->width,
535c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .renderArea.extent.height = demo->height,
536c332eefa3e8b7e97ca70abd8cfaa0d4f4e1b0fc2Cody Northrop        .clearValueCount = 2,
537c332eefa3e8b7e97ca70abd8cfaa0d4f4e1b0fc2Cody Northrop        .pClearValues = clear_values,
5383325d6b8ffdef53d826177f16c84d4d8ee752c11Jon Ashburn    };
53976cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    VkResult U_ASSERT_ONLY err;
5404e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
5419cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkBeginCommandBuffer(cmd_buf, &cmd_buf_info);
5424e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
5434e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
544c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    vkCmdBeginRenderPass(cmd_buf, &rp_begin, VK_RENDER_PASS_CONTENTS_INLINE);
545c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu
5469cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS,
5474e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter                                  demo->pipeline);
548a65c463d9b2f77e47a9e33f76fa211f63b872d5eMark Lobodzinski    vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, demo->pipeline_layout,
5491a01b1dd0734eb91e2a36509dab88f5cdfb7f1e9Cody Northrop            0, 1, &demo->desc_set, 0, NULL);
5504e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
55109772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    VkViewport viewport;
55209772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    memset(&viewport, 0, sizeof(viewport));
55309772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    viewport.height = (float) demo->height;
55409772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    viewport.width = (float) demo->width;
55509772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    viewport.minDepth = (float) 0.0f;
55609772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    viewport.maxDepth = (float) 1.0f;
557932cdb54a622f4ca69a25071eecbac235b4dc16fCourtney Goeltzenleuchter    vkCmdSetViewport(cmd_buf, 1, &viewport);
55809772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter
55909772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    VkRect2D scissor;
56009772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    memset(&scissor, 0, sizeof(scissor));
56109772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    scissor.extent.width = demo->width;
56209772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    scissor.extent.height = demo->height;
56309772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    scissor.offset.x = 0;
56409772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter    scissor.offset.y = 0;
565932cdb54a622f4ca69a25071eecbac235b4dc16fCourtney Goeltzenleuchter    vkCmdSetScissor(cmd_buf, 1, &scissor);
56609772bb64bc1c6577edef89074cbd9132191f402Courtney Goeltzenleuchter
5674ff11cc681bf32052b69573eb1418173f6b0262bCourtney Goeltzenleuchter    vkCmdDraw(cmd_buf, 12 * 3, 1, 0, 0);
56888eaa3bf0c7874f8b62cf35e3b649201ecc47c36Chia-I Wu    vkCmdEndRenderPass(cmd_buf);
5694e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
57040292ae4974a229c5def76615bec623fc4abe777Tony Barbour    VkImageMemoryBarrier prePresentBarrier = {
57140292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
57240292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .pNext = NULL,
57340292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .outputMask = VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT,
57440292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .inputMask = 0,
57540292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
57640292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .newLayout = VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR,
57740292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
57840292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .destQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
57940292ae4974a229c5def76615bec623fc4abe777Tony Barbour        .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
58040292ae4974a229c5def76615bec623fc4abe777Tony Barbour    };
58140292ae4974a229c5def76615bec623fc4abe777Tony Barbour
58240292ae4974a229c5def76615bec623fc4abe777Tony Barbour    prePresentBarrier.image = demo->buffers[demo->current_buffer].image;
58340292ae4974a229c5def76615bec623fc4abe777Tony Barbour    VkImageMemoryBarrier *pmemory_barrier = &prePresentBarrier;
58440292ae4974a229c5def76615bec623fc4abe777Tony Barbour    vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
58540292ae4974a229c5def76615bec623fc4abe777Tony Barbour                         VK_FALSE, 1, (const void * const*)&pmemory_barrier);
58640292ae4974a229c5def76615bec623fc4abe777Tony Barbour
58740292ae4974a229c5def76615bec623fc4abe777Tony Barbour
5889cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkEndCommandBuffer(cmd_buf);
5894e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
5904e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
5914e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
5926f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter
5933eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchtervoid demo_update_data_buffer(struct demo *demo)
5944e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
5956f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4 MVP, Model, VP;
5966f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    int matrixSize = sizeof(MVP);
597e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint8_t *pData;
59822a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
5994e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6006f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    mat4x4_mul(VP, demo->projection_matrix, demo->view_matrix);
6014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6026f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    // Rotate 22.5 degrees around the Y axis
603e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4_dup(Model, demo->model_matrix);
604886be472ea5f6fc366d2e20156396e17d0947816Piers Daniell    mat4x4_rotate(demo->model_matrix, Model, 0.0f, 1.0f, 0.0f, (float)degreesToRadians(demo->spin_angle));
605e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4_mul(MVP, VP, demo->model_matrix);
6064e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
607e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    err = vkMapMemory(demo->device, demo->uniform_data.mem, 0, demo->uniform_data.mem_alloc.allocationSize, 0, (void **) &pData);
6086f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    assert(!err);
6094e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6106f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter    memcpy(pData, (const void*) &MVP[0][0], matrixSize);
6114e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
61267b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski    vkUnmapMemory(demo->device, demo->uniform_data.mem);
6134e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
6144e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6154e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_draw(struct demo *demo)
6164e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
617e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkResult U_ASSERT_ONLY err;
618e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkSemaphore presentCompleteSemaphore;
619e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {
620e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
6215b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu        .pNext = NULL,
6222a25307e190c6babed79cb6cc08f7eac00e86b82Mark Lobodzinski        .flags = 0,
6234e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
624de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    VkFence nullFence = { VK_NULL_HANDLE };
6254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
626e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    err = vkCreateSemaphore(demo->device,
627e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                            &presentCompleteSemaphoreCreateInfo,
628e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                            &presentCompleteSemaphore);
629e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
630e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
631e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Get the index of the next available swapchain image:
632338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpAcquireNextImageKHR(demo->device, demo->swap_chain,
633e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                                      UINT64_MAX,
634e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                                      presentCompleteSemaphore,
635e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                                      &demo->current_buffer);
636338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
637e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // return codes
638e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
639e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
640e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Wait for the present complete semaphore to be signaled to ensure
641e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // that the image won't be rendered to until the presentation
642e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // engine has fully released ownership to the application, and it is
643e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // okay to render to the image.
644ede363628a499944723f1426c43ae8d2e7b89761Tony Barbour    err = vkQueueWaitSemaphore(demo->queue, presentCompleteSemaphore);
645ede363628a499944723f1426c43ae8d2e7b89761Tony Barbour    assert(!err);
646e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
64740292ae4974a229c5def76615bec623fc4abe777Tony Barbour    // Assume the command buffer has been run on current_buffer before so
64840292ae4974a229c5def76615bec623fc4abe777Tony Barbour    // we need to set the image layout back to COLOR_ATTACHMENT_OPTIMAL
64940292ae4974a229c5def76615bec623fc4abe777Tony Barbour    demo_set_image_layout(demo, demo->buffers[demo->current_buffer].image,
65040292ae4974a229c5def76615bec623fc4abe777Tony Barbour                           VK_IMAGE_ASPECT_COLOR_BIT,
65140292ae4974a229c5def76615bec623fc4abe777Tony Barbour                           VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR,
65240292ae4974a229c5def76615bec623fc4abe777Tony Barbour                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
65340292ae4974a229c5def76615bec623fc4abe777Tony Barbour    demo_flush_init_cmd(demo);
65440292ae4974a229c5def76615bec623fc4abe777Tony Barbour
655338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott// FIXME/TODO: DEAL WITH VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR
6569cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkQueueSubmit(demo->queue, 1, &demo->buffers[demo->current_buffer].cmd,
657de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour            nullFence);
6584e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
6594e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
660338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkPresentInfoKHR present = {
661338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
662e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        .pNext = NULL,
663338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .swapchainCount = 1,
664338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .swapchains = &demo->swap_chain,
665e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        .imageIndices = &demo->current_buffer,
666e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    };
667e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
668e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott// TBD/TODO: SHOULD THE "present" PARAMETER BE "const" IN THE HEADER?
669338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpQueuePresentKHR(demo->queue, &present);
670338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    // TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
671e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // return codes
6724e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
6734e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6745b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu    err = vkQueueWaitIdle(demo->queue);
6755b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu    assert(err == VK_SUCCESS);
676e187cc4a6c60dd598c6bbf71d95594d08771ab79Mike Stroyan
67767b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski    vkDestroySemaphore(demo->device, presentCompleteSemaphore);
6784e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
6794e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
6804e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_prepare_buffers(struct demo *demo)
6814e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
682e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    VkResult U_ASSERT_ONLY err;
683e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
684e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Check the surface properties and formats
685338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkSurfacePropertiesKHR surfProperties;
686338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpGetSurfacePropertiesKHR(demo->device,
687338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (const VkSurfaceDescriptionKHR *)&demo->surface_description,
6887fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        &surfProperties);
689e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
690e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
6917fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    uint32_t presentModeCount;
692338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpGetSurfacePresentModesKHR(demo->device,
693338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (const VkSurfaceDescriptionKHR *)&demo->surface_description,
6947fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        &presentModeCount, NULL);
695e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
696338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkPresentModeKHR *presentModes =
697338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
6987fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    assert(presentModes);
699338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpGetSurfacePresentModesKHR(demo->device,
700338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (const VkSurfaceDescriptionKHR *)&demo->surface_description,
7017fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        &presentModeCount, presentModes);
702e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
703e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
704338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkExtent2D swapchainExtent;
705e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // width and height are either both -1, or both not -1.
7067fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    if (surfProperties.currentExtent.width == -1)
707e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    {
708e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        // If the surface size is undefined, the size is set to
709e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        // the size of the images requested.
710338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        swapchainExtent.width = demo->width;
711338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        swapchainExtent.height = demo->height;
712e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
713e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    else
714e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    {
715e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        // If the surface size is defined, the swap chain size must match
716338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        swapchainExtent = surfProperties.currentExtent;
717e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
718e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
719e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // If mailbox mode is available, use it, as is the lowest-latency non-
7203fc49c2e4c6f7ab014f035195d4d706a43f97eb9Ian Elliott    // tearing mode.  If not, try IMMEDIATE which will usually be available,
7213fc49c2e4c6f7ab014f035195d4d706a43f97eb9Ian Elliott    // and is fastest (though it tears).  If not, fall back to FIFO which is
7223fc49c2e4c6f7ab014f035195d4d706a43f97eb9Ian Elliott    // always available.
723338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
724e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    for (size_t i = 0; i < presentModeCount; i++) {
725338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
726338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott            swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
727e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott            break;
728e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        }
729338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
730338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott            (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
731338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott            swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
7323fc49c2e4c6f7ab014f035195d4d706a43f97eb9Ian Elliott        }
733e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
734e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
735e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Determine the number of VkImage's to use in the swap chain (we desire to
736e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // own only 1 image at a time, besides the images being displayed and
737e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // queued for display):
738338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    uint32_t desiredNumberOfSwapchainImages = surfProperties.minImageCount + 1;
7397fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    if ((surfProperties.maxImageCount > 0) &&
740338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (desiredNumberOfSwapchainImages > surfProperties.maxImageCount))
741e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    {
742e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        // Application must settle for fewer images than desired:
743338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        desiredNumberOfSwapchainImages = surfProperties.maxImageCount;
744e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
745e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
746d161c54f8fc84e3447cb1162a3a7fd6d94ffc6ceTony Barbour    VkSurfaceTransformFlagsKHR preTransform;
747338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    if (surfProperties.supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_KHR) {
748338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        preTransform = VK_SURFACE_TRANSFORM_NONE_KHR;
749e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    } else {
7507fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        preTransform = surfProperties.currentTransform;
751e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
752e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
753338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    const VkSwapchainCreateInfoKHR swap_chain = {
754434d222a014e1ac8cf656ef8fc17faa1d224ad2fIan Elliott        .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
7555b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu        .pNext = NULL,
756338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .pSurfaceDescription = (const VkSurfaceDescriptionKHR *)&demo->surface_description,
757338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .minImageCount = desiredNumberOfSwapchainImages,
7585b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu        .imageFormat = demo->format,
7597fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        .imageColorSpace = demo->color_space,
7605b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu        .imageExtent = {
761338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott            .width = swapchainExtent.width,
762338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott            .height = swapchainExtent.height,
7634e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        },
7643b0a3ef1e1b19e015500c545627ea7fa475aae08Cody Northrop        .imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
765e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        .preTransform = preTransform,
7665b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu        .imageArraySize = 1,
7677fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
7687fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        .queueFamilyCount = 0,
7697fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott        .pQueueFamilyIndices = NULL,
770338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .presentMode = swapchainPresentMode,
771338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        .oldSwapchain.handle = 0,
772e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        .clipped = true,
77368040a41017a2e9e81a86af2d083a3079e882b96Chia-I Wu    };
774e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t i;
7754e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
776338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpCreateSwapchainKHR(demo->device, &swap_chain, &demo->swap_chain);
7775b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu    assert(!err);
7785b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu
779338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpGetSwapchainImagesKHR(demo->device, demo->swap_chain,
780338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                        &demo->swapchainImageCount, NULL);
781e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
7825b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu
783338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkImage* swapchainImages =
784338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (VkImage*)malloc(demo->swapchainImageCount * sizeof(VkImage));
785338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    assert(swapchainImages);
786338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpGetSwapchainImagesKHR(demo->device, demo->swap_chain,
787338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                        &demo->swapchainImageCount,
788338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                        swapchainImages);
789e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
790e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
791338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    demo->buffers = (SwapchainBuffers*)malloc(sizeof(SwapchainBuffers)*demo->swapchainImageCount);
792e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(demo->buffers);
793e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
794338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    for (i = 0; i < demo->swapchainImageCount; i++) {
7951856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        VkImageViewCreateInfo color_image_view = {
7961856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
7974e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .pNext = NULL,
7984e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .format = demo->format,
7991856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .channels = {
8001856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter                .r = VK_CHANNEL_SWIZZLE_R,
8011856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter                .g = VK_CHANNEL_SWIZZLE_G,
8021856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter                .b = VK_CHANNEL_SWIZZLE_B,
8031856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter                .a = VK_CHANNEL_SWIZZLE_A,
8041856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            },
8051856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .subresourceRange = {
80695b8bb3810e626be6e997a4a40e5f6cfc24ca7b0Cody Northrop                .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
8071856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter                .baseMipLevel = 0,
8081856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter                .mipLevels = 1,
8093dee8087999562e0637326175a3cf6cab858158eCourtney Goeltzenleuchter                .baseArrayLayer = 0,
8101856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter                .arraySize = 1
8111856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            },
8121856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .viewType = VK_IMAGE_VIEW_TYPE_2D,
8131856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .flags = 0,
8144e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        };
8154e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
816338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        demo->buffers[i].image = swapchainImages[i];
8174e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
81840292ae4974a229c5def76615bec623fc4abe777Tony Barbour        // Render loop will expect image to have been used before and in VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR
81940292ae4974a229c5def76615bec623fc4abe777Tony Barbour        // layout and will change to COLOR_ATTACHMENT_OPTIMAL, so init the image to that state
820bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter        demo_set_image_layout(demo, demo->buffers[i].image,
821983984fd6981293cc009bc64059fee51c1d02bafTony Barbour                               VK_IMAGE_ASPECT_COLOR_BIT,
8229cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                               VK_IMAGE_LAYOUT_UNDEFINED,
82340292ae4974a229c5def76615bec623fc4abe777Tony Barbour                               VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR);
824bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
8251856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        color_image_view.image = demo->buffers[i].image;
8264e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
8271856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        err = vkCreateImageView(demo->device,
8281856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter                &color_image_view, &demo->buffers[i].view);
8294e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        assert(!err);
8304e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
8314e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
8324e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
8334e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_prepare_depth(struct demo *demo)
8344e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
8358205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    const VkFormat depth_format = VK_FORMAT_D16_UNORM;
836382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkImageCreateInfo image = {
8379cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
8384e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .pNext = NULL,
8398205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour        .imageType = VK_IMAGE_TYPE_2D,
8404e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .format = depth_format,
8414e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .extent = { demo->width, demo->height, 1 },
8424e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .mipLevels = 1,
8434e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .arraySize = 1,
8444e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .samples = 1,
8458205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour        .tiling = VK_IMAGE_TILING_OPTIMAL,
846c3b8eea2f5e66db11651068575f4712cf195f542Courtney Goeltzenleuchter        .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
8474e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .flags = 0,
8484e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
849e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak
8501856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter    VkImageViewCreateInfo view = {
8511856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
8524e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .pNext = NULL,
853de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour        .image.handle = VK_NULL_HANDLE,
8544ab40c4acb0e4c17283a889dfe4fff9f29ff2ec3Courtney Goeltzenleuchter        .format = depth_format,
8551856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        .subresourceRange = {
85695b8bb3810e626be6e997a4a40e5f6cfc24ca7b0Cody Northrop            .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
8571856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .baseMipLevel = 0,
8581856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .mipLevels = 1,
8593dee8087999562e0637326175a3cf6cab858158eCourtney Goeltzenleuchter            .baseArrayLayer = 0,
8601856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .arraySize = 1
8611856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        },
8624e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .flags = 0,
8631856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        .viewType = VK_IMAGE_VIEW_TYPE_2D,
8644e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
865230e62505478ab0d9b05003e0e48baa5f090c6a0Mike Stroyan
8662318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    VkMemoryRequirements mem_reqs;
86722a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
8684e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
8694e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo->depth.format = depth_format;
8704e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
8714e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    /* create image */
8729cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkCreateImage(demo->device, &image,
8734e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            &demo->depth.image);
8744e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
8754e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
87601d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetImageMemoryRequirements(demo->device,
877de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour                    demo->depth.image, &mem_reqs);
878c109827920fd0991102d4979728eee74b6ac15fbTony Barbour    assert(!err);
879723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski
880e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->depth.mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
881e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->depth.mem_alloc.pNext = NULL;
882e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->depth.mem_alloc.allocationSize = mem_reqs.size;
883e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->depth.mem_alloc.memoryTypeIndex = 0;
884e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak
885723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    err = memory_type_from_properties(demo,
886723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski                                      mem_reqs.memoryTypeBits,
887f1eceb98219334d5540106fd024d6aee9e397802Tony Barbour                                      0, /* No requirements */
888e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak                                      &demo->depth.mem_alloc.memoryTypeIndex);
889723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    assert(!err);
8904e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
8912318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    /* allocate memory */
892e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    err = vkAllocMemory(demo->device, &demo->depth.mem_alloc, &demo->depth.mem);
8932318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
8942318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski
8952318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    /* bind memory */
896de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    err = vkBindImageMemory(demo->device, demo->depth.image,
8972318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski            demo->depth.mem, 0);
8982318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
8994e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
900bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    demo_set_image_layout(demo, demo->depth.image,
90195b8bb3810e626be6e997a4a40e5f6cfc24ca7b0Cody Northrop                           VK_IMAGE_ASPECT_DEPTH_BIT,
9029cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                           VK_IMAGE_LAYOUT_UNDEFINED,
9039cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                           VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
904bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
9054e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    /* create image view */
9064e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    view.image = demo->depth.image;
9071856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter    err = vkCreateImageView(demo->device, &view, &demo->depth.view);
9084e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
9094e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
9104e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
911a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour/* Load a ppm file into memory */
91240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchterbool loadTexture(const char *filename, uint8_t *rgba_data,
913382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter                 VkSubresourceLayout *layout,
914e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski                 int32_t *width, int32_t *height)
9151722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter{
916a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    FILE *fPtr = fopen(filename,"rb");
917a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    char header[256], *cPtr;
9181722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
919a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    if (!fPtr)
920a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        return false;
9211722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
922a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    cPtr = fgets(header, 256, fPtr); // P6
923a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    if (cPtr == NULL || strncmp(header, "P6\n", 3))
924a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        return false;
925a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour
926a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    do {
927a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        cPtr = fgets(header, 256, fPtr);
928a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        if (cPtr == NULL)
929a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour            return false;
930a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    } while ( !strncmp(header, "#", 1) );
931a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour
932a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    sscanf(header, "%u %u", height, width);
933a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    if (rgba_data == NULL)
934a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        return true;
935a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    fgets(header, 256, fPtr); // Format
936a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    if (cPtr == NULL || strncmp(header, "255\n", 3))
937a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        return false;
9381722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
939a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    for(int y = 0; y < *height; y++)
940a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    {
941a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        uint8_t *rowPtr = rgba_data;
942a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        for(int x = 0; x < *width; x++)
943a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        {
944a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour            fread(rowPtr, 3, 1, fPtr);
945a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour            rowPtr[3] = 255; /* Alpha of 1 */
946a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour            rowPtr += 4;
947a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        }
948a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        rgba_data += layout->rowPitch;
949a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    }
950a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    fclose(fPtr);
9511722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter  return true;
9521722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter}
9531722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
95440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchterstatic void demo_prepare_texture_image(struct demo *demo,
95540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter                                       const char *filename,
956bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter                                       struct texture_object *tex_obj,
957382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter                                       VkImageTiling tiling,
958cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter                                       VkImageUsageFlags usage,
959f1eceb98219334d5540106fd024d6aee9e397802Tony Barbour                                       VkFlags required_props)
9604e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
961de24a6fa4333020ee03b8024b4c1d12196ade31fMike Stroyan    const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM;
962e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    int32_t tex_width;
963e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    int32_t tex_height;
96422a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
96540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
96661e773861568e3cadefba8effeb4e7e12e36e6ddDavid Pinedo    if (!loadTexture(filename, NULL, NULL, &tex_width, &tex_height))
96761e773861568e3cadefba8effeb4e7e12e36e6ddDavid Pinedo    {
96861e773861568e3cadefba8effeb4e7e12e36e6ddDavid Pinedo        printf("Failed to load textures\n");
96961e773861568e3cadefba8effeb4e7e12e36e6ddDavid Pinedo        fflush(stdout);
97061e773861568e3cadefba8effeb4e7e12e36e6ddDavid Pinedo        exit(1);
97161e773861568e3cadefba8effeb4e7e12e36e6ddDavid Pinedo    }
97240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
973bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    tex_obj->tex_width = tex_width;
974bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    tex_obj->tex_height = tex_height;
97540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
976382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkImageCreateInfo image_create_info = {
9779cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
97840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .pNext = NULL,
9798205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour        .imageType = VK_IMAGE_TYPE_2D,
98040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .format = tex_format,
98140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .extent = { tex_width, tex_height, 1 },
98240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .mipLevels = 1,
98340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .arraySize = 1,
98440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .samples = 1,
98540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .tiling = tiling,
986cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter        .usage = usage,
98740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        .flags = 0,
98840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    };
98940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
9902318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    VkMemoryRequirements mem_reqs;
99140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
9929cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkCreateImage(demo->device, &image_create_info,
993bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            &tex_obj->image);
99440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    assert(!err);
99540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
99601d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetImageMemoryRequirements(demo->device, tex_obj->image, &mem_reqs);
99740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
998e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    tex_obj->mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
999e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    tex_obj->mem_alloc.pNext = NULL;
1000e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    tex_obj->mem_alloc.allocationSize = mem_reqs.size;
1001e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    tex_obj->mem_alloc.memoryTypeIndex = 0;
10022318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski
1003f1eceb98219334d5540106fd024d6aee9e397802Tony Barbour    err = memory_type_from_properties(demo, mem_reqs.memoryTypeBits, required_props, &tex_obj->mem_alloc.memoryTypeIndex);
1004723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    assert(!err);
1005723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski
10062318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    /* allocate memory */
1007e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    err = vkAllocMemory(demo->device, &tex_obj->mem_alloc,
10082318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski                &(tex_obj->mem));
10092318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
101040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
10112318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    /* bind memory */
1012de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    err = vkBindImageMemory(demo->device, tex_obj->image,
10132318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski            tex_obj->mem, 0);
10142318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
101540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1016f1eceb98219334d5540106fd024d6aee9e397802Tony Barbour    if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1017382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        const VkImageSubresource subres = {
10189cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .aspect = VK_IMAGE_ASPECT_COLOR,
101940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            .mipLevel = 0,
10203dee8087999562e0637326175a3cf6cab858158eCourtney Goeltzenleuchter            .arrayLayer = 0,
102140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        };
1022382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkSubresourceLayout layout;
102340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        void *data;
102440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
102501d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter        vkGetImageSubresourceLayout(demo->device, tex_obj->image, &subres, &layout);
102640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1027e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak        err = vkMapMemory(demo->device, tex_obj->mem, 0, tex_obj->mem_alloc.allocationSize, 0, &data);
102840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        assert(!err);
102940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
103040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        if (!loadTexture(filename, data, &layout, &tex_width, &tex_height)) {
103140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            fprintf(stderr, "Error loading texture: %s\n", filename);
103240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        }
103340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
103467b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski        vkUnmapMemory(demo->device, tex_obj->mem);
103540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    }
1036bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
10379cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1038bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    demo_set_image_layout(demo, tex_obj->image,
1039983984fd6981293cc009bc64059fee51c1d02bafTony Barbour                           VK_IMAGE_ASPECT_COLOR_BIT,
10409cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                           VK_IMAGE_LAYOUT_UNDEFINED,
1041bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter                           tex_obj->imageLayout);
1042bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    /* setting the image layout does not reference the actual memory so no need to add a mem ref */
104340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter}
104440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1045cf26e07b83fc43011e939b75f0d393a48a5628d0Mark Lobodzinskistatic void demo_destroy_texture_image(struct demo *demo, struct texture_object *tex_objs)
104640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter{
104740a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    /* clean up staging resources */
10482318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    vkFreeMemory(demo->device, tex_objs->mem);
1049de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyImage(demo->device, tex_objs->image);
105040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter}
105140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
105240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchterstatic void demo_prepare_textures(struct demo *demo)
105340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter{
10548205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    const VkFormat tex_format = VK_FORMAT_R8G8B8A8_UNORM;
1055382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkFormatProperties props;
1056e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t i;
10574e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
105801d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceFormatProperties(demo->gpu, tex_format, &props);
105940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
10604e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
106101d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter        VkResult U_ASSERT_ONLY err;
106240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1063434db6a007f7d7fade08dcf5525f91b831434c8cFslNopper        if ((props.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) && !demo->use_staging_buffer) {
106440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            /* Device can texture using linear textures */
106540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            demo_prepare_texture_image(demo, tex_files[i], &demo->textures[i],
1066cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter                                       VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
10678205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour        } else if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
106840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            /* Must use staging buffer to copy linear texture to optimized */
1069bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            struct texture_object staging_texture;
107040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
107140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            memset(&staging_texture, 0, sizeof(staging_texture));
107240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            demo_prepare_texture_image(demo, tex_files[i], &staging_texture,
1073cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter                                       VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
107440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
107540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            demo_prepare_texture_image(demo, tex_files[i], &demo->textures[i],
1076cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter                                       VK_IMAGE_TILING_OPTIMAL,
1077cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter                                       (VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
1078cb67a3299b59f9b992956d3d49181090c0cb932eCourtney Goeltzenleuchter                                       VK_MEMORY_PROPERTY_DEVICE_ONLY);
107940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1080bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            demo_set_image_layout(demo, staging_texture.image,
1081983984fd6981293cc009bc64059fee51c1d02bafTony Barbour                                   VK_IMAGE_ASPECT_COLOR_BIT,
1082bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter                                   staging_texture.imageLayout,
10839cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                                   VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL);
108440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1085bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            demo_set_image_layout(demo, demo->textures[i].image,
1086983984fd6981293cc009bc64059fee51c1d02bafTony Barbour                                   VK_IMAGE_ASPECT_COLOR_BIT,
1087bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter                                   demo->textures[i].imageLayout,
10889cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                                   VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL);
108940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1090382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter            VkImageCopy copy_region = {
10919cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                .srcSubresource = { VK_IMAGE_ASPECT_COLOR, 0, 0 },
109240a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter                .srcOffset = { 0, 0, 0 },
10939cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                .destSubresource = { VK_IMAGE_ASPECT_COLOR, 0, 0 },
109440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter                .destOffset = { 0, 0, 0 },
109540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter                .extent = { staging_texture.tex_width, staging_texture.tex_height, 1 },
109640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            };
10979cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            vkCmdCopyImage(demo->cmd,
10989cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                            staging_texture.image, VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL,
10999cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                            demo->textures[i].image, VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
110051cbf3047b0da3fce4bf797edb5bea82a3c11b3cCourtney Goeltzenleuchter                            1, &copy_region);
110140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1102bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            demo_set_image_layout(demo, demo->textures[i].image,
1103983984fd6981293cc009bc64059fee51c1d02bafTony Barbour                                   VK_IMAGE_ASPECT_COLOR_BIT,
11049cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                                   VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,
1105bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter                                   demo->textures[i].imageLayout);
110640a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1107bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter            demo_flush_init_cmd(demo);
110840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1109876629f092977a81cae0f2d483c8b6838bdd54c4Courtney Goeltzenleuchter            demo_destroy_texture_image(demo, &staging_texture);
111040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        } else {
1111de24a6fa4333020ee03b8024b4c1d12196ade31fMike Stroyan            /* Can't support VK_FORMAT_R8G8B8A8_UNORM !? */
1112de24a6fa4333020ee03b8024b4c1d12196ade31fMike Stroyan            assert(!"No support for R8G8B8A8_UNORM as texture image format");
111340a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter        }
111440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
1115382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        const VkSamplerCreateInfo sampler = {
11169cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
11174e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .pNext = NULL,
11189cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .magFilter = VK_TEX_FILTER_NEAREST,
11199cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .minFilter = VK_TEX_FILTER_NEAREST,
11208205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour            .mipMode = VK_TEX_MIPMAP_MODE_BASE,
11215162441c5e51c513e0003d904444ad563c6c79d2Courtney Goeltzenleuchter            .addressModeU = VK_TEX_ADDRESS_MODE_CLAMP,
11225162441c5e51c513e0003d904444ad563c6c79d2Courtney Goeltzenleuchter            .addressModeV = VK_TEX_ADDRESS_MODE_CLAMP,
11235162441c5e51c513e0003d904444ad563c6c79d2Courtney Goeltzenleuchter            .addressModeW = VK_TEX_ADDRESS_MODE_CLAMP,
11244e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .mipLodBias = 0.0f,
112540a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            .maxAnisotropy = 1,
11268205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour            .compareOp = VK_COMPARE_OP_NEVER,
11274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .minLod = 0.0f,
11284e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .maxLod = 0.0f,
11292c4e7c76b02d4ad0c09ff14bf9026dfcc0b9fa0cTony Barbour            .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
1130513acdfaef018860ab57d945d5df881e3d50c068Mark Lobodzinski            .unnormalizedCoordinates = VK_FALSE,
11314e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        };
11321722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
1133382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter        VkImageViewCreateInfo view = {
11349cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
11354e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            .pNext = NULL,
1136de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour            .image.handle = VK_NULL_HANDLE,
11378205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour            .viewType = VK_IMAGE_VIEW_TYPE_2D,
113840a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            .format = tex_format,
11399cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .channels = { VK_CHANNEL_SWIZZLE_R,
11409cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                          VK_CHANNEL_SWIZZLE_G,
11419cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                          VK_CHANNEL_SWIZZLE_B,
11429cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter                          VK_CHANNEL_SWIZZLE_A, },
114395b8bb3810e626be6e997a4a40e5f6cfc24ca7b0Cody Northrop            .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 },
11441856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter            .flags = 0,
11454e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        };
1146a9ae38392fd4359242fda1d2961f8347dbe970f7Jon Ashburn
11474e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        /* create sampler */
11489cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        err = vkCreateSampler(demo->device, &sampler,
11494e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter                &demo->textures[i].sampler);
11504e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        assert(!err);
11514e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
11524e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        /* create image view */
11534e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        view.image = demo->textures[i].image;
11549cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        err = vkCreateImageView(demo->device, &view,
11554e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter                &demo->textures[i].view);
11564e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        assert(!err);
11574e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
11584e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
11594e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1160e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchtervoid demo_prepare_cube_data_buffer(struct demo *demo)
1161e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter{
1162ddcb6192458d696a106f48eeb12fd0390a3ca63fCourtney Goeltzenleuchter    VkBufferCreateInfo buf_info;
11632318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    VkMemoryRequirements mem_reqs;
1164e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint8_t *pData;
1165e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    int i;
1166e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4 MVP, VP;
116722a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
11689cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    struct vktexcube_vs_uniform data;
1169e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1170e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4_mul(VP, demo->projection_matrix, demo->view_matrix);
1171e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    mat4x4_mul(MVP, VP, demo->model_matrix);
1172e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    memcpy(data.mvp, MVP, sizeof(MVP));
11733eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter//    dumpMatrix("MVP", MVP);
1174e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1175e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    for (i=0; i<12*3; i++) {
1176e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.position[i][0] = g_vertex_buffer_data[i*3];
1177e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.position[i][1] = g_vertex_buffer_data[i*3+1];
1178e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.position[i][2] = g_vertex_buffer_data[i*3+2];
1179e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.position[i][3] = 1.0f;
1180e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.attr[i][0] = g_uv_buffer_data[2*i];
1181e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.attr[i][1] = g_uv_buffer_data[2*i + 1];
1182e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.attr[i][2] = 0;
1183e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter        data.attr[i][3] = 0;
1184e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter    }
1185e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1186714df45f6733792374ad4fcb6e0fef3b47fbeb89Chia-I Wu    memset(&buf_info, 0, sizeof(buf_info));
11879cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1188ad870818fc61ad8dccc8af2c4992f15efa9c4c7fCourtney Goeltzenleuchter    buf_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
11898604939f334616555e35ef5771bd61e4a9160c88Cody Northrop    buf_info.size = sizeof(data);
11909cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkCreateBuffer(demo->device, &buf_info, &demo->uniform_data.buf);
1191714df45f6733792374ad4fcb6e0fef3b47fbeb89Chia-I Wu    assert(!err);
1192714df45f6733792374ad4fcb6e0fef3b47fbeb89Chia-I Wu
119301d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetBufferMemoryRequirements(demo->device, demo->uniform_data.buf, &mem_reqs);
1194e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1195e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->uniform_data.mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
1196e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->uniform_data.mem_alloc.pNext = NULL;
1197e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->uniform_data.mem_alloc.allocationSize = mem_reqs.size;
1198e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    demo->uniform_data.mem_alloc.memoryTypeIndex = 0;
1199e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak
1200723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    err = memory_type_from_properties(demo,
1201723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski                                      mem_reqs.memoryTypeBits,
1202723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski                                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
1203e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak                                      &demo->uniform_data.mem_alloc.memoryTypeIndex);
1204723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    assert(!err);
1205e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1206e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    err = vkAllocMemory(demo->device, &demo->uniform_data.mem_alloc, &(demo->uniform_data.mem));
12072318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
1208e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1209e82d5b6d3d359f4d24b93f1b39a97ee3ed83c39fDominik Witczak    err = vkMapMemory(demo->device, demo->uniform_data.mem, 0, demo->uniform_data.mem_alloc.allocationSize, 0, (void **) &pData);
12102318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
1211e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
12122318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    memcpy(pData, &data, sizeof data);
1213c6ae13d46c9c8a6651bf3809e2a12c69dda8a428Jon Ashburn
121467b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski    vkUnmapMemory(demo->device, demo->uniform_data.mem);
12152318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski
1216de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    err = vkBindBufferMemory(demo->device,
1217de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour            demo->uniform_data.buf,
12182318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski            demo->uniform_data.mem, 0);
12192318261dc2f6199f031ba9b815730ee5d649d57bMark Lobodzinski    assert(!err);
1220714df45f6733792374ad4fcb6e0fef3b47fbeb89Chia-I Wu
12214244257f1c3f61448bcafcc07238d8a313f11e3dCourtney Goeltzenleuchter    demo->uniform_data.desc.bufferInfo.buffer = demo->uniform_data.buf;
12224244257f1c3f61448bcafcc07238d8a313f11e3dCourtney Goeltzenleuchter    demo->uniform_data.desc.bufferInfo.offset = 0;
12234244257f1c3f61448bcafcc07238d8a313f11e3dCourtney Goeltzenleuchter    demo->uniform_data.desc.bufferInfo.range = sizeof(data);
1224e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter}
1225e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter
1226f838506ef976d1659c5dc5528215411c18011fcfChia-I Wustatic void demo_prepare_descriptor_layout(struct demo *demo)
12274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
1228382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkDescriptorSetLayoutBinding layout_bindings[2] = {
1229fc9d913ebe3461e4374d4264dfd5c9bad99df63dChia-I Wu        [0] = {
12309cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1231d3114a2b621b895fb05d5e31b2ab4ea9695b9f84Chia-I Wu            .arraySize = 1,
12328205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour            .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
1233310eece98b15a6861a8f717d5d691d92881c3a54Chia-I Wu            .pImmutableSamplers = NULL,
1234fc9d913ebe3461e4374d4264dfd5c9bad99df63dChia-I Wu        },
1235fc9d913ebe3461e4374d4264dfd5c9bad99df63dChia-I Wu        [1] = {
1236ad870818fc61ad8dccc8af2c4992f15efa9c4c7fCourtney Goeltzenleuchter            .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1237d3114a2b621b895fb05d5e31b2ab4ea9695b9f84Chia-I Wu            .arraySize = DEMO_TEXTURE_COUNT,
12388205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour            .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
1239310eece98b15a6861a8f717d5d691d92881c3a54Chia-I Wu            .pImmutableSamplers = NULL,
1240fc9d913ebe3461e4374d4264dfd5c9bad99df63dChia-I Wu        },
1241f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    };
1242382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkDescriptorSetLayoutCreateInfo descriptor_layout = {
12439cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1244fc9d913ebe3461e4374d4264dfd5c9bad99df63dChia-I Wu        .pNext = NULL,
1245fc9d913ebe3461e4374d4264dfd5c9bad99df63dChia-I Wu        .count = 2,
1246fc9d913ebe3461e4374d4264dfd5c9bad99df63dChia-I Wu        .pBinding = layout_bindings,
12476e68a893f0364c1157789d260cdf84365cb58cf7Chia-I Wu    };
124822a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
12494e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
12509cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkCreateDescriptorSetLayout(demo->device,
12517732cb2481328c1e94a0f308b315cc48df530dc2Chia-I Wu            &descriptor_layout, &demo->desc_layout);
12527732cb2481328c1e94a0f308b315cc48df530dc2Chia-I Wu    assert(!err);
12537732cb2481328c1e94a0f308b315cc48df530dc2Chia-I Wu
1254556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
1255556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski        .sType              = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1256556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski        .pNext              = NULL,
1257556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski        .descriptorSetCount = 1,
1258556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski        .pSetLayouts        = &demo->desc_layout,
1259556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    };
1260556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski
1261556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    err = vkCreatePipelineLayout(demo->device,
1262556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski                                 &pPipelineLayoutCreateInfo,
1263556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski                                 &demo->pipeline_layout);
12644e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
12654e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
12664e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
126776cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wustatic void demo_prepare_render_pass(struct demo *demo)
126876cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu{
1269c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkAttachmentDescription attachments[2] = {
1270c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        [0] = {
1271c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,
1272c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .pNext = NULL,
1273c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .format = demo->format,
1274c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .samples = 1,
1275c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
1276c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
1277c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1278c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1279c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1280c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1281c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        },
1282c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        [1] = {
1283c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,
1284c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .pNext = NULL,
1285c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .format = demo->depth.format,
1286c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .samples = 1,
1287c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
1288c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1289c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1290c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1291c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1292c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1293c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        },
1294c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    };
1295c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkAttachmentReference color_reference = {
1296c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .attachment = 0,
1297c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1298c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    };
1299c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    const VkSubpassDescription subpass = {
1300c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION,
1301c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pNext = NULL,
1302c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
1303c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .flags = 0,
1304c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .inputCount = 0,
13056de6b0b93a1704d673c42fea1f0e3e4e720a14ffCody Northrop        .pInputAttachments = NULL,
1306c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .colorCount = 1,
13076de6b0b93a1704d673c42fea1f0e3e4e720a14ffCody Northrop        .pColorAttachments = &color_reference,
13086de6b0b93a1704d673c42fea1f0e3e4e720a14ffCody Northrop        .pResolveAttachments = NULL,
1309c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .depthStencilAttachment = {
1310c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .attachment = 1,
1311c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu            .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1312c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        },
1313c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .preserveCount = 0,
13146de6b0b93a1704d673c42fea1f0e3e4e720a14ffCody Northrop        .pPreserveAttachments = NULL,
131576cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    };
131676cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    const VkRenderPassCreateInfo rp_info = {
131776cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
131876cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        .pNext = NULL,
1319c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .attachmentCount = 2,
1320c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pAttachments = attachments,
1321c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .subpassCount = 1,
1322c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pSubpasses = &subpass,
1323c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .dependencyCount = 0,
1324c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu        .pDependencies = NULL,
132576cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    };
1326c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu    VkResult U_ASSERT_ONLY err;
132776cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
132876cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    err = vkCreateRenderPass(demo->device, &rp_info, &demo->render_pass);
132976cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    assert(!err);
133076cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu}
133176cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
1332e796a1d653d558c68607c33e5071e47dac5bfd49Tobin Ehlisstatic VkShader demo_prepare_shader(struct demo* demo,
13338205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour                                      VkShaderStage stage,
13349400f09d3b3369554146ce070eb49d2fea00222cTony Barbour                                      VkShaderModule* pShaderModule,
1335e796a1d653d558c68607c33e5071e47dac5bfd49Tobin Ehlis                                      const void* code,
1336e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski                                      size_t size)
13374e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
13380b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    VkShaderModuleCreateInfo moduleCreateInfo;
13390b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    VkShaderCreateInfo shaderCreateInfo;
1340382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkShader shader;
1341382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkResult err;
13424e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
13437e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
13440b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
13450b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    moduleCreateInfo.pNext = NULL;
13464e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
13470b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    shaderCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO;
13480b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    shaderCreateInfo.pNext = NULL;
1349e796a1d653d558c68607c33e5071e47dac5bfd49Tobin Ehlis    shaderCreateInfo.pName = "main";
13501722360237895a60a62a033832b9ec94c4e6697bCourtney Goeltzenleuchter
13510b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter    if (!demo->use_glsl) {
13520b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        moduleCreateInfo.codeSize = size;
13530b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        moduleCreateInfo.pCode = code;
13540b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        moduleCreateInfo.flags = 0;
13559400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        err = vkCreateShaderModule(demo->device, &moduleCreateInfo, pShaderModule);
1356283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        assert(!err);
13570b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter
13580b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        shaderCreateInfo.flags = 0;
13599400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        shaderCreateInfo.module = *pShaderModule;
13601cf7fe1cdc352edbf24e7ad1a1f4362a5d10cc06Piers Daniell        shaderCreateInfo.pName = "main";
136187ae5e14eeb6478f01fe31567cf07fd8bf8f0697Cody Northrop        shaderCreateInfo.stage = stage;
13620b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        err = vkCreateShader(demo->device, &shaderCreateInfo, &shader);
1363c109827920fd0991102d4979728eee74b6ac15fbTony Barbour        assert(!err);
136475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    } else {
136575db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        // Create fake SPV structure to feed GLSL
136675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        // to the driver "under the covers"
13670b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        moduleCreateInfo.codeSize = 3 * sizeof(uint32_t) + size + 1;
13680b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        moduleCreateInfo.pCode = malloc(moduleCreateInfo.codeSize);
13690b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        moduleCreateInfo.flags = 0;
137075db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop
137175db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        /* try version 0 first: VkShaderStage followed by GLSL */
13720b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        ((uint32_t *) moduleCreateInfo.pCode)[0] = ICD_SPV_MAGIC;
13730b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        ((uint32_t *) moduleCreateInfo.pCode)[1] = 0;
13740b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        ((uint32_t *) moduleCreateInfo.pCode)[2] = stage;
13750b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        memcpy(((uint32_t *) moduleCreateInfo.pCode + 3), code, size + 1);
137675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop
13779400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        err = vkCreateShaderModule(demo->device, &moduleCreateInfo, pShaderModule);
137875db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        if (err) {
13790b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter            free((void *) moduleCreateInfo.pCode);
138075db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        }
13810b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter
13820b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        shaderCreateInfo.flags = 0;
13839400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        shaderCreateInfo.module = *pShaderModule;
13841cf7fe1cdc352edbf24e7ad1a1f4362a5d10cc06Piers Daniell        shaderCreateInfo.pName = "main";
138587ae5e14eeb6478f01fe31567cf07fd8bf8f0697Cody Northrop        shaderCreateInfo.stage = stage;
13860b29b0d0258f6a9ad46a14eb120fbb1f6dafa5a1Courtney Goeltzenleuchter        err = vkCreateShader(demo->device, &shaderCreateInfo, &shader);
1387c109827920fd0991102d4979728eee74b6ac15fbTony Barbour        assert(!err);
1388283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        free((void *) moduleCreateInfo.pCode);
13894e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
13904e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    return shader;
13914e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
13924e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1393acfb0491b89d57c3915f661edaad114d64d87386Cody Northropchar *demo_read_spv(const char *filename, size_t *psize)
13947e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter{
13957e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    long int size;
1396a938abb9d45b990819e37f09c3d107a461114c8eTony Barbour    size_t U_ASSERT_ONLY retval;
13977e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    void *shader_code;
13987e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
13997e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    FILE *fp = fopen(filename, "rb");
14007e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    if (!fp) return NULL;
14017e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
14027e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    fseek(fp, 0L, SEEK_END);
14037e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    size = ftell(fp);
14047e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
14057e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    fseek(fp, 0L, SEEK_SET);
14067e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
14077e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    shader_code = malloc(size);
140822a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    retval = fread(shader_code, size, 1, fp);
140922a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    assert(retval == 1);
14107e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
14117e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    *psize = size;
14127e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
14137e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter    return shader_code;
14147e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter}
14157e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
1416382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchterstatic VkShader demo_prepare_vs(struct demo *demo)
14174e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
141875db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    if (!demo->use_glsl) {
1419283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        VkShader shader;
142075db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        void *vertShaderCode;
142175db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        size_t size;
14227e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
142375db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        vertShaderCode = demo_read_spv("cube-vert.spv", &size);
14247e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
1425283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        shader = demo_prepare_shader(demo, VK_SHADER_STAGE_VERTEX, &demo->vert_shader_module,
1426283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter                                     vertShaderCode, size);
1427283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        free(vertShaderCode);
1428283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        return shader;
142975db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    } else {
143075db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        static const char *vertShaderText =
143175db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "#version 140\n"
143275db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "#extension GL_ARB_separate_shader_objects : enable\n"
143375db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "#extension GL_ARB_shading_language_420pack : enable\n"
143475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "\n"
143575db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "layout(binding = 0) uniform buf {\n"
143675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "        mat4 MVP;\n"
143775db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "        vec4 position[12*3];\n"
143875db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "        vec4 attr[12*3];\n"
143975db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "} ubuf;\n"
144075db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "\n"
144175db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "layout (location = 0) out vec4 texcoord;\n"
144275db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "\n"
144375db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "void main() \n"
144475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "{\n"
144575db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "   texcoord = ubuf.attr[gl_VertexID];\n"
144675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "   gl_Position = ubuf.MVP * ubuf.position[gl_VertexID];\n"
144775db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "\n"
144875db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "   // GL->VK conventions\n"
144975db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "   gl_Position.y = -gl_Position.y;\n"
145075db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "   gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;\n"
145175db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "}\n";
145275db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop
14539400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        return demo_prepare_shader(demo, VK_SHADER_STAGE_VERTEX, &demo->vert_shader_module,
145475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                                   (const void *) vertShaderText,
145575db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                                   strlen(vertShaderText));
145675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    }
14574e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
14584e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1459382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchterstatic VkShader demo_prepare_fs(struct demo *demo)
14604e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
146175db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    if (!demo->use_glsl) {
1462283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        VkShader shader;
146375db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        void *fragShaderCode;
146475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        size_t size;
14657e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
146675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        fragShaderCode = demo_read_spv("cube-frag.spv", &size);
14677e33498fda8634e45d0f5790bbe099f84e31b601Courtney Goeltzenleuchter
1468283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        shader = demo_prepare_shader(demo, VK_SHADER_STAGE_FRAGMENT, &demo->frag_shader_module,
1469283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter                                     fragShaderCode, size);
1470283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        free(fragShaderCode);
1471283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter        return shader;
147275db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    } else {
147375db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        static const char *fragShaderText =
147475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "#version 140\n"
147575db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "#extension GL_ARB_separate_shader_objects : enable\n"
147675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "#extension GL_ARB_shading_language_420pack : enable\n"
147775db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "layout (binding = 1) uniform sampler2D tex;\n"
147875db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "\n"
147975db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "layout (location = 0) in vec4 texcoord;\n"
148075db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "layout (location = 0) out vec4 uFragColor;\n"
148175db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "void main() {\n"
148275db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "   uFragColor = texture(tex, texcoord.xy);\n"
148375db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                "}\n";
148475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop
14859400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        return demo_prepare_shader(demo, VK_SHADER_STAGE_FRAGMENT, &demo->frag_shader_module,
148675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                                   (const void *) fragShaderText,
148775db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop                                   strlen(fragShaderText));
148875db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop    }
14894e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
14904e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
14914e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_prepare_pipeline(struct demo *demo)
14924e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
1493382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    VkGraphicsPipelineCreateInfo pipeline;
14940d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    VkPipelineCacheCreateInfo pipelineCache;
1495e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineInputAssemblyStateCreateInfo ia;
1496e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineRasterStateCreateInfo        rs;
1497e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineColorBlendStateCreateInfo    cb;
1498e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineDepthStencilStateCreateInfo  ds;
1499e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineViewportStateCreateInfo      vp;
1500e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineMultisampleStateCreateInfo   ms;
1501811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    VkDynamicState                         dynamicStateEnables[VK_DYNAMIC_STATE_NUM];
1502811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    VkPipelineDynamicStateCreateInfo       dynamicState;
150322a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
15044e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1505811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    memset(dynamicStateEnables, 0, sizeof dynamicStateEnables);
1506811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    memset(&dynamicState, 0, sizeof dynamicState);
1507811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1508811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    dynamicState.pDynamicStates = dynamicStateEnables;
1509811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell
15104e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(&pipeline, 0, sizeof(pipeline));
15119cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1512556f721b927c7f8bf6f37dd502afe8ebf3b76719Mark Lobodzinski    pipeline.layout = demo->pipeline_layout;
15134e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
15144e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(&ia, 0, sizeof(ia));
1515e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
15168205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
15174e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
15184e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(&rs, 0, sizeof(rs));
1519e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO;
15208205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    rs.fillMode = VK_FILL_MODE_SOLID;
15218205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    rs.cullMode = VK_CULL_MODE_BACK;
15229cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    rs.frontFace = VK_FRONT_FACE_CCW;
1523c0f9fa7f4a5e44878c491476e2ece1bacd3223c2Courtney Goeltzenleuchter    rs.depthClampEnable = VK_FALSE;
1524f5bd2253ff4114ac446f8eb820e78d56f711020fCody Northrop    rs.rasterizerDiscardEnable = VK_FALSE;
1525f5bd2253ff4114ac446f8eb820e78d56f711020fCody Northrop    rs.depthBiasEnable = VK_FALSE;
15264e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
15274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(&cb, 0, sizeof(cb));
1528e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1529e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    VkPipelineColorBlendAttachmentState att_state[1];
1530fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    memset(att_state, 0, sizeof(att_state));
1531fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    att_state[0].channelWriteMask = 0xf;
15329cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    att_state[0].blendEnable = VK_FALSE;
1533fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    cb.attachmentCount = 1;
1534fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    cb.pAttachments = att_state;
1535fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour
1536fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    memset(&vp, 0, sizeof(vp));
1537e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
15388205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    vp.viewportCount = 1;
1539811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT;
1540811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    vp.scissorCount = 1;
1541811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    dynamicStateEnables[dynamicState.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR;
1542fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour
1543fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    memset(&ds, 0, sizeof(ds));
1544e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
15459cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    ds.depthTestEnable = VK_TRUE;
15469cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    ds.depthWriteEnable = VK_TRUE;
15478205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    ds.depthCompareOp = VK_COMPARE_OP_LESS_EQUAL;
1548e4bc6948ada94c7fe0b35a89dbc2542ec4f791a2Cody Northrop    ds.depthBoundsTestEnable = VK_FALSE;
15499cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    ds.back.stencilFailOp = VK_STENCIL_OP_KEEP;
15509cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    ds.back.stencilPassOp = VK_STENCIL_OP_KEEP;
15518205d901f17b1c76d89c956be235cf4e7a20a546Tony Barbour    ds.back.stencilCompareOp = VK_COMPARE_OP_ALWAYS;
15529cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    ds.stencilTestEnable = VK_FALSE;
1553fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    ds.front = ds.back;
15544e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1555fa6cac730ca48f6202a8f35d79db34cb3f3b9df8Tony Barbour    memset(&ms, 0, sizeof(ms));
1556e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1557e9825b7a5f81e02cdb76851ed18c8ce404cb3deeCody Northrop    ms.pSampleMask = NULL;
1558e094edfa7deb8d694703bb27cdee6034c1085386Tony Barbour    ms.rasterSamples = 1;
15594e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
15600e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    // Two stages: vs and fs
15610e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    pipeline.stageCount = 2;
15620e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    VkPipelineShaderStageCreateInfo shaderStages[2];
15630e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    memset(&shaderStages, 0, 2 * sizeof(VkPipelineShaderStageCreateInfo));
15640e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski
15650e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    shaderStages[0].sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
15660e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    shaderStages[0].stage  = VK_SHADER_STAGE_VERTEX;
15670e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    shaderStages[0].shader = demo_prepare_vs(demo);
15680e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski
15690e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    shaderStages[1].sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
15700e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    shaderStages[1].stage  = VK_SHADER_STAGE_FRAGMENT;
15710e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    shaderStages[1].shader = demo_prepare_fs(demo);
15720e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski
15730d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    memset(&pipelineCache, 0, sizeof(pipelineCache));
15740d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
15754e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
15760d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    err = vkCreatePipelineCache(demo->device, &pipelineCache, &demo->pipelineCache);
15770d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    assert(!err);
1578e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour
1579e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pVertexInputState   = NULL;
1580e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pInputAssemblyState = &ia;
1581e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pRasterState        = &rs;
1582e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pColorBlendState    = &cb;
1583e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pMultisampleState   = &ms;
1584e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pViewportState      = &vp;
1585e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pDepthStencilState  = &ds;
1586e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour    pipeline.pStages             = shaderStages;
1587d31ab4353aee1772092d441a97022b342fcbc260Tony Barbour    pipeline.renderPass          = demo->render_pass;
1588811eb740b7f7ea79ca283426e093d89fd285b76bPiers Daniell    pipeline.pDynamicState       = &dynamicState;
1589e307f588ada2a959cab1964216a66934e5f8ab9eTony Barbour
159014eb5eac6d11950c8cc9fa98f075fabc35bbc00fCourtney Goeltzenleuchter    pipeline.renderPass = demo->render_pass;
159114eb5eac6d11950c8cc9fa98f075fabc35bbc00fCourtney Goeltzenleuchter
15920d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1, &pipeline, &demo->pipeline);
15934e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
15944e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
15950e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    for (uint32_t i = 0; i < pipeline.stageCount; i++) {
1596de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour        vkDestroyShader(demo->device, shaderStages[i].shader);
15970e0fb5cdf0f53e118ad3a405c3b881ef2ef4147dMark Lobodzinski    }
15989400f09d3b3369554146ce070eb49d2fea00222cTony Barbour    vkDestroyShaderModule(demo->device, demo->frag_shader_module);
15999400f09d3b3369554146ce070eb49d2fea00222cTony Barbour    vkDestroyShaderModule(demo->device, demo->vert_shader_module);
16004e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
16014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
16028d24b3bada572c64ef4f86f782e1f5136976f31dChia-I Wustatic void demo_prepare_descriptor_pool(struct demo *demo)
1603f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu{
1604382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkDescriptorTypeCount type_counts[2] = {
1605f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu        [0] = {
16069cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1607f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu            .count = 1,
1608f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu        },
1609f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu        [1] = {
1610ad870818fc61ad8dccc8af2c4992f15efa9c4c7fCourtney Goeltzenleuchter            .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1611f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu            .count = DEMO_TEXTURE_COUNT,
1612f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu        },
1613f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    };
1614382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkDescriptorPoolCreateInfo descriptor_pool = {
16159cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1616f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu        .pNext = NULL,
1617d9e966aac83c28e7f6ac6535f695c9a7c06f667dCourtney Goeltzenleuchter        .poolUsage = VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT,
1618d9e966aac83c28e7f6ac6535f695c9a7c06f667dCourtney Goeltzenleuchter        .maxSets = 1,
1619f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu        .count = 2,
1620f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu        .pTypeCount = type_counts,
1621f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    };
162222a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
1623f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
16249cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkCreateDescriptorPool(demo->device,
16258d24b3bada572c64ef4f86f782e1f5136976f31dChia-I Wu            &descriptor_pool, &demo->desc_pool);
1626f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    assert(!err);
1627f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu}
1628f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
1629f838506ef976d1659c5dc5528215411c18011fcfChia-I Wustatic void demo_prepare_descriptor_set(struct demo *demo)
1630f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu{
16318cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    VkDescriptorInfo tex_descs[DEMO_TEXTURE_COUNT];
16328cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    VkWriteDescriptorSet writes[2];
163322a30866de6210d780995dfaaae39f1a73115aa0Tony Barbour    VkResult U_ASSERT_ONLY err;
1634e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t i;
1635f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
1636230e62505478ab0d9b05003e0e48baa5f090c6a0Mike Stroyan    err = vkAllocDescriptorSets(demo->device, demo->desc_pool,
16379cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter            VK_DESCRIPTOR_SET_USAGE_STATIC,
16386e68a893f0364c1157789d260cdf84365cb58cf7Chia-I Wu            1, &demo->desc_layout,
1639c8aa4a5cf5902e22b99d0107164ac43c6c7c4e5dCody Northrop            &demo->desc_set);
1640c8aa4a5cf5902e22b99d0107164ac43c6c7c4e5dCody Northrop    assert(!err);
1641f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
16428cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    memset(&tex_descs, 0, sizeof(tex_descs));
16438cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
16448cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu        tex_descs[i].sampler = demo->textures[i].sampler;
16458cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu        tex_descs[i].imageView = demo->textures[i].view;
16468cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu        tex_descs[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
16478cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    }
16488cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu
16498cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    memset(&writes, 0, sizeof(writes));
16508cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu
16518cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
16528cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[0].destSet = demo->desc_set;
16538cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[0].count = 1;
16548cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
16558cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[0].pDescriptors = &demo->uniform_data.desc;
16568cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu
16578cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
16588cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[1].destSet = demo->desc_set;
16598cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[1].destBinding = 1;
16608cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[1].count = DEMO_TEXTURE_COUNT;
16618cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
16628cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu    writes[1].pDescriptors = tex_descs;
16638cd8ecde19f154f1779a7bcc93cb1a3519b57dbfChia-I Wu
166467b42b7bde3163f662452cd8ed20e0b69e1afa4fMark Lobodzinski    vkUpdateDescriptorSets(demo->device, 2, writes, 0, NULL);
1665f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu}
1666f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
166776cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wustatic void demo_prepare_framebuffers(struct demo *demo)
166876cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu{
16691856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter    VkImageView attachments[2];
1670f110c6ea46391b57f30588bbda17e7183e8c5bd7Cody Northrop    attachments[1] = demo->depth.view;
1671f110c6ea46391b57f30588bbda17e7183e8c5bd7Cody Northrop
167276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    const VkFramebufferCreateInfo fb_info = {
167376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu         .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
167476cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu         .pNext = NULL,
1675c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu         .renderPass = demo->render_pass,
1676c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu         .attachmentCount = 2,
1677c278df83ca4958fda8efcf3b52e2f89c8ccd8991Chia-I Wu         .pAttachments = attachments,
167876cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu         .width  = demo->width,
167976cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu         .height = demo->height,
168076cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu         .layers = 1,
168176cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    };
168276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    VkResult U_ASSERT_ONLY err;
168376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    uint32_t i;
168476cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
16855aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    demo->framebuffers = (VkFramebuffer *)malloc(demo->swapchainImageCount * sizeof(VkFramebuffer));
16865aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    assert(demo->framebuffers);
16875aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour
16885aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    for (i = 0; i < demo->swapchainImageCount; i++) {
1689f110c6ea46391b57f30588bbda17e7183e8c5bd7Cody Northrop        attachments[0] = demo->buffers[i].view;
169076cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        err = vkCreateFramebuffer(demo->device, &fb_info, &demo->framebuffers[i]);
169176cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu        assert(!err);
169276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    }
169376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu}
169476cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu
16954e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_prepare(struct demo *demo)
16964e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
169718ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    VkResult U_ASSERT_ONLY err;
169818ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop
169918ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    const VkCmdPoolCreateInfo cmd_pool_info = {
170018ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop        .sType = VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO,
170118ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop        .pNext = NULL,
170218ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop        .queueFamilyIndex = demo->graphics_queue_node_index,
170318ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop        .flags = 0,
170418ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    };
170518ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    err = vkCreateCommandPool(demo->device, &cmd_pool_info, &demo->cmd_pool);
170618ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    assert(!err);
170718ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop
1708382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkCmdBufferCreateInfo cmd = {
17099cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
17104e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .pNext = NULL,
171118ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop        .cmdPool = demo->cmd_pool,
171288eaa3bf0c7874f8b62cf35e3b649201ecc47c36Chia-I Wu        .level = VK_CMD_BUFFER_LEVEL_PRIMARY,
17134e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .flags = 0,
17144e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
17154e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
17164e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare_buffers(demo);
17174e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare_depth(demo);
17184e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare_textures(demo);
17193eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo_prepare_cube_data_buffer(demo);
17204e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1721f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    demo_prepare_descriptor_layout(demo);
172276cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    demo_prepare_render_pass(demo);
17234e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare_pipeline(demo);
17244e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1725338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
17269cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        err = vkCreateCommandBuffer(demo->device, &cmd, &demo->buffers[i].cmd);
1727bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter        assert(!err);
1728bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter    }
1729f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu
17308d24b3bada572c64ef4f86f782e1f5136976f31dChia-I Wu    demo_prepare_descriptor_pool(demo);
1731f838506ef976d1659c5dc5528215411c18011fcfChia-I Wu    demo_prepare_descriptor_set(demo);
1732bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter
173376cd422984e4ade573413cf3dbac6209ab08dc8aChia-I Wu    demo_prepare_framebuffers(demo);
1734bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter
1735338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    for (uint32_t i = 0; i < demo->swapchainImageCount; i++) {
1736bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter        demo->current_buffer = i;
1737bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter        demo_draw_build_cmd(demo, demo->buffers[i].cmd);
1738bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter    }
1739bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter
1740bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    /*
1741bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter     * Prepare functions above may generate pipeline commands
1742bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter     * that need to be flushed before beginning the render loop.
1743bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter     */
1744bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter    demo_flush_init_cmd(demo);
1745bfccf41a86ba670f345302ab4d7ab8a6915fb1d2Courtney Goeltzenleuchter
1746bd3b3aa599e47aa07325deb58fc53509ea672fdeCourtney Goeltzenleuchter    demo->current_buffer = 0;
17478a399e92cdfb72bd3f025cf63b7fc7681decd32bJon Ashburn	demo->prepared = true;
17484e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
17494e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1750eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedostatic void demo_cleanup(struct demo *demo)
1751eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo{
1752eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    uint32_t i;
1753eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1754eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    demo->prepared = false;
1755eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
17565aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    for (i = 0; i < demo->swapchainImageCount; i++) {
1757de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour        vkDestroyFramebuffer(demo->device, demo->framebuffers[i]);
1758de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    }
17595aabff59dba24f3fad04176f55c3135c9f4d571bTony Barbour    free(demo->framebuffers);
1760de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyDescriptorPool(demo->device, demo->desc_pool);
1761eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1762de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyPipeline(demo->device, demo->pipeline);
17630d60d274605d3061e5d8ac1cf38e4e9b5ee3ff1aJon Ashburn    vkDestroyPipelineCache(demo->device, demo->pipelineCache);
1764de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyRenderPass(demo->device, demo->render_pass);
1765de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyPipelineLayout(demo->device, demo->pipeline_layout);
1766de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout);
1767eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1768eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
1769de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour        vkDestroyImageView(demo->device, demo->textures[i].view);
1770de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour        vkDestroyImage(demo->device, demo->textures[i].image);
1771eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        vkFreeMemory(demo->device, demo->textures[i].mem);
1772de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour        vkDestroySampler(demo->device, demo->textures[i].sampler);
1773eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    }
1774338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    demo->fpDestroySwapchainKHR(demo->device, demo->swap_chain);
1775eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
17761856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter    vkDestroyImageView(demo->device, demo->depth.view);
1777de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyImage(demo->device, demo->depth.image);
1778eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    vkFreeMemory(demo->device, demo->depth.mem);
1779eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1780de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour    vkDestroyBuffer(demo->device, demo->uniform_data.buf);
1781eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    vkFreeMemory(demo->device, demo->uniform_data.mem);
1782eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1783338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    for (i = 0; i < demo->swapchainImageCount; i++) {
17841856d6f9294c7f9544cb58823fbfddef1546229dCourtney Goeltzenleuchter        vkDestroyImageView(demo->device, demo->buffers[i].view);
1785de4124da4233d201bf1d7326acf0e8bf53d5bee5Tony Barbour        vkDestroyCommandBuffer(demo->device, demo->buffers[i].cmd);
1786eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    }
1787e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    free(demo->buffers);
1788eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1789283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter    free(demo->queue_props);
1790283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter
179118ea11b03ca9bcf3b009434a987f908bfac20324Cody Northrop    vkDestroyCommandPool(demo->device, demo->cmd_pool);
1792eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    vkDestroyDevice(demo->device);
1793a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour    if (demo->validate) {
1794a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        demo->dbgDestroyMsgCallback(demo->inst, demo->msg_callback);
1795a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour    }
1796eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    vkDestroyInstance(demo->inst);
1797eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1798eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo#ifndef _WIN32
1799eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    xcb_destroy_window(demo->connection, demo->window);
1800eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    xcb_disconnect(demo->connection);
1801283f4a3f2233f244650b6583f3b0d9b11d49aa67Courtney Goeltzenleuchter    free(demo->atom_wm_delete_window);
1802eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo#endif // _WIN32
1803eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo}
1804eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1805eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo// On MS-Windows, make this a global, so it's available to WndProc()
1806eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedostruct demo demo;
1807eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1808e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#ifdef _WIN32
1809e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliottstatic void demo_run(struct demo *demo)
1810e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott{
1811857542bbc273de949d23515e9a36d4478ccd82e4Courtney Goeltzenleuchter    if (!demo->prepared)
1812857542bbc273de949d23515e9a36d4478ccd82e4Courtney Goeltzenleuchter        return;
1813e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    // Wait for work to finish before updating MVP.
1814e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    vkDeviceWaitIdle(demo->device);
1815e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_update_data_buffer(demo);
1816e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
1817e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_draw(demo);
1818e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
1819e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    // Wait for work to finish before updating MVP.
1820e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    vkDeviceWaitIdle(demo->device);
1821e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
1822eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    demo->curFrame++;
1823eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1824eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    if (demo->frameCount != INT_MAX && demo->curFrame == demo->frameCount)
1825eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    {
1826eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        demo->quit=true;
1827eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        demo_cleanup(demo);
1828eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        ExitProcess(0);
1829eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    }
1830eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
1831eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo}
1832e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
1833e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott// MS-Windows event handling function:
1834e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian ElliottLRESULT CALLBACK WndProc(HWND hWnd,
1835e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                         UINT uMsg,
1836e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                         WPARAM wParam,
1837e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                         LPARAM lParam)
1838e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott{
1839e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    switch(uMsg)
1840e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    {
1841e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    case WM_CLOSE:
1842e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        PostQuitMessage(0);
18435685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        break;
1844e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    case WM_PAINT:
1845e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        demo_run(&demo);
184618b53e792aad08d1d95210c372e1326bb952ef9aTony Barbour        break;
1847e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    default:
1848e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        break;
1849e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    }
1850e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    return (DefWindowProc(hWnd, uMsg, wParam, lParam));
1851e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott}
1852e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
1853e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliottstatic void demo_create_window(struct demo *demo)
1854e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott{
1855e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    WNDCLASSEX  win_class;
1856e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
1857e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    // Initialize the window class structure:
1858e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.cbSize = sizeof(WNDCLASSEX);
1859e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.style = CS_HREDRAW | CS_VREDRAW;
1860e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.lpfnWndProc = WndProc;
1861e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.cbClsExtra = 0;
1862e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.cbWndExtra = 0;
1863e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hInstance = demo->connection; // hInstance
1864e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1865e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1866e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1867e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.lpszMenuName = NULL;
1868e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.lpszClassName = demo->name;
1869e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1870e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    // Register window class:
1871e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    if (!RegisterClassEx(&win_class)) {
1872e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        // It didn't work, so try to give a useful error:
1873e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        printf("Unexpected error trying to start the application!\n");
1874e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        fflush(stdout);
1875e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        exit(1);
1876e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    }
1877e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    // Create window with the registered class:
1878f585629f8c7ad03f2128aa90dca75d698cb1eb4bMike Stroyan    RECT wr = { 0, 0, demo->width, demo->height };
1879f585629f8c7ad03f2128aa90dca75d698cb1eb4bMike Stroyan    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
1880e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo->window = CreateWindowEx(0,
1881e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  demo->name,           // class name
1882e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  demo->name,           // app name
1883e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  WS_OVERLAPPEDWINDOW | // window style
1884e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  WS_VISIBLE |
1885e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  WS_SYSMENU,
1886e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  100,100,              // x/y coords
1887f585629f8c7ad03f2128aa90dca75d698cb1eb4bMike Stroyan                                  wr.right-wr.left,     // width
1888f585629f8c7ad03f2128aa90dca75d698cb1eb4bMike Stroyan                                  wr.bottom-wr.top,     // height
1889e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  NULL,                 // handle to parent
1890e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  NULL,                 // handle to menu
1891e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  demo->connection,     // hInstance
1892e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott                                  NULL);                // no extra parameters
1893e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    if (!demo->window) {
1894e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        // It didn't work, so try to give a useful error:
1895e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        printf("Cannot create a window in which to draw!\n");
1896e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        fflush(stdout);
1897e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        exit(1);
1898e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    }
1899e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott}
1900e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#else  // _WIN32
19014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_handle_event(struct demo *demo,
19024e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter                              const xcb_generic_event_t *event)
19034e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
1904886be472ea5f6fc366d2e20156396e17d0947816Piers Daniell    uint8_t event_code = event->response_type & 0x7f;
1905ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    switch (event_code) {
19064e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    case XCB_EXPOSE:
1907546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        // TODO: Resize window
19084e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        break;
1909ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    case XCB_CLIENT_MESSAGE:
1910ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter        if((*(xcb_client_message_event_t*)event).data.data32[0] ==
1911ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter           (*demo->atom_wm_delete_window).atom) {
1912ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter            demo->quit = true;
1913ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter        }
1914ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter        break;
19154e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    case XCB_KEY_RELEASE:
19164e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        {
19174e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            const xcb_key_release_event_t *key =
19184e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter                (const xcb_key_release_event_t *) event;
19194e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
19206f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter            switch (key->detail) {
19216f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter            case 0x9:           // Escape
19224e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter                demo->quit = true;
19236f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter                break;
1924e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter            case 0x71:          // left arrow key
19253eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter                demo->spin_angle += demo->spin_increment;
1926e3342401d163212fce30ebb04dc0e0c998a058a3Courtney Goeltzenleuchter                break;
19276f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter            case 0x72:          // right arrow key
19283eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter                demo->spin_angle -= demo->spin_increment;
19296f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter                break;
19303eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter            case 0x41:
19313eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter                demo->pause = !demo->pause;
1932886be472ea5f6fc366d2e20156396e17d0947816Piers Daniell                break;
19336f88d4c7f5cbca061f6d4c6e64b7c12719a38b2dCourtney Goeltzenleuchter            }
19344e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        }
19354e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        break;
19364e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    default:
19374e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        break;
19384e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
19394e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
19404e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
19414e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_run(struct demo *demo)
19424e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
19434e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_flush(demo->connection);
19444e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
19454e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    while (!demo->quit) {
19464e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        xcb_generic_event_t *event;
19474e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1948546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        if (demo->pause) {
1949546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter            event = xcb_wait_for_event(demo->connection);
1950546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        } else {
1951546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter            event = xcb_poll_for_event(demo->connection);
1952546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        }
19534e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        if (event) {
19544e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            demo_handle_event(demo, event);
19554e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            free(event);
1956bb3e1312f9d8151ed996962332b814b68a2b4956Courtney Goeltzenleuchter        }
19573eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
1958546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        // Wait for work to finish before updating MVP.
19599cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        vkDeviceWaitIdle(demo->device);
1960546114856d78407cceb808957798e5ab7f28cb53Courtney Goeltzenleuchter        demo_update_data_buffer(demo);
19613eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
1962bb3e1312f9d8151ed996962332b814b68a2b4956Courtney Goeltzenleuchter        demo_draw(demo);
196321f89977bfc3cd59bcc539f74b90d538a85a0a71Courtney Goeltzenleuchter
1964bb3e1312f9d8151ed996962332b814b68a2b4956Courtney Goeltzenleuchter        // Wait for work to finish before updating MVP.
19659cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        vkDeviceWaitIdle(demo->device);
1966eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        demo->curFrame++;
1967a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour        if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
1968eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            demo->quit = true;
1969eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
19704e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    }
19714e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
19724e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
19734e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_create_window(struct demo *demo)
19744e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
19754e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    uint32_t value_mask, value_list[32];
19764e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
19774e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo->window = xcb_generate_id(demo->connection);
19784e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
19794e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
19804e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    value_list[0] = demo->screen->black_pixel;
19814e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
19824e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter                    XCB_EVENT_MASK_EXPOSURE;
19834e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
19844e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_create_window(demo->connection,
19854e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            XCB_COPY_FROM_PARENT,
19864e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            demo->window, demo->screen->root,
19874e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            0, 0, demo->width, demo->height, 0,
19884e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            XCB_WINDOW_CLASS_INPUT_OUTPUT,
19894e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            demo->screen->root_visual,
19904e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            value_mask, value_list);
19914e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
1992ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    /* Magic code that will send notification when window is destroyed */
1993ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    xcb_intern_atom_cookie_t cookie = xcb_intern_atom(demo->connection, 1, 12,
1994ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter                                                      "WM_PROTOCOLS");
1995ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(demo->connection, cookie, 0);
1996ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter
1997ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(demo->connection, 0, 16, "WM_DELETE_WINDOW");
1998ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    demo->atom_wm_delete_window = xcb_intern_atom_reply(demo->connection, cookie2, 0);
1999ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter
2000ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    xcb_change_property(demo->connection, XCB_PROP_MODE_REPLACE,
2001ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter                        demo->window, (*reply).atom, 4, 32, 1,
2002ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter                        &(*demo->atom_wm_delete_window).atom);
2003ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter    free(reply);
2004ca21a21bf712837a8f15c2421a18338cb0ce7e01Courtney Goeltzenleuchter
20054e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_map_window(demo->connection, demo->window);
2006eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo
2007eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    // Force the x/y coordinates to 100,100 results are identical in consecutive runs
2008eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    const uint32_t coords[] = {100,  100};
2009eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    xcb_configure_window(demo->connection, demo->window,
2010eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo                         XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords);
20114e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
2012e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#endif // _WIN32
20134e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
20148c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter/*
20158c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter * Return 1 (true) if all layer names specified in check_names
20168c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter * can be found in given layer properties.
20178c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter */
20181f41f54bc20d57faed702aec3074eacdfc34680dCourtney Goeltzenleuchterstatic VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
20198c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                              uint32_t layer_count, VkLayerProperties *layers)
20208c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter{
20218c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    for (uint32_t i = 0; i < check_count; i++) {
20221f41f54bc20d57faed702aec3074eacdfc34680dCourtney Goeltzenleuchter        VkBool32 found = 0;
20238c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        for (uint32_t j = 0; j < layer_count; j++) {
20248c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter            if (!strcmp(check_names[i], layers[j].layerName)) {
20258c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                found = 1;
20268c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter            }
20278c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        }
20288c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        if (!found) {
20298c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter            fprintf(stderr, "Cannot find layer: %s\n", check_names[i]);
20308c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter            return 0;
20318c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        }
20328c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    }
20338c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    return 1;
20348c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter}
20358c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
20369cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchterstatic void demo_init_vk(struct demo *demo)
20374e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
20383536b44d5d907e6ce3d97c40366f12a988c8036dTobin Ehlis    VkResult err;
203918061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    char *extension_names[64];
20401c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    VkExtensionProperties *instance_extensions;
20414f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    VkPhysicalDevice *physical_devices;
204218061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    VkLayerProperties *instance_layers;
204318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    VkLayerProperties *device_layers;
20441c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter    uint32_t instance_extension_count = 0;
204518061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    uint32_t instance_layer_count = 0;
204618061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    uint32_t enabled_extension_count = 0;
204718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    uint32_t enabled_layer_count = 0;
204818061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
20498c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    char *instance_validation_layers[] = {
20509400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "Threading",
20518c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        "MemTracker",
20529400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "ObjectTracker",
20539400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "DrawState",
20549400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "ParamChecker",
20559400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "ShaderChecker",
2056329da01f955ec59b8047b2b47418e83efbd2f7d9Ian Elliott        "Swapchain",
20573bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        "DeviceLimits",
20583bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        "Image",
20598c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    };
20608c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
20618c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    char *device_validation_layers[] = {
20629400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "Threading",
20638c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        "MemTracker",
20649400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "ObjectTracker",
20659400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "DrawState",
20669400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "ParamChecker",
20679400f09d3b3369554146ce070eb49d2fea00222cTony Barbour        "ShaderChecker",
2068329da01f955ec59b8047b2b47418e83efbd2f7d9Ian Elliott        "Swapchain",
20693bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        "DeviceLimits",
20703bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        "Image",
20718c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    };
20728c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
207318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    /* Look for validation layers */
20741f41f54bc20d57faed702aec3074eacdfc34680dCourtney Goeltzenleuchter    VkBool32 validation_found = 0;
207574c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter    err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
207618061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
207718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
207818061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    instance_layers = malloc(sizeof(VkLayerProperties) * instance_layer_count);
207974c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter    err = vkEnumerateInstanceLayerProperties(&instance_layer_count, instance_layers);
208018061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
20818c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
20828c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    if (demo->validate) {
20838c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        validation_found = demo_check_layers(ARRAY_SIZE(instance_validation_layers), instance_validation_layers,
20848c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                                             instance_layer_count, instance_layers);
20858c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        if (!validation_found) {
208674c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter            ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find"
20878c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                     "required validation layer.\n\n"
20888c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                     "Please look at the Getting Started guide for additional "
20898c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                     "information.\n",
20908c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                     "vkCreateInstance Failure");
209118061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        }
20928c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        enabled_layer_count = ARRAY_SIZE(instance_validation_layers);
209318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    }
209418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
209574c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter    err = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL);
20963536b44d5d907e6ce3d97c40366f12a988c8036dTobin Ehlis    assert(!err);
20973536b44d5d907e6ce3d97c40366f12a988c8036dTobin Ehlis
2098d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    VkBool32 swapchainExtFound = 0;
209918061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    memset(extension_names, 0, sizeof(extension_names));
210018061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    instance_extensions = malloc(sizeof(VkExtensionProperties) * instance_extension_count);
210174c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter    err = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, instance_extensions);
210218061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
210318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    for (uint32_t i = 0; i < instance_extension_count; i++) {
2104338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        if (!strcmp("VK_EXT_KHR_swapchain", instance_extensions[i].extName)) {
2105d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour            swapchainExtFound = 1;
2106338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott            extension_names[enabled_extension_count++] = "VK_EXT_KHR_swapchain";
21071c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
2108846298c67f02628ed8a93f0438aa079dfea8541bCourtney Goeltzenleuchter        if (!strcmp(VK_DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extName)) {
210918061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter            if (demo->validate) {
2110846298c67f02628ed8a93f0438aa079dfea8541bCourtney Goeltzenleuchter                extension_names[enabled_extension_count++] = VK_DEBUG_REPORT_EXTENSION_NAME;
211118061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter            }
2112a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        }
211318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        assert(enabled_extension_count < 64);
21143536b44d5d907e6ce3d97c40366f12a988c8036dTobin Ehlis    }
2115d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    if (!swapchainExtFound) {
211674c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter        ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find the "
2117338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                 "\"VK_EXT_KHR_swapchain\" extension.\n\nDo you have a compatible "
21183b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "Vulkan installable client driver (ICD) installed?\nPlease "
21193b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "look at the Getting Started guide for additional "
21203b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "information.\n",
21213b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "vkCreateInstance Failure");
21223b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott    }
2123382489d723fd0d3935da0dc7e1021c56c7b721d3Courtney Goeltzenleuchter    const VkApplicationInfo app = {
21249cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
21254e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .pNext = NULL,
21264e19ed0ed322e45993bac7917a1a253dbaaf88f9Ian Elliott        .pAppName = APP_SHORT_NAME,
21274e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .appVersion = 0,
21284e19ed0ed322e45993bac7917a1a253dbaaf88f9Ian Elliott        .pEngineName = APP_SHORT_NAME,
21294e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        .engineVersion = 0,
21309cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .apiVersion = VK_API_VERSION,
21314e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    };
21325685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    VkInstanceCreateInfo inst_info = {
21339cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
213429669a43755f6caa97c4c1d447f494514ba343d9Jon Ashburn        .pNext = NULL,
213529669a43755f6caa97c4c1d447f494514ba343d9Jon Ashburn        .pAppInfo = &app,
213629669a43755f6caa97c4c1d447f494514ba343d9Jon Ashburn        .pAllocCb = NULL,
213718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        .layerCount = enabled_layer_count,
21388c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        .ppEnabledLayerNames = (const char *const*) ((demo->validate) ? instance_validation_layers : NULL),
213918061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        .extensionCount = enabled_extension_count,
214018061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        .ppEnabledExtensionNames = (const char *const*) extension_names,
214129669a43755f6caa97c4c1d447f494514ba343d9Jon Ashburn    };
2142ff6dab510e7a43155926704eee930c9ed5b9d5efIan Elliott
2143e2d07a5a3810d83d0ea7ecb396d61477893b74a4Mark Lobodzinski    uint32_t gpu_count;
21444e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
21459cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkCreateInstance(&inst_info, &demo->inst);
2146caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott    if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
2147caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott        ERR_EXIT("Cannot find a compatible Vulkan installable client driver "
21483b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "(ICD).\n\nPlease look at the Getting Started guide for "
2149caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott                 "additional information.\n",
2150caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott                 "vkCreateInstance Failure");
2151ac544f3737b45a5b35251100a3396aa8be397d8dCourtney Goeltzenleuchter    } else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) {
21525685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        ERR_EXIT("Cannot find a specified extension library"
21535685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour                 ".\nMake sure your layers path is set appropriately\n",
21545685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour                 "vkCreateInstance Failure");
2155caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott    } else if (err) {
21563b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott        ERR_EXIT("vkCreateInstance failed.\n\nDo you have a compatible Vulkan "
21573b375cf83e99df2ddb0d3508dce57c9857a15991Ian Elliott                 "installable client driver (ICD) installed?\nPlease look at "
2158caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott                 "the Getting Started guide for additional information.\n",
2159caa9f27703cec208d4d8fa0ae5939eda1bdbf35bIan Elliott                 "vkCreateInstance Failure");
2160dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott    }
216129669a43755f6caa97c4c1d447f494514ba343d9Jon Ashburn
216218061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    free(instance_layers);
216318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    free(instance_extensions);
21645685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
21654f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    /* Make initial call to query gpu_count, then second call for gpu info*/
21664f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
21674f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    assert(!err && gpu_count > 0);
21684f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count);
21694f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices);
21704f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    assert(!err);
21714f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    /* For cube demo we just grab the first physical device */
21724f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    demo->gpu = physical_devices[0];
21734f482a71352bd542188a787ba1d747fe7605606cTobin Ehlis    free(physical_devices);
21744e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
217518061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    /* Look for validation layers */
217618061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    validation_found = 0;
217718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    enabled_layer_count = 0;
217818061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    uint32_t device_layer_count = 0;
217974c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter    err = vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count, NULL);
218018061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
218118061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
218218061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    device_layers = malloc(sizeof(VkLayerProperties) * device_layer_count);
218374c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter    err = vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count, device_layers);
218418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
21858c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter
21868c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter    if (demo->validate) {
21878c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        validation_found = demo_check_layers(ARRAY_SIZE(device_validation_layers), device_validation_layers,
21888c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                                             device_layer_count, device_layers);
21898c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        if (!validation_found) {
219074c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter            ERR_EXIT("vkEnumerateDeviceLayerProperties failed to find"
21918c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                     "a required validation layer.\n\n"
21928c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                     "Please look at the Getting Started guide for additional "
21938c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                     "information.\n",
21948c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter                     "vkCreateDevice Failure");
219518061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        }
21968c15fc56eb9a8d1f7d395f29f092ccda3430d829Courtney Goeltzenleuchter        enabled_layer_count = ARRAY_SIZE(device_validation_layers);
219718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    }
219818061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
219918061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    uint32_t device_extension_count = 0;
220018061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    VkExtensionProperties *device_extensions = NULL;
220174c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter    err = vkEnumerateDeviceExtensionProperties(
220218061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter              demo->gpu, NULL, &device_extension_count, NULL);
220318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
220418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
2205d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    swapchainExtFound = 0;
220618061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    enabled_extension_count = 0;
220718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    memset(extension_names, 0, sizeof(extension_names));
220818061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    device_extensions = malloc(sizeof(VkExtensionProperties) * device_extension_count);
220974c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter    err = vkEnumerateDeviceExtensionProperties(
221018061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter              demo->gpu, NULL, &device_extension_count, device_extensions);
221118061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    assert(!err);
2212e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
221318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    for (uint32_t i = 0; i < device_extension_count; i++) {
2214338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        if (!strcmp("VK_EXT_KHR_device_swapchain", device_extensions[i].extName)) {
2215d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour            swapchainExtFound = 1;
2216338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott            extension_names[enabled_extension_count++] = "VK_EXT_KHR_device_swapchain";
221718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        }
221818061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter        assert(enabled_extension_count < 64);
221918061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    }
2220d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    if (!swapchainExtFound) {
222174c4ce9c4fa101c0989a29cf918e799fa67adcecCourtney Goeltzenleuchter        ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find the "
2222338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                 "\"VK_EXT_KHR_device_swapchain\" extension.\n\nDo you have a compatible "
222318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter                 "Vulkan installable client driver (ICD) installed?\nPlease "
222418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter                 "look at the Getting Started guide for additional "
222518061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter                 "information.\n",
222618061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter                 "vkCreateInstance Failure");
222718061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    }
222818061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
22295685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    if (demo->validate) {
2230a4c8c71cb37926b9cc4dd8e131b2ddd3f5de48d5Courtney Goeltzenleuchter        demo->dbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) vkGetInstanceProcAddr(demo->inst, "vkDbgCreateMsgCallback");
2231a4c8c71cb37926b9cc4dd8e131b2ddd3f5de48d5Courtney Goeltzenleuchter        demo->dbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) vkGetInstanceProcAddr(demo->inst, "vkDbgDestroyMsgCallback");
22321c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        if (!demo->dbgCreateMsgCallback) {
22331c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            ERR_EXIT("GetProcAddr: Unable to find vkDbgCreateMsgCallback\n",
22341c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter                     "vkGetProcAddr Failure");
22351c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
2236a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        if (!demo->dbgDestroyMsgCallback) {
2237a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour            ERR_EXIT("GetProcAddr: Unable to find vkDbgDestroyMsgCallback\n",
2238a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour                     "vkGetProcAddr Failure");
2239a65ecc2039ef220af0324ef46f3c3caf623f6976Tony Barbour        }
22403230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        demo->dbgBreakCallback = (PFN_vkDbgMsgCallback) vkGetInstanceProcAddr(demo->inst, "vkDbgBreakCallback");
22413230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        if (!demo->dbgBreakCallback) {
22423230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter            ERR_EXIT("GetProcAddr: Unable to find vkDbgBreakCallback\n",
22433230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter                     "vkGetProcAddr Failure");
22443230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        }
22453230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter
22463230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        PFN_vkDbgMsgCallback callback;
22473230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter
22483230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        if (!demo->use_break) {
22493230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter            callback = dbgFunc;
22503230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        } else {
22513230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter            callback = demo->dbgBreakCallback;
22523230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        }
22531c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        err = demo->dbgCreateMsgCallback(
22541c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter                  demo->inst,
22551c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter                  VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
22563230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter                  callback, NULL,
22571c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter                  &demo->msg_callback);
22581c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        switch (err) {
22591c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        case VK_SUCCESS:
22601c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            break;
22611c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        case VK_ERROR_OUT_OF_HOST_MEMORY:
22621c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            ERR_EXIT("dbgCreateMsgCallback: out of host memory\n",
22631c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter                     "dbgCreateMsgCallback Failure");
22641c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            break;
22651c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        default:
22661c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            ERR_EXIT("dbgCreateMsgCallback: unknown failure\n",
22671c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter                     "dbgCreateMsgCallback Failure");
22681c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter            break;
22691c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter        }
22705685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    }
227101d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
22723bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis
22733bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    /* Call with NULL data to get count */
227401d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_count, NULL);
22753bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    assert(demo->queue_count >= 1);
22763bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis
22773bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    demo->queue_props = (VkQueueFamilyProperties *) malloc(demo->queue_count * sizeof(VkQueueFamilyProperties));
227801d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_count, demo->queue_props);
22793bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    // Find a queue that supports gfx
22803bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    uint32_t gfx_queue_idx = 0;
22813bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    for (gfx_queue_idx = 0; gfx_queue_idx<demo->queue_count; gfx_queue_idx++) {
22823bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        if (demo->queue_props[gfx_queue_idx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
22833bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis            break;
22843bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    }
22853bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    assert(gfx_queue_idx < demo->queue_count);
2286795460a0578a501c1e8d15ee4156a5fd1c13310cTobin Ehlis    // Query fine-grained feature support for this device.
2287795460a0578a501c1e8d15ee4156a5fd1c13310cTobin Ehlis    //  If app has specific feature requirements it should check supported features based on this query
22886454cd96df644d51bd4d71bfb5067345e8d2dd47Tobin Ehlis    VkPhysicalDeviceFeatures physDevFeatures;
228901d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceFeatures(demo->gpu, &physDevFeatures);
2290795460a0578a501c1e8d15ee4156a5fd1c13310cTobin Ehlis
22913bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    const VkDeviceQueueCreateInfo queue = {
22923bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
22933bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .pNext = NULL,
22943bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .queueFamilyIndex = gfx_queue_idx,
22953bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .queueCount = 1,
22963bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    };
22973bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis
22983bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    VkDeviceCreateInfo device = {
22993bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
23003bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .pNext = NULL,
2301dfd53f5bd7048e3d538cb195e22e04f95a02507bCourtney Goeltzenleuchter        .requestedQueueCount = 1,
23023bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .pRequestedQueues = &queue,
23033bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .layerCount = enabled_layer_count,
23043bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .ppEnabledLayerNames = (const char *const*) ((demo->validate) ? device_validation_layers : NULL),
23053bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .extensionCount = enabled_extension_count,
23063bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis        .ppEnabledExtensionNames = (const char *const*) extension_names,
2307795460a0578a501c1e8d15ee4156a5fd1c13310cTobin Ehlis        .pEnabledFeatures = NULL, // If specific features are required, pass them in here
23083bd5dc46e236b0ee2157f8f0d609801196cef545Tobin Ehlis    };
23095685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
23109cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    err = vkCreateDevice(demo->gpu, &device, &demo->device);
23114e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    assert(!err);
23124e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
231318061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter    free(device_layers);
231418061cdee54b19cd628178d2924a7a914c62a10bCourtney Goeltzenleuchter
2315338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceSupportKHR);
2316338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_DEVICE_PROC_ADDR(demo->device, GetSurfacePropertiesKHR);
2317338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_DEVICE_PROC_ADDR(demo->device, GetSurfaceFormatsKHR);
2318338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_DEVICE_PROC_ADDR(demo->device, GetSurfacePresentModesKHR);
2319338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_DEVICE_PROC_ADDR(demo->device, CreateSwapchainKHR);
2320338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_DEVICE_PROC_ADDR(demo->device, DestroySwapchainKHR);
2321338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_DEVICE_PROC_ADDR(demo->device, GetSwapchainImagesKHR);
2322338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_DEVICE_PROC_ADDR(demo->device, AcquireNextImageKHR);
2323338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    GET_DEVICE_PROC_ADDR(demo->device, QueuePresentKHR);
232489147b4c6e540869f2a8c1a43aa54c44848cde4cCourtney Goeltzenleuchter}
232589147b4c6e540869f2a8c1a43aa54c44848cde4cCourtney Goeltzenleuchter
2326d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbourstatic void demo_init_vk_swapchain(struct demo *demo)
232789147b4c6e540869f2a8c1a43aa54c44848cde4cCourtney Goeltzenleuchter{
232889147b4c6e540869f2a8c1a43aa54c44848cde4cCourtney Goeltzenleuchter    VkResult err;
232989147b4c6e540869f2a8c1a43aa54c44848cde4cCourtney Goeltzenleuchter    uint32_t i;
2330f316806ced61ba68efb7be2335bd1d1138e5234dCourtney Goeltzenleuchter
2331d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    // Construct the surface description:
2332338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    demo->surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_KHR;
2333e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->surface_description.pNext = NULL;
2334e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott#ifdef _WIN32
2335338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    demo->surface_description.platform = VK_PLATFORM_WIN32_KHR;
2336e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->surface_description.pPlatformHandle = demo->connection;
2337e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->surface_description.pPlatformWindow = demo->window;
2338e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott#else  // _WIN32
2339e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->platform_handle_xcb.connection = demo->connection;
2340e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->platform_handle_xcb.root = demo->screen->root;
2341338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    demo->surface_description.platform = VK_PLATFORM_XCB_KHR;
2342e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->surface_description.pPlatformHandle = &demo->platform_handle_xcb;
2343e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->surface_description.pPlatformWindow = &demo->window;
2344e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott#endif // _WIN32
2345e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
2346d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    // Iterate over each queue to learn whether it supports presenting:
2347b787a8eab825c09f299865b7e77ad00bc8196bbbCourtney Goeltzenleuchter    VkBool32* supportsPresent = (VkBool32 *)malloc(demo->queue_count * sizeof(VkBool32));
2348b787a8eab825c09f299865b7e77ad00bc8196bbbCourtney Goeltzenleuchter    for (i = 0; i < demo->queue_count; i++) {
2349338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        demo->fpGetPhysicalDeviceSurfaceSupportKHR(demo->gpu, i,
2350338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                                   (VkSurfaceDescriptionKHR *) &demo->surface_description,
2351e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                                                   &supportsPresent[i]);
2352f316806ced61ba68efb7be2335bd1d1138e5234dCourtney Goeltzenleuchter    }
2353e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
2354e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Search for a graphics and a present queue in the array of queue
2355e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // families, try to find one that supports both
2356e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    uint32_t graphicsQueueNodeIndex = UINT32_MAX;
2357e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    uint32_t presentQueueNodeIndex  = UINT32_MAX;
2358b787a8eab825c09f299865b7e77ad00bc8196bbbCourtney Goeltzenleuchter    for (i = 0; i < demo->queue_count; i++) {
2359e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
2360e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott            if (graphicsQueueNodeIndex == UINT32_MAX) {
2361e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                graphicsQueueNodeIndex = i;
2362e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott            }
2363e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
2364e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott            if (supportsPresent[i] == VK_TRUE) {
2365e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                graphicsQueueNodeIndex = i;
2366e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                presentQueueNodeIndex = i;
2367e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                break;
2368e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott            }
2369e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        }
2370e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
2371e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    if (presentQueueNodeIndex == UINT32_MAX) {
2372e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        // If didn't find a queue that supports both graphics and present, then
2373e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        // find a separate present queue.
2374b787a8eab825c09f299865b7e77ad00bc8196bbbCourtney Goeltzenleuchter        for (uint32_t i = 0; i < demo->queue_count; ++i) {
2375e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott            if (supportsPresent[i] == VK_TRUE) {
2376e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                presentQueueNodeIndex = i;
2377e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott                break;
2378e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott            }
2379e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        }
2380e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
2381e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    free(supportsPresent);
2382e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
2383e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Generate error if could not find both a graphics and a present queue
2384e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX) {
2385e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        ERR_EXIT("Could not find a graphics and a present queue\n",
2386d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour                 "Swapchain Initialization Failure");
2387e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
2388e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
2389e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // TODO: Add support for separate queues, including presentation,
2390e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    //       synchronization, and appropriate tracking for QueueSubmit
2391e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // While it is possible for an application to use a separate graphics and a
2392e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // present queues, this demo program assumes it is only using one:
2393e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    if (graphicsQueueNodeIndex != presentQueueNodeIndex) {
2394e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        ERR_EXIT("Could not find a common graphics and a present queue\n",
2395d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour                 "Swapchain Initialization Failure");
2396e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
2397e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott
2398e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    demo->graphics_queue_node_index = graphicsQueueNodeIndex;
2399f316806ced61ba68efb7be2335bd1d1138e5234dCourtney Goeltzenleuchter
240001d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetDeviceQueue(demo->device, demo->graphics_queue_node_index,
24014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter            0, &demo->queue);
24025685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
2403e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // Get the list of VkFormat's that are supported:
24047fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    uint32_t formatCount;
2405338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpGetSurfaceFormatsKHR(demo->device,
2406338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                    (VkSurfaceDescriptionKHR *) &demo->surface_description,
24077fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott                                    &formatCount, NULL);
2408e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
2409338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    VkSurfaceFormatKHR *surfFormats =
2410338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott        (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
2411338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott    err = demo->fpGetSurfaceFormatsKHR(demo->device,
2412338dedb8c82676fded0ab72e32d029292875ce71Ian Elliott                                    (VkSurfaceDescriptionKHR *) &demo->surface_description,
24137fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott                                    &formatCount, surfFormats);
2414e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    assert(!err);
2415e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
2416e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // the surface has no preferred format.  Otherwise, at least one
2417e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    // supported format will be returned.
2418e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
2419e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    {
2420e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        demo->format = VK_FORMAT_B8G8R8A8_UNORM;
2421e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
2422e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    else
2423e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    {
2424e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        assert(formatCount >= 1);
2425e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott        demo->format = surfFormats[0].format;
2426e36b208f32a0959cd7590b1717aac3ef19631b1aIan Elliott    }
24277fe115db80cf5ffdfa5d08ac90b1aadedd59ca26Ian Elliott    demo->color_space = surfFormats[0].colorSpace;
242832536f966d1b2d9034a467b36e398545ef54e9d1Ian Elliott
2429eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    demo->quit = false;
2430eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo    demo->curFrame = 0;
2431723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski
2432723462910ef2f9ed0255b74399c835020a75a0b1Mark Lobodzinski    // Get Memory information and properties
243301d2ae18f05184e04eb29a2ab30480f8d4660d25Courtney Goeltzenleuchter    vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_properties);
24344e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
24354e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
24364e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchterstatic void demo_init_connection(struct demo *demo)
24374e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
2438e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#ifndef _WIN32
24394e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    const xcb_setup_t *setup;
24404e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    xcb_screen_iterator_t iter;
24414e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    int scr;
24424e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
24434e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo->connection = xcb_connect(NULL, &scr);
2444dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott    if (demo->connection == NULL) {
2445dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott        printf("Cannot find a compatible Vulkan installable client driver "
2446dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott               "(ICD).\nExiting ...\n");
2447dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott        fflush(stdout);
2448dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott        exit(1);
2449dfe55f7cf6e23d7bf2ff0076a7347cbc99d4a6f9Ian Elliott    }
24504e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
24514e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    setup = xcb_get_setup(demo->connection);
24524e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    iter = xcb_setup_roots_iterator(setup);
24534e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    while (scr-- > 0)
24544e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter        xcb_screen_next(&iter);
24554e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
24564e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo->screen = iter.data;
2457e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#endif // _WIN32
24584e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
24594e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
246040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchterstatic void demo_init(struct demo *demo, int argc, char **argv)
24614e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
24623eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    vec3 eye = {0.0f, 3.0f, 5.0f};
24633eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    vec3 origin = {0, 0, 0};
2464c3487c272a160e78f7f4e62f4869ab96b623d276Chia-I Wu    vec3 up = {0.0f, 1.0f, 0.0};
24653eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
24664e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    memset(demo, 0, sizeof(*demo));
2467a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour    demo->frameCount = INT32_MAX;
24684e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2469886be472ea5f6fc366d2e20156396e17d0947816Piers Daniell    for (int i = 1; i < argc; i++) {
24705685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        if (strcmp(argv[i], "--use_staging") == 0) {
247140a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter            demo->use_staging_buffer = true;
24725685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour            continue;
2473e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        }
247475db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        if (strcmp(argv[i], "--use_glsl") == 0) {
247575db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop            demo->use_glsl = true;
247675db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop            continue;
247775db0326f1f102a15a4e59504fe6984b64d0d137Cody Northrop        }
24783230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        if (strcmp(argv[i], "--break") == 0) {
24793230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter            demo->use_break = true;
24803230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter            continue;
24813230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        }
24825685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        if (strcmp(argv[i], "--validate") == 0) {
24835685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour            demo->validate = true;
24845685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour            continue;
24855685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        }
2486eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        if (strcmp(argv[i], "--c") == 0 &&
2487a26fb7dfff6ccb2964ec7c63a49c4fc69a5d48dbTony Barbour            demo->frameCount == INT32_MAX &&
2488eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            i < argc-1 &&
2489eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            sscanf(argv[i+1],"%d", &demo->frameCount) == 1 &&
2490eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            demo->frameCount >= 0)
2491eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        {
2492eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            i++;
2493eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo            continue;
2494eeca2a260355a0680275ddb3dc2d1c7c2d61bf14David Pinedo        }
24955685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
24963230e58da9373ad93b2cf1ac9d66e7aa5c4e72f3Courtney Goeltzenleuchter        fprintf(stderr, "Usage:\n  %s [--use_staging] [--validate] [--break] [--c <framecount>]\n", APP_SHORT_NAME);
2497e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        fflush(stderr);
2498e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        exit(1);
249940a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    }
250040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter
25014e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_init_connection(demo);
25029cc421eb545767e22fd723dc573a7a3225261b1cCourtney Goeltzenleuchter    demo_init_vk(demo);
25034e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
25043eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo->width = 500;
25053eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo->height = 500;
25063eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
25073eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo->spin_angle = 0.01f;
25083eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo->spin_increment = 0.01f;
25093eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    demo->pause = false;
25103eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter
2511886be472ea5f6fc366d2e20156396e17d0947816Piers Daniell    mat4x4_perspective(demo->projection_matrix, (float)degreesToRadians(45.0f), 1.0f, 0.1f, 100.0f);
25123eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    mat4x4_look_at(demo->view_matrix, eye, origin, up);
25133eeff43ff1f39a6c765904f0730949e94a2660f4Courtney Goeltzenleuchter    mat4x4_identity(demo->model_matrix);
25144e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
25154e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
25164e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
2517e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#ifdef _WIN32
25185685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbourextern int __getmainargs(
25195685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        int * _Argc,
25205685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        char *** _Argv,
25215685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        char *** _Env,
25225685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        int _DoWildCard,
25235685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour        int * new_mode);
25247595eeeb9f9d0b0568df04e19c442ed22f7d7b5fIan Elliott
2525421107f97492e625626a91e6b153e38d889bbbb9Ian Elliottint WINAPI WinMain(HINSTANCE hInstance,
2526421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott                   HINSTANCE hPrevInstance,
2527421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott                   LPSTR pCmdLine,
2528421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott                   int nCmdShow)
2529e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott{
2530e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    MSG msg;         // message
2531e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    bool done;        // flag saying when app is complete
25325685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    int argc;
25335685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    char** argv;
25345685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    char** env;
25355685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    int new_mode = 0;
2536e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
25375685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    __getmainargs(&argc,&argv,&env,0,&new_mode);
25385685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour
25395685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    demo_init(&demo, argc, argv);
25405685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    demo.connection = hInstance;
25415685ad7549b281c6c4a297a58dfb303db89af1a1Tony Barbour    strncpy(demo.name, "cube", APP_NAME_STR_LEN);
2542e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_create_window(&demo);
2543d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    demo_init_vk_swapchain(&demo);
2544e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
2545e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_prepare(&demo);
2546e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
2547e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    done = false; //initialize loop condition variable
2548e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    /* main message loop*/
2549e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    while(!done)
2550e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    {
2551421107f97492e625626a91e6b153e38d889bbbb9Ian Elliott        PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
2552e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        if (msg.message == WM_QUIT) //check for a quit message
2553e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        {
2554e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott            done = true; //if found, quit app
2555e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        }
2556e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        else
2557e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        {
2558e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott            /* Translate and dispatch to event queue*/
2559e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott            TranslateMessage(&msg);
2560e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott            DispatchMessage(&msg);
2561e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott        }
256218b53e792aad08d1d95210c372e1326bb952ef9aTony Barbour        RedrawWindow(demo.window, NULL, NULL, RDW_INTERNALPAINT);
2563e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    }
2564e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
2565e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott    demo_cleanup(&demo);
2566e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott
2567a938abb9d45b990819e37f09c3d107a461114c8eTony Barbour    return (int) msg.wParam;
2568e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott}
2569e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#else  // _WIN32
257040a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchterint main(int argc, char **argv)
25714e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter{
25724e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    struct demo demo;
25734e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
257440a8b0a8c11264de45f48ffc150e83dc5a88b14fCourtney Goeltzenleuchter    demo_init(&demo, argc, argv);
25755b66aa51f060c804e1804cf45909ed6489552c62Chia-I Wu    demo_create_window(&demo);
2576d9955e4e5584aaab9dc4b5df4b4fea86bc6f5e30Tony Barbour    demo_init_vk_swapchain(&demo);
25774e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
25784e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_prepare(&demo);
25794e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_run(&demo);
25804e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
25814e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    demo_cleanup(&demo);
25824e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter
25834e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter    return 0;
25844e8246e9deffb6fec4c3c6b87780e2a9939fba9dCourtney Goeltzenleuchter}
2585e14e9f9a4b3b2409b8475e7f7568e17f78f878f4Ian Elliott#endif // _WIN32
2586