vulkan: Common trace capturing infrastructure
authorKonstantin Seurer <konstantin.seurer@gmail.com>
Sun, 8 Jan 2023 15:44:57 +0000 (16:44 +0100)
committerMarge Bot <emma+marge@anholt.net>
Tue, 27 Jun 2023 06:25:56 +0000 (06:25 +0000)
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20573>

src/vulkan/runtime/vk_device.c
src/vulkan/runtime/vk_device.h
src/vulkan/runtime/vk_instance.c
src/vulkan/runtime/vk_instance.h
src/vulkan/wsi/wsi_common.c

index 9d7b92b..f67f064 100644 (file)
@@ -179,6 +179,8 @@ vk_device_init(struct vk_device *device,
    device->swapchain_private = NULL;
 #endif /* ANDROID */
 
+   simple_mtx_init(&device->trace_mtx, mtx_plain);
+
    return VK_SUCCESS;
 }
 
@@ -198,6 +200,8 @@ vk_device_finish(struct vk_device *device)
    }
 #endif /* ANDROID */
 
+   simple_mtx_destroy(&device->trace_mtx);
+
    vk_object_base_finish(&device->base);
 }
 
index cefcc48..ecf4bab 100644 (file)
@@ -30,6 +30,7 @@
 #include "vk_physical_device_features.h"
 
 #include "util/list.h"
+#include "util/simple_mtx.h"
 #include "util/u_atomic.h"
 
 #ifdef __cplusplus
@@ -129,6 +130,18 @@ struct vk_device {
    /** Command buffer vtable when using the common command pool */
    const struct vk_command_buffer_ops *command_buffer_ops;
 
+   /** Driver provided callback for capturing traces
+    * 
+    * Triggers for this callback are:
+    *    - Keyboard input (F12)
+    *    - Creation of a trigger file
+    *    - Reaching the trace frame
+    */
+   VkResult (*capture_trace)(VkQueue queue);
+
+   uint32_t current_frame;
+   simple_mtx_t trace_mtx;
+
    /* For VK_EXT_private_data */
    uint32_t private_data_next_index;
 
index 1a471eb..a2ae6fd 100644 (file)
 #define VERSION_IS_1_0(version) \
    (VK_API_VERSION_MAJOR(version) == 1 && VK_API_VERSION_MINOR(version) == 0)
 
+static const struct debug_control trace_options[] = {
+   {NULL, 0},
+};
+
 VkResult
 vk_instance_init(struct vk_instance *instance,
                  const struct vk_instance_extension_table *supported_extensions,
@@ -189,6 +193,10 @@ vk_instance_init(struct vk_instance *instance,
       return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
    }
 
+   instance->trace_mode = parse_debug_string(getenv("MESA_VK_TRACE"), trace_options);
+   instance->trace_frame = (uint32_t)debug_get_num_option("MESA_VK_TRACE_FRAME", 0xFFFFFFFF);
+   instance->trace_trigger_file = getenv("MESA_VK_TRACE_TRIGGER");
+
    glsl_type_singleton_init_or_ref();
 
    return VK_SUCCESS;
@@ -356,6 +364,13 @@ vk_instance_get_physical_device_proc_addr(const struct vk_instance *instance,
                                                              &instance->enabled_extensions);
 }
 
+void
+vk_instance_add_driver_trace_modes(struct vk_instance *instance,
+                                   const struct debug_control *modes)
+{
+   instance->trace_mode |= parse_debug_string(getenv("MESA_VK_TRACE"), modes);
+}
+
 static VkResult
 enumerate_drm_physical_devices_locked(struct vk_instance *instance)
 {
index b1ddf6a..f4da86d 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "c11/threads.h"
 #include "util/list.h"
+#include "util/u_debug.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -58,6 +59,11 @@ struct vk_app_info {
 struct _drmDevice;
 struct vk_physical_device;
 
+enum vk_trace_mode {
+   /** Number of common trace modes. */
+   VK_TRACE_MODE_COUNT = 0,
+};
+
 /** Base struct for all `VkInstance` implementations
  *
  * This contains data structures necessary for detecting enabled extensions,
@@ -158,6 +164,12 @@ struct vk_instance {
 
       mtx_t mutex;
    } physical_devices;
+
+   /** Enabled tracing modes */
+   uint64_t trace_mode;
+
+   uint32_t trace_frame;
+   char *trace_trigger_file;
 };
 
 VK_DEFINE_HANDLE_CASTS(vk_instance, base, VkInstance,
@@ -224,6 +236,10 @@ PFN_vkVoidFunction
 vk_instance_get_physical_device_proc_addr(const struct vk_instance *instance,
                                           const char *name);
 
+void
+vk_instance_add_driver_trace_modes(struct vk_instance *instance,
+                                   const struct debug_control *modes);
+
 #ifdef __cplusplus
 }
 #endif
index b03a359..59ea230 100644 (file)
@@ -1221,6 +1221,41 @@ static VkResult wsi_signal_present_id_timeline(struct wsi_swapchain *swapchain,
    return swapchain->wsi->QueueSubmit(queue, submit_count, &submit_info, present_fence);
 }
 
+static VkResult
+handle_trace(VkQueue queue, struct vk_device *device)
+{
+   struct vk_instance *instance = device->physical->instance;
+   if (!instance->trace_mode)
+      return VK_SUCCESS;
+
+   simple_mtx_lock(&device->trace_mtx);
+
+   bool frame_trigger = device->current_frame == instance->trace_frame;
+   if (device->current_frame <= instance->trace_frame)
+      device->current_frame++;
+
+   bool file_trigger = false;
+#ifndef _WIN32
+   if (instance->trace_trigger_file && access(instance->trace_trigger_file, W_OK) == 0) {
+      if (unlink(instance->trace_trigger_file) == 0) {
+         file_trigger = true;
+      } else {
+         /* Do not enable tracing if we cannot remove the file,
+          * because by then we'll trace every frame ... */
+         fprintf(stderr, "Could not remove trace trigger file, ignoring\n");
+      }
+   }
+#endif
+
+   VkResult result = VK_SUCCESS;
+   if (frame_trigger || file_trigger)
+      result = device->capture_trace(queue);
+
+   simple_mtx_unlock(&device->trace_mtx);
+
+   return result;
+}
+
 VkResult
 wsi_common_queue_present(const struct wsi_device *wsi,
                          VkDevice device,
@@ -1228,7 +1263,7 @@ wsi_common_queue_present(const struct wsi_device *wsi,
                          int queue_family_index,
                          const VkPresentInfoKHR *pPresentInfo)
 {
-   VkResult final_result = VK_SUCCESS;
+   VkResult final_result = handle_trace(queue, vk_device_from_handle(device));
 
    STACK_ARRAY(VkPipelineStageFlags, stage_flags,
                MAX2(1, pPresentInfo->waitSemaphoreCount));