overlay.cpp revision 8a1362ad
18a1362adSmaya/* 28a1362adSmaya * Copyright © 2019 Intel Corporation 38a1362adSmaya * 48a1362adSmaya * Permission is hereby granted, free of charge, to any person obtaining a 58a1362adSmaya * copy of this software and associated documentation files (the "Software"), 68a1362adSmaya * to deal in the Software without restriction, including without limitation 78a1362adSmaya * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88a1362adSmaya * and/or sell copies of the Software, and to permit persons to whom the 98a1362adSmaya * Software is furnished to do so, subject to the following conditions: 108a1362adSmaya * 118a1362adSmaya * The above copyright notice and this permission notice (including the next 128a1362adSmaya * paragraph) shall be included in all copies or substantial portions of the 138a1362adSmaya * Software. 148a1362adSmaya * 158a1362adSmaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168a1362adSmaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178a1362adSmaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188a1362adSmaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198a1362adSmaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 208a1362adSmaya * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 218a1362adSmaya * IN THE SOFTWARE. 228a1362adSmaya */ 238a1362adSmaya 248a1362adSmaya#include <string.h> 258a1362adSmaya#include <stdlib.h> 268a1362adSmaya#include <assert.h> 278a1362adSmaya 288a1362adSmaya#include <vulkan/vulkan.h> 298a1362adSmaya#include <vulkan/vk_layer.h> 308a1362adSmaya 318a1362adSmaya#include "imgui.h" 328a1362adSmaya 338a1362adSmaya#include "overlay_params.h" 348a1362adSmaya 358a1362adSmaya#include "util/debug.h" 368a1362adSmaya#include "util/hash_table.h" 378a1362adSmaya#include "util/list.h" 388a1362adSmaya#include "util/ralloc.h" 398a1362adSmaya#include "util/os_time.h" 408a1362adSmaya#include "util/simple_mtx.h" 418a1362adSmaya 428a1362adSmaya#include "vk_enum_to_str.h" 438a1362adSmaya#include "vk_util.h" 448a1362adSmaya 458a1362adSmaya/* Mapped from VkInstace/VkPhysicalDevice */ 468a1362adSmayastruct instance_data { 478a1362adSmaya struct vk_instance_dispatch_table vtable; 488a1362adSmaya VkInstance instance; 498a1362adSmaya 508a1362adSmaya struct overlay_params params; 518a1362adSmaya bool pipeline_statistics_enabled; 528a1362adSmaya 538a1362adSmaya bool first_line_printed; 548a1362adSmaya}; 558a1362adSmaya 568a1362adSmayastruct frame_stat { 578a1362adSmaya uint64_t stats[OVERLAY_PARAM_ENABLED_MAX]; 588a1362adSmaya}; 598a1362adSmaya 608a1362adSmaya/* Mapped from VkDevice */ 618a1362adSmayastruct queue_data; 628a1362adSmayastruct device_data { 638a1362adSmaya struct instance_data *instance; 648a1362adSmaya 658a1362adSmaya PFN_vkSetDeviceLoaderData set_device_loader_data; 668a1362adSmaya 678a1362adSmaya struct vk_device_dispatch_table vtable; 688a1362adSmaya VkPhysicalDevice physical_device; 698a1362adSmaya VkDevice device; 708a1362adSmaya 718a1362adSmaya VkPhysicalDeviceProperties properties; 728a1362adSmaya 738a1362adSmaya struct queue_data *graphic_queue; 748a1362adSmaya 758a1362adSmaya struct queue_data **queues; 768a1362adSmaya uint32_t n_queues; 778a1362adSmaya 788a1362adSmaya /* For a single frame */ 798a1362adSmaya struct frame_stat frame_stats; 808a1362adSmaya}; 818a1362adSmaya 828a1362adSmaya/* Mapped from VkCommandBuffer */ 838a1362adSmayastruct command_buffer_data { 848a1362adSmaya struct device_data *device; 858a1362adSmaya 868a1362adSmaya VkCommandBufferLevel level; 878a1362adSmaya 888a1362adSmaya VkCommandBuffer cmd_buffer; 898a1362adSmaya VkQueryPool pipeline_query_pool; 908a1362adSmaya VkQueryPool timestamp_query_pool; 918a1362adSmaya uint32_t query_index; 928a1362adSmaya 938a1362adSmaya struct frame_stat stats; 948a1362adSmaya 958a1362adSmaya struct list_head link; /* link into queue_data::running_command_buffer */ 968a1362adSmaya}; 978a1362adSmaya 988a1362adSmaya/* Mapped from VkQueue */ 998a1362adSmayastruct queue_data { 1008a1362adSmaya struct device_data *device; 1018a1362adSmaya 1028a1362adSmaya VkQueue queue; 1038a1362adSmaya VkQueueFlags flags; 1048a1362adSmaya uint32_t family_index; 1058a1362adSmaya uint64_t timestamp_mask; 1068a1362adSmaya 1078a1362adSmaya VkFence queries_fence; 1088a1362adSmaya 1098a1362adSmaya struct list_head running_command_buffer; 1108a1362adSmaya}; 1118a1362adSmaya 1128a1362adSmayastruct overlay_draw { 1138a1362adSmaya struct list_head link; 1148a1362adSmaya 1158a1362adSmaya VkCommandBuffer command_buffer; 1168a1362adSmaya 1178a1362adSmaya VkSemaphore semaphore; 1188a1362adSmaya VkFence fence; 1198a1362adSmaya 1208a1362adSmaya VkBuffer vertex_buffer; 1218a1362adSmaya VkDeviceMemory vertex_buffer_mem; 1228a1362adSmaya VkDeviceSize vertex_buffer_size; 1238a1362adSmaya 1248a1362adSmaya VkBuffer index_buffer; 1258a1362adSmaya VkDeviceMemory index_buffer_mem; 1268a1362adSmaya VkDeviceSize index_buffer_size; 1278a1362adSmaya}; 1288a1362adSmaya 1298a1362adSmaya/* Mapped from VkSwapchainKHR */ 1308a1362adSmayastruct swapchain_data { 1318a1362adSmaya struct device_data *device; 1328a1362adSmaya 1338a1362adSmaya VkSwapchainKHR swapchain; 1348a1362adSmaya unsigned width, height; 1358a1362adSmaya VkFormat format; 1368a1362adSmaya 1378a1362adSmaya uint32_t n_images; 1388a1362adSmaya VkImage *images; 1398a1362adSmaya VkImageView *image_views; 1408a1362adSmaya VkFramebuffer *framebuffers; 1418a1362adSmaya 1428a1362adSmaya VkRenderPass render_pass; 1438a1362adSmaya 1448a1362adSmaya VkDescriptorPool descriptor_pool; 1458a1362adSmaya VkDescriptorSetLayout descriptor_layout; 1468a1362adSmaya VkDescriptorSet descriptor_set; 1478a1362adSmaya 1488a1362adSmaya VkSampler font_sampler; 1498a1362adSmaya 1508a1362adSmaya VkPipelineLayout pipeline_layout; 1518a1362adSmaya VkPipeline pipeline; 1528a1362adSmaya 1538a1362adSmaya VkCommandPool command_pool; 1548a1362adSmaya 1558a1362adSmaya struct list_head draws; /* List of struct overlay_draw */ 1568a1362adSmaya 1578a1362adSmaya bool font_uploaded; 1588a1362adSmaya VkImage font_image; 1598a1362adSmaya VkImageView font_image_view; 1608a1362adSmaya VkDeviceMemory font_mem; 1618a1362adSmaya VkBuffer upload_font_buffer; 1628a1362adSmaya VkDeviceMemory upload_font_buffer_mem; 1638a1362adSmaya 1648a1362adSmaya /**/ 1658a1362adSmaya ImGuiContext* imgui_context; 1668a1362adSmaya ImVec2 window_size; 1678a1362adSmaya 1688a1362adSmaya /**/ 1698a1362adSmaya uint64_t n_frames; 1708a1362adSmaya uint64_t last_present_time; 1718a1362adSmaya 1728a1362adSmaya unsigned n_frames_since_update; 1738a1362adSmaya uint64_t last_fps_update; 1748a1362adSmaya double fps; 1758a1362adSmaya 1768a1362adSmaya enum overlay_param_enabled stat_selector; 1778a1362adSmaya double time_dividor; 1788a1362adSmaya struct frame_stat stats_min, stats_max; 1798a1362adSmaya struct frame_stat frames_stats[200]; 1808a1362adSmaya 1818a1362adSmaya /* Over a single frame */ 1828a1362adSmaya struct frame_stat frame_stats; 1838a1362adSmaya 1848a1362adSmaya /* Over fps_sampling_period */ 1858a1362adSmaya struct frame_stat accumulated_stats; 1868a1362adSmaya}; 1878a1362adSmaya 1888a1362adSmayastatic const VkQueryPipelineStatisticFlags overlay_query_flags = 1898a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT | 1908a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT | 1918a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | 1928a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT | 1938a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT | 1948a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT | 1958a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT | 1968a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT | 1978a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT | 1988a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT | 1998a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT; 2008a1362adSmaya#define OVERLAY_QUERY_COUNT (11) 2018a1362adSmaya 2028a1362adSmayastatic struct hash_table_u64 *vk_object_to_data = NULL; 2038a1362adSmayastatic simple_mtx_t vk_object_to_data_mutex = _SIMPLE_MTX_INITIALIZER_NP; 2048a1362adSmaya 2058a1362adSmayathread_local ImGuiContext* __MesaImGui; 2068a1362adSmaya 2078a1362adSmayastatic inline void ensure_vk_object_map(void) 2088a1362adSmaya{ 2098a1362adSmaya if (!vk_object_to_data) 2108a1362adSmaya vk_object_to_data = _mesa_hash_table_u64_create(NULL); 2118a1362adSmaya} 2128a1362adSmaya 2138a1362adSmaya#define HKEY(obj) ((uint64_t)(obj)) 2148a1362adSmaya#define FIND_SWAPCHAIN_DATA(obj) ((struct swapchain_data *)find_object_data(HKEY(obj))) 2158a1362adSmaya#define FIND_CMD_BUFFER_DATA(obj) ((struct command_buffer_data *)find_object_data(HKEY(obj))) 2168a1362adSmaya#define FIND_DEVICE_DATA(obj) ((struct device_data *)find_object_data(HKEY(obj))) 2178a1362adSmaya#define FIND_QUEUE_DATA(obj) ((struct queue_data *)find_object_data(HKEY(obj))) 2188a1362adSmaya#define FIND_PHYSICAL_DEVICE_DATA(obj) ((struct instance_data *)find_object_data(HKEY(obj))) 2198a1362adSmaya#define FIND_INSTANCE_DATA(obj) ((struct instance_data *)find_object_data(HKEY(obj))) 2208a1362adSmayastatic void *find_object_data(uint64_t obj) 2218a1362adSmaya{ 2228a1362adSmaya simple_mtx_lock(&vk_object_to_data_mutex); 2238a1362adSmaya ensure_vk_object_map(); 2248a1362adSmaya void *data = _mesa_hash_table_u64_search(vk_object_to_data, obj); 2258a1362adSmaya simple_mtx_unlock(&vk_object_to_data_mutex); 2268a1362adSmaya return data; 2278a1362adSmaya} 2288a1362adSmaya 2298a1362adSmayastatic void map_object(uint64_t obj, void *data) 2308a1362adSmaya{ 2318a1362adSmaya simple_mtx_lock(&vk_object_to_data_mutex); 2328a1362adSmaya ensure_vk_object_map(); 2338a1362adSmaya _mesa_hash_table_u64_insert(vk_object_to_data, obj, data); 2348a1362adSmaya simple_mtx_unlock(&vk_object_to_data_mutex); 2358a1362adSmaya} 2368a1362adSmaya 2378a1362adSmayastatic void unmap_object(uint64_t obj) 2388a1362adSmaya{ 2398a1362adSmaya simple_mtx_lock(&vk_object_to_data_mutex); 2408a1362adSmaya _mesa_hash_table_u64_remove(vk_object_to_data, obj); 2418a1362adSmaya simple_mtx_unlock(&vk_object_to_data_mutex); 2428a1362adSmaya} 2438a1362adSmaya 2448a1362adSmaya/**/ 2458a1362adSmaya 2468a1362adSmaya#define VK_CHECK(expr) \ 2478a1362adSmaya do { \ 2488a1362adSmaya VkResult __result = (expr); \ 2498a1362adSmaya if (__result != VK_SUCCESS) { \ 2508a1362adSmaya fprintf(stderr, "'%s' line %i failed with %s\n", \ 2518a1362adSmaya #expr, __LINE__, vk_Result_to_str(__result)); \ 2528a1362adSmaya } \ 2538a1362adSmaya } while (0) 2548a1362adSmaya 2558a1362adSmaya/**/ 2568a1362adSmaya 2578a1362adSmayastatic VkLayerInstanceCreateInfo *get_instance_chain_info(const VkInstanceCreateInfo *pCreateInfo, 2588a1362adSmaya VkLayerFunction func) 2598a1362adSmaya{ 2608a1362adSmaya vk_foreach_struct(item, pCreateInfo->pNext) { 2618a1362adSmaya if (item->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && 2628a1362adSmaya ((VkLayerInstanceCreateInfo *) item)->function == func) 2638a1362adSmaya return (VkLayerInstanceCreateInfo *) item; 2648a1362adSmaya } 2658a1362adSmaya unreachable("instance chain info not found"); 2668a1362adSmaya return NULL; 2678a1362adSmaya} 2688a1362adSmaya 2698a1362adSmayastatic VkLayerDeviceCreateInfo *get_device_chain_info(const VkDeviceCreateInfo *pCreateInfo, 2708a1362adSmaya VkLayerFunction func) 2718a1362adSmaya{ 2728a1362adSmaya vk_foreach_struct(item, pCreateInfo->pNext) { 2738a1362adSmaya if (item->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && 2748a1362adSmaya ((VkLayerDeviceCreateInfo *) item)->function == func) 2758a1362adSmaya return (VkLayerDeviceCreateInfo *)item; 2768a1362adSmaya } 2778a1362adSmaya unreachable("device chain info not found"); 2788a1362adSmaya return NULL; 2798a1362adSmaya} 2808a1362adSmaya 2818a1362adSmayastatic struct VkBaseOutStructure * 2828a1362adSmayaclone_chain(const struct VkBaseInStructure *chain) 2838a1362adSmaya{ 2848a1362adSmaya struct VkBaseOutStructure *head = NULL, *tail = NULL; 2858a1362adSmaya 2868a1362adSmaya vk_foreach_struct_const(item, chain) { 2878a1362adSmaya size_t item_size = vk_structure_type_size(item); 2888a1362adSmaya struct VkBaseOutStructure *new_item = 2898a1362adSmaya (struct VkBaseOutStructure *)malloc(item_size);; 2908a1362adSmaya 2918a1362adSmaya memcpy(new_item, item, item_size); 2928a1362adSmaya 2938a1362adSmaya if (!head) 2948a1362adSmaya head = new_item; 2958a1362adSmaya if (tail) 2968a1362adSmaya tail->pNext = new_item; 2978a1362adSmaya tail = new_item; 2988a1362adSmaya } 2998a1362adSmaya 3008a1362adSmaya return head; 3018a1362adSmaya} 3028a1362adSmaya 3038a1362adSmayastatic void 3048a1362adSmayafree_chain(struct VkBaseOutStructure *chain) 3058a1362adSmaya{ 3068a1362adSmaya while (chain) { 3078a1362adSmaya void *node = chain; 3088a1362adSmaya chain = chain->pNext; 3098a1362adSmaya free(node); 3108a1362adSmaya } 3118a1362adSmaya} 3128a1362adSmaya 3138a1362adSmaya/**/ 3148a1362adSmaya 3158a1362adSmayastatic void check_vk_result(VkResult err) 3168a1362adSmaya{ 3178a1362adSmaya if (err != VK_SUCCESS) 3188a1362adSmaya printf("ERROR!\n"); 3198a1362adSmaya} 3208a1362adSmaya 3218a1362adSmayastatic struct instance_data *new_instance_data(VkInstance instance) 3228a1362adSmaya{ 3238a1362adSmaya struct instance_data *data = rzalloc(NULL, struct instance_data); 3248a1362adSmaya data->instance = instance; 3258a1362adSmaya map_object(HKEY(data->instance), data); 3268a1362adSmaya return data; 3278a1362adSmaya} 3288a1362adSmaya 3298a1362adSmayastatic void destroy_instance_data(struct instance_data *data) 3308a1362adSmaya{ 3318a1362adSmaya if (data->params.output_file) 3328a1362adSmaya fclose(data->params.output_file); 3338a1362adSmaya unmap_object(HKEY(data->instance)); 3348a1362adSmaya ralloc_free(data); 3358a1362adSmaya} 3368a1362adSmaya 3378a1362adSmayastatic void instance_data_map_physical_devices(struct instance_data *instance_data, 3388a1362adSmaya bool map) 3398a1362adSmaya{ 3408a1362adSmaya uint32_t physicalDeviceCount = 0; 3418a1362adSmaya instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, 3428a1362adSmaya &physicalDeviceCount, 3438a1362adSmaya NULL); 3448a1362adSmaya 3458a1362adSmaya VkPhysicalDevice *physicalDevices = (VkPhysicalDevice *) malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); 3468a1362adSmaya instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, 3478a1362adSmaya &physicalDeviceCount, 3488a1362adSmaya physicalDevices); 3498a1362adSmaya 3508a1362adSmaya for (uint32_t i = 0; i < physicalDeviceCount; i++) { 3518a1362adSmaya if (map) 3528a1362adSmaya map_object(HKEY(physicalDevices[i]), instance_data); 3538a1362adSmaya else 3548a1362adSmaya unmap_object(HKEY(physicalDevices[i])); 3558a1362adSmaya } 3568a1362adSmaya 3578a1362adSmaya free(physicalDevices); 3588a1362adSmaya} 3598a1362adSmaya 3608a1362adSmaya/**/ 3618a1362adSmayastatic struct device_data *new_device_data(VkDevice device, struct instance_data *instance) 3628a1362adSmaya{ 3638a1362adSmaya struct device_data *data = rzalloc(NULL, struct device_data); 3648a1362adSmaya data->instance = instance; 3658a1362adSmaya data->device = device; 3668a1362adSmaya map_object(HKEY(data->device), data); 3678a1362adSmaya return data; 3688a1362adSmaya} 3698a1362adSmaya 3708a1362adSmayastatic struct queue_data *new_queue_data(VkQueue queue, 3718a1362adSmaya const VkQueueFamilyProperties *family_props, 3728a1362adSmaya uint32_t family_index, 3738a1362adSmaya struct device_data *device_data) 3748a1362adSmaya{ 3758a1362adSmaya struct queue_data *data = rzalloc(device_data, struct queue_data); 3768a1362adSmaya data->device = device_data; 3778a1362adSmaya data->queue = queue; 3788a1362adSmaya data->flags = family_props->queueFlags; 3798a1362adSmaya data->timestamp_mask = (1ull << family_props->timestampValidBits) - 1; 3808a1362adSmaya data->family_index = family_index; 3818a1362adSmaya LIST_INITHEAD(&data->running_command_buffer); 3828a1362adSmaya map_object(HKEY(data->queue), data); 3838a1362adSmaya 3848a1362adSmaya /* Fence synchronizing access to queries on that queue. */ 3858a1362adSmaya VkFenceCreateInfo fence_info = {}; 3868a1362adSmaya fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 3878a1362adSmaya fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; 3888a1362adSmaya VkResult err = device_data->vtable.CreateFence(device_data->device, 3898a1362adSmaya &fence_info, 3908a1362adSmaya NULL, 3918a1362adSmaya &data->queries_fence); 3928a1362adSmaya check_vk_result(err); 3938a1362adSmaya 3948a1362adSmaya if (data->flags & VK_QUEUE_GRAPHICS_BIT) 3958a1362adSmaya device_data->graphic_queue = data; 3968a1362adSmaya 3978a1362adSmaya return data; 3988a1362adSmaya} 3998a1362adSmaya 4008a1362adSmayastatic void destroy_queue(struct queue_data *data) 4018a1362adSmaya{ 4028a1362adSmaya struct device_data *device_data = data->device; 4038a1362adSmaya device_data->vtable.DestroyFence(device_data->device, data->queries_fence, NULL); 4048a1362adSmaya unmap_object(HKEY(data->queue)); 4058a1362adSmaya ralloc_free(data); 4068a1362adSmaya} 4078a1362adSmaya 4088a1362adSmayastatic void device_map_queues(struct device_data *data, 4098a1362adSmaya const VkDeviceCreateInfo *pCreateInfo) 4108a1362adSmaya{ 4118a1362adSmaya for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) 4128a1362adSmaya data->n_queues += pCreateInfo->pQueueCreateInfos[i].queueCount; 4138a1362adSmaya data->queues = ralloc_array(data, struct queue_data *, data->n_queues); 4148a1362adSmaya 4158a1362adSmaya struct instance_data *instance_data = data->instance; 4168a1362adSmaya uint32_t n_family_props; 4178a1362adSmaya instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, 4188a1362adSmaya &n_family_props, 4198a1362adSmaya NULL); 4208a1362adSmaya VkQueueFamilyProperties *family_props = 4218a1362adSmaya (VkQueueFamilyProperties *)malloc(sizeof(VkQueueFamilyProperties) * n_family_props); 4228a1362adSmaya instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, 4238a1362adSmaya &n_family_props, 4248a1362adSmaya family_props); 4258a1362adSmaya 4268a1362adSmaya uint32_t queue_index = 0; 4278a1362adSmaya for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { 4288a1362adSmaya for (uint32_t j = 0; j < pCreateInfo->pQueueCreateInfos[i].queueCount; j++) { 4298a1362adSmaya VkQueue queue; 4308a1362adSmaya data->vtable.GetDeviceQueue(data->device, 4318a1362adSmaya pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, 4328a1362adSmaya j, &queue); 4338a1362adSmaya 4348a1362adSmaya VK_CHECK(data->set_device_loader_data(data->device, queue)); 4358a1362adSmaya 4368a1362adSmaya data->queues[queue_index++] = 4378a1362adSmaya new_queue_data(queue, &family_props[pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex], 4388a1362adSmaya pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, data); 4398a1362adSmaya } 4408a1362adSmaya } 4418a1362adSmaya 4428a1362adSmaya free(family_props); 4438a1362adSmaya} 4448a1362adSmaya 4458a1362adSmayastatic void device_unmap_queues(struct device_data *data) 4468a1362adSmaya{ 4478a1362adSmaya for (uint32_t i = 0; i < data->n_queues; i++) 4488a1362adSmaya destroy_queue(data->queues[i]); 4498a1362adSmaya} 4508a1362adSmaya 4518a1362adSmayastatic void destroy_device_data(struct device_data *data) 4528a1362adSmaya{ 4538a1362adSmaya unmap_object(HKEY(data->device)); 4548a1362adSmaya ralloc_free(data); 4558a1362adSmaya} 4568a1362adSmaya 4578a1362adSmaya/**/ 4588a1362adSmayastatic struct command_buffer_data *new_command_buffer_data(VkCommandBuffer cmd_buffer, 4598a1362adSmaya VkCommandBufferLevel level, 4608a1362adSmaya VkQueryPool pipeline_query_pool, 4618a1362adSmaya VkQueryPool timestamp_query_pool, 4628a1362adSmaya uint32_t query_index, 4638a1362adSmaya struct device_data *device_data) 4648a1362adSmaya{ 4658a1362adSmaya struct command_buffer_data *data = rzalloc(NULL, struct command_buffer_data); 4668a1362adSmaya data->device = device_data; 4678a1362adSmaya data->cmd_buffer = cmd_buffer; 4688a1362adSmaya data->level = level; 4698a1362adSmaya data->pipeline_query_pool = pipeline_query_pool; 4708a1362adSmaya data->timestamp_query_pool = timestamp_query_pool; 4718a1362adSmaya data->query_index = query_index; 4728a1362adSmaya list_inithead(&data->link); 4738a1362adSmaya map_object(HKEY(data->cmd_buffer), data); 4748a1362adSmaya return data; 4758a1362adSmaya} 4768a1362adSmaya 4778a1362adSmayastatic void destroy_command_buffer_data(struct command_buffer_data *data) 4788a1362adSmaya{ 4798a1362adSmaya unmap_object(HKEY(data->cmd_buffer)); 4808a1362adSmaya list_delinit(&data->link); 4818a1362adSmaya ralloc_free(data); 4828a1362adSmaya} 4838a1362adSmaya 4848a1362adSmaya/**/ 4858a1362adSmayastatic struct swapchain_data *new_swapchain_data(VkSwapchainKHR swapchain, 4868a1362adSmaya struct device_data *device_data) 4878a1362adSmaya{ 4888a1362adSmaya struct instance_data *instance_data = device_data->instance; 4898a1362adSmaya struct swapchain_data *data = rzalloc(NULL, struct swapchain_data); 4908a1362adSmaya data->device = device_data; 4918a1362adSmaya data->swapchain = swapchain; 4928a1362adSmaya data->window_size = ImVec2(instance_data->params.width, instance_data->params.height); 4938a1362adSmaya list_inithead(&data->draws); 4948a1362adSmaya map_object(HKEY(data->swapchain), data); 4958a1362adSmaya return data; 4968a1362adSmaya} 4978a1362adSmaya 4988a1362adSmayastatic void destroy_swapchain_data(struct swapchain_data *data) 4998a1362adSmaya{ 5008a1362adSmaya unmap_object(HKEY(data->swapchain)); 5018a1362adSmaya ralloc_free(data); 5028a1362adSmaya} 5038a1362adSmaya 5048a1362adSmayastruct overlay_draw *get_overlay_draw(struct swapchain_data *data) 5058a1362adSmaya{ 5068a1362adSmaya struct device_data *device_data = data->device; 5078a1362adSmaya struct overlay_draw *draw = list_empty(&data->draws) ? 5088a1362adSmaya NULL : list_first_entry(&data->draws, struct overlay_draw, link); 5098a1362adSmaya 5108a1362adSmaya VkSemaphoreCreateInfo sem_info = {}; 5118a1362adSmaya sem_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 5128a1362adSmaya 5138a1362adSmaya if (draw && device_data->vtable.GetFenceStatus(device_data->device, draw->fence) == VK_SUCCESS) { 5148a1362adSmaya list_del(&draw->link); 5158a1362adSmaya VK_CHECK(device_data->vtable.ResetFences(device_data->device, 5168a1362adSmaya 1, &draw->fence)); 5178a1362adSmaya list_addtail(&draw->link, &data->draws); 5188a1362adSmaya return draw; 5198a1362adSmaya } 5208a1362adSmaya 5218a1362adSmaya draw = rzalloc(data, struct overlay_draw); 5228a1362adSmaya 5238a1362adSmaya VkCommandBufferAllocateInfo cmd_buffer_info = {}; 5248a1362adSmaya cmd_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 5258a1362adSmaya cmd_buffer_info.commandPool = data->command_pool; 5268a1362adSmaya cmd_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 5278a1362adSmaya cmd_buffer_info.commandBufferCount = 1; 5288a1362adSmaya VK_CHECK(device_data->vtable.AllocateCommandBuffers(device_data->device, 5298a1362adSmaya &cmd_buffer_info, 5308a1362adSmaya &draw->command_buffer)); 5318a1362adSmaya VK_CHECK(device_data->set_device_loader_data(device_data->device, 5328a1362adSmaya draw->command_buffer)); 5338a1362adSmaya 5348a1362adSmaya 5358a1362adSmaya VkFenceCreateInfo fence_info = {}; 5368a1362adSmaya fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 5378a1362adSmaya VK_CHECK(device_data->vtable.CreateFence(device_data->device, 5388a1362adSmaya &fence_info, 5398a1362adSmaya NULL, 5408a1362adSmaya &draw->fence)); 5418a1362adSmaya 5428a1362adSmaya VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, 5438a1362adSmaya NULL, &draw->semaphore)); 5448a1362adSmaya 5458a1362adSmaya list_addtail(&draw->link, &data->draws); 5468a1362adSmaya 5478a1362adSmaya return draw; 5488a1362adSmaya} 5498a1362adSmaya 5508a1362adSmayastatic const char *param_unit(enum overlay_param_enabled param) 5518a1362adSmaya{ 5528a1362adSmaya switch (param) { 5538a1362adSmaya case OVERLAY_PARAM_ENABLED_frame_timing: 5548a1362adSmaya case OVERLAY_PARAM_ENABLED_acquire_timing: 5558a1362adSmaya return "(us)"; 5568a1362adSmaya case OVERLAY_PARAM_ENABLED_gpu_timing: 5578a1362adSmaya return "(ns)"; 5588a1362adSmaya default: 5598a1362adSmaya return ""; 5608a1362adSmaya } 5618a1362adSmaya} 5628a1362adSmaya 5638a1362adSmayastatic void snapshot_swapchain_frame(struct swapchain_data *data) 5648a1362adSmaya{ 5658a1362adSmaya struct device_data *device_data = data->device; 5668a1362adSmaya struct instance_data *instance_data = device_data->instance; 5678a1362adSmaya uint32_t f_idx = data->n_frames % ARRAY_SIZE(data->frames_stats); 5688a1362adSmaya uint64_t now = os_time_get(); /* us */ 5698a1362adSmaya 5708a1362adSmaya if (data->last_present_time) { 5718a1362adSmaya data->frame_stats.stats[OVERLAY_PARAM_ENABLED_frame_timing] = 5728a1362adSmaya now - data->last_present_time; 5738a1362adSmaya } 5748a1362adSmaya 5758a1362adSmaya memset(&data->frames_stats[f_idx], 0, sizeof(data->frames_stats[f_idx])); 5768a1362adSmaya for (int s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 5778a1362adSmaya data->frames_stats[f_idx].stats[s] += device_data->frame_stats.stats[s] + data->frame_stats.stats[s]; 5788a1362adSmaya data->accumulated_stats.stats[s] += device_data->frame_stats.stats[s] + data->frame_stats.stats[s]; 5798a1362adSmaya } 5808a1362adSmaya 5818a1362adSmaya if (data->last_fps_update) { 5828a1362adSmaya double elapsed = (double)(now - data->last_fps_update); /* us */ 5838a1362adSmaya if (elapsed >= instance_data->params.fps_sampling_period) { 5848a1362adSmaya data->fps = 1000000.0f * data->n_frames_since_update / elapsed; 5858a1362adSmaya if (instance_data->params.output_file) { 5868a1362adSmaya if (!instance_data->first_line_printed) { 5878a1362adSmaya bool first_column = true; 5888a1362adSmaya 5898a1362adSmaya instance_data->first_line_printed = true; 5908a1362adSmaya 5918a1362adSmaya#define OVERLAY_PARAM_BOOL(name) \ 5928a1362adSmaya if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_##name]) { \ 5938a1362adSmaya fprintf(instance_data->params.output_file, \ 5948a1362adSmaya "%s%s%s", first_column ? "" : ", ", #name, \ 5958a1362adSmaya param_unit(OVERLAY_PARAM_ENABLED_##name)); \ 5968a1362adSmaya first_column = false; \ 5978a1362adSmaya } 5988a1362adSmaya#define OVERLAY_PARAM_CUSTOM(name) 5998a1362adSmaya OVERLAY_PARAMS 6008a1362adSmaya#undef OVERLAY_PARAM_BOOL 6018a1362adSmaya#undef OVERLAY_PARAM_CUSTOM 6028a1362adSmaya fprintf(instance_data->params.output_file, "\n"); 6038a1362adSmaya } 6048a1362adSmaya 6058a1362adSmaya for (int s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 6068a1362adSmaya if (!instance_data->params.enabled[s]) 6078a1362adSmaya continue; 6088a1362adSmaya if (s == OVERLAY_PARAM_ENABLED_fps) { 6098a1362adSmaya fprintf(instance_data->params.output_file, 6108a1362adSmaya "%s%.2f", s == 0 ? "" : ", ", data->fps); 6118a1362adSmaya } else { 6128a1362adSmaya fprintf(instance_data->params.output_file, 6138a1362adSmaya "%s%" PRIu64, s == 0 ? "" : ", ", 6148a1362adSmaya data->accumulated_stats.stats[s]); 6158a1362adSmaya } 6168a1362adSmaya } 6178a1362adSmaya fprintf(instance_data->params.output_file, "\n"); 6188a1362adSmaya fflush(instance_data->params.output_file); 6198a1362adSmaya } 6208a1362adSmaya 6218a1362adSmaya memset(&data->accumulated_stats, 0, sizeof(data->accumulated_stats)); 6228a1362adSmaya data->n_frames_since_update = 0; 6238a1362adSmaya data->last_fps_update = now; 6248a1362adSmaya } 6258a1362adSmaya } else { 6268a1362adSmaya data->last_fps_update = now; 6278a1362adSmaya } 6288a1362adSmaya 6298a1362adSmaya memset(&device_data->frame_stats, 0, sizeof(device_data->frame_stats)); 6308a1362adSmaya memset(&data->frame_stats, 0, sizeof(device_data->frame_stats)); 6318a1362adSmaya 6328a1362adSmaya data->last_present_time = now; 6338a1362adSmaya data->n_frames++; 6348a1362adSmaya data->n_frames_since_update++; 6358a1362adSmaya} 6368a1362adSmaya 6378a1362adSmayastatic float get_time_stat(void *_data, int _idx) 6388a1362adSmaya{ 6398a1362adSmaya struct swapchain_data *data = (struct swapchain_data *) _data; 6408a1362adSmaya if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) 6418a1362adSmaya return 0.0f; 6428a1362adSmaya int idx = ARRAY_SIZE(data->frames_stats) + 6438a1362adSmaya data->n_frames < ARRAY_SIZE(data->frames_stats) ? 6448a1362adSmaya _idx - data->n_frames : 6458a1362adSmaya _idx + data->n_frames; 6468a1362adSmaya idx %= ARRAY_SIZE(data->frames_stats); 6478a1362adSmaya /* Time stats are in us. */ 6488a1362adSmaya return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; 6498a1362adSmaya} 6508a1362adSmaya 6518a1362adSmayastatic float get_stat(void *_data, int _idx) 6528a1362adSmaya{ 6538a1362adSmaya struct swapchain_data *data = (struct swapchain_data *) _data; 6548a1362adSmaya if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) 6558a1362adSmaya return 0.0f; 6568a1362adSmaya int idx = ARRAY_SIZE(data->frames_stats) + 6578a1362adSmaya data->n_frames < ARRAY_SIZE(data->frames_stats) ? 6588a1362adSmaya _idx - data->n_frames : 6598a1362adSmaya _idx + data->n_frames; 6608a1362adSmaya idx %= ARRAY_SIZE(data->frames_stats); 6618a1362adSmaya return data->frames_stats[idx].stats[data->stat_selector]; 6628a1362adSmaya} 6638a1362adSmaya 6648a1362adSmayastatic void position_layer(struct swapchain_data *data) 6658a1362adSmaya 6668a1362adSmaya{ 6678a1362adSmaya struct device_data *device_data = data->device; 6688a1362adSmaya struct instance_data *instance_data = device_data->instance; 6698a1362adSmaya const float margin = 10.0f; 6708a1362adSmaya 6718a1362adSmaya ImGui::SetNextWindowBgAlpha(0.5); 6728a1362adSmaya ImGui::SetNextWindowSize(data->window_size, ImGuiCond_Always); 6738a1362adSmaya switch (instance_data->params.position) { 6748a1362adSmaya case LAYER_POSITION_TOP_LEFT: 6758a1362adSmaya ImGui::SetNextWindowPos(ImVec2(margin, margin), ImGuiCond_Always); 6768a1362adSmaya break; 6778a1362adSmaya case LAYER_POSITION_TOP_RIGHT: 6788a1362adSmaya ImGui::SetNextWindowPos(ImVec2(data->width - data->window_size.x - margin, margin), 6798a1362adSmaya ImGuiCond_Always); 6808a1362adSmaya break; 6818a1362adSmaya case LAYER_POSITION_BOTTOM_LEFT: 6828a1362adSmaya ImGui::SetNextWindowPos(ImVec2(margin, data->height - data->window_size.y - margin), 6838a1362adSmaya ImGuiCond_Always); 6848a1362adSmaya break; 6858a1362adSmaya case LAYER_POSITION_BOTTOM_RIGHT: 6868a1362adSmaya ImGui::SetNextWindowPos(ImVec2(data->width - data->window_size.x - margin, 6878a1362adSmaya data->height - data->window_size.y - margin), 6888a1362adSmaya ImGuiCond_Always); 6898a1362adSmaya break; 6908a1362adSmaya } 6918a1362adSmaya} 6928a1362adSmaya 6938a1362adSmayastatic void compute_swapchain_display(struct swapchain_data *data) 6948a1362adSmaya{ 6958a1362adSmaya struct device_data *device_data = data->device; 6968a1362adSmaya struct instance_data *instance_data = device_data->instance; 6978a1362adSmaya 6988a1362adSmaya ImGui::SetCurrentContext(data->imgui_context); 6998a1362adSmaya ImGui::NewFrame(); 7008a1362adSmaya position_layer(data); 7018a1362adSmaya ImGui::Begin("Mesa overlay"); 7028a1362adSmaya ImGui::Text("Device: %s", device_data->properties.deviceName); 7038a1362adSmaya 7048a1362adSmaya const char *format_name = vk_Format_to_str(data->format); 7058a1362adSmaya format_name = format_name ? (format_name + strlen("VK_FORMAT_")) : "unknown"; 7068a1362adSmaya ImGui::Text("Swapchain format: %s", format_name); 7078a1362adSmaya ImGui::Text("Frames: %" PRIu64, data->n_frames); 7088a1362adSmaya if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_fps]) 7098a1362adSmaya ImGui::Text("FPS: %.2f" , data->fps); 7108a1362adSmaya 7118a1362adSmaya /* Recompute min/max */ 7128a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 7138a1362adSmaya data->stats_min.stats[s] = UINT64_MAX; 7148a1362adSmaya data->stats_max.stats[s] = 0; 7158a1362adSmaya } 7168a1362adSmaya for (uint32_t f = 0; f < MIN2(data->n_frames, ARRAY_SIZE(data->frames_stats)); f++) { 7178a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 7188a1362adSmaya data->stats_min.stats[s] = MIN2(data->frames_stats[f].stats[s], 7198a1362adSmaya data->stats_min.stats[s]); 7208a1362adSmaya data->stats_max.stats[s] = MAX2(data->frames_stats[f].stats[s], 7218a1362adSmaya data->stats_max.stats[s]); 7228a1362adSmaya } 7238a1362adSmaya } 7248a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 7258a1362adSmaya assert(data->stats_min.stats[s] != UINT64_MAX); 7268a1362adSmaya } 7278a1362adSmaya 7288a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 7298a1362adSmaya if (!instance_data->params.enabled[s] || 7308a1362adSmaya s == OVERLAY_PARAM_ENABLED_fps || 7318a1362adSmaya s == OVERLAY_PARAM_ENABLED_frame) 7328a1362adSmaya continue; 7338a1362adSmaya 7348a1362adSmaya char hash[40]; 7358a1362adSmaya snprintf(hash, sizeof(hash), "##%s", overlay_param_names[s]); 7368a1362adSmaya data->stat_selector = (enum overlay_param_enabled) s; 7378a1362adSmaya data->time_dividor = 1000.0f; 7388a1362adSmaya if (s == OVERLAY_PARAM_ENABLED_gpu_timing) 7398a1362adSmaya data->time_dividor = 1000000.0f; 7408a1362adSmaya 7418a1362adSmaya if (s == OVERLAY_PARAM_ENABLED_frame_timing || 7428a1362adSmaya s == OVERLAY_PARAM_ENABLED_acquire_timing || 7438a1362adSmaya s == OVERLAY_PARAM_ENABLED_gpu_timing) { 7448a1362adSmaya double min_time = data->stats_min.stats[s] / data->time_dividor; 7458a1362adSmaya double max_time = data->stats_max.stats[s] / data->time_dividor; 7468a1362adSmaya ImGui::PlotHistogram(hash, get_time_stat, data, 7478a1362adSmaya ARRAY_SIZE(data->frames_stats), 0, 7488a1362adSmaya NULL, min_time, max_time, 7498a1362adSmaya ImVec2(ImGui::GetContentRegionAvailWidth(), 30)); 7508a1362adSmaya ImGui::Text("%s: %.3fms [%.3f, %.3f]", overlay_param_names[s], 7518a1362adSmaya get_time_stat(data, ARRAY_SIZE(data->frames_stats) - 1), 7528a1362adSmaya min_time, max_time); 7538a1362adSmaya } else { 7548a1362adSmaya ImGui::PlotHistogram(hash, get_stat, data, 7558a1362adSmaya ARRAY_SIZE(data->frames_stats), 0, 7568a1362adSmaya NULL, 7578a1362adSmaya data->stats_min.stats[s], 7588a1362adSmaya data->stats_max.stats[s], 7598a1362adSmaya ImVec2(ImGui::GetContentRegionAvailWidth(), 30)); 7608a1362adSmaya ImGui::Text("%s: %.0f [%" PRIu64 ", %" PRIu64 "]", overlay_param_names[s], 7618a1362adSmaya get_stat(data, ARRAY_SIZE(data->frames_stats) - 1), 7628a1362adSmaya data->stats_min.stats[s], data->stats_max.stats[s]); 7638a1362adSmaya } 7648a1362adSmaya } 7658a1362adSmaya data->window_size = ImVec2(data->window_size.x, ImGui::GetCursorPosY() + 10.0f); 7668a1362adSmaya ImGui::End(); 7678a1362adSmaya ImGui::EndFrame(); 7688a1362adSmaya ImGui::Render(); 7698a1362adSmaya} 7708a1362adSmaya 7718a1362adSmayastatic uint32_t vk_memory_type(struct device_data *data, 7728a1362adSmaya VkMemoryPropertyFlags properties, 7738a1362adSmaya uint32_t type_bits) 7748a1362adSmaya{ 7758a1362adSmaya VkPhysicalDeviceMemoryProperties prop; 7768a1362adSmaya data->instance->vtable.GetPhysicalDeviceMemoryProperties(data->physical_device, &prop); 7778a1362adSmaya for (uint32_t i = 0; i < prop.memoryTypeCount; i++) 7788a1362adSmaya if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i)) 7798a1362adSmaya return i; 7808a1362adSmaya return 0xFFFFFFFF; // Unable to find memoryType 7818a1362adSmaya} 7828a1362adSmaya 7838a1362adSmayastatic void ensure_swapchain_fonts(struct swapchain_data *data, 7848a1362adSmaya VkCommandBuffer command_buffer) 7858a1362adSmaya{ 7868a1362adSmaya if (data->font_uploaded) 7878a1362adSmaya return; 7888a1362adSmaya 7898a1362adSmaya data->font_uploaded = true; 7908a1362adSmaya 7918a1362adSmaya struct device_data *device_data = data->device; 7928a1362adSmaya ImGuiIO& io = ImGui::GetIO(); 7938a1362adSmaya unsigned char* pixels; 7948a1362adSmaya int width, height; 7958a1362adSmaya io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 7968a1362adSmaya size_t upload_size = width * height * 4 * sizeof(char); 7978a1362adSmaya 7988a1362adSmaya /* Upload buffer */ 7998a1362adSmaya VkBufferCreateInfo buffer_info = {}; 8008a1362adSmaya buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 8018a1362adSmaya buffer_info.size = upload_size; 8028a1362adSmaya buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; 8038a1362adSmaya buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 8048a1362adSmaya VK_CHECK(device_data->vtable.CreateBuffer(device_data->device, &buffer_info, 8058a1362adSmaya NULL, &data->upload_font_buffer)); 8068a1362adSmaya VkMemoryRequirements upload_buffer_req; 8078a1362adSmaya device_data->vtable.GetBufferMemoryRequirements(device_data->device, 8088a1362adSmaya data->upload_font_buffer, 8098a1362adSmaya &upload_buffer_req); 8108a1362adSmaya VkMemoryAllocateInfo upload_alloc_info = {}; 8118a1362adSmaya upload_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 8128a1362adSmaya upload_alloc_info.allocationSize = upload_buffer_req.size; 8138a1362adSmaya upload_alloc_info.memoryTypeIndex = vk_memory_type(device_data, 8148a1362adSmaya VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 8158a1362adSmaya upload_buffer_req.memoryTypeBits); 8168a1362adSmaya VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, 8178a1362adSmaya &upload_alloc_info, 8188a1362adSmaya NULL, 8198a1362adSmaya &data->upload_font_buffer_mem)); 8208a1362adSmaya VK_CHECK(device_data->vtable.BindBufferMemory(device_data->device, 8218a1362adSmaya data->upload_font_buffer, 8228a1362adSmaya data->upload_font_buffer_mem, 0)); 8238a1362adSmaya 8248a1362adSmaya /* Upload to Buffer */ 8258a1362adSmaya char* map = NULL; 8268a1362adSmaya VK_CHECK(device_data->vtable.MapMemory(device_data->device, 8278a1362adSmaya data->upload_font_buffer_mem, 8288a1362adSmaya 0, upload_size, 0, (void**)(&map))); 8298a1362adSmaya memcpy(map, pixels, upload_size); 8308a1362adSmaya VkMappedMemoryRange range[1] = {}; 8318a1362adSmaya range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 8328a1362adSmaya range[0].memory = data->upload_font_buffer_mem; 8338a1362adSmaya range[0].size = upload_size; 8348a1362adSmaya VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 1, range)); 8358a1362adSmaya device_data->vtable.UnmapMemory(device_data->device, 8368a1362adSmaya data->upload_font_buffer_mem); 8378a1362adSmaya 8388a1362adSmaya /* Copy buffer to image */ 8398a1362adSmaya VkImageMemoryBarrier copy_barrier[1] = {}; 8408a1362adSmaya copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 8418a1362adSmaya copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 8428a1362adSmaya copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 8438a1362adSmaya copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 8448a1362adSmaya copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 8458a1362adSmaya copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 8468a1362adSmaya copy_barrier[0].image = data->font_image; 8478a1362adSmaya copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 8488a1362adSmaya copy_barrier[0].subresourceRange.levelCount = 1; 8498a1362adSmaya copy_barrier[0].subresourceRange.layerCount = 1; 8508a1362adSmaya device_data->vtable.CmdPipelineBarrier(command_buffer, 8518a1362adSmaya VK_PIPELINE_STAGE_HOST_BIT, 8528a1362adSmaya VK_PIPELINE_STAGE_TRANSFER_BIT, 8538a1362adSmaya 0, 0, NULL, 0, NULL, 8548a1362adSmaya 1, copy_barrier); 8558a1362adSmaya 8568a1362adSmaya VkBufferImageCopy region = {}; 8578a1362adSmaya region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 8588a1362adSmaya region.imageSubresource.layerCount = 1; 8598a1362adSmaya region.imageExtent.width = width; 8608a1362adSmaya region.imageExtent.height = height; 8618a1362adSmaya region.imageExtent.depth = 1; 8628a1362adSmaya device_data->vtable.CmdCopyBufferToImage(command_buffer, 8638a1362adSmaya data->upload_font_buffer, 8648a1362adSmaya data->font_image, 8658a1362adSmaya VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 8668a1362adSmaya 1, ®ion); 8678a1362adSmaya 8688a1362adSmaya VkImageMemoryBarrier use_barrier[1] = {}; 8698a1362adSmaya use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 8708a1362adSmaya use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 8718a1362adSmaya use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 8728a1362adSmaya use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 8738a1362adSmaya use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 8748a1362adSmaya use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 8758a1362adSmaya use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 8768a1362adSmaya use_barrier[0].image = data->font_image; 8778a1362adSmaya use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 8788a1362adSmaya use_barrier[0].subresourceRange.levelCount = 1; 8798a1362adSmaya use_barrier[0].subresourceRange.layerCount = 1; 8808a1362adSmaya device_data->vtable.CmdPipelineBarrier(command_buffer, 8818a1362adSmaya VK_PIPELINE_STAGE_TRANSFER_BIT, 8828a1362adSmaya VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 8838a1362adSmaya 0, 8848a1362adSmaya 0, NULL, 8858a1362adSmaya 0, NULL, 8868a1362adSmaya 1, use_barrier); 8878a1362adSmaya 8888a1362adSmaya /* Store our identifier */ 8898a1362adSmaya io.Fonts->TexID = (ImTextureID)(intptr_t)data->font_image; 8908a1362adSmaya} 8918a1362adSmaya 8928a1362adSmayastatic void CreateOrResizeBuffer(struct device_data *data, 8938a1362adSmaya VkBuffer *buffer, 8948a1362adSmaya VkDeviceMemory *buffer_memory, 8958a1362adSmaya VkDeviceSize *buffer_size, 8968a1362adSmaya size_t new_size, VkBufferUsageFlagBits usage) 8978a1362adSmaya{ 8988a1362adSmaya if (*buffer != VK_NULL_HANDLE) 8998a1362adSmaya data->vtable.DestroyBuffer(data->device, *buffer, NULL); 9008a1362adSmaya if (*buffer_memory) 9018a1362adSmaya data->vtable.FreeMemory(data->device, *buffer_memory, NULL); 9028a1362adSmaya 9038a1362adSmaya VkBufferCreateInfo buffer_info = {}; 9048a1362adSmaya buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 9058a1362adSmaya buffer_info.size = new_size; 9068a1362adSmaya buffer_info.usage = usage; 9078a1362adSmaya buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 9088a1362adSmaya VK_CHECK(data->vtable.CreateBuffer(data->device, &buffer_info, NULL, buffer)); 9098a1362adSmaya 9108a1362adSmaya VkMemoryRequirements req; 9118a1362adSmaya data->vtable.GetBufferMemoryRequirements(data->device, *buffer, &req); 9128a1362adSmaya VkMemoryAllocateInfo alloc_info = {}; 9138a1362adSmaya alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 9148a1362adSmaya alloc_info.allocationSize = req.size; 9158a1362adSmaya alloc_info.memoryTypeIndex = 9168a1362adSmaya vk_memory_type(data, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); 9178a1362adSmaya VK_CHECK(data->vtable.AllocateMemory(data->device, &alloc_info, NULL, buffer_memory)); 9188a1362adSmaya 9198a1362adSmaya VK_CHECK(data->vtable.BindBufferMemory(data->device, *buffer, *buffer_memory, 0)); 9208a1362adSmaya *buffer_size = new_size; 9218a1362adSmaya} 9228a1362adSmaya 9238a1362adSmayastatic struct overlay_draw *render_swapchain_display(struct swapchain_data *data, 9248a1362adSmaya struct queue_data *present_queue, 9258a1362adSmaya const VkSemaphore *wait_semaphores, 9268a1362adSmaya unsigned n_wait_semaphores, 9278a1362adSmaya unsigned image_index) 9288a1362adSmaya{ 9298a1362adSmaya ImDrawData* draw_data = ImGui::GetDrawData(); 9308a1362adSmaya if (draw_data->TotalVtxCount == 0) 9318a1362adSmaya return NULL; 9328a1362adSmaya 9338a1362adSmaya struct device_data *device_data = data->device; 9348a1362adSmaya struct overlay_draw *draw = get_overlay_draw(data); 9358a1362adSmaya 9368a1362adSmaya device_data->vtable.ResetCommandBuffer(draw->command_buffer, 0); 9378a1362adSmaya 9388a1362adSmaya VkRenderPassBeginInfo render_pass_info = {}; 9398a1362adSmaya render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 9408a1362adSmaya render_pass_info.renderPass = data->render_pass; 9418a1362adSmaya render_pass_info.framebuffer = data->framebuffers[image_index]; 9428a1362adSmaya render_pass_info.renderArea.extent.width = data->width; 9438a1362adSmaya render_pass_info.renderArea.extent.height = data->height; 9448a1362adSmaya 9458a1362adSmaya VkCommandBufferBeginInfo buffer_begin_info = {}; 9468a1362adSmaya buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 9478a1362adSmaya 9488a1362adSmaya device_data->vtable.BeginCommandBuffer(draw->command_buffer, &buffer_begin_info); 9498a1362adSmaya 9508a1362adSmaya ensure_swapchain_fonts(data, draw->command_buffer); 9518a1362adSmaya 9528a1362adSmaya /* Bounce the image to display back to color attachment layout for 9538a1362adSmaya * rendering on top of it. 9548a1362adSmaya */ 9558a1362adSmaya VkImageMemoryBarrier imb; 9568a1362adSmaya imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 9578a1362adSmaya imb.pNext = nullptr; 9588a1362adSmaya imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 9598a1362adSmaya imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 9608a1362adSmaya imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 9618a1362adSmaya imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 9628a1362adSmaya imb.image = data->images[image_index]; 9638a1362adSmaya imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 9648a1362adSmaya imb.subresourceRange.baseMipLevel = 0; 9658a1362adSmaya imb.subresourceRange.levelCount = 1; 9668a1362adSmaya imb.subresourceRange.baseArrayLayer = 0; 9678a1362adSmaya imb.subresourceRange.layerCount = 1; 9688a1362adSmaya imb.srcQueueFamilyIndex = present_queue->family_index; 9698a1362adSmaya imb.dstQueueFamilyIndex = device_data->graphic_queue->family_index; 9708a1362adSmaya device_data->vtable.CmdPipelineBarrier(draw->command_buffer, 9718a1362adSmaya VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 9728a1362adSmaya VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 9738a1362adSmaya 0, /* dependency flags */ 9748a1362adSmaya 0, nullptr, /* memory barriers */ 9758a1362adSmaya 0, nullptr, /* buffer memory barriers */ 9768a1362adSmaya 1, &imb); /* image memory barriers */ 9778a1362adSmaya 9788a1362adSmaya device_data->vtable.CmdBeginRenderPass(draw->command_buffer, &render_pass_info, 9798a1362adSmaya VK_SUBPASS_CONTENTS_INLINE); 9808a1362adSmaya 9818a1362adSmaya /* Create/Resize vertex & index buffers */ 9828a1362adSmaya size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); 9838a1362adSmaya size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); 9848a1362adSmaya if (draw->vertex_buffer_size < vertex_size) { 9858a1362adSmaya CreateOrResizeBuffer(device_data, 9868a1362adSmaya &draw->vertex_buffer, 9878a1362adSmaya &draw->vertex_buffer_mem, 9888a1362adSmaya &draw->vertex_buffer_size, 9898a1362adSmaya vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 9908a1362adSmaya } 9918a1362adSmaya if (draw->index_buffer_size < index_size) { 9928a1362adSmaya CreateOrResizeBuffer(device_data, 9938a1362adSmaya &draw->index_buffer, 9948a1362adSmaya &draw->index_buffer_mem, 9958a1362adSmaya &draw->index_buffer_size, 9968a1362adSmaya index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); 9978a1362adSmaya } 9988a1362adSmaya 9998a1362adSmaya /* Upload vertex & index data */ 10008a1362adSmaya ImDrawVert* vtx_dst = NULL; 10018a1362adSmaya ImDrawIdx* idx_dst = NULL; 10028a1362adSmaya VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->vertex_buffer_mem, 10038a1362adSmaya 0, vertex_size, 0, (void**)(&vtx_dst))); 10048a1362adSmaya VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->index_buffer_mem, 10058a1362adSmaya 0, index_size, 0, (void**)(&idx_dst))); 10068a1362adSmaya for (int n = 0; n < draw_data->CmdListsCount; n++) 10078a1362adSmaya { 10088a1362adSmaya const ImDrawList* cmd_list = draw_data->CmdLists[n]; 10098a1362adSmaya memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); 10108a1362adSmaya memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 10118a1362adSmaya vtx_dst += cmd_list->VtxBuffer.Size; 10128a1362adSmaya idx_dst += cmd_list->IdxBuffer.Size; 10138a1362adSmaya } 10148a1362adSmaya VkMappedMemoryRange range[2] = {}; 10158a1362adSmaya range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 10168a1362adSmaya range[0].memory = draw->vertex_buffer_mem; 10178a1362adSmaya range[0].size = VK_WHOLE_SIZE; 10188a1362adSmaya range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 10198a1362adSmaya range[1].memory = draw->index_buffer_mem; 10208a1362adSmaya range[1].size = VK_WHOLE_SIZE; 10218a1362adSmaya VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 2, range)); 10228a1362adSmaya device_data->vtable.UnmapMemory(device_data->device, draw->vertex_buffer_mem); 10238a1362adSmaya device_data->vtable.UnmapMemory(device_data->device, draw->index_buffer_mem); 10248a1362adSmaya 10258a1362adSmaya /* Bind pipeline and descriptor sets */ 10268a1362adSmaya device_data->vtable.CmdBindPipeline(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline); 10278a1362adSmaya VkDescriptorSet desc_set[1] = { data->descriptor_set }; 10288a1362adSmaya device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 10298a1362adSmaya data->pipeline_layout, 0, 1, desc_set, 0, NULL); 10308a1362adSmaya 10318a1362adSmaya /* Bind vertex & index buffers */ 10328a1362adSmaya VkBuffer vertex_buffers[1] = { draw->vertex_buffer }; 10338a1362adSmaya VkDeviceSize vertex_offset[1] = { 0 }; 10348a1362adSmaya device_data->vtable.CmdBindVertexBuffers(draw->command_buffer, 0, 1, vertex_buffers, vertex_offset); 10358a1362adSmaya device_data->vtable.CmdBindIndexBuffer(draw->command_buffer, draw->index_buffer, 0, VK_INDEX_TYPE_UINT16); 10368a1362adSmaya 10378a1362adSmaya /* Setup viewport */ 10388a1362adSmaya VkViewport viewport; 10398a1362adSmaya viewport.x = 0; 10408a1362adSmaya viewport.y = 0; 10418a1362adSmaya viewport.width = draw_data->DisplaySize.x; 10428a1362adSmaya viewport.height = draw_data->DisplaySize.y; 10438a1362adSmaya viewport.minDepth = 0.0f; 10448a1362adSmaya viewport.maxDepth = 1.0f; 10458a1362adSmaya device_data->vtable.CmdSetViewport(draw->command_buffer, 0, 1, &viewport); 10468a1362adSmaya 10478a1362adSmaya 10488a1362adSmaya /* Setup scale and translation through push constants : 10498a1362adSmaya * 10508a1362adSmaya * Our visible imgui space lies from draw_data->DisplayPos (top left) to 10518a1362adSmaya * draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin 10528a1362adSmaya * is typically (0,0) for single viewport apps. 10538a1362adSmaya */ 10548a1362adSmaya float scale[2]; 10558a1362adSmaya scale[0] = 2.0f / draw_data->DisplaySize.x; 10568a1362adSmaya scale[1] = 2.0f / draw_data->DisplaySize.y; 10578a1362adSmaya float translate[2]; 10588a1362adSmaya translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; 10598a1362adSmaya translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; 10608a1362adSmaya device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, 10618a1362adSmaya VK_SHADER_STAGE_VERTEX_BIT, 10628a1362adSmaya sizeof(float) * 0, sizeof(float) * 2, scale); 10638a1362adSmaya device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, 10648a1362adSmaya VK_SHADER_STAGE_VERTEX_BIT, 10658a1362adSmaya sizeof(float) * 2, sizeof(float) * 2, translate); 10668a1362adSmaya 10678a1362adSmaya // Render the command lists: 10688a1362adSmaya int vtx_offset = 0; 10698a1362adSmaya int idx_offset = 0; 10708a1362adSmaya ImVec2 display_pos = draw_data->DisplayPos; 10718a1362adSmaya for (int n = 0; n < draw_data->CmdListsCount; n++) 10728a1362adSmaya { 10738a1362adSmaya const ImDrawList* cmd_list = draw_data->CmdLists[n]; 10748a1362adSmaya for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 10758a1362adSmaya { 10768a1362adSmaya const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 10778a1362adSmaya // Apply scissor/clipping rectangle 10788a1362adSmaya // FIXME: We could clamp width/height based on clamped min/max values. 10798a1362adSmaya VkRect2D scissor; 10808a1362adSmaya scissor.offset.x = (int32_t)(pcmd->ClipRect.x - display_pos.x) > 0 ? (int32_t)(pcmd->ClipRect.x - display_pos.x) : 0; 10818a1362adSmaya scissor.offset.y = (int32_t)(pcmd->ClipRect.y - display_pos.y) > 0 ? (int32_t)(pcmd->ClipRect.y - display_pos.y) : 0; 10828a1362adSmaya scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); 10838a1362adSmaya scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here? 10848a1362adSmaya device_data->vtable.CmdSetScissor(draw->command_buffer, 0, 1, &scissor); 10858a1362adSmaya 10868a1362adSmaya // Draw 10878a1362adSmaya device_data->vtable.CmdDrawIndexed(draw->command_buffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); 10888a1362adSmaya 10898a1362adSmaya idx_offset += pcmd->ElemCount; 10908a1362adSmaya } 10918a1362adSmaya vtx_offset += cmd_list->VtxBuffer.Size; 10928a1362adSmaya } 10938a1362adSmaya 10948a1362adSmaya device_data->vtable.CmdEndRenderPass(draw->command_buffer); 10958a1362adSmaya 10968a1362adSmaya /* Bounce the image to display back to present layout. */ 10978a1362adSmaya imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 10988a1362adSmaya imb.pNext = nullptr; 10998a1362adSmaya imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 11008a1362adSmaya imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 11018a1362adSmaya imb.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 11028a1362adSmaya imb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 11038a1362adSmaya imb.image = data->images[image_index]; 11048a1362adSmaya imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 11058a1362adSmaya imb.subresourceRange.baseMipLevel = 0; 11068a1362adSmaya imb.subresourceRange.levelCount = 1; 11078a1362adSmaya imb.subresourceRange.baseArrayLayer = 0; 11088a1362adSmaya imb.subresourceRange.layerCount = 1; 11098a1362adSmaya imb.srcQueueFamilyIndex = device_data->graphic_queue->family_index; 11108a1362adSmaya imb.dstQueueFamilyIndex = present_queue->family_index; 11118a1362adSmaya device_data->vtable.CmdPipelineBarrier(draw->command_buffer, 11128a1362adSmaya VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 11138a1362adSmaya VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 11148a1362adSmaya 0, /* dependency flags */ 11158a1362adSmaya 0, nullptr, /* memory barriers */ 11168a1362adSmaya 0, nullptr, /* buffer memory barriers */ 11178a1362adSmaya 1, &imb); /* image memory barriers */ 11188a1362adSmaya 11198a1362adSmaya device_data->vtable.EndCommandBuffer(draw->command_buffer); 11208a1362adSmaya 11218a1362adSmaya VkSubmitInfo submit_info = {}; 11228a1362adSmaya VkPipelineStageFlags stage_wait = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 11238a1362adSmaya submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 11248a1362adSmaya submit_info.commandBufferCount = 1; 11258a1362adSmaya submit_info.pCommandBuffers = &draw->command_buffer; 11268a1362adSmaya submit_info.pWaitDstStageMask = &stage_wait; 11278a1362adSmaya submit_info.waitSemaphoreCount = n_wait_semaphores; 11288a1362adSmaya submit_info.pWaitSemaphores = wait_semaphores; 11298a1362adSmaya submit_info.signalSemaphoreCount = 1; 11308a1362adSmaya submit_info.pSignalSemaphores = &draw->semaphore; 11318a1362adSmaya 11328a1362adSmaya device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); 11338a1362adSmaya 11348a1362adSmaya return draw; 11358a1362adSmaya} 11368a1362adSmaya 11378a1362adSmayastatic const uint32_t overlay_vert_spv[] = { 11388a1362adSmaya#include "overlay.vert.spv.h" 11398a1362adSmaya}; 11408a1362adSmayastatic const uint32_t overlay_frag_spv[] = { 11418a1362adSmaya#include "overlay.frag.spv.h" 11428a1362adSmaya}; 11438a1362adSmaya 11448a1362adSmayastatic void setup_swapchain_data_pipeline(struct swapchain_data *data) 11458a1362adSmaya{ 11468a1362adSmaya struct device_data *device_data = data->device; 11478a1362adSmaya VkShaderModule vert_module, frag_module; 11488a1362adSmaya 11498a1362adSmaya /* Create shader modules */ 11508a1362adSmaya VkShaderModuleCreateInfo vert_info = {}; 11518a1362adSmaya vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 11528a1362adSmaya vert_info.codeSize = sizeof(overlay_vert_spv); 11538a1362adSmaya vert_info.pCode = overlay_vert_spv; 11548a1362adSmaya VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, 11558a1362adSmaya &vert_info, NULL, &vert_module)); 11568a1362adSmaya VkShaderModuleCreateInfo frag_info = {}; 11578a1362adSmaya frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 11588a1362adSmaya frag_info.codeSize = sizeof(overlay_frag_spv); 11598a1362adSmaya frag_info.pCode = (uint32_t*)overlay_frag_spv; 11608a1362adSmaya VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, 11618a1362adSmaya &frag_info, NULL, &frag_module)); 11628a1362adSmaya 11638a1362adSmaya /* Font sampler */ 11648a1362adSmaya VkSamplerCreateInfo sampler_info = {}; 11658a1362adSmaya sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 11668a1362adSmaya sampler_info.magFilter = VK_FILTER_LINEAR; 11678a1362adSmaya sampler_info.minFilter = VK_FILTER_LINEAR; 11688a1362adSmaya sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 11698a1362adSmaya sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; 11708a1362adSmaya sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; 11718a1362adSmaya sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; 11728a1362adSmaya sampler_info.minLod = -1000; 11738a1362adSmaya sampler_info.maxLod = 1000; 11748a1362adSmaya sampler_info.maxAnisotropy = 1.0f; 11758a1362adSmaya VK_CHECK(device_data->vtable.CreateSampler(device_data->device, &sampler_info, 11768a1362adSmaya NULL, &data->font_sampler)); 11778a1362adSmaya 11788a1362adSmaya /* Descriptor pool */ 11798a1362adSmaya VkDescriptorPoolSize sampler_pool_size = {}; 11808a1362adSmaya sampler_pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 11818a1362adSmaya sampler_pool_size.descriptorCount = 1; 11828a1362adSmaya VkDescriptorPoolCreateInfo desc_pool_info = {}; 11838a1362adSmaya desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 11848a1362adSmaya desc_pool_info.maxSets = 1; 11858a1362adSmaya desc_pool_info.poolSizeCount = 1; 11868a1362adSmaya desc_pool_info.pPoolSizes = &sampler_pool_size; 11878a1362adSmaya VK_CHECK(device_data->vtable.CreateDescriptorPool(device_data->device, 11888a1362adSmaya &desc_pool_info, 11898a1362adSmaya NULL, &data->descriptor_pool)); 11908a1362adSmaya 11918a1362adSmaya /* Descriptor layout */ 11928a1362adSmaya VkSampler sampler[1] = { data->font_sampler }; 11938a1362adSmaya VkDescriptorSetLayoutBinding binding[1] = {}; 11948a1362adSmaya binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 11958a1362adSmaya binding[0].descriptorCount = 1; 11968a1362adSmaya binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 11978a1362adSmaya binding[0].pImmutableSamplers = sampler; 11988a1362adSmaya VkDescriptorSetLayoutCreateInfo set_layout_info = {}; 11998a1362adSmaya set_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 12008a1362adSmaya set_layout_info.bindingCount = 1; 12018a1362adSmaya set_layout_info.pBindings = binding; 12028a1362adSmaya VK_CHECK(device_data->vtable.CreateDescriptorSetLayout(device_data->device, 12038a1362adSmaya &set_layout_info, 12048a1362adSmaya NULL, &data->descriptor_layout)); 12058a1362adSmaya 12068a1362adSmaya /* Descriptor set */ 12078a1362adSmaya VkDescriptorSetAllocateInfo alloc_info = {}; 12088a1362adSmaya alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 12098a1362adSmaya alloc_info.descriptorPool = data->descriptor_pool; 12108a1362adSmaya alloc_info.descriptorSetCount = 1; 12118a1362adSmaya alloc_info.pSetLayouts = &data->descriptor_layout; 12128a1362adSmaya VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, 12138a1362adSmaya &alloc_info, 12148a1362adSmaya &data->descriptor_set)); 12158a1362adSmaya 12168a1362adSmaya /* Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 12178a1362adSmaya * 3d projection matrix 12188a1362adSmaya */ 12198a1362adSmaya VkPushConstantRange push_constants[1] = {}; 12208a1362adSmaya push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 12218a1362adSmaya push_constants[0].offset = sizeof(float) * 0; 12228a1362adSmaya push_constants[0].size = sizeof(float) * 4; 12238a1362adSmaya VkPipelineLayoutCreateInfo layout_info = {}; 12248a1362adSmaya layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 12258a1362adSmaya layout_info.setLayoutCount = 1; 12268a1362adSmaya layout_info.pSetLayouts = &data->descriptor_layout; 12278a1362adSmaya layout_info.pushConstantRangeCount = 1; 12288a1362adSmaya layout_info.pPushConstantRanges = push_constants; 12298a1362adSmaya VK_CHECK(device_data->vtable.CreatePipelineLayout(device_data->device, 12308a1362adSmaya &layout_info, 12318a1362adSmaya NULL, &data->pipeline_layout)); 12328a1362adSmaya 12338a1362adSmaya VkPipelineShaderStageCreateInfo stage[2] = {}; 12348a1362adSmaya stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 12358a1362adSmaya stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 12368a1362adSmaya stage[0].module = vert_module; 12378a1362adSmaya stage[0].pName = "main"; 12388a1362adSmaya stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 12398a1362adSmaya stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 12408a1362adSmaya stage[1].module = frag_module; 12418a1362adSmaya stage[1].pName = "main"; 12428a1362adSmaya 12438a1362adSmaya VkVertexInputBindingDescription binding_desc[1] = {}; 12448a1362adSmaya binding_desc[0].stride = sizeof(ImDrawVert); 12458a1362adSmaya binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 12468a1362adSmaya 12478a1362adSmaya VkVertexInputAttributeDescription attribute_desc[3] = {}; 12488a1362adSmaya attribute_desc[0].location = 0; 12498a1362adSmaya attribute_desc[0].binding = binding_desc[0].binding; 12508a1362adSmaya attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; 12518a1362adSmaya attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos); 12528a1362adSmaya attribute_desc[1].location = 1; 12538a1362adSmaya attribute_desc[1].binding = binding_desc[0].binding; 12548a1362adSmaya attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; 12558a1362adSmaya attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv); 12568a1362adSmaya attribute_desc[2].location = 2; 12578a1362adSmaya attribute_desc[2].binding = binding_desc[0].binding; 12588a1362adSmaya attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; 12598a1362adSmaya attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col); 12608a1362adSmaya 12618a1362adSmaya VkPipelineVertexInputStateCreateInfo vertex_info = {}; 12628a1362adSmaya vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 12638a1362adSmaya vertex_info.vertexBindingDescriptionCount = 1; 12648a1362adSmaya vertex_info.pVertexBindingDescriptions = binding_desc; 12658a1362adSmaya vertex_info.vertexAttributeDescriptionCount = 3; 12668a1362adSmaya vertex_info.pVertexAttributeDescriptions = attribute_desc; 12678a1362adSmaya 12688a1362adSmaya VkPipelineInputAssemblyStateCreateInfo ia_info = {}; 12698a1362adSmaya ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 12708a1362adSmaya ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 12718a1362adSmaya 12728a1362adSmaya VkPipelineViewportStateCreateInfo viewport_info = {}; 12738a1362adSmaya viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 12748a1362adSmaya viewport_info.viewportCount = 1; 12758a1362adSmaya viewport_info.scissorCount = 1; 12768a1362adSmaya 12778a1362adSmaya VkPipelineRasterizationStateCreateInfo raster_info = {}; 12788a1362adSmaya raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 12798a1362adSmaya raster_info.polygonMode = VK_POLYGON_MODE_FILL; 12808a1362adSmaya raster_info.cullMode = VK_CULL_MODE_NONE; 12818a1362adSmaya raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 12828a1362adSmaya raster_info.lineWidth = 1.0f; 12838a1362adSmaya 12848a1362adSmaya VkPipelineMultisampleStateCreateInfo ms_info = {}; 12858a1362adSmaya ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 12868a1362adSmaya ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 12878a1362adSmaya 12888a1362adSmaya VkPipelineColorBlendAttachmentState color_attachment[1] = {}; 12898a1362adSmaya color_attachment[0].blendEnable = VK_TRUE; 12908a1362adSmaya color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 12918a1362adSmaya color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 12928a1362adSmaya color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; 12938a1362adSmaya color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 12948a1362adSmaya color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 12958a1362adSmaya color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; 12968a1362adSmaya color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | 12978a1362adSmaya VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 12988a1362adSmaya 12998a1362adSmaya VkPipelineDepthStencilStateCreateInfo depth_info = {}; 13008a1362adSmaya depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 13018a1362adSmaya 13028a1362adSmaya VkPipelineColorBlendStateCreateInfo blend_info = {}; 13038a1362adSmaya blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 13048a1362adSmaya blend_info.attachmentCount = 1; 13058a1362adSmaya blend_info.pAttachments = color_attachment; 13068a1362adSmaya 13078a1362adSmaya VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; 13088a1362adSmaya VkPipelineDynamicStateCreateInfo dynamic_state = {}; 13098a1362adSmaya dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 13108a1362adSmaya dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); 13118a1362adSmaya dynamic_state.pDynamicStates = dynamic_states; 13128a1362adSmaya 13138a1362adSmaya VkGraphicsPipelineCreateInfo info = {}; 13148a1362adSmaya info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 13158a1362adSmaya info.flags = 0; 13168a1362adSmaya info.stageCount = 2; 13178a1362adSmaya info.pStages = stage; 13188a1362adSmaya info.pVertexInputState = &vertex_info; 13198a1362adSmaya info.pInputAssemblyState = &ia_info; 13208a1362adSmaya info.pViewportState = &viewport_info; 13218a1362adSmaya info.pRasterizationState = &raster_info; 13228a1362adSmaya info.pMultisampleState = &ms_info; 13238a1362adSmaya info.pDepthStencilState = &depth_info; 13248a1362adSmaya info.pColorBlendState = &blend_info; 13258a1362adSmaya info.pDynamicState = &dynamic_state; 13268a1362adSmaya info.layout = data->pipeline_layout; 13278a1362adSmaya info.renderPass = data->render_pass; 13288a1362adSmaya VK_CHECK( 13298a1362adSmaya device_data->vtable.CreateGraphicsPipelines(device_data->device, VK_NULL_HANDLE, 13308a1362adSmaya 1, &info, 13318a1362adSmaya NULL, &data->pipeline)); 13328a1362adSmaya 13338a1362adSmaya device_data->vtable.DestroyShaderModule(device_data->device, vert_module, NULL); 13348a1362adSmaya device_data->vtable.DestroyShaderModule(device_data->device, frag_module, NULL); 13358a1362adSmaya 13368a1362adSmaya ImGuiIO& io = ImGui::GetIO(); 13378a1362adSmaya unsigned char* pixels; 13388a1362adSmaya int width, height; 13398a1362adSmaya io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 13408a1362adSmaya 13418a1362adSmaya /* Font image */ 13428a1362adSmaya VkImageCreateInfo image_info = {}; 13438a1362adSmaya image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 13448a1362adSmaya image_info.imageType = VK_IMAGE_TYPE_2D; 13458a1362adSmaya image_info.format = VK_FORMAT_R8G8B8A8_UNORM; 13468a1362adSmaya image_info.extent.width = width; 13478a1362adSmaya image_info.extent.height = height; 13488a1362adSmaya image_info.extent.depth = 1; 13498a1362adSmaya image_info.mipLevels = 1; 13508a1362adSmaya image_info.arrayLayers = 1; 13518a1362adSmaya image_info.samples = VK_SAMPLE_COUNT_1_BIT; 13528a1362adSmaya image_info.tiling = VK_IMAGE_TILING_OPTIMAL; 13538a1362adSmaya image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 13548a1362adSmaya image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 13558a1362adSmaya image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 13568a1362adSmaya VK_CHECK(device_data->vtable.CreateImage(device_data->device, &image_info, 13578a1362adSmaya NULL, &data->font_image)); 13588a1362adSmaya VkMemoryRequirements font_image_req; 13598a1362adSmaya device_data->vtable.GetImageMemoryRequirements(device_data->device, 13608a1362adSmaya data->font_image, &font_image_req); 13618a1362adSmaya VkMemoryAllocateInfo image_alloc_info = {}; 13628a1362adSmaya image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 13638a1362adSmaya image_alloc_info.allocationSize = font_image_req.size; 13648a1362adSmaya image_alloc_info.memoryTypeIndex = vk_memory_type(device_data, 13658a1362adSmaya VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 13668a1362adSmaya font_image_req.memoryTypeBits); 13678a1362adSmaya VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, &image_alloc_info, 13688a1362adSmaya NULL, &data->font_mem)); 13698a1362adSmaya VK_CHECK(device_data->vtable.BindImageMemory(device_data->device, 13708a1362adSmaya data->font_image, 13718a1362adSmaya data->font_mem, 0)); 13728a1362adSmaya 13738a1362adSmaya /* Font image view */ 13748a1362adSmaya VkImageViewCreateInfo view_info = {}; 13758a1362adSmaya view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 13768a1362adSmaya view_info.image = data->font_image; 13778a1362adSmaya view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 13788a1362adSmaya view_info.format = VK_FORMAT_R8G8B8A8_UNORM; 13798a1362adSmaya view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 13808a1362adSmaya view_info.subresourceRange.levelCount = 1; 13818a1362adSmaya view_info.subresourceRange.layerCount = 1; 13828a1362adSmaya VK_CHECK(device_data->vtable.CreateImageView(device_data->device, &view_info, 13838a1362adSmaya NULL, &data->font_image_view)); 13848a1362adSmaya 13858a1362adSmaya /* Descriptor set */ 13868a1362adSmaya VkDescriptorImageInfo desc_image[1] = {}; 13878a1362adSmaya desc_image[0].sampler = data->font_sampler; 13888a1362adSmaya desc_image[0].imageView = data->font_image_view; 13898a1362adSmaya desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 13908a1362adSmaya VkWriteDescriptorSet write_desc[1] = {}; 13918a1362adSmaya write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 13928a1362adSmaya write_desc[0].dstSet = data->descriptor_set; 13938a1362adSmaya write_desc[0].descriptorCount = 1; 13948a1362adSmaya write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 13958a1362adSmaya write_desc[0].pImageInfo = desc_image; 13968a1362adSmaya device_data->vtable.UpdateDescriptorSets(device_data->device, 1, write_desc, 0, NULL); 13978a1362adSmaya} 13988a1362adSmaya 13998a1362adSmayastatic void setup_swapchain_data(struct swapchain_data *data, 14008a1362adSmaya const VkSwapchainCreateInfoKHR *pCreateInfo) 14018a1362adSmaya{ 14028a1362adSmaya data->width = pCreateInfo->imageExtent.width; 14038a1362adSmaya data->height = pCreateInfo->imageExtent.height; 14048a1362adSmaya data->format = pCreateInfo->imageFormat; 14058a1362adSmaya 14068a1362adSmaya data->imgui_context = ImGui::CreateContext(); 14078a1362adSmaya ImGui::SetCurrentContext(data->imgui_context); 14088a1362adSmaya 14098a1362adSmaya ImGui::GetIO().IniFilename = NULL; 14108a1362adSmaya ImGui::GetIO().DisplaySize = ImVec2((float)data->width, (float)data->height); 14118a1362adSmaya 14128a1362adSmaya struct device_data *device_data = data->device; 14138a1362adSmaya 14148a1362adSmaya /* Render pass */ 14158a1362adSmaya VkAttachmentDescription attachment_desc = {}; 14168a1362adSmaya attachment_desc.format = pCreateInfo->imageFormat; 14178a1362adSmaya attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT; 14188a1362adSmaya attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 14198a1362adSmaya attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 14208a1362adSmaya attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 14218a1362adSmaya attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 14228a1362adSmaya attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 14238a1362adSmaya attachment_desc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 14248a1362adSmaya VkAttachmentReference color_attachment = {}; 14258a1362adSmaya color_attachment.attachment = 0; 14268a1362adSmaya color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 14278a1362adSmaya VkSubpassDescription subpass = {}; 14288a1362adSmaya subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 14298a1362adSmaya subpass.colorAttachmentCount = 1; 14308a1362adSmaya subpass.pColorAttachments = &color_attachment; 14318a1362adSmaya VkSubpassDependency dependency = {}; 14328a1362adSmaya dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 14338a1362adSmaya dependency.dstSubpass = 0; 14348a1362adSmaya dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 14358a1362adSmaya dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 14368a1362adSmaya dependency.srcAccessMask = 0; 14378a1362adSmaya dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 14388a1362adSmaya VkRenderPassCreateInfo render_pass_info = {}; 14398a1362adSmaya render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 14408a1362adSmaya render_pass_info.attachmentCount = 1; 14418a1362adSmaya render_pass_info.pAttachments = &attachment_desc; 14428a1362adSmaya render_pass_info.subpassCount = 1; 14438a1362adSmaya render_pass_info.pSubpasses = &subpass; 14448a1362adSmaya render_pass_info.dependencyCount = 1; 14458a1362adSmaya render_pass_info.pDependencies = &dependency; 14468a1362adSmaya VK_CHECK(device_data->vtable.CreateRenderPass(device_data->device, 14478a1362adSmaya &render_pass_info, 14488a1362adSmaya NULL, &data->render_pass)); 14498a1362adSmaya 14508a1362adSmaya setup_swapchain_data_pipeline(data); 14518a1362adSmaya 14528a1362adSmaya VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, 14538a1362adSmaya data->swapchain, 14548a1362adSmaya &data->n_images, 14558a1362adSmaya NULL)); 14568a1362adSmaya 14578a1362adSmaya data->images = ralloc_array(data, VkImage, data->n_images); 14588a1362adSmaya data->image_views = ralloc_array(data, VkImageView, data->n_images); 14598a1362adSmaya data->framebuffers = ralloc_array(data, VkFramebuffer, data->n_images); 14608a1362adSmaya 14618a1362adSmaya VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, 14628a1362adSmaya data->swapchain, 14638a1362adSmaya &data->n_images, 14648a1362adSmaya data->images)); 14658a1362adSmaya 14668a1362adSmaya /* Image views */ 14678a1362adSmaya VkImageViewCreateInfo view_info = {}; 14688a1362adSmaya view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 14698a1362adSmaya view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 14708a1362adSmaya view_info.format = pCreateInfo->imageFormat; 14718a1362adSmaya view_info.components.r = VK_COMPONENT_SWIZZLE_R; 14728a1362adSmaya view_info.components.g = VK_COMPONENT_SWIZZLE_G; 14738a1362adSmaya view_info.components.b = VK_COMPONENT_SWIZZLE_B; 14748a1362adSmaya view_info.components.a = VK_COMPONENT_SWIZZLE_A; 14758a1362adSmaya view_info.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 14768a1362adSmaya for (uint32_t i = 0; i < data->n_images; i++) { 14778a1362adSmaya view_info.image = data->images[i]; 14788a1362adSmaya VK_CHECK(device_data->vtable.CreateImageView(device_data->device, 14798a1362adSmaya &view_info, NULL, 14808a1362adSmaya &data->image_views[i])); 14818a1362adSmaya } 14828a1362adSmaya 14838a1362adSmaya /* Framebuffers */ 14848a1362adSmaya VkImageView attachment[1]; 14858a1362adSmaya VkFramebufferCreateInfo fb_info = {}; 14868a1362adSmaya fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 14878a1362adSmaya fb_info.renderPass = data->render_pass; 14888a1362adSmaya fb_info.attachmentCount = 1; 14898a1362adSmaya fb_info.pAttachments = attachment; 14908a1362adSmaya fb_info.width = data->width; 14918a1362adSmaya fb_info.height = data->height; 14928a1362adSmaya fb_info.layers = 1; 14938a1362adSmaya for (uint32_t i = 0; i < data->n_images; i++) { 14948a1362adSmaya attachment[0] = data->image_views[i]; 14958a1362adSmaya VK_CHECK(device_data->vtable.CreateFramebuffer(device_data->device, &fb_info, 14968a1362adSmaya NULL, &data->framebuffers[i])); 14978a1362adSmaya } 14988a1362adSmaya 14998a1362adSmaya /* Command buffer pool */ 15008a1362adSmaya VkCommandPoolCreateInfo cmd_buffer_pool_info = {}; 15018a1362adSmaya cmd_buffer_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 15028a1362adSmaya cmd_buffer_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; 15038a1362adSmaya cmd_buffer_pool_info.queueFamilyIndex = device_data->graphic_queue->family_index; 15048a1362adSmaya VK_CHECK(device_data->vtable.CreateCommandPool(device_data->device, 15058a1362adSmaya &cmd_buffer_pool_info, 15068a1362adSmaya NULL, &data->command_pool)); 15078a1362adSmaya} 15088a1362adSmaya 15098a1362adSmayastatic void shutdown_swapchain_data(struct swapchain_data *data) 15108a1362adSmaya{ 15118a1362adSmaya struct device_data *device_data = data->device; 15128a1362adSmaya 15138a1362adSmaya list_for_each_entry_safe(struct overlay_draw, draw, &data->draws, link) { 15148a1362adSmaya device_data->vtable.DestroySemaphore(device_data->device, draw->semaphore, NULL); 15158a1362adSmaya device_data->vtable.DestroyFence(device_data->device, draw->fence, NULL); 15168a1362adSmaya device_data->vtable.DestroyBuffer(device_data->device, draw->vertex_buffer, NULL); 15178a1362adSmaya device_data->vtable.DestroyBuffer(device_data->device, draw->index_buffer, NULL); 15188a1362adSmaya device_data->vtable.FreeMemory(device_data->device, draw->vertex_buffer_mem, NULL); 15198a1362adSmaya device_data->vtable.FreeMemory(device_data->device, draw->index_buffer_mem, NULL); 15208a1362adSmaya } 15218a1362adSmaya 15228a1362adSmaya for (uint32_t i = 0; i < data->n_images; i++) { 15238a1362adSmaya device_data->vtable.DestroyImageView(device_data->device, data->image_views[i], NULL); 15248a1362adSmaya device_data->vtable.DestroyFramebuffer(device_data->device, data->framebuffers[i], NULL); 15258a1362adSmaya } 15268a1362adSmaya 15278a1362adSmaya device_data->vtable.DestroyRenderPass(device_data->device, data->render_pass, NULL); 15288a1362adSmaya 15298a1362adSmaya device_data->vtable.DestroyCommandPool(device_data->device, data->command_pool, NULL); 15308a1362adSmaya 15318a1362adSmaya device_data->vtable.DestroyPipeline(device_data->device, data->pipeline, NULL); 15328a1362adSmaya device_data->vtable.DestroyPipelineLayout(device_data->device, data->pipeline_layout, NULL); 15338a1362adSmaya 15348a1362adSmaya device_data->vtable.DestroyDescriptorPool(device_data->device, 15358a1362adSmaya data->descriptor_pool, NULL); 15368a1362adSmaya device_data->vtable.DestroyDescriptorSetLayout(device_data->device, 15378a1362adSmaya data->descriptor_layout, NULL); 15388a1362adSmaya 15398a1362adSmaya device_data->vtable.DestroySampler(device_data->device, data->font_sampler, NULL); 15408a1362adSmaya device_data->vtable.DestroyImageView(device_data->device, data->font_image_view, NULL); 15418a1362adSmaya device_data->vtable.DestroyImage(device_data->device, data->font_image, NULL); 15428a1362adSmaya device_data->vtable.FreeMemory(device_data->device, data->font_mem, NULL); 15438a1362adSmaya 15448a1362adSmaya device_data->vtable.DestroyBuffer(device_data->device, data->upload_font_buffer, NULL); 15458a1362adSmaya device_data->vtable.FreeMemory(device_data->device, data->upload_font_buffer_mem, NULL); 15468a1362adSmaya 15478a1362adSmaya ImGui::DestroyContext(data->imgui_context); 15488a1362adSmaya} 15498a1362adSmaya 15508a1362adSmayastatic struct overlay_draw *before_present(struct swapchain_data *swapchain_data, 15518a1362adSmaya struct queue_data *present_queue, 15528a1362adSmaya const VkSemaphore *wait_semaphores, 15538a1362adSmaya unsigned n_wait_semaphores, 15548a1362adSmaya unsigned imageIndex) 15558a1362adSmaya{ 15568a1362adSmaya struct instance_data *instance_data = swapchain_data->device->instance; 15578a1362adSmaya struct overlay_draw *draw = NULL; 15588a1362adSmaya 15598a1362adSmaya snapshot_swapchain_frame(swapchain_data); 15608a1362adSmaya 15618a1362adSmaya if (!instance_data->params.no_display && swapchain_data->n_frames > 0) { 15628a1362adSmaya compute_swapchain_display(swapchain_data); 15638a1362adSmaya draw = render_swapchain_display(swapchain_data, present_queue, 15648a1362adSmaya wait_semaphores, n_wait_semaphores, 15658a1362adSmaya imageIndex); 15668a1362adSmaya } 15678a1362adSmaya 15688a1362adSmaya return draw; 15698a1362adSmaya} 15708a1362adSmaya 15718a1362adSmayastatic VkResult overlay_CreateSwapchainKHR( 15728a1362adSmaya VkDevice device, 15738a1362adSmaya const VkSwapchainCreateInfoKHR* pCreateInfo, 15748a1362adSmaya const VkAllocationCallbacks* pAllocator, 15758a1362adSmaya VkSwapchainKHR* pSwapchain) 15768a1362adSmaya{ 15778a1362adSmaya struct device_data *device_data = FIND_DEVICE_DATA(device); 15788a1362adSmaya VkResult result = device_data->vtable.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 15798a1362adSmaya if (result != VK_SUCCESS) return result; 15808a1362adSmaya 15818a1362adSmaya struct swapchain_data *swapchain_data = new_swapchain_data(*pSwapchain, device_data); 15828a1362adSmaya setup_swapchain_data(swapchain_data, pCreateInfo); 15838a1362adSmaya return result; 15848a1362adSmaya} 15858a1362adSmaya 15868a1362adSmayastatic void overlay_DestroySwapchainKHR( 15878a1362adSmaya VkDevice device, 15888a1362adSmaya VkSwapchainKHR swapchain, 15898a1362adSmaya const VkAllocationCallbacks* pAllocator) 15908a1362adSmaya{ 15918a1362adSmaya struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(swapchain); 15928a1362adSmaya 15938a1362adSmaya shutdown_swapchain_data(swapchain_data); 15948a1362adSmaya swapchain_data->device->vtable.DestroySwapchainKHR(device, swapchain, pAllocator); 15958a1362adSmaya destroy_swapchain_data(swapchain_data); 15968a1362adSmaya} 15978a1362adSmaya 15988a1362adSmayastatic VkResult overlay_QueuePresentKHR( 15998a1362adSmaya VkQueue queue, 16008a1362adSmaya const VkPresentInfoKHR* pPresentInfo) 16018a1362adSmaya{ 16028a1362adSmaya struct queue_data *queue_data = FIND_QUEUE_DATA(queue); 16038a1362adSmaya struct device_data *device_data = queue_data->device; 16048a1362adSmaya struct instance_data *instance_data = device_data->instance; 16058a1362adSmaya uint32_t query_results[OVERLAY_QUERY_COUNT]; 16068a1362adSmaya 16078a1362adSmaya device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_frame]++; 16088a1362adSmaya 16098a1362adSmaya if (list_length(&queue_data->running_command_buffer) > 0) { 16108a1362adSmaya /* Before getting the query results, make sure the operations have 16118a1362adSmaya * completed. 16128a1362adSmaya */ 16138a1362adSmaya VkResult err = device_data->vtable.ResetFences(device_data->device, 16148a1362adSmaya 1, &queue_data->queries_fence); 16158a1362adSmaya check_vk_result(err); 16168a1362adSmaya err = device_data->vtable.QueueSubmit(queue, 0, NULL, queue_data->queries_fence); 16178a1362adSmaya check_vk_result(err); 16188a1362adSmaya err = device_data->vtable.WaitForFences(device_data->device, 16198a1362adSmaya 1, &queue_data->queries_fence, 16208a1362adSmaya VK_FALSE, UINT64_MAX); 16218a1362adSmaya check_vk_result(err); 16228a1362adSmaya 16238a1362adSmaya /* Now get the results. */ 16248a1362adSmaya list_for_each_entry_safe(struct command_buffer_data, cmd_buffer_data, 16258a1362adSmaya &queue_data->running_command_buffer, link) { 16268a1362adSmaya list_delinit(&cmd_buffer_data->link); 16278a1362adSmaya 16288a1362adSmaya if (cmd_buffer_data->pipeline_query_pool) { 16298a1362adSmaya memset(query_results, 0, sizeof(query_results)); 16308a1362adSmaya err = 16318a1362adSmaya device_data->vtable.GetQueryPoolResults(device_data->device, 16328a1362adSmaya cmd_buffer_data->pipeline_query_pool, 16338a1362adSmaya cmd_buffer_data->query_index, 1, 16348a1362adSmaya sizeof(uint32_t) * OVERLAY_QUERY_COUNT, 16358a1362adSmaya query_results, 0, VK_QUERY_RESULT_WAIT_BIT); 16368a1362adSmaya check_vk_result(err); 16378a1362adSmaya 16388a1362adSmaya for (uint32_t i = OVERLAY_PARAM_ENABLED_vertices; 16398a1362adSmaya i <= OVERLAY_PARAM_ENABLED_compute_invocations; i++) { 16408a1362adSmaya device_data->frame_stats.stats[i] += query_results[i - OVERLAY_PARAM_ENABLED_vertices]; 16418a1362adSmaya } 16428a1362adSmaya } 16438a1362adSmaya if (cmd_buffer_data->timestamp_query_pool) { 16448a1362adSmaya uint64_t gpu_timestamps[2] = { 0 }; 16458a1362adSmaya err = 16468a1362adSmaya device_data->vtable.GetQueryPoolResults(device_data->device, 16478a1362adSmaya cmd_buffer_data->timestamp_query_pool, 16488a1362adSmaya cmd_buffer_data->query_index * 2, 2, 16498a1362adSmaya 2 * sizeof(uint64_t), gpu_timestamps, sizeof(uint64_t), 16508a1362adSmaya VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); 16518a1362adSmaya check_vk_result(err); 16528a1362adSmaya 16538a1362adSmaya gpu_timestamps[0] &= queue_data->timestamp_mask; 16548a1362adSmaya gpu_timestamps[1] &= queue_data->timestamp_mask; 16558a1362adSmaya device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_gpu_timing] += 16568a1362adSmaya (gpu_timestamps[1] - gpu_timestamps[0]) * 16578a1362adSmaya device_data->properties.limits.timestampPeriod; 16588a1362adSmaya } 16598a1362adSmaya } 16608a1362adSmaya } 16618a1362adSmaya 16628a1362adSmaya /* Otherwise we need to add our overlay drawing semaphore to the list of 16638a1362adSmaya * semaphores to wait on. If we don't do that the presented picture might 16648a1362adSmaya * be have incomplete overlay drawings. 16658a1362adSmaya */ 16668a1362adSmaya VkResult result = VK_SUCCESS; 16678a1362adSmaya if (instance_data->params.no_display) { 16688a1362adSmaya for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 16698a1362adSmaya VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; 16708a1362adSmaya struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(swapchain); 16718a1362adSmaya 16728a1362adSmaya before_present(swapchain_data, 16738a1362adSmaya queue_data, 16748a1362adSmaya pPresentInfo->pWaitSemaphores, 16758a1362adSmaya pPresentInfo->waitSemaphoreCount, 16768a1362adSmaya pPresentInfo->pImageIndices[i]); 16778a1362adSmaya } 16788a1362adSmaya result = queue_data->device->vtable.QueuePresentKHR(queue, pPresentInfo); 16798a1362adSmaya } else { 16808a1362adSmaya for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 16818a1362adSmaya VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; 16828a1362adSmaya struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(swapchain); 16838a1362adSmaya VkPresentInfoKHR present_info = *pPresentInfo; 16848a1362adSmaya present_info.swapchainCount = 1; 16858a1362adSmaya present_info.pSwapchains = &swapchain; 16868a1362adSmaya 16878a1362adSmaya uint32_t image_index = pPresentInfo->pImageIndices[i]; 16888a1362adSmaya 16898a1362adSmaya struct overlay_draw *draw = before_present(swapchain_data, 16908a1362adSmaya queue_data, 16918a1362adSmaya pPresentInfo->pWaitSemaphores, 16928a1362adSmaya pPresentInfo->waitSemaphoreCount, 16938a1362adSmaya image_index); 16948a1362adSmaya 16958a1362adSmaya /* Because the submission of the overlay draw waits on the semaphores 16968a1362adSmaya * handed for present, we don't need to have this present operation 16978a1362adSmaya * wait on them as well, we can just wait on the overlay submission 16988a1362adSmaya * semaphore. 16998a1362adSmaya */ 17008a1362adSmaya present_info.pWaitSemaphores = &draw->semaphore; 17018a1362adSmaya present_info.waitSemaphoreCount = 1; 17028a1362adSmaya 17038a1362adSmaya VkResult chain_result = queue_data->device->vtable.QueuePresentKHR(queue, &present_info); 17048a1362adSmaya if (pPresentInfo->pResults) 17058a1362adSmaya pPresentInfo->pResults[i] = chain_result; 17068a1362adSmaya if (chain_result != VK_SUCCESS && result == VK_SUCCESS) 17078a1362adSmaya result = chain_result; 17088a1362adSmaya } 17098a1362adSmaya } 17108a1362adSmaya return result; 17118a1362adSmaya} 17128a1362adSmaya 17138a1362adSmayastatic VkResult overlay_AcquireNextImageKHR( 17148a1362adSmaya VkDevice device, 17158a1362adSmaya VkSwapchainKHR swapchain, 17168a1362adSmaya uint64_t timeout, 17178a1362adSmaya VkSemaphore semaphore, 17188a1362adSmaya VkFence fence, 17198a1362adSmaya uint32_t* pImageIndex) 17208a1362adSmaya{ 17218a1362adSmaya struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(swapchain); 17228a1362adSmaya struct device_data *device_data = swapchain_data->device; 17238a1362adSmaya 17248a1362adSmaya uint64_t ts0 = os_time_get(); 17258a1362adSmaya VkResult result = device_data->vtable.AcquireNextImageKHR(device, swapchain, timeout, 17268a1362adSmaya semaphore, fence, pImageIndex); 17278a1362adSmaya uint64_t ts1 = os_time_get(); 17288a1362adSmaya 17298a1362adSmaya swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire_timing] += ts1 - ts0; 17308a1362adSmaya swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire]++; 17318a1362adSmaya 17328a1362adSmaya return result; 17338a1362adSmaya} 17348a1362adSmaya 17358a1362adSmayastatic VkResult overlay_AcquireNextImage2KHR( 17368a1362adSmaya VkDevice device, 17378a1362adSmaya const VkAcquireNextImageInfoKHR* pAcquireInfo, 17388a1362adSmaya uint32_t* pImageIndex) 17398a1362adSmaya{ 17408a1362adSmaya struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(pAcquireInfo->swapchain); 17418a1362adSmaya struct device_data *device_data = swapchain_data->device; 17428a1362adSmaya 17438a1362adSmaya uint64_t ts0 = os_time_get(); 17448a1362adSmaya VkResult result = device_data->vtable.AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex); 17458a1362adSmaya uint64_t ts1 = os_time_get(); 17468a1362adSmaya 17478a1362adSmaya swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire_timing] += ts1 - ts0; 17488a1362adSmaya swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire]++; 17498a1362adSmaya 17508a1362adSmaya return result; 17518a1362adSmaya} 17528a1362adSmaya 17538a1362adSmayastatic void overlay_CmdDraw( 17548a1362adSmaya VkCommandBuffer commandBuffer, 17558a1362adSmaya uint32_t vertexCount, 17568a1362adSmaya uint32_t instanceCount, 17578a1362adSmaya uint32_t firstVertex, 17588a1362adSmaya uint32_t firstInstance) 17598a1362adSmaya{ 17608a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 17618a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw]++; 17628a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 17638a1362adSmaya device_data->vtable.CmdDraw(commandBuffer, vertexCount, instanceCount, 17648a1362adSmaya firstVertex, firstInstance); 17658a1362adSmaya} 17668a1362adSmaya 17678a1362adSmayastatic void overlay_CmdDrawIndexed( 17688a1362adSmaya VkCommandBuffer commandBuffer, 17698a1362adSmaya uint32_t indexCount, 17708a1362adSmaya uint32_t instanceCount, 17718a1362adSmaya uint32_t firstIndex, 17728a1362adSmaya int32_t vertexOffset, 17738a1362adSmaya uint32_t firstInstance) 17748a1362adSmaya{ 17758a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 17768a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed]++; 17778a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 17788a1362adSmaya device_data->vtable.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, 17798a1362adSmaya firstIndex, vertexOffset, firstInstance); 17808a1362adSmaya} 17818a1362adSmaya 17828a1362adSmayastatic void overlay_CmdDrawIndirect( 17838a1362adSmaya VkCommandBuffer commandBuffer, 17848a1362adSmaya VkBuffer buffer, 17858a1362adSmaya VkDeviceSize offset, 17868a1362adSmaya uint32_t drawCount, 17878a1362adSmaya uint32_t stride) 17888a1362adSmaya{ 17898a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 17908a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indirect]++; 17918a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 17928a1362adSmaya device_data->vtable.CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride); 17938a1362adSmaya} 17948a1362adSmaya 17958a1362adSmayastatic void overlay_CmdDrawIndexedIndirect( 17968a1362adSmaya VkCommandBuffer commandBuffer, 17978a1362adSmaya VkBuffer buffer, 17988a1362adSmaya VkDeviceSize offset, 17998a1362adSmaya uint32_t drawCount, 18008a1362adSmaya uint32_t stride) 18018a1362adSmaya{ 18028a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 18038a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed_indirect]++; 18048a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 18058a1362adSmaya device_data->vtable.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride); 18068a1362adSmaya} 18078a1362adSmaya 18088a1362adSmayastatic void overlay_CmdDrawIndirectCountKHR( 18098a1362adSmaya VkCommandBuffer commandBuffer, 18108a1362adSmaya VkBuffer buffer, 18118a1362adSmaya VkDeviceSize offset, 18128a1362adSmaya VkBuffer countBuffer, 18138a1362adSmaya VkDeviceSize countBufferOffset, 18148a1362adSmaya uint32_t maxDrawCount, 18158a1362adSmaya uint32_t stride) 18168a1362adSmaya{ 18178a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 18188a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indirect_count]++; 18198a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 18208a1362adSmaya device_data->vtable.CmdDrawIndirectCountKHR(commandBuffer, buffer, offset, 18218a1362adSmaya countBuffer, countBufferOffset, 18228a1362adSmaya maxDrawCount, stride); 18238a1362adSmaya} 18248a1362adSmaya 18258a1362adSmayastatic void overlay_CmdDrawIndexedIndirectCountKHR( 18268a1362adSmaya VkCommandBuffer commandBuffer, 18278a1362adSmaya VkBuffer buffer, 18288a1362adSmaya VkDeviceSize offset, 18298a1362adSmaya VkBuffer countBuffer, 18308a1362adSmaya VkDeviceSize countBufferOffset, 18318a1362adSmaya uint32_t maxDrawCount, 18328a1362adSmaya uint32_t stride) 18338a1362adSmaya{ 18348a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 18358a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed_indirect_count]++; 18368a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 18378a1362adSmaya device_data->vtable.CmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, 18388a1362adSmaya countBuffer, countBufferOffset, 18398a1362adSmaya maxDrawCount, stride); 18408a1362adSmaya} 18418a1362adSmaya 18428a1362adSmayastatic void overlay_CmdDispatch( 18438a1362adSmaya VkCommandBuffer commandBuffer, 18448a1362adSmaya uint32_t groupCountX, 18458a1362adSmaya uint32_t groupCountY, 18468a1362adSmaya uint32_t groupCountZ) 18478a1362adSmaya{ 18488a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 18498a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_dispatch]++; 18508a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 18518a1362adSmaya device_data->vtable.CmdDispatch(commandBuffer, groupCountX, groupCountY, groupCountZ); 18528a1362adSmaya} 18538a1362adSmaya 18548a1362adSmayastatic void overlay_CmdDispatchIndirect( 18558a1362adSmaya VkCommandBuffer commandBuffer, 18568a1362adSmaya VkBuffer buffer, 18578a1362adSmaya VkDeviceSize offset) 18588a1362adSmaya{ 18598a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 18608a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_dispatch_indirect]++; 18618a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 18628a1362adSmaya device_data->vtable.CmdDispatchIndirect(commandBuffer, buffer, offset); 18638a1362adSmaya} 18648a1362adSmaya 18658a1362adSmayastatic void overlay_CmdBindPipeline( 18668a1362adSmaya VkCommandBuffer commandBuffer, 18678a1362adSmaya VkPipelineBindPoint pipelineBindPoint, 18688a1362adSmaya VkPipeline pipeline) 18698a1362adSmaya{ 18708a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 18718a1362adSmaya switch (pipelineBindPoint) { 18728a1362adSmaya case VK_PIPELINE_BIND_POINT_GRAPHICS: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_graphics]++; break; 18738a1362adSmaya case VK_PIPELINE_BIND_POINT_COMPUTE: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_compute]++; break; 18748a1362adSmaya case VK_PIPELINE_BIND_POINT_RAY_TRACING_NV: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_raytracing]++; break; 18758a1362adSmaya default: break; 18768a1362adSmaya } 18778a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 18788a1362adSmaya device_data->vtable.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 18798a1362adSmaya} 18808a1362adSmaya 18818a1362adSmayastatic VkResult overlay_BeginCommandBuffer( 18828a1362adSmaya VkCommandBuffer commandBuffer, 18838a1362adSmaya const VkCommandBufferBeginInfo* pBeginInfo) 18848a1362adSmaya{ 18858a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 18868a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 18878a1362adSmaya 18888a1362adSmaya memset(&cmd_buffer_data->stats, 0, sizeof(cmd_buffer_data->stats)); 18898a1362adSmaya 18908a1362adSmaya /* We don't record any query in secondary command buffers, just make sure 18918a1362adSmaya * we have the right inheritance. 18928a1362adSmaya */ 18938a1362adSmaya if (cmd_buffer_data->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) { 18948a1362adSmaya VkCommandBufferBeginInfo *begin_info = (VkCommandBufferBeginInfo *) 18958a1362adSmaya clone_chain((const struct VkBaseInStructure *)pBeginInfo); 18968a1362adSmaya VkCommandBufferInheritanceInfo *parent_inhe_info = (VkCommandBufferInheritanceInfo *) 18978a1362adSmaya vk_find_struct(begin_info, COMMAND_BUFFER_INHERITANCE_INFO); 18988a1362adSmaya VkCommandBufferInheritanceInfo inhe_info = { 18998a1362adSmaya VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 19008a1362adSmaya NULL, 19018a1362adSmaya VK_NULL_HANDLE, 19028a1362adSmaya 0, 19038a1362adSmaya VK_NULL_HANDLE, 19048a1362adSmaya VK_FALSE, 19058a1362adSmaya 0, 19068a1362adSmaya overlay_query_flags, 19078a1362adSmaya }; 19088a1362adSmaya 19098a1362adSmaya if (parent_inhe_info) 19108a1362adSmaya parent_inhe_info->pipelineStatistics = overlay_query_flags; 19118a1362adSmaya else { 19128a1362adSmaya inhe_info.pNext = begin_info->pNext; 19138a1362adSmaya begin_info->pNext = &inhe_info; 19148a1362adSmaya } 19158a1362adSmaya 19168a1362adSmaya VkResult result = device_data->vtable.BeginCommandBuffer(commandBuffer, pBeginInfo); 19178a1362adSmaya 19188a1362adSmaya if (!parent_inhe_info) 19198a1362adSmaya begin_info->pNext = inhe_info.pNext; 19208a1362adSmaya 19218a1362adSmaya free_chain((struct VkBaseOutStructure *)begin_info); 19228a1362adSmaya 19238a1362adSmaya return result; 19248a1362adSmaya } 19258a1362adSmaya 19268a1362adSmaya /* Otherwise record a begin query as first command. */ 19278a1362adSmaya VkResult result = device_data->vtable.BeginCommandBuffer(commandBuffer, pBeginInfo); 19288a1362adSmaya 19298a1362adSmaya if (result == VK_SUCCESS) { 19308a1362adSmaya if (cmd_buffer_data->pipeline_query_pool) { 19318a1362adSmaya device_data->vtable.CmdResetQueryPool(commandBuffer, 19328a1362adSmaya cmd_buffer_data->pipeline_query_pool, 19338a1362adSmaya cmd_buffer_data->query_index, 1); 19348a1362adSmaya } 19358a1362adSmaya if (cmd_buffer_data->timestamp_query_pool) { 19368a1362adSmaya device_data->vtable.CmdResetQueryPool(commandBuffer, 19378a1362adSmaya cmd_buffer_data->timestamp_query_pool, 19388a1362adSmaya cmd_buffer_data->query_index * 2, 2); 19398a1362adSmaya } 19408a1362adSmaya if (cmd_buffer_data->pipeline_query_pool) { 19418a1362adSmaya device_data->vtable.CmdBeginQuery(commandBuffer, 19428a1362adSmaya cmd_buffer_data->pipeline_query_pool, 19438a1362adSmaya cmd_buffer_data->query_index, 0); 19448a1362adSmaya } 19458a1362adSmaya if (cmd_buffer_data->timestamp_query_pool) { 19468a1362adSmaya device_data->vtable.CmdWriteTimestamp(commandBuffer, 19478a1362adSmaya VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 19488a1362adSmaya cmd_buffer_data->timestamp_query_pool, 19498a1362adSmaya cmd_buffer_data->query_index * 2); 19508a1362adSmaya } 19518a1362adSmaya } 19528a1362adSmaya 19538a1362adSmaya return result; 19548a1362adSmaya} 19558a1362adSmaya 19568a1362adSmayastatic VkResult overlay_EndCommandBuffer( 19578a1362adSmaya VkCommandBuffer commandBuffer) 19588a1362adSmaya{ 19598a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 19608a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 19618a1362adSmaya 19628a1362adSmaya if (cmd_buffer_data->timestamp_query_pool) { 19638a1362adSmaya device_data->vtable.CmdWriteTimestamp(commandBuffer, 19648a1362adSmaya VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 19658a1362adSmaya cmd_buffer_data->timestamp_query_pool, 19668a1362adSmaya cmd_buffer_data->query_index * 2 + 1); 19678a1362adSmaya } 19688a1362adSmaya if (cmd_buffer_data->pipeline_query_pool) { 19698a1362adSmaya device_data->vtable.CmdEndQuery(commandBuffer, 19708a1362adSmaya cmd_buffer_data->pipeline_query_pool, 19718a1362adSmaya cmd_buffer_data->query_index); 19728a1362adSmaya } 19738a1362adSmaya 19748a1362adSmaya return device_data->vtable.EndCommandBuffer(commandBuffer); 19758a1362adSmaya} 19768a1362adSmaya 19778a1362adSmayastatic VkResult overlay_ResetCommandBuffer( 19788a1362adSmaya VkCommandBuffer commandBuffer, 19798a1362adSmaya VkCommandBufferResetFlags flags) 19808a1362adSmaya{ 19818a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 19828a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 19838a1362adSmaya 19848a1362adSmaya memset(&cmd_buffer_data->stats, 0, sizeof(cmd_buffer_data->stats)); 19858a1362adSmaya 19868a1362adSmaya return device_data->vtable.ResetCommandBuffer(commandBuffer, flags); 19878a1362adSmaya} 19888a1362adSmaya 19898a1362adSmayastatic void overlay_CmdExecuteCommands( 19908a1362adSmaya VkCommandBuffer commandBuffer, 19918a1362adSmaya uint32_t commandBufferCount, 19928a1362adSmaya const VkCommandBuffer* pCommandBuffers) 19938a1362adSmaya{ 19948a1362adSmaya struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 19958a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 19968a1362adSmaya 19978a1362adSmaya /* Add the stats of the executed command buffers to the primary one. */ 19988a1362adSmaya for (uint32_t c = 0; c < commandBufferCount; c++) { 19998a1362adSmaya struct command_buffer_data *sec_cmd_buffer_data = FIND_CMD_BUFFER_DATA(pCommandBuffers[c]); 20008a1362adSmaya 20018a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) 20028a1362adSmaya cmd_buffer_data->stats.stats[s] += sec_cmd_buffer_data->stats.stats[s]; 20038a1362adSmaya } 20048a1362adSmaya 20058a1362adSmaya device_data->vtable.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers); 20068a1362adSmaya} 20078a1362adSmaya 20088a1362adSmayastatic VkResult overlay_AllocateCommandBuffers( 20098a1362adSmaya VkDevice device, 20108a1362adSmaya const VkCommandBufferAllocateInfo* pAllocateInfo, 20118a1362adSmaya VkCommandBuffer* pCommandBuffers) 20128a1362adSmaya{ 20138a1362adSmaya struct device_data *device_data = FIND_DEVICE_DATA(device); 20148a1362adSmaya VkResult result = 20158a1362adSmaya device_data->vtable.AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers); 20168a1362adSmaya if (result != VK_SUCCESS) 20178a1362adSmaya return result; 20188a1362adSmaya 20198a1362adSmaya VkQueryPool pipeline_query_pool = VK_NULL_HANDLE; 20208a1362adSmaya VkQueryPool timestamp_query_pool = VK_NULL_HANDLE; 20218a1362adSmaya if (device_data->instance->pipeline_statistics_enabled && 20228a1362adSmaya pAllocateInfo->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 20238a1362adSmaya VkQueryPoolCreateInfo pool_info = { 20248a1362adSmaya VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 20258a1362adSmaya NULL, 20268a1362adSmaya 0, 20278a1362adSmaya VK_QUERY_TYPE_PIPELINE_STATISTICS, 20288a1362adSmaya pAllocateInfo->commandBufferCount, 20298a1362adSmaya overlay_query_flags, 20308a1362adSmaya }; 20318a1362adSmaya VkResult err = 20328a1362adSmaya device_data->vtable.CreateQueryPool(device_data->device, &pool_info, 20338a1362adSmaya NULL, &pipeline_query_pool); 20348a1362adSmaya check_vk_result(err); 20358a1362adSmaya } 20368a1362adSmaya if (device_data->instance->params.enabled[OVERLAY_PARAM_ENABLED_gpu_timing]) { 20378a1362adSmaya VkQueryPoolCreateInfo pool_info = { 20388a1362adSmaya VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 20398a1362adSmaya NULL, 20408a1362adSmaya 0, 20418a1362adSmaya VK_QUERY_TYPE_TIMESTAMP, 20428a1362adSmaya pAllocateInfo->commandBufferCount * 2, 20438a1362adSmaya 0, 20448a1362adSmaya }; 20458a1362adSmaya VkResult err = 20468a1362adSmaya device_data->vtable.CreateQueryPool(device_data->device, &pool_info, 20478a1362adSmaya NULL, ×tamp_query_pool); 20488a1362adSmaya check_vk_result(err); 20498a1362adSmaya } 20508a1362adSmaya 20518a1362adSmaya for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) { 20528a1362adSmaya new_command_buffer_data(pCommandBuffers[i], pAllocateInfo->level, 20538a1362adSmaya pipeline_query_pool, timestamp_query_pool, 20548a1362adSmaya i, device_data); 20558a1362adSmaya } 20568a1362adSmaya 20578a1362adSmaya if (pipeline_query_pool) 20588a1362adSmaya map_object(HKEY(pipeline_query_pool), (void *)(uintptr_t) pAllocateInfo->commandBufferCount); 20598a1362adSmaya if (timestamp_query_pool) 20608a1362adSmaya map_object(HKEY(timestamp_query_pool), (void *)(uintptr_t) pAllocateInfo->commandBufferCount); 20618a1362adSmaya 20628a1362adSmaya return result; 20638a1362adSmaya} 20648a1362adSmaya 20658a1362adSmayastatic void overlay_FreeCommandBuffers( 20668a1362adSmaya VkDevice device, 20678a1362adSmaya VkCommandPool commandPool, 20688a1362adSmaya uint32_t commandBufferCount, 20698a1362adSmaya const VkCommandBuffer* pCommandBuffers) 20708a1362adSmaya{ 20718a1362adSmaya struct device_data *device_data = FIND_DEVICE_DATA(device); 20728a1362adSmaya for (uint32_t i = 0; i < commandBufferCount; i++) { 20738a1362adSmaya struct command_buffer_data *cmd_buffer_data = 20748a1362adSmaya FIND_CMD_BUFFER_DATA(pCommandBuffers[i]); 20758a1362adSmaya /* It is legal to free a NULL command buffer*/ 20768a1362adSmaya if (!cmd_buffer_data) 20778a1362adSmaya continue; 20788a1362adSmaya 20798a1362adSmaya uint64_t count = (uintptr_t)find_object_data(HKEY(cmd_buffer_data->pipeline_query_pool)); 20808a1362adSmaya if (count == 1) { 20818a1362adSmaya unmap_object(HKEY(cmd_buffer_data->pipeline_query_pool)); 20828a1362adSmaya device_data->vtable.DestroyQueryPool(device_data->device, 20838a1362adSmaya cmd_buffer_data->pipeline_query_pool, NULL); 20848a1362adSmaya } else if (count != 0) { 20858a1362adSmaya map_object(HKEY(cmd_buffer_data->pipeline_query_pool), (void *)(uintptr_t)(count - 1)); 20868a1362adSmaya } 20878a1362adSmaya count = (uintptr_t)find_object_data(HKEY(cmd_buffer_data->timestamp_query_pool)); 20888a1362adSmaya if (count == 1) { 20898a1362adSmaya unmap_object(HKEY(cmd_buffer_data->timestamp_query_pool)); 20908a1362adSmaya device_data->vtable.DestroyQueryPool(device_data->device, 20918a1362adSmaya cmd_buffer_data->timestamp_query_pool, NULL); 20928a1362adSmaya } else if (count != 0) { 20938a1362adSmaya map_object(HKEY(cmd_buffer_data->timestamp_query_pool), (void *)(uintptr_t)(count - 1)); 20948a1362adSmaya } 20958a1362adSmaya destroy_command_buffer_data(cmd_buffer_data); 20968a1362adSmaya } 20978a1362adSmaya 20988a1362adSmaya device_data->vtable.FreeCommandBuffers(device, commandPool, 20998a1362adSmaya commandBufferCount, pCommandBuffers); 21008a1362adSmaya} 21018a1362adSmaya 21028a1362adSmayastatic VkResult overlay_QueueSubmit( 21038a1362adSmaya VkQueue queue, 21048a1362adSmaya uint32_t submitCount, 21058a1362adSmaya const VkSubmitInfo* pSubmits, 21068a1362adSmaya VkFence fence) 21078a1362adSmaya{ 21088a1362adSmaya struct queue_data *queue_data = FIND_QUEUE_DATA(queue); 21098a1362adSmaya struct device_data *device_data = queue_data->device; 21108a1362adSmaya 21118a1362adSmaya device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_submit]++; 21128a1362adSmaya 21138a1362adSmaya for (uint32_t s = 0; s < submitCount; s++) { 21148a1362adSmaya for (uint32_t c = 0; c < pSubmits[s].commandBufferCount; c++) { 21158a1362adSmaya struct command_buffer_data *cmd_buffer_data = 21168a1362adSmaya FIND_CMD_BUFFER_DATA(pSubmits[s].pCommandBuffers[c]); 21178a1362adSmaya 21188a1362adSmaya /* Merge the submitted command buffer stats into the device. */ 21198a1362adSmaya for (uint32_t st = 0; st < OVERLAY_PARAM_ENABLED_MAX; st++) 21208a1362adSmaya device_data->frame_stats.stats[st] += cmd_buffer_data->stats.stats[st]; 21218a1362adSmaya 21228a1362adSmaya /* Attach the command buffer to the queue so we remember to read its 21238a1362adSmaya * pipeline statistics & timestamps at QueuePresent(). 21248a1362adSmaya */ 21258a1362adSmaya if (!cmd_buffer_data->pipeline_query_pool && 21268a1362adSmaya !cmd_buffer_data->timestamp_query_pool) 21278a1362adSmaya continue; 21288a1362adSmaya 21298a1362adSmaya if (list_empty(&cmd_buffer_data->link)) { 21308a1362adSmaya list_addtail(&cmd_buffer_data->link, 21318a1362adSmaya &queue_data->running_command_buffer); 21328a1362adSmaya } else { 21338a1362adSmaya fprintf(stderr, "Command buffer submitted multiple times before present.\n" 21348a1362adSmaya "This could lead to invalid data.\n"); 21358a1362adSmaya } 21368a1362adSmaya } 21378a1362adSmaya } 21388a1362adSmaya 21398a1362adSmaya return device_data->vtable.QueueSubmit(queue, submitCount, pSubmits, fence); 21408a1362adSmaya} 21418a1362adSmaya 21428a1362adSmayastatic VkResult overlay_CreateDevice( 21438a1362adSmaya VkPhysicalDevice physicalDevice, 21448a1362adSmaya const VkDeviceCreateInfo* pCreateInfo, 21458a1362adSmaya const VkAllocationCallbacks* pAllocator, 21468a1362adSmaya VkDevice* pDevice) 21478a1362adSmaya{ 21488a1362adSmaya struct instance_data *instance_data = FIND_PHYSICAL_DEVICE_DATA(physicalDevice); 21498a1362adSmaya VkLayerDeviceCreateInfo *chain_info = 21508a1362adSmaya get_device_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 21518a1362adSmaya 21528a1362adSmaya assert(chain_info->u.pLayerInfo); 21538a1362adSmaya PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 21548a1362adSmaya PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 21558a1362adSmaya PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice"); 21568a1362adSmaya if (fpCreateDevice == NULL) { 21578a1362adSmaya return VK_ERROR_INITIALIZATION_FAILED; 21588a1362adSmaya } 21598a1362adSmaya 21608a1362adSmaya // Advance the link info for the next element on the chain 21618a1362adSmaya chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 21628a1362adSmaya 21638a1362adSmaya VkPhysicalDeviceFeatures device_features = {}; 21648a1362adSmaya VkDeviceCreateInfo device_info = *pCreateInfo; 21658a1362adSmaya 21668a1362adSmaya if (pCreateInfo->pEnabledFeatures) 21678a1362adSmaya device_features = *(pCreateInfo->pEnabledFeatures); 21688a1362adSmaya if (instance_data->pipeline_statistics_enabled) { 21698a1362adSmaya device_features.inheritedQueries = true; 21708a1362adSmaya device_features.pipelineStatisticsQuery = true; 21718a1362adSmaya } 21728a1362adSmaya device_info.pEnabledFeatures = &device_features; 21738a1362adSmaya 21748a1362adSmaya 21758a1362adSmaya VkResult result = fpCreateDevice(physicalDevice, &device_info, pAllocator, pDevice); 21768a1362adSmaya if (result != VK_SUCCESS) return result; 21778a1362adSmaya 21788a1362adSmaya struct device_data *device_data = new_device_data(*pDevice, instance_data); 21798a1362adSmaya device_data->physical_device = physicalDevice; 21808a1362adSmaya vk_load_device_commands(*pDevice, fpGetDeviceProcAddr, &device_data->vtable); 21818a1362adSmaya 21828a1362adSmaya instance_data->vtable.GetPhysicalDeviceProperties(device_data->physical_device, 21838a1362adSmaya &device_data->properties); 21848a1362adSmaya 21858a1362adSmaya VkLayerDeviceCreateInfo *load_data_info = 21868a1362adSmaya get_device_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK); 21878a1362adSmaya device_data->set_device_loader_data = load_data_info->u.pfnSetDeviceLoaderData; 21888a1362adSmaya 21898a1362adSmaya device_map_queues(device_data, pCreateInfo); 21908a1362adSmaya 21918a1362adSmaya return result; 21928a1362adSmaya} 21938a1362adSmaya 21948a1362adSmayastatic void overlay_DestroyDevice( 21958a1362adSmaya VkDevice device, 21968a1362adSmaya const VkAllocationCallbacks* pAllocator) 21978a1362adSmaya{ 21988a1362adSmaya struct device_data *device_data = FIND_DEVICE_DATA(device); 21998a1362adSmaya device_unmap_queues(device_data); 22008a1362adSmaya device_data->vtable.DestroyDevice(device, pAllocator); 22018a1362adSmaya destroy_device_data(device_data); 22028a1362adSmaya} 22038a1362adSmaya 22048a1362adSmayastatic VkResult overlay_CreateInstance( 22058a1362adSmaya const VkInstanceCreateInfo* pCreateInfo, 22068a1362adSmaya const VkAllocationCallbacks* pAllocator, 22078a1362adSmaya VkInstance* pInstance) 22088a1362adSmaya{ 22098a1362adSmaya VkLayerInstanceCreateInfo *chain_info = 22108a1362adSmaya get_instance_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 22118a1362adSmaya 22128a1362adSmaya assert(chain_info->u.pLayerInfo); 22138a1362adSmaya PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = 22148a1362adSmaya chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 22158a1362adSmaya PFN_vkCreateInstance fpCreateInstance = 22168a1362adSmaya (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 22178a1362adSmaya if (fpCreateInstance == NULL) { 22188a1362adSmaya return VK_ERROR_INITIALIZATION_FAILED; 22198a1362adSmaya } 22208a1362adSmaya 22218a1362adSmaya // Advance the link info for the next element on the chain 22228a1362adSmaya chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 22238a1362adSmaya 22248a1362adSmaya VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 22258a1362adSmaya if (result != VK_SUCCESS) return result; 22268a1362adSmaya 22278a1362adSmaya struct instance_data *instance_data = new_instance_data(*pInstance); 22288a1362adSmaya vk_load_instance_commands(instance_data->instance, 22298a1362adSmaya fpGetInstanceProcAddr, 22308a1362adSmaya &instance_data->vtable); 22318a1362adSmaya instance_data_map_physical_devices(instance_data, true); 22328a1362adSmaya 22338a1362adSmaya parse_overlay_env(&instance_data->params, getenv("VK_LAYER_MESA_OVERLAY_CONFIG")); 22348a1362adSmaya 22358a1362adSmaya for (int i = OVERLAY_PARAM_ENABLED_vertices; 22368a1362adSmaya i <= OVERLAY_PARAM_ENABLED_compute_invocations; i++) { 22378a1362adSmaya if (instance_data->params.enabled[i]) { 22388a1362adSmaya instance_data->pipeline_statistics_enabled = true; 22398a1362adSmaya break; 22408a1362adSmaya } 22418a1362adSmaya } 22428a1362adSmaya 22438a1362adSmaya return result; 22448a1362adSmaya} 22458a1362adSmaya 22468a1362adSmayastatic void overlay_DestroyInstance( 22478a1362adSmaya VkInstance instance, 22488a1362adSmaya const VkAllocationCallbacks* pAllocator) 22498a1362adSmaya{ 22508a1362adSmaya struct instance_data *instance_data = FIND_INSTANCE_DATA(instance); 22518a1362adSmaya instance_data_map_physical_devices(instance_data, false); 22528a1362adSmaya instance_data->vtable.DestroyInstance(instance, pAllocator); 22538a1362adSmaya destroy_instance_data(instance_data); 22548a1362adSmaya} 22558a1362adSmaya 22568a1362adSmayastatic const struct { 22578a1362adSmaya const char *name; 22588a1362adSmaya void *ptr; 22598a1362adSmaya} name_to_funcptr_map[] = { 22608a1362adSmaya { "vkGetDeviceProcAddr", (void *) vkGetDeviceProcAddr }, 22618a1362adSmaya#define ADD_HOOK(fn) { "vk" # fn, (void *) overlay_ ## fn } 22628a1362adSmaya ADD_HOOK(AllocateCommandBuffers), 22638a1362adSmaya ADD_HOOK(FreeCommandBuffers), 22648a1362adSmaya ADD_HOOK(ResetCommandBuffer), 22658a1362adSmaya ADD_HOOK(BeginCommandBuffer), 22668a1362adSmaya ADD_HOOK(EndCommandBuffer), 22678a1362adSmaya ADD_HOOK(CmdExecuteCommands), 22688a1362adSmaya 22698a1362adSmaya ADD_HOOK(CmdDraw), 22708a1362adSmaya ADD_HOOK(CmdDrawIndexed), 22718a1362adSmaya ADD_HOOK(CmdDrawIndirect), 22728a1362adSmaya ADD_HOOK(CmdDrawIndexedIndirect), 22738a1362adSmaya ADD_HOOK(CmdDispatch), 22748a1362adSmaya ADD_HOOK(CmdDispatchIndirect), 22758a1362adSmaya ADD_HOOK(CmdDrawIndirectCountKHR), 22768a1362adSmaya ADD_HOOK(CmdDrawIndexedIndirectCountKHR), 22778a1362adSmaya 22788a1362adSmaya ADD_HOOK(CmdBindPipeline), 22798a1362adSmaya 22808a1362adSmaya ADD_HOOK(CreateSwapchainKHR), 22818a1362adSmaya ADD_HOOK(QueuePresentKHR), 22828a1362adSmaya ADD_HOOK(DestroySwapchainKHR), 22838a1362adSmaya ADD_HOOK(AcquireNextImageKHR), 22848a1362adSmaya ADD_HOOK(AcquireNextImage2KHR), 22858a1362adSmaya 22868a1362adSmaya ADD_HOOK(QueueSubmit), 22878a1362adSmaya 22888a1362adSmaya ADD_HOOK(CreateDevice), 22898a1362adSmaya ADD_HOOK(DestroyDevice), 22908a1362adSmaya 22918a1362adSmaya ADD_HOOK(CreateInstance), 22928a1362adSmaya ADD_HOOK(DestroyInstance), 22938a1362adSmaya#undef ADD_HOOK 22948a1362adSmaya}; 22958a1362adSmaya 22968a1362adSmayastatic void *find_ptr(const char *name) 22978a1362adSmaya{ 22988a1362adSmaya for (uint32_t i = 0; i < ARRAY_SIZE(name_to_funcptr_map); i++) { 22998a1362adSmaya if (strcmp(name, name_to_funcptr_map[i].name) == 0) 23008a1362adSmaya return name_to_funcptr_map[i].ptr; 23018a1362adSmaya } 23028a1362adSmaya 23038a1362adSmaya return NULL; 23048a1362adSmaya} 23058a1362adSmaya 23068a1362adSmayaVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, 23078a1362adSmaya const char *funcName) 23088a1362adSmaya{ 23098a1362adSmaya void *ptr = find_ptr(funcName); 23108a1362adSmaya if (ptr) return reinterpret_cast<PFN_vkVoidFunction>(ptr); 23118a1362adSmaya 23128a1362adSmaya if (dev == NULL) return NULL; 23138a1362adSmaya 23148a1362adSmaya struct device_data *device_data = FIND_DEVICE_DATA(dev); 23158a1362adSmaya if (device_data->vtable.GetDeviceProcAddr == NULL) return NULL; 23168a1362adSmaya return device_data->vtable.GetDeviceProcAddr(dev, funcName); 23178a1362adSmaya} 23188a1362adSmaya 23198a1362adSmayaVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, 23208a1362adSmaya const char *funcName) 23218a1362adSmaya{ 23228a1362adSmaya void *ptr = find_ptr(funcName); 23238a1362adSmaya if (ptr) return reinterpret_cast<PFN_vkVoidFunction>(ptr); 23248a1362adSmaya 23258a1362adSmaya if (instance == NULL) return NULL; 23268a1362adSmaya 23278a1362adSmaya struct instance_data *instance_data = FIND_INSTANCE_DATA(instance); 23288a1362adSmaya if (instance_data->vtable.GetInstanceProcAddr == NULL) return NULL; 23298a1362adSmaya return instance_data->vtable.GetInstanceProcAddr(instance, funcName); 23308a1362adSmaya} 2331