- 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>
360 lines
14 KiB
Diff
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
|
|
|