#include "imgui.h"
+#include "overlay_params.h"
+
#include "util/debug.h"
#include "util/hash_table.h"
#include "util/ralloc.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;
-}
-
/* Mapped from VkInstace/VkPhysicalDevice */
struct instance_data {
VkLayerInstanceDispatchTable 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 */
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];
};
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);
- 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]);
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]);
}
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]);
}
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);
}
fpGetInstanceProcAddr);
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;
}
--- /dev/null
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "overlay_params.h"
+
+static enum overlay_param_position
+parse_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;
+}
+
+static bool
+parse_help(const char *str)
+{
+ fprintf(stderr, "Layer params using VK_LAYER_MESA_OVERLAY_CONFIG=\n");
+#define OVERLAY_PARAM_BOOL(name) \
+ fprintf(stderr, "\t%s=0/1\n", #name);
+#define OVERLAY_PARAM_CUSTOM(name)
+ OVERLAY_PARAMS
+#undef OVERLAY_PARAM_BOOL
+#undef OVERLAY_PARAM_CUSTOM
+ fprintf(stderr, "\tposition=\n"
+ "\t\ttop-left\n"
+ "\t\ttop-right\n"
+ "\t\tbottom-left\n"
+ "\t\tbottom-right\n");
+
+ return true;
+}
+
+static bool is_delimiter(char c)
+{
+ return c == 0 || c == ',' || c == ':' || c == ';' || c == '=';
+}
+
+static int
+parse_string(const char *s, char *out_param, char *out_value)
+{
+ int i = 0;
+
+ for (; !is_delimiter(*s); s++, out_param++, i++)
+ *out_param = *s;
+
+ *out_param = 0;
+
+ if (*s == '=') {
+ s++;
+ i++;
+ for (; !is_delimiter(*s); s++, out_value++, i++)
+ *out_value = *s;
+ }
+ *out_value = 0;
+
+ if (*s && is_delimiter(*s)) {
+ s++;
+ i++;
+ }
+
+ if (*s && !i) {
+ fprintf(stderr, "mesa-overlay: syntax error: unexpected '%c' (%i) while "
+ "parsing a string\n", *s, *s);
+ fflush(stderr);
+ }
+
+ return i;
+}
+
+const char *overlay_param_names[] = {
+#define OVERLAY_PARAM_BOOL(name) #name,
+#define OVERLAY_PARAM_CUSTOM(name)
+ OVERLAY_PARAMS
+#undef OVERLAY_PARAM_BOOL
+#undef OVERLAY_PARAM_CUSTOM
+};
+
+void
+parse_overlay_env(struct overlay_params *params,
+ const char *env)
+{
+ uint32_t num;
+ char key[256], value[256];
+
+ memset(params, 0, sizeof(*params));
+
+ /* Visible by default */
+ params->enabled[OVERLAY_PARAM_ENABLED_fps] = true;
+ params->enabled[OVERLAY_PARAM_ENABLED_frame_timing] = true;
+
+ if (!env)
+ return;
+
+ while ((num = parse_string(env, key, value)) != 0) {
+ env += num;
+
+#define OVERLAY_PARAM_BOOL(name) \
+ if (!strcmp(#name, key)) { \
+ params->enabled[OVERLAY_PARAM_ENABLED_##name] = strtol(value, NULL, 0); \
+ continue; \
+ }
+#define OVERLAY_PARAM_CUSTOM(name) \
+ if (!strcmp(#name, key)) { \
+ params->name = parse_##name(value); \
+ continue; \
+ }
+ OVERLAY_PARAMS
+#undef OVERLAY_PARAM_BOOL
+#undef OVERLAY_PARAM_CUSTOM
+ fprintf(stderr, "Unknown option '%s'\n", key);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef OVERLAY_PARAMS_H
+#define OVERLAY_PARAMS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define OVERLAY_PARAMS \
+ OVERLAY_PARAM_BOOL(fps) \
+ OVERLAY_PARAM_BOOL(frame_timing) \
+ OVERLAY_PARAM_BOOL(submit) \
+ OVERLAY_PARAM_BOOL(draw) \
+ OVERLAY_PARAM_BOOL(draw_indexed) \
+ OVERLAY_PARAM_BOOL(draw_indirect) \
+ OVERLAY_PARAM_BOOL(draw_indexed_indirect) \
+ OVERLAY_PARAM_BOOL(draw_indirect_count) \
+ OVERLAY_PARAM_BOOL(draw_indexed_indirect_count) \
+ OVERLAY_PARAM_BOOL(dispatch) \
+ OVERLAY_PARAM_BOOL(dispatch_indirect) \
+ OVERLAY_PARAM_BOOL(pipeline_graphics) \
+ OVERLAY_PARAM_BOOL(pipeline_compute) \
+ OVERLAY_PARAM_BOOL(pipeline_raytracing) \
+ OVERLAY_PARAM_BOOL(acquire_timing) \
+ OVERLAY_PARAM_CUSTOM(position) \
+ OVERLAY_PARAM_CUSTOM(help)
+
+enum overlay_param_position {
+ LAYER_POSITION_TOP_LEFT,
+ LAYER_POSITION_TOP_RIGHT,
+ LAYER_POSITION_BOTTOM_LEFT,
+ LAYER_POSITION_BOTTOM_RIGHT,
+};
+
+enum overlay_param_enabled {
+#define OVERLAY_PARAM_BOOL(name) OVERLAY_PARAM_ENABLED_##name,
+#define OVERLAY_PARAM_CUSTOM(name)
+ OVERLAY_PARAMS
+#undef OVERLAY_PARAM_BOOL
+#undef OVERLAY_PARAM_CUSTOM
+ OVERLAY_PARAM_ENABLED_MAX
+};
+
+struct overlay_params {
+ bool enabled[OVERLAY_PARAM_ENABLED_MAX];
+ enum overlay_param_position position;
+ bool help;
+};
+
+const extern char *overlay_param_names[];
+
+void parse_overlay_env(struct overlay_params *params,
+ const char *env);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OVERLAY_PARAMS_H */