tu/autotune: Fail gracefully when CP counters are unavailable

When preemption optimization is supported then the necessary CP
counters being missing causes a device initialization error which
is unnecessary as support can simply be disabled instead to allow
for a more graceful fail. This also fixes A8XX which doesn't have
performance counters hooked up yet.

Cc: mesa-stable
Signed-off-by: Dhruv Mark Collins <mark@igalia.com>
Assisted-by: OpenAI Codex (GPT-5.4)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40949>
This commit is contained in:
Dhruv Mark Collins 2026-04-16 14:01:19 +00:00
parent c2708afbc7
commit a5ec9b7892
2 changed files with 49 additions and 46 deletions

View file

@ -1632,56 +1632,60 @@ tu_autotune::tu_autotune(struct tu_device *device, VkResult &result)
{
tu_bo_suballocator_init(&suballoc, device, 128 * 1024, TU_BO_ALLOC_INTERNAL_RESOURCE, "autotune_suballoc");
uint32_t group_count;
const struct fd_perfcntr_group *groups = fd_perfcntrs(&device->physical_device->dev_id, &group_count);
for (uint32_t i = 0; i < group_count; i++) {
if (strcmp(groups[i].name, "CP") == 0) {
cp_group = &groups[i];
break;
}
}
if (!cp_group) {
mesa_loge("autotune: CP group not found");
result = VK_ERROR_INITIALIZATION_FAILED;
return;
} else if (cp_group->num_countables < 5) {
mesa_loge("autotune: CP group has too few countables");
result = VK_ERROR_INITIALIZATION_FAILED;
return;
}
auto get_perfcntr_countable = [](const struct fd_perfcntr_group *group,
const char *name) -> const struct fd_perfcntr_countable * {
for (uint32_t i = 0; i < group->num_countables; i++) {
if (strcmp(group->countables[i].name, name) == 0)
return &group->countables[i];
}
mesa_loge("autotune: %s not found in group %s", name, group->name);
return nullptr;
};
if (supports_preempt_latency_tracking()) {
auto preemption_latency_countable = get_perfcntr_countable(cp_group, "PERF_CP_PREEMPTION_REACTION_DELAY");
auto always_count_countable = get_perfcntr_countable(cp_group, "PERF_CP_ALWAYS_COUNT");
uint32_t group_count;
const struct fd_perfcntr_group *groups = fd_perfcntrs(&device->physical_device->dev_id, &group_count);
const char *fail_reason = nullptr;
if (cp_group->num_counters < 2) {
mesa_loge("autotune: CP group has too few counters for preemption latency tracking");
result = VK_ERROR_INITIALIZATION_FAILED;
return;
const fd_perfcntr_group *cp_group = nullptr;
for (uint32_t i = 0; i < group_count; i++) {
if (strcmp(groups[i].name, "CP") == 0) {
cp_group = &groups[i];
break;
}
}
uint32_t preemption_latency_counter_index = cp_group->num_counters - 2;
preemption_latency_selector_reg = cp_group->counters[preemption_latency_counter_index].select_reg;
preemption_latency_selector = preemption_latency_countable->selector;
preemption_latency_counter_reg_lo = cp_group->counters[preemption_latency_counter_index].counter_reg_lo;
if (cp_group) {
auto get_perfcntr_countable = [](const struct fd_perfcntr_group *group,
const char *name) -> const struct fd_perfcntr_countable * {
for (uint32_t i = 0; i < group->num_countables; i++) {
if (strcmp(group->countables[i].name, name) == 0)
return &group->countables[i];
}
uint32_t always_count_counter_index = cp_group->num_counters - 1;
always_count_selector_reg = cp_group->counters[always_count_counter_index].select_reg;
always_count_selector = always_count_countable->selector;
always_count_counter_reg_lo = cp_group->counters[always_count_counter_index].counter_reg_lo;
return nullptr;
};
auto preemption_latency_countable = get_perfcntr_countable(cp_group, "PERF_CP_PREEMPTION_REACTION_DELAY");
auto always_count_countable = get_perfcntr_countable(cp_group, "PERF_CP_ALWAYS_COUNT");
if (preemption_latency_countable && always_count_countable) {
if (cp_group->num_counters >= 2) {
uint32_t preemption_latency_counter_index = cp_group->num_counters - 2;
preemption_latency_selector_reg = cp_group->counters[preemption_latency_counter_index].select_reg;
preemption_latency_selector = preemption_latency_countable->selector;
preemption_latency_counter_reg_lo = cp_group->counters[preemption_latency_counter_index].counter_reg_lo;
uint32_t always_count_counter_index = cp_group->num_counters - 1;
always_count_selector_reg = cp_group->counters[always_count_counter_index].select_reg;
always_count_selector = always_count_countable->selector;
always_count_counter_reg_lo = cp_group->counters[always_count_counter_index].counter_reg_lo;
} else {
fail_reason = "not enough counters in CP group for preemption latency tracking";
}
} else {
fail_reason = "required countables not found in CP group";
}
} else {
fail_reason = "CP counter group not found";
}
if (fail_reason) {
if (TU_DEBUG(STARTUP) || active_config.load().test(mod_flag::PREEMPT_OPTIMIZE))
mesa_logw("autotune: %s, preemption optimization not supported", fail_reason);
supported_mod_flags &= ~((uint32_t) mod_flag::PREEMPT_OPTIMIZE);
disable_preempt_optimize();
}
}
result = VK_SUCCESS;

View file

@ -242,7 +242,6 @@ struct tu_autotune {
std::mutex rp_latency_mutex; /* Protects rp_latency_tracking */
uint64_t last_latency_cleanup_ts = 0;
const fd_perfcntr_group *cp_group;
uint32_t preemption_latency_selector_reg;
uint32_t preemption_latency_selector;
uint32_t preemption_latency_counter_reg_lo;