1b877906bSopenharmony_ci/* 2b877906bSopenharmony_ci * Copyright (c) 2015-2016 The Khronos Group Inc. 3b877906bSopenharmony_ci * Copyright (c) 2015-2016 Valve Corporation 4b877906bSopenharmony_ci * Copyright (c) 2015-2016 LunarG, Inc. 5b877906bSopenharmony_ci * 6b877906bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 7b877906bSopenharmony_ci * you may not use this file except in compliance with the License. 8b877906bSopenharmony_ci * You may obtain a copy of the License at 9b877906bSopenharmony_ci * 10b877906bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 11b877906bSopenharmony_ci * 12b877906bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 13b877906bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 14b877906bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15b877906bSopenharmony_ci * See the License for the specific language governing permissions and 16b877906bSopenharmony_ci * limitations under the License. 17b877906bSopenharmony_ci * 18b877906bSopenharmony_ci * Author: Chia-I Wu <olvaffe@gmail.com> 19b877906bSopenharmony_ci * Author: Cody Northrop <cody@lunarg.com> 20b877906bSopenharmony_ci * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 21b877906bSopenharmony_ci * Author: Ian Elliott <ian@LunarG.com> 22b877906bSopenharmony_ci * Author: Jon Ashburn <jon@lunarg.com> 23b877906bSopenharmony_ci * Author: Piers Daniell <pdaniell@nvidia.com> 24b877906bSopenharmony_ci * Author: Gwan-gyeong Mun <elongbug@gmail.com> 25b877906bSopenharmony_ci * Porter: Camilla Löwy <elmindreda@glfw.org> 26b877906bSopenharmony_ci */ 27b877906bSopenharmony_ci/* 28b877906bSopenharmony_ci * Draw a textured triangle with depth testing. This is written against Intel 29b877906bSopenharmony_ci * ICD. It does not do state transition nor object memory binding like it 30b877906bSopenharmony_ci * should. It also does no error checking. 31b877906bSopenharmony_ci */ 32b877906bSopenharmony_ci 33b877906bSopenharmony_ci#include <stdio.h> 34b877906bSopenharmony_ci#include <stdlib.h> 35b877906bSopenharmony_ci#include <string.h> 36b877906bSopenharmony_ci#include <stdbool.h> 37b877906bSopenharmony_ci#include <assert.h> 38b877906bSopenharmony_ci#include <signal.h> 39b877906bSopenharmony_ci 40b877906bSopenharmony_ci#ifdef _WIN32 41b877906bSopenharmony_ci#include <windows.h> 42b877906bSopenharmony_ci#endif 43b877906bSopenharmony_ci 44b877906bSopenharmony_ci#define GLAD_VULKAN_IMPLEMENTATION 45b877906bSopenharmony_ci#include <glad/vulkan.h> 46b877906bSopenharmony_ci#define GLFW_INCLUDE_NONE 47b877906bSopenharmony_ci#include <GLFW/glfw3.h> 48b877906bSopenharmony_ci 49b877906bSopenharmony_ci#define DEMO_TEXTURE_COUNT 1 50b877906bSopenharmony_ci#define VERTEX_BUFFER_BIND_ID 0 51b877906bSopenharmony_ci#define APP_SHORT_NAME "tri" 52b877906bSopenharmony_ci#define APP_LONG_NAME "The Vulkan Triangle Demo Program" 53b877906bSopenharmony_ci 54b877906bSopenharmony_ci#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 55b877906bSopenharmony_ci 56b877906bSopenharmony_ci#if defined(NDEBUG) && defined(__GNUC__) 57b877906bSopenharmony_ci#define U_ASSERT_ONLY __attribute__((unused)) 58b877906bSopenharmony_ci#else 59b877906bSopenharmony_ci#define U_ASSERT_ONLY 60b877906bSopenharmony_ci#endif 61b877906bSopenharmony_ci 62b877906bSopenharmony_ci#define ERR_EXIT(err_msg, err_class) \ 63b877906bSopenharmony_ci do { \ 64b877906bSopenharmony_ci printf(err_msg); \ 65b877906bSopenharmony_ci fflush(stdout); \ 66b877906bSopenharmony_ci exit(1); \ 67b877906bSopenharmony_ci } while (0) 68b877906bSopenharmony_ci 69b877906bSopenharmony_cistatic const uint32_t fragShaderCode[] = { 70b877906bSopenharmony_ci 0x07230203,0x00010000,0x00080007,0x00000014,0x00000000,0x00020011,0x00000001,0x0006000b, 71b877906bSopenharmony_ci 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 72b877906bSopenharmony_ci 0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x00000011,0x00030010, 73b877906bSopenharmony_ci 0x00000004,0x00000007,0x00030003,0x00000002,0x00000190,0x00090004,0x415f4c47,0x735f4252, 74b877906bSopenharmony_ci 0x72617065,0x5f657461,0x64616873,0x6f5f7265,0x63656a62,0x00007374,0x00090004,0x415f4c47, 75b877906bSopenharmony_ci 0x735f4252,0x69646168,0x6c5f676e,0x75676e61,0x5f656761,0x70303234,0x006b6361,0x00040005, 76b877906bSopenharmony_ci 0x00000004,0x6e69616d,0x00000000,0x00050005,0x00000009,0x61724675,0x6c6f4367,0x0000726f, 77b877906bSopenharmony_ci 0x00030005,0x0000000d,0x00786574,0x00050005,0x00000011,0x63786574,0x64726f6f,0x00000000, 78b877906bSopenharmony_ci 0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x00000022,0x00000000, 79b877906bSopenharmony_ci 0x00040047,0x0000000d,0x00000021,0x00000000,0x00040047,0x00000011,0x0000001e,0x00000000, 80b877906bSopenharmony_ci 0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020, 81b877906bSopenharmony_ci 0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,0x00000007, 82b877906bSopenharmony_ci 0x0004003b,0x00000008,0x00000009,0x00000003,0x00090019,0x0000000a,0x00000006,0x00000001, 83b877906bSopenharmony_ci 0x00000000,0x00000000,0x00000000,0x00000001,0x00000000,0x0003001b,0x0000000b,0x0000000a, 84b877906bSopenharmony_ci 0x00040020,0x0000000c,0x00000000,0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000000, 85b877906bSopenharmony_ci 0x00040017,0x0000000f,0x00000006,0x00000002,0x00040020,0x00000010,0x00000001,0x0000000f, 86b877906bSopenharmony_ci 0x0004003b,0x00000010,0x00000011,0x00000001,0x00050036,0x00000002,0x00000004,0x00000000, 87b877906bSopenharmony_ci 0x00000003,0x000200f8,0x00000005,0x0004003d,0x0000000b,0x0000000e,0x0000000d,0x0004003d, 88b877906bSopenharmony_ci 0x0000000f,0x00000012,0x00000011,0x00050057,0x00000007,0x00000013,0x0000000e,0x00000012, 89b877906bSopenharmony_ci 0x0003003e,0x00000009,0x00000013,0x000100fd,0x00010038 90b877906bSopenharmony_ci}; 91b877906bSopenharmony_ci 92b877906bSopenharmony_cistatic const uint32_t vertShaderCode[] = { 93b877906bSopenharmony_ci 0x07230203,0x00010000,0x00080007,0x00000018,0x00000000,0x00020011,0x00000001,0x0006000b, 94b877906bSopenharmony_ci 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 95b877906bSopenharmony_ci 0x0009000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000b,0x00000010, 96b877906bSopenharmony_ci 0x00000014,0x00030003,0x00000002,0x00000190,0x00090004,0x415f4c47,0x735f4252,0x72617065, 97b877906bSopenharmony_ci 0x5f657461,0x64616873,0x6f5f7265,0x63656a62,0x00007374,0x00090004,0x415f4c47,0x735f4252, 98b877906bSopenharmony_ci 0x69646168,0x6c5f676e,0x75676e61,0x5f656761,0x70303234,0x006b6361,0x00040005,0x00000004, 99b877906bSopenharmony_ci 0x6e69616d,0x00000000,0x00050005,0x00000009,0x63786574,0x64726f6f,0x00000000,0x00040005, 100b877906bSopenharmony_ci 0x0000000b,0x72747461,0x00000000,0x00060005,0x0000000e,0x505f6c67,0x65567265,0x78657472, 101b877906bSopenharmony_ci 0x00000000,0x00060006,0x0000000e,0x00000000,0x505f6c67,0x7469736f,0x006e6f69,0x00030005, 102b877906bSopenharmony_ci 0x00000010,0x00000000,0x00030005,0x00000014,0x00736f70,0x00040047,0x00000009,0x0000001e, 103b877906bSopenharmony_ci 0x00000000,0x00040047,0x0000000b,0x0000001e,0x00000001,0x00050048,0x0000000e,0x00000000, 104b877906bSopenharmony_ci 0x0000000b,0x00000000,0x00030047,0x0000000e,0x00000002,0x00040047,0x00000014,0x0000001e, 105b877906bSopenharmony_ci 0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006, 106b877906bSopenharmony_ci 0x00000020,0x00040017,0x00000007,0x00000006,0x00000002,0x00040020,0x00000008,0x00000003, 107b877906bSopenharmony_ci 0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040020,0x0000000a,0x00000001, 108b877906bSopenharmony_ci 0x00000007,0x0004003b,0x0000000a,0x0000000b,0x00000001,0x00040017,0x0000000d,0x00000006, 109b877906bSopenharmony_ci 0x00000004,0x0003001e,0x0000000e,0x0000000d,0x00040020,0x0000000f,0x00000003,0x0000000e, 110b877906bSopenharmony_ci 0x0004003b,0x0000000f,0x00000010,0x00000003,0x00040015,0x00000011,0x00000020,0x00000001, 111b877906bSopenharmony_ci 0x0004002b,0x00000011,0x00000012,0x00000000,0x00040020,0x00000013,0x00000001,0x0000000d, 112b877906bSopenharmony_ci 0x0004003b,0x00000013,0x00000014,0x00000001,0x00040020,0x00000016,0x00000003,0x0000000d, 113b877906bSopenharmony_ci 0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003d, 114b877906bSopenharmony_ci 0x00000007,0x0000000c,0x0000000b,0x0003003e,0x00000009,0x0000000c,0x0004003d,0x0000000d, 115b877906bSopenharmony_ci 0x00000015,0x00000014,0x00050041,0x00000016,0x00000017,0x00000010,0x00000012,0x0003003e, 116b877906bSopenharmony_ci 0x00000017,0x00000015,0x000100fd,0x00010038 117b877906bSopenharmony_ci}; 118b877906bSopenharmony_ci 119b877906bSopenharmony_cistruct texture_object { 120b877906bSopenharmony_ci VkSampler sampler; 121b877906bSopenharmony_ci 122b877906bSopenharmony_ci VkImage image; 123b877906bSopenharmony_ci VkImageLayout imageLayout; 124b877906bSopenharmony_ci 125b877906bSopenharmony_ci VkDeviceMemory mem; 126b877906bSopenharmony_ci VkImageView view; 127b877906bSopenharmony_ci int32_t tex_width, tex_height; 128b877906bSopenharmony_ci}; 129b877906bSopenharmony_ci 130b877906bSopenharmony_cistatic int validation_error = 0; 131b877906bSopenharmony_ci 132b877906bSopenharmony_ciVKAPI_ATTR VkBool32 VKAPI_CALL 133b877906bSopenharmony_ciBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, 134b877906bSopenharmony_ci uint64_t srcObject, size_t location, int32_t msgCode, 135b877906bSopenharmony_ci const char *pLayerPrefix, const char *pMsg, 136b877906bSopenharmony_ci void *pUserData) { 137b877906bSopenharmony_ci#ifdef _WIN32 138b877906bSopenharmony_ci DebugBreak(); 139b877906bSopenharmony_ci#else 140b877906bSopenharmony_ci raise(SIGTRAP); 141b877906bSopenharmony_ci#endif 142b877906bSopenharmony_ci 143b877906bSopenharmony_ci return false; 144b877906bSopenharmony_ci} 145b877906bSopenharmony_ci 146b877906bSopenharmony_citypedef struct { 147b877906bSopenharmony_ci VkImage image; 148b877906bSopenharmony_ci VkCommandBuffer cmd; 149b877906bSopenharmony_ci VkImageView view; 150b877906bSopenharmony_ci} SwapchainBuffers; 151b877906bSopenharmony_ci 152b877906bSopenharmony_cistruct demo { 153b877906bSopenharmony_ci GLFWwindow* window; 154b877906bSopenharmony_ci VkSurfaceKHR surface; 155b877906bSopenharmony_ci bool use_staging_buffer; 156b877906bSopenharmony_ci 157b877906bSopenharmony_ci VkInstance inst; 158b877906bSopenharmony_ci VkPhysicalDevice gpu; 159b877906bSopenharmony_ci VkDevice device; 160b877906bSopenharmony_ci VkQueue queue; 161b877906bSopenharmony_ci VkPhysicalDeviceProperties gpu_props; 162b877906bSopenharmony_ci VkPhysicalDeviceFeatures gpu_features; 163b877906bSopenharmony_ci VkQueueFamilyProperties *queue_props; 164b877906bSopenharmony_ci uint32_t graphics_queue_node_index; 165b877906bSopenharmony_ci 166b877906bSopenharmony_ci uint32_t enabled_extension_count; 167b877906bSopenharmony_ci uint32_t enabled_layer_count; 168b877906bSopenharmony_ci const char *extension_names[64]; 169b877906bSopenharmony_ci const char *enabled_layers[64]; 170b877906bSopenharmony_ci 171b877906bSopenharmony_ci int width, height; 172b877906bSopenharmony_ci VkFormat format; 173b877906bSopenharmony_ci VkColorSpaceKHR color_space; 174b877906bSopenharmony_ci 175b877906bSopenharmony_ci uint32_t swapchainImageCount; 176b877906bSopenharmony_ci VkSwapchainKHR swapchain; 177b877906bSopenharmony_ci SwapchainBuffers *buffers; 178b877906bSopenharmony_ci 179b877906bSopenharmony_ci VkCommandPool cmd_pool; 180b877906bSopenharmony_ci 181b877906bSopenharmony_ci struct { 182b877906bSopenharmony_ci VkFormat format; 183b877906bSopenharmony_ci 184b877906bSopenharmony_ci VkImage image; 185b877906bSopenharmony_ci VkDeviceMemory mem; 186b877906bSopenharmony_ci VkImageView view; 187b877906bSopenharmony_ci } depth; 188b877906bSopenharmony_ci 189b877906bSopenharmony_ci struct texture_object textures[DEMO_TEXTURE_COUNT]; 190b877906bSopenharmony_ci 191b877906bSopenharmony_ci struct { 192b877906bSopenharmony_ci VkBuffer buf; 193b877906bSopenharmony_ci VkDeviceMemory mem; 194b877906bSopenharmony_ci 195b877906bSopenharmony_ci VkPipelineVertexInputStateCreateInfo vi; 196b877906bSopenharmony_ci VkVertexInputBindingDescription vi_bindings[1]; 197b877906bSopenharmony_ci VkVertexInputAttributeDescription vi_attrs[2]; 198b877906bSopenharmony_ci } vertices; 199b877906bSopenharmony_ci 200b877906bSopenharmony_ci VkCommandBuffer setup_cmd; // Command Buffer for initialization commands 201b877906bSopenharmony_ci VkCommandBuffer draw_cmd; // Command Buffer for drawing commands 202b877906bSopenharmony_ci VkPipelineLayout pipeline_layout; 203b877906bSopenharmony_ci VkDescriptorSetLayout desc_layout; 204b877906bSopenharmony_ci VkPipelineCache pipelineCache; 205b877906bSopenharmony_ci VkRenderPass render_pass; 206b877906bSopenharmony_ci VkPipeline pipeline; 207b877906bSopenharmony_ci 208b877906bSopenharmony_ci VkShaderModule vert_shader_module; 209b877906bSopenharmony_ci VkShaderModule frag_shader_module; 210b877906bSopenharmony_ci 211b877906bSopenharmony_ci VkDescriptorPool desc_pool; 212b877906bSopenharmony_ci VkDescriptorSet desc_set; 213b877906bSopenharmony_ci 214b877906bSopenharmony_ci VkFramebuffer *framebuffers; 215b877906bSopenharmony_ci 216b877906bSopenharmony_ci VkPhysicalDeviceMemoryProperties memory_properties; 217b877906bSopenharmony_ci 218b877906bSopenharmony_ci int32_t curFrame; 219b877906bSopenharmony_ci int32_t frameCount; 220b877906bSopenharmony_ci bool validate; 221b877906bSopenharmony_ci bool use_break; 222b877906bSopenharmony_ci VkDebugReportCallbackEXT msg_callback; 223b877906bSopenharmony_ci 224b877906bSopenharmony_ci float depthStencil; 225b877906bSopenharmony_ci float depthIncrement; 226b877906bSopenharmony_ci 227b877906bSopenharmony_ci uint32_t current_buffer; 228b877906bSopenharmony_ci uint32_t queue_count; 229b877906bSopenharmony_ci}; 230b877906bSopenharmony_ci 231b877906bSopenharmony_ciVKAPI_ATTR VkBool32 VKAPI_CALL 232b877906bSopenharmony_cidbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, 233b877906bSopenharmony_ci uint64_t srcObject, size_t location, int32_t msgCode, 234b877906bSopenharmony_ci const char *pLayerPrefix, const char *pMsg, void *pUserData) { 235b877906bSopenharmony_ci char *message = (char *)malloc(strlen(pMsg) + 100); 236b877906bSopenharmony_ci 237b877906bSopenharmony_ci assert(message); 238b877906bSopenharmony_ci 239b877906bSopenharmony_ci validation_error = 1; 240b877906bSopenharmony_ci 241b877906bSopenharmony_ci if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { 242b877906bSopenharmony_ci sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, 243b877906bSopenharmony_ci pMsg); 244b877906bSopenharmony_ci } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { 245b877906bSopenharmony_ci sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, 246b877906bSopenharmony_ci pMsg); 247b877906bSopenharmony_ci } else { 248b877906bSopenharmony_ci return false; 249b877906bSopenharmony_ci } 250b877906bSopenharmony_ci 251b877906bSopenharmony_ci printf("%s\n", message); 252b877906bSopenharmony_ci fflush(stdout); 253b877906bSopenharmony_ci free(message); 254b877906bSopenharmony_ci 255b877906bSopenharmony_ci /* 256b877906bSopenharmony_ci * false indicates that layer should not bail-out of an 257b877906bSopenharmony_ci * API call that had validation failures. This may mean that the 258b877906bSopenharmony_ci * app dies inside the driver due to invalid parameter(s). 259b877906bSopenharmony_ci * That's what would happen without validation layers, so we'll 260b877906bSopenharmony_ci * keep that behavior here. 261b877906bSopenharmony_ci */ 262b877906bSopenharmony_ci return false; 263b877906bSopenharmony_ci} 264b877906bSopenharmony_ci 265b877906bSopenharmony_ci// Forward declaration: 266b877906bSopenharmony_cistatic void demo_resize(struct demo *demo); 267b877906bSopenharmony_ci 268b877906bSopenharmony_cistatic bool memory_type_from_properties(struct demo *demo, uint32_t typeBits, 269b877906bSopenharmony_ci VkFlags requirements_mask, 270b877906bSopenharmony_ci uint32_t *typeIndex) { 271b877906bSopenharmony_ci uint32_t i; 272b877906bSopenharmony_ci // Search memtypes to find first index with those properties 273b877906bSopenharmony_ci for (i = 0; i < VK_MAX_MEMORY_TYPES; i++) { 274b877906bSopenharmony_ci if ((typeBits & 1) == 1) { 275b877906bSopenharmony_ci // Type is available, does it match user properties? 276b877906bSopenharmony_ci if ((demo->memory_properties.memoryTypes[i].propertyFlags & 277b877906bSopenharmony_ci requirements_mask) == requirements_mask) { 278b877906bSopenharmony_ci *typeIndex = i; 279b877906bSopenharmony_ci return true; 280b877906bSopenharmony_ci } 281b877906bSopenharmony_ci } 282b877906bSopenharmony_ci typeBits >>= 1; 283b877906bSopenharmony_ci } 284b877906bSopenharmony_ci // No memory types matched, return failure 285b877906bSopenharmony_ci return false; 286b877906bSopenharmony_ci} 287b877906bSopenharmony_ci 288b877906bSopenharmony_cistatic void demo_flush_init_cmd(struct demo *demo) { 289b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 290b877906bSopenharmony_ci 291b877906bSopenharmony_ci if (demo->setup_cmd == VK_NULL_HANDLE) 292b877906bSopenharmony_ci return; 293b877906bSopenharmony_ci 294b877906bSopenharmony_ci err = vkEndCommandBuffer(demo->setup_cmd); 295b877906bSopenharmony_ci assert(!err); 296b877906bSopenharmony_ci 297b877906bSopenharmony_ci const VkCommandBuffer cmd_bufs[] = {demo->setup_cmd}; 298b877906bSopenharmony_ci VkFence nullFence = {VK_NULL_HANDLE}; 299b877906bSopenharmony_ci VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 300b877906bSopenharmony_ci .pNext = NULL, 301b877906bSopenharmony_ci .waitSemaphoreCount = 0, 302b877906bSopenharmony_ci .pWaitSemaphores = NULL, 303b877906bSopenharmony_ci .pWaitDstStageMask = NULL, 304b877906bSopenharmony_ci .commandBufferCount = 1, 305b877906bSopenharmony_ci .pCommandBuffers = cmd_bufs, 306b877906bSopenharmony_ci .signalSemaphoreCount = 0, 307b877906bSopenharmony_ci .pSignalSemaphores = NULL}; 308b877906bSopenharmony_ci 309b877906bSopenharmony_ci err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence); 310b877906bSopenharmony_ci assert(!err); 311b877906bSopenharmony_ci 312b877906bSopenharmony_ci err = vkQueueWaitIdle(demo->queue); 313b877906bSopenharmony_ci assert(!err); 314b877906bSopenharmony_ci 315b877906bSopenharmony_ci vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, cmd_bufs); 316b877906bSopenharmony_ci demo->setup_cmd = VK_NULL_HANDLE; 317b877906bSopenharmony_ci} 318b877906bSopenharmony_ci 319b877906bSopenharmony_cistatic void demo_set_image_layout(struct demo *demo, VkImage image, 320b877906bSopenharmony_ci VkImageAspectFlags aspectMask, 321b877906bSopenharmony_ci VkImageLayout old_image_layout, 322b877906bSopenharmony_ci VkImageLayout new_image_layout, 323b877906bSopenharmony_ci VkAccessFlagBits srcAccessMask) { 324b877906bSopenharmony_ci 325b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 326b877906bSopenharmony_ci 327b877906bSopenharmony_ci if (demo->setup_cmd == VK_NULL_HANDLE) { 328b877906bSopenharmony_ci const VkCommandBufferAllocateInfo cmd = { 329b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 330b877906bSopenharmony_ci .pNext = NULL, 331b877906bSopenharmony_ci .commandPool = demo->cmd_pool, 332b877906bSopenharmony_ci .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 333b877906bSopenharmony_ci .commandBufferCount = 1, 334b877906bSopenharmony_ci }; 335b877906bSopenharmony_ci 336b877906bSopenharmony_ci err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->setup_cmd); 337b877906bSopenharmony_ci assert(!err); 338b877906bSopenharmony_ci 339b877906bSopenharmony_ci VkCommandBufferBeginInfo cmd_buf_info = { 340b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 341b877906bSopenharmony_ci .pNext = NULL, 342b877906bSopenharmony_ci .flags = 0, 343b877906bSopenharmony_ci .pInheritanceInfo = NULL, 344b877906bSopenharmony_ci }; 345b877906bSopenharmony_ci err = vkBeginCommandBuffer(demo->setup_cmd, &cmd_buf_info); 346b877906bSopenharmony_ci assert(!err); 347b877906bSopenharmony_ci } 348b877906bSopenharmony_ci 349b877906bSopenharmony_ci VkImageMemoryBarrier image_memory_barrier = { 350b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 351b877906bSopenharmony_ci .pNext = NULL, 352b877906bSopenharmony_ci .srcAccessMask = srcAccessMask, 353b877906bSopenharmony_ci .dstAccessMask = 0, 354b877906bSopenharmony_ci .oldLayout = old_image_layout, 355b877906bSopenharmony_ci .newLayout = new_image_layout, 356b877906bSopenharmony_ci .image = image, 357b877906bSopenharmony_ci .subresourceRange = {aspectMask, 0, 1, 0, 1}}; 358b877906bSopenharmony_ci 359b877906bSopenharmony_ci if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { 360b877906bSopenharmony_ci /* Make sure anything that was copying from this image has completed */ 361b877906bSopenharmony_ci image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 362b877906bSopenharmony_ci } 363b877906bSopenharmony_ci 364b877906bSopenharmony_ci if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { 365b877906bSopenharmony_ci image_memory_barrier.dstAccessMask = 366b877906bSopenharmony_ci VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 367b877906bSopenharmony_ci } 368b877906bSopenharmony_ci 369b877906bSopenharmony_ci if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { 370b877906bSopenharmony_ci image_memory_barrier.dstAccessMask = 371b877906bSopenharmony_ci VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; 372b877906bSopenharmony_ci } 373b877906bSopenharmony_ci 374b877906bSopenharmony_ci if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { 375b877906bSopenharmony_ci /* Make sure any Copy or CPU writes to image are flushed */ 376b877906bSopenharmony_ci image_memory_barrier.dstAccessMask = 377b877906bSopenharmony_ci VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; 378b877906bSopenharmony_ci } 379b877906bSopenharmony_ci 380b877906bSopenharmony_ci VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier; 381b877906bSopenharmony_ci 382b877906bSopenharmony_ci VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 383b877906bSopenharmony_ci VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 384b877906bSopenharmony_ci 385b877906bSopenharmony_ci vkCmdPipelineBarrier(demo->setup_cmd, src_stages, dest_stages, 0, 0, NULL, 386b877906bSopenharmony_ci 0, NULL, 1, pmemory_barrier); 387b877906bSopenharmony_ci} 388b877906bSopenharmony_ci 389b877906bSopenharmony_cistatic void demo_draw_build_cmd(struct demo *demo) { 390b877906bSopenharmony_ci const VkCommandBufferBeginInfo cmd_buf_info = { 391b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 392b877906bSopenharmony_ci .pNext = NULL, 393b877906bSopenharmony_ci .flags = 0, 394b877906bSopenharmony_ci .pInheritanceInfo = NULL, 395b877906bSopenharmony_ci }; 396b877906bSopenharmony_ci const VkClearValue clear_values[2] = { 397b877906bSopenharmony_ci [0] = {.color.float32 = {0.2f, 0.2f, 0.2f, 0.2f}}, 398b877906bSopenharmony_ci [1] = {.depthStencil = {demo->depthStencil, 0}}, 399b877906bSopenharmony_ci }; 400b877906bSopenharmony_ci const VkRenderPassBeginInfo rp_begin = { 401b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 402b877906bSopenharmony_ci .pNext = NULL, 403b877906bSopenharmony_ci .renderPass = demo->render_pass, 404b877906bSopenharmony_ci .framebuffer = demo->framebuffers[demo->current_buffer], 405b877906bSopenharmony_ci .renderArea.offset.x = 0, 406b877906bSopenharmony_ci .renderArea.offset.y = 0, 407b877906bSopenharmony_ci .renderArea.extent.width = demo->width, 408b877906bSopenharmony_ci .renderArea.extent.height = demo->height, 409b877906bSopenharmony_ci .clearValueCount = 2, 410b877906bSopenharmony_ci .pClearValues = clear_values, 411b877906bSopenharmony_ci }; 412b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 413b877906bSopenharmony_ci 414b877906bSopenharmony_ci err = vkBeginCommandBuffer(demo->draw_cmd, &cmd_buf_info); 415b877906bSopenharmony_ci assert(!err); 416b877906bSopenharmony_ci 417b877906bSopenharmony_ci // We can use LAYOUT_UNDEFINED as a wildcard here because we don't care what 418b877906bSopenharmony_ci // happens to the previous contents of the image 419b877906bSopenharmony_ci VkImageMemoryBarrier image_memory_barrier = { 420b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 421b877906bSopenharmony_ci .pNext = NULL, 422b877906bSopenharmony_ci .srcAccessMask = 0, 423b877906bSopenharmony_ci .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 424b877906bSopenharmony_ci .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, 425b877906bSopenharmony_ci .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 426b877906bSopenharmony_ci .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 427b877906bSopenharmony_ci .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 428b877906bSopenharmony_ci .image = demo->buffers[demo->current_buffer].image, 429b877906bSopenharmony_ci .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}}; 430b877906bSopenharmony_ci 431b877906bSopenharmony_ci vkCmdPipelineBarrier(demo->draw_cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 432b877906bSopenharmony_ci VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0, 433b877906bSopenharmony_ci NULL, 1, &image_memory_barrier); 434b877906bSopenharmony_ci vkCmdBeginRenderPass(demo->draw_cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); 435b877906bSopenharmony_ci vkCmdBindPipeline(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, 436b877906bSopenharmony_ci demo->pipeline); 437b877906bSopenharmony_ci vkCmdBindDescriptorSets(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, 438b877906bSopenharmony_ci demo->pipeline_layout, 0, 1, &demo->desc_set, 0, 439b877906bSopenharmony_ci NULL); 440b877906bSopenharmony_ci 441b877906bSopenharmony_ci VkViewport viewport; 442b877906bSopenharmony_ci memset(&viewport, 0, sizeof(viewport)); 443b877906bSopenharmony_ci viewport.height = (float)demo->height; 444b877906bSopenharmony_ci viewport.width = (float)demo->width; 445b877906bSopenharmony_ci viewport.minDepth = (float)0.0f; 446b877906bSopenharmony_ci viewport.maxDepth = (float)1.0f; 447b877906bSopenharmony_ci vkCmdSetViewport(demo->draw_cmd, 0, 1, &viewport); 448b877906bSopenharmony_ci 449b877906bSopenharmony_ci VkRect2D scissor; 450b877906bSopenharmony_ci memset(&scissor, 0, sizeof(scissor)); 451b877906bSopenharmony_ci scissor.extent.width = demo->width; 452b877906bSopenharmony_ci scissor.extent.height = demo->height; 453b877906bSopenharmony_ci scissor.offset.x = 0; 454b877906bSopenharmony_ci scissor.offset.y = 0; 455b877906bSopenharmony_ci vkCmdSetScissor(demo->draw_cmd, 0, 1, &scissor); 456b877906bSopenharmony_ci 457b877906bSopenharmony_ci VkDeviceSize offsets[1] = {0}; 458b877906bSopenharmony_ci vkCmdBindVertexBuffers(demo->draw_cmd, VERTEX_BUFFER_BIND_ID, 1, 459b877906bSopenharmony_ci &demo->vertices.buf, offsets); 460b877906bSopenharmony_ci 461b877906bSopenharmony_ci vkCmdDraw(demo->draw_cmd, 3, 1, 0, 0); 462b877906bSopenharmony_ci vkCmdEndRenderPass(demo->draw_cmd); 463b877906bSopenharmony_ci 464b877906bSopenharmony_ci VkImageMemoryBarrier prePresentBarrier = { 465b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 466b877906bSopenharmony_ci .pNext = NULL, 467b877906bSopenharmony_ci .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 468b877906bSopenharmony_ci .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, 469b877906bSopenharmony_ci .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 470b877906bSopenharmony_ci .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 471b877906bSopenharmony_ci .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 472b877906bSopenharmony_ci .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 473b877906bSopenharmony_ci .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}}; 474b877906bSopenharmony_ci 475b877906bSopenharmony_ci prePresentBarrier.image = demo->buffers[demo->current_buffer].image; 476b877906bSopenharmony_ci VkImageMemoryBarrier *pmemory_barrier = &prePresentBarrier; 477b877906bSopenharmony_ci vkCmdPipelineBarrier(demo->draw_cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 478b877906bSopenharmony_ci VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0, 479b877906bSopenharmony_ci NULL, 1, pmemory_barrier); 480b877906bSopenharmony_ci 481b877906bSopenharmony_ci err = vkEndCommandBuffer(demo->draw_cmd); 482b877906bSopenharmony_ci assert(!err); 483b877906bSopenharmony_ci} 484b877906bSopenharmony_ci 485b877906bSopenharmony_cistatic void demo_draw(struct demo *demo) { 486b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 487b877906bSopenharmony_ci VkSemaphore imageAcquiredSemaphore, drawCompleteSemaphore; 488b877906bSopenharmony_ci VkSemaphoreCreateInfo semaphoreCreateInfo = { 489b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, 490b877906bSopenharmony_ci .pNext = NULL, 491b877906bSopenharmony_ci .flags = 0, 492b877906bSopenharmony_ci }; 493b877906bSopenharmony_ci 494b877906bSopenharmony_ci err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, 495b877906bSopenharmony_ci NULL, &imageAcquiredSemaphore); 496b877906bSopenharmony_ci assert(!err); 497b877906bSopenharmony_ci 498b877906bSopenharmony_ci err = vkCreateSemaphore(demo->device, &semaphoreCreateInfo, 499b877906bSopenharmony_ci NULL, &drawCompleteSemaphore); 500b877906bSopenharmony_ci assert(!err); 501b877906bSopenharmony_ci 502b877906bSopenharmony_ci // Get the index of the next available swapchain image: 503b877906bSopenharmony_ci err = vkAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX, 504b877906bSopenharmony_ci imageAcquiredSemaphore, 505b877906bSopenharmony_ci (VkFence)0, // TODO: Show use of fence 506b877906bSopenharmony_ci &demo->current_buffer); 507b877906bSopenharmony_ci if (err == VK_ERROR_OUT_OF_DATE_KHR) { 508b877906bSopenharmony_ci // demo->swapchain is out of date (e.g. the window was resized) and 509b877906bSopenharmony_ci // must be recreated: 510b877906bSopenharmony_ci demo_resize(demo); 511b877906bSopenharmony_ci demo_draw(demo); 512b877906bSopenharmony_ci vkDestroySemaphore(demo->device, imageAcquiredSemaphore, NULL); 513b877906bSopenharmony_ci vkDestroySemaphore(demo->device, drawCompleteSemaphore, NULL); 514b877906bSopenharmony_ci return; 515b877906bSopenharmony_ci } else if (err == VK_SUBOPTIMAL_KHR) { 516b877906bSopenharmony_ci // demo->swapchain is not as optimal as it could be, but the platform's 517b877906bSopenharmony_ci // presentation engine will still present the image correctly. 518b877906bSopenharmony_ci } else { 519b877906bSopenharmony_ci assert(!err); 520b877906bSopenharmony_ci } 521b877906bSopenharmony_ci 522b877906bSopenharmony_ci demo_flush_init_cmd(demo); 523b877906bSopenharmony_ci 524b877906bSopenharmony_ci // Wait for the present complete semaphore to be signaled to ensure 525b877906bSopenharmony_ci // that the image won't be rendered to until the presentation 526b877906bSopenharmony_ci // engine has fully released ownership to the application, and it is 527b877906bSopenharmony_ci // okay to render to the image. 528b877906bSopenharmony_ci 529b877906bSopenharmony_ci demo_draw_build_cmd(demo); 530b877906bSopenharmony_ci VkFence nullFence = VK_NULL_HANDLE; 531b877906bSopenharmony_ci VkPipelineStageFlags pipe_stage_flags = 532b877906bSopenharmony_ci VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; 533b877906bSopenharmony_ci VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 534b877906bSopenharmony_ci .pNext = NULL, 535b877906bSopenharmony_ci .waitSemaphoreCount = 1, 536b877906bSopenharmony_ci .pWaitSemaphores = &imageAcquiredSemaphore, 537b877906bSopenharmony_ci .pWaitDstStageMask = &pipe_stage_flags, 538b877906bSopenharmony_ci .commandBufferCount = 1, 539b877906bSopenharmony_ci .pCommandBuffers = &demo->draw_cmd, 540b877906bSopenharmony_ci .signalSemaphoreCount = 1, 541b877906bSopenharmony_ci .pSignalSemaphores = &drawCompleteSemaphore}; 542b877906bSopenharmony_ci 543b877906bSopenharmony_ci err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence); 544b877906bSopenharmony_ci assert(!err); 545b877906bSopenharmony_ci 546b877906bSopenharmony_ci VkPresentInfoKHR present = { 547b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 548b877906bSopenharmony_ci .pNext = NULL, 549b877906bSopenharmony_ci .waitSemaphoreCount = 1, 550b877906bSopenharmony_ci .pWaitSemaphores = &drawCompleteSemaphore, 551b877906bSopenharmony_ci .swapchainCount = 1, 552b877906bSopenharmony_ci .pSwapchains = &demo->swapchain, 553b877906bSopenharmony_ci .pImageIndices = &demo->current_buffer, 554b877906bSopenharmony_ci }; 555b877906bSopenharmony_ci 556b877906bSopenharmony_ci err = vkQueuePresentKHR(demo->queue, &present); 557b877906bSopenharmony_ci if (err == VK_ERROR_OUT_OF_DATE_KHR) { 558b877906bSopenharmony_ci // demo->swapchain is out of date (e.g. the window was resized) and 559b877906bSopenharmony_ci // must be recreated: 560b877906bSopenharmony_ci demo_resize(demo); 561b877906bSopenharmony_ci } else if (err == VK_SUBOPTIMAL_KHR) { 562b877906bSopenharmony_ci // demo->swapchain is not as optimal as it could be, but the platform's 563b877906bSopenharmony_ci // presentation engine will still present the image correctly. 564b877906bSopenharmony_ci } else { 565b877906bSopenharmony_ci assert(!err); 566b877906bSopenharmony_ci } 567b877906bSopenharmony_ci 568b877906bSopenharmony_ci err = vkQueueWaitIdle(demo->queue); 569b877906bSopenharmony_ci assert(err == VK_SUCCESS); 570b877906bSopenharmony_ci 571b877906bSopenharmony_ci vkDestroySemaphore(demo->device, imageAcquiredSemaphore, NULL); 572b877906bSopenharmony_ci vkDestroySemaphore(demo->device, drawCompleteSemaphore, NULL); 573b877906bSopenharmony_ci} 574b877906bSopenharmony_ci 575b877906bSopenharmony_cistatic void demo_prepare_buffers(struct demo *demo) { 576b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 577b877906bSopenharmony_ci VkSwapchainKHR oldSwapchain = demo->swapchain; 578b877906bSopenharmony_ci 579b877906bSopenharmony_ci // Check the surface capabilities and formats 580b877906bSopenharmony_ci VkSurfaceCapabilitiesKHR surfCapabilities; 581b877906bSopenharmony_ci err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( 582b877906bSopenharmony_ci demo->gpu, demo->surface, &surfCapabilities); 583b877906bSopenharmony_ci assert(!err); 584b877906bSopenharmony_ci 585b877906bSopenharmony_ci uint32_t presentModeCount; 586b877906bSopenharmony_ci err = vkGetPhysicalDeviceSurfacePresentModesKHR( 587b877906bSopenharmony_ci demo->gpu, demo->surface, &presentModeCount, NULL); 588b877906bSopenharmony_ci assert(!err); 589b877906bSopenharmony_ci VkPresentModeKHR *presentModes = 590b877906bSopenharmony_ci (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR)); 591b877906bSopenharmony_ci assert(presentModes); 592b877906bSopenharmony_ci err = vkGetPhysicalDeviceSurfacePresentModesKHR( 593b877906bSopenharmony_ci demo->gpu, demo->surface, &presentModeCount, presentModes); 594b877906bSopenharmony_ci assert(!err); 595b877906bSopenharmony_ci 596b877906bSopenharmony_ci VkExtent2D swapchainExtent; 597b877906bSopenharmony_ci // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF. 598b877906bSopenharmony_ci if (surfCapabilities.currentExtent.width == 0xFFFFFFFF) { 599b877906bSopenharmony_ci // If the surface size is undefined, the size is set to the size 600b877906bSopenharmony_ci // of the images requested, which must fit within the minimum and 601b877906bSopenharmony_ci // maximum values. 602b877906bSopenharmony_ci swapchainExtent.width = demo->width; 603b877906bSopenharmony_ci swapchainExtent.height = demo->height; 604b877906bSopenharmony_ci 605b877906bSopenharmony_ci if (swapchainExtent.width < surfCapabilities.minImageExtent.width) { 606b877906bSopenharmony_ci swapchainExtent.width = surfCapabilities.minImageExtent.width; 607b877906bSopenharmony_ci } else if (swapchainExtent.width > surfCapabilities.maxImageExtent.width) { 608b877906bSopenharmony_ci swapchainExtent.width = surfCapabilities.maxImageExtent.width; 609b877906bSopenharmony_ci } 610b877906bSopenharmony_ci 611b877906bSopenharmony_ci if (swapchainExtent.height < surfCapabilities.minImageExtent.height) { 612b877906bSopenharmony_ci swapchainExtent.height = surfCapabilities.minImageExtent.height; 613b877906bSopenharmony_ci } else if (swapchainExtent.height > surfCapabilities.maxImageExtent.height) { 614b877906bSopenharmony_ci swapchainExtent.height = surfCapabilities.maxImageExtent.height; 615b877906bSopenharmony_ci } 616b877906bSopenharmony_ci } else { 617b877906bSopenharmony_ci // If the surface size is defined, the swap chain size must match 618b877906bSopenharmony_ci swapchainExtent = surfCapabilities.currentExtent; 619b877906bSopenharmony_ci demo->width = surfCapabilities.currentExtent.width; 620b877906bSopenharmony_ci demo->height = surfCapabilities.currentExtent.height; 621b877906bSopenharmony_ci } 622b877906bSopenharmony_ci 623b877906bSopenharmony_ci VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; 624b877906bSopenharmony_ci 625b877906bSopenharmony_ci // Determine the number of VkImage's to use in the swap chain. 626b877906bSopenharmony_ci // Application desires to only acquire 1 image at a time (which is 627b877906bSopenharmony_ci // "surfCapabilities.minImageCount"). 628b877906bSopenharmony_ci uint32_t desiredNumOfSwapchainImages = surfCapabilities.minImageCount; 629b877906bSopenharmony_ci // If maxImageCount is 0, we can ask for as many images as we want; 630b877906bSopenharmony_ci // otherwise we're limited to maxImageCount 631b877906bSopenharmony_ci if ((surfCapabilities.maxImageCount > 0) && 632b877906bSopenharmony_ci (desiredNumOfSwapchainImages > surfCapabilities.maxImageCount)) { 633b877906bSopenharmony_ci // Application must settle for fewer images than desired: 634b877906bSopenharmony_ci desiredNumOfSwapchainImages = surfCapabilities.maxImageCount; 635b877906bSopenharmony_ci } 636b877906bSopenharmony_ci 637b877906bSopenharmony_ci VkSurfaceTransformFlagsKHR preTransform; 638b877906bSopenharmony_ci if (surfCapabilities.supportedTransforms & 639b877906bSopenharmony_ci VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { 640b877906bSopenharmony_ci preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 641b877906bSopenharmony_ci } else { 642b877906bSopenharmony_ci preTransform = surfCapabilities.currentTransform; 643b877906bSopenharmony_ci } 644b877906bSopenharmony_ci 645b877906bSopenharmony_ci const VkSwapchainCreateInfoKHR swapchain = { 646b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 647b877906bSopenharmony_ci .pNext = NULL, 648b877906bSopenharmony_ci .surface = demo->surface, 649b877906bSopenharmony_ci .minImageCount = desiredNumOfSwapchainImages, 650b877906bSopenharmony_ci .imageFormat = demo->format, 651b877906bSopenharmony_ci .imageColorSpace = demo->color_space, 652b877906bSopenharmony_ci .imageExtent = 653b877906bSopenharmony_ci { 654b877906bSopenharmony_ci .width = swapchainExtent.width, .height = swapchainExtent.height, 655b877906bSopenharmony_ci }, 656b877906bSopenharmony_ci .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 657b877906bSopenharmony_ci .preTransform = preTransform, 658b877906bSopenharmony_ci .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, 659b877906bSopenharmony_ci .imageArrayLayers = 1, 660b877906bSopenharmony_ci .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, 661b877906bSopenharmony_ci .queueFamilyIndexCount = 0, 662b877906bSopenharmony_ci .pQueueFamilyIndices = NULL, 663b877906bSopenharmony_ci .presentMode = swapchainPresentMode, 664b877906bSopenharmony_ci .oldSwapchain = oldSwapchain, 665b877906bSopenharmony_ci .clipped = true, 666b877906bSopenharmony_ci }; 667b877906bSopenharmony_ci uint32_t i; 668b877906bSopenharmony_ci 669b877906bSopenharmony_ci err = vkCreateSwapchainKHR(demo->device, &swapchain, NULL, &demo->swapchain); 670b877906bSopenharmony_ci assert(!err); 671b877906bSopenharmony_ci 672b877906bSopenharmony_ci // If we just re-created an existing swapchain, we should destroy the old 673b877906bSopenharmony_ci // swapchain at this point. 674b877906bSopenharmony_ci // Note: destroying the swapchain also cleans up all its associated 675b877906bSopenharmony_ci // presentable images once the platform is done with them. 676b877906bSopenharmony_ci if (oldSwapchain != VK_NULL_HANDLE) { 677b877906bSopenharmony_ci vkDestroySwapchainKHR(demo->device, oldSwapchain, NULL); 678b877906bSopenharmony_ci } 679b877906bSopenharmony_ci 680b877906bSopenharmony_ci err = vkGetSwapchainImagesKHR(demo->device, demo->swapchain, 681b877906bSopenharmony_ci &demo->swapchainImageCount, NULL); 682b877906bSopenharmony_ci assert(!err); 683b877906bSopenharmony_ci 684b877906bSopenharmony_ci VkImage *swapchainImages = 685b877906bSopenharmony_ci (VkImage *)malloc(demo->swapchainImageCount * sizeof(VkImage)); 686b877906bSopenharmony_ci assert(swapchainImages); 687b877906bSopenharmony_ci err = vkGetSwapchainImagesKHR(demo->device, demo->swapchain, 688b877906bSopenharmony_ci &demo->swapchainImageCount, 689b877906bSopenharmony_ci swapchainImages); 690b877906bSopenharmony_ci assert(!err); 691b877906bSopenharmony_ci 692b877906bSopenharmony_ci demo->buffers = (SwapchainBuffers *)malloc(sizeof(SwapchainBuffers) * 693b877906bSopenharmony_ci demo->swapchainImageCount); 694b877906bSopenharmony_ci assert(demo->buffers); 695b877906bSopenharmony_ci 696b877906bSopenharmony_ci for (i = 0; i < demo->swapchainImageCount; i++) { 697b877906bSopenharmony_ci VkImageViewCreateInfo color_attachment_view = { 698b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 699b877906bSopenharmony_ci .pNext = NULL, 700b877906bSopenharmony_ci .format = demo->format, 701b877906bSopenharmony_ci .components = 702b877906bSopenharmony_ci { 703b877906bSopenharmony_ci .r = VK_COMPONENT_SWIZZLE_R, 704b877906bSopenharmony_ci .g = VK_COMPONENT_SWIZZLE_G, 705b877906bSopenharmony_ci .b = VK_COMPONENT_SWIZZLE_B, 706b877906bSopenharmony_ci .a = VK_COMPONENT_SWIZZLE_A, 707b877906bSopenharmony_ci }, 708b877906bSopenharmony_ci .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 709b877906bSopenharmony_ci .baseMipLevel = 0, 710b877906bSopenharmony_ci .levelCount = 1, 711b877906bSopenharmony_ci .baseArrayLayer = 0, 712b877906bSopenharmony_ci .layerCount = 1}, 713b877906bSopenharmony_ci .viewType = VK_IMAGE_VIEW_TYPE_2D, 714b877906bSopenharmony_ci .flags = 0, 715b877906bSopenharmony_ci }; 716b877906bSopenharmony_ci 717b877906bSopenharmony_ci demo->buffers[i].image = swapchainImages[i]; 718b877906bSopenharmony_ci 719b877906bSopenharmony_ci color_attachment_view.image = demo->buffers[i].image; 720b877906bSopenharmony_ci 721b877906bSopenharmony_ci err = vkCreateImageView(demo->device, &color_attachment_view, NULL, 722b877906bSopenharmony_ci &demo->buffers[i].view); 723b877906bSopenharmony_ci assert(!err); 724b877906bSopenharmony_ci } 725b877906bSopenharmony_ci 726b877906bSopenharmony_ci demo->current_buffer = 0; 727b877906bSopenharmony_ci 728b877906bSopenharmony_ci if (NULL != presentModes) { 729b877906bSopenharmony_ci free(presentModes); 730b877906bSopenharmony_ci } 731b877906bSopenharmony_ci} 732b877906bSopenharmony_ci 733b877906bSopenharmony_cistatic void demo_prepare_depth(struct demo *demo) { 734b877906bSopenharmony_ci const VkFormat depth_format = VK_FORMAT_D16_UNORM; 735b877906bSopenharmony_ci const VkImageCreateInfo image = { 736b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 737b877906bSopenharmony_ci .pNext = NULL, 738b877906bSopenharmony_ci .imageType = VK_IMAGE_TYPE_2D, 739b877906bSopenharmony_ci .format = depth_format, 740b877906bSopenharmony_ci .extent = {demo->width, demo->height, 1}, 741b877906bSopenharmony_ci .mipLevels = 1, 742b877906bSopenharmony_ci .arrayLayers = 1, 743b877906bSopenharmony_ci .samples = VK_SAMPLE_COUNT_1_BIT, 744b877906bSopenharmony_ci .tiling = VK_IMAGE_TILING_OPTIMAL, 745b877906bSopenharmony_ci .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 746b877906bSopenharmony_ci .flags = 0, 747b877906bSopenharmony_ci }; 748b877906bSopenharmony_ci VkMemoryAllocateInfo mem_alloc = { 749b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 750b877906bSopenharmony_ci .pNext = NULL, 751b877906bSopenharmony_ci .allocationSize = 0, 752b877906bSopenharmony_ci .memoryTypeIndex = 0, 753b877906bSopenharmony_ci }; 754b877906bSopenharmony_ci VkImageViewCreateInfo view = { 755b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 756b877906bSopenharmony_ci .pNext = NULL, 757b877906bSopenharmony_ci .image = VK_NULL_HANDLE, 758b877906bSopenharmony_ci .format = depth_format, 759b877906bSopenharmony_ci .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, 760b877906bSopenharmony_ci .baseMipLevel = 0, 761b877906bSopenharmony_ci .levelCount = 1, 762b877906bSopenharmony_ci .baseArrayLayer = 0, 763b877906bSopenharmony_ci .layerCount = 1}, 764b877906bSopenharmony_ci .flags = 0, 765b877906bSopenharmony_ci .viewType = VK_IMAGE_VIEW_TYPE_2D, 766b877906bSopenharmony_ci }; 767b877906bSopenharmony_ci 768b877906bSopenharmony_ci VkMemoryRequirements mem_reqs; 769b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 770b877906bSopenharmony_ci bool U_ASSERT_ONLY pass; 771b877906bSopenharmony_ci 772b877906bSopenharmony_ci demo->depth.format = depth_format; 773b877906bSopenharmony_ci 774b877906bSopenharmony_ci /* create image */ 775b877906bSopenharmony_ci err = vkCreateImage(demo->device, &image, NULL, &demo->depth.image); 776b877906bSopenharmony_ci assert(!err); 777b877906bSopenharmony_ci 778b877906bSopenharmony_ci /* get memory requirements for this object */ 779b877906bSopenharmony_ci vkGetImageMemoryRequirements(demo->device, demo->depth.image, &mem_reqs); 780b877906bSopenharmony_ci 781b877906bSopenharmony_ci /* select memory size and type */ 782b877906bSopenharmony_ci mem_alloc.allocationSize = mem_reqs.size; 783b877906bSopenharmony_ci pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits, 784b877906bSopenharmony_ci 0, /* No requirements */ 785b877906bSopenharmony_ci &mem_alloc.memoryTypeIndex); 786b877906bSopenharmony_ci assert(pass); 787b877906bSopenharmony_ci 788b877906bSopenharmony_ci /* allocate memory */ 789b877906bSopenharmony_ci err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &demo->depth.mem); 790b877906bSopenharmony_ci assert(!err); 791b877906bSopenharmony_ci 792b877906bSopenharmony_ci /* bind memory */ 793b877906bSopenharmony_ci err = 794b877906bSopenharmony_ci vkBindImageMemory(demo->device, demo->depth.image, demo->depth.mem, 0); 795b877906bSopenharmony_ci assert(!err); 796b877906bSopenharmony_ci 797b877906bSopenharmony_ci demo_set_image_layout(demo, demo->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT, 798b877906bSopenharmony_ci VK_IMAGE_LAYOUT_UNDEFINED, 799b877906bSopenharmony_ci VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 800b877906bSopenharmony_ci 0); 801b877906bSopenharmony_ci 802b877906bSopenharmony_ci /* create image view */ 803b877906bSopenharmony_ci view.image = demo->depth.image; 804b877906bSopenharmony_ci err = vkCreateImageView(demo->device, &view, NULL, &demo->depth.view); 805b877906bSopenharmony_ci assert(!err); 806b877906bSopenharmony_ci} 807b877906bSopenharmony_ci 808b877906bSopenharmony_cistatic void 809b877906bSopenharmony_cidemo_prepare_texture_image(struct demo *demo, const uint32_t *tex_colors, 810b877906bSopenharmony_ci struct texture_object *tex_obj, VkImageTiling tiling, 811b877906bSopenharmony_ci VkImageUsageFlags usage, VkFlags required_props) { 812b877906bSopenharmony_ci const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; 813b877906bSopenharmony_ci const int32_t tex_width = 2; 814b877906bSopenharmony_ci const int32_t tex_height = 2; 815b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 816b877906bSopenharmony_ci bool U_ASSERT_ONLY pass; 817b877906bSopenharmony_ci 818b877906bSopenharmony_ci tex_obj->tex_width = tex_width; 819b877906bSopenharmony_ci tex_obj->tex_height = tex_height; 820b877906bSopenharmony_ci 821b877906bSopenharmony_ci const VkImageCreateInfo image_create_info = { 822b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 823b877906bSopenharmony_ci .pNext = NULL, 824b877906bSopenharmony_ci .imageType = VK_IMAGE_TYPE_2D, 825b877906bSopenharmony_ci .format = tex_format, 826b877906bSopenharmony_ci .extent = {tex_width, tex_height, 1}, 827b877906bSopenharmony_ci .mipLevels = 1, 828b877906bSopenharmony_ci .arrayLayers = 1, 829b877906bSopenharmony_ci .samples = VK_SAMPLE_COUNT_1_BIT, 830b877906bSopenharmony_ci .tiling = tiling, 831b877906bSopenharmony_ci .usage = usage, 832b877906bSopenharmony_ci .flags = 0, 833b877906bSopenharmony_ci .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED 834b877906bSopenharmony_ci }; 835b877906bSopenharmony_ci VkMemoryAllocateInfo mem_alloc = { 836b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 837b877906bSopenharmony_ci .pNext = NULL, 838b877906bSopenharmony_ci .allocationSize = 0, 839b877906bSopenharmony_ci .memoryTypeIndex = 0, 840b877906bSopenharmony_ci }; 841b877906bSopenharmony_ci 842b877906bSopenharmony_ci VkMemoryRequirements mem_reqs; 843b877906bSopenharmony_ci 844b877906bSopenharmony_ci err = 845b877906bSopenharmony_ci vkCreateImage(demo->device, &image_create_info, NULL, &tex_obj->image); 846b877906bSopenharmony_ci assert(!err); 847b877906bSopenharmony_ci 848b877906bSopenharmony_ci vkGetImageMemoryRequirements(demo->device, tex_obj->image, &mem_reqs); 849b877906bSopenharmony_ci 850b877906bSopenharmony_ci mem_alloc.allocationSize = mem_reqs.size; 851b877906bSopenharmony_ci pass = 852b877906bSopenharmony_ci memory_type_from_properties(demo, mem_reqs.memoryTypeBits, 853b877906bSopenharmony_ci required_props, &mem_alloc.memoryTypeIndex); 854b877906bSopenharmony_ci assert(pass); 855b877906bSopenharmony_ci 856b877906bSopenharmony_ci /* allocate memory */ 857b877906bSopenharmony_ci err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &tex_obj->mem); 858b877906bSopenharmony_ci assert(!err); 859b877906bSopenharmony_ci 860b877906bSopenharmony_ci /* bind memory */ 861b877906bSopenharmony_ci err = vkBindImageMemory(demo->device, tex_obj->image, tex_obj->mem, 0); 862b877906bSopenharmony_ci assert(!err); 863b877906bSopenharmony_ci 864b877906bSopenharmony_ci if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { 865b877906bSopenharmony_ci const VkImageSubresource subres = { 866b877906bSopenharmony_ci .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 867b877906bSopenharmony_ci .mipLevel = 0, 868b877906bSopenharmony_ci .arrayLayer = 0, 869b877906bSopenharmony_ci }; 870b877906bSopenharmony_ci VkSubresourceLayout layout; 871b877906bSopenharmony_ci void *data; 872b877906bSopenharmony_ci int32_t x, y; 873b877906bSopenharmony_ci 874b877906bSopenharmony_ci vkGetImageSubresourceLayout(demo->device, tex_obj->image, &subres, 875b877906bSopenharmony_ci &layout); 876b877906bSopenharmony_ci 877b877906bSopenharmony_ci err = vkMapMemory(demo->device, tex_obj->mem, 0, 878b877906bSopenharmony_ci mem_alloc.allocationSize, 0, &data); 879b877906bSopenharmony_ci assert(!err); 880b877906bSopenharmony_ci 881b877906bSopenharmony_ci for (y = 0; y < tex_height; y++) { 882b877906bSopenharmony_ci uint32_t *row = (uint32_t *)((char *)data + layout.rowPitch * y); 883b877906bSopenharmony_ci for (x = 0; x < tex_width; x++) 884b877906bSopenharmony_ci row[x] = tex_colors[(x & 1) ^ (y & 1)]; 885b877906bSopenharmony_ci } 886b877906bSopenharmony_ci 887b877906bSopenharmony_ci vkUnmapMemory(demo->device, tex_obj->mem); 888b877906bSopenharmony_ci } 889b877906bSopenharmony_ci 890b877906bSopenharmony_ci tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 891b877906bSopenharmony_ci demo_set_image_layout(demo, tex_obj->image, VK_IMAGE_ASPECT_COLOR_BIT, 892b877906bSopenharmony_ci VK_IMAGE_LAYOUT_PREINITIALIZED, tex_obj->imageLayout, 893b877906bSopenharmony_ci VK_ACCESS_HOST_WRITE_BIT); 894b877906bSopenharmony_ci /* setting the image layout does not reference the actual memory so no need 895b877906bSopenharmony_ci * to add a mem ref */ 896b877906bSopenharmony_ci} 897b877906bSopenharmony_ci 898b877906bSopenharmony_cistatic void demo_destroy_texture_image(struct demo *demo, 899b877906bSopenharmony_ci struct texture_object *tex_obj) { 900b877906bSopenharmony_ci /* clean up staging resources */ 901b877906bSopenharmony_ci vkDestroyImage(demo->device, tex_obj->image, NULL); 902b877906bSopenharmony_ci vkFreeMemory(demo->device, tex_obj->mem, NULL); 903b877906bSopenharmony_ci} 904b877906bSopenharmony_ci 905b877906bSopenharmony_cistatic void demo_prepare_textures(struct demo *demo) { 906b877906bSopenharmony_ci const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; 907b877906bSopenharmony_ci VkFormatProperties props; 908b877906bSopenharmony_ci const uint32_t tex_colors[DEMO_TEXTURE_COUNT][2] = { 909b877906bSopenharmony_ci {0xffff0000, 0xff00ff00}, 910b877906bSopenharmony_ci }; 911b877906bSopenharmony_ci uint32_t i; 912b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 913b877906bSopenharmony_ci 914b877906bSopenharmony_ci vkGetPhysicalDeviceFormatProperties(demo->gpu, tex_format, &props); 915b877906bSopenharmony_ci 916b877906bSopenharmony_ci for (i = 0; i < DEMO_TEXTURE_COUNT; i++) { 917b877906bSopenharmony_ci if ((props.linearTilingFeatures & 918b877906bSopenharmony_ci VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) && 919b877906bSopenharmony_ci !demo->use_staging_buffer) { 920b877906bSopenharmony_ci /* Device can texture using linear textures */ 921b877906bSopenharmony_ci demo_prepare_texture_image( 922b877906bSopenharmony_ci demo, tex_colors[i], &demo->textures[i], VK_IMAGE_TILING_LINEAR, 923b877906bSopenharmony_ci VK_IMAGE_USAGE_SAMPLED_BIT, 924b877906bSopenharmony_ci VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 925b877906bSopenharmony_ci VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); 926b877906bSopenharmony_ci } else if (props.optimalTilingFeatures & 927b877906bSopenharmony_ci VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) { 928b877906bSopenharmony_ci /* Must use staging buffer to copy linear texture to optimized */ 929b877906bSopenharmony_ci struct texture_object staging_texture; 930b877906bSopenharmony_ci 931b877906bSopenharmony_ci memset(&staging_texture, 0, sizeof(staging_texture)); 932b877906bSopenharmony_ci demo_prepare_texture_image( 933b877906bSopenharmony_ci demo, tex_colors[i], &staging_texture, VK_IMAGE_TILING_LINEAR, 934b877906bSopenharmony_ci VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 935b877906bSopenharmony_ci VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 936b877906bSopenharmony_ci VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); 937b877906bSopenharmony_ci 938b877906bSopenharmony_ci demo_prepare_texture_image( 939b877906bSopenharmony_ci demo, tex_colors[i], &demo->textures[i], 940b877906bSopenharmony_ci VK_IMAGE_TILING_OPTIMAL, 941b877906bSopenharmony_ci (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), 942b877906bSopenharmony_ci VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 943b877906bSopenharmony_ci 944b877906bSopenharmony_ci demo_set_image_layout(demo, staging_texture.image, 945b877906bSopenharmony_ci VK_IMAGE_ASPECT_COLOR_BIT, 946b877906bSopenharmony_ci staging_texture.imageLayout, 947b877906bSopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 948b877906bSopenharmony_ci 0); 949b877906bSopenharmony_ci 950b877906bSopenharmony_ci demo_set_image_layout(demo, demo->textures[i].image, 951b877906bSopenharmony_ci VK_IMAGE_ASPECT_COLOR_BIT, 952b877906bSopenharmony_ci demo->textures[i].imageLayout, 953b877906bSopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 954b877906bSopenharmony_ci 0); 955b877906bSopenharmony_ci 956b877906bSopenharmony_ci VkImageCopy copy_region = { 957b877906bSopenharmony_ci .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, 958b877906bSopenharmony_ci .srcOffset = {0, 0, 0}, 959b877906bSopenharmony_ci .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, 960b877906bSopenharmony_ci .dstOffset = {0, 0, 0}, 961b877906bSopenharmony_ci .extent = {staging_texture.tex_width, 962b877906bSopenharmony_ci staging_texture.tex_height, 1}, 963b877906bSopenharmony_ci }; 964b877906bSopenharmony_ci vkCmdCopyImage( 965b877906bSopenharmony_ci demo->setup_cmd, staging_texture.image, 966b877906bSopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, demo->textures[i].image, 967b877906bSopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); 968b877906bSopenharmony_ci 969b877906bSopenharmony_ci demo_set_image_layout(demo, demo->textures[i].image, 970b877906bSopenharmony_ci VK_IMAGE_ASPECT_COLOR_BIT, 971b877906bSopenharmony_ci VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 972b877906bSopenharmony_ci demo->textures[i].imageLayout, 973b877906bSopenharmony_ci 0); 974b877906bSopenharmony_ci 975b877906bSopenharmony_ci demo_flush_init_cmd(demo); 976b877906bSopenharmony_ci 977b877906bSopenharmony_ci demo_destroy_texture_image(demo, &staging_texture); 978b877906bSopenharmony_ci } else { 979b877906bSopenharmony_ci /* Can't support VK_FORMAT_B8G8R8A8_UNORM !? */ 980b877906bSopenharmony_ci assert(!"No support for B8G8R8A8_UNORM as texture image format"); 981b877906bSopenharmony_ci } 982b877906bSopenharmony_ci 983b877906bSopenharmony_ci const VkSamplerCreateInfo sampler = { 984b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, 985b877906bSopenharmony_ci .pNext = NULL, 986b877906bSopenharmony_ci .magFilter = VK_FILTER_NEAREST, 987b877906bSopenharmony_ci .minFilter = VK_FILTER_NEAREST, 988b877906bSopenharmony_ci .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST, 989b877906bSopenharmony_ci .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT, 990b877906bSopenharmony_ci .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, 991b877906bSopenharmony_ci .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, 992b877906bSopenharmony_ci .mipLodBias = 0.0f, 993b877906bSopenharmony_ci .anisotropyEnable = VK_FALSE, 994b877906bSopenharmony_ci .maxAnisotropy = 1, 995b877906bSopenharmony_ci .compareOp = VK_COMPARE_OP_NEVER, 996b877906bSopenharmony_ci .minLod = 0.0f, 997b877906bSopenharmony_ci .maxLod = 0.0f, 998b877906bSopenharmony_ci .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, 999b877906bSopenharmony_ci .unnormalizedCoordinates = VK_FALSE, 1000b877906bSopenharmony_ci }; 1001b877906bSopenharmony_ci VkImageViewCreateInfo view = { 1002b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 1003b877906bSopenharmony_ci .pNext = NULL, 1004b877906bSopenharmony_ci .image = VK_NULL_HANDLE, 1005b877906bSopenharmony_ci .viewType = VK_IMAGE_VIEW_TYPE_2D, 1006b877906bSopenharmony_ci .format = tex_format, 1007b877906bSopenharmony_ci .components = 1008b877906bSopenharmony_ci { 1009b877906bSopenharmony_ci VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, 1010b877906bSopenharmony_ci VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A, 1011b877906bSopenharmony_ci }, 1012b877906bSopenharmony_ci .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, 1013b877906bSopenharmony_ci .flags = 0, 1014b877906bSopenharmony_ci }; 1015b877906bSopenharmony_ci 1016b877906bSopenharmony_ci /* create sampler */ 1017b877906bSopenharmony_ci err = vkCreateSampler(demo->device, &sampler, NULL, 1018b877906bSopenharmony_ci &demo->textures[i].sampler); 1019b877906bSopenharmony_ci assert(!err); 1020b877906bSopenharmony_ci 1021b877906bSopenharmony_ci /* create image view */ 1022b877906bSopenharmony_ci view.image = demo->textures[i].image; 1023b877906bSopenharmony_ci err = vkCreateImageView(demo->device, &view, NULL, 1024b877906bSopenharmony_ci &demo->textures[i].view); 1025b877906bSopenharmony_ci assert(!err); 1026b877906bSopenharmony_ci } 1027b877906bSopenharmony_ci} 1028b877906bSopenharmony_ci 1029b877906bSopenharmony_cistatic void demo_prepare_vertices(struct demo *demo) { 1030b877906bSopenharmony_ci // clang-format off 1031b877906bSopenharmony_ci const float vb[3][5] = { 1032b877906bSopenharmony_ci /* position texcoord */ 1033b877906bSopenharmony_ci { -1.0f, -1.0f, 0.25f, 0.0f, 0.0f }, 1034b877906bSopenharmony_ci { 1.0f, -1.0f, 0.25f, 1.0f, 0.0f }, 1035b877906bSopenharmony_ci { 0.0f, 1.0f, 1.0f, 0.5f, 1.0f }, 1036b877906bSopenharmony_ci }; 1037b877906bSopenharmony_ci // clang-format on 1038b877906bSopenharmony_ci const VkBufferCreateInfo buf_info = { 1039b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 1040b877906bSopenharmony_ci .pNext = NULL, 1041b877906bSopenharmony_ci .size = sizeof(vb), 1042b877906bSopenharmony_ci .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 1043b877906bSopenharmony_ci .flags = 0, 1044b877906bSopenharmony_ci }; 1045b877906bSopenharmony_ci VkMemoryAllocateInfo mem_alloc = { 1046b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 1047b877906bSopenharmony_ci .pNext = NULL, 1048b877906bSopenharmony_ci .allocationSize = 0, 1049b877906bSopenharmony_ci .memoryTypeIndex = 0, 1050b877906bSopenharmony_ci }; 1051b877906bSopenharmony_ci VkMemoryRequirements mem_reqs; 1052b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1053b877906bSopenharmony_ci bool U_ASSERT_ONLY pass; 1054b877906bSopenharmony_ci void *data; 1055b877906bSopenharmony_ci 1056b877906bSopenharmony_ci memset(&demo->vertices, 0, sizeof(demo->vertices)); 1057b877906bSopenharmony_ci 1058b877906bSopenharmony_ci err = vkCreateBuffer(demo->device, &buf_info, NULL, &demo->vertices.buf); 1059b877906bSopenharmony_ci assert(!err); 1060b877906bSopenharmony_ci 1061b877906bSopenharmony_ci vkGetBufferMemoryRequirements(demo->device, demo->vertices.buf, &mem_reqs); 1062b877906bSopenharmony_ci assert(!err); 1063b877906bSopenharmony_ci 1064b877906bSopenharmony_ci mem_alloc.allocationSize = mem_reqs.size; 1065b877906bSopenharmony_ci pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits, 1066b877906bSopenharmony_ci VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 1067b877906bSopenharmony_ci VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 1068b877906bSopenharmony_ci &mem_alloc.memoryTypeIndex); 1069b877906bSopenharmony_ci assert(pass); 1070b877906bSopenharmony_ci 1071b877906bSopenharmony_ci err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &demo->vertices.mem); 1072b877906bSopenharmony_ci assert(!err); 1073b877906bSopenharmony_ci 1074b877906bSopenharmony_ci err = vkMapMemory(demo->device, demo->vertices.mem, 0, 1075b877906bSopenharmony_ci mem_alloc.allocationSize, 0, &data); 1076b877906bSopenharmony_ci assert(!err); 1077b877906bSopenharmony_ci 1078b877906bSopenharmony_ci memcpy(data, vb, sizeof(vb)); 1079b877906bSopenharmony_ci 1080b877906bSopenharmony_ci vkUnmapMemory(demo->device, demo->vertices.mem); 1081b877906bSopenharmony_ci 1082b877906bSopenharmony_ci err = vkBindBufferMemory(demo->device, demo->vertices.buf, 1083b877906bSopenharmony_ci demo->vertices.mem, 0); 1084b877906bSopenharmony_ci assert(!err); 1085b877906bSopenharmony_ci 1086b877906bSopenharmony_ci demo->vertices.vi.sType = 1087b877906bSopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 1088b877906bSopenharmony_ci demo->vertices.vi.pNext = NULL; 1089b877906bSopenharmony_ci demo->vertices.vi.vertexBindingDescriptionCount = 1; 1090b877906bSopenharmony_ci demo->vertices.vi.pVertexBindingDescriptions = demo->vertices.vi_bindings; 1091b877906bSopenharmony_ci demo->vertices.vi.vertexAttributeDescriptionCount = 2; 1092b877906bSopenharmony_ci demo->vertices.vi.pVertexAttributeDescriptions = demo->vertices.vi_attrs; 1093b877906bSopenharmony_ci 1094b877906bSopenharmony_ci demo->vertices.vi_bindings[0].binding = VERTEX_BUFFER_BIND_ID; 1095b877906bSopenharmony_ci demo->vertices.vi_bindings[0].stride = sizeof(vb[0]); 1096b877906bSopenharmony_ci demo->vertices.vi_bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 1097b877906bSopenharmony_ci 1098b877906bSopenharmony_ci demo->vertices.vi_attrs[0].binding = VERTEX_BUFFER_BIND_ID; 1099b877906bSopenharmony_ci demo->vertices.vi_attrs[0].location = 0; 1100b877906bSopenharmony_ci demo->vertices.vi_attrs[0].format = VK_FORMAT_R32G32B32_SFLOAT; 1101b877906bSopenharmony_ci demo->vertices.vi_attrs[0].offset = 0; 1102b877906bSopenharmony_ci 1103b877906bSopenharmony_ci demo->vertices.vi_attrs[1].binding = VERTEX_BUFFER_BIND_ID; 1104b877906bSopenharmony_ci demo->vertices.vi_attrs[1].location = 1; 1105b877906bSopenharmony_ci demo->vertices.vi_attrs[1].format = VK_FORMAT_R32G32_SFLOAT; 1106b877906bSopenharmony_ci demo->vertices.vi_attrs[1].offset = sizeof(float) * 3; 1107b877906bSopenharmony_ci} 1108b877906bSopenharmony_ci 1109b877906bSopenharmony_cistatic void demo_prepare_descriptor_layout(struct demo *demo) { 1110b877906bSopenharmony_ci const VkDescriptorSetLayoutBinding layout_binding = { 1111b877906bSopenharmony_ci .binding = 0, 1112b877906bSopenharmony_ci .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1113b877906bSopenharmony_ci .descriptorCount = DEMO_TEXTURE_COUNT, 1114b877906bSopenharmony_ci .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, 1115b877906bSopenharmony_ci .pImmutableSamplers = NULL, 1116b877906bSopenharmony_ci }; 1117b877906bSopenharmony_ci const VkDescriptorSetLayoutCreateInfo descriptor_layout = { 1118b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 1119b877906bSopenharmony_ci .pNext = NULL, 1120b877906bSopenharmony_ci .bindingCount = 1, 1121b877906bSopenharmony_ci .pBindings = &layout_binding, 1122b877906bSopenharmony_ci }; 1123b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1124b877906bSopenharmony_ci 1125b877906bSopenharmony_ci err = vkCreateDescriptorSetLayout(demo->device, &descriptor_layout, NULL, 1126b877906bSopenharmony_ci &demo->desc_layout); 1127b877906bSopenharmony_ci assert(!err); 1128b877906bSopenharmony_ci 1129b877906bSopenharmony_ci const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = { 1130b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 1131b877906bSopenharmony_ci .pNext = NULL, 1132b877906bSopenharmony_ci .setLayoutCount = 1, 1133b877906bSopenharmony_ci .pSetLayouts = &demo->desc_layout, 1134b877906bSopenharmony_ci }; 1135b877906bSopenharmony_ci 1136b877906bSopenharmony_ci err = vkCreatePipelineLayout(demo->device, &pPipelineLayoutCreateInfo, NULL, 1137b877906bSopenharmony_ci &demo->pipeline_layout); 1138b877906bSopenharmony_ci assert(!err); 1139b877906bSopenharmony_ci} 1140b877906bSopenharmony_ci 1141b877906bSopenharmony_cistatic void demo_prepare_render_pass(struct demo *demo) { 1142b877906bSopenharmony_ci const VkAttachmentDescription attachments[2] = { 1143b877906bSopenharmony_ci [0] = 1144b877906bSopenharmony_ci { 1145b877906bSopenharmony_ci .format = demo->format, 1146b877906bSopenharmony_ci .samples = VK_SAMPLE_COUNT_1_BIT, 1147b877906bSopenharmony_ci .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, 1148b877906bSopenharmony_ci .storeOp = VK_ATTACHMENT_STORE_OP_STORE, 1149b877906bSopenharmony_ci .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, 1150b877906bSopenharmony_ci .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, 1151b877906bSopenharmony_ci .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1152b877906bSopenharmony_ci .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1153b877906bSopenharmony_ci }, 1154b877906bSopenharmony_ci [1] = 1155b877906bSopenharmony_ci { 1156b877906bSopenharmony_ci .format = demo->depth.format, 1157b877906bSopenharmony_ci .samples = VK_SAMPLE_COUNT_1_BIT, 1158b877906bSopenharmony_ci .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, 1159b877906bSopenharmony_ci .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, 1160b877906bSopenharmony_ci .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, 1161b877906bSopenharmony_ci .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, 1162b877906bSopenharmony_ci .initialLayout = 1163b877906bSopenharmony_ci VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1164b877906bSopenharmony_ci .finalLayout = 1165b877906bSopenharmony_ci VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1166b877906bSopenharmony_ci }, 1167b877906bSopenharmony_ci }; 1168b877906bSopenharmony_ci const VkAttachmentReference color_reference = { 1169b877906bSopenharmony_ci .attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1170b877906bSopenharmony_ci }; 1171b877906bSopenharmony_ci const VkAttachmentReference depth_reference = { 1172b877906bSopenharmony_ci .attachment = 1, 1173b877906bSopenharmony_ci .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1174b877906bSopenharmony_ci }; 1175b877906bSopenharmony_ci const VkSubpassDescription subpass = { 1176b877906bSopenharmony_ci .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 1177b877906bSopenharmony_ci .flags = 0, 1178b877906bSopenharmony_ci .inputAttachmentCount = 0, 1179b877906bSopenharmony_ci .pInputAttachments = NULL, 1180b877906bSopenharmony_ci .colorAttachmentCount = 1, 1181b877906bSopenharmony_ci .pColorAttachments = &color_reference, 1182b877906bSopenharmony_ci .pResolveAttachments = NULL, 1183b877906bSopenharmony_ci .pDepthStencilAttachment = &depth_reference, 1184b877906bSopenharmony_ci .preserveAttachmentCount = 0, 1185b877906bSopenharmony_ci .pPreserveAttachments = NULL, 1186b877906bSopenharmony_ci }; 1187b877906bSopenharmony_ci const VkRenderPassCreateInfo rp_info = { 1188b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 1189b877906bSopenharmony_ci .pNext = NULL, 1190b877906bSopenharmony_ci .attachmentCount = 2, 1191b877906bSopenharmony_ci .pAttachments = attachments, 1192b877906bSopenharmony_ci .subpassCount = 1, 1193b877906bSopenharmony_ci .pSubpasses = &subpass, 1194b877906bSopenharmony_ci .dependencyCount = 0, 1195b877906bSopenharmony_ci .pDependencies = NULL, 1196b877906bSopenharmony_ci }; 1197b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1198b877906bSopenharmony_ci 1199b877906bSopenharmony_ci err = vkCreateRenderPass(demo->device, &rp_info, NULL, &demo->render_pass); 1200b877906bSopenharmony_ci assert(!err); 1201b877906bSopenharmony_ci} 1202b877906bSopenharmony_ci 1203b877906bSopenharmony_cistatic VkShaderModule 1204b877906bSopenharmony_cidemo_prepare_shader_module(struct demo *demo, const void *code, size_t size) { 1205b877906bSopenharmony_ci VkShaderModuleCreateInfo moduleCreateInfo; 1206b877906bSopenharmony_ci VkShaderModule module; 1207b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1208b877906bSopenharmony_ci 1209b877906bSopenharmony_ci moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 1210b877906bSopenharmony_ci moduleCreateInfo.pNext = NULL; 1211b877906bSopenharmony_ci 1212b877906bSopenharmony_ci moduleCreateInfo.codeSize = size; 1213b877906bSopenharmony_ci moduleCreateInfo.pCode = code; 1214b877906bSopenharmony_ci moduleCreateInfo.flags = 0; 1215b877906bSopenharmony_ci err = vkCreateShaderModule(demo->device, &moduleCreateInfo, NULL, &module); 1216b877906bSopenharmony_ci assert(!err); 1217b877906bSopenharmony_ci 1218b877906bSopenharmony_ci return module; 1219b877906bSopenharmony_ci} 1220b877906bSopenharmony_ci 1221b877906bSopenharmony_cistatic VkShaderModule demo_prepare_vs(struct demo *demo) { 1222b877906bSopenharmony_ci size_t size = sizeof(vertShaderCode); 1223b877906bSopenharmony_ci 1224b877906bSopenharmony_ci demo->vert_shader_module = 1225b877906bSopenharmony_ci demo_prepare_shader_module(demo, vertShaderCode, size); 1226b877906bSopenharmony_ci 1227b877906bSopenharmony_ci return demo->vert_shader_module; 1228b877906bSopenharmony_ci} 1229b877906bSopenharmony_ci 1230b877906bSopenharmony_cistatic VkShaderModule demo_prepare_fs(struct demo *demo) { 1231b877906bSopenharmony_ci size_t size = sizeof(fragShaderCode); 1232b877906bSopenharmony_ci 1233b877906bSopenharmony_ci demo->frag_shader_module = 1234b877906bSopenharmony_ci demo_prepare_shader_module(demo, fragShaderCode, size); 1235b877906bSopenharmony_ci 1236b877906bSopenharmony_ci return demo->frag_shader_module; 1237b877906bSopenharmony_ci} 1238b877906bSopenharmony_ci 1239b877906bSopenharmony_cistatic void demo_prepare_pipeline(struct demo *demo) { 1240b877906bSopenharmony_ci VkGraphicsPipelineCreateInfo pipeline; 1241b877906bSopenharmony_ci VkPipelineCacheCreateInfo pipelineCache; 1242b877906bSopenharmony_ci 1243b877906bSopenharmony_ci VkPipelineVertexInputStateCreateInfo vi; 1244b877906bSopenharmony_ci VkPipelineInputAssemblyStateCreateInfo ia; 1245b877906bSopenharmony_ci VkPipelineRasterizationStateCreateInfo rs; 1246b877906bSopenharmony_ci VkPipelineColorBlendStateCreateInfo cb; 1247b877906bSopenharmony_ci VkPipelineDepthStencilStateCreateInfo ds; 1248b877906bSopenharmony_ci VkPipelineViewportStateCreateInfo vp; 1249b877906bSopenharmony_ci VkPipelineMultisampleStateCreateInfo ms; 1250b877906bSopenharmony_ci VkDynamicState dynamicStateEnables[(VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1)]; 1251b877906bSopenharmony_ci VkPipelineDynamicStateCreateInfo dynamicState; 1252b877906bSopenharmony_ci 1253b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1254b877906bSopenharmony_ci 1255b877906bSopenharmony_ci memset(dynamicStateEnables, 0, sizeof dynamicStateEnables); 1256b877906bSopenharmony_ci memset(&dynamicState, 0, sizeof dynamicState); 1257b877906bSopenharmony_ci dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 1258b877906bSopenharmony_ci dynamicState.pDynamicStates = dynamicStateEnables; 1259b877906bSopenharmony_ci 1260b877906bSopenharmony_ci memset(&pipeline, 0, sizeof(pipeline)); 1261b877906bSopenharmony_ci pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 1262b877906bSopenharmony_ci pipeline.layout = demo->pipeline_layout; 1263b877906bSopenharmony_ci 1264b877906bSopenharmony_ci vi = demo->vertices.vi; 1265b877906bSopenharmony_ci 1266b877906bSopenharmony_ci memset(&ia, 0, sizeof(ia)); 1267b877906bSopenharmony_ci ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 1268b877906bSopenharmony_ci ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1269b877906bSopenharmony_ci 1270b877906bSopenharmony_ci memset(&rs, 0, sizeof(rs)); 1271b877906bSopenharmony_ci rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 1272b877906bSopenharmony_ci rs.polygonMode = VK_POLYGON_MODE_FILL; 1273b877906bSopenharmony_ci rs.cullMode = VK_CULL_MODE_BACK_BIT; 1274b877906bSopenharmony_ci rs.frontFace = VK_FRONT_FACE_CLOCKWISE; 1275b877906bSopenharmony_ci rs.depthClampEnable = VK_FALSE; 1276b877906bSopenharmony_ci rs.rasterizerDiscardEnable = VK_FALSE; 1277b877906bSopenharmony_ci rs.depthBiasEnable = VK_FALSE; 1278b877906bSopenharmony_ci rs.lineWidth = 1.0f; 1279b877906bSopenharmony_ci 1280b877906bSopenharmony_ci memset(&cb, 0, sizeof(cb)); 1281b877906bSopenharmony_ci cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 1282b877906bSopenharmony_ci VkPipelineColorBlendAttachmentState att_state[1]; 1283b877906bSopenharmony_ci memset(att_state, 0, sizeof(att_state)); 1284b877906bSopenharmony_ci att_state[0].colorWriteMask = 0xf; 1285b877906bSopenharmony_ci att_state[0].blendEnable = VK_FALSE; 1286b877906bSopenharmony_ci cb.attachmentCount = 1; 1287b877906bSopenharmony_ci cb.pAttachments = att_state; 1288b877906bSopenharmony_ci 1289b877906bSopenharmony_ci memset(&vp, 0, sizeof(vp)); 1290b877906bSopenharmony_ci vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 1291b877906bSopenharmony_ci vp.viewportCount = 1; 1292b877906bSopenharmony_ci dynamicStateEnables[dynamicState.dynamicStateCount++] = 1293b877906bSopenharmony_ci VK_DYNAMIC_STATE_VIEWPORT; 1294b877906bSopenharmony_ci vp.scissorCount = 1; 1295b877906bSopenharmony_ci dynamicStateEnables[dynamicState.dynamicStateCount++] = 1296b877906bSopenharmony_ci VK_DYNAMIC_STATE_SCISSOR; 1297b877906bSopenharmony_ci 1298b877906bSopenharmony_ci memset(&ds, 0, sizeof(ds)); 1299b877906bSopenharmony_ci ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 1300b877906bSopenharmony_ci ds.depthTestEnable = VK_TRUE; 1301b877906bSopenharmony_ci ds.depthWriteEnable = VK_TRUE; 1302b877906bSopenharmony_ci ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; 1303b877906bSopenharmony_ci ds.depthBoundsTestEnable = VK_FALSE; 1304b877906bSopenharmony_ci ds.back.failOp = VK_STENCIL_OP_KEEP; 1305b877906bSopenharmony_ci ds.back.passOp = VK_STENCIL_OP_KEEP; 1306b877906bSopenharmony_ci ds.back.compareOp = VK_COMPARE_OP_ALWAYS; 1307b877906bSopenharmony_ci ds.stencilTestEnable = VK_FALSE; 1308b877906bSopenharmony_ci ds.front = ds.back; 1309b877906bSopenharmony_ci 1310b877906bSopenharmony_ci memset(&ms, 0, sizeof(ms)); 1311b877906bSopenharmony_ci ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 1312b877906bSopenharmony_ci ms.pSampleMask = NULL; 1313b877906bSopenharmony_ci ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 1314b877906bSopenharmony_ci 1315b877906bSopenharmony_ci // Two stages: vs and fs 1316b877906bSopenharmony_ci pipeline.stageCount = 2; 1317b877906bSopenharmony_ci VkPipelineShaderStageCreateInfo shaderStages[2]; 1318b877906bSopenharmony_ci memset(&shaderStages, 0, 2 * sizeof(VkPipelineShaderStageCreateInfo)); 1319b877906bSopenharmony_ci 1320b877906bSopenharmony_ci shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1321b877906bSopenharmony_ci shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 1322b877906bSopenharmony_ci shaderStages[0].module = demo_prepare_vs(demo); 1323b877906bSopenharmony_ci shaderStages[0].pName = "main"; 1324b877906bSopenharmony_ci 1325b877906bSopenharmony_ci shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1326b877906bSopenharmony_ci shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 1327b877906bSopenharmony_ci shaderStages[1].module = demo_prepare_fs(demo); 1328b877906bSopenharmony_ci shaderStages[1].pName = "main"; 1329b877906bSopenharmony_ci 1330b877906bSopenharmony_ci pipeline.pVertexInputState = &vi; 1331b877906bSopenharmony_ci pipeline.pInputAssemblyState = &ia; 1332b877906bSopenharmony_ci pipeline.pRasterizationState = &rs; 1333b877906bSopenharmony_ci pipeline.pColorBlendState = &cb; 1334b877906bSopenharmony_ci pipeline.pMultisampleState = &ms; 1335b877906bSopenharmony_ci pipeline.pViewportState = &vp; 1336b877906bSopenharmony_ci pipeline.pDepthStencilState = &ds; 1337b877906bSopenharmony_ci pipeline.pStages = shaderStages; 1338b877906bSopenharmony_ci pipeline.renderPass = demo->render_pass; 1339b877906bSopenharmony_ci pipeline.pDynamicState = &dynamicState; 1340b877906bSopenharmony_ci 1341b877906bSopenharmony_ci memset(&pipelineCache, 0, sizeof(pipelineCache)); 1342b877906bSopenharmony_ci pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; 1343b877906bSopenharmony_ci 1344b877906bSopenharmony_ci err = vkCreatePipelineCache(demo->device, &pipelineCache, NULL, 1345b877906bSopenharmony_ci &demo->pipelineCache); 1346b877906bSopenharmony_ci assert(!err); 1347b877906bSopenharmony_ci err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1, 1348b877906bSopenharmony_ci &pipeline, NULL, &demo->pipeline); 1349b877906bSopenharmony_ci assert(!err); 1350b877906bSopenharmony_ci 1351b877906bSopenharmony_ci vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL); 1352b877906bSopenharmony_ci 1353b877906bSopenharmony_ci vkDestroyShaderModule(demo->device, demo->frag_shader_module, NULL); 1354b877906bSopenharmony_ci vkDestroyShaderModule(demo->device, demo->vert_shader_module, NULL); 1355b877906bSopenharmony_ci} 1356b877906bSopenharmony_ci 1357b877906bSopenharmony_cistatic void demo_prepare_descriptor_pool(struct demo *demo) { 1358b877906bSopenharmony_ci const VkDescriptorPoolSize type_count = { 1359b877906bSopenharmony_ci .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1360b877906bSopenharmony_ci .descriptorCount = DEMO_TEXTURE_COUNT, 1361b877906bSopenharmony_ci }; 1362b877906bSopenharmony_ci const VkDescriptorPoolCreateInfo descriptor_pool = { 1363b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 1364b877906bSopenharmony_ci .pNext = NULL, 1365b877906bSopenharmony_ci .maxSets = 1, 1366b877906bSopenharmony_ci .poolSizeCount = 1, 1367b877906bSopenharmony_ci .pPoolSizes = &type_count, 1368b877906bSopenharmony_ci }; 1369b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1370b877906bSopenharmony_ci 1371b877906bSopenharmony_ci err = vkCreateDescriptorPool(demo->device, &descriptor_pool, NULL, 1372b877906bSopenharmony_ci &demo->desc_pool); 1373b877906bSopenharmony_ci assert(!err); 1374b877906bSopenharmony_ci} 1375b877906bSopenharmony_ci 1376b877906bSopenharmony_cistatic void demo_prepare_descriptor_set(struct demo *demo) { 1377b877906bSopenharmony_ci VkDescriptorImageInfo tex_descs[DEMO_TEXTURE_COUNT]; 1378b877906bSopenharmony_ci VkWriteDescriptorSet write; 1379b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1380b877906bSopenharmony_ci uint32_t i; 1381b877906bSopenharmony_ci 1382b877906bSopenharmony_ci VkDescriptorSetAllocateInfo alloc_info = { 1383b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1384b877906bSopenharmony_ci .pNext = NULL, 1385b877906bSopenharmony_ci .descriptorPool = demo->desc_pool, 1386b877906bSopenharmony_ci .descriptorSetCount = 1, 1387b877906bSopenharmony_ci .pSetLayouts = &demo->desc_layout}; 1388b877906bSopenharmony_ci err = vkAllocateDescriptorSets(demo->device, &alloc_info, &demo->desc_set); 1389b877906bSopenharmony_ci assert(!err); 1390b877906bSopenharmony_ci 1391b877906bSopenharmony_ci memset(&tex_descs, 0, sizeof(tex_descs)); 1392b877906bSopenharmony_ci for (i = 0; i < DEMO_TEXTURE_COUNT; i++) { 1393b877906bSopenharmony_ci tex_descs[i].sampler = demo->textures[i].sampler; 1394b877906bSopenharmony_ci tex_descs[i].imageView = demo->textures[i].view; 1395b877906bSopenharmony_ci tex_descs[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; 1396b877906bSopenharmony_ci } 1397b877906bSopenharmony_ci 1398b877906bSopenharmony_ci memset(&write, 0, sizeof(write)); 1399b877906bSopenharmony_ci write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 1400b877906bSopenharmony_ci write.dstSet = demo->desc_set; 1401b877906bSopenharmony_ci write.descriptorCount = DEMO_TEXTURE_COUNT; 1402b877906bSopenharmony_ci write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 1403b877906bSopenharmony_ci write.pImageInfo = tex_descs; 1404b877906bSopenharmony_ci 1405b877906bSopenharmony_ci vkUpdateDescriptorSets(demo->device, 1, &write, 0, NULL); 1406b877906bSopenharmony_ci} 1407b877906bSopenharmony_ci 1408b877906bSopenharmony_cistatic void demo_prepare_framebuffers(struct demo *demo) { 1409b877906bSopenharmony_ci VkImageView attachments[2]; 1410b877906bSopenharmony_ci attachments[1] = demo->depth.view; 1411b877906bSopenharmony_ci 1412b877906bSopenharmony_ci const VkFramebufferCreateInfo fb_info = { 1413b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 1414b877906bSopenharmony_ci .pNext = NULL, 1415b877906bSopenharmony_ci .renderPass = demo->render_pass, 1416b877906bSopenharmony_ci .attachmentCount = 2, 1417b877906bSopenharmony_ci .pAttachments = attachments, 1418b877906bSopenharmony_ci .width = demo->width, 1419b877906bSopenharmony_ci .height = demo->height, 1420b877906bSopenharmony_ci .layers = 1, 1421b877906bSopenharmony_ci }; 1422b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1423b877906bSopenharmony_ci uint32_t i; 1424b877906bSopenharmony_ci 1425b877906bSopenharmony_ci demo->framebuffers = (VkFramebuffer *)malloc(demo->swapchainImageCount * 1426b877906bSopenharmony_ci sizeof(VkFramebuffer)); 1427b877906bSopenharmony_ci assert(demo->framebuffers); 1428b877906bSopenharmony_ci 1429b877906bSopenharmony_ci for (i = 0; i < demo->swapchainImageCount; i++) { 1430b877906bSopenharmony_ci attachments[0] = demo->buffers[i].view; 1431b877906bSopenharmony_ci err = vkCreateFramebuffer(demo->device, &fb_info, NULL, 1432b877906bSopenharmony_ci &demo->framebuffers[i]); 1433b877906bSopenharmony_ci assert(!err); 1434b877906bSopenharmony_ci } 1435b877906bSopenharmony_ci} 1436b877906bSopenharmony_ci 1437b877906bSopenharmony_cistatic void demo_prepare(struct demo *demo) { 1438b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1439b877906bSopenharmony_ci 1440b877906bSopenharmony_ci const VkCommandPoolCreateInfo cmd_pool_info = { 1441b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 1442b877906bSopenharmony_ci .pNext = NULL, 1443b877906bSopenharmony_ci .queueFamilyIndex = demo->graphics_queue_node_index, 1444b877906bSopenharmony_ci .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, 1445b877906bSopenharmony_ci }; 1446b877906bSopenharmony_ci err = vkCreateCommandPool(demo->device, &cmd_pool_info, NULL, 1447b877906bSopenharmony_ci &demo->cmd_pool); 1448b877906bSopenharmony_ci assert(!err); 1449b877906bSopenharmony_ci 1450b877906bSopenharmony_ci const VkCommandBufferAllocateInfo cmd = { 1451b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 1452b877906bSopenharmony_ci .pNext = NULL, 1453b877906bSopenharmony_ci .commandPool = demo->cmd_pool, 1454b877906bSopenharmony_ci .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1455b877906bSopenharmony_ci .commandBufferCount = 1, 1456b877906bSopenharmony_ci }; 1457b877906bSopenharmony_ci err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->draw_cmd); 1458b877906bSopenharmony_ci assert(!err); 1459b877906bSopenharmony_ci 1460b877906bSopenharmony_ci demo_prepare_buffers(demo); 1461b877906bSopenharmony_ci demo_prepare_depth(demo); 1462b877906bSopenharmony_ci demo_prepare_textures(demo); 1463b877906bSopenharmony_ci demo_prepare_vertices(demo); 1464b877906bSopenharmony_ci demo_prepare_descriptor_layout(demo); 1465b877906bSopenharmony_ci demo_prepare_render_pass(demo); 1466b877906bSopenharmony_ci demo_prepare_pipeline(demo); 1467b877906bSopenharmony_ci 1468b877906bSopenharmony_ci demo_prepare_descriptor_pool(demo); 1469b877906bSopenharmony_ci demo_prepare_descriptor_set(demo); 1470b877906bSopenharmony_ci 1471b877906bSopenharmony_ci demo_prepare_framebuffers(demo); 1472b877906bSopenharmony_ci} 1473b877906bSopenharmony_ci 1474b877906bSopenharmony_cistatic void demo_error_callback(int error, const char* description) { 1475b877906bSopenharmony_ci printf("GLFW error: %s\n", description); 1476b877906bSopenharmony_ci fflush(stdout); 1477b877906bSopenharmony_ci} 1478b877906bSopenharmony_ci 1479b877906bSopenharmony_cistatic void demo_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { 1480b877906bSopenharmony_ci if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) 1481b877906bSopenharmony_ci glfwSetWindowShouldClose(window, GLFW_TRUE); 1482b877906bSopenharmony_ci} 1483b877906bSopenharmony_ci 1484b877906bSopenharmony_cistatic void demo_refresh_callback(GLFWwindow* window) { 1485b877906bSopenharmony_ci struct demo* demo = glfwGetWindowUserPointer(window); 1486b877906bSopenharmony_ci demo_draw(demo); 1487b877906bSopenharmony_ci} 1488b877906bSopenharmony_ci 1489b877906bSopenharmony_cistatic void demo_resize_callback(GLFWwindow* window, int width, int height) { 1490b877906bSopenharmony_ci struct demo* demo = glfwGetWindowUserPointer(window); 1491b877906bSopenharmony_ci demo->width = width; 1492b877906bSopenharmony_ci demo->height = height; 1493b877906bSopenharmony_ci demo_resize(demo); 1494b877906bSopenharmony_ci} 1495b877906bSopenharmony_ci 1496b877906bSopenharmony_cistatic void demo_run(struct demo *demo) { 1497b877906bSopenharmony_ci while (!glfwWindowShouldClose(demo->window)) { 1498b877906bSopenharmony_ci glfwPollEvents(); 1499b877906bSopenharmony_ci 1500b877906bSopenharmony_ci demo_draw(demo); 1501b877906bSopenharmony_ci 1502b877906bSopenharmony_ci if (demo->depthStencil > 0.99f) 1503b877906bSopenharmony_ci demo->depthIncrement = -0.001f; 1504b877906bSopenharmony_ci if (demo->depthStencil < 0.8f) 1505b877906bSopenharmony_ci demo->depthIncrement = 0.001f; 1506b877906bSopenharmony_ci 1507b877906bSopenharmony_ci demo->depthStencil += demo->depthIncrement; 1508b877906bSopenharmony_ci 1509b877906bSopenharmony_ci // Wait for work to finish before updating MVP. 1510b877906bSopenharmony_ci vkDeviceWaitIdle(demo->device); 1511b877906bSopenharmony_ci demo->curFrame++; 1512b877906bSopenharmony_ci if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount) 1513b877906bSopenharmony_ci glfwSetWindowShouldClose(demo->window, GLFW_TRUE); 1514b877906bSopenharmony_ci } 1515b877906bSopenharmony_ci} 1516b877906bSopenharmony_ci 1517b877906bSopenharmony_cistatic void demo_create_window(struct demo *demo) { 1518b877906bSopenharmony_ci glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 1519b877906bSopenharmony_ci 1520b877906bSopenharmony_ci demo->window = glfwCreateWindow(demo->width, 1521b877906bSopenharmony_ci demo->height, 1522b877906bSopenharmony_ci APP_LONG_NAME, 1523b877906bSopenharmony_ci NULL, 1524b877906bSopenharmony_ci NULL); 1525b877906bSopenharmony_ci if (!demo->window) { 1526b877906bSopenharmony_ci // It didn't work, so try to give a useful error: 1527b877906bSopenharmony_ci printf("Cannot create a window in which to draw!\n"); 1528b877906bSopenharmony_ci fflush(stdout); 1529b877906bSopenharmony_ci exit(1); 1530b877906bSopenharmony_ci } 1531b877906bSopenharmony_ci 1532b877906bSopenharmony_ci glfwSetWindowUserPointer(demo->window, demo); 1533b877906bSopenharmony_ci glfwSetWindowRefreshCallback(demo->window, demo_refresh_callback); 1534b877906bSopenharmony_ci glfwSetFramebufferSizeCallback(demo->window, demo_resize_callback); 1535b877906bSopenharmony_ci glfwSetKeyCallback(demo->window, demo_key_callback); 1536b877906bSopenharmony_ci} 1537b877906bSopenharmony_ci 1538b877906bSopenharmony_ci/* 1539b877906bSopenharmony_ci * Return 1 (true) if all layer names specified in check_names 1540b877906bSopenharmony_ci * can be found in given layer properties. 1541b877906bSopenharmony_ci */ 1542b877906bSopenharmony_cistatic VkBool32 demo_check_layers(uint32_t check_count, const char **check_names, 1543b877906bSopenharmony_ci uint32_t layer_count, 1544b877906bSopenharmony_ci VkLayerProperties *layers) { 1545b877906bSopenharmony_ci uint32_t i, j; 1546b877906bSopenharmony_ci for (i = 0; i < check_count; i++) { 1547b877906bSopenharmony_ci VkBool32 found = 0; 1548b877906bSopenharmony_ci for (j = 0; j < layer_count; j++) { 1549b877906bSopenharmony_ci if (!strcmp(check_names[i], layers[j].layerName)) { 1550b877906bSopenharmony_ci found = 1; 1551b877906bSopenharmony_ci break; 1552b877906bSopenharmony_ci } 1553b877906bSopenharmony_ci } 1554b877906bSopenharmony_ci if (!found) { 1555b877906bSopenharmony_ci fprintf(stderr, "Cannot find layer: %s\n", check_names[i]); 1556b877906bSopenharmony_ci return 0; 1557b877906bSopenharmony_ci } 1558b877906bSopenharmony_ci } 1559b877906bSopenharmony_ci return 1; 1560b877906bSopenharmony_ci} 1561b877906bSopenharmony_ci 1562b877906bSopenharmony_cistatic void demo_init_vk(struct demo *demo) { 1563b877906bSopenharmony_ci VkResult err; 1564b877906bSopenharmony_ci VkBool32 portability_enumeration = VK_FALSE; 1565b877906bSopenharmony_ci uint32_t i = 0; 1566b877906bSopenharmony_ci uint32_t required_extension_count = 0; 1567b877906bSopenharmony_ci uint32_t instance_extension_count = 0; 1568b877906bSopenharmony_ci uint32_t instance_layer_count = 0; 1569b877906bSopenharmony_ci uint32_t validation_layer_count = 0; 1570b877906bSopenharmony_ci const char **required_extensions = NULL; 1571b877906bSopenharmony_ci const char **instance_validation_layers = NULL; 1572b877906bSopenharmony_ci demo->enabled_extension_count = 0; 1573b877906bSopenharmony_ci demo->enabled_layer_count = 0; 1574b877906bSopenharmony_ci 1575b877906bSopenharmony_ci char *instance_validation_layers_alt1[] = { 1576b877906bSopenharmony_ci "VK_LAYER_LUNARG_standard_validation" 1577b877906bSopenharmony_ci }; 1578b877906bSopenharmony_ci 1579b877906bSopenharmony_ci char *instance_validation_layers_alt2[] = { 1580b877906bSopenharmony_ci "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", 1581b877906bSopenharmony_ci "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_image", 1582b877906bSopenharmony_ci "VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain", 1583b877906bSopenharmony_ci "VK_LAYER_GOOGLE_unique_objects" 1584b877906bSopenharmony_ci }; 1585b877906bSopenharmony_ci 1586b877906bSopenharmony_ci /* Look for validation layers */ 1587b877906bSopenharmony_ci VkBool32 validation_found = 0; 1588b877906bSopenharmony_ci if (demo->validate) { 1589b877906bSopenharmony_ci 1590b877906bSopenharmony_ci err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL); 1591b877906bSopenharmony_ci assert(!err); 1592b877906bSopenharmony_ci 1593b877906bSopenharmony_ci instance_validation_layers = (const char**) instance_validation_layers_alt1; 1594b877906bSopenharmony_ci if (instance_layer_count > 0) { 1595b877906bSopenharmony_ci VkLayerProperties *instance_layers = 1596b877906bSopenharmony_ci malloc(sizeof (VkLayerProperties) * instance_layer_count); 1597b877906bSopenharmony_ci err = vkEnumerateInstanceLayerProperties(&instance_layer_count, 1598b877906bSopenharmony_ci instance_layers); 1599b877906bSopenharmony_ci assert(!err); 1600b877906bSopenharmony_ci 1601b877906bSopenharmony_ci 1602b877906bSopenharmony_ci validation_found = demo_check_layers( 1603b877906bSopenharmony_ci ARRAY_SIZE(instance_validation_layers_alt1), 1604b877906bSopenharmony_ci instance_validation_layers, instance_layer_count, 1605b877906bSopenharmony_ci instance_layers); 1606b877906bSopenharmony_ci if (validation_found) { 1607b877906bSopenharmony_ci demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt1); 1608b877906bSopenharmony_ci demo->enabled_layers[0] = "VK_LAYER_LUNARG_standard_validation"; 1609b877906bSopenharmony_ci validation_layer_count = 1; 1610b877906bSopenharmony_ci } else { 1611b877906bSopenharmony_ci // use alternative set of validation layers 1612b877906bSopenharmony_ci instance_validation_layers = 1613b877906bSopenharmony_ci (const char**) instance_validation_layers_alt2; 1614b877906bSopenharmony_ci demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt2); 1615b877906bSopenharmony_ci validation_found = demo_check_layers( 1616b877906bSopenharmony_ci ARRAY_SIZE(instance_validation_layers_alt2), 1617b877906bSopenharmony_ci instance_validation_layers, instance_layer_count, 1618b877906bSopenharmony_ci instance_layers); 1619b877906bSopenharmony_ci validation_layer_count = 1620b877906bSopenharmony_ci ARRAY_SIZE(instance_validation_layers_alt2); 1621b877906bSopenharmony_ci for (i = 0; i < validation_layer_count; i++) { 1622b877906bSopenharmony_ci demo->enabled_layers[i] = instance_validation_layers[i]; 1623b877906bSopenharmony_ci } 1624b877906bSopenharmony_ci } 1625b877906bSopenharmony_ci free(instance_layers); 1626b877906bSopenharmony_ci } 1627b877906bSopenharmony_ci 1628b877906bSopenharmony_ci if (!validation_found) { 1629b877906bSopenharmony_ci ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find " 1630b877906bSopenharmony_ci "required validation layer.\n\n" 1631b877906bSopenharmony_ci "Please look at the Getting Started guide for additional " 1632b877906bSopenharmony_ci "information.\n", 1633b877906bSopenharmony_ci "vkCreateInstance Failure"); 1634b877906bSopenharmony_ci } 1635b877906bSopenharmony_ci } 1636b877906bSopenharmony_ci 1637b877906bSopenharmony_ci /* Look for instance extensions */ 1638b877906bSopenharmony_ci required_extensions = glfwGetRequiredInstanceExtensions(&required_extension_count); 1639b877906bSopenharmony_ci if (!required_extensions) { 1640b877906bSopenharmony_ci ERR_EXIT("glfwGetRequiredInstanceExtensions failed to find the " 1641b877906bSopenharmony_ci "platform surface extensions.\n\nDo you have a compatible " 1642b877906bSopenharmony_ci "Vulkan installable client driver (ICD) installed?\nPlease " 1643b877906bSopenharmony_ci "look at the Getting Started guide for additional " 1644b877906bSopenharmony_ci "information.\n", 1645b877906bSopenharmony_ci "vkCreateInstance Failure"); 1646b877906bSopenharmony_ci } 1647b877906bSopenharmony_ci 1648b877906bSopenharmony_ci for (i = 0; i < required_extension_count; i++) { 1649b877906bSopenharmony_ci demo->extension_names[demo->enabled_extension_count++] = required_extensions[i]; 1650b877906bSopenharmony_ci assert(demo->enabled_extension_count < 64); 1651b877906bSopenharmony_ci } 1652b877906bSopenharmony_ci 1653b877906bSopenharmony_ci err = vkEnumerateInstanceExtensionProperties( 1654b877906bSopenharmony_ci NULL, &instance_extension_count, NULL); 1655b877906bSopenharmony_ci assert(!err); 1656b877906bSopenharmony_ci 1657b877906bSopenharmony_ci if (instance_extension_count > 0) { 1658b877906bSopenharmony_ci VkExtensionProperties *instance_extensions = 1659b877906bSopenharmony_ci malloc(sizeof(VkExtensionProperties) * instance_extension_count); 1660b877906bSopenharmony_ci err = vkEnumerateInstanceExtensionProperties( 1661b877906bSopenharmony_ci NULL, &instance_extension_count, instance_extensions); 1662b877906bSopenharmony_ci assert(!err); 1663b877906bSopenharmony_ci for (i = 0; i < instance_extension_count; i++) { 1664b877906bSopenharmony_ci if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, 1665b877906bSopenharmony_ci instance_extensions[i].extensionName)) { 1666b877906bSopenharmony_ci if (demo->validate) { 1667b877906bSopenharmony_ci demo->extension_names[demo->enabled_extension_count++] = 1668b877906bSopenharmony_ci VK_EXT_DEBUG_REPORT_EXTENSION_NAME; 1669b877906bSopenharmony_ci } 1670b877906bSopenharmony_ci } 1671b877906bSopenharmony_ci assert(demo->enabled_extension_count < 64); 1672b877906bSopenharmony_ci if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, 1673b877906bSopenharmony_ci instance_extensions[i].extensionName)) { 1674b877906bSopenharmony_ci demo->extension_names[demo->enabled_extension_count++] = 1675b877906bSopenharmony_ci VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME; 1676b877906bSopenharmony_ci portability_enumeration = VK_TRUE; 1677b877906bSopenharmony_ci } 1678b877906bSopenharmony_ci assert(demo->enabled_extension_count < 64); 1679b877906bSopenharmony_ci } 1680b877906bSopenharmony_ci 1681b877906bSopenharmony_ci free(instance_extensions); 1682b877906bSopenharmony_ci } 1683b877906bSopenharmony_ci 1684b877906bSopenharmony_ci const VkApplicationInfo app = { 1685b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 1686b877906bSopenharmony_ci .pNext = NULL, 1687b877906bSopenharmony_ci .pApplicationName = APP_SHORT_NAME, 1688b877906bSopenharmony_ci .applicationVersion = 0, 1689b877906bSopenharmony_ci .pEngineName = APP_SHORT_NAME, 1690b877906bSopenharmony_ci .engineVersion = 0, 1691b877906bSopenharmony_ci .apiVersion = VK_API_VERSION_1_0, 1692b877906bSopenharmony_ci }; 1693b877906bSopenharmony_ci VkInstanceCreateInfo inst_info = { 1694b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 1695b877906bSopenharmony_ci .pNext = NULL, 1696b877906bSopenharmony_ci .pApplicationInfo = &app, 1697b877906bSopenharmony_ci .enabledLayerCount = demo->enabled_layer_count, 1698b877906bSopenharmony_ci .ppEnabledLayerNames = (const char *const *)instance_validation_layers, 1699b877906bSopenharmony_ci .enabledExtensionCount = demo->enabled_extension_count, 1700b877906bSopenharmony_ci .ppEnabledExtensionNames = (const char *const *)demo->extension_names, 1701b877906bSopenharmony_ci }; 1702b877906bSopenharmony_ci 1703b877906bSopenharmony_ci if (portability_enumeration) 1704b877906bSopenharmony_ci inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; 1705b877906bSopenharmony_ci 1706b877906bSopenharmony_ci uint32_t gpu_count; 1707b877906bSopenharmony_ci 1708b877906bSopenharmony_ci err = vkCreateInstance(&inst_info, NULL, &demo->inst); 1709b877906bSopenharmony_ci if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { 1710b877906bSopenharmony_ci ERR_EXIT("Cannot find a compatible Vulkan installable client driver " 1711b877906bSopenharmony_ci "(ICD).\n\nPlease look at the Getting Started guide for " 1712b877906bSopenharmony_ci "additional information.\n", 1713b877906bSopenharmony_ci "vkCreateInstance Failure"); 1714b877906bSopenharmony_ci } else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) { 1715b877906bSopenharmony_ci ERR_EXIT("Cannot find a specified extension library" 1716b877906bSopenharmony_ci ".\nMake sure your layers path is set appropriately\n", 1717b877906bSopenharmony_ci "vkCreateInstance Failure"); 1718b877906bSopenharmony_ci } else if (err) { 1719b877906bSopenharmony_ci ERR_EXIT("vkCreateInstance failed.\n\nDo you have a compatible Vulkan " 1720b877906bSopenharmony_ci "installable client driver (ICD) installed?\nPlease look at " 1721b877906bSopenharmony_ci "the Getting Started guide for additional information.\n", 1722b877906bSopenharmony_ci "vkCreateInstance Failure"); 1723b877906bSopenharmony_ci } 1724b877906bSopenharmony_ci 1725b877906bSopenharmony_ci gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, demo->inst); 1726b877906bSopenharmony_ci 1727b877906bSopenharmony_ci /* Make initial call to query gpu_count, then second call for gpu info*/ 1728b877906bSopenharmony_ci err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL); 1729b877906bSopenharmony_ci assert(!err && gpu_count > 0); 1730b877906bSopenharmony_ci 1731b877906bSopenharmony_ci if (gpu_count > 0) { 1732b877906bSopenharmony_ci VkPhysicalDevice *physical_devices = 1733b877906bSopenharmony_ci malloc(sizeof(VkPhysicalDevice) * gpu_count); 1734b877906bSopenharmony_ci err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, 1735b877906bSopenharmony_ci physical_devices); 1736b877906bSopenharmony_ci assert(!err); 1737b877906bSopenharmony_ci /* For tri demo we just grab the first physical device */ 1738b877906bSopenharmony_ci demo->gpu = physical_devices[0]; 1739b877906bSopenharmony_ci free(physical_devices); 1740b877906bSopenharmony_ci } else { 1741b877906bSopenharmony_ci ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices." 1742b877906bSopenharmony_ci "\n\nDo you have a compatible Vulkan installable client" 1743b877906bSopenharmony_ci " driver (ICD) installed?\nPlease look at the Getting Started" 1744b877906bSopenharmony_ci " guide for additional information.\n", 1745b877906bSopenharmony_ci "vkEnumeratePhysicalDevices Failure"); 1746b877906bSopenharmony_ci } 1747b877906bSopenharmony_ci 1748b877906bSopenharmony_ci gladLoadVulkanUserPtr(demo->gpu, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, demo->inst); 1749b877906bSopenharmony_ci 1750b877906bSopenharmony_ci /* Look for device extensions */ 1751b877906bSopenharmony_ci uint32_t device_extension_count = 0; 1752b877906bSopenharmony_ci VkBool32 swapchainExtFound = 0; 1753b877906bSopenharmony_ci demo->enabled_extension_count = 0; 1754b877906bSopenharmony_ci 1755b877906bSopenharmony_ci err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL, 1756b877906bSopenharmony_ci &device_extension_count, NULL); 1757b877906bSopenharmony_ci assert(!err); 1758b877906bSopenharmony_ci 1759b877906bSopenharmony_ci if (device_extension_count > 0) { 1760b877906bSopenharmony_ci VkExtensionProperties *device_extensions = 1761b877906bSopenharmony_ci malloc(sizeof(VkExtensionProperties) * device_extension_count); 1762b877906bSopenharmony_ci err = vkEnumerateDeviceExtensionProperties( 1763b877906bSopenharmony_ci demo->gpu, NULL, &device_extension_count, device_extensions); 1764b877906bSopenharmony_ci assert(!err); 1765b877906bSopenharmony_ci 1766b877906bSopenharmony_ci for (i = 0; i < device_extension_count; i++) { 1767b877906bSopenharmony_ci if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 1768b877906bSopenharmony_ci device_extensions[i].extensionName)) { 1769b877906bSopenharmony_ci swapchainExtFound = 1; 1770b877906bSopenharmony_ci demo->extension_names[demo->enabled_extension_count++] = 1771b877906bSopenharmony_ci VK_KHR_SWAPCHAIN_EXTENSION_NAME; 1772b877906bSopenharmony_ci } 1773b877906bSopenharmony_ci assert(demo->enabled_extension_count < 64); 1774b877906bSopenharmony_ci } 1775b877906bSopenharmony_ci 1776b877906bSopenharmony_ci free(device_extensions); 1777b877906bSopenharmony_ci } 1778b877906bSopenharmony_ci 1779b877906bSopenharmony_ci if (!swapchainExtFound) { 1780b877906bSopenharmony_ci ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find " 1781b877906bSopenharmony_ci "the " VK_KHR_SWAPCHAIN_EXTENSION_NAME 1782b877906bSopenharmony_ci " extension.\n\nDo you have a compatible " 1783b877906bSopenharmony_ci "Vulkan installable client driver (ICD) installed?\nPlease " 1784b877906bSopenharmony_ci "look at the Getting Started guide for additional " 1785b877906bSopenharmony_ci "information.\n", 1786b877906bSopenharmony_ci "vkCreateInstance Failure"); 1787b877906bSopenharmony_ci } 1788b877906bSopenharmony_ci 1789b877906bSopenharmony_ci if (demo->validate) { 1790b877906bSopenharmony_ci VkDebugReportCallbackCreateInfoEXT dbgCreateInfo; 1791b877906bSopenharmony_ci dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 1792b877906bSopenharmony_ci dbgCreateInfo.flags = 1793b877906bSopenharmony_ci VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; 1794b877906bSopenharmony_ci dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc; 1795b877906bSopenharmony_ci dbgCreateInfo.pUserData = demo; 1796b877906bSopenharmony_ci dbgCreateInfo.pNext = NULL; 1797b877906bSopenharmony_ci err = vkCreateDebugReportCallbackEXT(demo->inst, &dbgCreateInfo, NULL, 1798b877906bSopenharmony_ci &demo->msg_callback); 1799b877906bSopenharmony_ci switch (err) { 1800b877906bSopenharmony_ci case VK_SUCCESS: 1801b877906bSopenharmony_ci break; 1802b877906bSopenharmony_ci case VK_ERROR_OUT_OF_HOST_MEMORY: 1803b877906bSopenharmony_ci ERR_EXIT("CreateDebugReportCallback: out of host memory\n", 1804b877906bSopenharmony_ci "CreateDebugReportCallback Failure"); 1805b877906bSopenharmony_ci break; 1806b877906bSopenharmony_ci default: 1807b877906bSopenharmony_ci ERR_EXIT("CreateDebugReportCallback: unknown failure\n", 1808b877906bSopenharmony_ci "CreateDebugReportCallback Failure"); 1809b877906bSopenharmony_ci break; 1810b877906bSopenharmony_ci } 1811b877906bSopenharmony_ci } 1812b877906bSopenharmony_ci 1813b877906bSopenharmony_ci vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props); 1814b877906bSopenharmony_ci 1815b877906bSopenharmony_ci // Query with NULL data to get count 1816b877906bSopenharmony_ci vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_count, 1817b877906bSopenharmony_ci NULL); 1818b877906bSopenharmony_ci 1819b877906bSopenharmony_ci demo->queue_props = (VkQueueFamilyProperties *)malloc( 1820b877906bSopenharmony_ci demo->queue_count * sizeof(VkQueueFamilyProperties)); 1821b877906bSopenharmony_ci vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_count, 1822b877906bSopenharmony_ci demo->queue_props); 1823b877906bSopenharmony_ci assert(demo->queue_count >= 1); 1824b877906bSopenharmony_ci 1825b877906bSopenharmony_ci vkGetPhysicalDeviceFeatures(demo->gpu, &demo->gpu_features); 1826b877906bSopenharmony_ci 1827b877906bSopenharmony_ci // Graphics queue and MemMgr queue can be separate. 1828b877906bSopenharmony_ci // TODO: Add support for separate queues, including synchronization, 1829b877906bSopenharmony_ci // and appropriate tracking for QueueSubmit 1830b877906bSopenharmony_ci} 1831b877906bSopenharmony_ci 1832b877906bSopenharmony_cistatic void demo_init_device(struct demo *demo) { 1833b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1834b877906bSopenharmony_ci 1835b877906bSopenharmony_ci float queue_priorities[1] = {0.0}; 1836b877906bSopenharmony_ci const VkDeviceQueueCreateInfo queue = { 1837b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 1838b877906bSopenharmony_ci .pNext = NULL, 1839b877906bSopenharmony_ci .queueFamilyIndex = demo->graphics_queue_node_index, 1840b877906bSopenharmony_ci .queueCount = 1, 1841b877906bSopenharmony_ci .pQueuePriorities = queue_priorities}; 1842b877906bSopenharmony_ci 1843b877906bSopenharmony_ci 1844b877906bSopenharmony_ci VkPhysicalDeviceFeatures features; 1845b877906bSopenharmony_ci memset(&features, 0, sizeof(features)); 1846b877906bSopenharmony_ci if (demo->gpu_features.shaderClipDistance) { 1847b877906bSopenharmony_ci features.shaderClipDistance = VK_TRUE; 1848b877906bSopenharmony_ci } 1849b877906bSopenharmony_ci 1850b877906bSopenharmony_ci VkDeviceCreateInfo device = { 1851b877906bSopenharmony_ci .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 1852b877906bSopenharmony_ci .pNext = NULL, 1853b877906bSopenharmony_ci .queueCreateInfoCount = 1, 1854b877906bSopenharmony_ci .pQueueCreateInfos = &queue, 1855b877906bSopenharmony_ci .enabledLayerCount = 0, 1856b877906bSopenharmony_ci .ppEnabledLayerNames = NULL, 1857b877906bSopenharmony_ci .enabledExtensionCount = demo->enabled_extension_count, 1858b877906bSopenharmony_ci .ppEnabledExtensionNames = (const char *const *)demo->extension_names, 1859b877906bSopenharmony_ci .pEnabledFeatures = &features, 1860b877906bSopenharmony_ci }; 1861b877906bSopenharmony_ci 1862b877906bSopenharmony_ci err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device); 1863b877906bSopenharmony_ci assert(!err); 1864b877906bSopenharmony_ci} 1865b877906bSopenharmony_ci 1866b877906bSopenharmony_cistatic void demo_init_vk_swapchain(struct demo *demo) { 1867b877906bSopenharmony_ci VkResult U_ASSERT_ONLY err; 1868b877906bSopenharmony_ci uint32_t i; 1869b877906bSopenharmony_ci 1870b877906bSopenharmony_ci // Create a WSI surface for the window: 1871b877906bSopenharmony_ci glfwCreateWindowSurface(demo->inst, demo->window, NULL, &demo->surface); 1872b877906bSopenharmony_ci 1873b877906bSopenharmony_ci // Iterate over each queue to learn whether it supports presenting: 1874b877906bSopenharmony_ci VkBool32 *supportsPresent = 1875b877906bSopenharmony_ci (VkBool32 *)malloc(demo->queue_count * sizeof(VkBool32)); 1876b877906bSopenharmony_ci for (i = 0; i < demo->queue_count; i++) { 1877b877906bSopenharmony_ci vkGetPhysicalDeviceSurfaceSupportKHR(demo->gpu, i, demo->surface, 1878b877906bSopenharmony_ci &supportsPresent[i]); 1879b877906bSopenharmony_ci } 1880b877906bSopenharmony_ci 1881b877906bSopenharmony_ci // Search for a graphics and a present queue in the array of queue 1882b877906bSopenharmony_ci // families, try to find one that supports both 1883b877906bSopenharmony_ci uint32_t graphicsQueueNodeIndex = UINT32_MAX; 1884b877906bSopenharmony_ci uint32_t presentQueueNodeIndex = UINT32_MAX; 1885b877906bSopenharmony_ci for (i = 0; i < demo->queue_count; i++) { 1886b877906bSopenharmony_ci if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) { 1887b877906bSopenharmony_ci if (graphicsQueueNodeIndex == UINT32_MAX) { 1888b877906bSopenharmony_ci graphicsQueueNodeIndex = i; 1889b877906bSopenharmony_ci } 1890b877906bSopenharmony_ci 1891b877906bSopenharmony_ci if (supportsPresent[i] == VK_TRUE) { 1892b877906bSopenharmony_ci graphicsQueueNodeIndex = i; 1893b877906bSopenharmony_ci presentQueueNodeIndex = i; 1894b877906bSopenharmony_ci break; 1895b877906bSopenharmony_ci } 1896b877906bSopenharmony_ci } 1897b877906bSopenharmony_ci } 1898b877906bSopenharmony_ci if (presentQueueNodeIndex == UINT32_MAX) { 1899b877906bSopenharmony_ci // If didn't find a queue that supports both graphics and present, then 1900b877906bSopenharmony_ci // find a separate present queue. 1901b877906bSopenharmony_ci for (i = 0; i < demo->queue_count; ++i) { 1902b877906bSopenharmony_ci if (supportsPresent[i] == VK_TRUE) { 1903b877906bSopenharmony_ci presentQueueNodeIndex = i; 1904b877906bSopenharmony_ci break; 1905b877906bSopenharmony_ci } 1906b877906bSopenharmony_ci } 1907b877906bSopenharmony_ci } 1908b877906bSopenharmony_ci free(supportsPresent); 1909b877906bSopenharmony_ci 1910b877906bSopenharmony_ci // Generate error if could not find both a graphics and a present queue 1911b877906bSopenharmony_ci if (graphicsQueueNodeIndex == UINT32_MAX || 1912b877906bSopenharmony_ci presentQueueNodeIndex == UINT32_MAX) { 1913b877906bSopenharmony_ci ERR_EXIT("Could not find a graphics and a present queue\n", 1914b877906bSopenharmony_ci "Swapchain Initialization Failure"); 1915b877906bSopenharmony_ci } 1916b877906bSopenharmony_ci 1917b877906bSopenharmony_ci // TODO: Add support for separate queues, including presentation, 1918b877906bSopenharmony_ci // synchronization, and appropriate tracking for QueueSubmit. 1919b877906bSopenharmony_ci // NOTE: While it is possible for an application to use a separate graphics 1920b877906bSopenharmony_ci // and a present queues, this demo program assumes it is only using 1921b877906bSopenharmony_ci // one: 1922b877906bSopenharmony_ci if (graphicsQueueNodeIndex != presentQueueNodeIndex) { 1923b877906bSopenharmony_ci ERR_EXIT("Could not find a common graphics and a present queue\n", 1924b877906bSopenharmony_ci "Swapchain Initialization Failure"); 1925b877906bSopenharmony_ci } 1926b877906bSopenharmony_ci 1927b877906bSopenharmony_ci demo->graphics_queue_node_index = graphicsQueueNodeIndex; 1928b877906bSopenharmony_ci 1929b877906bSopenharmony_ci demo_init_device(demo); 1930b877906bSopenharmony_ci 1931b877906bSopenharmony_ci vkGetDeviceQueue(demo->device, demo->graphics_queue_node_index, 0, 1932b877906bSopenharmony_ci &demo->queue); 1933b877906bSopenharmony_ci 1934b877906bSopenharmony_ci // Get the list of VkFormat's that are supported: 1935b877906bSopenharmony_ci uint32_t formatCount; 1936b877906bSopenharmony_ci err = vkGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface, 1937b877906bSopenharmony_ci &formatCount, NULL); 1938b877906bSopenharmony_ci assert(!err); 1939b877906bSopenharmony_ci VkSurfaceFormatKHR *surfFormats = 1940b877906bSopenharmony_ci (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR)); 1941b877906bSopenharmony_ci err = vkGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface, 1942b877906bSopenharmony_ci &formatCount, surfFormats); 1943b877906bSopenharmony_ci assert(!err); 1944b877906bSopenharmony_ci // If the format list includes just one entry of VK_FORMAT_UNDEFINED, 1945b877906bSopenharmony_ci // the surface has no preferred format. Otherwise, at least one 1946b877906bSopenharmony_ci // supported format will be returned. 1947b877906bSopenharmony_ci if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) { 1948b877906bSopenharmony_ci demo->format = VK_FORMAT_B8G8R8A8_UNORM; 1949b877906bSopenharmony_ci } else { 1950b877906bSopenharmony_ci assert(formatCount >= 1); 1951b877906bSopenharmony_ci demo->format = surfFormats[0].format; 1952b877906bSopenharmony_ci } 1953b877906bSopenharmony_ci demo->color_space = surfFormats[0].colorSpace; 1954b877906bSopenharmony_ci 1955b877906bSopenharmony_ci demo->curFrame = 0; 1956b877906bSopenharmony_ci 1957b877906bSopenharmony_ci // Get Memory information and properties 1958b877906bSopenharmony_ci vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_properties); 1959b877906bSopenharmony_ci} 1960b877906bSopenharmony_ci 1961b877906bSopenharmony_cistatic void demo_init_connection(struct demo *demo) { 1962b877906bSopenharmony_ci glfwSetErrorCallback(demo_error_callback); 1963b877906bSopenharmony_ci 1964b877906bSopenharmony_ci if (!glfwInit()) { 1965b877906bSopenharmony_ci printf("Cannot initialize GLFW.\nExiting ...\n"); 1966b877906bSopenharmony_ci fflush(stdout); 1967b877906bSopenharmony_ci exit(1); 1968b877906bSopenharmony_ci } 1969b877906bSopenharmony_ci 1970b877906bSopenharmony_ci if (!glfwVulkanSupported()) { 1971b877906bSopenharmony_ci printf("GLFW failed to find the Vulkan loader.\nExiting ...\n"); 1972b877906bSopenharmony_ci fflush(stdout); 1973b877906bSopenharmony_ci exit(1); 1974b877906bSopenharmony_ci } 1975b877906bSopenharmony_ci 1976b877906bSopenharmony_ci gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, NULL); 1977b877906bSopenharmony_ci} 1978b877906bSopenharmony_ci 1979b877906bSopenharmony_cistatic void demo_init(struct demo *demo, const int argc, const char *argv[]) 1980b877906bSopenharmony_ci{ 1981b877906bSopenharmony_ci int i; 1982b877906bSopenharmony_ci memset(demo, 0, sizeof(*demo)); 1983b877906bSopenharmony_ci demo->frameCount = INT32_MAX; 1984b877906bSopenharmony_ci 1985b877906bSopenharmony_ci for (i = 1; i < argc; i++) { 1986b877906bSopenharmony_ci if (strcmp(argv[i], "--use_staging") == 0) { 1987b877906bSopenharmony_ci demo->use_staging_buffer = true; 1988b877906bSopenharmony_ci continue; 1989b877906bSopenharmony_ci } 1990b877906bSopenharmony_ci if (strcmp(argv[i], "--break") == 0) { 1991b877906bSopenharmony_ci demo->use_break = true; 1992b877906bSopenharmony_ci continue; 1993b877906bSopenharmony_ci } 1994b877906bSopenharmony_ci if (strcmp(argv[i], "--validate") == 0) { 1995b877906bSopenharmony_ci demo->validate = true; 1996b877906bSopenharmony_ci continue; 1997b877906bSopenharmony_ci } 1998b877906bSopenharmony_ci if (strcmp(argv[i], "--c") == 0 && demo->frameCount == INT32_MAX && 1999b877906bSopenharmony_ci i < argc - 1 && sscanf(argv[i + 1], "%d", &demo->frameCount) == 1 && 2000b877906bSopenharmony_ci demo->frameCount >= 0) { 2001b877906bSopenharmony_ci i++; 2002b877906bSopenharmony_ci continue; 2003b877906bSopenharmony_ci } 2004b877906bSopenharmony_ci 2005b877906bSopenharmony_ci fprintf(stderr, "Usage:\n %s [--use_staging] [--validate] [--break] " 2006b877906bSopenharmony_ci "[--c <framecount>]\n", 2007b877906bSopenharmony_ci APP_SHORT_NAME); 2008b877906bSopenharmony_ci fflush(stderr); 2009b877906bSopenharmony_ci exit(1); 2010b877906bSopenharmony_ci } 2011b877906bSopenharmony_ci 2012b877906bSopenharmony_ci demo_init_connection(demo); 2013b877906bSopenharmony_ci demo_init_vk(demo); 2014b877906bSopenharmony_ci 2015b877906bSopenharmony_ci demo->width = 300; 2016b877906bSopenharmony_ci demo->height = 300; 2017b877906bSopenharmony_ci demo->depthStencil = 1.0; 2018b877906bSopenharmony_ci demo->depthIncrement = -0.01f; 2019b877906bSopenharmony_ci} 2020b877906bSopenharmony_ci 2021b877906bSopenharmony_cistatic void demo_cleanup(struct demo *demo) { 2022b877906bSopenharmony_ci uint32_t i; 2023b877906bSopenharmony_ci 2024b877906bSopenharmony_ci for (i = 0; i < demo->swapchainImageCount; i++) { 2025b877906bSopenharmony_ci vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL); 2026b877906bSopenharmony_ci } 2027b877906bSopenharmony_ci free(demo->framebuffers); 2028b877906bSopenharmony_ci vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL); 2029b877906bSopenharmony_ci 2030b877906bSopenharmony_ci if (demo->setup_cmd) { 2031b877906bSopenharmony_ci vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->setup_cmd); 2032b877906bSopenharmony_ci } 2033b877906bSopenharmony_ci vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->draw_cmd); 2034b877906bSopenharmony_ci vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL); 2035b877906bSopenharmony_ci 2036b877906bSopenharmony_ci vkDestroyPipeline(demo->device, demo->pipeline, NULL); 2037b877906bSopenharmony_ci vkDestroyRenderPass(demo->device, demo->render_pass, NULL); 2038b877906bSopenharmony_ci vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL); 2039b877906bSopenharmony_ci vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL); 2040b877906bSopenharmony_ci 2041b877906bSopenharmony_ci vkDestroyBuffer(demo->device, demo->vertices.buf, NULL); 2042b877906bSopenharmony_ci vkFreeMemory(demo->device, demo->vertices.mem, NULL); 2043b877906bSopenharmony_ci 2044b877906bSopenharmony_ci for (i = 0; i < DEMO_TEXTURE_COUNT; i++) { 2045b877906bSopenharmony_ci vkDestroyImageView(demo->device, demo->textures[i].view, NULL); 2046b877906bSopenharmony_ci vkDestroyImage(demo->device, demo->textures[i].image, NULL); 2047b877906bSopenharmony_ci vkFreeMemory(demo->device, demo->textures[i].mem, NULL); 2048b877906bSopenharmony_ci vkDestroySampler(demo->device, demo->textures[i].sampler, NULL); 2049b877906bSopenharmony_ci } 2050b877906bSopenharmony_ci 2051b877906bSopenharmony_ci for (i = 0; i < demo->swapchainImageCount; i++) { 2052b877906bSopenharmony_ci vkDestroyImageView(demo->device, demo->buffers[i].view, NULL); 2053b877906bSopenharmony_ci } 2054b877906bSopenharmony_ci 2055b877906bSopenharmony_ci vkDestroyImageView(demo->device, demo->depth.view, NULL); 2056b877906bSopenharmony_ci vkDestroyImage(demo->device, demo->depth.image, NULL); 2057b877906bSopenharmony_ci vkFreeMemory(demo->device, demo->depth.mem, NULL); 2058b877906bSopenharmony_ci 2059b877906bSopenharmony_ci vkDestroySwapchainKHR(demo->device, demo->swapchain, NULL); 2060b877906bSopenharmony_ci free(demo->buffers); 2061b877906bSopenharmony_ci 2062b877906bSopenharmony_ci vkDestroyDevice(demo->device, NULL); 2063b877906bSopenharmony_ci if (demo->validate) { 2064b877906bSopenharmony_ci vkDestroyDebugReportCallbackEXT(demo->inst, demo->msg_callback, NULL); 2065b877906bSopenharmony_ci } 2066b877906bSopenharmony_ci vkDestroySurfaceKHR(demo->inst, demo->surface, NULL); 2067b877906bSopenharmony_ci vkDestroyInstance(demo->inst, NULL); 2068b877906bSopenharmony_ci 2069b877906bSopenharmony_ci free(demo->queue_props); 2070b877906bSopenharmony_ci 2071b877906bSopenharmony_ci glfwDestroyWindow(demo->window); 2072b877906bSopenharmony_ci glfwTerminate(); 2073b877906bSopenharmony_ci} 2074b877906bSopenharmony_ci 2075b877906bSopenharmony_cistatic void demo_resize(struct demo *demo) { 2076b877906bSopenharmony_ci uint32_t i; 2077b877906bSopenharmony_ci 2078b877906bSopenharmony_ci // In order to properly resize the window, we must re-create the swapchain 2079b877906bSopenharmony_ci // AND redo the command buffers, etc. 2080b877906bSopenharmony_ci // 2081b877906bSopenharmony_ci // First, perform part of the demo_cleanup() function: 2082b877906bSopenharmony_ci 2083b877906bSopenharmony_ci for (i = 0; i < demo->swapchainImageCount; i++) { 2084b877906bSopenharmony_ci vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL); 2085b877906bSopenharmony_ci } 2086b877906bSopenharmony_ci free(demo->framebuffers); 2087b877906bSopenharmony_ci vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL); 2088b877906bSopenharmony_ci 2089b877906bSopenharmony_ci if (demo->setup_cmd) { 2090b877906bSopenharmony_ci vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->setup_cmd); 2091b877906bSopenharmony_ci demo->setup_cmd = VK_NULL_HANDLE; 2092b877906bSopenharmony_ci } 2093b877906bSopenharmony_ci vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->draw_cmd); 2094b877906bSopenharmony_ci vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL); 2095b877906bSopenharmony_ci 2096b877906bSopenharmony_ci vkDestroyPipeline(demo->device, demo->pipeline, NULL); 2097b877906bSopenharmony_ci vkDestroyRenderPass(demo->device, demo->render_pass, NULL); 2098b877906bSopenharmony_ci vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL); 2099b877906bSopenharmony_ci vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL); 2100b877906bSopenharmony_ci 2101b877906bSopenharmony_ci vkDestroyBuffer(demo->device, demo->vertices.buf, NULL); 2102b877906bSopenharmony_ci vkFreeMemory(demo->device, demo->vertices.mem, NULL); 2103b877906bSopenharmony_ci 2104b877906bSopenharmony_ci for (i = 0; i < DEMO_TEXTURE_COUNT; i++) { 2105b877906bSopenharmony_ci vkDestroyImageView(demo->device, demo->textures[i].view, NULL); 2106b877906bSopenharmony_ci vkDestroyImage(demo->device, demo->textures[i].image, NULL); 2107b877906bSopenharmony_ci vkFreeMemory(demo->device, demo->textures[i].mem, NULL); 2108b877906bSopenharmony_ci vkDestroySampler(demo->device, demo->textures[i].sampler, NULL); 2109b877906bSopenharmony_ci } 2110b877906bSopenharmony_ci 2111b877906bSopenharmony_ci for (i = 0; i < demo->swapchainImageCount; i++) { 2112b877906bSopenharmony_ci vkDestroyImageView(demo->device, demo->buffers[i].view, NULL); 2113b877906bSopenharmony_ci } 2114b877906bSopenharmony_ci 2115b877906bSopenharmony_ci vkDestroyImageView(demo->device, demo->depth.view, NULL); 2116b877906bSopenharmony_ci vkDestroyImage(demo->device, demo->depth.image, NULL); 2117b877906bSopenharmony_ci vkFreeMemory(demo->device, demo->depth.mem, NULL); 2118b877906bSopenharmony_ci 2119b877906bSopenharmony_ci free(demo->buffers); 2120b877906bSopenharmony_ci 2121b877906bSopenharmony_ci // Second, re-perform the demo_prepare() function, which will re-create the 2122b877906bSopenharmony_ci // swapchain: 2123b877906bSopenharmony_ci demo_prepare(demo); 2124b877906bSopenharmony_ci} 2125b877906bSopenharmony_ci 2126b877906bSopenharmony_ciint main(const int argc, const char *argv[]) { 2127b877906bSopenharmony_ci struct demo demo; 2128b877906bSopenharmony_ci 2129b877906bSopenharmony_ci demo_init(&demo, argc, argv); 2130b877906bSopenharmony_ci demo_create_window(&demo); 2131b877906bSopenharmony_ci demo_init_vk_swapchain(&demo); 2132b877906bSopenharmony_ci 2133b877906bSopenharmony_ci demo_prepare(&demo); 2134b877906bSopenharmony_ci demo_run(&demo); 2135b877906bSopenharmony_ci 2136b877906bSopenharmony_ci demo_cleanup(&demo); 2137b877906bSopenharmony_ci 2138b877906bSopenharmony_ci return validation_error; 2139b877906bSopenharmony_ci} 2140b877906bSopenharmony_ci 2141