mesa/0016-Revert-tu-autotune-Add-Profiled-algorithm.patch
Jocelyn Falempe f49ef1410d update to 26.1.1
- remove patches that are in upstream
- remove vdpau as upstream removed it
- update version of dependencies
- update rust libwrap filename
- Update libclc to 22.1 has the 21.1.8 doesn't build on centos stream 9
- Fix python issues with 3.9 (Mesa requires 3.10)
- Revert Freedreno tu_autotune to previous C implementation, as C++ implementation
- Remove some kmsro driver on x86_64

Resolves: RHEL-135263

Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
2026-07-01 09:44:14 +02:00

360 lines
14 KiB
Diff

From 9a69681069d4d8b9b7fd925bd381db3e8cf3e720 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 11:03:35 +0200
Subject: [PATCH 16/19] Revert "tu/autotune: Add "Profiled" algorithm"
This reverts commit fac705ab8aa15e98325cf216e66512601de0c005.
---
docs/drivers/freedreno.rst | 13 --
src/freedreno/vulkan/tu_autotune.cc | 201 +---------------------------
2 files changed, 1 insertion(+), 213 deletions(-)
diff --git a/docs/drivers/freedreno.rst b/docs/drivers/freedreno.rst
index a2318559526..ee733950fe4 100644
--- a/docs/drivers/freedreno.rst
+++ b/docs/drivers/freedreno.rst
@@ -686,19 +686,6 @@ environment variables:
Estimates the bandwidth usage of rendering in SYSMEM and GMEM modes, and chooses
the one with lower estimated bandwidth. This is the default algorithm.
- ``profiled``
- Dynamically profiles the RP timings in SYSMEM and GMEM modes, and uses that to
- move a probability distribution towards the optimal choice over time. This
- algorithm tends to be far more accurate than the bandwidth algorithm at choosing
- the optimal rendering mode but may result in larger FPS variance due to being
- based on a probability distribution with random sampling.
-
- ``profiled_imm``
- Similar to ``profiled``, but only profiles the first few instances of a RP
- and then sticks to the chosen mode for subsequent instances. This is meant
- for single-frame traces run multiple times in a CI where this algorithm can
- immediately chose the optimal rendering mode for each RP.
-
.. envvar:: TU_AUTOTUNE_FLAGS
Modifies the behavior of the selected algorithm. Supported flags are:
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index 38d09f5db45..cfc145e3286 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -28,7 +28,6 @@
#define TU_AUTOTUNE_DEBUG_LOG_BASE 0
#define TU_AUTOTUNE_DEBUG_LOG_BANDWIDTH 0
-#define TU_AUTOTUNE_DEBUG_LOG_PROFILED 0
#if TU_AUTOTUNE_DEBUG_LOG_BASE
#define at_log_base(fmt, ...) mesa_logi("autotune: " fmt, ##__VA_ARGS__)
@@ -44,12 +43,6 @@
#define at_log_bandwidth_h(fmt, hash, ...)
#endif
-#if TU_AUTOTUNE_DEBUG_LOG_PROFILED
-#define at_log_profiled_h(fmt, hash, ...) mesa_logi("autotune-prof %016" PRIx64 ": " fmt, hash, ##__VA_ARGS__)
-#else
-#define at_log_profiled_h(fmt, hash, ...)
-#endif
-
/* Process any pending entries on autotuner finish, could be used to gather data from traces. */
#define TU_AUTOTUNE_FLUSH_AT_FINISH 0
@@ -89,8 +82,6 @@ render_mode_str(tu_autotune::render_mode mode)
enum class tu_autotune::algorithm : uint8_t {
BANDWIDTH = 0, /* Uses estimated BW for determining rendering mode. */
- PROFILED = 1, /* Uses dynamically profiled results for determining rendering mode. */
- PROFILED_IMM = 2, /* Same as PROFILED but immediately resolves the SYSMEM/GMEM probability. */
DEFAULT = BANDWIDTH, /* Default algorithm, used if no other is specified. */
};
@@ -104,7 +95,6 @@ enum class tu_autotune::mod_flag : uint8_t {
/* Metric flags, for internal tracking of enabled metrics. */
enum class tu_autotune::metric_flag : uint8_t {
SAMPLES = BIT(1), /* Enable tracking samples passed metric. */
- TS = BIT(2), /* Enable tracking per-RP timestamp metric. */
};
struct PACKED tu_autotune::config_t {
@@ -118,8 +108,6 @@ struct PACKED tu_autotune::config_t {
/* Note: Always keep in sync with rp_history to prevent UB. */
if (algo == algorithm::BANDWIDTH) {
metric_flags |= (uint8_t) metric_flag::SAMPLES;
- } else if (algo == algorithm::PROFILED || algo == algorithm::PROFILED_IMM) {
- metric_flags |= (uint8_t) metric_flag::TS;
}
}
@@ -193,8 +181,6 @@ struct PACKED tu_autotune::config_t {
std::string str = "Algorithm: ";
ALGO_STR(BANDWIDTH);
- ALGO_STR(PROFILED);
- ALGO_STR(PROFILED_IMM);
str += ", Mod Flags: 0x" + std::to_string(mod_flags) + " (";
MODF_STR(BIG_GMEM);
@@ -203,7 +189,6 @@ struct PACKED tu_autotune::config_t {
str += ", Metric Flags: 0x" + std::to_string(metric_flags) + " (";
METRICF_STR(SAMPLES);
- METRICF_STR(TS);
str += ")";
return str;
@@ -262,12 +247,6 @@ tu_autotune::get_env_config()
std::string_view algo_strv(algo_env_str);
if (algo_strv == "bandwidth") {
algo = algorithm::BANDWIDTH;
- } else if (algo_strv == "profiled") {
- algo = algorithm::PROFILED;
- } else if (algo_strv == "profiled_imm") {
- algo = algorithm::PROFILED_IMM;
- } else {
- mesa_logw("Unknown TU_AUTOTUNE_ALGO '%s', using default", algo_env_str);
}
if (TU_DEBUG(STARTUP))
@@ -561,22 +540,6 @@ struct tu_autotune::rp_entry {
}
}
- /** RP/Tile Timestamp Metric **/
-
- uint64_t get_rp_duration()
- {
- assert(config.test(metric_flag::TS));
- rp_gpu_data &gpu = get_gpu_data();
- return gpu.ts_end - gpu.ts_start;
- }
-
- void emit_metric_timestamp(struct tu_cs *cs, uint64_t timestamp_iova)
- {
- tu_cs_emit_pkt7(cs, CP_REG_TO_MEM, 3);
- tu_cs_emit(cs, CP_REG_TO_MEM_0_REG(REG_A6XX_CP_ALWAYS_ON_COUNTER) | CP_REG_TO_MEM_0_CNT(2) | CP_REG_TO_MEM_0_64B);
- tu_cs_emit_qw(cs, timestamp_iova);
- }
-
/** CS Emission **/
void emit_rp_start(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
@@ -585,9 +548,6 @@ struct tu_autotune::rp_entry {
uint64_t bo_iova = bo.iova;
if (config.test(metric_flag::SAMPLES))
emit_metric_samples_start(cmd, cs, bo_iova + offsetof(rp_gpu_data, samples_start));
-
- if (config.test(metric_flag::TS))
- emit_metric_timestamp(cs, bo_iova + offsetof(rp_gpu_data, ts_start));
}
void emit_rp_end(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
@@ -597,9 +557,6 @@ struct tu_autotune::rp_entry {
if (config.test(metric_flag::SAMPLES))
emit_metric_samples_end(cmd, cs, bo_iova + offsetof(rp_gpu_data, samples_start),
bo_iova + offsetof(rp_gpu_data, samples_end));
-
- if (config.test(metric_flag::TS))
- emit_metric_timestamp(cs, bo_iova + offsetof(rp_gpu_data, ts_end));
}
};
@@ -734,66 +691,10 @@ template <typename T = double> class exponential_average {
}
};
-/* An improvement over pure EMA to filter out spikes by using two EMAs:
- * - A "slow" EMA with a low alpha to track the long-term average.
- * - A "fast" EMA with a high alpha to track short-term changes.
- * When retrieving the average, if the fast EMA deviates significantly from the slow EMA, it indicates a spike, and we
- * fall back to the slow EMA.
- */
-template <typename T = double> class adaptive_average {
- private:
- static constexpr double DEFAULT_SLOW_ALPHA = 0.1, DEFAULT_FAST_ALPHA = 0.5, DEFAULT_DEVIATION_THRESHOLD = 0.3;
- exponential_average<T> slow;
- exponential_average<T> fast;
- double deviationThreshold;
-
- public:
- size_t count = 0;
-
- explicit adaptive_average(double slow_alpha = DEFAULT_SLOW_ALPHA,
- double fast_alpha = DEFAULT_FAST_ALPHA,
- double deviation_threshold = DEFAULT_DEVIATION_THRESHOLD) noexcept
- : slow(slow_alpha), fast(fast_alpha), deviationThreshold(deviation_threshold)
- {
- }
-
- void add(T value) noexcept
- {
- slow.add(value);
- fast.add(value);
- count++;
- }
-
- T get() const noexcept
- {
- double s = slow.get();
- double f = fast.get();
- /* Use fast if it's close to slow (normal variation).
- * Use slow if fast deviates too much (likely a spike).
- */
- double deviation = std::abs(f - s) / s;
- return (deviation < deviationThreshold) ? f : s + (f - s) * deviationThreshold;
- }
-
- void clear() noexcept
- {
- slow.clear();
- fast.clear();
- count = 0;
- }
-};
-
/* All historical state pertaining to a uniquely identified RP. This integrates data from RP entries, accumulating
* metrics over the long-term and providing autotune algorithms using the data.
*/
struct tu_autotune::rp_history {
- private:
- /* Amount of duration samples for profiling before we start averaging. */
- static constexpr uint32_t MIN_PROFILE_DURATION_COUNT = 5;
-
- adaptive_average<uint64_t> sysmem_rp_average;
- adaptive_average<uint64_t> gmem_rp_average;
-
public:
uint64_t hash; /* The hash of the renderpass, just for debug output. */
uint32_t duplicates; /* The amount of times we've seen this RP, used for identifying repeated RPs. */
@@ -801,7 +702,7 @@ struct tu_autotune::rp_history {
std::atomic<uint32_t> refcount = 0; /* Reference count to prevent deletion when active. */
std::atomic<uint64_t> last_use_ts; /* Last time the reference count was updated, in monotonic nanoseconds. */
- rp_history(uint64_t hash): hash(hash), last_use_ts(os_time_get_nano()), profiled(hash)
+ rp_history(uint64_t hash): hash(hash), last_use_ts(os_time_get_nano())
{
}
@@ -876,90 +777,6 @@ struct tu_autotune::rp_history {
}
} bandwidth;
- /** Profiled Algorithms **/
- struct profiled_algo {
- private:
- /* Range [0 (GMEM), 100 (SYSMEM)], where 50 means no preference. */
- constexpr static uint32_t PROBABILITY_MAX = 100, PROBABILITY_MID = 50;
- constexpr static uint32_t PROBABILITY_PREFER_SYSMEM = 80, PROBABILITY_PREFER_GMEM = 20;
-
- std::atomic<uint32_t> sysmem_probability = PROBABILITY_MID;
- bool should_reset = false; /* If true, will reset sysmem_probability before next update. */
- uint64_t seed[2] { 0x3bffb83978e24f88, 0x9238d5d56c71cd35 };
-
- public:
- profiled_algo(uint64_t hash)
- {
- seed[1] = hash;
- }
-
- void update(rp_history &history, bool immediate)
- {
- auto &sysmem_ema = history.sysmem_rp_average;
- auto &gmem_ema = history.gmem_rp_average;
- uint32_t sysmem_prob = sysmem_probability.load(std::memory_order_relaxed);
- if (immediate) {
- /* Try to immediately resolve the probability, this is useful for CI running a single trace of frames where
- * the probabilites aren't expected to change from run to run. This environment also gives us a best case
- * scenario for autotune performance, since we know the optimal decisions.
- */
-
- if (sysmem_prob == 0 || sysmem_prob == 100)
- return; /* Already resolved, no further updates are necessary. */
-
- if (sysmem_ema.count < 1) {
- sysmem_prob = PROBABILITY_MAX;
- } else if (gmem_ema.count < 1) {
- sysmem_prob = 0;
- } else {
- sysmem_prob = gmem_ema.get() < sysmem_ema.get() ? 0 : PROBABILITY_MAX;
- }
- } else {
- if (sysmem_ema.count < MIN_PROFILE_DURATION_COUNT || gmem_ema.count < MIN_PROFILE_DURATION_COUNT) {
- /* Not enough data to make a decision, bias towards least used. */
- sysmem_prob = sysmem_ema.count < gmem_ema.count ? PROBABILITY_PREFER_SYSMEM : PROBABILITY_PREFER_GMEM;
- should_reset = true;
- } else {
- if (should_reset) {
- sysmem_prob = PROBABILITY_MID;
- should_reset = false;
- }
-
- /* Adjust probability based on timing results. */
- constexpr uint32_t STEP_DELTA = 5, MIN_PROBABILITY = 5, MAX_PROBABILITY = 95;
-
- uint64_t avg_sysmem = sysmem_ema.get();
- uint64_t avg_gmem = gmem_ema.get();
- if (avg_gmem < avg_sysmem && sysmem_prob > MIN_PROBABILITY) {
- sysmem_prob = MAX2(sysmem_prob - STEP_DELTA, MIN_PROBABILITY);
- } else if (avg_sysmem < avg_gmem && sysmem_prob < MAX_PROBABILITY) {
- sysmem_prob = MIN2(sysmem_prob + STEP_DELTA, MAX_PROBABILITY);
- }
- }
- }
-
- sysmem_probability.store(sysmem_prob, std::memory_order_relaxed);
-
- at_log_profiled_h("update%s avg_gmem: %" PRIu64 " us (%" PRIu64 " samples) avg_sysmem: %" PRIu64
- " us (%" PRIu64 " samples) = sysmem_probability: %" PRIu32,
- history.hash, immediate ? "-imm" : "", ticks_to_us(gmem_ema.get()), gmem_ema.count,
- ticks_to_us(sysmem_ema.get()), sysmem_ema.count, sysmem_prob);
- }
-
- public:
- render_mode get_optimal_mode(rp_history &history)
- {
- uint32_t l_sysmem_probability = sysmem_probability.load(std::memory_order_relaxed);
- bool select_sysmem = (rand_xorshift128plus(seed) % PROBABILITY_MAX) < l_sysmem_probability;
- render_mode mode = select_sysmem ? render_mode::SYSMEM : render_mode::GMEM;
-
- at_log_profiled_h("%" PRIu32 "%% sysmem chance, using %s", history.hash, l_sysmem_probability,
- render_mode_str(mode));
-
- return mode;
- }
- } profiled;
-
void process(rp_entry &entry, tu_autotune &at)
{
/* We use entry config to know what metrics it has, autotune config to know what algorithms are enabled. */
@@ -968,19 +785,6 @@ struct tu_autotune::rp_history {
if (entry_config.test(metric_flag::SAMPLES) && at_config.is_enabled(algorithm::BANDWIDTH))
bandwidth.update(entry.get_samples_passed());
- if (entry_config.test(metric_flag::TS)) {
- if (entry.sysmem) {
- uint64_t rp_duration = entry.get_rp_duration();
-
- sysmem_rp_average.add(rp_duration);
- } else {
- gmem_rp_average.add(entry.get_rp_duration());
- }
-
- if (at_config.is_enabled(algorithm::PROFILED) || at_config.is_enabled(algorithm::PROFILED_IMM)) {
- profiled.update(*this, at_config.is_enabled(algorithm::PROFILED_IMM));
- }
- }
}
};
@@ -1279,9 +1083,6 @@ tu_autotune::get_optimal_mode(struct tu_cmd_buffer *cmd_buffer, rp_ctx_t *rp_ctx
*rp_ctx = cb_ctx.attach_rp_entry(device, find_or_create_rp_history(key), config, rp_state->drawcall_count);
rp_history &history = *((*rp_ctx)->history);
- if (config.is_enabled(algorithm::PROFILED) || config.is_enabled(algorithm::PROFILED_IMM))
- return history.profiled.get_optimal_mode(history);
-
if (config.is_enabled(algorithm::BANDWIDTH))
return history.bandwidth.get_optimal_mode(history, cmd_state, pass, framebuffer, rp_state);
--
2.54.0