1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2019 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include <string.h> 25b8e80941Smrg#include <stdlib.h> 26b8e80941Smrg#include <assert.h> 27b8e80941Smrg 28b8e80941Smrg#include <vulkan/vulkan.h> 29b8e80941Smrg#include <vulkan/vk_layer.h> 30b8e80941Smrg 31b8e80941Smrg#include "imgui.h" 32b8e80941Smrg 33b8e80941Smrg#include "overlay_params.h" 34b8e80941Smrg 35b8e80941Smrg#include "util/debug.h" 36b8e80941Smrg#include "util/hash_table.h" 37b8e80941Smrg#include "util/list.h" 38b8e80941Smrg#include "util/ralloc.h" 39b8e80941Smrg#include "util/os_time.h" 40b8e80941Smrg#include "util/simple_mtx.h" 41b8e80941Smrg 42b8e80941Smrg#include "vk_enum_to_str.h" 43b8e80941Smrg#include "vk_util.h" 44b8e80941Smrg 45b8e80941Smrg/* Mapped from VkInstace/VkPhysicalDevice */ 46b8e80941Smrgstruct instance_data { 47b8e80941Smrg struct vk_instance_dispatch_table vtable; 48b8e80941Smrg VkInstance instance; 49b8e80941Smrg 50b8e80941Smrg struct overlay_params params; 51b8e80941Smrg bool pipeline_statistics_enabled; 52b8e80941Smrg 53b8e80941Smrg bool first_line_printed; 54b8e80941Smrg}; 55b8e80941Smrg 56b8e80941Smrgstruct frame_stat { 57b8e80941Smrg uint64_t stats[OVERLAY_PARAM_ENABLED_MAX]; 58b8e80941Smrg}; 59b8e80941Smrg 60b8e80941Smrg/* Mapped from VkDevice */ 61b8e80941Smrgstruct queue_data; 62b8e80941Smrgstruct device_data { 63b8e80941Smrg struct instance_data *instance; 64b8e80941Smrg 65b8e80941Smrg PFN_vkSetDeviceLoaderData set_device_loader_data; 66b8e80941Smrg 67b8e80941Smrg struct vk_device_dispatch_table vtable; 68b8e80941Smrg VkPhysicalDevice physical_device; 69b8e80941Smrg VkDevice device; 70b8e80941Smrg 71b8e80941Smrg VkPhysicalDeviceProperties properties; 72b8e80941Smrg 73b8e80941Smrg struct queue_data *graphic_queue; 74b8e80941Smrg 75b8e80941Smrg struct queue_data **queues; 76b8e80941Smrg uint32_t n_queues; 77b8e80941Smrg 78b8e80941Smrg /* For a single frame */ 79b8e80941Smrg struct frame_stat frame_stats; 80b8e80941Smrg}; 81b8e80941Smrg 82b8e80941Smrg/* Mapped from VkCommandBuffer */ 83b8e80941Smrgstruct command_buffer_data { 84b8e80941Smrg struct device_data *device; 85b8e80941Smrg 86b8e80941Smrg VkCommandBufferLevel level; 87b8e80941Smrg 88b8e80941Smrg VkCommandBuffer cmd_buffer; 89b8e80941Smrg VkQueryPool pipeline_query_pool; 90b8e80941Smrg VkQueryPool timestamp_query_pool; 91b8e80941Smrg uint32_t query_index; 92b8e80941Smrg 93b8e80941Smrg struct frame_stat stats; 94b8e80941Smrg 95b8e80941Smrg struct list_head link; /* link into queue_data::running_command_buffer */ 96b8e80941Smrg}; 97b8e80941Smrg 98b8e80941Smrg/* Mapped from VkQueue */ 99b8e80941Smrgstruct queue_data { 100b8e80941Smrg struct device_data *device; 101b8e80941Smrg 102b8e80941Smrg VkQueue queue; 103b8e80941Smrg VkQueueFlags flags; 104b8e80941Smrg uint32_t family_index; 105b8e80941Smrg uint64_t timestamp_mask; 106b8e80941Smrg 107b8e80941Smrg VkFence queries_fence; 108b8e80941Smrg 109b8e80941Smrg struct list_head running_command_buffer; 110b8e80941Smrg}; 111b8e80941Smrg 112b8e80941Smrgstruct overlay_draw { 113b8e80941Smrg struct list_head link; 114b8e80941Smrg 115b8e80941Smrg VkCommandBuffer command_buffer; 116b8e80941Smrg 117b8e80941Smrg VkSemaphore semaphore; 118b8e80941Smrg VkFence fence; 119b8e80941Smrg 120b8e80941Smrg VkBuffer vertex_buffer; 121b8e80941Smrg VkDeviceMemory vertex_buffer_mem; 122b8e80941Smrg VkDeviceSize vertex_buffer_size; 123b8e80941Smrg 124b8e80941Smrg VkBuffer index_buffer; 125b8e80941Smrg VkDeviceMemory index_buffer_mem; 126b8e80941Smrg VkDeviceSize index_buffer_size; 127b8e80941Smrg}; 128b8e80941Smrg 129b8e80941Smrg/* Mapped from VkSwapchainKHR */ 130b8e80941Smrgstruct swapchain_data { 131b8e80941Smrg struct device_data *device; 132b8e80941Smrg 133b8e80941Smrg VkSwapchainKHR swapchain; 134b8e80941Smrg unsigned width, height; 135b8e80941Smrg VkFormat format; 136b8e80941Smrg 137b8e80941Smrg uint32_t n_images; 138b8e80941Smrg VkImage *images; 139b8e80941Smrg VkImageView *image_views; 140b8e80941Smrg VkFramebuffer *framebuffers; 141b8e80941Smrg 142b8e80941Smrg VkRenderPass render_pass; 143b8e80941Smrg 144b8e80941Smrg VkDescriptorPool descriptor_pool; 145b8e80941Smrg VkDescriptorSetLayout descriptor_layout; 146b8e80941Smrg VkDescriptorSet descriptor_set; 147b8e80941Smrg 148b8e80941Smrg VkSampler font_sampler; 149b8e80941Smrg 150b8e80941Smrg VkPipelineLayout pipeline_layout; 151b8e80941Smrg VkPipeline pipeline; 152b8e80941Smrg 153b8e80941Smrg VkCommandPool command_pool; 154b8e80941Smrg 155b8e80941Smrg struct list_head draws; /* List of struct overlay_draw */ 156b8e80941Smrg 157b8e80941Smrg bool font_uploaded; 158b8e80941Smrg VkImage font_image; 159b8e80941Smrg VkImageView font_image_view; 160b8e80941Smrg VkDeviceMemory font_mem; 161b8e80941Smrg VkBuffer upload_font_buffer; 162b8e80941Smrg VkDeviceMemory upload_font_buffer_mem; 163b8e80941Smrg 164b8e80941Smrg /**/ 165b8e80941Smrg ImGuiContext* imgui_context; 166b8e80941Smrg ImVec2 window_size; 167b8e80941Smrg 168b8e80941Smrg /**/ 169b8e80941Smrg uint64_t n_frames; 170b8e80941Smrg uint64_t last_present_time; 171b8e80941Smrg 172b8e80941Smrg unsigned n_frames_since_update; 173b8e80941Smrg uint64_t last_fps_update; 174b8e80941Smrg double fps; 175b8e80941Smrg 176b8e80941Smrg enum overlay_param_enabled stat_selector; 177b8e80941Smrg double time_dividor; 178b8e80941Smrg struct frame_stat stats_min, stats_max; 179b8e80941Smrg struct frame_stat frames_stats[200]; 180b8e80941Smrg 181b8e80941Smrg /* Over a single frame */ 182b8e80941Smrg struct frame_stat frame_stats; 183b8e80941Smrg 184b8e80941Smrg /* Over fps_sampling_period */ 185b8e80941Smrg struct frame_stat accumulated_stats; 186b8e80941Smrg}; 187b8e80941Smrg 188b8e80941Smrgstatic const VkQueryPipelineStatisticFlags overlay_query_flags = 189b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT | 190b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT | 191b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | 192b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT | 193b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT | 194b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT | 195b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT | 196b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT | 197b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT | 198b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT | 199b8e80941Smrg VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT; 200b8e80941Smrg#define OVERLAY_QUERY_COUNT (11) 201b8e80941Smrg 202b8e80941Smrgstatic struct hash_table_u64 *vk_object_to_data = NULL; 203b8e80941Smrgstatic simple_mtx_t vk_object_to_data_mutex = _SIMPLE_MTX_INITIALIZER_NP; 204b8e80941Smrg 205b8e80941Smrgthread_local ImGuiContext* __MesaImGui; 206b8e80941Smrg 207b8e80941Smrgstatic inline void ensure_vk_object_map(void) 208b8e80941Smrg{ 209b8e80941Smrg if (!vk_object_to_data) 210b8e80941Smrg vk_object_to_data = _mesa_hash_table_u64_create(NULL); 211b8e80941Smrg} 212b8e80941Smrg 213b8e80941Smrg#define HKEY(obj) ((uint64_t)(obj)) 214b8e80941Smrg#define FIND_SWAPCHAIN_DATA(obj) ((struct swapchain_data *)find_object_data(HKEY(obj))) 215b8e80941Smrg#define FIND_CMD_BUFFER_DATA(obj) ((struct command_buffer_data *)find_object_data(HKEY(obj))) 216b8e80941Smrg#define FIND_DEVICE_DATA(obj) ((struct device_data *)find_object_data(HKEY(obj))) 217b8e80941Smrg#define FIND_QUEUE_DATA(obj) ((struct queue_data *)find_object_data(HKEY(obj))) 218b8e80941Smrg#define FIND_PHYSICAL_DEVICE_DATA(obj) ((struct instance_data *)find_object_data(HKEY(obj))) 219b8e80941Smrg#define FIND_INSTANCE_DATA(obj) ((struct instance_data *)find_object_data(HKEY(obj))) 220b8e80941Smrgstatic void *find_object_data(uint64_t obj) 221b8e80941Smrg{ 222b8e80941Smrg simple_mtx_lock(&vk_object_to_data_mutex); 223b8e80941Smrg ensure_vk_object_map(); 224b8e80941Smrg void *data = _mesa_hash_table_u64_search(vk_object_to_data, obj); 225b8e80941Smrg simple_mtx_unlock(&vk_object_to_data_mutex); 226b8e80941Smrg return data; 227b8e80941Smrg} 228b8e80941Smrg 229b8e80941Smrgstatic void map_object(uint64_t obj, void *data) 230b8e80941Smrg{ 231b8e80941Smrg simple_mtx_lock(&vk_object_to_data_mutex); 232b8e80941Smrg ensure_vk_object_map(); 233b8e80941Smrg _mesa_hash_table_u64_insert(vk_object_to_data, obj, data); 234b8e80941Smrg simple_mtx_unlock(&vk_object_to_data_mutex); 235b8e80941Smrg} 236b8e80941Smrg 237b8e80941Smrgstatic void unmap_object(uint64_t obj) 238b8e80941Smrg{ 239b8e80941Smrg simple_mtx_lock(&vk_object_to_data_mutex); 240b8e80941Smrg _mesa_hash_table_u64_remove(vk_object_to_data, obj); 241b8e80941Smrg simple_mtx_unlock(&vk_object_to_data_mutex); 242b8e80941Smrg} 243b8e80941Smrg 244b8e80941Smrg/**/ 245b8e80941Smrg 246b8e80941Smrg#define VK_CHECK(expr) \ 247b8e80941Smrg do { \ 248b8e80941Smrg VkResult __result = (expr); \ 249b8e80941Smrg if (__result != VK_SUCCESS) { \ 250b8e80941Smrg fprintf(stderr, "'%s' line %i failed with %s\n", \ 251b8e80941Smrg #expr, __LINE__, vk_Result_to_str(__result)); \ 252b8e80941Smrg } \ 253b8e80941Smrg } while (0) 254b8e80941Smrg 255b8e80941Smrg/**/ 256b8e80941Smrg 257b8e80941Smrgstatic VkLayerInstanceCreateInfo *get_instance_chain_info(const VkInstanceCreateInfo *pCreateInfo, 258b8e80941Smrg VkLayerFunction func) 259b8e80941Smrg{ 260b8e80941Smrg vk_foreach_struct(item, pCreateInfo->pNext) { 261b8e80941Smrg if (item->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && 262b8e80941Smrg ((VkLayerInstanceCreateInfo *) item)->function == func) 263b8e80941Smrg return (VkLayerInstanceCreateInfo *) item; 264b8e80941Smrg } 265b8e80941Smrg unreachable("instance chain info not found"); 266b8e80941Smrg return NULL; 267b8e80941Smrg} 268b8e80941Smrg 269b8e80941Smrgstatic VkLayerDeviceCreateInfo *get_device_chain_info(const VkDeviceCreateInfo *pCreateInfo, 270b8e80941Smrg VkLayerFunction func) 271b8e80941Smrg{ 272b8e80941Smrg vk_foreach_struct(item, pCreateInfo->pNext) { 273b8e80941Smrg if (item->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && 274b8e80941Smrg ((VkLayerDeviceCreateInfo *) item)->function == func) 275b8e80941Smrg return (VkLayerDeviceCreateInfo *)item; 276b8e80941Smrg } 277b8e80941Smrg unreachable("device chain info not found"); 278b8e80941Smrg return NULL; 279b8e80941Smrg} 280b8e80941Smrg 281b8e80941Smrgstatic struct VkBaseOutStructure * 282b8e80941Smrgclone_chain(const struct VkBaseInStructure *chain) 283b8e80941Smrg{ 284b8e80941Smrg struct VkBaseOutStructure *head = NULL, *tail = NULL; 285b8e80941Smrg 286b8e80941Smrg vk_foreach_struct_const(item, chain) { 287b8e80941Smrg size_t item_size = vk_structure_type_size(item); 288b8e80941Smrg struct VkBaseOutStructure *new_item = 289b8e80941Smrg (struct VkBaseOutStructure *)malloc(item_size);; 290b8e80941Smrg 291b8e80941Smrg memcpy(new_item, item, item_size); 292b8e80941Smrg 293b8e80941Smrg if (!head) 294b8e80941Smrg head = new_item; 295b8e80941Smrg if (tail) 296b8e80941Smrg tail->pNext = new_item; 297b8e80941Smrg tail = new_item; 298b8e80941Smrg } 299b8e80941Smrg 300b8e80941Smrg return head; 301b8e80941Smrg} 302b8e80941Smrg 303b8e80941Smrgstatic void 304b8e80941Smrgfree_chain(struct VkBaseOutStructure *chain) 305b8e80941Smrg{ 306b8e80941Smrg while (chain) { 307b8e80941Smrg void *node = chain; 308b8e80941Smrg chain = chain->pNext; 309b8e80941Smrg free(node); 310b8e80941Smrg } 311b8e80941Smrg} 312b8e80941Smrg 313b8e80941Smrg/**/ 314b8e80941Smrg 315b8e80941Smrgstatic void check_vk_result(VkResult err) 316b8e80941Smrg{ 317b8e80941Smrg if (err != VK_SUCCESS) 318b8e80941Smrg printf("ERROR!\n"); 319b8e80941Smrg} 320b8e80941Smrg 321b8e80941Smrgstatic struct instance_data *new_instance_data(VkInstance instance) 322b8e80941Smrg{ 323b8e80941Smrg struct instance_data *data = rzalloc(NULL, struct instance_data); 324b8e80941Smrg data->instance = instance; 325b8e80941Smrg map_object(HKEY(data->instance), data); 326b8e80941Smrg return data; 327b8e80941Smrg} 328b8e80941Smrg 329b8e80941Smrgstatic void destroy_instance_data(struct instance_data *data) 330b8e80941Smrg{ 331b8e80941Smrg if (data->params.output_file) 332b8e80941Smrg fclose(data->params.output_file); 333b8e80941Smrg unmap_object(HKEY(data->instance)); 334b8e80941Smrg ralloc_free(data); 335b8e80941Smrg} 336b8e80941Smrg 337b8e80941Smrgstatic void instance_data_map_physical_devices(struct instance_data *instance_data, 338b8e80941Smrg bool map) 339b8e80941Smrg{ 340b8e80941Smrg uint32_t physicalDeviceCount = 0; 341b8e80941Smrg instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, 342b8e80941Smrg &physicalDeviceCount, 343b8e80941Smrg NULL); 344b8e80941Smrg 345b8e80941Smrg VkPhysicalDevice *physicalDevices = (VkPhysicalDevice *) malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); 346b8e80941Smrg instance_data->vtable.EnumeratePhysicalDevices(instance_data->instance, 347b8e80941Smrg &physicalDeviceCount, 348b8e80941Smrg physicalDevices); 349b8e80941Smrg 350b8e80941Smrg for (uint32_t i = 0; i < physicalDeviceCount; i++) { 351b8e80941Smrg if (map) 352b8e80941Smrg map_object(HKEY(physicalDevices[i]), instance_data); 353b8e80941Smrg else 354b8e80941Smrg unmap_object(HKEY(physicalDevices[i])); 355b8e80941Smrg } 356b8e80941Smrg 357b8e80941Smrg free(physicalDevices); 358b8e80941Smrg} 359b8e80941Smrg 360b8e80941Smrg/**/ 361b8e80941Smrgstatic struct device_data *new_device_data(VkDevice device, struct instance_data *instance) 362b8e80941Smrg{ 363b8e80941Smrg struct device_data *data = rzalloc(NULL, struct device_data); 364b8e80941Smrg data->instance = instance; 365b8e80941Smrg data->device = device; 366b8e80941Smrg map_object(HKEY(data->device), data); 367b8e80941Smrg return data; 368b8e80941Smrg} 369b8e80941Smrg 370b8e80941Smrgstatic struct queue_data *new_queue_data(VkQueue queue, 371b8e80941Smrg const VkQueueFamilyProperties *family_props, 372b8e80941Smrg uint32_t family_index, 373b8e80941Smrg struct device_data *device_data) 374b8e80941Smrg{ 375b8e80941Smrg struct queue_data *data = rzalloc(device_data, struct queue_data); 376b8e80941Smrg data->device = device_data; 377b8e80941Smrg data->queue = queue; 378b8e80941Smrg data->flags = family_props->queueFlags; 379b8e80941Smrg data->timestamp_mask = (1ull << family_props->timestampValidBits) - 1; 380b8e80941Smrg data->family_index = family_index; 381b8e80941Smrg LIST_INITHEAD(&data->running_command_buffer); 382b8e80941Smrg map_object(HKEY(data->queue), data); 383b8e80941Smrg 384b8e80941Smrg /* Fence synchronizing access to queries on that queue. */ 385b8e80941Smrg VkFenceCreateInfo fence_info = {}; 386b8e80941Smrg fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 387b8e80941Smrg fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; 388b8e80941Smrg VkResult err = device_data->vtable.CreateFence(device_data->device, 389b8e80941Smrg &fence_info, 390b8e80941Smrg NULL, 391b8e80941Smrg &data->queries_fence); 392b8e80941Smrg check_vk_result(err); 393b8e80941Smrg 394b8e80941Smrg if (data->flags & VK_QUEUE_GRAPHICS_BIT) 395b8e80941Smrg device_data->graphic_queue = data; 396b8e80941Smrg 397b8e80941Smrg return data; 398b8e80941Smrg} 399b8e80941Smrg 400b8e80941Smrgstatic void destroy_queue(struct queue_data *data) 401b8e80941Smrg{ 402b8e80941Smrg struct device_data *device_data = data->device; 403b8e80941Smrg device_data->vtable.DestroyFence(device_data->device, data->queries_fence, NULL); 404b8e80941Smrg unmap_object(HKEY(data->queue)); 405b8e80941Smrg ralloc_free(data); 406b8e80941Smrg} 407b8e80941Smrg 408b8e80941Smrgstatic void device_map_queues(struct device_data *data, 409b8e80941Smrg const VkDeviceCreateInfo *pCreateInfo) 410b8e80941Smrg{ 411b8e80941Smrg for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) 412b8e80941Smrg data->n_queues += pCreateInfo->pQueueCreateInfos[i].queueCount; 413b8e80941Smrg data->queues = ralloc_array(data, struct queue_data *, data->n_queues); 414b8e80941Smrg 415b8e80941Smrg struct instance_data *instance_data = data->instance; 416b8e80941Smrg uint32_t n_family_props; 417b8e80941Smrg instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, 418b8e80941Smrg &n_family_props, 419b8e80941Smrg NULL); 420b8e80941Smrg VkQueueFamilyProperties *family_props = 421b8e80941Smrg (VkQueueFamilyProperties *)malloc(sizeof(VkQueueFamilyProperties) * n_family_props); 422b8e80941Smrg instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device, 423b8e80941Smrg &n_family_props, 424b8e80941Smrg family_props); 425b8e80941Smrg 426b8e80941Smrg uint32_t queue_index = 0; 427b8e80941Smrg for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { 428b8e80941Smrg for (uint32_t j = 0; j < pCreateInfo->pQueueCreateInfos[i].queueCount; j++) { 429b8e80941Smrg VkQueue queue; 430b8e80941Smrg data->vtable.GetDeviceQueue(data->device, 431b8e80941Smrg pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, 432b8e80941Smrg j, &queue); 433b8e80941Smrg 434b8e80941Smrg VK_CHECK(data->set_device_loader_data(data->device, queue)); 435b8e80941Smrg 436b8e80941Smrg data->queues[queue_index++] = 437b8e80941Smrg new_queue_data(queue, &family_props[pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex], 438b8e80941Smrg pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, data); 439b8e80941Smrg } 440b8e80941Smrg } 441b8e80941Smrg 442b8e80941Smrg free(family_props); 443b8e80941Smrg} 444b8e80941Smrg 445b8e80941Smrgstatic void device_unmap_queues(struct device_data *data) 446b8e80941Smrg{ 447b8e80941Smrg for (uint32_t i = 0; i < data->n_queues; i++) 448b8e80941Smrg destroy_queue(data->queues[i]); 449b8e80941Smrg} 450b8e80941Smrg 451b8e80941Smrgstatic void destroy_device_data(struct device_data *data) 452b8e80941Smrg{ 453b8e80941Smrg unmap_object(HKEY(data->device)); 454b8e80941Smrg ralloc_free(data); 455b8e80941Smrg} 456b8e80941Smrg 457b8e80941Smrg/**/ 458b8e80941Smrgstatic struct command_buffer_data *new_command_buffer_data(VkCommandBuffer cmd_buffer, 459b8e80941Smrg VkCommandBufferLevel level, 460b8e80941Smrg VkQueryPool pipeline_query_pool, 461b8e80941Smrg VkQueryPool timestamp_query_pool, 462b8e80941Smrg uint32_t query_index, 463b8e80941Smrg struct device_data *device_data) 464b8e80941Smrg{ 465b8e80941Smrg struct command_buffer_data *data = rzalloc(NULL, struct command_buffer_data); 466b8e80941Smrg data->device = device_data; 467b8e80941Smrg data->cmd_buffer = cmd_buffer; 468b8e80941Smrg data->level = level; 469b8e80941Smrg data->pipeline_query_pool = pipeline_query_pool; 470b8e80941Smrg data->timestamp_query_pool = timestamp_query_pool; 471b8e80941Smrg data->query_index = query_index; 472b8e80941Smrg list_inithead(&data->link); 473b8e80941Smrg map_object(HKEY(data->cmd_buffer), data); 474b8e80941Smrg return data; 475b8e80941Smrg} 476b8e80941Smrg 477b8e80941Smrgstatic void destroy_command_buffer_data(struct command_buffer_data *data) 478b8e80941Smrg{ 479b8e80941Smrg unmap_object(HKEY(data->cmd_buffer)); 480b8e80941Smrg list_delinit(&data->link); 481b8e80941Smrg ralloc_free(data); 482b8e80941Smrg} 483b8e80941Smrg 484b8e80941Smrg/**/ 485b8e80941Smrgstatic struct swapchain_data *new_swapchain_data(VkSwapchainKHR swapchain, 486b8e80941Smrg struct device_data *device_data) 487b8e80941Smrg{ 488b8e80941Smrg struct instance_data *instance_data = device_data->instance; 489b8e80941Smrg struct swapchain_data *data = rzalloc(NULL, struct swapchain_data); 490b8e80941Smrg data->device = device_data; 491b8e80941Smrg data->swapchain = swapchain; 492b8e80941Smrg data->window_size = ImVec2(instance_data->params.width, instance_data->params.height); 493b8e80941Smrg list_inithead(&data->draws); 494b8e80941Smrg map_object(HKEY(data->swapchain), data); 495b8e80941Smrg return data; 496b8e80941Smrg} 497b8e80941Smrg 498b8e80941Smrgstatic void destroy_swapchain_data(struct swapchain_data *data) 499b8e80941Smrg{ 500b8e80941Smrg unmap_object(HKEY(data->swapchain)); 501b8e80941Smrg ralloc_free(data); 502b8e80941Smrg} 503b8e80941Smrg 504b8e80941Smrgstruct overlay_draw *get_overlay_draw(struct swapchain_data *data) 505b8e80941Smrg{ 506b8e80941Smrg struct device_data *device_data = data->device; 507b8e80941Smrg struct overlay_draw *draw = list_empty(&data->draws) ? 508b8e80941Smrg NULL : list_first_entry(&data->draws, struct overlay_draw, link); 509b8e80941Smrg 510b8e80941Smrg VkSemaphoreCreateInfo sem_info = {}; 511b8e80941Smrg sem_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 512b8e80941Smrg 513b8e80941Smrg if (draw && device_data->vtable.GetFenceStatus(device_data->device, draw->fence) == VK_SUCCESS) { 514b8e80941Smrg list_del(&draw->link); 515b8e80941Smrg VK_CHECK(device_data->vtable.ResetFences(device_data->device, 516b8e80941Smrg 1, &draw->fence)); 517b8e80941Smrg list_addtail(&draw->link, &data->draws); 518b8e80941Smrg return draw; 519b8e80941Smrg } 520b8e80941Smrg 521b8e80941Smrg draw = rzalloc(data, struct overlay_draw); 522b8e80941Smrg 523b8e80941Smrg VkCommandBufferAllocateInfo cmd_buffer_info = {}; 524b8e80941Smrg cmd_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 525b8e80941Smrg cmd_buffer_info.commandPool = data->command_pool; 526b8e80941Smrg cmd_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 527b8e80941Smrg cmd_buffer_info.commandBufferCount = 1; 528b8e80941Smrg VK_CHECK(device_data->vtable.AllocateCommandBuffers(device_data->device, 529b8e80941Smrg &cmd_buffer_info, 530b8e80941Smrg &draw->command_buffer)); 531b8e80941Smrg VK_CHECK(device_data->set_device_loader_data(device_data->device, 532b8e80941Smrg draw->command_buffer)); 533b8e80941Smrg 534b8e80941Smrg 535b8e80941Smrg VkFenceCreateInfo fence_info = {}; 536b8e80941Smrg fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 537b8e80941Smrg VK_CHECK(device_data->vtable.CreateFence(device_data->device, 538b8e80941Smrg &fence_info, 539b8e80941Smrg NULL, 540b8e80941Smrg &draw->fence)); 541b8e80941Smrg 542b8e80941Smrg VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, 543b8e80941Smrg NULL, &draw->semaphore)); 544b8e80941Smrg 545b8e80941Smrg list_addtail(&draw->link, &data->draws); 546b8e80941Smrg 547b8e80941Smrg return draw; 548b8e80941Smrg} 549b8e80941Smrg 550b8e80941Smrgstatic const char *param_unit(enum overlay_param_enabled param) 551b8e80941Smrg{ 552b8e80941Smrg switch (param) { 553b8e80941Smrg case OVERLAY_PARAM_ENABLED_frame_timing: 554b8e80941Smrg case OVERLAY_PARAM_ENABLED_acquire_timing: 555b8e80941Smrg return "(us)"; 556b8e80941Smrg case OVERLAY_PARAM_ENABLED_gpu_timing: 557b8e80941Smrg return "(ns)"; 558b8e80941Smrg default: 559b8e80941Smrg return ""; 560b8e80941Smrg } 561b8e80941Smrg} 562b8e80941Smrg 563b8e80941Smrgstatic void snapshot_swapchain_frame(struct swapchain_data *data) 564b8e80941Smrg{ 565b8e80941Smrg struct device_data *device_data = data->device; 566b8e80941Smrg struct instance_data *instance_data = device_data->instance; 567b8e80941Smrg uint32_t f_idx = data->n_frames % ARRAY_SIZE(data->frames_stats); 568b8e80941Smrg uint64_t now = os_time_get(); /* us */ 569b8e80941Smrg 570b8e80941Smrg if (data->last_present_time) { 571b8e80941Smrg data->frame_stats.stats[OVERLAY_PARAM_ENABLED_frame_timing] = 572b8e80941Smrg now - data->last_present_time; 573b8e80941Smrg } 574b8e80941Smrg 575b8e80941Smrg memset(&data->frames_stats[f_idx], 0, sizeof(data->frames_stats[f_idx])); 576b8e80941Smrg for (int s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 577b8e80941Smrg data->frames_stats[f_idx].stats[s] += device_data->frame_stats.stats[s] + data->frame_stats.stats[s]; 578b8e80941Smrg data->accumulated_stats.stats[s] += device_data->frame_stats.stats[s] + data->frame_stats.stats[s]; 579b8e80941Smrg } 580b8e80941Smrg 581b8e80941Smrg if (data->last_fps_update) { 582b8e80941Smrg double elapsed = (double)(now - data->last_fps_update); /* us */ 583b8e80941Smrg if (elapsed >= instance_data->params.fps_sampling_period) { 584b8e80941Smrg data->fps = 1000000.0f * data->n_frames_since_update / elapsed; 585b8e80941Smrg if (instance_data->params.output_file) { 586b8e80941Smrg if (!instance_data->first_line_printed) { 587b8e80941Smrg bool first_column = true; 588b8e80941Smrg 589b8e80941Smrg instance_data->first_line_printed = true; 590b8e80941Smrg 591b8e80941Smrg#define OVERLAY_PARAM_BOOL(name) \ 592b8e80941Smrg if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_##name]) { \ 593b8e80941Smrg fprintf(instance_data->params.output_file, \ 594b8e80941Smrg "%s%s%s", first_column ? "" : ", ", #name, \ 595b8e80941Smrg param_unit(OVERLAY_PARAM_ENABLED_##name)); \ 596b8e80941Smrg first_column = false; \ 597b8e80941Smrg } 598b8e80941Smrg#define OVERLAY_PARAM_CUSTOM(name) 599b8e80941Smrg OVERLAY_PARAMS 600b8e80941Smrg#undef OVERLAY_PARAM_BOOL 601b8e80941Smrg#undef OVERLAY_PARAM_CUSTOM 602b8e80941Smrg fprintf(instance_data->params.output_file, "\n"); 603b8e80941Smrg } 604b8e80941Smrg 605b8e80941Smrg for (int s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 606b8e80941Smrg if (!instance_data->params.enabled[s]) 607b8e80941Smrg continue; 608b8e80941Smrg if (s == OVERLAY_PARAM_ENABLED_fps) { 609b8e80941Smrg fprintf(instance_data->params.output_file, 610b8e80941Smrg "%s%.2f", s == 0 ? "" : ", ", data->fps); 611b8e80941Smrg } else { 612b8e80941Smrg fprintf(instance_data->params.output_file, 613b8e80941Smrg "%s%" PRIu64, s == 0 ? "" : ", ", 614b8e80941Smrg data->accumulated_stats.stats[s]); 615b8e80941Smrg } 616b8e80941Smrg } 617b8e80941Smrg fprintf(instance_data->params.output_file, "\n"); 618b8e80941Smrg fflush(instance_data->params.output_file); 619b8e80941Smrg } 620b8e80941Smrg 621b8e80941Smrg memset(&data->accumulated_stats, 0, sizeof(data->accumulated_stats)); 622b8e80941Smrg data->n_frames_since_update = 0; 623b8e80941Smrg data->last_fps_update = now; 624b8e80941Smrg } 625b8e80941Smrg } else { 626b8e80941Smrg data->last_fps_update = now; 627b8e80941Smrg } 628b8e80941Smrg 629b8e80941Smrg memset(&device_data->frame_stats, 0, sizeof(device_data->frame_stats)); 630b8e80941Smrg memset(&data->frame_stats, 0, sizeof(device_data->frame_stats)); 631b8e80941Smrg 632b8e80941Smrg data->last_present_time = now; 633b8e80941Smrg data->n_frames++; 634b8e80941Smrg data->n_frames_since_update++; 635b8e80941Smrg} 636b8e80941Smrg 637b8e80941Smrgstatic float get_time_stat(void *_data, int _idx) 638b8e80941Smrg{ 639b8e80941Smrg struct swapchain_data *data = (struct swapchain_data *) _data; 640b8e80941Smrg if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) 641b8e80941Smrg return 0.0f; 642b8e80941Smrg int idx = ARRAY_SIZE(data->frames_stats) + 643b8e80941Smrg data->n_frames < ARRAY_SIZE(data->frames_stats) ? 644b8e80941Smrg _idx - data->n_frames : 645b8e80941Smrg _idx + data->n_frames; 646b8e80941Smrg idx %= ARRAY_SIZE(data->frames_stats); 647b8e80941Smrg /* Time stats are in us. */ 648b8e80941Smrg return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; 649b8e80941Smrg} 650b8e80941Smrg 651b8e80941Smrgstatic float get_stat(void *_data, int _idx) 652b8e80941Smrg{ 653b8e80941Smrg struct swapchain_data *data = (struct swapchain_data *) _data; 654b8e80941Smrg if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) 655b8e80941Smrg return 0.0f; 656b8e80941Smrg int idx = ARRAY_SIZE(data->frames_stats) + 657b8e80941Smrg data->n_frames < ARRAY_SIZE(data->frames_stats) ? 658b8e80941Smrg _idx - data->n_frames : 659b8e80941Smrg _idx + data->n_frames; 660b8e80941Smrg idx %= ARRAY_SIZE(data->frames_stats); 661b8e80941Smrg return data->frames_stats[idx].stats[data->stat_selector]; 662b8e80941Smrg} 663b8e80941Smrg 664b8e80941Smrgstatic void position_layer(struct swapchain_data *data) 665b8e80941Smrg 666b8e80941Smrg{ 667b8e80941Smrg struct device_data *device_data = data->device; 668b8e80941Smrg struct instance_data *instance_data = device_data->instance; 669b8e80941Smrg const float margin = 10.0f; 670b8e80941Smrg 671b8e80941Smrg ImGui::SetNextWindowBgAlpha(0.5); 672b8e80941Smrg ImGui::SetNextWindowSize(data->window_size, ImGuiCond_Always); 673b8e80941Smrg switch (instance_data->params.position) { 674b8e80941Smrg case LAYER_POSITION_TOP_LEFT: 675b8e80941Smrg ImGui::SetNextWindowPos(ImVec2(margin, margin), ImGuiCond_Always); 676b8e80941Smrg break; 677b8e80941Smrg case LAYER_POSITION_TOP_RIGHT: 678b8e80941Smrg ImGui::SetNextWindowPos(ImVec2(data->width - data->window_size.x - margin, margin), 679b8e80941Smrg ImGuiCond_Always); 680b8e80941Smrg break; 681b8e80941Smrg case LAYER_POSITION_BOTTOM_LEFT: 682b8e80941Smrg ImGui::SetNextWindowPos(ImVec2(margin, data->height - data->window_size.y - margin), 683b8e80941Smrg ImGuiCond_Always); 684b8e80941Smrg break; 685b8e80941Smrg case LAYER_POSITION_BOTTOM_RIGHT: 686b8e80941Smrg ImGui::SetNextWindowPos(ImVec2(data->width - data->window_size.x - margin, 687b8e80941Smrg data->height - data->window_size.y - margin), 688b8e80941Smrg ImGuiCond_Always); 689b8e80941Smrg break; 690b8e80941Smrg } 691b8e80941Smrg} 692b8e80941Smrg 693b8e80941Smrgstatic void compute_swapchain_display(struct swapchain_data *data) 694b8e80941Smrg{ 695b8e80941Smrg struct device_data *device_data = data->device; 696b8e80941Smrg struct instance_data *instance_data = device_data->instance; 697b8e80941Smrg 698b8e80941Smrg ImGui::SetCurrentContext(data->imgui_context); 699b8e80941Smrg ImGui::NewFrame(); 700b8e80941Smrg position_layer(data); 701b8e80941Smrg ImGui::Begin("Mesa overlay"); 702b8e80941Smrg ImGui::Text("Device: %s", device_data->properties.deviceName); 703b8e80941Smrg 704b8e80941Smrg const char *format_name = vk_Format_to_str(data->format); 705b8e80941Smrg format_name = format_name ? (format_name + strlen("VK_FORMAT_")) : "unknown"; 706b8e80941Smrg ImGui::Text("Swapchain format: %s", format_name); 707b8e80941Smrg ImGui::Text("Frames: %" PRIu64, data->n_frames); 708b8e80941Smrg if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_fps]) 709b8e80941Smrg ImGui::Text("FPS: %.2f" , data->fps); 710b8e80941Smrg 711b8e80941Smrg /* Recompute min/max */ 712b8e80941Smrg for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 713b8e80941Smrg data->stats_min.stats[s] = UINT64_MAX; 714b8e80941Smrg data->stats_max.stats[s] = 0; 715b8e80941Smrg } 716b8e80941Smrg for (uint32_t f = 0; f < MIN2(data->n_frames, ARRAY_SIZE(data->frames_stats)); f++) { 717b8e80941Smrg for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 718b8e80941Smrg data->stats_min.stats[s] = MIN2(data->frames_stats[f].stats[s], 719b8e80941Smrg data->stats_min.stats[s]); 720b8e80941Smrg data->stats_max.stats[s] = MAX2(data->frames_stats[f].stats[s], 721b8e80941Smrg data->stats_max.stats[s]); 722b8e80941Smrg } 723b8e80941Smrg } 724b8e80941Smrg for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 725b8e80941Smrg assert(data->stats_min.stats[s] != UINT64_MAX); 726b8e80941Smrg } 727b8e80941Smrg 728b8e80941Smrg for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) { 729b8e80941Smrg if (!instance_data->params.enabled[s] || 730b8e80941Smrg s == OVERLAY_PARAM_ENABLED_fps || 731b8e80941Smrg s == OVERLAY_PARAM_ENABLED_frame) 732b8e80941Smrg continue; 733b8e80941Smrg 734b8e80941Smrg char hash[40]; 735b8e80941Smrg snprintf(hash, sizeof(hash), "##%s", overlay_param_names[s]); 736b8e80941Smrg data->stat_selector = (enum overlay_param_enabled) s; 737b8e80941Smrg data->time_dividor = 1000.0f; 738b8e80941Smrg if (s == OVERLAY_PARAM_ENABLED_gpu_timing) 739b8e80941Smrg data->time_dividor = 1000000.0f; 740b8e80941Smrg 741b8e80941Smrg if (s == OVERLAY_PARAM_ENABLED_frame_timing || 742b8e80941Smrg s == OVERLAY_PARAM_ENABLED_acquire_timing || 743b8e80941Smrg s == OVERLAY_PARAM_ENABLED_gpu_timing) { 744b8e80941Smrg double min_time = data->stats_min.stats[s] / data->time_dividor; 745b8e80941Smrg double max_time = data->stats_max.stats[s] / data->time_dividor; 746b8e80941Smrg ImGui::PlotHistogram(hash, get_time_stat, data, 747b8e80941Smrg ARRAY_SIZE(data->frames_stats), 0, 748b8e80941Smrg NULL, min_time, max_time, 749b8e80941Smrg ImVec2(ImGui::GetContentRegionAvailWidth(), 30)); 750b8e80941Smrg ImGui::Text("%s: %.3fms [%.3f, %.3f]", overlay_param_names[s], 751b8e80941Smrg get_time_stat(data, ARRAY_SIZE(data->frames_stats) - 1), 752b8e80941Smrg min_time, max_time); 753b8e80941Smrg } else { 754b8e80941Smrg ImGui::PlotHistogram(hash, get_stat, data, 755b8e80941Smrg ARRAY_SIZE(data->frames_stats), 0, 756b8e80941Smrg NULL, 757b8e80941Smrg data->stats_min.stats[s], 758b8e80941Smrg data->stats_max.stats[s], 759b8e80941Smrg ImVec2(ImGui::GetContentRegionAvailWidth(), 30)); 760b8e80941Smrg ImGui::Text("%s: %.0f [%" PRIu64 ", %" PRIu64 "]", overlay_param_names[s], 761b8e80941Smrg get_stat(data, ARRAY_SIZE(data->frames_stats) - 1), 762b8e80941Smrg data->stats_min.stats[s], data->stats_max.stats[s]); 763b8e80941Smrg } 764b8e80941Smrg } 765b8e80941Smrg data->window_size = ImVec2(data->window_size.x, ImGui::GetCursorPosY() + 10.0f); 766b8e80941Smrg ImGui::End(); 767b8e80941Smrg ImGui::EndFrame(); 768b8e80941Smrg ImGui::Render(); 769b8e80941Smrg} 770b8e80941Smrg 771b8e80941Smrgstatic uint32_t vk_memory_type(struct device_data *data, 772b8e80941Smrg VkMemoryPropertyFlags properties, 773b8e80941Smrg uint32_t type_bits) 774b8e80941Smrg{ 775b8e80941Smrg VkPhysicalDeviceMemoryProperties prop; 776b8e80941Smrg data->instance->vtable.GetPhysicalDeviceMemoryProperties(data->physical_device, &prop); 777b8e80941Smrg for (uint32_t i = 0; i < prop.memoryTypeCount; i++) 778b8e80941Smrg if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i)) 779b8e80941Smrg return i; 780b8e80941Smrg return 0xFFFFFFFF; // Unable to find memoryType 781b8e80941Smrg} 782b8e80941Smrg 783b8e80941Smrgstatic void ensure_swapchain_fonts(struct swapchain_data *data, 784b8e80941Smrg VkCommandBuffer command_buffer) 785b8e80941Smrg{ 786b8e80941Smrg if (data->font_uploaded) 787b8e80941Smrg return; 788b8e80941Smrg 789b8e80941Smrg data->font_uploaded = true; 790b8e80941Smrg 791b8e80941Smrg struct device_data *device_data = data->device; 792b8e80941Smrg ImGuiIO& io = ImGui::GetIO(); 793b8e80941Smrg unsigned char* pixels; 794b8e80941Smrg int width, height; 795b8e80941Smrg io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 796b8e80941Smrg size_t upload_size = width * height * 4 * sizeof(char); 797b8e80941Smrg 798b8e80941Smrg /* Upload buffer */ 799b8e80941Smrg VkBufferCreateInfo buffer_info = {}; 800b8e80941Smrg buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 801b8e80941Smrg buffer_info.size = upload_size; 802b8e80941Smrg buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; 803b8e80941Smrg buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 804b8e80941Smrg VK_CHECK(device_data->vtable.CreateBuffer(device_data->device, &buffer_info, 805b8e80941Smrg NULL, &data->upload_font_buffer)); 806b8e80941Smrg VkMemoryRequirements upload_buffer_req; 807b8e80941Smrg device_data->vtable.GetBufferMemoryRequirements(device_data->device, 808b8e80941Smrg data->upload_font_buffer, 809b8e80941Smrg &upload_buffer_req); 810b8e80941Smrg VkMemoryAllocateInfo upload_alloc_info = {}; 811b8e80941Smrg upload_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 812b8e80941Smrg upload_alloc_info.allocationSize = upload_buffer_req.size; 813b8e80941Smrg upload_alloc_info.memoryTypeIndex = vk_memory_type(device_data, 814b8e80941Smrg VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 815b8e80941Smrg upload_buffer_req.memoryTypeBits); 816b8e80941Smrg VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, 817b8e80941Smrg &upload_alloc_info, 818b8e80941Smrg NULL, 819b8e80941Smrg &data->upload_font_buffer_mem)); 820b8e80941Smrg VK_CHECK(device_data->vtable.BindBufferMemory(device_data->device, 821b8e80941Smrg data->upload_font_buffer, 822b8e80941Smrg data->upload_font_buffer_mem, 0)); 823b8e80941Smrg 824b8e80941Smrg /* Upload to Buffer */ 825b8e80941Smrg char* map = NULL; 826b8e80941Smrg VK_CHECK(device_data->vtable.MapMemory(device_data->device, 827b8e80941Smrg data->upload_font_buffer_mem, 828b8e80941Smrg 0, upload_size, 0, (void**)(&map))); 829b8e80941Smrg memcpy(map, pixels, upload_size); 830b8e80941Smrg VkMappedMemoryRange range[1] = {}; 831b8e80941Smrg range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 832b8e80941Smrg range[0].memory = data->upload_font_buffer_mem; 833b8e80941Smrg range[0].size = upload_size; 834b8e80941Smrg VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 1, range)); 835b8e80941Smrg device_data->vtable.UnmapMemory(device_data->device, 836b8e80941Smrg data->upload_font_buffer_mem); 837b8e80941Smrg 838b8e80941Smrg /* Copy buffer to image */ 839b8e80941Smrg VkImageMemoryBarrier copy_barrier[1] = {}; 840b8e80941Smrg copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 841b8e80941Smrg copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 842b8e80941Smrg copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 843b8e80941Smrg copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 844b8e80941Smrg copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 845b8e80941Smrg copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 846b8e80941Smrg copy_barrier[0].image = data->font_image; 847b8e80941Smrg copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 848b8e80941Smrg copy_barrier[0].subresourceRange.levelCount = 1; 849b8e80941Smrg copy_barrier[0].subresourceRange.layerCount = 1; 850b8e80941Smrg device_data->vtable.CmdPipelineBarrier(command_buffer, 851b8e80941Smrg VK_PIPELINE_STAGE_HOST_BIT, 852b8e80941Smrg VK_PIPELINE_STAGE_TRANSFER_BIT, 853b8e80941Smrg 0, 0, NULL, 0, NULL, 854b8e80941Smrg 1, copy_barrier); 855b8e80941Smrg 856b8e80941Smrg VkBufferImageCopy region = {}; 857b8e80941Smrg region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 858b8e80941Smrg region.imageSubresource.layerCount = 1; 859b8e80941Smrg region.imageExtent.width = width; 860b8e80941Smrg region.imageExtent.height = height; 861b8e80941Smrg region.imageExtent.depth = 1; 862b8e80941Smrg device_data->vtable.CmdCopyBufferToImage(command_buffer, 863b8e80941Smrg data->upload_font_buffer, 864b8e80941Smrg data->font_image, 865b8e80941Smrg VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 866b8e80941Smrg 1, ®ion); 867b8e80941Smrg 868b8e80941Smrg VkImageMemoryBarrier use_barrier[1] = {}; 869b8e80941Smrg use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 870b8e80941Smrg use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 871b8e80941Smrg use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 872b8e80941Smrg use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 873b8e80941Smrg use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 874b8e80941Smrg use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 875b8e80941Smrg use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 876b8e80941Smrg use_barrier[0].image = data->font_image; 877b8e80941Smrg use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 878b8e80941Smrg use_barrier[0].subresourceRange.levelCount = 1; 879b8e80941Smrg use_barrier[0].subresourceRange.layerCount = 1; 880b8e80941Smrg device_data->vtable.CmdPipelineBarrier(command_buffer, 881b8e80941Smrg VK_PIPELINE_STAGE_TRANSFER_BIT, 882b8e80941Smrg VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 883b8e80941Smrg 0, 884b8e80941Smrg 0, NULL, 885b8e80941Smrg 0, NULL, 886b8e80941Smrg 1, use_barrier); 887b8e80941Smrg 888b8e80941Smrg /* Store our identifier */ 889b8e80941Smrg io.Fonts->TexID = (ImTextureID)(intptr_t)data->font_image; 890b8e80941Smrg} 891b8e80941Smrg 892b8e80941Smrgstatic void CreateOrResizeBuffer(struct device_data *data, 893b8e80941Smrg VkBuffer *buffer, 894b8e80941Smrg VkDeviceMemory *buffer_memory, 895b8e80941Smrg VkDeviceSize *buffer_size, 896b8e80941Smrg size_t new_size, VkBufferUsageFlagBits usage) 897b8e80941Smrg{ 898b8e80941Smrg if (*buffer != VK_NULL_HANDLE) 899b8e80941Smrg data->vtable.DestroyBuffer(data->device, *buffer, NULL); 900b8e80941Smrg if (*buffer_memory) 901b8e80941Smrg data->vtable.FreeMemory(data->device, *buffer_memory, NULL); 902b8e80941Smrg 903b8e80941Smrg VkBufferCreateInfo buffer_info = {}; 904b8e80941Smrg buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 905b8e80941Smrg buffer_info.size = new_size; 906b8e80941Smrg buffer_info.usage = usage; 907b8e80941Smrg buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 908b8e80941Smrg VK_CHECK(data->vtable.CreateBuffer(data->device, &buffer_info, NULL, buffer)); 909b8e80941Smrg 910b8e80941Smrg VkMemoryRequirements req; 911b8e80941Smrg data->vtable.GetBufferMemoryRequirements(data->device, *buffer, &req); 912b8e80941Smrg VkMemoryAllocateInfo alloc_info = {}; 913b8e80941Smrg alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 914b8e80941Smrg alloc_info.allocationSize = req.size; 915b8e80941Smrg alloc_info.memoryTypeIndex = 916b8e80941Smrg vk_memory_type(data, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); 917b8e80941Smrg VK_CHECK(data->vtable.AllocateMemory(data->device, &alloc_info, NULL, buffer_memory)); 918b8e80941Smrg 919b8e80941Smrg VK_CHECK(data->vtable.BindBufferMemory(data->device, *buffer, *buffer_memory, 0)); 920b8e80941Smrg *buffer_size = new_size; 921b8e80941Smrg} 922b8e80941Smrg 923b8e80941Smrgstatic struct overlay_draw *render_swapchain_display(struct swapchain_data *data, 924b8e80941Smrg struct queue_data *present_queue, 925b8e80941Smrg const VkSemaphore *wait_semaphores, 926b8e80941Smrg unsigned n_wait_semaphores, 927b8e80941Smrg unsigned image_index) 928b8e80941Smrg{ 929b8e80941Smrg ImDrawData* draw_data = ImGui::GetDrawData(); 930b8e80941Smrg if (draw_data->TotalVtxCount == 0) 931b8e80941Smrg return NULL; 932b8e80941Smrg 933b8e80941Smrg struct device_data *device_data = data->device; 934b8e80941Smrg struct overlay_draw *draw = get_overlay_draw(data); 935b8e80941Smrg 936b8e80941Smrg device_data->vtable.ResetCommandBuffer(draw->command_buffer, 0); 937b8e80941Smrg 938b8e80941Smrg VkRenderPassBeginInfo render_pass_info = {}; 939b8e80941Smrg render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 940b8e80941Smrg render_pass_info.renderPass = data->render_pass; 941b8e80941Smrg render_pass_info.framebuffer = data->framebuffers[image_index]; 942b8e80941Smrg render_pass_info.renderArea.extent.width = data->width; 943b8e80941Smrg render_pass_info.renderArea.extent.height = data->height; 944b8e80941Smrg 945b8e80941Smrg VkCommandBufferBeginInfo buffer_begin_info = {}; 946b8e80941Smrg buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 947b8e80941Smrg 948b8e80941Smrg device_data->vtable.BeginCommandBuffer(draw->command_buffer, &buffer_begin_info); 949b8e80941Smrg 950b8e80941Smrg ensure_swapchain_fonts(data, draw->command_buffer); 951b8e80941Smrg 952b8e80941Smrg /* Bounce the image to display back to color attachment layout for 953b8e80941Smrg * rendering on top of it. 954b8e80941Smrg */ 955b8e80941Smrg VkImageMemoryBarrier imb; 956b8e80941Smrg imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 957b8e80941Smrg imb.pNext = nullptr; 958b8e80941Smrg imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 959b8e80941Smrg imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 960b8e80941Smrg imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 961b8e80941Smrg imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 962b8e80941Smrg imb.image = data->images[image_index]; 963b8e80941Smrg imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 964b8e80941Smrg imb.subresourceRange.baseMipLevel = 0; 965b8e80941Smrg imb.subresourceRange.levelCount = 1; 966b8e80941Smrg imb.subresourceRange.baseArrayLayer = 0; 967b8e80941Smrg imb.subresourceRange.layerCount = 1; 968b8e80941Smrg imb.srcQueueFamilyIndex = present_queue->family_index; 969b8e80941Smrg imb.dstQueueFamilyIndex = device_data->graphic_queue->family_index; 970b8e80941Smrg device_data->vtable.CmdPipelineBarrier(draw->command_buffer, 971b8e80941Smrg VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 972b8e80941Smrg VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 973b8e80941Smrg 0, /* dependency flags */ 974b8e80941Smrg 0, nullptr, /* memory barriers */ 975b8e80941Smrg 0, nullptr, /* buffer memory barriers */ 976b8e80941Smrg 1, &imb); /* image memory barriers */ 977b8e80941Smrg 978b8e80941Smrg device_data->vtable.CmdBeginRenderPass(draw->command_buffer, &render_pass_info, 979b8e80941Smrg VK_SUBPASS_CONTENTS_INLINE); 980b8e80941Smrg 981b8e80941Smrg /* Create/Resize vertex & index buffers */ 982b8e80941Smrg size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); 983b8e80941Smrg size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); 984b8e80941Smrg if (draw->vertex_buffer_size < vertex_size) { 985b8e80941Smrg CreateOrResizeBuffer(device_data, 986b8e80941Smrg &draw->vertex_buffer, 987b8e80941Smrg &draw->vertex_buffer_mem, 988b8e80941Smrg &draw->vertex_buffer_size, 989b8e80941Smrg vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 990b8e80941Smrg } 991b8e80941Smrg if (draw->index_buffer_size < index_size) { 992b8e80941Smrg CreateOrResizeBuffer(device_data, 993b8e80941Smrg &draw->index_buffer, 994b8e80941Smrg &draw->index_buffer_mem, 995b8e80941Smrg &draw->index_buffer_size, 996b8e80941Smrg index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); 997b8e80941Smrg } 998b8e80941Smrg 999b8e80941Smrg /* Upload vertex & index data */ 1000b8e80941Smrg ImDrawVert* vtx_dst = NULL; 1001b8e80941Smrg ImDrawIdx* idx_dst = NULL; 1002b8e80941Smrg VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->vertex_buffer_mem, 1003b8e80941Smrg 0, vertex_size, 0, (void**)(&vtx_dst))); 1004b8e80941Smrg VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->index_buffer_mem, 1005b8e80941Smrg 0, index_size, 0, (void**)(&idx_dst))); 1006b8e80941Smrg for (int n = 0; n < draw_data->CmdListsCount; n++) 1007b8e80941Smrg { 1008b8e80941Smrg const ImDrawList* cmd_list = draw_data->CmdLists[n]; 1009b8e80941Smrg memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); 1010b8e80941Smrg memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 1011b8e80941Smrg vtx_dst += cmd_list->VtxBuffer.Size; 1012b8e80941Smrg idx_dst += cmd_list->IdxBuffer.Size; 1013b8e80941Smrg } 1014b8e80941Smrg VkMappedMemoryRange range[2] = {}; 1015b8e80941Smrg range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 1016b8e80941Smrg range[0].memory = draw->vertex_buffer_mem; 1017b8e80941Smrg range[0].size = VK_WHOLE_SIZE; 1018b8e80941Smrg range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 1019b8e80941Smrg range[1].memory = draw->index_buffer_mem; 1020b8e80941Smrg range[1].size = VK_WHOLE_SIZE; 1021b8e80941Smrg VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 2, range)); 1022b8e80941Smrg device_data->vtable.UnmapMemory(device_data->device, draw->vertex_buffer_mem); 1023b8e80941Smrg device_data->vtable.UnmapMemory(device_data->device, draw->index_buffer_mem); 1024b8e80941Smrg 1025b8e80941Smrg /* Bind pipeline and descriptor sets */ 1026b8e80941Smrg device_data->vtable.CmdBindPipeline(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline); 1027b8e80941Smrg VkDescriptorSet desc_set[1] = { data->descriptor_set }; 1028b8e80941Smrg device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 1029b8e80941Smrg data->pipeline_layout, 0, 1, desc_set, 0, NULL); 1030b8e80941Smrg 1031b8e80941Smrg /* Bind vertex & index buffers */ 1032b8e80941Smrg VkBuffer vertex_buffers[1] = { draw->vertex_buffer }; 1033b8e80941Smrg VkDeviceSize vertex_offset[1] = { 0 }; 1034b8e80941Smrg device_data->vtable.CmdBindVertexBuffers(draw->command_buffer, 0, 1, vertex_buffers, vertex_offset); 1035b8e80941Smrg device_data->vtable.CmdBindIndexBuffer(draw->command_buffer, draw->index_buffer, 0, VK_INDEX_TYPE_UINT16); 1036b8e80941Smrg 1037b8e80941Smrg /* Setup viewport */ 1038b8e80941Smrg VkViewport viewport; 1039b8e80941Smrg viewport.x = 0; 1040b8e80941Smrg viewport.y = 0; 1041b8e80941Smrg viewport.width = draw_data->DisplaySize.x; 1042b8e80941Smrg viewport.height = draw_data->DisplaySize.y; 1043b8e80941Smrg viewport.minDepth = 0.0f; 1044b8e80941Smrg viewport.maxDepth = 1.0f; 1045b8e80941Smrg device_data->vtable.CmdSetViewport(draw->command_buffer, 0, 1, &viewport); 1046b8e80941Smrg 1047b8e80941Smrg 1048b8e80941Smrg /* Setup scale and translation through push constants : 1049b8e80941Smrg * 1050b8e80941Smrg * Our visible imgui space lies from draw_data->DisplayPos (top left) to 1051b8e80941Smrg * draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin 1052b8e80941Smrg * is typically (0,0) for single viewport apps. 1053b8e80941Smrg */ 1054b8e80941Smrg float scale[2]; 1055b8e80941Smrg scale[0] = 2.0f / draw_data->DisplaySize.x; 1056b8e80941Smrg scale[1] = 2.0f / draw_data->DisplaySize.y; 1057b8e80941Smrg float translate[2]; 1058b8e80941Smrg translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; 1059b8e80941Smrg translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; 1060b8e80941Smrg device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, 1061b8e80941Smrg VK_SHADER_STAGE_VERTEX_BIT, 1062b8e80941Smrg sizeof(float) * 0, sizeof(float) * 2, scale); 1063b8e80941Smrg device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, 1064b8e80941Smrg VK_SHADER_STAGE_VERTEX_BIT, 1065b8e80941Smrg sizeof(float) * 2, sizeof(float) * 2, translate); 1066b8e80941Smrg 1067b8e80941Smrg // Render the command lists: 1068b8e80941Smrg int vtx_offset = 0; 1069b8e80941Smrg int idx_offset = 0; 1070b8e80941Smrg ImVec2 display_pos = draw_data->DisplayPos; 1071b8e80941Smrg for (int n = 0; n < draw_data->CmdListsCount; n++) 1072b8e80941Smrg { 1073b8e80941Smrg const ImDrawList* cmd_list = draw_data->CmdLists[n]; 1074b8e80941Smrg for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 1075b8e80941Smrg { 1076b8e80941Smrg const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 1077b8e80941Smrg // Apply scissor/clipping rectangle 1078b8e80941Smrg // FIXME: We could clamp width/height based on clamped min/max values. 1079b8e80941Smrg VkRect2D scissor; 1080b8e80941Smrg scissor.offset.x = (int32_t)(pcmd->ClipRect.x - display_pos.x) > 0 ? (int32_t)(pcmd->ClipRect.x - display_pos.x) : 0; 1081b8e80941Smrg scissor.offset.y = (int32_t)(pcmd->ClipRect.y - display_pos.y) > 0 ? (int32_t)(pcmd->ClipRect.y - display_pos.y) : 0; 1082b8e80941Smrg scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); 1083b8e80941Smrg scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here? 1084b8e80941Smrg device_data->vtable.CmdSetScissor(draw->command_buffer, 0, 1, &scissor); 1085b8e80941Smrg 1086b8e80941Smrg // Draw 1087b8e80941Smrg device_data->vtable.CmdDrawIndexed(draw->command_buffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); 1088b8e80941Smrg 1089b8e80941Smrg idx_offset += pcmd->ElemCount; 1090b8e80941Smrg } 1091b8e80941Smrg vtx_offset += cmd_list->VtxBuffer.Size; 1092b8e80941Smrg } 1093b8e80941Smrg 1094b8e80941Smrg device_data->vtable.CmdEndRenderPass(draw->command_buffer); 1095b8e80941Smrg 1096b8e80941Smrg /* Bounce the image to display back to present layout. */ 1097b8e80941Smrg imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 1098b8e80941Smrg imb.pNext = nullptr; 1099b8e80941Smrg imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 1100b8e80941Smrg imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 1101b8e80941Smrg imb.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1102b8e80941Smrg imb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 1103b8e80941Smrg imb.image = data->images[image_index]; 1104b8e80941Smrg imb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1105b8e80941Smrg imb.subresourceRange.baseMipLevel = 0; 1106b8e80941Smrg imb.subresourceRange.levelCount = 1; 1107b8e80941Smrg imb.subresourceRange.baseArrayLayer = 0; 1108b8e80941Smrg imb.subresourceRange.layerCount = 1; 1109b8e80941Smrg imb.srcQueueFamilyIndex = device_data->graphic_queue->family_index; 1110b8e80941Smrg imb.dstQueueFamilyIndex = present_queue->family_index; 1111b8e80941Smrg device_data->vtable.CmdPipelineBarrier(draw->command_buffer, 1112b8e80941Smrg VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 1113b8e80941Smrg VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 1114b8e80941Smrg 0, /* dependency flags */ 1115b8e80941Smrg 0, nullptr, /* memory barriers */ 1116b8e80941Smrg 0, nullptr, /* buffer memory barriers */ 1117b8e80941Smrg 1, &imb); /* image memory barriers */ 1118b8e80941Smrg 1119b8e80941Smrg device_data->vtable.EndCommandBuffer(draw->command_buffer); 1120b8e80941Smrg 1121b8e80941Smrg VkSubmitInfo submit_info = {}; 1122b8e80941Smrg VkPipelineStageFlags stage_wait = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 1123b8e80941Smrg submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 1124b8e80941Smrg submit_info.commandBufferCount = 1; 1125b8e80941Smrg submit_info.pCommandBuffers = &draw->command_buffer; 1126b8e80941Smrg submit_info.pWaitDstStageMask = &stage_wait; 1127b8e80941Smrg submit_info.waitSemaphoreCount = n_wait_semaphores; 1128b8e80941Smrg submit_info.pWaitSemaphores = wait_semaphores; 1129b8e80941Smrg submit_info.signalSemaphoreCount = 1; 1130b8e80941Smrg submit_info.pSignalSemaphores = &draw->semaphore; 1131b8e80941Smrg 1132b8e80941Smrg device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); 1133b8e80941Smrg 1134b8e80941Smrg return draw; 1135b8e80941Smrg} 1136b8e80941Smrg 1137b8e80941Smrgstatic const uint32_t overlay_vert_spv[] = { 1138b8e80941Smrg#include "overlay.vert.spv.h" 1139b8e80941Smrg}; 1140b8e80941Smrgstatic const uint32_t overlay_frag_spv[] = { 1141b8e80941Smrg#include "overlay.frag.spv.h" 1142b8e80941Smrg}; 1143b8e80941Smrg 1144b8e80941Smrgstatic void setup_swapchain_data_pipeline(struct swapchain_data *data) 1145b8e80941Smrg{ 1146b8e80941Smrg struct device_data *device_data = data->device; 1147b8e80941Smrg VkShaderModule vert_module, frag_module; 1148b8e80941Smrg 1149b8e80941Smrg /* Create shader modules */ 1150b8e80941Smrg VkShaderModuleCreateInfo vert_info = {}; 1151b8e80941Smrg vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 1152b8e80941Smrg vert_info.codeSize = sizeof(overlay_vert_spv); 1153b8e80941Smrg vert_info.pCode = overlay_vert_spv; 1154b8e80941Smrg VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, 1155b8e80941Smrg &vert_info, NULL, &vert_module)); 1156b8e80941Smrg VkShaderModuleCreateInfo frag_info = {}; 1157b8e80941Smrg frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 1158b8e80941Smrg frag_info.codeSize = sizeof(overlay_frag_spv); 1159b8e80941Smrg frag_info.pCode = (uint32_t*)overlay_frag_spv; 1160b8e80941Smrg VK_CHECK(device_data->vtable.CreateShaderModule(device_data->device, 1161b8e80941Smrg &frag_info, NULL, &frag_module)); 1162b8e80941Smrg 1163b8e80941Smrg /* Font sampler */ 1164b8e80941Smrg VkSamplerCreateInfo sampler_info = {}; 1165b8e80941Smrg sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 1166b8e80941Smrg sampler_info.magFilter = VK_FILTER_LINEAR; 1167b8e80941Smrg sampler_info.minFilter = VK_FILTER_LINEAR; 1168b8e80941Smrg sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 1169b8e80941Smrg sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; 1170b8e80941Smrg sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; 1171b8e80941Smrg sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; 1172b8e80941Smrg sampler_info.minLod = -1000; 1173b8e80941Smrg sampler_info.maxLod = 1000; 1174b8e80941Smrg sampler_info.maxAnisotropy = 1.0f; 1175b8e80941Smrg VK_CHECK(device_data->vtable.CreateSampler(device_data->device, &sampler_info, 1176b8e80941Smrg NULL, &data->font_sampler)); 1177b8e80941Smrg 1178b8e80941Smrg /* Descriptor pool */ 1179b8e80941Smrg VkDescriptorPoolSize sampler_pool_size = {}; 1180b8e80941Smrg sampler_pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 1181b8e80941Smrg sampler_pool_size.descriptorCount = 1; 1182b8e80941Smrg VkDescriptorPoolCreateInfo desc_pool_info = {}; 1183b8e80941Smrg desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 1184b8e80941Smrg desc_pool_info.maxSets = 1; 1185b8e80941Smrg desc_pool_info.poolSizeCount = 1; 1186b8e80941Smrg desc_pool_info.pPoolSizes = &sampler_pool_size; 1187b8e80941Smrg VK_CHECK(device_data->vtable.CreateDescriptorPool(device_data->device, 1188b8e80941Smrg &desc_pool_info, 1189b8e80941Smrg NULL, &data->descriptor_pool)); 1190b8e80941Smrg 1191b8e80941Smrg /* Descriptor layout */ 1192b8e80941Smrg VkSampler sampler[1] = { data->font_sampler }; 1193b8e80941Smrg VkDescriptorSetLayoutBinding binding[1] = {}; 1194b8e80941Smrg binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 1195b8e80941Smrg binding[0].descriptorCount = 1; 1196b8e80941Smrg binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; 1197b8e80941Smrg binding[0].pImmutableSamplers = sampler; 1198b8e80941Smrg VkDescriptorSetLayoutCreateInfo set_layout_info = {}; 1199b8e80941Smrg set_layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 1200b8e80941Smrg set_layout_info.bindingCount = 1; 1201b8e80941Smrg set_layout_info.pBindings = binding; 1202b8e80941Smrg VK_CHECK(device_data->vtable.CreateDescriptorSetLayout(device_data->device, 1203b8e80941Smrg &set_layout_info, 1204b8e80941Smrg NULL, &data->descriptor_layout)); 1205b8e80941Smrg 1206b8e80941Smrg /* Descriptor set */ 1207b8e80941Smrg VkDescriptorSetAllocateInfo alloc_info = {}; 1208b8e80941Smrg alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 1209b8e80941Smrg alloc_info.descriptorPool = data->descriptor_pool; 1210b8e80941Smrg alloc_info.descriptorSetCount = 1; 1211b8e80941Smrg alloc_info.pSetLayouts = &data->descriptor_layout; 1212b8e80941Smrg VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, 1213b8e80941Smrg &alloc_info, 1214b8e80941Smrg &data->descriptor_set)); 1215b8e80941Smrg 1216b8e80941Smrg /* Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 1217b8e80941Smrg * 3d projection matrix 1218b8e80941Smrg */ 1219b8e80941Smrg VkPushConstantRange push_constants[1] = {}; 1220b8e80941Smrg push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; 1221b8e80941Smrg push_constants[0].offset = sizeof(float) * 0; 1222b8e80941Smrg push_constants[0].size = sizeof(float) * 4; 1223b8e80941Smrg VkPipelineLayoutCreateInfo layout_info = {}; 1224b8e80941Smrg layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 1225b8e80941Smrg layout_info.setLayoutCount = 1; 1226b8e80941Smrg layout_info.pSetLayouts = &data->descriptor_layout; 1227b8e80941Smrg layout_info.pushConstantRangeCount = 1; 1228b8e80941Smrg layout_info.pPushConstantRanges = push_constants; 1229b8e80941Smrg VK_CHECK(device_data->vtable.CreatePipelineLayout(device_data->device, 1230b8e80941Smrg &layout_info, 1231b8e80941Smrg NULL, &data->pipeline_layout)); 1232b8e80941Smrg 1233b8e80941Smrg VkPipelineShaderStageCreateInfo stage[2] = {}; 1234b8e80941Smrg stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1235b8e80941Smrg stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 1236b8e80941Smrg stage[0].module = vert_module; 1237b8e80941Smrg stage[0].pName = "main"; 1238b8e80941Smrg stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 1239b8e80941Smrg stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 1240b8e80941Smrg stage[1].module = frag_module; 1241b8e80941Smrg stage[1].pName = "main"; 1242b8e80941Smrg 1243b8e80941Smrg VkVertexInputBindingDescription binding_desc[1] = {}; 1244b8e80941Smrg binding_desc[0].stride = sizeof(ImDrawVert); 1245b8e80941Smrg binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 1246b8e80941Smrg 1247b8e80941Smrg VkVertexInputAttributeDescription attribute_desc[3] = {}; 1248b8e80941Smrg attribute_desc[0].location = 0; 1249b8e80941Smrg attribute_desc[0].binding = binding_desc[0].binding; 1250b8e80941Smrg attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; 1251b8e80941Smrg attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos); 1252b8e80941Smrg attribute_desc[1].location = 1; 1253b8e80941Smrg attribute_desc[1].binding = binding_desc[0].binding; 1254b8e80941Smrg attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; 1255b8e80941Smrg attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv); 1256b8e80941Smrg attribute_desc[2].location = 2; 1257b8e80941Smrg attribute_desc[2].binding = binding_desc[0].binding; 1258b8e80941Smrg attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; 1259b8e80941Smrg attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col); 1260b8e80941Smrg 1261b8e80941Smrg VkPipelineVertexInputStateCreateInfo vertex_info = {}; 1262b8e80941Smrg vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 1263b8e80941Smrg vertex_info.vertexBindingDescriptionCount = 1; 1264b8e80941Smrg vertex_info.pVertexBindingDescriptions = binding_desc; 1265b8e80941Smrg vertex_info.vertexAttributeDescriptionCount = 3; 1266b8e80941Smrg vertex_info.pVertexAttributeDescriptions = attribute_desc; 1267b8e80941Smrg 1268b8e80941Smrg VkPipelineInputAssemblyStateCreateInfo ia_info = {}; 1269b8e80941Smrg ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; 1270b8e80941Smrg ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1271b8e80941Smrg 1272b8e80941Smrg VkPipelineViewportStateCreateInfo viewport_info = {}; 1273b8e80941Smrg viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; 1274b8e80941Smrg viewport_info.viewportCount = 1; 1275b8e80941Smrg viewport_info.scissorCount = 1; 1276b8e80941Smrg 1277b8e80941Smrg VkPipelineRasterizationStateCreateInfo raster_info = {}; 1278b8e80941Smrg raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 1279b8e80941Smrg raster_info.polygonMode = VK_POLYGON_MODE_FILL; 1280b8e80941Smrg raster_info.cullMode = VK_CULL_MODE_NONE; 1281b8e80941Smrg raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; 1282b8e80941Smrg raster_info.lineWidth = 1.0f; 1283b8e80941Smrg 1284b8e80941Smrg VkPipelineMultisampleStateCreateInfo ms_info = {}; 1285b8e80941Smrg ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; 1286b8e80941Smrg ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 1287b8e80941Smrg 1288b8e80941Smrg VkPipelineColorBlendAttachmentState color_attachment[1] = {}; 1289b8e80941Smrg color_attachment[0].blendEnable = VK_TRUE; 1290b8e80941Smrg color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 1291b8e80941Smrg color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 1292b8e80941Smrg color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; 1293b8e80941Smrg color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 1294b8e80941Smrg color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 1295b8e80941Smrg color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; 1296b8e80941Smrg color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | 1297b8e80941Smrg VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 1298b8e80941Smrg 1299b8e80941Smrg VkPipelineDepthStencilStateCreateInfo depth_info = {}; 1300b8e80941Smrg depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; 1301b8e80941Smrg 1302b8e80941Smrg VkPipelineColorBlendStateCreateInfo blend_info = {}; 1303b8e80941Smrg blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; 1304b8e80941Smrg blend_info.attachmentCount = 1; 1305b8e80941Smrg blend_info.pAttachments = color_attachment; 1306b8e80941Smrg 1307b8e80941Smrg VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; 1308b8e80941Smrg VkPipelineDynamicStateCreateInfo dynamic_state = {}; 1309b8e80941Smrg dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; 1310b8e80941Smrg dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); 1311b8e80941Smrg dynamic_state.pDynamicStates = dynamic_states; 1312b8e80941Smrg 1313b8e80941Smrg VkGraphicsPipelineCreateInfo info = {}; 1314b8e80941Smrg info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 1315b8e80941Smrg info.flags = 0; 1316b8e80941Smrg info.stageCount = 2; 1317b8e80941Smrg info.pStages = stage; 1318b8e80941Smrg info.pVertexInputState = &vertex_info; 1319b8e80941Smrg info.pInputAssemblyState = &ia_info; 1320b8e80941Smrg info.pViewportState = &viewport_info; 1321b8e80941Smrg info.pRasterizationState = &raster_info; 1322b8e80941Smrg info.pMultisampleState = &ms_info; 1323b8e80941Smrg info.pDepthStencilState = &depth_info; 1324b8e80941Smrg info.pColorBlendState = &blend_info; 1325b8e80941Smrg info.pDynamicState = &dynamic_state; 1326b8e80941Smrg info.layout = data->pipeline_layout; 1327b8e80941Smrg info.renderPass = data->render_pass; 1328b8e80941Smrg VK_CHECK( 1329b8e80941Smrg device_data->vtable.CreateGraphicsPipelines(device_data->device, VK_NULL_HANDLE, 1330b8e80941Smrg 1, &info, 1331b8e80941Smrg NULL, &data->pipeline)); 1332b8e80941Smrg 1333b8e80941Smrg device_data->vtable.DestroyShaderModule(device_data->device, vert_module, NULL); 1334b8e80941Smrg device_data->vtable.DestroyShaderModule(device_data->device, frag_module, NULL); 1335b8e80941Smrg 1336b8e80941Smrg ImGuiIO& io = ImGui::GetIO(); 1337b8e80941Smrg unsigned char* pixels; 1338b8e80941Smrg int width, height; 1339b8e80941Smrg io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 1340b8e80941Smrg 1341b8e80941Smrg /* Font image */ 1342b8e80941Smrg VkImageCreateInfo image_info = {}; 1343b8e80941Smrg image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 1344b8e80941Smrg image_info.imageType = VK_IMAGE_TYPE_2D; 1345b8e80941Smrg image_info.format = VK_FORMAT_R8G8B8A8_UNORM; 1346b8e80941Smrg image_info.extent.width = width; 1347b8e80941Smrg image_info.extent.height = height; 1348b8e80941Smrg image_info.extent.depth = 1; 1349b8e80941Smrg image_info.mipLevels = 1; 1350b8e80941Smrg image_info.arrayLayers = 1; 1351b8e80941Smrg image_info.samples = VK_SAMPLE_COUNT_1_BIT; 1352b8e80941Smrg image_info.tiling = VK_IMAGE_TILING_OPTIMAL; 1353b8e80941Smrg image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 1354b8e80941Smrg image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 1355b8e80941Smrg image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 1356b8e80941Smrg VK_CHECK(device_data->vtable.CreateImage(device_data->device, &image_info, 1357b8e80941Smrg NULL, &data->font_image)); 1358b8e80941Smrg VkMemoryRequirements font_image_req; 1359b8e80941Smrg device_data->vtable.GetImageMemoryRequirements(device_data->device, 1360b8e80941Smrg data->font_image, &font_image_req); 1361b8e80941Smrg VkMemoryAllocateInfo image_alloc_info = {}; 1362b8e80941Smrg image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 1363b8e80941Smrg image_alloc_info.allocationSize = font_image_req.size; 1364b8e80941Smrg image_alloc_info.memoryTypeIndex = vk_memory_type(device_data, 1365b8e80941Smrg VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 1366b8e80941Smrg font_image_req.memoryTypeBits); 1367b8e80941Smrg VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, &image_alloc_info, 1368b8e80941Smrg NULL, &data->font_mem)); 1369b8e80941Smrg VK_CHECK(device_data->vtable.BindImageMemory(device_data->device, 1370b8e80941Smrg data->font_image, 1371b8e80941Smrg data->font_mem, 0)); 1372b8e80941Smrg 1373b8e80941Smrg /* Font image view */ 1374b8e80941Smrg VkImageViewCreateInfo view_info = {}; 1375b8e80941Smrg view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 1376b8e80941Smrg view_info.image = data->font_image; 1377b8e80941Smrg view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 1378b8e80941Smrg view_info.format = VK_FORMAT_R8G8B8A8_UNORM; 1379b8e80941Smrg view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 1380b8e80941Smrg view_info.subresourceRange.levelCount = 1; 1381b8e80941Smrg view_info.subresourceRange.layerCount = 1; 1382b8e80941Smrg VK_CHECK(device_data->vtable.CreateImageView(device_data->device, &view_info, 1383b8e80941Smrg NULL, &data->font_image_view)); 1384b8e80941Smrg 1385b8e80941Smrg /* Descriptor set */ 1386b8e80941Smrg VkDescriptorImageInfo desc_image[1] = {}; 1387b8e80941Smrg desc_image[0].sampler = data->font_sampler; 1388b8e80941Smrg desc_image[0].imageView = data->font_image_view; 1389b8e80941Smrg desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 1390b8e80941Smrg VkWriteDescriptorSet write_desc[1] = {}; 1391b8e80941Smrg write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 1392b8e80941Smrg write_desc[0].dstSet = data->descriptor_set; 1393b8e80941Smrg write_desc[0].descriptorCount = 1; 1394b8e80941Smrg write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 1395b8e80941Smrg write_desc[0].pImageInfo = desc_image; 1396b8e80941Smrg device_data->vtable.UpdateDescriptorSets(device_data->device, 1, write_desc, 0, NULL); 1397b8e80941Smrg} 1398b8e80941Smrg 1399b8e80941Smrgstatic void setup_swapchain_data(struct swapchain_data *data, 1400b8e80941Smrg const VkSwapchainCreateInfoKHR *pCreateInfo) 1401b8e80941Smrg{ 1402b8e80941Smrg data->width = pCreateInfo->imageExtent.width; 1403b8e80941Smrg data->height = pCreateInfo->imageExtent.height; 1404b8e80941Smrg data->format = pCreateInfo->imageFormat; 1405b8e80941Smrg 1406b8e80941Smrg data->imgui_context = ImGui::CreateContext(); 1407b8e80941Smrg ImGui::SetCurrentContext(data->imgui_context); 1408b8e80941Smrg 1409b8e80941Smrg ImGui::GetIO().IniFilename = NULL; 1410b8e80941Smrg ImGui::GetIO().DisplaySize = ImVec2((float)data->width, (float)data->height); 1411b8e80941Smrg 1412b8e80941Smrg struct device_data *device_data = data->device; 1413b8e80941Smrg 1414b8e80941Smrg /* Render pass */ 1415b8e80941Smrg VkAttachmentDescription attachment_desc = {}; 1416b8e80941Smrg attachment_desc.format = pCreateInfo->imageFormat; 1417b8e80941Smrg attachment_desc.samples = VK_SAMPLE_COUNT_1_BIT; 1418b8e80941Smrg attachment_desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; 1419b8e80941Smrg attachment_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 1420b8e80941Smrg attachment_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 1421b8e80941Smrg attachment_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 1422b8e80941Smrg attachment_desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1423b8e80941Smrg attachment_desc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 1424b8e80941Smrg VkAttachmentReference color_attachment = {}; 1425b8e80941Smrg color_attachment.attachment = 0; 1426b8e80941Smrg color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 1427b8e80941Smrg VkSubpassDescription subpass = {}; 1428b8e80941Smrg subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 1429b8e80941Smrg subpass.colorAttachmentCount = 1; 1430b8e80941Smrg subpass.pColorAttachments = &color_attachment; 1431b8e80941Smrg VkSubpassDependency dependency = {}; 1432b8e80941Smrg dependency.srcSubpass = VK_SUBPASS_EXTERNAL; 1433b8e80941Smrg dependency.dstSubpass = 0; 1434b8e80941Smrg dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1435b8e80941Smrg dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1436b8e80941Smrg dependency.srcAccessMask = 0; 1437b8e80941Smrg dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 1438b8e80941Smrg VkRenderPassCreateInfo render_pass_info = {}; 1439b8e80941Smrg render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 1440b8e80941Smrg render_pass_info.attachmentCount = 1; 1441b8e80941Smrg render_pass_info.pAttachments = &attachment_desc; 1442b8e80941Smrg render_pass_info.subpassCount = 1; 1443b8e80941Smrg render_pass_info.pSubpasses = &subpass; 1444b8e80941Smrg render_pass_info.dependencyCount = 1; 1445b8e80941Smrg render_pass_info.pDependencies = &dependency; 1446b8e80941Smrg VK_CHECK(device_data->vtable.CreateRenderPass(device_data->device, 1447b8e80941Smrg &render_pass_info, 1448b8e80941Smrg NULL, &data->render_pass)); 1449b8e80941Smrg 1450b8e80941Smrg setup_swapchain_data_pipeline(data); 1451b8e80941Smrg 1452b8e80941Smrg VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, 1453b8e80941Smrg data->swapchain, 1454b8e80941Smrg &data->n_images, 1455b8e80941Smrg NULL)); 1456b8e80941Smrg 1457b8e80941Smrg data->images = ralloc_array(data, VkImage, data->n_images); 1458b8e80941Smrg data->image_views = ralloc_array(data, VkImageView, data->n_images); 1459b8e80941Smrg data->framebuffers = ralloc_array(data, VkFramebuffer, data->n_images); 1460b8e80941Smrg 1461b8e80941Smrg VK_CHECK(device_data->vtable.GetSwapchainImagesKHR(device_data->device, 1462b8e80941Smrg data->swapchain, 1463b8e80941Smrg &data->n_images, 1464b8e80941Smrg data->images)); 1465b8e80941Smrg 1466b8e80941Smrg /* Image views */ 1467b8e80941Smrg VkImageViewCreateInfo view_info = {}; 1468b8e80941Smrg view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 1469b8e80941Smrg view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; 1470b8e80941Smrg view_info.format = pCreateInfo->imageFormat; 1471b8e80941Smrg view_info.components.r = VK_COMPONENT_SWIZZLE_R; 1472b8e80941Smrg view_info.components.g = VK_COMPONENT_SWIZZLE_G; 1473b8e80941Smrg view_info.components.b = VK_COMPONENT_SWIZZLE_B; 1474b8e80941Smrg view_info.components.a = VK_COMPONENT_SWIZZLE_A; 1475b8e80941Smrg view_info.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 1476b8e80941Smrg for (uint32_t i = 0; i < data->n_images; i++) { 1477b8e80941Smrg view_info.image = data->images[i]; 1478b8e80941Smrg VK_CHECK(device_data->vtable.CreateImageView(device_data->device, 1479b8e80941Smrg &view_info, NULL, 1480b8e80941Smrg &data->image_views[i])); 1481b8e80941Smrg } 1482b8e80941Smrg 1483b8e80941Smrg /* Framebuffers */ 1484b8e80941Smrg VkImageView attachment[1]; 1485b8e80941Smrg VkFramebufferCreateInfo fb_info = {}; 1486b8e80941Smrg fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 1487b8e80941Smrg fb_info.renderPass = data->render_pass; 1488b8e80941Smrg fb_info.attachmentCount = 1; 1489b8e80941Smrg fb_info.pAttachments = attachment; 1490b8e80941Smrg fb_info.width = data->width; 1491b8e80941Smrg fb_info.height = data->height; 1492b8e80941Smrg fb_info.layers = 1; 1493b8e80941Smrg for (uint32_t i = 0; i < data->n_images; i++) { 1494b8e80941Smrg attachment[0] = data->image_views[i]; 1495b8e80941Smrg VK_CHECK(device_data->vtable.CreateFramebuffer(device_data->device, &fb_info, 1496b8e80941Smrg NULL, &data->framebuffers[i])); 1497b8e80941Smrg } 1498b8e80941Smrg 1499b8e80941Smrg /* Command buffer pool */ 1500b8e80941Smrg VkCommandPoolCreateInfo cmd_buffer_pool_info = {}; 1501b8e80941Smrg cmd_buffer_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 1502b8e80941Smrg cmd_buffer_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; 1503b8e80941Smrg cmd_buffer_pool_info.queueFamilyIndex = device_data->graphic_queue->family_index; 1504b8e80941Smrg VK_CHECK(device_data->vtable.CreateCommandPool(device_data->device, 1505b8e80941Smrg &cmd_buffer_pool_info, 1506b8e80941Smrg NULL, &data->command_pool)); 1507b8e80941Smrg} 1508b8e80941Smrg 1509b8e80941Smrgstatic void shutdown_swapchain_data(struct swapchain_data *data) 1510b8e80941Smrg{ 1511b8e80941Smrg struct device_data *device_data = data->device; 1512b8e80941Smrg 1513b8e80941Smrg list_for_each_entry_safe(struct overlay_draw, draw, &data->draws, link) { 1514b8e80941Smrg device_data->vtable.DestroySemaphore(device_data->device, draw->semaphore, NULL); 1515b8e80941Smrg device_data->vtable.DestroyFence(device_data->device, draw->fence, NULL); 1516b8e80941Smrg device_data->vtable.DestroyBuffer(device_data->device, draw->vertex_buffer, NULL); 1517b8e80941Smrg device_data->vtable.DestroyBuffer(device_data->device, draw->index_buffer, NULL); 1518b8e80941Smrg device_data->vtable.FreeMemory(device_data->device, draw->vertex_buffer_mem, NULL); 1519b8e80941Smrg device_data->vtable.FreeMemory(device_data->device, draw->index_buffer_mem, NULL); 1520b8e80941Smrg } 1521b8e80941Smrg 1522b8e80941Smrg for (uint32_t i = 0; i < data->n_images; i++) { 1523b8e80941Smrg device_data->vtable.DestroyImageView(device_data->device, data->image_views[i], NULL); 1524b8e80941Smrg device_data->vtable.DestroyFramebuffer(device_data->device, data->framebuffers[i], NULL); 1525b8e80941Smrg } 1526b8e80941Smrg 1527b8e80941Smrg device_data->vtable.DestroyRenderPass(device_data->device, data->render_pass, NULL); 1528b8e80941Smrg 1529b8e80941Smrg device_data->vtable.DestroyCommandPool(device_data->device, data->command_pool, NULL); 1530b8e80941Smrg 1531b8e80941Smrg device_data->vtable.DestroyPipeline(device_data->device, data->pipeline, NULL); 1532b8e80941Smrg device_data->vtable.DestroyPipelineLayout(device_data->device, data->pipeline_layout, NULL); 1533b8e80941Smrg 1534b8e80941Smrg device_data->vtable.DestroyDescriptorPool(device_data->device, 1535b8e80941Smrg data->descriptor_pool, NULL); 1536b8e80941Smrg device_data->vtable.DestroyDescriptorSetLayout(device_data->device, 1537b8e80941Smrg data->descriptor_layout, NULL); 1538b8e80941Smrg 1539b8e80941Smrg device_data->vtable.DestroySampler(device_data->device, data->font_sampler, NULL); 1540b8e80941Smrg device_data->vtable.DestroyImageView(device_data->device, data->font_image_view, NULL); 1541b8e80941Smrg device_data->vtable.DestroyImage(device_data->device, data->font_image, NULL); 1542b8e80941Smrg device_data->vtable.FreeMemory(device_data->device, data->font_mem, NULL); 1543b8e80941Smrg 1544b8e80941Smrg device_data->vtable.DestroyBuffer(device_data->device, data->upload_font_buffer, NULL); 1545b8e80941Smrg device_data->vtable.FreeMemory(device_data->device, data->upload_font_buffer_mem, NULL); 1546b8e80941Smrg 1547b8e80941Smrg ImGui::DestroyContext(data->imgui_context); 1548b8e80941Smrg} 1549b8e80941Smrg 1550b8e80941Smrgstatic struct overlay_draw *before_present(struct swapchain_data *swapchain_data, 1551b8e80941Smrg struct queue_data *present_queue, 1552b8e80941Smrg const VkSemaphore *wait_semaphores, 1553b8e80941Smrg unsigned n_wait_semaphores, 1554b8e80941Smrg unsigned imageIndex) 1555b8e80941Smrg{ 1556b8e80941Smrg struct instance_data *instance_data = swapchain_data->device->instance; 1557b8e80941Smrg struct overlay_draw *draw = NULL; 1558b8e80941Smrg 1559b8e80941Smrg snapshot_swapchain_frame(swapchain_data); 1560b8e80941Smrg 1561b8e80941Smrg if (!instance_data->params.no_display && swapchain_data->n_frames > 0) { 1562b8e80941Smrg compute_swapchain_display(swapchain_data); 1563b8e80941Smrg draw = render_swapchain_display(swapchain_data, present_queue, 1564b8e80941Smrg wait_semaphores, n_wait_semaphores, 1565b8e80941Smrg imageIndex); 1566b8e80941Smrg } 1567b8e80941Smrg 1568b8e80941Smrg return draw; 1569b8e80941Smrg} 1570b8e80941Smrg 1571b8e80941Smrgstatic VkResult overlay_CreateSwapchainKHR( 1572b8e80941Smrg VkDevice device, 1573b8e80941Smrg const VkSwapchainCreateInfoKHR* pCreateInfo, 1574b8e80941Smrg const VkAllocationCallbacks* pAllocator, 1575b8e80941Smrg VkSwapchainKHR* pSwapchain) 1576b8e80941Smrg{ 1577b8e80941Smrg struct device_data *device_data = FIND_DEVICE_DATA(device); 1578b8e80941Smrg VkResult result = device_data->vtable.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 1579b8e80941Smrg if (result != VK_SUCCESS) return result; 1580b8e80941Smrg 1581b8e80941Smrg struct swapchain_data *swapchain_data = new_swapchain_data(*pSwapchain, device_data); 1582b8e80941Smrg setup_swapchain_data(swapchain_data, pCreateInfo); 1583b8e80941Smrg return result; 1584b8e80941Smrg} 1585b8e80941Smrg 1586b8e80941Smrgstatic void overlay_DestroySwapchainKHR( 1587b8e80941Smrg VkDevice device, 1588b8e80941Smrg VkSwapchainKHR swapchain, 1589b8e80941Smrg const VkAllocationCallbacks* pAllocator) 1590b8e80941Smrg{ 1591b8e80941Smrg struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(swapchain); 1592b8e80941Smrg 1593b8e80941Smrg shutdown_swapchain_data(swapchain_data); 1594b8e80941Smrg swapchain_data->device->vtable.DestroySwapchainKHR(device, swapchain, pAllocator); 1595b8e80941Smrg destroy_swapchain_data(swapchain_data); 1596b8e80941Smrg} 1597b8e80941Smrg 1598b8e80941Smrgstatic VkResult overlay_QueuePresentKHR( 1599b8e80941Smrg VkQueue queue, 1600b8e80941Smrg const VkPresentInfoKHR* pPresentInfo) 1601b8e80941Smrg{ 1602b8e80941Smrg struct queue_data *queue_data = FIND_QUEUE_DATA(queue); 1603b8e80941Smrg struct device_data *device_data = queue_data->device; 1604b8e80941Smrg struct instance_data *instance_data = device_data->instance; 1605b8e80941Smrg uint32_t query_results[OVERLAY_QUERY_COUNT]; 1606b8e80941Smrg 1607b8e80941Smrg device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_frame]++; 1608b8e80941Smrg 1609b8e80941Smrg if (list_length(&queue_data->running_command_buffer) > 0) { 1610b8e80941Smrg /* Before getting the query results, make sure the operations have 1611b8e80941Smrg * completed. 1612b8e80941Smrg */ 1613b8e80941Smrg VkResult err = device_data->vtable.ResetFences(device_data->device, 1614b8e80941Smrg 1, &queue_data->queries_fence); 1615b8e80941Smrg check_vk_result(err); 1616b8e80941Smrg err = device_data->vtable.QueueSubmit(queue, 0, NULL, queue_data->queries_fence); 1617b8e80941Smrg check_vk_result(err); 1618b8e80941Smrg err = device_data->vtable.WaitForFences(device_data->device, 1619b8e80941Smrg 1, &queue_data->queries_fence, 1620b8e80941Smrg VK_FALSE, UINT64_MAX); 1621b8e80941Smrg check_vk_result(err); 1622b8e80941Smrg 1623b8e80941Smrg /* Now get the results. */ 1624b8e80941Smrg list_for_each_entry_safe(struct command_buffer_data, cmd_buffer_data, 1625b8e80941Smrg &queue_data->running_command_buffer, link) { 1626b8e80941Smrg list_delinit(&cmd_buffer_data->link); 1627b8e80941Smrg 1628b8e80941Smrg if (cmd_buffer_data->pipeline_query_pool) { 1629b8e80941Smrg memset(query_results, 0, sizeof(query_results)); 1630b8e80941Smrg err = 1631b8e80941Smrg device_data->vtable.GetQueryPoolResults(device_data->device, 1632b8e80941Smrg cmd_buffer_data->pipeline_query_pool, 1633b8e80941Smrg cmd_buffer_data->query_index, 1, 1634b8e80941Smrg sizeof(uint32_t) * OVERLAY_QUERY_COUNT, 1635b8e80941Smrg query_results, 0, VK_QUERY_RESULT_WAIT_BIT); 1636b8e80941Smrg check_vk_result(err); 1637b8e80941Smrg 1638b8e80941Smrg for (uint32_t i = OVERLAY_PARAM_ENABLED_vertices; 1639b8e80941Smrg i <= OVERLAY_PARAM_ENABLED_compute_invocations; i++) { 1640b8e80941Smrg device_data->frame_stats.stats[i] += query_results[i - OVERLAY_PARAM_ENABLED_vertices]; 1641b8e80941Smrg } 1642b8e80941Smrg } 1643b8e80941Smrg if (cmd_buffer_data->timestamp_query_pool) { 1644b8e80941Smrg uint64_t gpu_timestamps[2] = { 0 }; 1645b8e80941Smrg err = 1646b8e80941Smrg device_data->vtable.GetQueryPoolResults(device_data->device, 1647b8e80941Smrg cmd_buffer_data->timestamp_query_pool, 1648b8e80941Smrg cmd_buffer_data->query_index * 2, 2, 1649b8e80941Smrg 2 * sizeof(uint64_t), gpu_timestamps, sizeof(uint64_t), 1650b8e80941Smrg VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT); 1651b8e80941Smrg check_vk_result(err); 1652b8e80941Smrg 1653b8e80941Smrg gpu_timestamps[0] &= queue_data->timestamp_mask; 1654b8e80941Smrg gpu_timestamps[1] &= queue_data->timestamp_mask; 1655b8e80941Smrg device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_gpu_timing] += 1656b8e80941Smrg (gpu_timestamps[1] - gpu_timestamps[0]) * 1657b8e80941Smrg device_data->properties.limits.timestampPeriod; 1658b8e80941Smrg } 1659b8e80941Smrg } 1660b8e80941Smrg } 1661b8e80941Smrg 1662b8e80941Smrg /* Otherwise we need to add our overlay drawing semaphore to the list of 1663b8e80941Smrg * semaphores to wait on. If we don't do that the presented picture might 1664b8e80941Smrg * be have incomplete overlay drawings. 1665b8e80941Smrg */ 1666b8e80941Smrg VkResult result = VK_SUCCESS; 1667b8e80941Smrg if (instance_data->params.no_display) { 1668b8e80941Smrg for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 1669b8e80941Smrg VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; 1670b8e80941Smrg struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(swapchain); 1671b8e80941Smrg 1672b8e80941Smrg before_present(swapchain_data, 1673b8e80941Smrg queue_data, 1674b8e80941Smrg pPresentInfo->pWaitSemaphores, 1675b8e80941Smrg pPresentInfo->waitSemaphoreCount, 1676b8e80941Smrg pPresentInfo->pImageIndices[i]); 1677b8e80941Smrg } 1678b8e80941Smrg result = queue_data->device->vtable.QueuePresentKHR(queue, pPresentInfo); 1679b8e80941Smrg } else { 1680b8e80941Smrg for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 1681b8e80941Smrg VkSwapchainKHR swapchain = pPresentInfo->pSwapchains[i]; 1682b8e80941Smrg struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(swapchain); 1683b8e80941Smrg VkPresentInfoKHR present_info = *pPresentInfo; 1684b8e80941Smrg present_info.swapchainCount = 1; 1685b8e80941Smrg present_info.pSwapchains = &swapchain; 1686b8e80941Smrg 1687b8e80941Smrg uint32_t image_index = pPresentInfo->pImageIndices[i]; 1688b8e80941Smrg 1689b8e80941Smrg struct overlay_draw *draw = before_present(swapchain_data, 1690b8e80941Smrg queue_data, 1691b8e80941Smrg pPresentInfo->pWaitSemaphores, 1692b8e80941Smrg pPresentInfo->waitSemaphoreCount, 1693b8e80941Smrg image_index); 1694b8e80941Smrg 1695b8e80941Smrg /* Because the submission of the overlay draw waits on the semaphores 1696b8e80941Smrg * handed for present, we don't need to have this present operation 1697b8e80941Smrg * wait on them as well, we can just wait on the overlay submission 1698b8e80941Smrg * semaphore. 1699b8e80941Smrg */ 1700b8e80941Smrg present_info.pWaitSemaphores = &draw->semaphore; 1701b8e80941Smrg present_info.waitSemaphoreCount = 1; 1702b8e80941Smrg 1703b8e80941Smrg VkResult chain_result = queue_data->device->vtable.QueuePresentKHR(queue, &present_info); 1704b8e80941Smrg if (pPresentInfo->pResults) 1705b8e80941Smrg pPresentInfo->pResults[i] = chain_result; 1706b8e80941Smrg if (chain_result != VK_SUCCESS && result == VK_SUCCESS) 1707b8e80941Smrg result = chain_result; 1708b8e80941Smrg } 1709b8e80941Smrg } 1710b8e80941Smrg return result; 1711b8e80941Smrg} 1712b8e80941Smrg 1713b8e80941Smrgstatic VkResult overlay_AcquireNextImageKHR( 1714b8e80941Smrg VkDevice device, 1715b8e80941Smrg VkSwapchainKHR swapchain, 1716b8e80941Smrg uint64_t timeout, 1717b8e80941Smrg VkSemaphore semaphore, 1718b8e80941Smrg VkFence fence, 1719b8e80941Smrg uint32_t* pImageIndex) 1720b8e80941Smrg{ 1721b8e80941Smrg struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(swapchain); 1722b8e80941Smrg struct device_data *device_data = swapchain_data->device; 1723b8e80941Smrg 1724b8e80941Smrg uint64_t ts0 = os_time_get(); 1725b8e80941Smrg VkResult result = device_data->vtable.AcquireNextImageKHR(device, swapchain, timeout, 1726b8e80941Smrg semaphore, fence, pImageIndex); 1727b8e80941Smrg uint64_t ts1 = os_time_get(); 1728b8e80941Smrg 1729b8e80941Smrg swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire_timing] += ts1 - ts0; 1730b8e80941Smrg swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire]++; 1731b8e80941Smrg 1732b8e80941Smrg return result; 1733b8e80941Smrg} 1734b8e80941Smrg 1735b8e80941Smrgstatic VkResult overlay_AcquireNextImage2KHR( 1736b8e80941Smrg VkDevice device, 1737b8e80941Smrg const VkAcquireNextImageInfoKHR* pAcquireInfo, 1738b8e80941Smrg uint32_t* pImageIndex) 1739b8e80941Smrg{ 1740b8e80941Smrg struct swapchain_data *swapchain_data = FIND_SWAPCHAIN_DATA(pAcquireInfo->swapchain); 1741b8e80941Smrg struct device_data *device_data = swapchain_data->device; 1742b8e80941Smrg 1743b8e80941Smrg uint64_t ts0 = os_time_get(); 1744b8e80941Smrg VkResult result = device_data->vtable.AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex); 1745b8e80941Smrg uint64_t ts1 = os_time_get(); 1746b8e80941Smrg 1747b8e80941Smrg swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire_timing] += ts1 - ts0; 1748b8e80941Smrg swapchain_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_acquire]++; 1749b8e80941Smrg 1750b8e80941Smrg return result; 1751b8e80941Smrg} 1752b8e80941Smrg 1753b8e80941Smrgstatic void overlay_CmdDraw( 1754b8e80941Smrg VkCommandBuffer commandBuffer, 1755b8e80941Smrg uint32_t vertexCount, 1756b8e80941Smrg uint32_t instanceCount, 1757b8e80941Smrg uint32_t firstVertex, 1758b8e80941Smrg uint32_t firstInstance) 1759b8e80941Smrg{ 1760b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1761b8e80941Smrg cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw]++; 1762b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1763b8e80941Smrg device_data->vtable.CmdDraw(commandBuffer, vertexCount, instanceCount, 1764b8e80941Smrg firstVertex, firstInstance); 1765b8e80941Smrg} 1766b8e80941Smrg 1767b8e80941Smrgstatic void overlay_CmdDrawIndexed( 1768b8e80941Smrg VkCommandBuffer commandBuffer, 1769b8e80941Smrg uint32_t indexCount, 1770b8e80941Smrg uint32_t instanceCount, 1771b8e80941Smrg uint32_t firstIndex, 1772b8e80941Smrg int32_t vertexOffset, 1773b8e80941Smrg uint32_t firstInstance) 1774b8e80941Smrg{ 1775b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1776b8e80941Smrg cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed]++; 1777b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1778b8e80941Smrg device_data->vtable.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, 1779b8e80941Smrg firstIndex, vertexOffset, firstInstance); 1780b8e80941Smrg} 1781b8e80941Smrg 1782b8e80941Smrgstatic void overlay_CmdDrawIndirect( 1783b8e80941Smrg VkCommandBuffer commandBuffer, 1784b8e80941Smrg VkBuffer buffer, 1785b8e80941Smrg VkDeviceSize offset, 1786b8e80941Smrg uint32_t drawCount, 1787b8e80941Smrg uint32_t stride) 1788b8e80941Smrg{ 1789b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1790b8e80941Smrg cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indirect]++; 1791b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1792b8e80941Smrg device_data->vtable.CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride); 1793b8e80941Smrg} 1794b8e80941Smrg 1795b8e80941Smrgstatic void overlay_CmdDrawIndexedIndirect( 1796b8e80941Smrg VkCommandBuffer commandBuffer, 1797b8e80941Smrg VkBuffer buffer, 1798b8e80941Smrg VkDeviceSize offset, 1799b8e80941Smrg uint32_t drawCount, 1800b8e80941Smrg uint32_t stride) 1801b8e80941Smrg{ 1802b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1803b8e80941Smrg cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed_indirect]++; 1804b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1805b8e80941Smrg device_data->vtable.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride); 1806b8e80941Smrg} 1807b8e80941Smrg 1808b8e80941Smrgstatic void overlay_CmdDrawIndirectCountKHR( 1809b8e80941Smrg VkCommandBuffer commandBuffer, 1810b8e80941Smrg VkBuffer buffer, 1811b8e80941Smrg VkDeviceSize offset, 1812b8e80941Smrg VkBuffer countBuffer, 1813b8e80941Smrg VkDeviceSize countBufferOffset, 1814b8e80941Smrg uint32_t maxDrawCount, 1815b8e80941Smrg uint32_t stride) 1816b8e80941Smrg{ 1817b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1818b8e80941Smrg cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indirect_count]++; 1819b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1820b8e80941Smrg device_data->vtable.CmdDrawIndirectCountKHR(commandBuffer, buffer, offset, 1821b8e80941Smrg countBuffer, countBufferOffset, 1822b8e80941Smrg maxDrawCount, stride); 1823b8e80941Smrg} 1824b8e80941Smrg 1825b8e80941Smrgstatic void overlay_CmdDrawIndexedIndirectCountKHR( 1826b8e80941Smrg VkCommandBuffer commandBuffer, 1827b8e80941Smrg VkBuffer buffer, 1828b8e80941Smrg VkDeviceSize offset, 1829b8e80941Smrg VkBuffer countBuffer, 1830b8e80941Smrg VkDeviceSize countBufferOffset, 1831b8e80941Smrg uint32_t maxDrawCount, 1832b8e80941Smrg uint32_t stride) 1833b8e80941Smrg{ 1834b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1835b8e80941Smrg cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed_indirect_count]++; 1836b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1837b8e80941Smrg device_data->vtable.CmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, 1838b8e80941Smrg countBuffer, countBufferOffset, 1839b8e80941Smrg maxDrawCount, stride); 1840b8e80941Smrg} 1841b8e80941Smrg 1842b8e80941Smrgstatic void overlay_CmdDispatch( 1843b8e80941Smrg VkCommandBuffer commandBuffer, 1844b8e80941Smrg uint32_t groupCountX, 1845b8e80941Smrg uint32_t groupCountY, 1846b8e80941Smrg uint32_t groupCountZ) 1847b8e80941Smrg{ 1848b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1849b8e80941Smrg cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_dispatch]++; 1850b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1851b8e80941Smrg device_data->vtable.CmdDispatch(commandBuffer, groupCountX, groupCountY, groupCountZ); 1852b8e80941Smrg} 1853b8e80941Smrg 1854b8e80941Smrgstatic void overlay_CmdDispatchIndirect( 1855b8e80941Smrg VkCommandBuffer commandBuffer, 1856b8e80941Smrg VkBuffer buffer, 1857b8e80941Smrg VkDeviceSize offset) 1858b8e80941Smrg{ 1859b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1860b8e80941Smrg cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_dispatch_indirect]++; 1861b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1862b8e80941Smrg device_data->vtable.CmdDispatchIndirect(commandBuffer, buffer, offset); 1863b8e80941Smrg} 1864b8e80941Smrg 1865b8e80941Smrgstatic void overlay_CmdBindPipeline( 1866b8e80941Smrg VkCommandBuffer commandBuffer, 1867b8e80941Smrg VkPipelineBindPoint pipelineBindPoint, 1868b8e80941Smrg VkPipeline pipeline) 1869b8e80941Smrg{ 1870b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1871b8e80941Smrg switch (pipelineBindPoint) { 1872b8e80941Smrg case VK_PIPELINE_BIND_POINT_GRAPHICS: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_graphics]++; break; 1873b8e80941Smrg case VK_PIPELINE_BIND_POINT_COMPUTE: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_compute]++; break; 1874b8e80941Smrg case VK_PIPELINE_BIND_POINT_RAY_TRACING_NV: cmd_buffer_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_raytracing]++; break; 1875b8e80941Smrg default: break; 1876b8e80941Smrg } 1877b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1878b8e80941Smrg device_data->vtable.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 1879b8e80941Smrg} 1880b8e80941Smrg 1881b8e80941Smrgstatic VkResult overlay_BeginCommandBuffer( 1882b8e80941Smrg VkCommandBuffer commandBuffer, 1883b8e80941Smrg const VkCommandBufferBeginInfo* pBeginInfo) 1884b8e80941Smrg{ 1885b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1886b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1887b8e80941Smrg 1888b8e80941Smrg memset(&cmd_buffer_data->stats, 0, sizeof(cmd_buffer_data->stats)); 1889b8e80941Smrg 1890b8e80941Smrg /* We don't record any query in secondary command buffers, just make sure 1891b8e80941Smrg * we have the right inheritance. 1892b8e80941Smrg */ 1893b8e80941Smrg if (cmd_buffer_data->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) { 1894b8e80941Smrg VkCommandBufferBeginInfo *begin_info = (VkCommandBufferBeginInfo *) 1895b8e80941Smrg clone_chain((const struct VkBaseInStructure *)pBeginInfo); 1896b8e80941Smrg VkCommandBufferInheritanceInfo *parent_inhe_info = (VkCommandBufferInheritanceInfo *) 1897b8e80941Smrg vk_find_struct(begin_info, COMMAND_BUFFER_INHERITANCE_INFO); 1898b8e80941Smrg VkCommandBufferInheritanceInfo inhe_info = { 1899b8e80941Smrg VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 1900b8e80941Smrg NULL, 1901b8e80941Smrg VK_NULL_HANDLE, 1902b8e80941Smrg 0, 1903b8e80941Smrg VK_NULL_HANDLE, 1904b8e80941Smrg VK_FALSE, 1905b8e80941Smrg 0, 1906b8e80941Smrg overlay_query_flags, 1907b8e80941Smrg }; 1908b8e80941Smrg 1909b8e80941Smrg if (parent_inhe_info) 1910b8e80941Smrg parent_inhe_info->pipelineStatistics = overlay_query_flags; 1911b8e80941Smrg else { 1912b8e80941Smrg inhe_info.pNext = begin_info->pNext; 1913b8e80941Smrg begin_info->pNext = &inhe_info; 1914b8e80941Smrg } 1915b8e80941Smrg 1916b8e80941Smrg VkResult result = device_data->vtable.BeginCommandBuffer(commandBuffer, pBeginInfo); 1917b8e80941Smrg 1918b8e80941Smrg if (!parent_inhe_info) 1919b8e80941Smrg begin_info->pNext = inhe_info.pNext; 1920b8e80941Smrg 1921b8e80941Smrg free_chain((struct VkBaseOutStructure *)begin_info); 1922b8e80941Smrg 1923b8e80941Smrg return result; 1924b8e80941Smrg } 1925b8e80941Smrg 1926b8e80941Smrg /* Otherwise record a begin query as first command. */ 1927b8e80941Smrg VkResult result = device_data->vtable.BeginCommandBuffer(commandBuffer, pBeginInfo); 1928b8e80941Smrg 1929b8e80941Smrg if (result == VK_SUCCESS) { 1930b8e80941Smrg if (cmd_buffer_data->pipeline_query_pool) { 1931b8e80941Smrg device_data->vtable.CmdResetQueryPool(commandBuffer, 1932b8e80941Smrg cmd_buffer_data->pipeline_query_pool, 1933b8e80941Smrg cmd_buffer_data->query_index, 1); 1934b8e80941Smrg } 1935b8e80941Smrg if (cmd_buffer_data->timestamp_query_pool) { 1936b8e80941Smrg device_data->vtable.CmdResetQueryPool(commandBuffer, 1937b8e80941Smrg cmd_buffer_data->timestamp_query_pool, 1938b8e80941Smrg cmd_buffer_data->query_index * 2, 2); 1939b8e80941Smrg } 1940b8e80941Smrg if (cmd_buffer_data->pipeline_query_pool) { 1941b8e80941Smrg device_data->vtable.CmdBeginQuery(commandBuffer, 1942b8e80941Smrg cmd_buffer_data->pipeline_query_pool, 1943b8e80941Smrg cmd_buffer_data->query_index, 0); 1944b8e80941Smrg } 1945b8e80941Smrg if (cmd_buffer_data->timestamp_query_pool) { 1946b8e80941Smrg device_data->vtable.CmdWriteTimestamp(commandBuffer, 1947b8e80941Smrg VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 1948b8e80941Smrg cmd_buffer_data->timestamp_query_pool, 1949b8e80941Smrg cmd_buffer_data->query_index * 2); 1950b8e80941Smrg } 1951b8e80941Smrg } 1952b8e80941Smrg 1953b8e80941Smrg return result; 1954b8e80941Smrg} 1955b8e80941Smrg 1956b8e80941Smrgstatic VkResult overlay_EndCommandBuffer( 1957b8e80941Smrg VkCommandBuffer commandBuffer) 1958b8e80941Smrg{ 1959b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1960b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1961b8e80941Smrg 1962b8e80941Smrg if (cmd_buffer_data->timestamp_query_pool) { 1963b8e80941Smrg device_data->vtable.CmdWriteTimestamp(commandBuffer, 1964b8e80941Smrg VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 1965b8e80941Smrg cmd_buffer_data->timestamp_query_pool, 1966b8e80941Smrg cmd_buffer_data->query_index * 2 + 1); 1967b8e80941Smrg } 1968b8e80941Smrg if (cmd_buffer_data->pipeline_query_pool) { 1969b8e80941Smrg device_data->vtable.CmdEndQuery(commandBuffer, 1970b8e80941Smrg cmd_buffer_data->pipeline_query_pool, 1971b8e80941Smrg cmd_buffer_data->query_index); 1972b8e80941Smrg } 1973b8e80941Smrg 1974b8e80941Smrg return device_data->vtable.EndCommandBuffer(commandBuffer); 1975b8e80941Smrg} 1976b8e80941Smrg 1977b8e80941Smrgstatic VkResult overlay_ResetCommandBuffer( 1978b8e80941Smrg VkCommandBuffer commandBuffer, 1979b8e80941Smrg VkCommandBufferResetFlags flags) 1980b8e80941Smrg{ 1981b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1982b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1983b8e80941Smrg 1984b8e80941Smrg memset(&cmd_buffer_data->stats, 0, sizeof(cmd_buffer_data->stats)); 1985b8e80941Smrg 1986b8e80941Smrg return device_data->vtable.ResetCommandBuffer(commandBuffer, flags); 1987b8e80941Smrg} 1988b8e80941Smrg 1989b8e80941Smrgstatic void overlay_CmdExecuteCommands( 1990b8e80941Smrg VkCommandBuffer commandBuffer, 1991b8e80941Smrg uint32_t commandBufferCount, 1992b8e80941Smrg const VkCommandBuffer* pCommandBuffers) 1993b8e80941Smrg{ 1994b8e80941Smrg struct command_buffer_data *cmd_buffer_data = FIND_CMD_BUFFER_DATA(commandBuffer); 1995b8e80941Smrg struct device_data *device_data = cmd_buffer_data->device; 1996b8e80941Smrg 1997b8e80941Smrg /* Add the stats of the executed command buffers to the primary one. */ 1998b8e80941Smrg for (uint32_t c = 0; c < commandBufferCount; c++) { 1999b8e80941Smrg struct command_buffer_data *sec_cmd_buffer_data = FIND_CMD_BUFFER_DATA(pCommandBuffers[c]); 2000b8e80941Smrg 2001b8e80941Smrg for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) 2002b8e80941Smrg cmd_buffer_data->stats.stats[s] += sec_cmd_buffer_data->stats.stats[s]; 2003b8e80941Smrg } 2004b8e80941Smrg 2005b8e80941Smrg device_data->vtable.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers); 2006b8e80941Smrg} 2007b8e80941Smrg 2008b8e80941Smrgstatic VkResult overlay_AllocateCommandBuffers( 2009b8e80941Smrg VkDevice device, 2010b8e80941Smrg const VkCommandBufferAllocateInfo* pAllocateInfo, 2011b8e80941Smrg VkCommandBuffer* pCommandBuffers) 2012b8e80941Smrg{ 2013b8e80941Smrg struct device_data *device_data = FIND_DEVICE_DATA(device); 2014b8e80941Smrg VkResult result = 2015b8e80941Smrg device_data->vtable.AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers); 2016b8e80941Smrg if (result != VK_SUCCESS) 2017b8e80941Smrg return result; 2018b8e80941Smrg 2019b8e80941Smrg VkQueryPool pipeline_query_pool = VK_NULL_HANDLE; 2020b8e80941Smrg VkQueryPool timestamp_query_pool = VK_NULL_HANDLE; 2021b8e80941Smrg if (device_data->instance->pipeline_statistics_enabled && 2022b8e80941Smrg pAllocateInfo->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 2023b8e80941Smrg VkQueryPoolCreateInfo pool_info = { 2024b8e80941Smrg VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 2025b8e80941Smrg NULL, 2026b8e80941Smrg 0, 2027b8e80941Smrg VK_QUERY_TYPE_PIPELINE_STATISTICS, 2028b8e80941Smrg pAllocateInfo->commandBufferCount, 2029b8e80941Smrg overlay_query_flags, 2030b8e80941Smrg }; 2031b8e80941Smrg VkResult err = 2032b8e80941Smrg device_data->vtable.CreateQueryPool(device_data->device, &pool_info, 2033b8e80941Smrg NULL, &pipeline_query_pool); 2034b8e80941Smrg check_vk_result(err); 2035b8e80941Smrg } 2036b8e80941Smrg if (device_data->instance->params.enabled[OVERLAY_PARAM_ENABLED_gpu_timing]) { 2037b8e80941Smrg VkQueryPoolCreateInfo pool_info = { 2038b8e80941Smrg VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 2039b8e80941Smrg NULL, 2040b8e80941Smrg 0, 2041b8e80941Smrg VK_QUERY_TYPE_TIMESTAMP, 2042b8e80941Smrg pAllocateInfo->commandBufferCount * 2, 2043b8e80941Smrg 0, 2044b8e80941Smrg }; 2045b8e80941Smrg VkResult err = 2046b8e80941Smrg device_data->vtable.CreateQueryPool(device_data->device, &pool_info, 2047b8e80941Smrg NULL, ×tamp_query_pool); 2048b8e80941Smrg check_vk_result(err); 2049b8e80941Smrg } 2050b8e80941Smrg 2051b8e80941Smrg for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) { 2052b8e80941Smrg new_command_buffer_data(pCommandBuffers[i], pAllocateInfo->level, 2053b8e80941Smrg pipeline_query_pool, timestamp_query_pool, 2054b8e80941Smrg i, device_data); 2055b8e80941Smrg } 2056b8e80941Smrg 2057b8e80941Smrg if (pipeline_query_pool) 2058b8e80941Smrg map_object(HKEY(pipeline_query_pool), (void *)(uintptr_t) pAllocateInfo->commandBufferCount); 2059b8e80941Smrg if (timestamp_query_pool) 2060b8e80941Smrg map_object(HKEY(timestamp_query_pool), (void *)(uintptr_t) pAllocateInfo->commandBufferCount); 2061b8e80941Smrg 2062b8e80941Smrg return result; 2063b8e80941Smrg} 2064b8e80941Smrg 2065b8e80941Smrgstatic void overlay_FreeCommandBuffers( 2066b8e80941Smrg VkDevice device, 2067b8e80941Smrg VkCommandPool commandPool, 2068b8e80941Smrg uint32_t commandBufferCount, 2069b8e80941Smrg const VkCommandBuffer* pCommandBuffers) 2070b8e80941Smrg{ 2071b8e80941Smrg struct device_data *device_data = FIND_DEVICE_DATA(device); 2072b8e80941Smrg for (uint32_t i = 0; i < commandBufferCount; i++) { 2073b8e80941Smrg struct command_buffer_data *cmd_buffer_data = 2074b8e80941Smrg FIND_CMD_BUFFER_DATA(pCommandBuffers[i]); 2075b8e80941Smrg /* It is legal to free a NULL command buffer*/ 2076b8e80941Smrg if (!cmd_buffer_data) 2077b8e80941Smrg continue; 2078b8e80941Smrg 2079b8e80941Smrg uint64_t count = (uintptr_t)find_object_data(HKEY(cmd_buffer_data->pipeline_query_pool)); 2080b8e80941Smrg if (count == 1) { 2081b8e80941Smrg unmap_object(HKEY(cmd_buffer_data->pipeline_query_pool)); 2082b8e80941Smrg device_data->vtable.DestroyQueryPool(device_data->device, 2083b8e80941Smrg cmd_buffer_data->pipeline_query_pool, NULL); 2084b8e80941Smrg } else if (count != 0) { 2085b8e80941Smrg map_object(HKEY(cmd_buffer_data->pipeline_query_pool), (void *)(uintptr_t)(count - 1)); 2086b8e80941Smrg } 2087b8e80941Smrg count = (uintptr_t)find_object_data(HKEY(cmd_buffer_data->timestamp_query_pool)); 2088b8e80941Smrg if (count == 1) { 2089b8e80941Smrg unmap_object(HKEY(cmd_buffer_data->timestamp_query_pool)); 2090b8e80941Smrg device_data->vtable.DestroyQueryPool(device_data->device, 2091b8e80941Smrg cmd_buffer_data->timestamp_query_pool, NULL); 2092b8e80941Smrg } else if (count != 0) { 2093b8e80941Smrg map_object(HKEY(cmd_buffer_data->timestamp_query_pool), (void *)(uintptr_t)(count - 1)); 2094b8e80941Smrg } 2095b8e80941Smrg destroy_command_buffer_data(cmd_buffer_data); 2096b8e80941Smrg } 2097b8e80941Smrg 2098b8e80941Smrg device_data->vtable.FreeCommandBuffers(device, commandPool, 2099b8e80941Smrg commandBufferCount, pCommandBuffers); 2100b8e80941Smrg} 2101b8e80941Smrg 2102b8e80941Smrgstatic VkResult overlay_QueueSubmit( 2103b8e80941Smrg VkQueue queue, 2104b8e80941Smrg uint32_t submitCount, 2105b8e80941Smrg const VkSubmitInfo* pSubmits, 2106b8e80941Smrg VkFence fence) 2107b8e80941Smrg{ 2108b8e80941Smrg struct queue_data *queue_data = FIND_QUEUE_DATA(queue); 2109b8e80941Smrg struct device_data *device_data = queue_data->device; 2110b8e80941Smrg 2111b8e80941Smrg device_data->frame_stats.stats[OVERLAY_PARAM_ENABLED_submit]++; 2112b8e80941Smrg 2113b8e80941Smrg for (uint32_t s = 0; s < submitCount; s++) { 2114b8e80941Smrg for (uint32_t c = 0; c < pSubmits[s].commandBufferCount; c++) { 2115b8e80941Smrg struct command_buffer_data *cmd_buffer_data = 2116b8e80941Smrg FIND_CMD_BUFFER_DATA(pSubmits[s].pCommandBuffers[c]); 2117b8e80941Smrg 2118b8e80941Smrg /* Merge the submitted command buffer stats into the device. */ 2119b8e80941Smrg for (uint32_t st = 0; st < OVERLAY_PARAM_ENABLED_MAX; st++) 2120b8e80941Smrg device_data->frame_stats.stats[st] += cmd_buffer_data->stats.stats[st]; 2121b8e80941Smrg 2122b8e80941Smrg /* Attach the command buffer to the queue so we remember to read its 2123b8e80941Smrg * pipeline statistics & timestamps at QueuePresent(). 2124b8e80941Smrg */ 2125b8e80941Smrg if (!cmd_buffer_data->pipeline_query_pool && 2126b8e80941Smrg !cmd_buffer_data->timestamp_query_pool) 2127b8e80941Smrg continue; 2128b8e80941Smrg 2129b8e80941Smrg if (list_empty(&cmd_buffer_data->link)) { 2130b8e80941Smrg list_addtail(&cmd_buffer_data->link, 2131b8e80941Smrg &queue_data->running_command_buffer); 2132b8e80941Smrg } else { 2133b8e80941Smrg fprintf(stderr, "Command buffer submitted multiple times before present.\n" 2134b8e80941Smrg "This could lead to invalid data.\n"); 2135b8e80941Smrg } 2136b8e80941Smrg } 2137b8e80941Smrg } 2138b8e80941Smrg 2139b8e80941Smrg return device_data->vtable.QueueSubmit(queue, submitCount, pSubmits, fence); 2140b8e80941Smrg} 2141b8e80941Smrg 2142b8e80941Smrgstatic VkResult overlay_CreateDevice( 2143b8e80941Smrg VkPhysicalDevice physicalDevice, 2144b8e80941Smrg const VkDeviceCreateInfo* pCreateInfo, 2145b8e80941Smrg const VkAllocationCallbacks* pAllocator, 2146b8e80941Smrg VkDevice* pDevice) 2147b8e80941Smrg{ 2148b8e80941Smrg struct instance_data *instance_data = FIND_PHYSICAL_DEVICE_DATA(physicalDevice); 2149b8e80941Smrg VkLayerDeviceCreateInfo *chain_info = 2150b8e80941Smrg get_device_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 2151b8e80941Smrg 2152b8e80941Smrg assert(chain_info->u.pLayerInfo); 2153b8e80941Smrg PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 2154b8e80941Smrg PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 2155b8e80941Smrg PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice"); 2156b8e80941Smrg if (fpCreateDevice == NULL) { 2157b8e80941Smrg return VK_ERROR_INITIALIZATION_FAILED; 2158b8e80941Smrg } 2159b8e80941Smrg 2160b8e80941Smrg // Advance the link info for the next element on the chain 2161b8e80941Smrg chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 2162b8e80941Smrg 2163b8e80941Smrg VkPhysicalDeviceFeatures device_features = {}; 2164b8e80941Smrg VkDeviceCreateInfo device_info = *pCreateInfo; 2165b8e80941Smrg 2166b8e80941Smrg if (pCreateInfo->pEnabledFeatures) 2167b8e80941Smrg device_features = *(pCreateInfo->pEnabledFeatures); 2168b8e80941Smrg if (instance_data->pipeline_statistics_enabled) { 2169b8e80941Smrg device_features.inheritedQueries = true; 2170b8e80941Smrg device_features.pipelineStatisticsQuery = true; 2171b8e80941Smrg } 2172b8e80941Smrg device_info.pEnabledFeatures = &device_features; 2173b8e80941Smrg 2174b8e80941Smrg 2175b8e80941Smrg VkResult result = fpCreateDevice(physicalDevice, &device_info, pAllocator, pDevice); 2176b8e80941Smrg if (result != VK_SUCCESS) return result; 2177b8e80941Smrg 2178b8e80941Smrg struct device_data *device_data = new_device_data(*pDevice, instance_data); 2179b8e80941Smrg device_data->physical_device = physicalDevice; 2180b8e80941Smrg vk_load_device_commands(*pDevice, fpGetDeviceProcAddr, &device_data->vtable); 2181b8e80941Smrg 2182b8e80941Smrg instance_data->vtable.GetPhysicalDeviceProperties(device_data->physical_device, 2183b8e80941Smrg &device_data->properties); 2184b8e80941Smrg 2185b8e80941Smrg VkLayerDeviceCreateInfo *load_data_info = 2186b8e80941Smrg get_device_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK); 2187b8e80941Smrg device_data->set_device_loader_data = load_data_info->u.pfnSetDeviceLoaderData; 2188b8e80941Smrg 2189b8e80941Smrg device_map_queues(device_data, pCreateInfo); 2190b8e80941Smrg 2191b8e80941Smrg return result; 2192b8e80941Smrg} 2193b8e80941Smrg 2194b8e80941Smrgstatic void overlay_DestroyDevice( 2195b8e80941Smrg VkDevice device, 2196b8e80941Smrg const VkAllocationCallbacks* pAllocator) 2197b8e80941Smrg{ 2198b8e80941Smrg struct device_data *device_data = FIND_DEVICE_DATA(device); 2199b8e80941Smrg device_unmap_queues(device_data); 2200b8e80941Smrg device_data->vtable.DestroyDevice(device, pAllocator); 2201b8e80941Smrg destroy_device_data(device_data); 2202b8e80941Smrg} 2203b8e80941Smrg 2204b8e80941Smrgstatic VkResult overlay_CreateInstance( 2205b8e80941Smrg const VkInstanceCreateInfo* pCreateInfo, 2206b8e80941Smrg const VkAllocationCallbacks* pAllocator, 2207b8e80941Smrg VkInstance* pInstance) 2208b8e80941Smrg{ 2209b8e80941Smrg VkLayerInstanceCreateInfo *chain_info = 2210b8e80941Smrg get_instance_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 2211b8e80941Smrg 2212b8e80941Smrg assert(chain_info->u.pLayerInfo); 2213b8e80941Smrg PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = 2214b8e80941Smrg chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 2215b8e80941Smrg PFN_vkCreateInstance fpCreateInstance = 2216b8e80941Smrg (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 2217b8e80941Smrg if (fpCreateInstance == NULL) { 2218b8e80941Smrg return VK_ERROR_INITIALIZATION_FAILED; 2219b8e80941Smrg } 2220b8e80941Smrg 2221b8e80941Smrg // Advance the link info for the next element on the chain 2222b8e80941Smrg chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 2223b8e80941Smrg 2224b8e80941Smrg VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 2225b8e80941Smrg if (result != VK_SUCCESS) return result; 2226b8e80941Smrg 2227b8e80941Smrg struct instance_data *instance_data = new_instance_data(*pInstance); 2228b8e80941Smrg vk_load_instance_commands(instance_data->instance, 2229b8e80941Smrg fpGetInstanceProcAddr, 2230b8e80941Smrg &instance_data->vtable); 2231b8e80941Smrg instance_data_map_physical_devices(instance_data, true); 2232b8e80941Smrg 2233b8e80941Smrg parse_overlay_env(&instance_data->params, getenv("VK_LAYER_MESA_OVERLAY_CONFIG")); 2234b8e80941Smrg 2235b8e80941Smrg for (int i = OVERLAY_PARAM_ENABLED_vertices; 2236b8e80941Smrg i <= OVERLAY_PARAM_ENABLED_compute_invocations; i++) { 2237b8e80941Smrg if (instance_data->params.enabled[i]) { 2238b8e80941Smrg instance_data->pipeline_statistics_enabled = true; 2239b8e80941Smrg break; 2240b8e80941Smrg } 2241b8e80941Smrg } 2242b8e80941Smrg 2243b8e80941Smrg return result; 2244b8e80941Smrg} 2245b8e80941Smrg 2246b8e80941Smrgstatic void overlay_DestroyInstance( 2247b8e80941Smrg VkInstance instance, 2248b8e80941Smrg const VkAllocationCallbacks* pAllocator) 2249b8e80941Smrg{ 2250b8e80941Smrg struct instance_data *instance_data = FIND_INSTANCE_DATA(instance); 2251b8e80941Smrg instance_data_map_physical_devices(instance_data, false); 2252b8e80941Smrg instance_data->vtable.DestroyInstance(instance, pAllocator); 2253b8e80941Smrg destroy_instance_data(instance_data); 2254b8e80941Smrg} 2255b8e80941Smrg 2256b8e80941Smrgstatic const struct { 2257b8e80941Smrg const char *name; 2258b8e80941Smrg void *ptr; 2259b8e80941Smrg} name_to_funcptr_map[] = { 2260b8e80941Smrg { "vkGetDeviceProcAddr", (void *) vkGetDeviceProcAddr }, 2261b8e80941Smrg#define ADD_HOOK(fn) { "vk" # fn, (void *) overlay_ ## fn } 2262b8e80941Smrg ADD_HOOK(AllocateCommandBuffers), 2263b8e80941Smrg ADD_HOOK(FreeCommandBuffers), 2264b8e80941Smrg ADD_HOOK(ResetCommandBuffer), 2265b8e80941Smrg ADD_HOOK(BeginCommandBuffer), 2266b8e80941Smrg ADD_HOOK(EndCommandBuffer), 2267b8e80941Smrg ADD_HOOK(CmdExecuteCommands), 2268b8e80941Smrg 2269b8e80941Smrg ADD_HOOK(CmdDraw), 2270b8e80941Smrg ADD_HOOK(CmdDrawIndexed), 2271b8e80941Smrg ADD_HOOK(CmdDrawIndirect), 2272b8e80941Smrg ADD_HOOK(CmdDrawIndexedIndirect), 2273b8e80941Smrg ADD_HOOK(CmdDispatch), 2274b8e80941Smrg ADD_HOOK(CmdDispatchIndirect), 2275b8e80941Smrg ADD_HOOK(CmdDrawIndirectCountKHR), 2276b8e80941Smrg ADD_HOOK(CmdDrawIndexedIndirectCountKHR), 2277b8e80941Smrg 2278b8e80941Smrg ADD_HOOK(CmdBindPipeline), 2279b8e80941Smrg 2280b8e80941Smrg ADD_HOOK(CreateSwapchainKHR), 2281b8e80941Smrg ADD_HOOK(QueuePresentKHR), 2282b8e80941Smrg ADD_HOOK(DestroySwapchainKHR), 2283b8e80941Smrg ADD_HOOK(AcquireNextImageKHR), 2284b8e80941Smrg ADD_HOOK(AcquireNextImage2KHR), 2285b8e80941Smrg 2286b8e80941Smrg ADD_HOOK(QueueSubmit), 2287b8e80941Smrg 2288b8e80941Smrg ADD_HOOK(CreateDevice), 2289b8e80941Smrg ADD_HOOK(DestroyDevice), 2290b8e80941Smrg 2291b8e80941Smrg ADD_HOOK(CreateInstance), 2292b8e80941Smrg ADD_HOOK(DestroyInstance), 2293b8e80941Smrg#undef ADD_HOOK 2294b8e80941Smrg}; 2295b8e80941Smrg 2296b8e80941Smrgstatic void *find_ptr(const char *name) 2297b8e80941Smrg{ 2298b8e80941Smrg for (uint32_t i = 0; i < ARRAY_SIZE(name_to_funcptr_map); i++) { 2299b8e80941Smrg if (strcmp(name, name_to_funcptr_map[i].name) == 0) 2300b8e80941Smrg return name_to_funcptr_map[i].ptr; 2301b8e80941Smrg } 2302b8e80941Smrg 2303b8e80941Smrg return NULL; 2304b8e80941Smrg} 2305b8e80941Smrg 2306b8e80941SmrgVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, 2307b8e80941Smrg const char *funcName) 2308b8e80941Smrg{ 2309b8e80941Smrg void *ptr = find_ptr(funcName); 2310b8e80941Smrg if (ptr) return reinterpret_cast<PFN_vkVoidFunction>(ptr); 2311b8e80941Smrg 2312b8e80941Smrg if (dev == NULL) return NULL; 2313b8e80941Smrg 2314b8e80941Smrg struct device_data *device_data = FIND_DEVICE_DATA(dev); 2315b8e80941Smrg if (device_data->vtable.GetDeviceProcAddr == NULL) return NULL; 2316b8e80941Smrg return device_data->vtable.GetDeviceProcAddr(dev, funcName); 2317b8e80941Smrg} 2318b8e80941Smrg 2319b8e80941SmrgVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, 2320b8e80941Smrg const char *funcName) 2321b8e80941Smrg{ 2322b8e80941Smrg void *ptr = find_ptr(funcName); 2323b8e80941Smrg if (ptr) return reinterpret_cast<PFN_vkVoidFunction>(ptr); 2324b8e80941Smrg 2325b8e80941Smrg if (instance == NULL) return NULL; 2326b8e80941Smrg 2327b8e80941Smrg struct instance_data *instance_data = FIND_INSTANCE_DATA(instance); 2328b8e80941Smrg if (instance_data->vtable.GetInstanceProcAddr == NULL) return NULL; 2329b8e80941Smrg return instance_data->vtable.GetInstanceProcAddr(instance, funcName); 2330b8e80941Smrg} 2331