device->swapchain_private = NULL;
#endif /* ANDROID */
+ simple_mtx_init(&device->trace_mtx, mtx_plain);
+
return VK_SUCCESS;
}
}
#endif /* ANDROID */
+ simple_mtx_destroy(&device->trace_mtx);
+
vk_object_base_finish(&device->base);
}
#include "vk_physical_device_features.h"
#include "util/list.h"
+#include "util/simple_mtx.h"
#include "util/u_atomic.h"
#ifdef __cplusplus
/** 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;
#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,
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;
&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)
{
#include "c11/threads.h"
#include "util/list.h"
+#include "util/u_debug.h"
#ifdef __cplusplus
extern "C" {
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,
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,
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
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,
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));