tu/util: Allow setting all TU_DEBUG options from envvar and file

Due to the division of TU_DEBUG options into runtime and envvar
options, it limited where options could be set from when
TU_DEBUG_FILE was being used. This commit addresses that by allowing
the envvar to set runtime debug options even when TU_DEBUG_FILE is
active while also allowing the file to set non-runtime options if
the file included them at startup.

Signed-off-by: Dhruv Mark Collins <mark@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37580>
This commit is contained in:
Dhruv Mark Collins
2025-09-25 18:36:56 +00:00
committed by Marge Bot
parent c473b0b551
commit 4e762df664
6 changed files with 46 additions and 32 deletions

View File

@@ -648,8 +648,9 @@ Runtime toggling of ``TU_DEBUG`` options
In some cases, it is useful to toggle ``TU_DEBUG`` options at runtime, such as
when assessing the performance impact of a particular option. This can be done
by setting the ``TU_DEBUG_FILE`` environment variable to a file path, and writing
the desired ``TU_DEBUG`` options to that file. The driver will check the file for
changes and apply them.
the desired ``TU_DEBUG`` options to that file. The driver will check the file at
startup and apply all debug options (runtime and non-runtime) but then will
continue to monitor the file for changes and only apply runtime options.
The folder containing the file should exist prior to running the application, and
deleting the folder during runtime will result in the driver no longer picking up

View File

@@ -3345,7 +3345,7 @@ tu_create_cmd_buffer(struct vk_command_pool *pool,
u_trace_begin_iterator(&cmd_buffer->rp_trace);
list_inithead(&cmd_buffer->renderpass_autotune_results);
if (TU_DEBUG_ENV(CHECK_CMD_BUFFER_STATUS)) {
if (TU_DEBUG_START(CHECK_CMD_BUFFER_STATUS)) {
cmd_buffer->status_bo = tu_cmd_buffer_setup_status_tracking(device);
if (cmd_buffer->status_bo == NULL) {
mesa_logw("Failed creating cmd_buffer status_bo. "
@@ -3383,7 +3383,7 @@ tu_cmd_buffer_destroy(struct vk_command_buffer *vk_cmd_buffer)
tu_cs_finish(&cmd_buffer->pre_chain.draw_cs);
tu_cs_finish(&cmd_buffer->pre_chain.draw_epilogue_cs);
if (TU_DEBUG_ENV(CHECK_CMD_BUFFER_STATUS)) {
if (TU_DEBUG_START(CHECK_CMD_BUFFER_STATUS)) {
tu_cmd_buffer_status_check_idle(cmd_buffer);
tu_bo_unmap(cmd_buffer->device, cmd_buffer->status_bo, false);
tu_bo_finish(cmd_buffer->device, cmd_buffer->status_bo);
@@ -3420,12 +3420,12 @@ tu_reset_cmd_buffer(struct vk_command_buffer *vk_cmd_buffer,
container_of(vk_cmd_buffer, struct tu_cmd_buffer, vk);
VkResult status_check_result = VK_SUCCESS;
if (TU_DEBUG_ENV(CHECK_CMD_BUFFER_STATUS))
if (TU_DEBUG_START(CHECK_CMD_BUFFER_STATUS))
status_check_result = tu_cmd_buffer_status_check_idle(cmd_buffer);
vk_command_buffer_reset(&cmd_buffer->vk);
if (TU_DEBUG_ENV(CHECK_CMD_BUFFER_STATUS) &&
if (TU_DEBUG_START(CHECK_CMD_BUFFER_STATUS) &&
status_check_result != VK_SUCCESS) {
cmd_buffer->vk.record_result = status_check_result;
}
@@ -4455,7 +4455,7 @@ tu_EndCommandBuffer(VkCommandBuffer commandBuffer)
cmd_buffer->state.pass ? &cmd_buffer->draw_cs : &cmd_buffer->cs);
}
if (TU_DEBUG_ENV(CHECK_CMD_BUFFER_STATUS))
if (TU_DEBUG_START(CHECK_CMD_BUFFER_STATUS))
tu_cmd_buffer_status_gpu_write(cmd_buffer, TU_CMD_BUFFER_STATUS_IDLE);
tu_cs_end(&cmd_buffer->cs);

View File

@@ -624,7 +624,7 @@ struct tu_cmd_buffer
struct tu_cmd_state state;
uint32_t queue_family_index;
/* For TU_DEBUG_ENV(CHECK_CMD_BUFFER_STATUS) functionality. */
/* For TU_DEBUG_START(CHECK_CMD_BUFFER_STATUS) functionality. */
struct tu_bo *status_bo;
uint32_t push_constants[MAX_PUSH_CONSTANTS_SIZE / 4];

View File

@@ -2961,7 +2961,7 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice,
physical_device->info->a6xx.has_z24uint_s8uint &&
(!border_color_without_format ||
physical_device->instance->disable_d24s8_border_color_workaround);
device->use_lrz = !TU_DEBUG_ENV(NOLRZ);
device->use_lrz = !TU_DEBUG_START(NOLRZ);
tu_gpu_tracepoint_config_variable();

View File

@@ -12,6 +12,7 @@
#include "util/u_math.h"
#include "util/timespec.h"
#include "util/os_file_notify.h"
#include "util/os_file.h"
#include "vk_enum_to_str.h"
#include "tu_device.h"
@@ -74,31 +75,40 @@ const uint64_t tu_runtime_debug_flags =
os_file_notifier_t tu_debug_notifier;
struct tu_env tu_env;
static uint64_t
tu_env_get_file_flags(const char *path)
{
char *str = os_read_file(path, NULL);
if (str) {
uint64_t flags = parse_debug_string(str, tu_debug_options);
free(str);
return flags;
}
return 0;
}
static void
tu_env_notify(
void *data, const char *path, bool created, bool deleted, bool dir_deleted)
{
uint64_t file_flags = 0;
if (!deleted) {
FILE *file = fopen(path, "r");
if (file) {
char buf[512];
size_t len = fread(buf, 1, sizeof(buf) - 1, file);
fclose(file);
buf[len] = '\0';
file_flags = parse_debug_string(buf, tu_debug_options);
}
file_flags = tu_env_get_file_flags(path);
}
uint64_t runtime_flags = file_flags & tu_runtime_debug_flags;
if (unlikely(runtime_flags != file_flags)) {
mesa_logw(
"Certain options in TU_DEBUG_FILE don't support runtime changes: 0x%" PRIx64 ", ignoring",
file_flags & ~tu_runtime_debug_flags);
if ((tu_env.debug.load(std::memory_order_acquire) & tu_runtime_debug_flags) ^ runtime_flags) {
mesa_logd("TU_DEBUG_FILE: Runtime debug flags change detected. Flags set:");
for (unsigned i = 0; i < ARRAY_SIZE(tu_debug_options); i++) {
if (runtime_flags & tu_debug_options[i].flag)
mesa_logd("TU_DEBUG_FILE: %s", tu_debug_options[i].string);
}
if (runtime_flags == 0)
mesa_logd("TU_DEBUG_FILE: None");
}
tu_env.debug.store(runtime_flags | tu_env.env_debug, std::memory_order_release);
tu_env.debug.store(runtime_flags | tu_env.start_debug, std::memory_order_release);
if (unlikely(dir_deleted))
mesa_logw(
@@ -116,11 +126,10 @@ tu_env_deinit(void)
static void
tu_env_init_once(void)
{
tu_env.debug = parse_debug_string(os_get_option("TU_DEBUG"), tu_debug_options);
tu_env.env_debug = tu_env.debug & ~tu_runtime_debug_flags;
tu_env.start_debug = tu_env.debug = parse_debug_string(os_get_option("TU_DEBUG"), tu_debug_options);
if (TU_DEBUG(STARTUP))
mesa_logi("TU_DEBUG=0x%" PRIx64 " (ENV: 0x%" PRIx64 ")", tu_env.debug.load(), tu_env.env_debug);
mesa_logi("TU_DEBUG=0x%" PRIx64, tu_env.debug.load());
/* TU_DEBUG=rd functionality was moved to fd_rd_output. This debug option
* should translate to the basic-level FD_RD_DUMP_ENABLE option.
@@ -130,12 +139,16 @@ tu_env_init_once(void)
const char *debug_file = os_get_option("TU_DEBUG_FILE");
if (debug_file) {
if (tu_env.debug != tu_env.env_debug) {
if ((tu_env.debug & tu_runtime_debug_flags) != 0) {
mesa_logw("TU_DEBUG_FILE is set (%s), but TU_DEBUG is also set. "
"Any runtime options (0x%" PRIx64 ") in TU_DEBUG will be ignored.",
"Any runtime options (0x%" PRIx64 ") set in TU_DEBUG cannot be changed at runtime.",
debug_file, tu_env.debug & tu_runtime_debug_flags);
}
uint64_t file_flags = tu_env_get_file_flags(debug_file);
tu_env.start_debug |= file_flags & ~tu_runtime_debug_flags;
tu_env.debug = file_flags | tu_env.start_debug;
if (TU_DEBUG(STARTUP))
mesa_logi("Watching TU_DEBUG_FILE: %s", debug_file);

View File

@@ -29,12 +29,12 @@
#define TU_DEBUG(name) unlikely(tu_env.debug.load(std::memory_order_acquire) & TU_DEBUG_##name)
/*
* Same as TU_DEBUG, but only uses the environment variable's value rather
* than TU_DEBUG_FILE. This is useful for flags that should not be changed
* Same as TU_DEBUG, but only uses the initial value without any runtime changes
* from TU_DEBUG_FILE. This is useful for flags that should not be changed
* at runtime or when a flag has different behavior depending on whether it
* is set in TU_DEBUG or TU_DEBUG_FILE.
*/
#define TU_DEBUG_ENV(name) unlikely(tu_env.env_debug & TU_DEBUG_##name)
#define TU_DEBUG_START(name) unlikely(tu_env.start_debug & TU_DEBUG_##name)
enum tu_debug_flags : uint64_t
{
@@ -77,7 +77,7 @@ enum tu_debug_flags : uint64_t
struct tu_env {
std::atomic<uint64_t> debug;
uint64_t env_debug;
uint64_t start_debug;
};
extern struct tu_env tu_env;