#include <stdlib.h>
#include <assert.h>
-#include <vk_loader_platform.h>
#include <vulkan/vulkan.h>
-#include <vk_dispatch_table_helper.h>
#include <vulkan/vk_layer.h>
-#include "vk_layer_data.h"
-#include "vk_layer_table.h"
-#include "vk_layer_extension_utils.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 */
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;
uint64_t n_frames;
uint64_t last_present_time;
+ unsigned n_frames_since_update;
+ uint64_t last_fps_update;
+ double fps;
+
double frame_times[200];
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];
};
}
/**/
+
+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);
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);
}
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);
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)
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)] =
((double)now - (double)data->last_present_time) / 1000.0;
}
+ if (data->last_fps_update) {
+ 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;
+ }
+
struct device_data *device_data = data->device;
data->stats[data->n_frames % ARRAY_SIZE(data->frame_times)] = device_data->stats;
memset(&device_data->stats, 0, sizeof(device_data->stats));
data->last_present_time = now;
data->n_frames++;
+ data->n_frames_since_update++;
}
static float get_frame_timing(void *_data, int _idx)
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;
format_name = format_name ? (format_name + strlen("VK_FORMAT_")) : "unknown";
ImGui::Text("Swapchain format: %s", format_name);
ImGui::Text("Frames: %" PRIu64, data->n_frames);
+ 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]);
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]);
ImGui::Text("Acquire timing: %.3fms [%.3f, %.3f]",
get_acquire_timing(data, ARRAY_SIZE(data->acquire_times) - 1),
min_time, max_time);
+ }
- for (uint32_t i = 0; i < ARRAY_SIZE(data->stats_min.stats); i++) {
- data->stats_min.stats[i] = UINT32_MAX;
- data->stats_max.stats[i] = 0;
- }
- for (uint32_t i = 0; i < MIN2(data->n_frames - 1, ARRAY_SIZE(data->stats)); i++) {
- for (uint32_t j = 0; j < ARRAY_SIZE(data->stats[0].stats); j++) {
- data->stats_min.stats[j] = MIN2(data->stats[i].stats[j],
- data->stats_min.stats[j]);
- data->stats_max.stats[j] = MAX2(data->stats[i].stats[j],
- data->stats_max.stats[j]);
- }
+ for (uint32_t i = 0; i < ARRAY_SIZE(data->stats_min.stats); i++) {
+ data->stats_min.stats[i] = UINT32_MAX;
+ data->stats_max.stats[i] = 0;
+ }
+ for (uint32_t i = 0; i < MIN2(data->n_frames - 1, ARRAY_SIZE(data->stats)); i++) {
+ for (uint32_t j = 0; j < ARRAY_SIZE(data->stats[0].stats); j++) {
+ data->stats_min.stats[j] = MIN2(data->stats[i].stats[j],
+ data->stats_min.stats[j]);
+ data->stats_max.stats[j] = MAX2(data->stats[i].stats[j],
+ data->stats_max.stats[j]);
}
}
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,
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]);
}
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];
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 */
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;
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 = {};
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 = {};
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)
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,
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(
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(
{
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(
{
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(
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(
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(
{
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(
{
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(
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;
}
}
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);
}
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;
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;
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 =
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;
}