vulkan/overlay: check return value of swapchain get images
[mesa.git] / src / vulkan / overlay-layer / overlay.cpp
index 658feb66337b5f292ad0e27fc95bd2688f259444..edaad969e20e000ae264c474de80dd7f8e7550be 100644 (file)
 #include <assert.h>
 
 #include <vulkan/vulkan.h>
-#include <vulkan/vk_dispatch_table_helper.h>
 #include <vulkan/vk_layer.h>
-#include <vulkan/vk_layer_data.h>
-#include <vulkan/vk_layer_extension_utils.h>
-#include <vulkan/vk_loader_platform.h>
-#include "vk_layer_table.h"
 
 #include "imgui.h"
 
+#include "overlay_params.h"
+
 #include "util/debug.h"
 #include "util/hash_table.h"
 #include "util/ralloc.h"
 #include "util/simple_mtx.h"
 
 #include "vk_enum_to_str.h"
-
-enum layer_position {
-   LAYER_POSITION_TOP_LEFT,
-   LAYER_POSITION_TOP_RIGHT,
-   LAYER_POSITION_BOTTOM_LEFT,
-   LAYER_POSITION_BOTTOM_RIGHT,
-};
-
-static enum layer_position
-parse_layer_position(const char *str)
-{
-   if (!str || !strcmp(str, "top-left"))
-      return LAYER_POSITION_TOP_LEFT;
-   if (!strcmp(str, "top-right"))
-      return LAYER_POSITION_TOP_RIGHT;
-   if (!strcmp(str, "bottom-left"))
-      return LAYER_POSITION_BOTTOM_LEFT;
-   if (!strcmp(str, "bottom-right"))
-      return LAYER_POSITION_BOTTOM_RIGHT;
-   return LAYER_POSITION_TOP_LEFT;
-}
+#include "vk_util.h"
 
 /* Mapped from VkInstace/VkPhysicalDevice */
 struct instance_data {
-   VkLayerInstanceDispatchTable vtable;
+   struct vk_instance_dispatch_table vtable;
    VkInstance instance;
 
-   enum layer_position position;
-   uint64_t enabled_stats;
-};
-
-enum frame_stat_type {
-   FRAME_STAT_SUBMIT,
-   FRAME_STAT_DRAW,
-   FRAME_STAT_DRAW_INDEXED,
-   FRAME_STAT_DRAW_INDIRECT,
-   FRAME_STAT_DRAW_INDEXED_INDIRECT,
-   FRAME_STAT_DRAW_INDIRECT_COUNT,
-   FRAME_STAT_DRAW_INDEXED_INDIRECT_COUNT,
-   FRAME_STAT_DISPATCH,
-   FRAME_STAT_DISPATCH_INDIRECT,
-   FRAME_STAT_PIPELINE_GRAPHICS,
-   FRAME_STAT_PIPELINE_COMPUTE,
-   FRAME_STAT_PIPELINE_RAYTRACING,
-
-   FRAME_STAT_COUNT,
-
-   FRAME_STAT_ACQUIRE_TIMING = FRAME_STAT_COUNT,
-   FRAME_STAT_HELP,
-};
-
-#define FRAME_STAT_ENABLED(id) (1ULL << (FRAME_STAT_ ## id))
-
-static struct debug_control enable_flags[] = {
-   { "submit",                      FRAME_STAT_ENABLED(SUBMIT) },
-   { "draw",                        FRAME_STAT_ENABLED(DRAW) },
-   { "draw-indexed",                FRAME_STAT_ENABLED(DRAW_INDEXED) },
-   { "draw-indirect",               FRAME_STAT_ENABLED(DRAW_INDIRECT) },
-   { "draw-indexed-indirect",       FRAME_STAT_ENABLED(DRAW_INDEXED_INDIRECT) },
-   { "draw-indirect-count",         FRAME_STAT_ENABLED(DRAW_INDIRECT_COUNT) },
-   { "draw-indexed-indirect-count", FRAME_STAT_ENABLED(DRAW_INDEXED_INDIRECT_COUNT) },
-   { "dispatch",                    FRAME_STAT_ENABLED(DISPATCH) },
-   { "dispatch-indirect",           FRAME_STAT_ENABLED(DISPATCH_INDIRECT) },
-   { "pipeline-graphics",           FRAME_STAT_ENABLED(PIPELINE_GRAPHICS) },
-   { "pipeline-compute",            FRAME_STAT_ENABLED(PIPELINE_COMPUTE) },
-   { "pipeline-raytracing",         FRAME_STAT_ENABLED(PIPELINE_RAYTRACING) },
-   { "acquire-timing",              FRAME_STAT_ENABLED(ACQUIRE_TIMING) },
-   { "help",                        FRAME_STAT_ENABLED(HELP) },
-   { NULL,                          0 },
+   struct overlay_params params;
 };
 
 struct frame_stat {
-   uint32_t stats[FRAME_STAT_COUNT];
+   uint32_t stats[OVERLAY_PARAM_ENABLED_MAX];
 };
 
 /* Mapped from VkDevice/VkCommandBuffer */
@@ -122,7 +58,9 @@ struct queue_data;
 struct device_data {
    struct instance_data *instance;
 
-   VkLayerDispatchTable vtable;
+   PFN_vkSetDeviceLoaderData set_device_loader_data;
+
+   struct vk_device_dispatch_table vtable;
    VkPhysicalDevice physical_device;
    VkDevice device;
 
@@ -210,7 +148,7 @@ struct swapchain_data {
    double acquire_times[200];
    uint64_t n_acquire;
 
-   enum frame_stat_type stat_selector;
+   enum overlay_param_enabled stat_selector;
    struct frame_stat stats_min, stats_max;
    struct frame_stat stats[200];
 };
@@ -261,6 +199,41 @@ static void unmap_object(void *obj)
 }
 
 /**/
+
+static void check_vk_result(VkResult err)
+{
+   if (err != VK_SUCCESS)
+      printf("ERROR!\n");
+}
+
+/**/
+
+static VkLayerInstanceCreateInfo *get_instance_chain_info(const VkInstanceCreateInfo *pCreateInfo,
+                                                          VkLayerFunction func)
+{
+   vk_foreach_struct(item, pCreateInfo->pNext) {
+      if (item->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO &&
+          ((VkLayerInstanceCreateInfo *) item)->function == func)
+         return (VkLayerInstanceCreateInfo *) item;
+   }
+   unreachable("instance chain info not found");
+   return NULL;
+}
+
+static VkLayerDeviceCreateInfo *get_device_chain_info(const VkDeviceCreateInfo *pCreateInfo,
+                                                      VkLayerFunction func)
+{
+   vk_foreach_struct(item, pCreateInfo->pNext) {
+      if (item->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO &&
+          ((VkLayerDeviceCreateInfo *) item)->function == func)
+         return (VkLayerDeviceCreateInfo *)item;
+   }
+   unreachable("device chain info not found");
+   return NULL;
+}
+
+/**/
+
 static struct instance_data *new_instance_data(VkInstance instance)
 {
    struct instance_data *data = rzalloc(NULL, struct instance_data);
@@ -271,6 +244,8 @@ static struct instance_data *new_instance_data(VkInstance instance)
 
 static void destroy_instance_data(struct instance_data *data)
 {
+   if (data->params.output_file)
+      fclose(data->params.output_file);
    unmap_object(data->instance);
    ralloc_free(data);
 }
@@ -351,6 +326,10 @@ static void device_map_queues(struct device_data *data,
          data->vtable.GetDeviceQueue(data->device,
                                      pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex,
                                      j, &queue);
+
+         VkResult err = data->set_device_loader_data(data->device, queue);
+         check_vk_result(err);
+
          data->queues[queue_index++] =
             new_queue_data(queue, &family_props[pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex],
                            pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, data);
@@ -372,12 +351,6 @@ static void destroy_device_data(struct device_data *data)
    ralloc_free(data);
 }
 
-static void check_vk_result(VkResult err)
-{
-   if (err != VK_SUCCESS)
-      printf("ERROR!\n");
-}
-
 /**/
 static struct swapchain_data *new_swapchain_data(VkSwapchainKHR swapchain,
                                                  struct device_data *device_data)
@@ -398,7 +371,8 @@ static void destroy_swapchain_data(struct swapchain_data *data)
 
 static void snapshot_swapchain_frame(struct swapchain_data *data)
 {
-   uint64_t now = os_time_get();
+   struct instance_data *instance_data = data->device->instance;
+   uint64_t now = os_time_get(); /* us */
 
    if (data->last_present_time) {
       data->frame_times[(data->n_frames - 1) % ARRAY_SIZE(data->frame_times)] =
@@ -406,11 +380,15 @@ static void snapshot_swapchain_frame(struct swapchain_data *data)
    }
 
    if (data->last_fps_update) {
-      double elapsed = (double)(now - data->last_fps_update);
-      if (elapsed >= 500000.0) {
-         data->fps = ((uint64_t)data->n_frames_since_update * 1000000 / elapsed);
+      double elapsed = (double)(now - data->last_fps_update); /* us */
+      if (elapsed >= instance_data->params.fps_sampling_period) {
+         data->fps = 1000000.0f * data->n_frames_since_update / elapsed;
          data->n_frames_since_update = 0;
          data->last_fps_update = now;
+         if (instance_data->params.output_file) {
+            fprintf(instance_data->params.output_file, "%.2f\n", data->fps);
+            fflush(instance_data->params.output_file);
+         }
       }
    } else {
       data->last_fps_update = now;
@@ -472,7 +450,7 @@ static void position_layer(struct swapchain_data *data)
 
    ImGui::SetNextWindowBgAlpha(0.5);
    ImGui::SetNextWindowSize(data->window_size, ImGuiCond_Always);
-   switch (instance_data->position) {
+   switch (instance_data->params.position) {
    case LAYER_POSITION_TOP_LEFT:
       ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
       break;
@@ -507,9 +485,10 @@ static void compute_swapchain_display(struct swapchain_data *data)
    format_name = format_name ? (format_name + strlen("VK_FORMAT_")) : "unknown";
    ImGui::Text("Swapchain format: %s", format_name);
    ImGui::Text("Frames: %" PRIu64, data->n_frames);
-   ImGui::Text("FPS: %.2f" , data->fps);
+   if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_fps])
+      ImGui::Text("FPS: %.2f" , data->fps);
 
-   {
+   if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){
       double min_time = FLT_MAX, max_time = 0.0f;
       for (uint32_t i = 0; i < MIN2(data->n_frames - 2, ARRAY_SIZE(data->frame_times)); i++) {
          min_time = MIN2(min_time, data->frame_times[i]);
@@ -524,7 +503,7 @@ static void compute_swapchain_display(struct swapchain_data *data)
                   min_time, max_time);
    }
 
-   if (instance_data->enabled_stats & FRAME_STAT_ENABLED(ACQUIRE_TIMING)) {
+   if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_acquire_timing]) {
       double min_time = FLT_MAX, max_time = 0.0f;
       for (uint32_t i = 0; i < MIN2(data->n_acquire - 2, ARRAY_SIZE(data->acquire_times)); i++) {
          min_time = MIN2(min_time, data->acquire_times[i]);
@@ -553,12 +532,15 @@ static void compute_swapchain_display(struct swapchain_data *data)
    }
 
    for (uint32_t i = 0; i < ARRAY_SIZE(device_data->stats.stats); i++) {
-      if (!(instance_data->enabled_stats & (1ULL << i)))
+      if (!instance_data->params.enabled[i] ||
+          i == OVERLAY_PARAM_ENABLED_fps ||
+          i == OVERLAY_PARAM_ENABLED_frame_timing ||
+          i == OVERLAY_PARAM_ENABLED_acquire_timing)
          continue;
 
       char hash[40];
-      snprintf(hash, sizeof(hash), "##%s", enable_flags[i].string);
-      data->stat_selector = (enum frame_stat_type) i;
+      snprintf(hash, sizeof(hash), "##%s", overlay_param_names[i]);
+      data->stat_selector = (enum overlay_param_enabled) i;
 
       ImGui::PlotHistogram(hash, get_stat, data,
                            ARRAY_SIZE(data->stats), 0,
@@ -566,7 +548,7 @@ static void compute_swapchain_display(struct swapchain_data *data)
                            data->stats_min.stats[i],
                            data->stats_max.stats[i],
                            ImVec2(ImGui::GetContentRegionAvailWidth(), 30));
-      ImGui::Text("%s: %.0f [%u, %u]", enable_flags[i].string,
+      ImGui::Text("%s: %.0f [%u, %u]", overlay_param_names[i],
                   get_stat(data, ARRAY_SIZE(data->stats) - 1),
                   data->stats_min.stats[i], data->stats_max.stats[i]);
    }
@@ -771,8 +753,8 @@ static void render_swapchain_display(struct swapchain_data *data, unsigned image
    VkImageMemoryBarrier imb;
    imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    imb.pNext = nullptr;
-   imb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    imb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+   imb.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    imb.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
    imb.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    imb.image = data->images[image_index];
@@ -784,8 +766,8 @@ static void render_swapchain_display(struct swapchain_data *data, unsigned image
    imb.srcQueueFamilyIndex = device_data->graphic_queue->family_index;
    imb.dstQueueFamilyIndex = device_data->graphic_queue->family_index;
    device_data->vtable.CmdPipelineBarrier(command_buffer,
-                                          VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
-                                          VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                                          VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+                                          VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
                                           0,          /* dependency flags */
                                           0, nullptr, /* memory barriers */
                                           0, nullptr, /* buffer memory barriers */
@@ -930,9 +912,11 @@ static void render_swapchain_display(struct swapchain_data *data, unsigned image
    check_vk_result(err);
 
    VkSubmitInfo submit_info = {};
+   VkPipelineStageFlags stage_wait = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submit_info.commandBufferCount = 1;
    submit_info.pCommandBuffers = &command_buffer;
+   submit_info.pWaitDstStageMask = &stage_wait;
    submit_info.signalSemaphoreCount = 1;
    submit_info.pSignalSemaphores = &data->submission_semaphore;
 
@@ -1271,18 +1255,21 @@ static void setup_swapchain_data(struct swapchain_data *data,
 
    setup_swapchain_data_pipeline(data);
 
-   device_data->vtable.GetSwapchainImagesKHR(device_data->device,
-                                             data->swapchain,
-                                             &data->n_images,
-                                             NULL);
+   err = device_data->vtable.GetSwapchainImagesKHR(device_data->device,
+                                                   data->swapchain,
+                                                   &data->n_images,
+                                                   NULL);
+   check_vk_result(err);
+
    data->images = ralloc_array(data, VkImage, data->n_images);
    data->image_views = ralloc_array(data, VkImageView, data->n_images);
    data->framebuffers = ralloc_array(data, VkFramebuffer, data->n_images);
 
-   device_data->vtable.GetSwapchainImagesKHR(device_data->device,
-                                             data->swapchain,
-                                             &data->n_images,
-                                             data->images);
+   err = device_data->vtable.GetSwapchainImagesKHR(device_data->device,
+                                                   data->swapchain,
+                                                   &data->n_images,
+                                                   data->images);
+   check_vk_result(err);
 
    /* Image views */
    VkImageViewCreateInfo view_info = {};
@@ -1340,9 +1327,13 @@ static void setup_swapchain_data(struct swapchain_data *data,
                                                     cmd_bufs);
    check_vk_result(err);
 
-   for (uint32_t i = 0; i < ARRAY_SIZE(data->frame_data); i++)
-      data->frame_data[i].command_buffer = cmd_bufs[i];
+   for (uint32_t i = 0; i < ARRAY_SIZE(data->frame_data); i++) {
+      err = device_data->set_device_loader_data(device_data->device,
+                                                cmd_bufs[i]);
+      check_vk_result(err);
 
+      data->frame_data[i].command_buffer = cmd_bufs[i];
+   }
 
    /* Submission fence */
    VkFenceCreateInfo fence_info = {};
@@ -1351,7 +1342,6 @@ static void setup_swapchain_data(struct swapchain_data *data,
    err = device_data->vtable.CreateFence(device_data->device, &fence_info,
                                          NULL, &data->fence);
    check_vk_result(err);
-
 }
 
 static void shutdown_swapchain_data(struct swapchain_data *data)
@@ -1387,8 +1377,6 @@ static void shutdown_swapchain_data(struct swapchain_data *data)
    device_data->vtable.DestroyPipeline(device_data->device, data->pipeline, NULL);
    device_data->vtable.DestroyPipelineLayout(device_data->device, data->pipeline_layout, NULL);
 
-   device_data->vtable.FreeDescriptorSets(device_data->device, data->descriptor_pool,
-                                          1, &data->descriptor_set);
    device_data->vtable.DestroyDescriptorPool(device_data->device,
                                              data->descriptor_pool, NULL);
    device_data->vtable.DestroyDescriptorSetLayout(device_data->device,
@@ -1534,7 +1522,7 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdDraw(
    struct device_data *device_data = FIND_DEVICE_DATA(commandBuffer);
    device_data->vtable.CmdDraw(commandBuffer, vertexCount, instanceCount,
                                firstVertex, firstInstance);
-   device_data->stats.stats[FRAME_STAT_DRAW]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_draw]++;
 }
 
 VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndexed(
@@ -1548,7 +1536,7 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndexed(
    struct device_data *device_data = FIND_DEVICE_DATA(commandBuffer);
    device_data->vtable.CmdDrawIndexed(commandBuffer, indexCount, instanceCount,
                                       firstIndex, vertexOffset, firstInstance);
-   device_data->stats.stats[FRAME_STAT_DRAW_INDEXED]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed]++;
 }
 
 VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndirect(
@@ -1560,7 +1548,7 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndirect(
 {
    struct device_data *device_data = FIND_DEVICE_DATA(commandBuffer);
    device_data->vtable.CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride);
-   device_data->stats.stats[FRAME_STAT_DRAW_INDIRECT]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indirect]++;
 }
 
 VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndexedIndirect(
@@ -1572,7 +1560,7 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndexedIndirect(
 {
    struct device_data *device_data = FIND_DEVICE_DATA(commandBuffer);
    device_data->vtable.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
-   device_data->stats.stats[FRAME_STAT_DRAW_INDEXED_INDIRECT]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed_indirect]++;
 }
 
 VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndirectCountKHR(
@@ -1588,7 +1576,7 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndirectCountKHR(
    device_data->vtable.CmdDrawIndirectCountKHR(commandBuffer, buffer, offset,
                                                countBuffer, countBufferOffset,
                                                maxDrawCount, stride);
-   device_data->stats.stats[FRAME_STAT_DRAW_INDIRECT_COUNT]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indirect_count]++;
 }
 
 VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndexedIndirectCountKHR(
@@ -1604,7 +1592,7 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdDrawIndexedIndirectCountKHR(
    device_data->vtable.CmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset,
                                                       countBuffer, countBufferOffset,
                                                       maxDrawCount, stride);
-   device_data->stats.stats[FRAME_STAT_DRAW_INDEXED_INDIRECT_COUNT]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_draw_indexed_indirect_count]++;
 }
 
 VKAPI_ATTR void VKAPI_CALL overlay_CmdDispatch(
@@ -1615,7 +1603,7 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdDispatch(
 {
    struct device_data *device_data = FIND_DEVICE_DATA(commandBuffer);
    device_data->vtable.CmdDispatch(commandBuffer, groupCountX, groupCountY, groupCountZ);
-   device_data->stats.stats[FRAME_STAT_DISPATCH]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_dispatch]++;
 }
 
 VKAPI_ATTR void VKAPI_CALL overlay_CmdDispatchIndirect(
@@ -1625,7 +1613,7 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdDispatchIndirect(
 {
    struct device_data *device_data = FIND_DEVICE_DATA(commandBuffer);
    device_data->vtable.CmdDispatchIndirect(commandBuffer, buffer, offset);
-   device_data->stats.stats[FRAME_STAT_DISPATCH_INDIRECT]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_dispatch_indirect]++;
 }
 
 VKAPI_ATTR void VKAPI_CALL overlay_CmdBindPipeline(
@@ -1636,9 +1624,9 @@ VKAPI_ATTR void VKAPI_CALL overlay_CmdBindPipeline(
    struct device_data *device_data = FIND_DEVICE_DATA(commandBuffer);
    device_data->vtable.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
    switch (pipelineBindPoint) {
-   case VK_PIPELINE_BIND_POINT_GRAPHICS: device_data->stats.stats[FRAME_STAT_PIPELINE_GRAPHICS]++; break;
-   case VK_PIPELINE_BIND_POINT_COMPUTE: device_data->stats.stats[FRAME_STAT_PIPELINE_COMPUTE]++; break;
-   case VK_PIPELINE_BIND_POINT_RAY_TRACING_NV: device_data->stats.stats[FRAME_STAT_PIPELINE_RAYTRACING]++; break;
+   case VK_PIPELINE_BIND_POINT_GRAPHICS: device_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_graphics]++; break;
+   case VK_PIPELINE_BIND_POINT_COMPUTE: device_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_compute]++; break;
+   case VK_PIPELINE_BIND_POINT_RAY_TRACING_NV: device_data->stats.stats[OVERLAY_PARAM_ENABLED_pipeline_raytracing]++; break;
    default: break;
    }
 }
@@ -1682,7 +1670,7 @@ VKAPI_ATTR VkResult VKAPI_CALL overlay_QueueSubmit(
    struct queue_data *queue_data = FIND_QUEUE_DATA(queue);
    struct device_data *device_data = queue_data->device;
 
-   device_data->stats.stats[FRAME_STAT_SUBMIT]++;
+   device_data->stats.stats[OVERLAY_PARAM_ENABLED_submit]++;
 
    return device_data->vtable.QueueSubmit(queue, submitCount, pSubmits, fence);
 }
@@ -1694,7 +1682,8 @@ VKAPI_ATTR VkResult VKAPI_CALL overlay_CreateDevice(
     VkDevice*                                   pDevice)
 {
    struct instance_data *instance_data = FIND_PHYSICAL_DEVICE_DATA(physicalDevice);
-   VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+   VkLayerDeviceCreateInfo *chain_info =
+      get_device_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
    assert(chain_info->u.pLayerInfo);
    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
@@ -1712,11 +1701,15 @@ VKAPI_ATTR VkResult VKAPI_CALL overlay_CreateDevice(
 
    struct device_data *device_data = new_device_data(*pDevice, instance_data);
    device_data->physical_device = physicalDevice;
-   layer_init_device_dispatch_table(*pDevice, &device_data->vtable, fpGetDeviceProcAddr);
+   vk_load_device_commands(*pDevice, fpGetDeviceProcAddr, &device_data->vtable);
 
    instance_data->vtable.GetPhysicalDeviceProperties(device_data->physical_device,
                                                      &device_data->properties);
 
+   VkLayerDeviceCreateInfo *load_data_info =
+      get_device_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
+   device_data->set_device_loader_data = load_data_info->u.pfnSetDeviceLoaderData;
+
    device_map_queues(device_data, pCreateInfo);
 
    return result;
@@ -1737,7 +1730,8 @@ VKAPI_ATTR VkResult VKAPI_CALL overlay_CreateInstance(
     const VkAllocationCallbacks*                pAllocator,
     VkInstance*                                 pInstance)
 {
-   VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+   VkLayerInstanceCreateInfo *chain_info =
+      get_instance_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
 
    assert(chain_info->u.pLayerInfo);
    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr =
@@ -1755,28 +1749,12 @@ VKAPI_ATTR VkResult VKAPI_CALL overlay_CreateInstance(
    if (result != VK_SUCCESS) return result;
 
    struct instance_data *instance_data = new_instance_data(*pInstance);
-   layer_init_instance_dispatch_table(instance_data->instance,
-                                      &instance_data->vtable,
-                                      fpGetInstanceProcAddr);
+   vk_load_instance_commands(instance_data->instance,
+                             fpGetInstanceProcAddr,
+                             &instance_data->vtable);
    instance_data_map_physical_devices(instance_data, true);
 
-   const char *stats_config = getenv("VK_LAYER_MESA_OVERLAY_STATS");
-   instance_data->enabled_stats = parse_debug_string(stats_config,
-                                                     enable_flags);
-
-   if (instance_data->enabled_stats & FRAME_STAT_ENABLED(HELP)) {
-      fprintf(stderr, "Available stats:\n");
-      for (uint32_t i = 0; enable_flags[i].string != NULL; i++)
-         fprintf(stderr, "\t%s\n", enable_flags[i].string);
-      fprintf(stderr, "Position layer using VK_LAYER_MESA_OVERLAY_POSITION=\n"
-              "\ttop-left\n"
-              "\ttop-right\n"
-              "\tbottom-left\n"
-              "\tbottom-right\n");
-   }
-
-   instance_data->position =
-      parse_layer_position(getenv("VK_LAYER_MESA_OVERLAY_POSITION"));
+   parse_overlay_env(&instance_data->params, getenv("VK_LAYER_MESA_OVERLAY_CONFIG"));
 
    return result;
 }