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