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 317ec681f3Smrg#include "git_sha1.h" 327ec681f3Smrg 338a1362adSmaya#include "imgui.h" 348a1362adSmaya 358a1362adSmaya#include "overlay_params.h" 368a1362adSmaya 378a1362adSmaya#include "util/debug.h" 388a1362adSmaya#include "util/hash_table.h" 398a1362adSmaya#include "util/list.h" 408a1362adSmaya#include "util/ralloc.h" 418a1362adSmaya#include "util/os_time.h" 427ec681f3Smrg#include "util/os_socket.h" 438a1362adSmaya#include "util/simple_mtx.h" 447ec681f3Smrg#include "util/u_math.h" 458a1362adSmaya 468a1362adSmaya#include "vk_enum_to_str.h" 477ec681f3Smrg#include "vk_dispatch_table.h" 488a1362adSmaya#include "vk_util.h" 498a1362adSmaya 508a1362adSmaya/* Mapped from VkInstace/VkPhysicalDevice */ 518a1362adSmayastruct instance_data { 528a1362adSmaya struct vk_instance_dispatch_table vtable; 537ec681f3Smrg struct vk_physical_device_dispatch_table pd_vtable; 548a1362adSmaya VkInstance instance; 558a1362adSmaya 568a1362adSmaya struct overlay_params params; 578a1362adSmaya bool pipeline_statistics_enabled; 588a1362adSmaya 598a1362adSmaya bool first_line_printed; 607ec681f3Smrg 617ec681f3Smrg int control_client; 627ec681f3Smrg 637ec681f3Smrg /* Dumping of frame stats to a file has been enabled. */ 647ec681f3Smrg bool capture_enabled; 657ec681f3Smrg 667ec681f3Smrg /* Dumping of frame stats to a file has been enabled and started. */ 677ec681f3Smrg bool capture_started; 688a1362adSmaya}; 698a1362adSmaya 708a1362adSmayastruct frame_stat { 718a1362adSmaya uint64_t stats[OVERLAY_PARAM_ENABLED_MAX]; 728a1362adSmaya}; 738a1362adSmaya 748a1362adSmaya/* Mapped from VkDevice */ 758a1362adSmayastruct queue_data; 768a1362adSmayastruct device_data { 778a1362adSmaya struct instance_data *instance; 788a1362adSmaya 798a1362adSmaya PFN_vkSetDeviceLoaderData set_device_loader_data; 808a1362adSmaya 818a1362adSmaya struct vk_device_dispatch_table vtable; 828a1362adSmaya VkPhysicalDevice physical_device; 838a1362adSmaya VkDevice device; 848a1362adSmaya 858a1362adSmaya VkPhysicalDeviceProperties properties; 868a1362adSmaya 878a1362adSmaya struct queue_data *graphic_queue; 888a1362adSmaya 898a1362adSmaya struct queue_data **queues; 908a1362adSmaya uint32_t n_queues; 918a1362adSmaya 928a1362adSmaya /* For a single frame */ 938a1362adSmaya struct frame_stat frame_stats; 948a1362adSmaya}; 958a1362adSmaya 968a1362adSmaya/* Mapped from VkCommandBuffer */ 978a1362adSmayastruct command_buffer_data { 988a1362adSmaya struct device_data *device; 998a1362adSmaya 1008a1362adSmaya VkCommandBufferLevel level; 1018a1362adSmaya 1028a1362adSmaya VkCommandBuffer cmd_buffer; 1038a1362adSmaya VkQueryPool pipeline_query_pool; 1048a1362adSmaya VkQueryPool timestamp_query_pool; 1058a1362adSmaya uint32_t query_index; 1068a1362adSmaya 1078a1362adSmaya struct frame_stat stats; 1088a1362adSmaya 1098a1362adSmaya struct list_head link; /* link into queue_data::running_command_buffer */ 1108a1362adSmaya}; 1118a1362adSmaya 1128a1362adSmaya/* Mapped from VkQueue */ 1138a1362adSmayastruct queue_data { 1148a1362adSmaya struct device_data *device; 1158a1362adSmaya 1168a1362adSmaya VkQueue queue; 1178a1362adSmaya VkQueueFlags flags; 1188a1362adSmaya uint32_t family_index; 1198a1362adSmaya uint64_t timestamp_mask; 1208a1362adSmaya 1218a1362adSmaya VkFence queries_fence; 1228a1362adSmaya 1238a1362adSmaya struct list_head running_command_buffer; 1248a1362adSmaya}; 1258a1362adSmaya 1268a1362adSmayastruct overlay_draw { 1278a1362adSmaya struct list_head link; 1288a1362adSmaya 1298a1362adSmaya VkCommandBuffer command_buffer; 1308a1362adSmaya 1317ec681f3Smrg VkSemaphore cross_engine_semaphore; 1327ec681f3Smrg 1338a1362adSmaya VkSemaphore semaphore; 1348a1362adSmaya VkFence fence; 1358a1362adSmaya 1368a1362adSmaya VkBuffer vertex_buffer; 1378a1362adSmaya VkDeviceMemory vertex_buffer_mem; 1388a1362adSmaya VkDeviceSize vertex_buffer_size; 1398a1362adSmaya 1408a1362adSmaya VkBuffer index_buffer; 1418a1362adSmaya VkDeviceMemory index_buffer_mem; 1428a1362adSmaya VkDeviceSize index_buffer_size; 1438a1362adSmaya}; 1448a1362adSmaya 1458a1362adSmaya/* Mapped from VkSwapchainKHR */ 1468a1362adSmayastruct swapchain_data { 1478a1362adSmaya struct device_data *device; 1488a1362adSmaya 1498a1362adSmaya VkSwapchainKHR swapchain; 1508a1362adSmaya unsigned width, height; 1518a1362adSmaya VkFormat format; 1528a1362adSmaya 1538a1362adSmaya uint32_t n_images; 1548a1362adSmaya VkImage *images; 1558a1362adSmaya VkImageView *image_views; 1568a1362adSmaya VkFramebuffer *framebuffers; 1578a1362adSmaya 1588a1362adSmaya VkRenderPass render_pass; 1598a1362adSmaya 1608a1362adSmaya VkDescriptorPool descriptor_pool; 1618a1362adSmaya VkDescriptorSetLayout descriptor_layout; 1628a1362adSmaya VkDescriptorSet descriptor_set; 1638a1362adSmaya 1648a1362adSmaya VkSampler font_sampler; 1658a1362adSmaya 1668a1362adSmaya VkPipelineLayout pipeline_layout; 1678a1362adSmaya VkPipeline pipeline; 1688a1362adSmaya 1698a1362adSmaya VkCommandPool command_pool; 1708a1362adSmaya 1718a1362adSmaya struct list_head draws; /* List of struct overlay_draw */ 1728a1362adSmaya 1738a1362adSmaya bool font_uploaded; 1748a1362adSmaya VkImage font_image; 1758a1362adSmaya VkImageView font_image_view; 1768a1362adSmaya VkDeviceMemory font_mem; 1778a1362adSmaya VkBuffer upload_font_buffer; 1788a1362adSmaya VkDeviceMemory upload_font_buffer_mem; 1798a1362adSmaya 1808a1362adSmaya /**/ 1818a1362adSmaya ImGuiContext* imgui_context; 1828a1362adSmaya ImVec2 window_size; 1838a1362adSmaya 1848a1362adSmaya /**/ 1858a1362adSmaya uint64_t n_frames; 1868a1362adSmaya uint64_t last_present_time; 1878a1362adSmaya 1888a1362adSmaya unsigned n_frames_since_update; 1898a1362adSmaya uint64_t last_fps_update; 1908a1362adSmaya double fps; 1918a1362adSmaya 1928a1362adSmaya enum overlay_param_enabled stat_selector; 1938a1362adSmaya double time_dividor; 1948a1362adSmaya struct frame_stat stats_min, stats_max; 1958a1362adSmaya struct frame_stat frames_stats[200]; 1968a1362adSmaya 1978a1362adSmaya /* Over a single frame */ 1988a1362adSmaya struct frame_stat frame_stats; 1998a1362adSmaya 2008a1362adSmaya /* Over fps_sampling_period */ 2018a1362adSmaya struct frame_stat accumulated_stats; 2028a1362adSmaya}; 2038a1362adSmaya 2048a1362adSmayastatic const VkQueryPipelineStatisticFlags overlay_query_flags = 2058a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT | 2068a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT | 2078a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | 2088a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT | 2098a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT | 2108a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT | 2118a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT | 2128a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT | 2138a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT | 2148a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT | 2158a1362adSmaya VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT; 2168a1362adSmaya#define OVERLAY_QUERY_COUNT (11) 2178a1362adSmaya 2188a1362adSmayastatic struct hash_table_u64 *vk_object_to_data = NULL; 2198a1362adSmayastatic simple_mtx_t vk_object_to_data_mutex = _SIMPLE_MTX_INITIALIZER_NP; 2208a1362adSmaya 2218a1362adSmayathread_local ImGuiContext* __MesaImGui; 2228a1362adSmaya 2238a1362adSmayastatic inline void ensure_vk_object_map(void) 2248a1362adSmaya{ 2258a1362adSmaya if (!vk_object_to_data) 2268a1362adSmaya vk_object_to_data = _mesa_hash_table_u64_create(NULL); 2278a1362adSmaya} 2288a1362adSmaya 2298a1362adSmaya#define HKEY(obj) ((uint64_t)(obj)) 2307ec681f3Smrg#define FIND(type, obj) ((type *)find_object_data(HKEY(obj))) 2317ec681f3Smrg 2328a1362adSmayastatic void *find_object_data(uint64_t obj) 2338a1362adSmaya{ 2348a1362adSmaya simple_mtx_lock(&vk_object_to_data_mutex); 2358a1362adSmaya ensure_vk_object_map(); 2368a1362adSmaya void *data = _mesa_hash_table_u64_search(vk_object_to_data, obj); 2378a1362adSmaya simple_mtx_unlock(&vk_object_to_data_mutex); 2388a1362adSmaya return data; 2398a1362adSmaya} 2408a1362adSmaya 2418a1362adSmayastatic void map_object(uint64_t obj, void *data) 2428a1362adSmaya{ 2438a1362adSmaya simple_mtx_lock(&vk_object_to_data_mutex); 2448a1362adSmaya ensure_vk_object_map(); 2458a1362adSmaya _mesa_hash_table_u64_insert(vk_object_to_data, obj, data); 2468a1362adSmaya simple_mtx_unlock(&vk_object_to_data_mutex); 2478a1362adSmaya} 2488a1362adSmaya 2498a1362adSmayastatic void unmap_object(uint64_t obj) 2508a1362adSmaya{ 2518a1362adSmaya simple_mtx_lock(&vk_object_to_data_mutex); 2528a1362adSmaya _mesa_hash_table_u64_remove(vk_object_to_data, obj); 2538a1362adSmaya simple_mtx_unlock(&vk_object_to_data_mutex); 2548a1362adSmaya} 2558a1362adSmaya 2568a1362adSmaya/**/ 2578a1362adSmaya 2588a1362adSmaya#define VK_CHECK(expr) \ 2598a1362adSmaya do { \ 2608a1362adSmaya VkResult __result = (expr); \ 2618a1362adSmaya if (__result != VK_SUCCESS) { \ 2628a1362adSmaya fprintf(stderr, "'%s' line %i failed with %s\n", \ 2638a1362adSmaya #expr, __LINE__, vk_Result_to_str(__result)); \ 2648a1362adSmaya } \ 2658a1362adSmaya } while (0) 2668a1362adSmaya 2678a1362adSmaya/**/ 2688a1362adSmaya 2698a1362adSmayastatic VkLayerInstanceCreateInfo *get_instance_chain_info(const VkInstanceCreateInfo *pCreateInfo, 2708a1362adSmaya VkLayerFunction func) 2718a1362adSmaya{ 2728a1362adSmaya vk_foreach_struct(item, pCreateInfo->pNext) { 2738a1362adSmaya if (item->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && 2748a1362adSmaya ((VkLayerInstanceCreateInfo *) item)->function == func) 2758a1362adSmaya return (VkLayerInstanceCreateInfo *) item; 2768a1362adSmaya } 2778a1362adSmaya unreachable("instance chain info not found"); 2788a1362adSmaya return NULL; 2798a1362adSmaya} 2808a1362adSmaya 2818a1362adSmayastatic VkLayerDeviceCreateInfo *get_device_chain_info(const VkDeviceCreateInfo *pCreateInfo, 2828a1362adSmaya VkLayerFunction func) 2838a1362adSmaya{ 2848a1362adSmaya vk_foreach_struct(item, pCreateInfo->pNext) { 2858a1362adSmaya if (item->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && 2868a1362adSmaya ((VkLayerDeviceCreateInfo *) item)->function == func) 2878a1362adSmaya return (VkLayerDeviceCreateInfo *)item; 2888a1362adSmaya } 2898a1362adSmaya unreachable("device chain info not found"); 2908a1362adSmaya return NULL; 2918a1362adSmaya} 2928a1362adSmaya 2938a1362adSmayastatic struct VkBaseOutStructure * 2948a1362adSmayaclone_chain(const struct VkBaseInStructure *chain) 2958a1362adSmaya{ 2968a1362adSmaya struct VkBaseOutStructure *head = NULL, *tail = NULL; 2978a1362adSmaya 2988a1362adSmaya vk_foreach_struct_const(item, chain) { 2998a1362adSmaya size_t item_size = vk_structure_type_size(item); 3008a1362adSmaya struct VkBaseOutStructure *new_item = 3018a1362adSmaya (struct VkBaseOutStructure *)malloc(item_size);; 3028a1362adSmaya 3038a1362adSmaya memcpy(new_item, item, item_size); 3048a1362adSmaya 3058a1362adSmaya if (!head) 3068a1362adSmaya head = new_item; 3078a1362adSmaya if (tail) 3088a1362adSmaya tail->pNext = new_item; 3098a1362adSmaya tail = new_item; 3108a1362adSmaya } 3118a1362adSmaya 3128a1362adSmaya return head; 3138a1362adSmaya} 3148a1362adSmaya 3158a1362adSmayastatic void 3168a1362adSmayafree_chain(struct VkBaseOutStructure *chain) 3178a1362adSmaya{ 3188a1362adSmaya while (chain) { 3198a1362adSmaya void *node = chain; 3208a1362adSmaya chain = chain->pNext; 3218a1362adSmaya free(node); 3228a1362adSmaya } 3238a1362adSmaya} 3248a1362adSmaya 3258a1362adSmaya/**/ 3268a1362adSmaya 3278a1362adSmayastatic struct instance_data *new_instance_data(VkInstance instance) 3288a1362adSmaya{ 3298a1362adSmaya struct instance_data *data = rzalloc(NULL, struct instance_data); 3308a1362adSmaya data->instance = instance; 3317ec681f3Smrg data->control_client = -1; 3328a1362adSmaya map_object(HKEY(data->instance), data); 3338a1362adSmaya return data; 3348a1362adSmaya} 3358a1362adSmaya 3368a1362adSmayastatic void destroy_instance_data(struct instance_data *data) 3378a1362adSmaya{ 3388a1362adSmaya if (data->params.output_file) 3398a1362adSmaya fclose(data->params.output_file); 3407ec681f3Smrg if (data->params.control >= 0) 3417ec681f3Smrg os_socket_close(data->params.control); 3428a1362adSmaya unmap_object(HKEY(data->instance)); 3438a1362adSmaya ralloc_free(data); 3448a1362adSmaya} 3458a1362adSmaya 3468a1362adSmayastatic void instance_data_map_physical_devices(struct instance_data *instance_data, 3478a1362adSmaya bool map) 3488a1362adSmaya{ 3498a1362adSmaya uint32_t physicalDeviceCount = 0; 3508a1362adSmaya instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, 3518a1362adSmaya &physicalDeviceCount, 3528a1362adSmaya NULL); 3538a1362adSmaya 3548a1362adSmaya VkPhysicalDevice *physicalDevices = (VkPhysicalDevice *) malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); 3558a1362adSmaya instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, 3568a1362adSmaya &physicalDeviceCount, 3578a1362adSmaya physicalDevices); 3588a1362adSmaya 3598a1362adSmaya for (uint32_t i = 0; i < physicalDeviceCount; i++) { 3608a1362adSmaya if (map) 3618a1362adSmaya map_object(HKEY(physicalDevices[i]), instance_data); 3628a1362adSmaya else 3638a1362adSmaya unmap_object(HKEY(physicalDevices[i])); 3648a1362adSmaya } 3658a1362adSmaya 3668a1362adSmaya free(physicalDevices); 3678a1362adSmaya} 3688a1362adSmaya 3698a1362adSmaya/**/ 3708a1362adSmayastatic struct device_data *new_device_data(VkDevice device, struct instance_data *instance) 3718a1362adSmaya{ 3728a1362adSmaya struct device_data *data = rzalloc(NULL, struct device_data); 3738a1362adSmaya data->instance = instance; 3748a1362adSmaya data->device = device; 3758a1362adSmaya map_object(HKEY(data->device), data); 3768a1362adSmaya return data; 3778a1362adSmaya} 3788a1362adSmaya 3798a1362adSmayastatic struct queue_data *new_queue_data(VkQueue queue, 3808a1362adSmaya const VkQueueFamilyProperties *family_props, 3818a1362adSmaya uint32_t family_index, 3828a1362adSmaya struct device_data *device_data) 3838a1362adSmaya{ 3848a1362adSmaya struct queue_data *data = rzalloc(device_data, struct queue_data); 3858a1362adSmaya data->device = device_data; 3868a1362adSmaya data->queue = queue; 3878a1362adSmaya data->flags = family_props->queueFlags; 3888a1362adSmaya data->timestamp_mask = (1ull << family_props->timestampValidBits) - 1; 3898a1362adSmaya data->family_index = family_index; 3907ec681f3Smrg list_inithead(&data->running_command_buffer); 3918a1362adSmaya map_object(HKEY(data->queue), data); 3928a1362adSmaya 3938a1362adSmaya /* Fence synchronizing access to queries on that queue. */ 3948a1362adSmaya VkFenceCreateInfo fence_info = {}; 3958a1362adSmaya fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 3968a1362adSmaya fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; 3977ec681f3Smrg VK_CHECK(device_data->vtable.CreateFence(device_data->device, 3987ec681f3Smrg &fence_info, 3997ec681f3Smrg NULL, 4007ec681f3Smrg &data->queries_fence)); 4018a1362adSmaya 4028a1362adSmaya if (data->flags & VK_QUEUE_GRAPHICS_BIT) 4038a1362adSmaya device_data->graphic_queue = data; 4048a1362adSmaya 4058a1362adSmaya return data; 4068a1362adSmaya} 4078a1362adSmaya 4088a1362adSmayastatic void destroy_queue(struct queue_data *data) 4098a1362adSmaya{ 4108a1362adSmaya struct device_data *device_data = data->device; 4118a1362adSmaya device_data->vtable.DestroyFence(device_data->device, data->queries_fence, NULL); 4128a1362adSmaya unmap_object(HKEY(data->queue)); 4138a1362adSmaya ralloc_free(data); 4148a1362adSmaya} 4158a1362adSmaya 4168a1362adSmayastatic void device_map_queues(struct device_data *data, 4178a1362adSmaya const VkDeviceCreateInfo *pCreateInfo) 4188a1362adSmaya{ 4198a1362adSmaya for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) 4208a1362adSmaya data->n_queues += pCreateInfo->pQueueCreateInfos[i].queueCount; 4218a1362adSmaya data->queues = ralloc_array(data, struct queue_data *, data->n_queues); 4228a1362adSmaya 4238a1362adSmaya struct instance_data *instance_data = data->instance; 4248a1362adSmaya uint32_t n_family_props; 4257ec681f3Smrg instance_data->pd_vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, 4267ec681f3Smrg &n_family_props, 4277ec681f3Smrg NULL); 4288a1362adSmaya VkQueueFamilyProperties *family_props = 4298a1362adSmaya (VkQueueFamilyProperties *)malloc(sizeof(VkQueueFamilyProperties) * n_family_props); 4307ec681f3Smrg instance_data->pd_vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, 4317ec681f3Smrg &n_family_props, 4327ec681f3Smrg family_props); 4338a1362adSmaya 4348a1362adSmaya uint32_t queue_index = 0; 4358a1362adSmaya for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { 4368a1362adSmaya for (uint32_t j = 0; j < pCreateInfo->pQueueCreateInfos[i].queueCount; j++) { 4378a1362adSmaya VkQueue queue; 4388a1362adSmaya data->vtable.GetDeviceQueue(data->device, 4398a1362adSmaya pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, 4408a1362adSmaya j, &queue); 4418a1362adSmaya 4428a1362adSmaya VK_CHECK(data->set_device_loader_data(data->device, queue)); 4438a1362adSmaya 4448a1362adSmaya data->queues[queue_index++] = 4458a1362adSmaya new_queue_data(queue, &family_props[pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex], 4468a1362adSmaya pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, data); 4478a1362adSmaya } 4488a1362adSmaya } 4498a1362adSmaya 4508a1362adSmaya free(family_props); 4518a1362adSmaya} 4528a1362adSmaya 4538a1362adSmayastatic void device_unmap_queues(struct device_data *data) 4548a1362adSmaya{ 4558a1362adSmaya for (uint32_t i = 0; i < data->n_queues; i++) 4568a1362adSmaya destroy_queue(data->queues[i]); 4578a1362adSmaya} 4588a1362adSmaya 4598a1362adSmayastatic void destroy_device_data(struct device_data *data) 4608a1362adSmaya{ 4618a1362adSmaya unmap_object(HKEY(data->device)); 4628a1362adSmaya ralloc_free(data); 4638a1362adSmaya} 4648a1362adSmaya 4658a1362adSmaya/**/ 4668a1362adSmayastatic struct command_buffer_data *new_command_buffer_data(VkCommandBuffer cmd_buffer, 4678a1362adSmaya VkCommandBufferLevel level, 4688a1362adSmaya VkQueryPool pipeline_query_pool, 4698a1362adSmaya VkQueryPool timestamp_query_pool, 4708a1362adSmaya uint32_t query_index, 4718a1362adSmaya struct device_data *device_data) 4728a1362adSmaya{ 4738a1362adSmaya struct command_buffer_data *data = rzalloc(NULL, struct command_buffer_data); 4748a1362adSmaya data->device = device_data; 4758a1362adSmaya data->cmd_buffer = cmd_buffer; 4768a1362adSmaya data->level = level; 4778a1362adSmaya data->pipeline_query_pool = pipeline_query_pool; 4788a1362adSmaya data->timestamp_query_pool = timestamp_query_pool; 4798a1362adSmaya data->query_index = query_index; 4808a1362adSmaya list_inithead(&data->link); 4818a1362adSmaya map_object(HKEY(data->cmd_buffer), data); 4828a1362adSmaya return data; 4838a1362adSmaya} 4848a1362adSmaya 4858a1362adSmayastatic void destroy_command_buffer_data(struct command_buffer_data *data) 4868a1362adSmaya{ 4878a1362adSmaya unmap_object(HKEY(data->cmd_buffer)); 4888a1362adSmaya list_delinit(&data->link); 4898a1362adSmaya ralloc_free(data); 4908a1362adSmaya} 4918a1362adSmaya 4928a1362adSmaya/**/ 4938a1362adSmayastatic struct swapchain_data *new_swapchain_data(VkSwapchainKHR swapchain, 4948a1362adSmaya struct device_data *device_data) 4958a1362adSmaya{ 4968a1362adSmaya struct instance_data *instance_data = device_data->instance; 4978a1362adSmaya struct swapchain_data *data = rzalloc(NULL, struct swapchain_data); 4988a1362adSmaya data->device = device_data; 4998a1362adSmaya data->swapchain = swapchain; 5008a1362adSmaya data->window_size = ImVec2(instance_data->params.width, instance_data->params.height); 5018a1362adSmaya list_inithead(&data->draws); 5028a1362adSmaya map_object(HKEY(data->swapchain), data); 5038a1362adSmaya return data; 5048a1362adSmaya} 5058a1362adSmaya 5068a1362adSmayastatic void destroy_swapchain_data(struct swapchain_data *data) 5078a1362adSmaya{ 5088a1362adSmaya unmap_object(HKEY(data->swapchain)); 5098a1362adSmaya ralloc_free(data); 5108a1362adSmaya} 5118a1362adSmaya 5128a1362adSmayastruct overlay_draw *get_overlay_draw(struct swapchain_data *data) 5138a1362adSmaya{ 5148a1362adSmaya struct device_data *device_data = data->device; 5157ec681f3Smrg struct overlay_draw *draw = list_is_empty(&data->draws) ? 5168a1362adSmaya NULL : list_first_entry(&data->draws, struct overlay_draw, link); 5178a1362adSmaya 5188a1362adSmaya VkSemaphoreCreateInfo sem_info = {}; 5198a1362adSmaya sem_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 5208a1362adSmaya 5218a1362adSmaya if (draw && device_data->vtable.GetFenceStatus(device_data->device, draw->fence) == VK_SUCCESS) { 5228a1362adSmaya list_del(&draw->link); 5238a1362adSmaya VK_CHECK(device_data->vtable.ResetFences(device_data->device, 5248a1362adSmaya 1, &draw->fence)); 5258a1362adSmaya list_addtail(&draw->link, &data->draws); 5268a1362adSmaya return draw; 5278a1362adSmaya } 5288a1362adSmaya 5298a1362adSmaya draw = rzalloc(data, struct overlay_draw); 5308a1362adSmaya 5318a1362adSmaya VkCommandBufferAllocateInfo cmd_buffer_info = {}; 5328a1362adSmaya cmd_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 5338a1362adSmaya cmd_buffer_info.commandPool = data->command_pool; 5348a1362adSmaya cmd_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 5358a1362adSmaya cmd_buffer_info.commandBufferCount = 1; 5368a1362adSmaya VK_CHECK(device_data->vtable.AllocateCommandBuffers(device_data->device, 5378a1362adSmaya &cmd_buffer_info, 5388a1362adSmaya &draw->command_buffer)); 5398a1362adSmaya VK_CHECK(device_data->set_device_loader_data(device_data->device, 5408a1362adSmaya draw->command_buffer)); 5418a1362adSmaya 5428a1362adSmaya 5438a1362adSmaya VkFenceCreateInfo fence_info = {}; 5448a1362adSmaya fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 5458a1362adSmaya VK_CHECK(device_data->vtable.CreateFence(device_data->device, 5468a1362adSmaya &fence_info, 5478a1362adSmaya NULL, 5488a1362adSmaya &draw->fence)); 5498a1362adSmaya 5508a1362adSmaya VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, 5518a1362adSmaya NULL, &draw->semaphore)); 5527ec681f3Smrg VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, 5537ec681f3Smrg NULL, &draw->cross_engine_semaphore)); 5548a1362adSmaya 5558a1362adSmaya list_addtail(&draw->link, &data->draws); 5568a1362adSmaya 5578a1362adSmaya return draw; 5588a1362adSmaya} 5598a1362adSmaya 5608a1362adSmayastatic const char *param_unit(enum overlay_param_enabled param) 5618a1362adSmaya{ 5628a1362adSmaya switch (param) { 5638a1362adSmaya case OVERLAY_PARAM_ENABLED_frame_timing: 5648a1362adSmaya case OVERLAY_PARAM_ENABLED_acquire_timing: 5657ec681f3Smrg case OVERLAY_PARAM_ENABLED_present_timing: 5668a1362adSmaya return "(us)"; 5678a1362adSmaya case OVERLAY_PARAM_ENABLED_gpu_timing: 5688a1362adSmaya return "(ns)"; 5698a1362adSmaya default: 5708a1362adSmaya return ""; 5718a1362adSmaya } 5728a1362adSmaya} 5738a1362adSmaya 5747ec681f3Smrgstatic void parse_command(struct instance_data *instance_data, 5757ec681f3Smrg const char *cmd, unsigned cmdlen, 5767ec681f3Smrg const char *param, unsigned paramlen) 5777ec681f3Smrg{ 5787ec681f3Smrg if (!strncmp(cmd, "capture", cmdlen)) { 5797ec681f3Smrg int value = atoi(param); 5807ec681f3Smrg bool enabled = value > 0; 5817ec681f3Smrg 5827ec681f3Smrg if (enabled) { 5837ec681f3Smrg instance_data->capture_enabled = true; 5847ec681f3Smrg } else { 5857ec681f3Smrg instance_data->capture_enabled = false; 5867ec681f3Smrg instance_data->capture_started = false; 5877ec681f3Smrg } 5887ec681f3Smrg } 5897ec681f3Smrg} 5907ec681f3Smrg 5917ec681f3Smrg#define BUFSIZE 4096 5927ec681f3Smrg 5937ec681f3Smrg/** 5947ec681f3Smrg * This function will process commands through the control file. 5957ec681f3Smrg * 5967ec681f3Smrg * A command starts with a colon, followed by the command, and followed by an 5977ec681f3Smrg * option '=' and a parameter. It has to end with a semi-colon. A full command 5987ec681f3Smrg * + parameter looks like: 5997ec681f3Smrg * 6007ec681f3Smrg * :cmd=param; 6017ec681f3Smrg */ 6027ec681f3Smrgstatic void process_char(struct instance_data *instance_data, char c) 6037ec681f3Smrg{ 6047ec681f3Smrg static char cmd[BUFSIZE]; 6057ec681f3Smrg static char param[BUFSIZE]; 6067ec681f3Smrg 6077ec681f3Smrg static unsigned cmdpos = 0; 6087ec681f3Smrg static unsigned parampos = 0; 6097ec681f3Smrg static bool reading_cmd = false; 6107ec681f3Smrg static bool reading_param = false; 6117ec681f3Smrg 6127ec681f3Smrg switch (c) { 6137ec681f3Smrg case ':': 6147ec681f3Smrg cmdpos = 0; 6157ec681f3Smrg parampos = 0; 6167ec681f3Smrg reading_cmd = true; 6177ec681f3Smrg reading_param = false; 6187ec681f3Smrg break; 6197ec681f3Smrg case ';': 6207ec681f3Smrg if (!reading_cmd) 6217ec681f3Smrg break; 6227ec681f3Smrg cmd[cmdpos++] = '\0'; 6237ec681f3Smrg param[parampos++] = '\0'; 6247ec681f3Smrg parse_command(instance_data, cmd, cmdpos, param, parampos); 6257ec681f3Smrg reading_cmd = false; 6267ec681f3Smrg reading_param = false; 6277ec681f3Smrg break; 6287ec681f3Smrg case '=': 6297ec681f3Smrg if (!reading_cmd) 6307ec681f3Smrg break; 6317ec681f3Smrg reading_param = true; 6327ec681f3Smrg break; 6337ec681f3Smrg default: 6347ec681f3Smrg if (!reading_cmd) 6357ec681f3Smrg break; 6367ec681f3Smrg 6377ec681f3Smrg if (reading_param) { 6387ec681f3Smrg /* overflow means an invalid parameter */ 6397ec681f3Smrg if (parampos >= BUFSIZE - 1) { 6407ec681f3Smrg reading_cmd = false; 6417ec681f3Smrg reading_param = false; 6427ec681f3Smrg break; 6437ec681f3Smrg } 6447ec681f3Smrg 6457ec681f3Smrg param[parampos++] = c; 6467ec681f3Smrg } else { 6477ec681f3Smrg /* overflow means an invalid command */ 6487ec681f3Smrg if (cmdpos >= BUFSIZE - 1) { 6497ec681f3Smrg reading_cmd = false; 6507ec681f3Smrg break; 6517ec681f3Smrg } 6527ec681f3Smrg 6537ec681f3Smrg cmd[cmdpos++] = c; 6547ec681f3Smrg } 6557ec681f3Smrg } 6567ec681f3Smrg} 6577ec681f3Smrg 6587ec681f3Smrgstatic void control_send(struct instance_data *instance_data, 6597ec681f3Smrg const char *cmd, unsigned cmdlen, 6607ec681f3Smrg const char *param, unsigned paramlen) 6617ec681f3Smrg{ 6627ec681f3Smrg unsigned msglen = 0; 6637ec681f3Smrg char buffer[BUFSIZE]; 6647ec681f3Smrg 6657ec681f3Smrg assert(cmdlen + paramlen + 3 < BUFSIZE); 6667ec681f3Smrg 6677ec681f3Smrg buffer[msglen++] = ':'; 6687ec681f3Smrg 6697ec681f3Smrg memcpy(&buffer[msglen], cmd, cmdlen); 6707ec681f3Smrg msglen += cmdlen; 6717ec681f3Smrg 6727ec681f3Smrg if (paramlen > 0) { 6737ec681f3Smrg buffer[msglen++] = '='; 6747ec681f3Smrg memcpy(&buffer[msglen], param, paramlen); 6757ec681f3Smrg msglen += paramlen; 6767ec681f3Smrg buffer[msglen++] = ';'; 6777ec681f3Smrg } 6787ec681f3Smrg 6797ec681f3Smrg os_socket_send(instance_data->control_client, buffer, msglen, 0); 6807ec681f3Smrg} 6817ec681f3Smrg 6827ec681f3Smrgstatic void control_send_connection_string(struct device_data *device_data) 6837ec681f3Smrg{ 6847ec681f3Smrg struct instance_data *instance_data = device_data->instance; 6857ec681f3Smrg 6867ec681f3Smrg const char *controlVersionCmd = "MesaOverlayControlVersion"; 6877ec681f3Smrg const char *controlVersionString = "1"; 6887ec681f3Smrg 6897ec681f3Smrg control_send(instance_data, controlVersionCmd, strlen(controlVersionCmd), 6907ec681f3Smrg controlVersionString, strlen(controlVersionString)); 6917ec681f3Smrg 6927ec681f3Smrg const char *deviceCmd = "DeviceName"; 6937ec681f3Smrg const char *deviceName = device_data->properties.deviceName; 6947ec681f3Smrg 6957ec681f3Smrg control_send(instance_data, deviceCmd, strlen(deviceCmd), 6967ec681f3Smrg deviceName, strlen(deviceName)); 6977ec681f3Smrg 6987ec681f3Smrg const char *mesaVersionCmd = "MesaVersion"; 6997ec681f3Smrg const char *mesaVersionString = "Mesa " PACKAGE_VERSION MESA_GIT_SHA1; 7007ec681f3Smrg 7017ec681f3Smrg control_send(instance_data, mesaVersionCmd, strlen(mesaVersionCmd), 7027ec681f3Smrg mesaVersionString, strlen(mesaVersionString)); 7037ec681f3Smrg} 7047ec681f3Smrg 7057ec681f3Smrgstatic void control_client_check(struct device_data *device_data) 7067ec681f3Smrg{ 7077ec681f3Smrg struct instance_data *instance_data = device_data->instance; 7087ec681f3Smrg 7097ec681f3Smrg /* Already connected, just return. */ 7107ec681f3Smrg if (instance_data->control_client >= 0) 7117ec681f3Smrg return; 7127ec681f3Smrg 7137ec681f3Smrg int socket = os_socket_accept(instance_data->params.control); 7147ec681f3Smrg if (socket == -1) { 7157ec681f3Smrg if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ECONNABORTED) 7167ec681f3Smrg fprintf(stderr, "ERROR on socket: %s\n", strerror(errno)); 7177ec681f3Smrg return; 7187ec681f3Smrg } 7197ec681f3Smrg 7207ec681f3Smrg if (socket >= 0) { 7217ec681f3Smrg os_socket_block(socket, false); 7227ec681f3Smrg instance_data->control_client = socket; 7237ec681f3Smrg control_send_connection_string(device_data); 7247ec681f3Smrg } 7257ec681f3Smrg} 7267ec681f3Smrg 7277ec681f3Smrgstatic void control_client_disconnected(struct instance_data *instance_data) 7287ec681f3Smrg{ 7297ec681f3Smrg os_socket_close(instance_data->control_client); 7307ec681f3Smrg instance_data->control_client = -1; 7317ec681f3Smrg} 7327ec681f3Smrg 7337ec681f3Smrgstatic void process_control_socket(struct instance_data *instance_data) 7347ec681f3Smrg{ 7357ec681f3Smrg const int client = instance_data->control_client; 7367ec681f3Smrg if (client >= 0) { 7377ec681f3Smrg char buf[BUFSIZE]; 7387ec681f3Smrg 7397ec681f3Smrg while (true) { 7407ec681f3Smrg ssize_t n = os_socket_recv(client, buf, BUFSIZE, 0); 7417ec681f3Smrg 7427ec681f3Smrg if (n == -1) { 7437ec681f3Smrg if (errno == EAGAIN || errno == EWOULDBLOCK) { 7447ec681f3Smrg /* nothing to read, try again later */ 7457ec681f3Smrg break; 7467ec681f3Smrg } 7477ec681f3Smrg 7487ec681f3Smrg if (errno != ECONNRESET) 7497ec681f3Smrg fprintf(stderr, "ERROR on connection: %s\n", strerror(errno)); 7507ec681f3Smrg 7517ec681f3Smrg control_client_disconnected(instance_data); 7527ec681f3Smrg } else if (n == 0) { 7537ec681f3Smrg /* recv() returns 0 when the client disconnects */ 7547ec681f3Smrg control_client_disconnected(instance_data); 7557ec681f3Smrg } 7567ec681f3Smrg 7577ec681f3Smrg for (ssize_t i = 0; i < n; i++) { 7587ec681f3Smrg process_char(instance_data, buf[i]); 7597ec681f3Smrg } 7607ec681f3Smrg 7617ec681f3Smrg /* If we try to read BUFSIZE and receive BUFSIZE bytes from the 7627ec681f3Smrg * socket, there's a good chance that there's still more data to be 7637ec681f3Smrg * read, so we will try again. Otherwise, simply be done for this 7647ec681f3Smrg * iteration and try again on the next frame. 7657ec681f3Smrg */ 7667ec681f3Smrg if (n < BUFSIZE) 7677ec681f3Smrg break; 7687ec681f3Smrg } 7697ec681f3Smrg } 7707ec681f3Smrg} 7717ec681f3Smrg 7728a1362adSmayastatic void snapshot_swapchain_frame(struct swapchain_data *data) 7738a1362adSmaya{ 7748a1362adSmaya struct device_data *device_data = data->device; 7758a1362adSmaya struct instance_data *instance_data = device_data->instance; 7768a1362adSmaya uint32_t f_idx = data->n_frames % ARRAY_SIZE(data->frames_stats); 7778a1362adSmaya uint64_t now = os_time_get(); /* us */ 7788a1362adSmaya 7797ec681f3Smrg if (instance_data->params.control >= 0) { 7807ec681f3Smrg control_client_check(device_data); 7817ec681f3Smrg process_control_socket(instance_data); 7827ec681f3Smrg } 7837ec681f3Smrg 7848a1362adSmaya if (data->last_present_time) { 7858a1362adSmaya data->frame_stats.stats[OVERLAY_PARAM_ENABLED_frame_timing] = 7868a1362adSmaya now - data->last_present_time; 7878a1362adSmaya } 7888a1362adSmaya 7898a1362adSmaya memset(&data->frames_stats[f_idx], 0, sizeof(data->frames_stats[f_idx])); 7908a1362adSmaya for (int s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 7918a1362adSmaya data->frames_stats[f_idx].stats[s] += device_data->frame_stats.stats[s] + data->frame_stats.stats[s]; 7928a1362adSmaya data->accumulated_stats.stats[s] += device_data->frame_stats.stats[s] + data->frame_stats.stats[s]; 7938a1362adSmaya } 7948a1362adSmaya 7957ec681f3Smrg /* If capture has been enabled but it hasn't started yet, it means we are on 7967ec681f3Smrg * the first snapshot after it has been enabled. At this point we want to 7977ec681f3Smrg * use the stats captured so far to update the display, but we don't want 7987ec681f3Smrg * this data to cause noise to the stats that we want to capture from now 7997ec681f3Smrg * on. 8007ec681f3Smrg * 8017ec681f3Smrg * capture_begin == true will trigger an update of the fps on display, and a 8027ec681f3Smrg * flush of the data, but no stats will be written to the output file. This 8037ec681f3Smrg * way, we will have only stats from after the capture has been enabled 8047ec681f3Smrg * written to the output_file. 8057ec681f3Smrg */ 8067ec681f3Smrg const bool capture_begin = 8077ec681f3Smrg instance_data->capture_enabled && !instance_data->capture_started; 8087ec681f3Smrg 8098a1362adSmaya if (data->last_fps_update) { 8108a1362adSmaya double elapsed = (double)(now - data->last_fps_update); /* us */ 8117ec681f3Smrg if (capture_begin || 8127ec681f3Smrg elapsed >= instance_data->params.fps_sampling_period) { 8138a1362adSmaya data->fps = 1000000.0f * data->n_frames_since_update / elapsed; 8147ec681f3Smrg if (instance_data->capture_started) { 8158a1362adSmaya if (!instance_data->first_line_printed) { 8168a1362adSmaya bool first_column = true; 8178a1362adSmaya 8188a1362adSmaya instance_data->first_line_printed = true; 8198a1362adSmaya 8208a1362adSmaya#define OVERLAY_PARAM_BOOL(name) \ 8218a1362adSmaya if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_##name]) { \ 8228a1362adSmaya fprintf(instance_data->params.output_file, \ 8238a1362adSmaya "%s%s%s", first_column ? "" : ", ", #name, \ 8248a1362adSmaya param_unit(OVERLAY_PARAM_ENABLED_##name)); \ 8258a1362adSmaya first_column = false; \ 8268a1362adSmaya } 8278a1362adSmaya#define OVERLAY_PARAM_CUSTOM(name) 8288a1362adSmaya OVERLAY_PARAMS 8298a1362adSmaya#undef OVERLAY_PARAM_BOOL 8308a1362adSmaya#undef OVERLAY_PARAM_CUSTOM 8318a1362adSmaya fprintf(instance_data->params.output_file, "\n"); 8328a1362adSmaya } 8338a1362adSmaya 8348a1362adSmaya for (int s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 8358a1362adSmaya if (!instance_data->params.enabled[s]) 8368a1362adSmaya continue; 8378a1362adSmaya if (s == OVERLAY_PARAM_ENABLED_fps) { 8388a1362adSmaya fprintf(instance_data->params.output_file, 8398a1362adSmaya "%s%.2f", s == 0 ? "" : ", ", data->fps); 8408a1362adSmaya } else { 8418a1362adSmaya fprintf(instance_data->params.output_file, 8428a1362adSmaya "%s%" PRIu64, s == 0 ? "" : ", ", 8438a1362adSmaya data->accumulated_stats.stats[s]); 8448a1362adSmaya } 8458a1362adSmaya } 8468a1362adSmaya fprintf(instance_data->params.output_file, "\n"); 8478a1362adSmaya fflush(instance_data->params.output_file); 8488a1362adSmaya } 8498a1362adSmaya 8508a1362adSmaya memset(&data->accumulated_stats, 0, sizeof(data->accumulated_stats)); 8518a1362adSmaya data->n_frames_since_update = 0; 8528a1362adSmaya data->last_fps_update = now; 8537ec681f3Smrg 8547ec681f3Smrg if (capture_begin) 8557ec681f3Smrg instance_data->capture_started = true; 8568a1362adSmaya } 8578a1362adSmaya } else { 8588a1362adSmaya data->last_fps_update = now; 8598a1362adSmaya } 8608a1362adSmaya 8618a1362adSmaya memset(&device_data->frame_stats, 0, sizeof(device_data->frame_stats)); 8628a1362adSmaya memset(&data->frame_stats, 0, sizeof(device_data->frame_stats)); 8638a1362adSmaya 8648a1362adSmaya data->last_present_time = now; 8658a1362adSmaya data->n_frames++; 8668a1362adSmaya data->n_frames_since_update++; 8678a1362adSmaya} 8688a1362adSmaya 8698a1362adSmayastatic float get_time_stat(void *_data, int _idx) 8708a1362adSmaya{ 8718a1362adSmaya struct swapchain_data *data = (struct swapchain_data *) _data; 8728a1362adSmaya if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) 8738a1362adSmaya return 0.0f; 8748a1362adSmaya int idx = ARRAY_SIZE(data->frames_stats) + 8758a1362adSmaya data->n_frames < ARRAY_SIZE(data->frames_stats) ? 8768a1362adSmaya _idx - data->n_frames : 8778a1362adSmaya _idx + data->n_frames; 8788a1362adSmaya idx %= ARRAY_SIZE(data->frames_stats); 8798a1362adSmaya /* Time stats are in us. */ 8808a1362adSmaya return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; 8818a1362adSmaya} 8828a1362adSmaya 8838a1362adSmayastatic float get_stat(void *_data, int _idx) 8848a1362adSmaya{ 8858a1362adSmaya struct swapchain_data *data = (struct swapchain_data *) _data; 8868a1362adSmaya if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) 8878a1362adSmaya return 0.0f; 8888a1362adSmaya int idx = ARRAY_SIZE(data->frames_stats) + 8898a1362adSmaya data->n_frames < ARRAY_SIZE(data->frames_stats) ? 8908a1362adSmaya _idx - data->n_frames : 8918a1362adSmaya _idx + data->n_frames; 8928a1362adSmaya idx %= ARRAY_SIZE(data->frames_stats); 8938a1362adSmaya return data->frames_stats[idx].stats[data->stat_selector]; 8948a1362adSmaya} 8958a1362adSmaya 8968a1362adSmayastatic void position_layer(struct swapchain_data *data) 8978a1362adSmaya 8988a1362adSmaya{ 8998a1362adSmaya struct device_data *device_data = data->device; 9008a1362adSmaya struct instance_data *instance_data = device_data->instance; 9018a1362adSmaya const float margin = 10.0f; 9028a1362adSmaya 9038a1362adSmaya ImGui::SetNextWindowBgAlpha(0.5); 9048a1362adSmaya ImGui::SetNextWindowSize(data->window_size, ImGuiCond_Always); 9058a1362adSmaya switch (instance_data->params.position) { 9068a1362adSmaya case LAYER_POSITION_TOP_LEFT: 9078a1362adSmaya ImGui::SetNextWindowPos(ImVec2(margin, margin), ImGuiCond_Always); 9088a1362adSmaya break; 9098a1362adSmaya case LAYER_POSITION_TOP_RIGHT: 9108a1362adSmaya ImGui::SetNextWindowPos(ImVec2(data->width - data->window_size.x - margin, margin), 9118a1362adSmaya ImGuiCond_Always); 9128a1362adSmaya break; 9138a1362adSmaya case LAYER_POSITION_BOTTOM_LEFT: 9148a1362adSmaya ImGui::SetNextWindowPos(ImVec2(margin, data->height - data->window_size.y - margin), 9158a1362adSmaya ImGuiCond_Always); 9168a1362adSmaya break; 9178a1362adSmaya case LAYER_POSITION_BOTTOM_RIGHT: 9188a1362adSmaya ImGui::SetNextWindowPos(ImVec2(data->width - data->window_size.x - margin, 9198a1362adSmaya data->height - data->window_size.y - margin), 9208a1362adSmaya ImGuiCond_Always); 9218a1362adSmaya break; 9228a1362adSmaya } 9238a1362adSmaya} 9248a1362adSmaya 9258a1362adSmayastatic void compute_swapchain_display(struct swapchain_data *data) 9268a1362adSmaya{ 9278a1362adSmaya struct device_data *device_data = data->device; 9288a1362adSmaya struct instance_data *instance_data = device_data->instance; 9298a1362adSmaya 9308a1362adSmaya ImGui::SetCurrentContext(data->imgui_context); 9318a1362adSmaya ImGui::NewFrame(); 9328a1362adSmaya position_layer(data); 9338a1362adSmaya ImGui::Begin("Mesa overlay"); 9347ec681f3Smrg if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_device]) 9357ec681f3Smrg ImGui::Text("Device: %s", device_data->properties.deviceName); 9368a1362adSmaya 9377ec681f3Smrg if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_format]) { 9387ec681f3Smrg const char *format_name = vk_Format_to_str(data->format); 9397ec681f3Smrg format_name = format_name ? (format_name + strlen("VK_FORMAT_")) : "unknown"; 9407ec681f3Smrg ImGui::Text("Swapchain format: %s", format_name); 9417ec681f3Smrg } 9427ec681f3Smrg if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_frame]) 9437ec681f3Smrg ImGui::Text("Frames: %" PRIu64, data->n_frames); 9448a1362adSmaya if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_fps]) 9458a1362adSmaya ImGui::Text("FPS: %.2f" , data->fps); 9468a1362adSmaya 9478a1362adSmaya /* Recompute min/max */ 9488a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 9498a1362adSmaya data->stats_min.stats[s] = UINT64_MAX; 9508a1362adSmaya data->stats_max.stats[s] = 0; 9518a1362adSmaya } 9528a1362adSmaya for (uint32_t f = 0; f < MIN2(data->n_frames, ARRAY_SIZE(data->frames_stats)); f++) { 9538a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 9548a1362adSmaya data->stats_min.stats[s] = MIN2(data->frames_stats[f].stats[s], 9558a1362adSmaya data->stats_min.stats[s]); 9568a1362adSmaya data->stats_max.stats[s] = MAX2(data->frames_stats[f].stats[s], 9578a1362adSmaya data->stats_max.stats[s]); 9588a1362adSmaya } 9598a1362adSmaya } 9608a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 9618a1362adSmaya assert(data->stats_min.stats[s] != UINT64_MAX); 9628a1362adSmaya } 9638a1362adSmaya 9648a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 9658a1362adSmaya if (!instance_data->params.enabled[s] || 9667ec681f3Smrg s == OVERLAY_PARAM_ENABLED_device || 9677ec681f3Smrg s == OVERLAY_PARAM_ENABLED_format || 9688a1362adSmaya s == OVERLAY_PARAM_ENABLED_fps || 9698a1362adSmaya s == OVERLAY_PARAM_ENABLED_frame) 9708a1362adSmaya continue; 9718a1362adSmaya 9728a1362adSmaya char hash[40]; 9738a1362adSmaya snprintf(hash, sizeof(hash), "##%s", overlay_param_names[s]); 9748a1362adSmaya data->stat_selector = (enum overlay_param_enabled) s; 9758a1362adSmaya data->time_dividor = 1000.0f; 9768a1362adSmaya if (s == OVERLAY_PARAM_ENABLED_gpu_timing) 9778a1362adSmaya data->time_dividor = 1000000.0f; 9788a1362adSmaya 9798a1362adSmaya if (s == OVERLAY_PARAM_ENABLED_frame_timing || 9808a1362adSmaya s == OVERLAY_PARAM_ENABLED_acquire_timing || 9817ec681f3Smrg s == OVERLAY_PARAM_ENABLED_present_timing || 9828a1362adSmaya s == OVERLAY_PARAM_ENABLED_gpu_timing) { 9838a1362adSmaya double min_time = data->stats_min.stats[s] / data->time_dividor; 9848a1362adSmaya double max_time = data->stats_max.stats[s] / data->time_dividor; 9858a1362adSmaya ImGui::PlotHistogram(hash, get_time_stat, data, 9868a1362adSmaya ARRAY_SIZE(data->frames_stats), 0, 9878a1362adSmaya NULL, min_time, max_time, 9888a1362adSmaya ImVec2(ImGui::GetContentRegionAvailWidth(), 30)); 9898a1362adSmaya ImGui::Text("%s: %.3fms [%.3f, %.3f]", overlay_param_names[s], 9908a1362adSmaya get_time_stat(data, ARRAY_SIZE(data->frames_stats) - 1), 9918a1362adSmaya min_time, max_time); 9928a1362adSmaya } else { 9938a1362adSmaya ImGui::PlotHistogram(hash, get_stat, data, 9948a1362adSmaya ARRAY_SIZE(data->frames_stats), 0, 9958a1362adSmaya NULL, 9968a1362adSmaya data->stats_min.stats[s], 9978a1362adSmaya data->stats_max.stats[s], 9988a1362adSmaya ImVec2(ImGui::GetContentRegionAvailWidth(), 30)); 9998a1362adSmaya ImGui::Text("%s: %.0f [%" PRIu64 ", %" PRIu64 "]", overlay_param_names[s], 10008a1362adSmaya get_stat(data, ARRAY_SIZE(data->frames_stats) - 1), 10018a1362adSmaya data->stats_min.stats[s], data->stats_max.stats[s]); 10028a1362adSmaya } 10038a1362adSmaya } 10048a1362adSmaya data->window_size = ImVec2(data->window_size.x, ImGui::GetCursorPosY() + 10.0f); 10058a1362adSmaya ImGui::End(); 10068a1362adSmaya ImGui::EndFrame(); 10078a1362adSmaya ImGui::Render(); 10088a1362adSmaya} 10098a1362adSmaya 10108a1362adSmayastatic uint32_t vk_memory_type(struct device_data *data, 10118a1362adSmaya VkMemoryPropertyFlags properties, 10128a1362adSmaya uint32_t type_bits) 10138a1362adSmaya{ 10148a1362adSmaya VkPhysicalDeviceMemoryProperties prop; 10157ec681f3Smrg data->instance->pd_vtable.GetPhysicalDeviceMemoryProperties(data->physical_device, &prop); 10168a1362adSmaya for (uint32_t i = 0; i < prop.memoryTypeCount; i++) 10178a1362adSmaya if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i)) 10188a1362adSmaya return i; 10198a1362adSmaya return 0xFFFFFFFF; // Unable to find memoryType 10208a1362adSmaya} 10218a1362adSmaya 10228a1362adSmayastatic void ensure_swapchain_fonts(struct swapchain_data *data, 10238a1362adSmaya VkCommandBuffer command_buffer) 10248a1362adSmaya{ 10258a1362adSmaya if (data->font_uploaded) 10268a1362adSmaya return; 10278a1362adSmaya 10288a1362adSmaya data->font_uploaded = true; 10298a1362adSmaya 10308a1362adSmaya struct device_data *device_data = data->device; 10318a1362adSmaya ImGuiIO& io = ImGui::GetIO(); 10328a1362adSmaya unsigned char* pixels; 10338a1362adSmaya int width, height; 10348a1362adSmaya io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 10358a1362adSmaya size_t upload_size = width * height * 4 * sizeof(char); 10368a1362adSmaya 10378a1362adSmaya /* Upload buffer */ 10388a1362adSmaya VkBufferCreateInfo buffer_info = {}; 10398a1362adSmaya buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 10408a1362adSmaya buffer_info.size = upload_size; 10418a1362adSmaya buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; 10428a1362adSmaya buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 10438a1362adSmaya VK_CHECK(device_data->vtable.CreateBuffer(device_data->device, &buffer_info, 10448a1362adSmaya NULL, &data->upload_font_buffer)); 10458a1362adSmaya VkMemoryRequirements upload_buffer_req; 10468a1362adSmaya device_data->vtable.GetBufferMemoryRequirements(device_data->device, 10478a1362adSmaya data->upload_font_buffer, 10488a1362adSmaya &upload_buffer_req); 10498a1362adSmaya VkMemoryAllocateInfo upload_alloc_info = {}; 10508a1362adSmaya upload_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 10518a1362adSmaya upload_alloc_info.allocationSize = upload_buffer_req.size; 10528a1362adSmaya upload_alloc_info.memoryTypeIndex = vk_memory_type(device_data, 10538a1362adSmaya VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 10548a1362adSmaya upload_buffer_req.memoryTypeBits); 10558a1362adSmaya VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, 10568a1362adSmaya &upload_alloc_info, 10578a1362adSmaya NULL, 10588a1362adSmaya &data->upload_font_buffer_mem)); 10598a1362adSmaya VK_CHECK(device_data->vtable.BindBufferMemory(device_data->device, 10608a1362adSmaya data->upload_font_buffer, 10618a1362adSmaya data->upload_font_buffer_mem, 0)); 10628a1362adSmaya 10638a1362adSmaya /* Upload to Buffer */ 10648a1362adSmaya char* map = NULL; 10658a1362adSmaya VK_CHECK(device_data->vtable.MapMemory(device_data->device, 10668a1362adSmaya data->upload_font_buffer_mem, 10678a1362adSmaya 0, upload_size, 0, (void**)(&map))); 10688a1362adSmaya memcpy(map, pixels, upload_size); 10698a1362adSmaya VkMappedMemoryRange range[1] = {}; 10708a1362adSmaya range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 10718a1362adSmaya range[0].memory = data->upload_font_buffer_mem; 10728a1362adSmaya range[0].size = upload_size; 10738a1362adSmaya VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 1, range)); 10748a1362adSmaya device_data->vtable.UnmapMemory(device_data->device, 10758a1362adSmaya data->upload_font_buffer_mem); 10768a1362adSmaya 10778a1362adSmaya /* Copy buffer to image */ 10788a1362adSmaya VkImageMemoryBarrier copy_barrier[1] = {}; 10798a1362adSmaya copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 10808a1362adSmaya copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 10818a1362adSmaya copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 10828a1362adSmaya copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 10838a1362adSmaya copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 10848a1362adSmaya copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 10858a1362adSmaya copy_barrier[0].image = data->font_image; 10868a1362adSmaya copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 10878a1362adSmaya copy_barrier[0].subresourceRange.levelCount = 1; 10888a1362adSmaya copy_barrier[0].subresourceRange.layerCount = 1; 10898a1362adSmaya device_data->vtable.CmdPipelineBarrier(command_buffer, 10908a1362adSmaya VK_PIPELINE_STAGE_HOST_BIT, 10918a1362adSmaya VK_PIPELINE_STAGE_TRANSFER_BIT, 10928a1362adSmaya 0, 0, NULL, 0, NULL, 10938a1362adSmaya 1, copy_barrier); 10948a1362adSmaya 10958a1362adSmaya VkBufferImageCopy region = {}; 10968a1362adSmaya region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 10978a1362adSmaya region.imageSubresource.layerCount = 1; 10988a1362adSmaya region.imageExtent.width = width; 10998a1362adSmaya region.imageExtent.height = height; 11008a1362adSmaya region.imageExtent.depth = 1; 11018a1362adSmaya device_data->vtable.CmdCopyBufferToImage(command_buffer, 11028a1362adSmaya data->upload_font_buffer, 11038a1362adSmaya data->font_image, 11048a1362adSmaya VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 11058a1362adSmaya 1, ®ion); 11068a1362adSmaya 11078a1362adSmaya VkImageMemoryBarrier use_barrier[1] = {}; 11088a1362adSmaya use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 11098a1362adSmaya use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 11108a1362adSmaya use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 11118a1362adSmaya use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 11128a1362adSmaya use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 11138a1362adSmaya use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 11148a1362adSmaya use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 11158a1362adSmaya use_barrier[0].image = data->font_image; 11168a1362adSmaya use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 11178a1362adSmaya use_barrier[0].subresourceRange.levelCount = 1; 11188a1362adSmaya use_barrier[0].subresourceRange.layerCount = 1; 11198a1362adSmaya device_data->vtable.CmdPipelineBarrier(command_buffer, 11208a1362adSmaya VK_PIPELINE_STAGE_TRANSFER_BIT, 11218a1362adSmaya VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 11228a1362adSmaya 0, 11238a1362adSmaya 0, NULL, 11248a1362adSmaya 0, NULL, 11258a1362adSmaya 1, use_barrier); 11268a1362adSmaya 11278a1362adSmaya /* Store our identifier */ 11288a1362adSmaya io.Fonts->TexID = (ImTextureID)(intptr_t)data->font_image; 11298a1362adSmaya} 11308a1362adSmaya 11318a1362adSmayastatic void CreateOrResizeBuffer(struct device_data *data, 11328a1362adSmaya VkBuffer *buffer, 11338a1362adSmaya VkDeviceMemory *buffer_memory, 11348a1362adSmaya VkDeviceSize *buffer_size, 11358a1362adSmaya size_t new_size, VkBufferUsageFlagBits usage) 11368a1362adSmaya{ 11378a1362adSmaya if (*buffer != VK_NULL_HANDLE) 11388a1362adSmaya data->vtable.DestroyBuffer(data->device, *buffer, NULL); 11398a1362adSmaya if (*buffer_memory) 11408a1362adSmaya data->vtable.FreeMemory(data->device, *buffer_memory, NULL); 11418a1362adSmaya 11428a1362adSmaya VkBufferCreateInfo buffer_info = {}; 11438a1362adSmaya buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 11448a1362adSmaya buffer_info.size = new_size; 11458a1362adSmaya buffer_info.usage = usage; 11468a1362adSmaya buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 11478a1362adSmaya VK_CHECK(data->vtable.CreateBuffer(data->device, &buffer_info, NULL, buffer)); 11488a1362adSmaya 11498a1362adSmaya VkMemoryRequirements req; 11508a1362adSmaya data->vtable.GetBufferMemoryRequirements(data->device, *buffer, &req); 11518a1362adSmaya VkMemoryAllocateInfo alloc_info = {}; 11528a1362adSmaya alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 11538a1362adSmaya alloc_info.allocationSize = req.size; 11548a1362adSmaya alloc_info.memoryTypeIndex = 11558a1362adSmaya vk_memory_type(data, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); 11568a1362adSmaya VK_CHECK(data->vtable.AllocateMemory(data->device, &alloc_info, NULL, buffer_memory)); 11578a1362adSmaya 11588a1362adSmaya VK_CHECK(data->vtable.BindBufferMemory(data->device, *buffer, *buffer_memory, 0)); 11598a1362adSmaya *buffer_size = new_size; 11608a1362adSmaya} 11618a1362adSmaya 11628a1362adSmayastatic struct overlay_draw *render_swapchain_display(struct swapchain_data *data, 11638a1362adSmaya struct queue_data *present_queue, 11648a1362adSmaya const VkSemaphore *wait_semaphores, 11658a1362adSmaya unsigned n_wait_semaphores, 11668a1362adSmaya unsigned image_index) 11678a1362adSmaya{ 11688a1362adSmaya ImDrawData* draw_data = ImGui::GetDrawData(); 11698a1362adSmaya if (draw_data->TotalVtxCount == 0) 11708a1362adSmaya return NULL; 11718a1362adSmaya 11728a1362adSmaya struct device_data *device_data = data->device; 11738a1362adSmaya struct overlay_draw *draw = get_overlay_draw(data); 11748a1362adSmaya 11758a1362adSmaya device_data->vtable.ResetCommandBuffer(draw->command_buffer, 0); 11768a1362adSmaya 11778a1362adSmaya VkRenderPassBeginInfo render_pass_info = {}; 11788a1362adSmaya render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 11798a1362adSmaya render_pass_info.renderPass = data->render_pass; 11808a1362adSmaya render_pass_info.framebuffer = data->framebuffers[image_index]; 11818a1362adSmaya render_pass_info.renderArea.extent.width = data->width; 11828a1362adSmaya render_pass_info.renderArea.extent.height = data->height; 11838a1362adSmaya 11848a1362adSmaya VkCommandBufferBeginInfo buffer_begin_info = {}; 11858a1362adSmaya buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 11868a1362adSmaya 11878a1362adSmaya device_data->vtable.BeginCommandBuffer(draw->command_buffer, &buffer_begin_info); 11888a1362adSmaya 11898a1362adSmaya ensure_swapchain_fonts(data, draw->command_buffer); 11908a1362adSmaya 11918a1362adSmaya /* Bounce the image to display back to color attachment layout for 11928a1362adSmaya * rendering on top of it. 11938a1362adSmaya */ 11948a1362adSmaya VkImageMemoryBarrier imb; 11958a1362adSmaya imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 11968a1362adSmaya imb.pNext = nullptr; 11978a1362adSmaya imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 11988a1362adSmaya imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 11998a1362adSmaya imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 12008a1362adSmaya imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 12018a1362adSmaya imb.image = data->images[image_index]; 12028a1362adSmaya imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 12038a1362adSmaya imb.subresourceRange.baseMipLevel = 0; 12048a1362adSmaya imb.subresourceRange.levelCount = 1; 12058a1362adSmaya imb.subresourceRange.baseArrayLayer = 0; 12068a1362adSmaya imb.subresourceRange.layerCount = 1; 12078a1362adSmaya imb.srcQueueFamilyIndex = present_queue->family_index; 12088a1362adSmaya imb.dstQueueFamilyIndex = device_data->graphic_queue->family_index; 12098a1362adSmaya device_data->vtable.CmdPipelineBarrier(draw->command_buffer, 12108a1362adSmaya VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 12118a1362adSmaya VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 12128a1362adSmaya 0, /* dependency flags */ 12138a1362adSmaya 0, nullptr, /* memory barriers */ 12148a1362adSmaya 0, nullptr, /* buffer memory barriers */ 12158a1362adSmaya 1, &imb); /* image memory barriers */ 12168a1362adSmaya 12178a1362adSmaya device_data->vtable.CmdBeginRenderPass(draw->command_buffer, &render_pass_info, 12188a1362adSmaya VK_SUBPASS_CONTENTS_INLINE); 12198a1362adSmaya 12208a1362adSmaya /* Create/Resize vertex & index buffers */ 12217ec681f3Smrg size_t vertex_size = ALIGN(draw_data->TotalVtxCount * sizeof(ImDrawVert), device_data->properties.limits.nonCoherentAtomSize); 12227ec681f3Smrg size_t index_size = ALIGN(draw_data->TotalIdxCount * sizeof(ImDrawIdx), device_data->properties.limits.nonCoherentAtomSize); 12238a1362adSmaya if (draw->vertex_buffer_size < vertex_size) { 12248a1362adSmaya CreateOrResizeBuffer(device_data, 12258a1362adSmaya &draw->vertex_buffer, 12268a1362adSmaya &draw->vertex_buffer_mem, 12278a1362adSmaya &draw->vertex_buffer_size, 12288a1362adSmaya vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 12298a1362adSmaya } 12308a1362adSmaya if (draw->index_buffer_size < index_size) { 12318a1362adSmaya CreateOrResizeBuffer(device_data, 12328a1362adSmaya &draw->index_buffer, 12338a1362adSmaya &draw->index_buffer_mem, 12348a1362adSmaya &draw->index_buffer_size, 12358a1362adSmaya index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); 12368a1362adSmaya } 12378a1362adSmaya 12388a1362adSmaya /* Upload vertex & index data */ 12398a1362adSmaya ImDrawVert* vtx_dst = NULL; 12408a1362adSmaya ImDrawIdx* idx_dst = NULL; 12418a1362adSmaya VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->vertex_buffer_mem, 12428a1362adSmaya 0, vertex_size, 0, (void**)(&vtx_dst))); 12438a1362adSmaya VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->index_buffer_mem, 12448a1362adSmaya 0, index_size, 0, (void**)(&idx_dst))); 12458a1362adSmaya for (int n = 0; n < draw_data->CmdListsCount; n++) 12468a1362adSmaya { 12478a1362adSmaya const ImDrawList* cmd_list = draw_data->CmdLists[n]; 12488a1362adSmaya memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); 12498a1362adSmaya memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 12508a1362adSmaya vtx_dst += cmd_list->VtxBuffer.Size; 12518a1362adSmaya idx_dst += cmd_list->IdxBuffer.Size; 12528a1362adSmaya } 12538a1362adSmaya VkMappedMemoryRange range[2] = {}; 12548a1362adSmaya range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 12558a1362adSmaya range[0].memory = draw->vertex_buffer_mem; 12568a1362adSmaya range[0].size = VK_WHOLE_SIZE; 12578a1362adSmaya range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 12588a1362adSmaya range[1].memory = draw->index_buffer_mem; 12598a1362adSmaya range[1].size = VK_WHOLE_SIZE; 12608a1362adSmaya VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 2, range)); 12618a1362adSmaya device_data->vtable.UnmapMemory(device_data->device, draw->vertex_buffer_mem); 12628a1362adSmaya device_data->vtable.UnmapMemory(device_data->device, draw->index_buffer_mem); 12638a1362adSmaya 12648a1362adSmaya /* Bind pipeline and descriptor sets */ 12658a1362adSmaya device_data->vtable.CmdBindPipeline(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline); 12668a1362adSmaya VkDescriptorSet desc_set[1] = { data->descriptor_set }; 12678a1362adSmaya device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 12688a1362adSmaya data->pipeline_layout, 0, 1, desc_set, 0, NULL); 12698a1362adSmaya 12708a1362adSmaya /* Bind vertex & index buffers */ 12718a1362adSmaya VkBuffer vertex_buffers[1] = { draw->vertex_buffer }; 12728a1362adSmaya VkDeviceSize vertex_offset[1] = { 0 }; 12738a1362adSmaya device_data->vtable.CmdBindVertexBuffers(draw->command_buffer, 0, 1, vertex_buffers, vertex_offset); 12748a1362adSmaya device_data->vtable.CmdBindIndexBuffer(draw->command_buffer, draw->index_buffer, 0, VK_INDEX_TYPE_UINT16); 12758a1362adSmaya 12768a1362adSmaya /* Setup viewport */ 12778a1362adSmaya VkViewport viewport; 12788a1362adSmaya viewport.x = 0; 12798a1362adSmaya viewport.y = 0; 12808a1362adSmaya viewport.width = draw_data->DisplaySize.x; 12818a1362adSmaya viewport.height = draw_data->DisplaySize.y; 12828a1362adSmaya viewport.minDepth = 0.0f; 12838a1362adSmaya viewport.maxDepth = 1.0f; 12848a1362adSmaya device_data->vtable.CmdSetViewport(draw->command_buffer, 0, 1, &viewport); 12858a1362adSmaya 12868a1362adSmaya 12878a1362adSmaya /* Setup scale and translation through push constants : 12888a1362adSmaya * 12898a1362adSmaya * Our visible imgui space lies from draw_data->DisplayPos (top left) to 12908a1362adSmaya * draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin 12918a1362adSmaya * is typically (0,0) for single viewport apps. 12928a1362adSmaya */ 12938a1362adSmaya float scale[2]; 12948a1362adSmaya scale[0] = 2.0f / draw_data->DisplaySize.x; 12958a1362adSmaya scale[1] = 2.0f / draw_data->DisplaySize.y; 12968a1362adSmaya float translate[2]; 12978a1362adSmaya translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; 12988a1362adSmaya translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; 12998a1362adSmaya device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, 13008a1362adSmaya VK_SHADER_STAGE_VERTEX_BIT, 13018a1362adSmaya sizeof(float) * 0, sizeof(float) * 2, scale); 13028a1362adSmaya device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, 13038a1362adSmaya VK_SHADER_STAGE_VERTEX_BIT, 13048a1362adSmaya sizeof(float) * 2, sizeof(float) * 2, translate); 13058a1362adSmaya 13068a1362adSmaya // Render the command lists: 13078a1362adSmaya int vtx_offset = 0; 13088a1362adSmaya int idx_offset = 0; 13098a1362adSmaya ImVec2 display_pos = draw_data->DisplayPos; 13108a1362adSmaya for (int n = 0; n < draw_data->CmdListsCount; n++) 13118a1362adSmaya { 13128a1362adSmaya const ImDrawList* cmd_list = draw_data->CmdLists[n]; 13138a1362adSmaya for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 13148a1362adSmaya { 13158a1362adSmaya const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 13168a1362adSmaya // Apply scissor/clipping rectangle 13178a1362adSmaya // FIXME: We could clamp width/height based on clamped min/max values. 13188a1362adSmaya VkRect2D scissor; 13198a1362adSmaya scissor.offset.x = (int32_t)(pcmd->ClipRect.x - display_pos.x) > 0 ? (int32_t)(pcmd->ClipRect.x - display_pos.x) : 0; 13208a1362adSmaya scissor.offset.y = (int32_t)(pcmd->ClipRect.y - display_pos.y) > 0 ? (int32_t)(pcmd->ClipRect.y - display_pos.y) : 0; 13218a1362adSmaya scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); 13228a1362adSmaya scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here? 13238a1362adSmaya device_data->vtable.CmdSetScissor(draw->command_buffer, 0, 1, &scissor); 13248a1362adSmaya 13258a1362adSmaya // Draw 13268a1362adSmaya device_data->vtable.CmdDrawIndexed(draw->command_buffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); 13278a1362adSmaya 13288a1362adSmaya idx_offset += pcmd->ElemCount; 13298a1362adSmaya } 13308a1362adSmaya vtx_offset += cmd_list->VtxBuffer.Size; 13318a1362adSmaya } 13328a1362adSmaya 13338a1362adSmaya device_data->vtable.CmdEndRenderPass(draw->command_buffer); 13348a1362adSmaya 13357ec681f3Smrg if (device_data->graphic_queue->family_index != present_queue->family_index) 13367ec681f3Smrg { 13377ec681f3Smrg /* Transfer the image back to the present queue family 13387ec681f3Smrg * image layout was already changed to present by the render pass 13397ec681f3Smrg */ 13407ec681f3Smrg imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 13417ec681f3Smrg imb.pNext = nullptr; 13427ec681f3Smrg imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 13437ec681f3Smrg imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 13447ec681f3Smrg imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 13457ec681f3Smrg imb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 13467ec681f3Smrg imb.image = data->images[image_index]; 13477ec681f3Smrg imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 13487ec681f3Smrg imb.subresourceRange.baseMipLevel = 0; 13497ec681f3Smrg imb.subresourceRange.levelCount = 1; 13507ec681f3Smrg imb.subresourceRange.baseArrayLayer = 0; 13517ec681f3Smrg imb.subresourceRange.layerCount = 1; 13527ec681f3Smrg imb.srcQueueFamilyIndex = device_data->graphic_queue->family_index; 13537ec681f3Smrg imb.dstQueueFamilyIndex = present_queue->family_index; 13547ec681f3Smrg device_data->vtable.CmdPipelineBarrier(draw->command_buffer, 13557ec681f3Smrg VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 13567ec681f3Smrg VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 13577ec681f3Smrg 0, /* dependency flags */ 13587ec681f3Smrg 0, nullptr, /* memory barriers */ 13597ec681f3Smrg 0, nullptr, /* buffer memory barriers */ 13607ec681f3Smrg 1, &imb); /* image memory barriers */ 13617ec681f3Smrg } 13628a1362adSmaya 13638a1362adSmaya device_data->vtable.EndCommandBuffer(draw->command_buffer); 13648a1362adSmaya 13657ec681f3Smrg /* When presenting on a different queue than where we're drawing the 13667ec681f3Smrg * overlay *AND* when the application does not provide a semaphore to 13677ec681f3Smrg * vkQueuePresent, insert our own cross engine synchronization 13687ec681f3Smrg * semaphore. 13697ec681f3Smrg */ 13707ec681f3Smrg if (n_wait_semaphores == 0 && device_data->graphic_queue->queue != present_queue->queue) { 13717ec681f3Smrg VkPipelineStageFlags stages_wait = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 13727ec681f3Smrg VkSubmitInfo submit_info = {}; 13737ec681f3Smrg submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 13747ec681f3Smrg submit_info.commandBufferCount = 0; 13757ec681f3Smrg submit_info.pWaitDstStageMask = &stages_wait; 13767ec681f3Smrg submit_info.waitSemaphoreCount = 0; 13777ec681f3Smrg submit_info.signalSemaphoreCount = 1; 13787ec681f3Smrg submit_info.pSignalSemaphores = &draw->cross_engine_semaphore; 13797ec681f3Smrg 13807ec681f3Smrg device_data->vtable.QueueSubmit(present_queue->queue, 1, &submit_info, VK_NULL_HANDLE); 13817ec681f3Smrg 13827ec681f3Smrg submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 13837ec681f3Smrg submit_info.commandBufferCount = 1; 13847ec681f3Smrg submit_info.pWaitDstStageMask = &stages_wait; 13857ec681f3Smrg submit_info.pCommandBuffers = &draw->command_buffer; 13867ec681f3Smrg submit_info.waitSemaphoreCount = 1; 13877ec681f3Smrg submit_info.pWaitSemaphores = &draw->cross_engine_semaphore; 13887ec681f3Smrg submit_info.signalSemaphoreCount = 1; 13897ec681f3Smrg submit_info.pSignalSemaphores = &draw->semaphore; 13907ec681f3Smrg 13917ec681f3Smrg device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); 13927ec681f3Smrg } else { 13937ec681f3Smrg VkPipelineStageFlags *stages_wait = (VkPipelineStageFlags*) malloc(sizeof(VkPipelineStageFlags) * n_wait_semaphores); 13947ec681f3Smrg for (unsigned i = 0; i < n_wait_semaphores; i++) 13957ec681f3Smrg { 13967ec681f3Smrg // wait in the fragment stage until the swapchain image is ready 13977ec681f3Smrg stages_wait[i] = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 13987ec681f3Smrg } 13997ec681f3Smrg 14007ec681f3Smrg VkSubmitInfo submit_info = {}; 14017ec681f3Smrg submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 14027ec681f3Smrg submit_info.commandBufferCount = 1; 14037ec681f3Smrg submit_info.pCommandBuffers = &draw->command_buffer; 14047ec681f3Smrg submit_info.pWaitDstStageMask = stages_wait; 14057ec681f3Smrg submit_info.waitSemaphoreCount = n_wait_semaphores; 14067ec681f3Smrg submit_info.pWaitSemaphores = wait_semaphores; 14077ec681f3Smrg submit_info.signalSemaphoreCount = 1; 14087ec681f3Smrg submit_info.pSignalSemaphores = &draw->semaphore; 14097ec681f3Smrg 14107ec681f3Smrg device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); 14118a1362adSmaya 14127ec681f3Smrg free(stages_wait); 14137ec681f3Smrg } 14148a1362adSmaya 14158a1362adSmaya return draw; 14168a1362adSmaya} 14178a1362adSmaya 14188a1362adSmayastatic const uint32_t overlay_vert_spv[] = { 14198a1362adSmaya#include "overlay.vert.spv.h" 14208a1362adSmaya}; 14218a1362adSmayastatic const uint32_t overlay_frag_spv[] = { 14228a1362adSmaya#include "overlay.frag.spv.h" 14238a1362adSmaya}; 14248a1362adSmaya 14258a1362adSmayastatic void setup_swapchain_data_pipeline(struct swapchain_data *data) 14268a1362adSmaya{ 14278a1362adSmaya struct device_data *device_data = data->device; 14288a1362adSmaya VkShaderModule vert_module, frag_module; 14298a1362adSmaya 14308a1362adSmaya /* Create shader modules */ 14318a1362adSmaya VkShaderModuleCreateInfo vert_info = {}; 14328a1362adSmaya vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 14338a1362adSmaya vert_info.codeSize = sizeof(overlay_vert_spv); 14348a1362adSmaya vert_info.pCode = overlay_vert_spv; 14358a1362adSmaya VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, 14368a1362adSmaya &vert_info, NULL, &vert_module)); 14378a1362adSmaya VkShaderModuleCreateInfo frag_info = {}; 14388a1362adSmaya frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 14398a1362adSmaya frag_info.codeSize = sizeof(overlay_frag_spv); 14408a1362adSmaya frag_info.pCode = (uint32_t*)overlay_frag_spv; 14418a1362adSmaya VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, 14428a1362adSmaya &frag_info, NULL, &frag_module)); 14438a1362adSmaya 14448a1362adSmaya /* Font sampler */ 14458a1362adSmaya VkSamplerCreateInfo sampler_info = {}; 14468a1362adSmaya sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 14478a1362adSmaya sampler_info.magFilter = VK_FILTER_LINEAR; 14488a1362adSmaya sampler_info.minFilter = VK_FILTER_LINEAR; 14498a1362adSmaya sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 14508a1362adSmaya sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; 14518a1362adSmaya sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; 14528a1362adSmaya sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; 14538a1362adSmaya sampler_info.minLod = -1000; 14548a1362adSmaya sampler_info.maxLod = 1000; 14558a1362adSmaya sampler_info.maxAnisotropy = 1.0f; 14568a1362adSmaya VK_CHECK(device_data->vtable.CreateSampler(device_data->device, &sampler_info, 14578a1362adSmaya NULL, &data->font_sampler)); 14588a1362adSmaya 14598a1362adSmaya /* Descriptor pool */ 14608a1362adSmaya VkDescriptorPoolSize sampler_pool_size = {}; 14618a1362adSmaya sampler_pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 14628a1362adSmaya sampler_pool_size.descriptorCount = 1; 14638a1362adSmaya VkDescriptorPoolCreateInfo desc_pool_info = {}; 14648a1362adSmaya desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 14658a1362adSmaya desc_pool_info.maxSets = 1; 14668a1362adSmaya desc_pool_info.poolSizeCount = 1; 14678a1362adSmaya desc_pool_info.pPoolSizes = &sampler_pool_size; 14688a1362adSmaya VK_CHECK(device_data->vtable.CreateDescriptorPool(device_data->device, 14698a1362adSmaya &desc_pool_info, 14708a1362adSmaya NULL, &data->descriptor_pool)); 14718a1362adSmaya 14728a1362adSmaya /* Descriptor layout */ 14738a1362adSmaya VkSampler sampler[1] = { data->font_sampler }; 14748a1362adSmaya VkDescriptorSetLayoutBinding binding[1] = {}; 14758a1362adSmaya binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 14768a1362adSmaya binding[0].descriptorCount = 1; 14778a1362adSmaya binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 14788a1362adSmaya binding[0].pImmutableSamplers = sampler; 14798a1362adSmaya VkDescriptorSetLayoutCreateInfo set_layout_info = {}; 14808a1362adSmaya set_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 14818a1362adSmaya set_layout_info.bindingCount = 1; 14828a1362adSmaya set_layout_info.pBindings = binding; 14838a1362adSmaya VK_CHECK(device_data->vtable.CreateDescriptorSetLayout(device_data->device, 14848a1362adSmaya &set_layout_info, 14858a1362adSmaya NULL, &data->descriptor_layout)); 14868a1362adSmaya 14878a1362adSmaya /* Descriptor set */ 14888a1362adSmaya VkDescriptorSetAllocateInfo alloc_info = {}; 14898a1362adSmaya alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 14908a1362adSmaya alloc_info.descriptorPool = data->descriptor_pool; 14918a1362adSmaya alloc_info.descriptorSetCount = 1; 14928a1362adSmaya alloc_info.pSetLayouts = &data->descriptor_layout; 14938a1362adSmaya VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, 14948a1362adSmaya &alloc_info, 14958a1362adSmaya &data->descriptor_set)); 14968a1362adSmaya 14978a1362adSmaya /* Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 14988a1362adSmaya * 3d projection matrix 14998a1362adSmaya */ 15008a1362adSmaya VkPushConstantRange push_constants[1] = {}; 15018a1362adSmaya push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 15028a1362adSmaya push_constants[0].offset = sizeof(float) * 0; 15038a1362adSmaya push_constants[0].size = sizeof(float) * 4; 15048a1362adSmaya VkPipelineLayoutCreateInfo layout_info = {}; 15058a1362adSmaya layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 15068a1362adSmaya layout_info.setLayoutCount = 1; 15078a1362adSmaya layout_info.pSetLayouts = &data->descriptor_layout; 15088a1362adSmaya layout_info.pushConstantRangeCount = 1; 15098a1362adSmaya layout_info.pPushConstantRanges = push_constants; 15108a1362adSmaya VK_CHECK(device_data->vtable.CreatePipelineLayout(device_data->device, 15118a1362adSmaya &layout_info, 15128a1362adSmaya NULL, &data->pipeline_layout)); 15138a1362adSmaya 15148a1362adSmaya VkPipelineShaderStageCreateInfo stage[2] = {}; 15158a1362adSmaya stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 15168a1362adSmaya stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 15178a1362adSmaya stage[0].module = vert_module; 15188a1362adSmaya stage[0].pName = "main"; 15198a1362adSmaya stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 15208a1362adSmaya stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 15218a1362adSmaya stage[1].module = frag_module; 15228a1362adSmaya stage[1].pName = "main"; 15238a1362adSmaya 15248a1362adSmaya VkVertexInputBindingDescription binding_desc[1] = {}; 15258a1362adSmaya binding_desc[0].stride = sizeof(ImDrawVert); 15268a1362adSmaya binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 15278a1362adSmaya 15288a1362adSmaya VkVertexInputAttributeDescription attribute_desc[3] = {}; 15298a1362adSmaya attribute_desc[0].location = 0; 15308a1362adSmaya attribute_desc[0].binding = binding_desc[0].binding; 15318a1362adSmaya attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; 15328a1362adSmaya attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos); 15338a1362adSmaya attribute_desc[1].location = 1; 15348a1362adSmaya attribute_desc[1].binding = binding_desc[0].binding; 15358a1362adSmaya attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; 15368a1362adSmaya attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv); 15378a1362adSmaya attribute_desc[2].location = 2; 15388a1362adSmaya attribute_desc[2].binding = binding_desc[0].binding; 15398a1362adSmaya attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; 15408a1362adSmaya attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col); 15418a1362adSmaya 15428a1362adSmaya VkPipelineVertexInputStateCreateInfo vertex_info = {}; 15438a1362adSmaya vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 15448a1362adSmaya vertex_info.vertexBindingDescriptionCount = 1; 15458a1362adSmaya vertex_info.pVertexBindingDescriptions = binding_desc; 15468a1362adSmaya vertex_info.vertexAttributeDescriptionCount = 3; 15478a1362adSmaya vertex_info.pVertexAttributeDescriptions = attribute_desc; 15488a1362adSmaya 15498a1362adSmaya VkPipelineInputAssemblyStateCreateInfo ia_info = {}; 15508a1362adSmaya ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 15518a1362adSmaya ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 15528a1362adSmaya 15538a1362adSmaya VkPipelineViewportStateCreateInfo viewport_info = {}; 15548a1362adSmaya viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 15558a1362adSmaya viewport_info.viewportCount = 1; 15568a1362adSmaya viewport_info.scissorCount = 1; 15578a1362adSmaya 15588a1362adSmaya VkPipelineRasterizationStateCreateInfo raster_info = {}; 15598a1362adSmaya raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 15608a1362adSmaya raster_info.polygonMode = VK_POLYGON_MODE_FILL; 15618a1362adSmaya raster_info.cullMode = VK_CULL_MODE_NONE; 15628a1362adSmaya raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 15638a1362adSmaya raster_info.lineWidth = 1.0f; 15648a1362adSmaya 15658a1362adSmaya VkPipelineMultisampleStateCreateInfo ms_info = {}; 15668a1362adSmaya ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 15678a1362adSmaya ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 15688a1362adSmaya 15698a1362adSmaya VkPipelineColorBlendAttachmentState color_attachment[1] = {}; 15708a1362adSmaya color_attachment[0].blendEnable = VK_TRUE; 15718a1362adSmaya color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 15728a1362adSmaya color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 15738a1362adSmaya color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; 15748a1362adSmaya color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 15758a1362adSmaya color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 15768a1362adSmaya color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; 15778a1362adSmaya color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | 15788a1362adSmaya VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 15798a1362adSmaya 15808a1362adSmaya VkPipelineDepthStencilStateCreateInfo depth_info = {}; 15818a1362adSmaya depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 15828a1362adSmaya 15838a1362adSmaya VkPipelineColorBlendStateCreateInfo blend_info = {}; 15848a1362adSmaya blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 15858a1362adSmaya blend_info.attachmentCount = 1; 15868a1362adSmaya blend_info.pAttachments = color_attachment; 15878a1362adSmaya 15888a1362adSmaya VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; 15898a1362adSmaya VkPipelineDynamicStateCreateInfo dynamic_state = {}; 15908a1362adSmaya dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 15918a1362adSmaya dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); 15928a1362adSmaya dynamic_state.pDynamicStates = dynamic_states; 15938a1362adSmaya 15948a1362adSmaya VkGraphicsPipelineCreateInfo info = {}; 15958a1362adSmaya info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 15968a1362adSmaya info.flags = 0; 15978a1362adSmaya info.stageCount = 2; 15988a1362adSmaya info.pStages = stage; 15998a1362adSmaya info.pVertexInputState = &vertex_info; 16008a1362adSmaya info.pInputAssemblyState = &ia_info; 16018a1362adSmaya info.pViewportState = &viewport_info; 16028a1362adSmaya info.pRasterizationState = &raster_info; 16038a1362adSmaya info.pMultisampleState = &ms_info; 16048a1362adSmaya info.pDepthStencilState = &depth_info; 16058a1362adSmaya info.pColorBlendState = &blend_info; 16068a1362adSmaya info.pDynamicState = &dynamic_state; 16078a1362adSmaya info.layout = data->pipeline_layout; 16088a1362adSmaya info.renderPass = data->render_pass; 16098a1362adSmaya VK_CHECK( 16108a1362adSmaya device_data->vtable.CreateGraphicsPipelines(device_data->device, VK_NULL_HANDLE, 16118a1362adSmaya 1, &info, 16128a1362adSmaya NULL, &data->pipeline)); 16138a1362adSmaya 16148a1362adSmaya device_data->vtable.DestroyShaderModule(device_data->device, vert_module, NULL); 16158a1362adSmaya device_data->vtable.DestroyShaderModule(device_data->device, frag_module, NULL); 16168a1362adSmaya 16178a1362adSmaya ImGuiIO& io = ImGui::GetIO(); 16188a1362adSmaya unsigned char* pixels; 16198a1362adSmaya int width, height; 16208a1362adSmaya io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 16218a1362adSmaya 16228a1362adSmaya /* Font image */ 16238a1362adSmaya VkImageCreateInfo image_info = {}; 16248a1362adSmaya image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 16258a1362adSmaya image_info.imageType = VK_IMAGE_TYPE_2D; 16268a1362adSmaya image_info.format = VK_FORMAT_R8G8B8A8_UNORM; 16278a1362adSmaya image_info.extent.width = width; 16288a1362adSmaya image_info.extent.height = height; 16298a1362adSmaya image_info.extent.depth = 1; 16308a1362adSmaya image_info.mipLevels = 1; 16318a1362adSmaya image_info.arrayLayers = 1; 16328a1362adSmaya image_info.samples = VK_SAMPLE_COUNT_1_BIT; 16338a1362adSmaya image_info.tiling = VK_IMAGE_TILING_OPTIMAL; 16348a1362adSmaya image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 16358a1362adSmaya image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 16368a1362adSmaya image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 16378a1362adSmaya VK_CHECK(device_data->vtable.CreateImage(device_data->device, &image_info, 16388a1362adSmaya NULL, &data->font_image)); 16398a1362adSmaya VkMemoryRequirements font_image_req; 16408a1362adSmaya device_data->vtable.GetImageMemoryRequirements(device_data->device, 16418a1362adSmaya data->font_image, &font_image_req); 16428a1362adSmaya VkMemoryAllocateInfo image_alloc_info = {}; 16438a1362adSmaya image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 16448a1362adSmaya image_alloc_info.allocationSize = font_image_req.size; 16458a1362adSmaya image_alloc_info.memoryTypeIndex = vk_memory_type(device_data, 16468a1362adSmaya VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 16478a1362adSmaya font_image_req.memoryTypeBits); 16488a1362adSmaya VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, &image_alloc_info, 16498a1362adSmaya NULL, &data->font_mem)); 16508a1362adSmaya VK_CHECK(device_data->vtable.BindImageMemory(device_data->device, 16518a1362adSmaya data->font_image, 16528a1362adSmaya data->font_mem, 0)); 16538a1362adSmaya 16548a1362adSmaya /* Font image view */ 16558a1362adSmaya VkImageViewCreateInfo view_info = {}; 16568a1362adSmaya view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 16578a1362adSmaya view_info.image = data->font_image; 16588a1362adSmaya view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 16598a1362adSmaya view_info.format = VK_FORMAT_R8G8B8A8_UNORM; 16608a1362adSmaya view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 16618a1362adSmaya view_info.subresourceRange.levelCount = 1; 16628a1362adSmaya view_info.subresourceRange.layerCount = 1; 16638a1362adSmaya VK_CHECK(device_data->vtable.CreateImageView(device_data->device, &view_info, 16648a1362adSmaya NULL, &data->font_image_view)); 16658a1362adSmaya 16668a1362adSmaya /* Descriptor set */ 16678a1362adSmaya VkDescriptorImageInfo desc_image[1] = {}; 16688a1362adSmaya desc_image[0].sampler = data->font_sampler; 16698a1362adSmaya desc_image[0].imageView = data->font_image_view; 16708a1362adSmaya desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 16718a1362adSmaya VkWriteDescriptorSet write_desc[1] = {}; 16728a1362adSmaya write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 16738a1362adSmaya write_desc[0].dstSet = data->descriptor_set; 16748a1362adSmaya write_desc[0].descriptorCount = 1; 16758a1362adSmaya write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 16768a1362adSmaya write_desc[0].pImageInfo = desc_image; 16778a1362adSmaya device_data->vtable.UpdateDescriptorSets(device_data->device, 1, write_desc, 0, NULL); 16788a1362adSmaya} 16798a1362adSmaya 16808a1362adSmayastatic void setup_swapchain_data(struct swapchain_data *data, 16818a1362adSmaya const VkSwapchainCreateInfoKHR *pCreateInfo) 16828a1362adSmaya{ 16838a1362adSmaya data->width = pCreateInfo->imageExtent.width; 16848a1362adSmaya data->height = pCreateInfo->imageExtent.height; 16858a1362adSmaya data->format = pCreateInfo->imageFormat; 16868a1362adSmaya 16878a1362adSmaya data->imgui_context = ImGui::CreateContext(); 16888a1362adSmaya ImGui::SetCurrentContext(data->imgui_context); 16898a1362adSmaya 16908a1362adSmaya ImGui::GetIO().IniFilename = NULL; 16918a1362adSmaya ImGui::GetIO().DisplaySize = ImVec2((float)data->width, (float)data->height); 16928a1362adSmaya 16938a1362adSmaya struct device_data *device_data = data->device; 16948a1362adSmaya 16958a1362adSmaya /* Render pass */ 16968a1362adSmaya VkAttachmentDescription attachment_desc = {}; 16978a1362adSmaya attachment_desc.format = pCreateInfo->imageFormat; 16988a1362adSmaya attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT; 16998a1362adSmaya attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 17008a1362adSmaya attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 17018a1362adSmaya attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 17028a1362adSmaya attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 17038a1362adSmaya attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 17048a1362adSmaya attachment_desc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 17058a1362adSmaya VkAttachmentReference color_attachment = {}; 17068a1362adSmaya color_attachment.attachment = 0; 17078a1362adSmaya color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 17088a1362adSmaya VkSubpassDescription subpass = {}; 17098a1362adSmaya subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 17108a1362adSmaya subpass.colorAttachmentCount = 1; 17118a1362adSmaya subpass.pColorAttachments = &color_attachment; 17128a1362adSmaya VkSubpassDependency dependency = {}; 17138a1362adSmaya dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 17148a1362adSmaya dependency.dstSubpass = 0; 17158a1362adSmaya dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 17168a1362adSmaya dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 17178a1362adSmaya dependency.srcAccessMask = 0; 17188a1362adSmaya dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 17198a1362adSmaya VkRenderPassCreateInfo render_pass_info = {}; 17208a1362adSmaya render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 17218a1362adSmaya render_pass_info.attachmentCount = 1; 17228a1362adSmaya render_pass_info.pAttachments = &attachment_desc; 17238a1362adSmaya render_pass_info.subpassCount = 1; 17248a1362adSmaya render_pass_info.pSubpasses = &subpass; 17258a1362adSmaya render_pass_info.dependencyCount = 1; 17268a1362adSmaya render_pass_info.pDependencies = &dependency; 17278a1362adSmaya VK_CHECK(device_data->vtable.CreateRenderPass(device_data->device, 17288a1362adSmaya &render_pass_info, 17298a1362adSmaya NULL, &data->render_pass)); 17308a1362adSmaya 17318a1362adSmaya setup_swapchain_data_pipeline(data); 17328a1362adSmaya 17338a1362adSmaya VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, 17348a1362adSmaya data->swapchain, 17358a1362adSmaya &data->n_images, 17368a1362adSmaya NULL)); 17378a1362adSmaya 17388a1362adSmaya data->images = ralloc_array(data, VkImage, data->n_images); 17398a1362adSmaya data->image_views = ralloc_array(data, VkImageView, data->n_images); 17408a1362adSmaya data->framebuffers = ralloc_array(data, VkFramebuffer, data->n_images); 17418a1362adSmaya 17428a1362adSmaya VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, 17438a1362adSmaya data->swapchain, 17448a1362adSmaya &data->n_images, 17458a1362adSmaya data->images)); 17468a1362adSmaya 17478a1362adSmaya /* Image views */ 17488a1362adSmaya VkImageViewCreateInfo view_info = {}; 17498a1362adSmaya view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 17508a1362adSmaya view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 17518a1362adSmaya view_info.format = pCreateInfo->imageFormat; 17528a1362adSmaya view_info.components.r = VK_COMPONENT_SWIZZLE_R; 17538a1362adSmaya view_info.components.g = VK_COMPONENT_SWIZZLE_G; 17548a1362adSmaya view_info.components.b = VK_COMPONENT_SWIZZLE_B; 17558a1362adSmaya view_info.components.a = VK_COMPONENT_SWIZZLE_A; 17568a1362adSmaya view_info.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 17578a1362adSmaya for (uint32_t i = 0; i < data->n_images; i++) { 17588a1362adSmaya view_info.image = data->images[i]; 17598a1362adSmaya VK_CHECK(device_data->vtable.CreateImageView(device_data->device, 17608a1362adSmaya &view_info, NULL, 17618a1362adSmaya &data->image_views[i])); 17628a1362adSmaya } 17638a1362adSmaya 17648a1362adSmaya /* Framebuffers */ 17658a1362adSmaya VkImageView attachment[1]; 17668a1362adSmaya VkFramebufferCreateInfo fb_info = {}; 17678a1362adSmaya fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 17688a1362adSmaya fb_info.renderPass = data->render_pass; 17698a1362adSmaya fb_info.attachmentCount = 1; 17708a1362adSmaya fb_info.pAttachments = attachment; 17718a1362adSmaya fb_info.width = data->width; 17728a1362adSmaya fb_info.height = data->height; 17738a1362adSmaya fb_info.layers = 1; 17748a1362adSmaya for (uint32_t i = 0; i < data->n_images; i++) { 17758a1362adSmaya attachment[0] = data->image_views[i]; 17768a1362adSmaya VK_CHECK(device_data->vtable.CreateFramebuffer(device_data->device, &fb_info, 17778a1362adSmaya NULL, &data->framebuffers[i])); 17788a1362adSmaya } 17798a1362adSmaya 17808a1362adSmaya /* Command buffer pool */ 17818a1362adSmaya VkCommandPoolCreateInfo cmd_buffer_pool_info = {}; 17828a1362adSmaya cmd_buffer_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 17838a1362adSmaya cmd_buffer_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; 17848a1362adSmaya cmd_buffer_pool_info.queueFamilyIndex = device_data->graphic_queue->family_index; 17858a1362adSmaya VK_CHECK(device_data->vtable.CreateCommandPool(device_data->device, 17868a1362adSmaya &cmd_buffer_pool_info, 17878a1362adSmaya NULL, &data->command_pool)); 17888a1362adSmaya} 17898a1362adSmaya 17908a1362adSmayastatic void shutdown_swapchain_data(struct swapchain_data *data) 17918a1362adSmaya{ 17928a1362adSmaya struct device_data *device_data = data->device; 17938a1362adSmaya 17948a1362adSmaya list_for_each_entry_safe(struct overlay_draw, draw, &data->draws, link) { 17957ec681f3Smrg device_data->vtable.DestroySemaphore(device_data->device, draw->cross_engine_semaphore, NULL); 17968a1362adSmaya device_data->vtable.DestroySemaphore(device_data->device, draw->semaphore, NULL); 17978a1362adSmaya device_data->vtable.DestroyFence(device_data->device, draw->fence, NULL); 17988a1362adSmaya device_data->vtable.DestroyBuffer(device_data->device, draw->vertex_buffer, NULL); 17998a1362adSmaya device_data->vtable.DestroyBuffer(device_data->device, draw->index_buffer, NULL); 18008a1362adSmaya device_data->vtable.FreeMemory(device_data->device, draw->vertex_buffer_mem, NULL); 18018a1362adSmaya device_data->vtable.FreeMemory(device_data->device, draw->index_buffer_mem, NULL); 18028a1362adSmaya } 18038a1362adSmaya 18048a1362adSmaya for (uint32_t i = 0; i < data->n_images; i++) { 18058a1362adSmaya device_data->vtable.DestroyImageView(device_data->device, data->image_views[i], NULL); 18068a1362adSmaya device_data->vtable.DestroyFramebuffer(device_data->device, data->framebuffers[i], NULL); 18078a1362adSmaya } 18088a1362adSmaya 18098a1362adSmaya device_data->vtable.DestroyRenderPass(device_data->device, data->render_pass, NULL); 18108a1362adSmaya 18118a1362adSmaya device_data->vtable.DestroyCommandPool(device_data->device, data->command_pool, NULL); 18128a1362adSmaya 18138a1362adSmaya device_data->vtable.DestroyPipeline(device_data->device, data->pipeline, NULL); 18148a1362adSmaya device_data->vtable.DestroyPipelineLayout(device_data->device, data->pipeline_layout, NULL); 18158a1362adSmaya 18168a1362adSmaya device_data->vtable.DestroyDescriptorPool(device_data->device, 18178a1362adSmaya data->descriptor_pool, NULL); 18188a1362adSmaya device_data->vtable.DestroyDescriptorSetLayout(device_data->device, 18198a1362adSmaya data->descriptor_layout, NULL); 18208a1362adSmaya 18218a1362adSmaya device_data->vtable.DestroySampler(device_data->device, data->font_sampler, NULL); 18228a1362adSmaya device_data->vtable.DestroyImageView(device_data->device, data->font_image_view, NULL); 18238a1362adSmaya device_data->vtable.DestroyImage(device_data->device, data->font_image, NULL); 18248a1362adSmaya device_data->vtable.FreeMemory(device_data->device, data->font_mem, NULL); 18258a1362adSmaya 18268a1362adSmaya device_data->vtable.DestroyBuffer(device_data->device, data->upload_font_buffer, NULL); 18278a1362adSmaya device_data->vtable.FreeMemory(device_data->device, data->upload_font_buffer_mem, NULL); 18288a1362adSmaya 18298a1362adSmaya ImGui::DestroyContext(data->imgui_context); 18308a1362adSmaya} 18318a1362adSmaya 18328a1362adSmayastatic struct overlay_draw *before_present(struct swapchain_data *swapchain_data, 18338a1362adSmaya struct queue_data *present_queue, 18348a1362adSmaya const VkSemaphore *wait_semaphores, 18358a1362adSmaya unsigned n_wait_semaphores, 18368a1362adSmaya unsigned imageIndex) 18378a1362adSmaya{ 18388a1362adSmaya struct instance_data *instance_data = swapchain_data->device->instance; 18398a1362adSmaya struct overlay_draw *draw = NULL; 18408a1362adSmaya 18418a1362adSmaya snapshot_swapchain_frame(swapchain_data); 18428a1362adSmaya 18438a1362adSmaya if (!instance_data->params.no_display && swapchain_data->n_frames > 0) { 18448a1362adSmaya compute_swapchain_display(swapchain_data); 18458a1362adSmaya draw = render_swapchain_display(swapchain_data, present_queue, 18468a1362adSmaya wait_semaphores, n_wait_semaphores, 18478a1362adSmaya imageIndex); 18488a1362adSmaya } 18498a1362adSmaya 18508a1362adSmaya return draw; 18518a1362adSmaya} 18528a1362adSmaya 18538a1362adSmayastatic VkResult overlay_CreateSwapchainKHR( 18548a1362adSmaya VkDevice device, 18558a1362adSmaya const VkSwapchainCreateInfoKHR* pCreateInfo, 18568a1362adSmaya const VkAllocationCallbacks* pAllocator, 18578a1362adSmaya VkSwapchainKHR* pSwapchain) 18588a1362adSmaya{ 18597ec681f3Smrg struct device_data *device_data = FIND(struct device_data, device); 18608a1362adSmaya VkResult result = device_data->vtable.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 18618a1362adSmaya if (result != VK_SUCCESS) return result; 18628a1362adSmaya 18638a1362adSmaya struct swapchain_data *swapchain_data = new_swapchain_data(*pSwapchain, device_data); 18648a1362adSmaya setup_swapchain_data(swapchain_data, pCreateInfo); 18658a1362adSmaya return result; 18668a1362adSmaya} 18678a1362adSmaya 18688a1362adSmayastatic void overlay_DestroySwapchainKHR( 18698a1362adSmaya VkDevice device, 18708a1362adSmaya VkSwapchainKHR swapchain, 18718a1362adSmaya const VkAllocationCallbacks* pAllocator) 18728a1362adSmaya{ 18737ec681f3Smrg if (swapchain == VK_NULL_HANDLE) { 18747ec681f3Smrg struct device_data *device_data = FIND(struct device_data, device); 18757ec681f3Smrg device_data->vtable.DestroySwapchainKHR(device, swapchain, pAllocator); 18767ec681f3Smrg return; 18777ec681f3Smrg } 18787ec681f3Smrg 18797ec681f3Smrg struct swapchain_data *swapchain_data = 18807ec681f3Smrg FIND(struct swapchain_data, swapchain); 18818a1362adSmaya 18828a1362adSmaya shutdown_swapchain_data(swapchain_data); 18838a1362adSmaya swapchain_data->device->vtable.DestroySwapchainKHR(device, swapchain, pAllocator); 18848a1362adSmaya destroy_swapchain_data(swapchain_data); 18858a1362adSmaya} 18868a1362adSmaya 18878a1362adSmayastatic VkResult overlay_QueuePresentKHR( 18888a1362adSmaya VkQueue queue, 18898a1362adSmaya const VkPresentInfoKHR* pPresentInfo) 18908a1362adSmaya{ 18917ec681f3Smrg struct queue_data *queue_data = FIND(struct queue_data, queue); 18928a1362adSmaya struct device_data *device_data = queue_data->device; 18938a1362adSmaya struct instance_data *instance_data = device_data->instance; 18948a1362adSmaya uint32_t query_results[OVERLAY_QUERY_COUNT]; 18958a1362adSmaya 18968a1362adSmaya device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_frame]++; 18978a1362adSmaya 18988a1362adSmaya if (list_length(&queue_data->running_command_buffer) > 0) { 18998a1362adSmaya /* Before getting the query results, make sure the operations have 19008a1362adSmaya * completed. 19018a1362adSmaya */ 19027ec681f3Smrg VK_CHECK(device_data->vtable.ResetFences(device_data->device, 19037ec681f3Smrg 1, &queue_data->queries_fence)); 19047ec681f3Smrg VK_CHECK(device_data->vtable.QueueSubmit(queue, 0, NULL, queue_data->queries_fence)); 19057ec681f3Smrg VK_CHECK(device_data->vtable.WaitForFences(device_data->device, 19067ec681f3Smrg 1, &queue_data->queries_fence, 19077ec681f3Smrg VK_FALSE, UINT64_MAX)); 19088a1362adSmaya 19098a1362adSmaya /* Now get the results. */ 19108a1362adSmaya list_for_each_entry_safe(struct command_buffer_data, cmd_buffer_data, 19118a1362adSmaya &queue_data->running_command_buffer, link) { 19128a1362adSmaya list_delinit(&cmd_buffer_data->link); 19138a1362adSmaya 19148a1362adSmaya if (cmd_buffer_data->pipeline_query_pool) { 19158a1362adSmaya memset(query_results, 0, sizeof(query_results)); 19167ec681f3Smrg VK_CHECK(device_data->vtable.GetQueryPoolResults(device_data->device, 19177ec681f3Smrg cmd_buffer_data->pipeline_query_pool, 19187ec681f3Smrg cmd_buffer_data->query_index, 1, 19197ec681f3Smrg sizeof(uint32_t) * OVERLAY_QUERY_COUNT, 19207ec681f3Smrg query_results, 0, VK_QUERY_RESULT_WAIT_BIT)); 19218a1362adSmaya 19228a1362adSmaya for (uint32_t i = OVERLAY_PARAM_ENABLED_vertices; 19238a1362adSmaya i <= OVERLAY_PARAM_ENABLED_compute_invocations; i++) { 19248a1362adSmaya device_data->frame_stats.stats[i] += query_results[i - OVERLAY_PARAM_ENABLED_vertices]; 19258a1362adSmaya } 19268a1362adSmaya } 19278a1362adSmaya if (cmd_buffer_data->timestamp_query_pool) { 19288a1362adSmaya uint64_t gpu_timestamps[2] = { 0 }; 19297ec681f3Smrg VK_CHECK(device_data->vtable.GetQueryPoolResults(device_data->device, 19307ec681f3Smrg cmd_buffer_data->timestamp_query_pool, 19317ec681f3Smrg cmd_buffer_data->query_index * 2, 2, 19327ec681f3Smrg 2 * sizeof(uint64_t), gpu_timestamps, sizeof(uint64_t), 19337ec681f3Smrg VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT)); 19348a1362adSmaya 19358a1362adSmaya gpu_timestamps[0] &= queue_data->timestamp_mask; 19368a1362adSmaya gpu_timestamps[1] &= queue_data->timestamp_mask; 19378a1362adSmaya device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_gpu_timing] += 19388a1362adSmaya (gpu_timestamps[1] - gpu_timestamps[0]) * 19398a1362adSmaya device_data->properties.limits.timestampPeriod; 19408a1362adSmaya } 19418a1362adSmaya } 19428a1362adSmaya } 19438a1362adSmaya 19448a1362adSmaya /* Otherwise we need to add our overlay drawing semaphore to the list of 19458a1362adSmaya * semaphores to wait on. If we don't do that the presented picture might 19468a1362adSmaya * be have incomplete overlay drawings. 19478a1362adSmaya */ 19488a1362adSmaya VkResult result = VK_SUCCESS; 19498a1362adSmaya if (instance_data->params.no_display) { 19508a1362adSmaya for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 19518a1362adSmaya VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; 19527ec681f3Smrg struct swapchain_data *swapchain_data = 19537ec681f3Smrg FIND(struct swapchain_data, swapchain); 19547ec681f3Smrg 19557ec681f3Smrg uint32_t image_index = pPresentInfo->pImageIndices[i]; 19568a1362adSmaya 19578a1362adSmaya before_present(swapchain_data, 19588a1362adSmaya queue_data, 19598a1362adSmaya pPresentInfo->pWaitSemaphores, 19608a1362adSmaya pPresentInfo->waitSemaphoreCount, 19617ec681f3Smrg image_index); 19627ec681f3Smrg 19637ec681f3Smrg VkPresentInfoKHR present_info = *pPresentInfo; 19647ec681f3Smrg present_info.swapchainCount = 1; 19657ec681f3Smrg present_info.pSwapchains = &swapchain; 19667ec681f3Smrg present_info.pImageIndices = &image_index; 19677ec681f3Smrg 19687ec681f3Smrg uint64_t ts0 = os_time_get(); 19697ec681f3Smrg result = queue_data->device->vtable.QueuePresentKHR(queue, &present_info); 19707ec681f3Smrg uint64_t ts1 = os_time_get(); 19717ec681f3Smrg swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_present_timing] += ts1 - ts0; 19728a1362adSmaya } 19738a1362adSmaya } else { 19748a1362adSmaya for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 19758a1362adSmaya VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; 19767ec681f3Smrg struct swapchain_data *swapchain_data = 19777ec681f3Smrg FIND(struct swapchain_data, swapchain); 19787ec681f3Smrg 19797ec681f3Smrg uint32_t image_index = pPresentInfo->pImageIndices[i]; 19807ec681f3Smrg 19818a1362adSmaya VkPresentInfoKHR present_info = *pPresentInfo; 19828a1362adSmaya present_info.swapchainCount = 1; 19838a1362adSmaya present_info.pSwapchains = &swapchain; 19847ec681f3Smrg present_info.pImageIndices = &image_index; 19858a1362adSmaya 19868a1362adSmaya struct overlay_draw *draw = before_present(swapchain_data, 19878a1362adSmaya queue_data, 19888a1362adSmaya pPresentInfo->pWaitSemaphores, 19898a1362adSmaya pPresentInfo->waitSemaphoreCount, 19908a1362adSmaya image_index); 19918a1362adSmaya 19928a1362adSmaya /* Because the submission of the overlay draw waits on the semaphores 19938a1362adSmaya * handed for present, we don't need to have this present operation 19948a1362adSmaya * wait on them as well, we can just wait on the overlay submission 19958a1362adSmaya * semaphore. 19968a1362adSmaya */ 19978a1362adSmaya present_info.pWaitSemaphores = &draw->semaphore; 19988a1362adSmaya present_info.waitSemaphoreCount = 1; 19998a1362adSmaya 20007ec681f3Smrg uint64_t ts0 = os_time_get(); 20018a1362adSmaya VkResult chain_result = queue_data->device->vtable.QueuePresentKHR(queue, &present_info); 20027ec681f3Smrg uint64_t ts1 = os_time_get(); 20037ec681f3Smrg swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_present_timing] += ts1 - ts0; 20048a1362adSmaya if (pPresentInfo->pResults) 20058a1362adSmaya pPresentInfo->pResults[i] = chain_result; 20068a1362adSmaya if (chain_result != VK_SUCCESS && result == VK_SUCCESS) 20078a1362adSmaya result = chain_result; 20088a1362adSmaya } 20098a1362adSmaya } 20108a1362adSmaya return result; 20118a1362adSmaya} 20128a1362adSmaya 20138a1362adSmayastatic VkResult overlay_AcquireNextImageKHR( 20148a1362adSmaya VkDevice device, 20158a1362adSmaya VkSwapchainKHR swapchain, 20168a1362adSmaya uint64_t timeout, 20178a1362adSmaya VkSemaphore semaphore, 20188a1362adSmaya VkFence fence, 20198a1362adSmaya uint32_t* pImageIndex) 20208a1362adSmaya{ 20217ec681f3Smrg struct swapchain_data *swapchain_data = 20227ec681f3Smrg FIND(struct swapchain_data, swapchain); 20238a1362adSmaya struct device_data *device_data = swapchain_data->device; 20248a1362adSmaya 20258a1362adSmaya uint64_t ts0 = os_time_get(); 20268a1362adSmaya VkResult result = device_data->vtable.AcquireNextImageKHR(device, swapchain, timeout, 20278a1362adSmaya semaphore, fence, pImageIndex); 20288a1362adSmaya uint64_t ts1 = os_time_get(); 20298a1362adSmaya 20308a1362adSmaya swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire_timing] += ts1 - ts0; 20318a1362adSmaya swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire]++; 20328a1362adSmaya 20338a1362adSmaya return result; 20348a1362adSmaya} 20358a1362adSmaya 20368a1362adSmayastatic VkResult overlay_AcquireNextImage2KHR( 20378a1362adSmaya VkDevice device, 20388a1362adSmaya const VkAcquireNextImageInfoKHR* pAcquireInfo, 20398a1362adSmaya uint32_t* pImageIndex) 20408a1362adSmaya{ 20417ec681f3Smrg struct swapchain_data *swapchain_data = 20427ec681f3Smrg FIND(struct swapchain_data, pAcquireInfo->swapchain); 20438a1362adSmaya struct device_data *device_data = swapchain_data->device; 20448a1362adSmaya 20458a1362adSmaya uint64_t ts0 = os_time_get(); 20468a1362adSmaya VkResult result = device_data->vtable.AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex); 20478a1362adSmaya uint64_t ts1 = os_time_get(); 20488a1362adSmaya 20498a1362adSmaya swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire_timing] += ts1 - ts0; 20508a1362adSmaya swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire]++; 20518a1362adSmaya 20528a1362adSmaya return result; 20538a1362adSmaya} 20548a1362adSmaya 20558a1362adSmayastatic void overlay_CmdDraw( 20568a1362adSmaya VkCommandBuffer commandBuffer, 20578a1362adSmaya uint32_t vertexCount, 20588a1362adSmaya uint32_t instanceCount, 20598a1362adSmaya uint32_t firstVertex, 20608a1362adSmaya uint32_t firstInstance) 20618a1362adSmaya{ 20627ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 20637ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 20648a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw]++; 20658a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 20668a1362adSmaya device_data->vtable.CmdDraw(commandBuffer, vertexCount, instanceCount, 20678a1362adSmaya firstVertex, firstInstance); 20688a1362adSmaya} 20698a1362adSmaya 20708a1362adSmayastatic void overlay_CmdDrawIndexed( 20718a1362adSmaya VkCommandBuffer commandBuffer, 20728a1362adSmaya uint32_t indexCount, 20738a1362adSmaya uint32_t instanceCount, 20748a1362adSmaya uint32_t firstIndex, 20758a1362adSmaya int32_t vertexOffset, 20768a1362adSmaya uint32_t firstInstance) 20778a1362adSmaya{ 20787ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 20797ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 20808a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed]++; 20818a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 20828a1362adSmaya device_data->vtable.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, 20838a1362adSmaya firstIndex, vertexOffset, firstInstance); 20848a1362adSmaya} 20858a1362adSmaya 20868a1362adSmayastatic void overlay_CmdDrawIndirect( 20878a1362adSmaya VkCommandBuffer commandBuffer, 20888a1362adSmaya VkBuffer buffer, 20898a1362adSmaya VkDeviceSize offset, 20908a1362adSmaya uint32_t drawCount, 20918a1362adSmaya uint32_t stride) 20928a1362adSmaya{ 20937ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 20947ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 20958a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indirect]++; 20968a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 20978a1362adSmaya device_data->vtable.CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride); 20988a1362adSmaya} 20998a1362adSmaya 21008a1362adSmayastatic void overlay_CmdDrawIndexedIndirect( 21018a1362adSmaya VkCommandBuffer commandBuffer, 21028a1362adSmaya VkBuffer buffer, 21038a1362adSmaya VkDeviceSize offset, 21048a1362adSmaya uint32_t drawCount, 21058a1362adSmaya uint32_t stride) 21068a1362adSmaya{ 21077ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 21087ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 21098a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed_indirect]++; 21108a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 21118a1362adSmaya device_data->vtable.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride); 21128a1362adSmaya} 21138a1362adSmaya 21147ec681f3Smrgstatic void overlay_CmdDrawIndirectCount( 21158a1362adSmaya VkCommandBuffer commandBuffer, 21168a1362adSmaya VkBuffer buffer, 21178a1362adSmaya VkDeviceSize offset, 21188a1362adSmaya VkBuffer countBuffer, 21198a1362adSmaya VkDeviceSize countBufferOffset, 21208a1362adSmaya uint32_t maxDrawCount, 21218a1362adSmaya uint32_t stride) 21228a1362adSmaya{ 21237ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 21247ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 21258a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indirect_count]++; 21268a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 21277ec681f3Smrg device_data->vtable.CmdDrawIndirectCount(commandBuffer, buffer, offset, 21287ec681f3Smrg countBuffer, countBufferOffset, 21297ec681f3Smrg maxDrawCount, stride); 21308a1362adSmaya} 21318a1362adSmaya 21327ec681f3Smrgstatic void overlay_CmdDrawIndexedIndirectCount( 21338a1362adSmaya VkCommandBuffer commandBuffer, 21348a1362adSmaya VkBuffer buffer, 21358a1362adSmaya VkDeviceSize offset, 21368a1362adSmaya VkBuffer countBuffer, 21378a1362adSmaya VkDeviceSize countBufferOffset, 21388a1362adSmaya uint32_t maxDrawCount, 21398a1362adSmaya uint32_t stride) 21408a1362adSmaya{ 21417ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 21427ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 21438a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed_indirect_count]++; 21448a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 21457ec681f3Smrg device_data->vtable.CmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, 21467ec681f3Smrg countBuffer, countBufferOffset, 21477ec681f3Smrg maxDrawCount, stride); 21488a1362adSmaya} 21498a1362adSmaya 21508a1362adSmayastatic void overlay_CmdDispatch( 21518a1362adSmaya VkCommandBuffer commandBuffer, 21528a1362adSmaya uint32_t groupCountX, 21538a1362adSmaya uint32_t groupCountY, 21548a1362adSmaya uint32_t groupCountZ) 21558a1362adSmaya{ 21567ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 21577ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 21588a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_dispatch]++; 21598a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 21608a1362adSmaya device_data->vtable.CmdDispatch(commandBuffer, groupCountX, groupCountY, groupCountZ); 21618a1362adSmaya} 21628a1362adSmaya 21638a1362adSmayastatic void overlay_CmdDispatchIndirect( 21648a1362adSmaya VkCommandBuffer commandBuffer, 21658a1362adSmaya VkBuffer buffer, 21668a1362adSmaya VkDeviceSize offset) 21678a1362adSmaya{ 21687ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 21697ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 21708a1362adSmaya cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_dispatch_indirect]++; 21718a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 21728a1362adSmaya device_data->vtable.CmdDispatchIndirect(commandBuffer, buffer, offset); 21738a1362adSmaya} 21748a1362adSmaya 21758a1362adSmayastatic void overlay_CmdBindPipeline( 21768a1362adSmaya VkCommandBuffer commandBuffer, 21778a1362adSmaya VkPipelineBindPoint pipelineBindPoint, 21788a1362adSmaya VkPipeline pipeline) 21798a1362adSmaya{ 21807ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 21817ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 21828a1362adSmaya switch (pipelineBindPoint) { 21838a1362adSmaya case VK_PIPELINE_BIND_POINT_GRAPHICS: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_graphics]++; break; 21848a1362adSmaya case VK_PIPELINE_BIND_POINT_COMPUTE: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_compute]++; break; 21858a1362adSmaya case VK_PIPELINE_BIND_POINT_RAY_TRACING_NV: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_raytracing]++; break; 21868a1362adSmaya default: break; 21878a1362adSmaya } 21888a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 21898a1362adSmaya device_data->vtable.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 21908a1362adSmaya} 21918a1362adSmaya 21928a1362adSmayastatic VkResult overlay_BeginCommandBuffer( 21938a1362adSmaya VkCommandBuffer commandBuffer, 21948a1362adSmaya const VkCommandBufferBeginInfo* pBeginInfo) 21958a1362adSmaya{ 21967ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 21977ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 21988a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 21998a1362adSmaya 22008a1362adSmaya memset(&cmd_buffer_data->stats, 0, sizeof(cmd_buffer_data->stats)); 22018a1362adSmaya 22028a1362adSmaya /* We don't record any query in secondary command buffers, just make sure 22038a1362adSmaya * we have the right inheritance. 22048a1362adSmaya */ 22058a1362adSmaya if (cmd_buffer_data->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) { 22068a1362adSmaya VkCommandBufferBeginInfo *begin_info = (VkCommandBufferBeginInfo *) 22078a1362adSmaya clone_chain((const struct VkBaseInStructure *)pBeginInfo); 22088a1362adSmaya VkCommandBufferInheritanceInfo *parent_inhe_info = (VkCommandBufferInheritanceInfo *) 22098a1362adSmaya vk_find_struct(begin_info, COMMAND_BUFFER_INHERITANCE_INFO); 22108a1362adSmaya VkCommandBufferInheritanceInfo inhe_info = { 22118a1362adSmaya VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 22128a1362adSmaya NULL, 22138a1362adSmaya VK_NULL_HANDLE, 22148a1362adSmaya 0, 22158a1362adSmaya VK_NULL_HANDLE, 22168a1362adSmaya VK_FALSE, 22178a1362adSmaya 0, 22188a1362adSmaya overlay_query_flags, 22198a1362adSmaya }; 22208a1362adSmaya 22218a1362adSmaya if (parent_inhe_info) 22228a1362adSmaya parent_inhe_info->pipelineStatistics = overlay_query_flags; 22238a1362adSmaya else { 22248a1362adSmaya inhe_info.pNext = begin_info->pNext; 22258a1362adSmaya begin_info->pNext = &inhe_info; 22268a1362adSmaya } 22278a1362adSmaya 22288a1362adSmaya VkResult result = device_data->vtable.BeginCommandBuffer(commandBuffer, pBeginInfo); 22298a1362adSmaya 22308a1362adSmaya if (!parent_inhe_info) 22318a1362adSmaya begin_info->pNext = inhe_info.pNext; 22328a1362adSmaya 22338a1362adSmaya free_chain((struct VkBaseOutStructure *)begin_info); 22348a1362adSmaya 22358a1362adSmaya return result; 22368a1362adSmaya } 22378a1362adSmaya 22388a1362adSmaya /* Otherwise record a begin query as first command. */ 22398a1362adSmaya VkResult result = device_data->vtable.BeginCommandBuffer(commandBuffer, pBeginInfo); 22408a1362adSmaya 22418a1362adSmaya if (result == VK_SUCCESS) { 22428a1362adSmaya if (cmd_buffer_data->pipeline_query_pool) { 22438a1362adSmaya device_data->vtable.CmdResetQueryPool(commandBuffer, 22448a1362adSmaya cmd_buffer_data->pipeline_query_pool, 22458a1362adSmaya cmd_buffer_data->query_index, 1); 22468a1362adSmaya } 22478a1362adSmaya if (cmd_buffer_data->timestamp_query_pool) { 22488a1362adSmaya device_data->vtable.CmdResetQueryPool(commandBuffer, 22498a1362adSmaya cmd_buffer_data->timestamp_query_pool, 22508a1362adSmaya cmd_buffer_data->query_index * 2, 2); 22518a1362adSmaya } 22528a1362adSmaya if (cmd_buffer_data->pipeline_query_pool) { 22538a1362adSmaya device_data->vtable.CmdBeginQuery(commandBuffer, 22548a1362adSmaya cmd_buffer_data->pipeline_query_pool, 22558a1362adSmaya cmd_buffer_data->query_index, 0); 22568a1362adSmaya } 22578a1362adSmaya if (cmd_buffer_data->timestamp_query_pool) { 22588a1362adSmaya device_data->vtable.CmdWriteTimestamp(commandBuffer, 22598a1362adSmaya VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 22608a1362adSmaya cmd_buffer_data->timestamp_query_pool, 22618a1362adSmaya cmd_buffer_data->query_index * 2); 22628a1362adSmaya } 22638a1362adSmaya } 22648a1362adSmaya 22658a1362adSmaya return result; 22668a1362adSmaya} 22678a1362adSmaya 22688a1362adSmayastatic VkResult overlay_EndCommandBuffer( 22698a1362adSmaya VkCommandBuffer commandBuffer) 22708a1362adSmaya{ 22717ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 22727ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 22738a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 22748a1362adSmaya 22758a1362adSmaya if (cmd_buffer_data->timestamp_query_pool) { 22768a1362adSmaya device_data->vtable.CmdWriteTimestamp(commandBuffer, 22778a1362adSmaya VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 22788a1362adSmaya cmd_buffer_data->timestamp_query_pool, 22798a1362adSmaya cmd_buffer_data->query_index * 2 + 1); 22808a1362adSmaya } 22818a1362adSmaya if (cmd_buffer_data->pipeline_query_pool) { 22828a1362adSmaya device_data->vtable.CmdEndQuery(commandBuffer, 22838a1362adSmaya cmd_buffer_data->pipeline_query_pool, 22848a1362adSmaya cmd_buffer_data->query_index); 22858a1362adSmaya } 22868a1362adSmaya 22878a1362adSmaya return device_data->vtable.EndCommandBuffer(commandBuffer); 22888a1362adSmaya} 22898a1362adSmaya 22908a1362adSmayastatic VkResult overlay_ResetCommandBuffer( 22918a1362adSmaya VkCommandBuffer commandBuffer, 22928a1362adSmaya VkCommandBufferResetFlags flags) 22938a1362adSmaya{ 22947ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 22957ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 22968a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 22978a1362adSmaya 22988a1362adSmaya memset(&cmd_buffer_data->stats, 0, sizeof(cmd_buffer_data->stats)); 22998a1362adSmaya 23008a1362adSmaya return device_data->vtable.ResetCommandBuffer(commandBuffer, flags); 23018a1362adSmaya} 23028a1362adSmaya 23038a1362adSmayastatic void overlay_CmdExecuteCommands( 23048a1362adSmaya VkCommandBuffer commandBuffer, 23058a1362adSmaya uint32_t commandBufferCount, 23068a1362adSmaya const VkCommandBuffer* pCommandBuffers) 23078a1362adSmaya{ 23087ec681f3Smrg struct command_buffer_data *cmd_buffer_data = 23097ec681f3Smrg FIND(struct command_buffer_data, commandBuffer); 23108a1362adSmaya struct device_data *device_data = cmd_buffer_data->device; 23118a1362adSmaya 23128a1362adSmaya /* Add the stats of the executed command buffers to the primary one. */ 23138a1362adSmaya for (uint32_t c = 0; c < commandBufferCount; c++) { 23147ec681f3Smrg struct command_buffer_data *sec_cmd_buffer_data = 23157ec681f3Smrg FIND(struct command_buffer_data, pCommandBuffers[c]); 23168a1362adSmaya 23178a1362adSmaya for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) 23188a1362adSmaya cmd_buffer_data->stats.stats[s] += sec_cmd_buffer_data->stats.stats[s]; 23198a1362adSmaya } 23208a1362adSmaya 23218a1362adSmaya device_data->vtable.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers); 23228a1362adSmaya} 23238a1362adSmaya 23248a1362adSmayastatic VkResult overlay_AllocateCommandBuffers( 23258a1362adSmaya VkDevice device, 23268a1362adSmaya const VkCommandBufferAllocateInfo* pAllocateInfo, 23278a1362adSmaya VkCommandBuffer* pCommandBuffers) 23288a1362adSmaya{ 23297ec681f3Smrg struct device_data *device_data = FIND(struct device_data, device); 23308a1362adSmaya VkResult result = 23318a1362adSmaya device_data->vtable.AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers); 23328a1362adSmaya if (result != VK_SUCCESS) 23338a1362adSmaya return result; 23348a1362adSmaya 23358a1362adSmaya VkQueryPool pipeline_query_pool = VK_NULL_HANDLE; 23368a1362adSmaya VkQueryPool timestamp_query_pool = VK_NULL_HANDLE; 23378a1362adSmaya if (device_data->instance->pipeline_statistics_enabled && 23388a1362adSmaya pAllocateInfo->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 23398a1362adSmaya VkQueryPoolCreateInfo pool_info = { 23408a1362adSmaya VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 23418a1362adSmaya NULL, 23428a1362adSmaya 0, 23438a1362adSmaya VK_QUERY_TYPE_PIPELINE_STATISTICS, 23448a1362adSmaya pAllocateInfo->commandBufferCount, 23458a1362adSmaya overlay_query_flags, 23468a1362adSmaya }; 23477ec681f3Smrg VK_CHECK(device_data->vtable.CreateQueryPool(device_data->device, &pool_info, 23487ec681f3Smrg NULL, &pipeline_query_pool)); 23498a1362adSmaya } 23508a1362adSmaya if (device_data->instance->params.enabled[OVERLAY_PARAM_ENABLED_gpu_timing]) { 23518a1362adSmaya VkQueryPoolCreateInfo pool_info = { 23528a1362adSmaya VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 23538a1362adSmaya NULL, 23548a1362adSmaya 0, 23558a1362adSmaya VK_QUERY_TYPE_TIMESTAMP, 23568a1362adSmaya pAllocateInfo->commandBufferCount * 2, 23578a1362adSmaya 0, 23588a1362adSmaya }; 23597ec681f3Smrg VK_CHECK(device_data->vtable.CreateQueryPool(device_data->device, &pool_info, 23607ec681f3Smrg NULL, ×tamp_query_pool)); 23618a1362adSmaya } 23628a1362adSmaya 23638a1362adSmaya for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) { 23648a1362adSmaya new_command_buffer_data(pCommandBuffers[i], pAllocateInfo->level, 23658a1362adSmaya pipeline_query_pool, timestamp_query_pool, 23668a1362adSmaya i, device_data); 23678a1362adSmaya } 23688a1362adSmaya 23698a1362adSmaya if (pipeline_query_pool) 23708a1362adSmaya map_object(HKEY(pipeline_query_pool), (void *)(uintptr_t) pAllocateInfo->commandBufferCount); 23718a1362adSmaya if (timestamp_query_pool) 23728a1362adSmaya map_object(HKEY(timestamp_query_pool), (void *)(uintptr_t) pAllocateInfo->commandBufferCount); 23738a1362adSmaya 23748a1362adSmaya return result; 23758a1362adSmaya} 23768a1362adSmaya 23778a1362adSmayastatic void overlay_FreeCommandBuffers( 23788a1362adSmaya VkDevice device, 23798a1362adSmaya VkCommandPool commandPool, 23808a1362adSmaya uint32_t commandBufferCount, 23818a1362adSmaya const VkCommandBuffer* pCommandBuffers) 23828a1362adSmaya{ 23837ec681f3Smrg struct device_data *device_data = FIND(struct device_data, device); 23848a1362adSmaya for (uint32_t i = 0; i < commandBufferCount; i++) { 23858a1362adSmaya struct command_buffer_data *cmd_buffer_data = 23867ec681f3Smrg FIND(struct command_buffer_data, pCommandBuffers[i]); 23877ec681f3Smrg 23888a1362adSmaya /* It is legal to free a NULL command buffer*/ 23898a1362adSmaya if (!cmd_buffer_data) 23908a1362adSmaya continue; 23918a1362adSmaya 23928a1362adSmaya uint64_t count = (uintptr_t)find_object_data(HKEY(cmd_buffer_data->pipeline_query_pool)); 23938a1362adSmaya if (count == 1) { 23948a1362adSmaya unmap_object(HKEY(cmd_buffer_data->pipeline_query_pool)); 23958a1362adSmaya device_data->vtable.DestroyQueryPool(device_data->device, 23968a1362adSmaya cmd_buffer_data->pipeline_query_pool, NULL); 23978a1362adSmaya } else if (count != 0) { 23988a1362adSmaya map_object(HKEY(cmd_buffer_data->pipeline_query_pool), (void *)(uintptr_t)(count - 1)); 23998a1362adSmaya } 24008a1362adSmaya count = (uintptr_t)find_object_data(HKEY(cmd_buffer_data->timestamp_query_pool)); 24018a1362adSmaya if (count == 1) { 24028a1362adSmaya unmap_object(HKEY(cmd_buffer_data->timestamp_query_pool)); 24038a1362adSmaya device_data->vtable.DestroyQueryPool(device_data->device, 24048a1362adSmaya cmd_buffer_data->timestamp_query_pool, NULL); 24058a1362adSmaya } else if (count != 0) { 24068a1362adSmaya map_object(HKEY(cmd_buffer_data->timestamp_query_pool), (void *)(uintptr_t)(count - 1)); 24078a1362adSmaya } 24088a1362adSmaya destroy_command_buffer_data(cmd_buffer_data); 24098a1362adSmaya } 24108a1362adSmaya 24118a1362adSmaya device_data->vtable.FreeCommandBuffers(device, commandPool, 24128a1362adSmaya commandBufferCount, pCommandBuffers); 24138a1362adSmaya} 24148a1362adSmaya 24158a1362adSmayastatic VkResult overlay_QueueSubmit( 24168a1362adSmaya VkQueue queue, 24178a1362adSmaya uint32_t submitCount, 24188a1362adSmaya const VkSubmitInfo* pSubmits, 24198a1362adSmaya VkFence fence) 24208a1362adSmaya{ 24217ec681f3Smrg struct queue_data *queue_data = FIND(struct queue_data, queue); 24228a1362adSmaya struct device_data *device_data = queue_data->device; 24238a1362adSmaya 24248a1362adSmaya device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_submit]++; 24258a1362adSmaya 24268a1362adSmaya for (uint32_t s = 0; s < submitCount; s++) { 24278a1362adSmaya for (uint32_t c = 0; c < pSubmits[s].commandBufferCount; c++) { 24288a1362adSmaya struct command_buffer_data *cmd_buffer_data = 24297ec681f3Smrg FIND(struct command_buffer_data, pSubmits[s].pCommandBuffers[c]); 24308a1362adSmaya 24318a1362adSmaya /* Merge the submitted command buffer stats into the device. */ 24328a1362adSmaya for (uint32_t st = 0; st < OVERLAY_PARAM_ENABLED_MAX; st++) 24338a1362adSmaya device_data->frame_stats.stats[st] += cmd_buffer_data->stats.stats[st]; 24348a1362adSmaya 24358a1362adSmaya /* Attach the command buffer to the queue so we remember to read its 24368a1362adSmaya * pipeline statistics & timestamps at QueuePresent(). 24378a1362adSmaya */ 24388a1362adSmaya if (!cmd_buffer_data->pipeline_query_pool && 24398a1362adSmaya !cmd_buffer_data->timestamp_query_pool) 24408a1362adSmaya continue; 24418a1362adSmaya 24427ec681f3Smrg if (list_is_empty(&cmd_buffer_data->link)) { 24438a1362adSmaya list_addtail(&cmd_buffer_data->link, 24448a1362adSmaya &queue_data->running_command_buffer); 24458a1362adSmaya } else { 24468a1362adSmaya fprintf(stderr, "Command buffer submitted multiple times before present.\n" 24478a1362adSmaya "This could lead to invalid data.\n"); 24488a1362adSmaya } 24498a1362adSmaya } 24508a1362adSmaya } 24518a1362adSmaya 24528a1362adSmaya return device_data->vtable.QueueSubmit(queue, submitCount, pSubmits, fence); 24538a1362adSmaya} 24548a1362adSmaya 24558a1362adSmayastatic VkResult overlay_CreateDevice( 24568a1362adSmaya VkPhysicalDevice physicalDevice, 24578a1362adSmaya const VkDeviceCreateInfo* pCreateInfo, 24588a1362adSmaya const VkAllocationCallbacks* pAllocator, 24598a1362adSmaya VkDevice* pDevice) 24608a1362adSmaya{ 24617ec681f3Smrg struct instance_data *instance_data = 24627ec681f3Smrg FIND(struct instance_data, physicalDevice); 24638a1362adSmaya VkLayerDeviceCreateInfo *chain_info = 24648a1362adSmaya get_device_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 24658a1362adSmaya 24668a1362adSmaya assert(chain_info->u.pLayerInfo); 24678a1362adSmaya PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 24688a1362adSmaya PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 24698a1362adSmaya PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice"); 24708a1362adSmaya if (fpCreateDevice == NULL) { 24718a1362adSmaya return VK_ERROR_INITIALIZATION_FAILED; 24728a1362adSmaya } 24738a1362adSmaya 24748a1362adSmaya // Advance the link info for the next element on the chain 24758a1362adSmaya chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 24768a1362adSmaya 24778a1362adSmaya VkPhysicalDeviceFeatures device_features = {}; 24787ec681f3Smrg VkPhysicalDeviceFeatures *device_features_ptr = NULL; 24797ec681f3Smrg 24807ec681f3Smrg VkDeviceCreateInfo *device_info = (VkDeviceCreateInfo *) 24817ec681f3Smrg clone_chain((const struct VkBaseInStructure *)pCreateInfo); 24827ec681f3Smrg 24837ec681f3Smrg VkPhysicalDeviceFeatures2 *device_features2 = (VkPhysicalDeviceFeatures2 *) 24847ec681f3Smrg vk_find_struct(device_info, PHYSICAL_DEVICE_FEATURES_2); 24857ec681f3Smrg if (device_features2) { 24867ec681f3Smrg /* Can't use device_info->pEnabledFeatures when VkPhysicalDeviceFeatures2 is present */ 24877ec681f3Smrg device_features_ptr = &device_features2->features; 24887ec681f3Smrg } else { 24897ec681f3Smrg if (device_info->pEnabledFeatures) 24907ec681f3Smrg device_features = *(device_info->pEnabledFeatures); 24917ec681f3Smrg device_features_ptr = &device_features; 24927ec681f3Smrg device_info->pEnabledFeatures = &device_features; 24937ec681f3Smrg } 24948a1362adSmaya 24958a1362adSmaya if (instance_data->pipeline_statistics_enabled) { 24967ec681f3Smrg device_features_ptr->inheritedQueries = true; 24977ec681f3Smrg device_features_ptr->pipelineStatisticsQuery = true; 24988a1362adSmaya } 24998a1362adSmaya 25008a1362adSmaya 25017ec681f3Smrg VkResult result = fpCreateDevice(physicalDevice, device_info, pAllocator, pDevice); 25027ec681f3Smrg free_chain((struct VkBaseOutStructure *)device_info); 25038a1362adSmaya if (result != VK_SUCCESS) return result; 25048a1362adSmaya 25058a1362adSmaya struct device_data *device_data = new_device_data(*pDevice, instance_data); 25068a1362adSmaya device_data->physical_device = physicalDevice; 25077ec681f3Smrg vk_device_dispatch_table_load(&device_data->vtable, 25087ec681f3Smrg fpGetDeviceProcAddr, *pDevice); 25098a1362adSmaya 25107ec681f3Smrg instance_data->pd_vtable.GetPhysicalDeviceProperties(device_data->physical_device, 25117ec681f3Smrg &device_data->properties); 25128a1362adSmaya 25138a1362adSmaya VkLayerDeviceCreateInfo *load_data_info = 25148a1362adSmaya get_device_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK); 25158a1362adSmaya device_data->set_device_loader_data = load_data_info->u.pfnSetDeviceLoaderData; 25168a1362adSmaya 25178a1362adSmaya device_map_queues(device_data, pCreateInfo); 25188a1362adSmaya 25198a1362adSmaya return result; 25208a1362adSmaya} 25218a1362adSmaya 25228a1362adSmayastatic void overlay_DestroyDevice( 25238a1362adSmaya VkDevice device, 25248a1362adSmaya const VkAllocationCallbacks* pAllocator) 25258a1362adSmaya{ 25267ec681f3Smrg struct device_data *device_data = FIND(struct device_data, device); 25278a1362adSmaya device_unmap_queues(device_data); 25288a1362adSmaya device_data->vtable.DestroyDevice(device, pAllocator); 25298a1362adSmaya destroy_device_data(device_data); 25308a1362adSmaya} 25318a1362adSmaya 25328a1362adSmayastatic VkResult overlay_CreateInstance( 25338a1362adSmaya const VkInstanceCreateInfo* pCreateInfo, 25348a1362adSmaya const VkAllocationCallbacks* pAllocator, 25358a1362adSmaya VkInstance* pInstance) 25368a1362adSmaya{ 25378a1362adSmaya VkLayerInstanceCreateInfo *chain_info = 25388a1362adSmaya get_instance_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 25398a1362adSmaya 25408a1362adSmaya assert(chain_info->u.pLayerInfo); 25418a1362adSmaya PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = 25428a1362adSmaya chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 25438a1362adSmaya PFN_vkCreateInstance fpCreateInstance = 25448a1362adSmaya (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 25458a1362adSmaya if (fpCreateInstance == NULL) { 25468a1362adSmaya return VK_ERROR_INITIALIZATION_FAILED; 25478a1362adSmaya } 25488a1362adSmaya 25498a1362adSmaya // Advance the link info for the next element on the chain 25508a1362adSmaya chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 25518a1362adSmaya 25528a1362adSmaya VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 25538a1362adSmaya if (result != VK_SUCCESS) return result; 25548a1362adSmaya 25558a1362adSmaya struct instance_data *instance_data = new_instance_data(*pInstance); 25567ec681f3Smrg vk_instance_dispatch_table_load(&instance_data->vtable, 25577ec681f3Smrg fpGetInstanceProcAddr, 25587ec681f3Smrg instance_data->instance); 25597ec681f3Smrg vk_physical_device_dispatch_table_load(&instance_data->pd_vtable, 25607ec681f3Smrg fpGetInstanceProcAddr, 25617ec681f3Smrg instance_data->instance); 25628a1362adSmaya instance_data_map_physical_devices(instance_data, true); 25638a1362adSmaya 25648a1362adSmaya parse_overlay_env(&instance_data->params, getenv("VK_LAYER_MESA_OVERLAY_CONFIG")); 25658a1362adSmaya 25667ec681f3Smrg /* If there's no control file, and an output_file was specified, start 25677ec681f3Smrg * capturing fps data right away. 25687ec681f3Smrg */ 25697ec681f3Smrg instance_data->capture_enabled = 25707ec681f3Smrg instance_data->params.output_file && instance_data->params.control < 0; 25717ec681f3Smrg instance_data->capture_started = instance_data->capture_enabled; 25727ec681f3Smrg 25738a1362adSmaya for (int i = OVERLAY_PARAM_ENABLED_vertices; 25748a1362adSmaya i <= OVERLAY_PARAM_ENABLED_compute_invocations; i++) { 25758a1362adSmaya if (instance_data->params.enabled[i]) { 25768a1362adSmaya instance_data->pipeline_statistics_enabled = true; 25778a1362adSmaya break; 25788a1362adSmaya } 25798a1362adSmaya } 25808a1362adSmaya 25818a1362adSmaya return result; 25828a1362adSmaya} 25838a1362adSmaya 25848a1362adSmayastatic void overlay_DestroyInstance( 25858a1362adSmaya VkInstance instance, 25868a1362adSmaya const VkAllocationCallbacks* pAllocator) 25878a1362adSmaya{ 25887ec681f3Smrg struct instance_data *instance_data = FIND(struct instance_data, instance); 25898a1362adSmaya instance_data_map_physical_devices(instance_data, false); 25908a1362adSmaya instance_data->vtable.DestroyInstance(instance, pAllocator); 25918a1362adSmaya destroy_instance_data(instance_data); 25928a1362adSmaya} 25938a1362adSmaya 25948a1362adSmayastatic const struct { 25958a1362adSmaya const char *name; 25968a1362adSmaya void *ptr; 25978a1362adSmaya} name_to_funcptr_map[] = { 25987ec681f3Smrg { "vkGetInstanceProcAddr", (void *) vkGetInstanceProcAddr }, 25998a1362adSmaya { "vkGetDeviceProcAddr", (void *) vkGetDeviceProcAddr }, 26008a1362adSmaya#define ADD_HOOK(fn) { "vk" # fn, (void *) overlay_ ## fn } 26017ec681f3Smrg#define ADD_ALIAS_HOOK(alias, fn) { "vk" # alias, (void *) overlay_ ## fn } 26028a1362adSmaya ADD_HOOK(AllocateCommandBuffers), 26038a1362adSmaya ADD_HOOK(FreeCommandBuffers), 26048a1362adSmaya ADD_HOOK(ResetCommandBuffer), 26058a1362adSmaya ADD_HOOK(BeginCommandBuffer), 26068a1362adSmaya ADD_HOOK(EndCommandBuffer), 26078a1362adSmaya ADD_HOOK(CmdExecuteCommands), 26088a1362adSmaya 26098a1362adSmaya ADD_HOOK(CmdDraw), 26108a1362adSmaya ADD_HOOK(CmdDrawIndexed), 26118a1362adSmaya ADD_HOOK(CmdDrawIndirect), 26128a1362adSmaya ADD_HOOK(CmdDrawIndexedIndirect), 26138a1362adSmaya ADD_HOOK(CmdDispatch), 26148a1362adSmaya ADD_HOOK(CmdDispatchIndirect), 26157ec681f3Smrg ADD_HOOK(CmdDrawIndirectCount), 26167ec681f3Smrg ADD_ALIAS_HOOK(CmdDrawIndirectCountKHR, CmdDrawIndirectCount), 26177ec681f3Smrg ADD_HOOK(CmdDrawIndexedIndirectCount), 26187ec681f3Smrg ADD_ALIAS_HOOK(CmdDrawIndexedIndirectCountKHR, CmdDrawIndexedIndirectCount), 26198a1362adSmaya 26208a1362adSmaya ADD_HOOK(CmdBindPipeline), 26218a1362adSmaya 26228a1362adSmaya ADD_HOOK(CreateSwapchainKHR), 26238a1362adSmaya ADD_HOOK(QueuePresentKHR), 26248a1362adSmaya ADD_HOOK(DestroySwapchainKHR), 26258a1362adSmaya ADD_HOOK(AcquireNextImageKHR), 26268a1362adSmaya ADD_HOOK(AcquireNextImage2KHR), 26278a1362adSmaya 26288a1362adSmaya ADD_HOOK(QueueSubmit), 26298a1362adSmaya 26308a1362adSmaya ADD_HOOK(CreateDevice), 26318a1362adSmaya ADD_HOOK(DestroyDevice), 26328a1362adSmaya 26338a1362adSmaya ADD_HOOK(CreateInstance), 26348a1362adSmaya ADD_HOOK(DestroyInstance), 26358a1362adSmaya#undef ADD_HOOK 26367ec681f3Smrg#undef ADD_ALIAS_HOOK 26378a1362adSmaya}; 26388a1362adSmaya 26398a1362adSmayastatic void *find_ptr(const char *name) 26408a1362adSmaya{ 26418a1362adSmaya for (uint32_t i = 0; i < ARRAY_SIZE(name_to_funcptr_map); i++) { 26428a1362adSmaya if (strcmp(name, name_to_funcptr_map[i].name) == 0) 26438a1362adSmaya return name_to_funcptr_map[i].ptr; 26448a1362adSmaya } 26458a1362adSmaya 26468a1362adSmaya return NULL; 26478a1362adSmaya} 26488a1362adSmaya 26498a1362adSmayaVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, 26508a1362adSmaya const char *funcName) 26518a1362adSmaya{ 26528a1362adSmaya void *ptr = find_ptr(funcName); 26538a1362adSmaya if (ptr) return reinterpret_cast<PFN_vkVoidFunction>(ptr); 26548a1362adSmaya 26558a1362adSmaya if (dev == NULL) return NULL; 26568a1362adSmaya 26577ec681f3Smrg struct device_data *device_data = FIND(struct device_data, dev); 26588a1362adSmaya if (device_data->vtable.GetDeviceProcAddr == NULL) return NULL; 26598a1362adSmaya return device_data->vtable.GetDeviceProcAddr(dev, funcName); 26608a1362adSmaya} 26618a1362adSmaya 26628a1362adSmayaVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, 26638a1362adSmaya const char *funcName) 26648a1362adSmaya{ 26658a1362adSmaya void *ptr = find_ptr(funcName); 26668a1362adSmaya if (ptr) return reinterpret_cast<PFN_vkVoidFunction>(ptr); 26678a1362adSmaya 26688a1362adSmaya if (instance == NULL) return NULL; 26698a1362adSmaya 26707ec681f3Smrg struct instance_data *instance_data = FIND(struct instance_data, instance); 26718a1362adSmaya if (instance_data->vtable.GetInstanceProcAddr == NULL) return NULL; 26728a1362adSmaya return instance_data->vtable.GetInstanceProcAddr(instance, funcName); 26738a1362adSmaya} 2674