Compare commits

...

No commits in common. "c8" and "a9-beta" have entirely different histories.
c8 ... a9-beta

34 changed files with 7856 additions and 850 deletions

14
.gitignore vendored
View File

@ -1,3 +1,11 @@
SOURCES/dataclasses-0.8.tar.gz
SOURCES/mesa-23.1.4.tar.xz
SOURCES/meson-0.61.4.tar.gz
SOURCES/llvm-project-22.1.1.src.tar.xz
SOURCES/mesa-26.1.1.tar.xz
SOURCES/meson-1.7.0.tar.gz
SOURCES/paste-1.0.15.tar.gz
SOURCES/proc-macro2-1.0.106.tar.gz
SOURCES/quote-1.0.44.tar.gz
SOURCES/rustc-hash-2.1.1.tar.gz
SOURCES/spirv-llvm-translator-114f5ee.tar.gz
SOURCES/syn-2.0.115.tar.gz
SOURCES/unicode-ident-1.0.23.tar.gz
SOURCES/wayland-protocols-1.41.tar.xz

View File

@ -1,3 +1,11 @@
ef25d3e9e2523805baa314a4adcb915ae901740e SOURCES/dataclasses-0.8.tar.gz
8a48c0e1fbda2c9563ddcf95b05012ab00a8a692 SOURCES/mesa-23.1.4.tar.xz
b0ab169abd8ec87ce773a02b2c7d6a8664b8db00 SOURCES/meson-0.61.4.tar.gz
fe2279ab1dfa6eaa2dfd559aea1cfcfd3ed70031 SOURCES/llvm-project-22.1.1.src.tar.xz
b29f71eabedd45d4527d03f7f64421f6bc6fd157 SOURCES/mesa-26.1.1.tar.xz
df69d7e60fd4d502d2b717b35d35924c017f3068 SOURCES/meson-1.7.0.tar.gz
9daa82dceaa495951cc92ad83879d99cc04969af SOURCES/paste-1.0.15.tar.gz
acc9994d32f3f5e81bc7bf229f350ba058346fa7 SOURCES/proc-macro2-1.0.106.tar.gz
a3db13f0ba7c51093c929aa485bdccfb323834f7 SOURCES/quote-1.0.44.tar.gz
f144c32f41afa29f6e09c0ceefcc458b291c5bff SOURCES/rustc-hash-2.1.1.tar.gz
48568694970d0e8b46c56ed82fbec5e63f21d727 SOURCES/spirv-llvm-translator-114f5ee.tar.gz
3bb713efec1fc6b2213ec71381a25a2a2bfe54f5 SOURCES/syn-2.0.115.tar.gz
ce7416b949bc5155cef6ba79ec7778b0b356fdd8 SOURCES/unicode-ident-1.0.23.tar.gz
523b591f54e788d3117718096228b2cb6e999f2d SOURCES/wayland-protocols-1.41.tar.xz

View File

@ -0,0 +1,255 @@
From 8aee5837d69f15322a5d9ca9a9df4e2dd77554a5 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 19 Jun 2026 13:44:02 +0200
Subject: [PATCH 01/19] Fix build with python 3.9
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
---
meson.build | 2 +-
src/intel/compiler/jay/jay_opcodes.py | 2 +-
src/vulkan/util/vk_cmd_queue_gen.py | 195 +++++++++++++-------------
3 files changed, 99 insertions(+), 100 deletions(-)
diff --git a/meson.build b/meson.build
index 392f147f365..b6aec7f8d93 100644
--- a/meson.build
+++ b/meson.build
@@ -1037,7 +1037,7 @@ endif
# Find a python executable that meets our version requirement.
# - On Windows, a venv has no versioned aliased to 'python'.
# - On RHEL 9, python3 is 3.9, so we must use python3.12.
-python_version_req = '>= 3.10'
+python_version_req = '>= 3.9'
python_exec_list = ['python3.16', 'python3.15', 'python3.14', 'python3.13',
'python3.12', 'python3.11', 'python3.10', 'python3', 'python']
diff --git a/src/intel/compiler/jay/jay_opcodes.py b/src/intel/compiler/jay/jay_opcodes.py
index 029b087ed7c..4951e875ac7 100644
--- a/src/intel/compiler/jay/jay_opcodes.py
+++ b/src/intel/compiler/jay/jay_opcodes.py
@@ -1,6 +1,6 @@
# Copyright 2026 Intel Corporation
# SPDX-License-Identifier: MIT
-
+from __future__ import annotations
from typing import TYPE_CHECKING
from dataclasses import dataclass
import enum
diff --git a/src/vulkan/util/vk_cmd_queue_gen.py b/src/vulkan/util/vk_cmd_queue_gen.py
index 4c74158f11e..2468d9bc098 100644
--- a/src/vulkan/util/vk_cmd_queue_gen.py
+++ b/src/vulkan/util/vk_cmd_queue_gen.py
@@ -644,113 +644,112 @@ def get_param_copy(builder, command, types, src_parent_access, dst_parent_access
src = src_parent_access + param.name
dst = dst_parent_access + (to_field_name(param.name) if dst_snake_case else param.name)
- match categorize_param(command, types, None, param):
- case ParamCategory.ASSIGNABLE:
- builder.add("%s = %s;" % (dst, src))
- case ParamCategory.FLAT_ARRAY:
- builder.add("memcpy(%s, %s, sizeof(*%s) * %s);" % (dst, src, src, get_array_len(param)))
- case ParamCategory.UNSIZED_RAW_POINTER:
- builder.add("%s = (%s)%s;" % (dst, remove_suffix(param.decl.replace("const", ""), param.name), src))
- case ParamCategory.STRING:
- builder.add("%s = linear_strdup(queue->ctx, %s);" % (dst, src))
- case ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE_DATA:
- builder.add("%s = enqueue_push_descriptor_template_data(queue, %sdescriptorUpdateTemplate, %s);" % (dst, src_parent_access, src))
- case ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE:
- builder.add("%s = %s;" % (dst, src))
- builder.add("enqueue_descriptor_template(queue, %s);" % (src))
- case ParamCategory.PIPELINE_LAYOUT:
- builder.add("%s = %s;" % (dst, src))
- builder.add("enqueue_pipeline_layout(queue, %s);" % (src))
- case ParamCategory.STRUCT:
-
- if nullable:
- builder.add("if (%s) {" % (src))
- builder.level += 1
-
- if param.type == "void":
- size = 1
- else:
- size = "sizeof(%s)" % param.type
-
- is_ndarray = param.len and "," in param.len
- if param.len and param.len != "struct-ptr" and not is_ndarray:
- size = "%s * ceil(%s%s)" % (size, src_parent_access, param.len)
-
- builder.add("%s = linear_alloc_child(queue->ctx, %s);" % (dst, size))
- builder.add("if (%s == NULL) return NULL;" % (dst))
- builder.add("memcpy((void *)%s, %s, %s);" % (dst, src, size))
- if param.type == 'VkDescriptorSetLayout':
- array_index = builder.get_variable_name("i")
- builder.add("for (unsigned %s = 0; %s < %s%s; %s++) {" % (array_index, array_index, src_parent_access, param.len, array_index))
- builder.level += 1
- builder.add("enqueue_descriptor_layout(queue, %s[%s]);" % (src, array_index))
- builder.level -= 1
- builder.add("}")
-
- if param.type in types:
- has_explicit_copy = param.type in EXPLICIT_PARAM_COPIES
- needs_member_copy = has_explicit_copy
- for member in types[param.type].members:
- match categorize_param(command, types, param.type, member):
- case ParamCategory.PNEXT | ParamCategory.STRUCT | ParamCategory.STRING:
- needs_member_copy = True
- case ParamCategory.PIPELINE_LAYOUT:
- builder.add("enqueue_pipeline_layout(queue, %s->%s);" % (src, member.name))
- case ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE:
- builder.add("enqueue_descriptor_template(queue, %s->%s);" % (src, member.name))
-
- if needs_member_copy:
+ cat_param = categorize_param(command, types, None, param)
+ if cat_param == ParamCategory.ASSIGNABLE:
+ builder.add("%s = %s;" % (dst, src))
+ elif cat_param == ParamCategory.FLAT_ARRAY:
+ builder.add("memcpy(%s, %s, sizeof(*%s) * %s);" % (dst, src, src, get_array_len(param)))
+ elif cat_param == ParamCategory.UNSIZED_RAW_POINTER:
+ builder.add("%s = (%s)%s;" % (dst, remove_suffix(param.decl.replace("const", ""), param.name), src))
+ elif cat_param == ParamCategory.STRING:
+ builder.add("%s = linear_strdup(queue->ctx, %s);" % (dst, src))
+ elif cat_param == ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE_DATA:
+ builder.add("%s = enqueue_push_descriptor_template_data(queue, %sdescriptorUpdateTemplate, %s);" % (dst, src_parent_access, src))
+ elif cat_param == ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE:
+ builder.add("%s = %s;" % (dst, src))
+ builder.add("enqueue_descriptor_template(queue, %s);" % (src))
+ elif cat_param == ParamCategory.PIPELINE_LAYOUT:
+ builder.add("%s = %s;" % (dst, src))
+ builder.add("enqueue_pipeline_layout(queue, %s);" % (src))
+ elif cat_param == ParamCategory.STRUCT:
+ if nullable:
+ builder.add("if (%s) {" % (src))
+ builder.level += 1
+
+ if param.type == "void":
+ size = 1
+ else:
+ size = "sizeof(%s)" % param.type
+
+ is_ndarray = param.len and "," in param.len
+ if param.len and param.len != "struct-ptr" and not is_ndarray:
+ size = "%s * ceil(%s%s)" % (size, src_parent_access, param.len)
+
+ builder.add("%s = linear_alloc_child(queue->ctx, %s);" % (dst, size))
+ builder.add("if (%s == NULL) return NULL;" % (dst))
+ builder.add("memcpy((void *)%s, %s, %s);" % (dst, src, size))
+ if param.type == 'VkDescriptorSetLayout':
+ array_index = builder.get_variable_name("i")
+ builder.add("for (unsigned %s = 0; %s < %s%s; %s++) {" % (array_index, array_index, src_parent_access, param.len, array_index))
+ builder.level += 1
+ builder.add("enqueue_descriptor_layout(queue, %s[%s]);" % (src, array_index))
+ builder.level -= 1
+ builder.add("}")
+
+ if param.type in types:
+ has_explicit_copy = param.type in EXPLICIT_PARAM_COPIES
+ needs_member_copy = has_explicit_copy
+ for member in types[param.type].members:
+ cat_param_type = categorize_param(command, types, param.type, member)
+ if cat_param_type == ParamCategory.PNEXT or cat_param_type == ParamCategory.STRUCT or cat_param_type == ParamCategory.STRING:
+ needs_member_copy = True
+ elif cat_param_type == ParamCategory.PIPELINE_LAYOUT:
+ builder.add("enqueue_pipeline_layout(queue, %s->%s);" % (src, member.name))
+ elif cat_param_type == ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE:
+ builder.add("enqueue_descriptor_template(queue, %s->%s);" % (src, member.name))
+
+ if needs_member_copy:
+ tmp_dst_name = builder.get_variable_name("tmp_dst")
+ tmp_src_name = builder.get_variable_name("tmp_src")
+
+ builder.add("%s *%s = (void *)%s;" % (param.type, tmp_dst_name, dst))
+ builder.add("%s *%s = (void *)%s;" % (param.type, tmp_src_name, src))
+
+ struct_array_copy = param.len and param.len != "struct-ptr" and param.type != "void"
+ if struct_array_copy:
+ array_index = builder.get_variable_name("i")
+ builder.add("for (uint32_t %s = 0; %s < %s%s; %s++) {" % (array_index, array_index, src_parent_access, param.len, array_index))
+ builder.level += 1
+ prev_tmp_dst_name = tmp_dst_name
+ prev_tmp_src_name = tmp_src_name
tmp_dst_name = builder.get_variable_name("tmp_dst")
tmp_src_name = builder.get_variable_name("tmp_src")
+ builder.add("%s *%s = %s + %s;" % (param.type, tmp_dst_name, prev_tmp_dst_name, array_index))
+ builder.add("%s *%s = %s + %s;" % (param.type, tmp_src_name, prev_tmp_src_name, array_index))
- builder.add("%s *%s = (void *)%s;" % (param.type, tmp_dst_name, dst))
- builder.add("%s *%s = (void *)%s;" % (param.type, tmp_src_name, src))
-
- struct_array_copy = param.len and param.len != "struct-ptr" and param.type != "void"
- if struct_array_copy:
- array_index = builder.get_variable_name("i")
- builder.add("for (uint32_t %s = 0; %s < %s%s; %s++) {" % (array_index, array_index, src_parent_access, param.len, array_index))
- builder.level += 1
- prev_tmp_dst_name = tmp_dst_name
- prev_tmp_src_name = tmp_src_name
- tmp_dst_name = builder.get_variable_name("tmp_dst")
- tmp_src_name = builder.get_variable_name("tmp_src")
- builder.add("%s *%s = %s + %s;" % (param.type, tmp_dst_name, prev_tmp_dst_name, array_index))
- builder.add("%s *%s = %s + %s;" % (param.type, tmp_src_name, prev_tmp_src_name, array_index))
-
+ for member in types[param.type].members:
+ category = categorize_param(command, types, param.type, member)
+ if category == ParamCategory.PNEXT:
+ get_pnext_copy(builder, command, types, param.type, "%s->pNext" % (tmp_src_name), "%s->pNext" % (tmp_dst_name))
+ elif category == ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE_DATA:
+ get_param_copy(builder, command, types, "%s->" % (tmp_src_name), "%s->" % (tmp_dst_name), member, dst_initialized=True)
+
+ if has_explicit_copy:
+ builder.add("enqueue_%s(queue, %s, %s);" % (param.type, tmp_dst_name, tmp_src_name))
+ else:
for member in types[param.type].members:
category = categorize_param(command, types, param.type, member)
- if category == ParamCategory.PNEXT:
- get_pnext_copy(builder, command, types, param.type, "%s->pNext" % (tmp_src_name), "%s->pNext" % (tmp_dst_name))
- elif category == ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE_DATA:
+ if category == ParamCategory.STRUCT or category == ParamCategory.STRING:
get_param_copy(builder, command, types, "%s->" % (tmp_src_name), "%s->" % (tmp_dst_name), member, dst_initialized=True)
- if has_explicit_copy:
- builder.add("enqueue_%s(queue, %s, %s);" % (param.type, tmp_dst_name, tmp_src_name))
- else:
- for member in types[param.type].members:
- category = categorize_param(command, types, param.type, member)
- if category == ParamCategory.STRUCT or category == ParamCategory.STRING:
- get_param_copy(builder, command, types, "%s->" % (tmp_src_name), "%s->" % (tmp_dst_name), member, dst_initialized=True)
-
- if struct_array_copy:
- builder.level -= 1
- builder.add("}")
-
- if nullable:
- builder.level -= 1
- if dst_initialized:
- builder.add("}")
- else:
- builder.add("} else {")
- builder.level += 1
- builder.add("%s = NULL;" % (dst))
+ if struct_array_copy:
builder.level -= 1
builder.add("}")
- case ParamCategory.NULL:
- assert False
- case ParamCategory.PNEXT:
- assert False
+
+ if nullable:
+ builder.level -= 1
+ if dst_initialized:
+ builder.add("}")
+ else:
+ builder.add("} else {")
+ builder.level += 1
+ builder.add("%s = NULL;" % (dst))
+ builder.level -= 1
+ builder.add("}")
+ elif cat_param == ParamCategory.NULL:
+ assert False
+ elif cat_param == ParamCategory.PNEXT:
+ assert False
def get_params_copy(command, types):
builder = CodeBuilder(1)
--
2.54.0

View File

@ -1,127 +0,0 @@
From 2d4fe5f229791fde52846b3f583c12508b5109d6 Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Fri, 25 Aug 2023 12:43:44 +1000
Subject: [PATCH] clover/llvm: move to modern pass manager.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This seems like it should work, but I haven't tested it yet.
Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24879>
---
.../frontends/clover/llvm/invocation.cpp | 64 +++++++++++++++----
1 file changed, 51 insertions(+), 13 deletions(-)
diff --git a/src/gallium/frontends/clover/llvm/invocation.cpp b/src/gallium/frontends/clover/llvm/invocation.cpp
index 7a50fea3323..43d26fe1abb 100644
--- a/src/gallium/frontends/clover/llvm/invocation.cpp
+++ b/src/gallium/frontends/clover/llvm/invocation.cpp
@@ -27,13 +27,17 @@
#include <llvm/IR/DiagnosticPrinter.h>
#include <llvm/IR/DiagnosticInfo.h>
#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/Module.h>
#include <llvm/Support/raw_ostream.h>
-#include <llvm/Transforms/IPO/PassManagerBuilder.h>
+#include <llvm/Transforms/IPO/Internalize.h>
#include <llvm-c/Target.h>
#ifdef HAVE_CLOVER_SPIRV
#include <LLVMSPIRVLib/LLVMSPIRVLib.h>
#endif
+#include <llvm-c/TargetMachine.h>
+#include <llvm-c/Transforms/PassBuilder.h>
+#include <llvm/Support/CBindingWrapping.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Lex/PreprocessorOptions.h>
#include <clang/Frontend/TextDiagnosticBuffer.h>
@@ -439,10 +443,10 @@ clover::llvm::compile_program(const std::string &source,
namespace {
void
- optimize(Module &mod, unsigned optimization_level,
+ optimize(Module &mod,
+ const std::string& ir_target,
+ unsigned optimization_level,
bool internalize_symbols) {
- ::llvm::legacy::PassManager pm;
-
// By default, the function internalizer pass will look for a function
// called "main" and then mark all other functions as internal. Marking
// functions as internal enables the optimizer to perform optimizations
@@ -458,19 +462,53 @@ namespace {
if (internalize_symbols) {
std::vector<std::string> names =
map(std::mem_fn(&Function::getName), get_kernels(mod));
- pm.add(::llvm::createInternalizePass(
+ internalizeModule(mod,
[=](const ::llvm::GlobalValue &gv) {
return std::find(names.begin(), names.end(),
gv.getName()) != names.end();
- }));
+ });
}
- ::llvm::PassManagerBuilder pmb;
- pmb.OptLevel = optimization_level;
- pmb.LibraryInfo = new ::llvm::TargetLibraryInfoImpl(
- ::llvm::Triple(mod.getTargetTriple()));
- pmb.populateModulePassManager(pm);
- pm.run(mod);
+
+ const char *opt_str = NULL;
+ LLVMCodeGenOptLevel level;
+ switch (optimization_level) {
+ case 0:
+ default:
+ opt_str = "default<O0>";
+ level = LLVMCodeGenLevelNone;
+ break;
+ case 1:
+ opt_str = "default<O1>";
+ level = LLVMCodeGenLevelLess;
+ break;
+ case 2:
+ opt_str = "default<O2>";
+ level = LLVMCodeGenLevelDefault;
+ break;
+ case 3:
+ opt_str = "default<O3>";
+ level = LLVMCodeGenLevelAggressive;
+ break;
+ }
+
+ const target &target = ir_target;
+ LLVMTargetRef targ;
+ char *err_message;
+
+ if (LLVMGetTargetFromTriple(target.triple.c_str(), &targ, &err_message))
+ return;
+ LLVMTargetMachineRef tm =
+ LLVMCreateTargetMachine(targ, target.triple.c_str(),
+ target.cpu.c_str(), "", level,
+ LLVMRelocDefault, LLVMCodeModelDefault);
+
+ if (!tm)
+ return;
+ LLVMPassBuilderOptionsRef opts = LLVMCreatePassBuilderOptions();
+ LLVMRunPasses(wrap(&mod), opt_str, tm, opts);
+
+ LLVMDisposeTargetMachine(tm);
}
std::unique_ptr<Module>
@@ -500,7 +538,7 @@ clover::llvm::link_program(const std::vector<binary> &binaries,
auto c = create_compiler_instance(dev, dev.ir_target(), options, r_log);
auto mod = link(*ctx, *c, binaries, r_log);
- optimize(*mod, c->getCodeGenOpts().OptimizationLevel, !create_library);
+ optimize(*mod, dev.ir_target(), c->getCodeGenOpts().OptimizationLevel, !create_library);
static std::atomic_uint seq(0);
const std::string id = "." + mod->getModuleIdentifier() + "-" +
--
2.42.0

View File

@ -1,41 +0,0 @@
From 9ba416cdc67073cdda9a73fe9d37304b82bdd526 Mon Sep 17 00:00:00 2001
From: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Date: Fri, 12 May 2023 09:58:26 +0200
Subject: [PATCH] llvmpipe: only include old Transform includes when needed
This fixes building with recent LLVM where these 2 .h files
were removed.
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/8671
Acked-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22980>
---
src/gallium/auxiliary/gallivm/lp_bld_init.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_init.c b/src/gallium/auxiliary/gallivm/lp_bld_init.c
index 24d082398e9..9e0d6a5f643 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_init.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_init.c
@@ -42,14 +42,14 @@
#include <llvm/Config/llvm-config.h>
#include <llvm-c/Analysis.h>
-#include <llvm-c/Transforms/Scalar.h>
-#if LLVM_VERSION_MAJOR >= 7
-#include <llvm-c/Transforms/Utils.h>
-#endif
#include <llvm-c/BitWriter.h>
#if GALLIVM_USE_NEW_PASS == 1
#include <llvm-c/Transforms/PassBuilder.h>
#elif GALLIVM_HAVE_CORO == 1
+#include <llvm-c/Transforms/Scalar.h>
+#if LLVM_VERSION_MAJOR >= 7
+#include <llvm-c/Transforms/Utils.h>
+#endif
#if LLVM_VERSION_MAJOR <= 8 && (DETECT_ARCH_AARCH64 || DETECT_ARCH_ARM || DETECT_ARCH_S390 || DETECT_ARCH_MIPS64)
#include <llvm-c/Transforms/IPO.h>
#endif
--
2.42.0

View File

@ -1,28 +0,0 @@
From 460d2c46a903fed295a1528c8b6273dd6b0e0d19 Mon Sep 17 00:00:00 2001
From: thfrwn <11335318+rfht@users.noreply.github.com>
Date: Fri, 9 Feb 2024 17:00:55 -0500
Subject: [PATCH] mesa: fix off-by-one for newblock allocation in dlist_alloc
Cc: mesa-stable
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27556>
---
src/mesa/main/dlist.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index b0184a24e20..9213641699a 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -1220,7 +1220,7 @@ dlist_alloc(struct gl_context *ctx, OpCode opcode, GLuint bytes, bool align8)
ctx->ListState.CurrentPos++;
}
- if (ctx->ListState.CurrentPos + numNodes + contNodes > BLOCK_SIZE) {
+ if (ctx->ListState.CurrentPos + numNodes + contNodes >= BLOCK_SIZE) {
/* This block is full. Allocate a new block and chain to it */
Node *newblock;
Node *n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
--
2.45.2

View File

@ -1,37 +0,0 @@
From f7434d7576032cf97e3c74ef09912f59617a4bad Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Fri, 14 Jun 2024 12:22:58 +1000
Subject: [PATCH] nouveau/nvc0: increase overallocation on shader bo to 2K
I've been seeing a bunch of read page faults at the end of the
shader allocation, nvk uses a full page at the end to overallocate
so align with that and see if it goes away.
ahulliet and skeggsb both said 2k was used.
Cc: mesa-stable
Reviewed-by: Arthur Huillet <ahuillet@nvidia.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29722>
---
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff -up mesa-23.1.4/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c.dma mesa-23.1.4/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
--- mesa-23.1.4/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c.dma 2023-07-21 22:42:42.000000000 +1000
+++ mesa-23.1.4/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c 2024-08-16 12:49:13.532998512 +1000
@@ -886,10 +886,11 @@ nvc0_screen_resize_text_area(struct nvc0
nouveau_heap_free(&screen->lib_code);
nouveau_heap_destroy(&screen->text_heap);
- /* XXX: getting a page fault at the end of the code buffer every few
- * launches, don't use the last 256 bytes to work around them - prefetch ?
+ /*
+ * Shader storage needs a 2K (from NVIDIA) overallocations at the end
+ * to avoid prefetch bugs.
*/
- nouveau_heap_init(&screen->text_heap, 0, size - 0x100);
+ nouveau_heap_init(&screen->text_heap, 0, size - 0x800);
/* update the code segment setup */
if (screen->eng3d->oclass < GV100_3D_CLASS) {

View File

@ -0,0 +1,36 @@
From af7ed267f67b024829c391f9016d0fb7ca18cecc Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Wed, 24 Jun 2026 11:42:19 +0200
Subject: [PATCH 02/19] Fix enum
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
---
src/intel/compiler/jay/jay_ir.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/intel/compiler/jay/jay_ir.h b/src/intel/compiler/jay/jay_ir.h
index 8307044ef8a..afd923062ca 100644
--- a/src/intel/compiler/jay/jay_ir.h
+++ b/src/intel/compiler/jay/jay_ir.h
@@ -579,7 +579,8 @@ jay_type_is_any_float(enum jay_type t)
return jay_base_type(t) == JAY_TYPE_F || jay_base_type(t) == JAY_TYPE_BF;
}
-enum jay_predication : uint8_t {
+typedef uint8_t jay_predication;
+enum {
/** No predication. */
JAY_NOT_PREDICATED = 0,
@@ -634,7 +635,7 @@ typedef struct jay_inst {
bool decrement_dep:1;
unsigned padding :12;
- enum jay_predication predication;
+ jay_predication predication;
enum jay_conditional_mod conditional_mod;
jay_def cond_flag; /**< conditional flag */
--
2.54.0

View File

@ -0,0 +1,40 @@
From 1d770a0fb463c03f7e4a1b0627b4af98a8789ad0 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 10:53:05 +0200
Subject: [PATCH 03/19] Revert "tu/autotune: Clear active_batches before
history objects are freed"
This reverts commit 42df4a7e416b387e06a67173e67ed6de1bfd6c5b.
---
.pick_status.json | 2 +-
src/freedreno/vulkan/tu_autotune.cc | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/.pick_status.json b/.pick_status.json
index 69436008ada..aeb82c74693 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -3314,7 +3314,7 @@
"description": "tu/autotune: Clear active_batches before history objects are freed",
"nominated": true,
"nomination_type": 2,
- "resolution": 1,
+ "resolution": 0,
"main_sha": null,
"because_sha": "40ffc052afff7a40da99b398c09594c3ff2d40ed",
"notes": null
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index 820a655b2fc..028e9282227 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -1698,7 +1698,6 @@ tu_autotune::~tu_autotune()
at_log_base("finished processing all entries");
}
- active_batches.clear();
tu_bo_suballocator_finish(&suballoc);
}
--
2.54.0

View File

@ -0,0 +1,52 @@
From d5561b08593b59df1f2bdc82a676fb565b84ef56 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 10:53:27 +0200
Subject: [PATCH 04/19] Revert "tu/autotune: Allocate performance counters from
low-to-high"
This reverts commit 203ae3509166ebb5076bdc0df28dbb30062c4dfd.
---
.pick_status.json | 2 +-
src/freedreno/vulkan/tu_autotune.cc | 10 ++++++----
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/.pick_status.json b/.pick_status.json
index aeb82c74693..e04710b3344 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -13964,7 +13964,7 @@
"description": "tu/autotune: Allocate performance counters from low-to-high",
"nominated": true,
"nomination_type": 1,
- "resolution": 1,
+ "resolution": 0,
"main_sha": null,
"because_sha": null,
"notes": null
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index 028e9282227..2dd5017b11b 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -1660,13 +1660,15 @@ tu_autotune::tu_autotune(struct tu_device *device, VkResult &result)
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) {
- preemption_latency_selector_reg = cp_group->counters[0].select_reg;
+ 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[0].counter_reg_lo;
+ preemption_latency_counter_reg_lo = cp_group->counters[preemption_latency_counter_index].counter_reg_lo;
- always_count_selector_reg = cp_group->counters[1].select_reg;
+ 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[1].counter_reg_lo;
+ 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";
}
--
2.54.0

View File

@ -0,0 +1,149 @@
From e9862fcd366d761f131865b390bde72157983a24 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 10:53:34 +0200
Subject: [PATCH 05/19] Revert "tu/autotune: Fail gracefully when CP counters
are unavailable"
This reverts commit 920a84802792cea85d752518a20881f1f6be110d.
---
.pick_status.json | 2 +-
src/freedreno/vulkan/tu_autotune.cc | 90 ++++++++++++++---------------
src/freedreno/vulkan/tu_autotune.h | 1 +
3 files changed, 45 insertions(+), 48 deletions(-)
diff --git a/.pick_status.json b/.pick_status.json
index e04710b3344..c54f039590a 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -13984,7 +13984,7 @@
"description": "tu/autotune: Fail gracefully when CP counters are unavailable",
"nominated": true,
"nomination_type": 1,
- "resolution": 1,
+ "resolution": 0,
"main_sha": null,
"because_sha": null,
"notes": null
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index 2dd5017b11b..e1e4666768c 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -1632,60 +1632,56 @@ 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");
- if (supports_preempt_latency_tracking()) {
- uint32_t group_count;
- const struct fd_perfcntr_group *groups = fd_perfcntrs(&device->physical_device->dev_id, &group_count);
- const char *fail_reason = nullptr;
-
- 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 group_count;
+ const struct fd_perfcntr_group *groups = fd_perfcntrs(&device->physical_device->dev_id, &group_count);
- 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];
- }
+ for (uint32_t i = 0; i < group_count; i++) {
+ if (strcmp(groups[i].name, "CP") == 0) {
+ cp_group = &groups[i];
+ break;
+ }
+ }
- return nullptr;
- };
+ 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 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";
+ 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];
}
- 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);
+ mesa_loge("autotune: %s not found in group %s", name, group->name);
+ return nullptr;
+ };
- supported_mod_flags &= ~((uint32_t) mod_flag::PREEMPT_OPTIMIZE);
- disable_preempt_optimize();
+ 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");
+
+ 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;
}
+
+ 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;
}
result = VK_SUCCESS;
diff --git a/src/freedreno/vulkan/tu_autotune.h b/src/freedreno/vulkan/tu_autotune.h
index 55e579ae93a..aba8d3e6f95 100644
--- a/src/freedreno/vulkan/tu_autotune.h
+++ b/src/freedreno/vulkan/tu_autotune.h
@@ -242,6 +242,7 @@ 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;
--
2.54.0

View File

@ -0,0 +1,53 @@
From 59621a3e812fbc8267ebfb03001c82eff48cc86a Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 10:54:40 +0200
Subject: [PATCH 06/19] Revert "tu/autotune: Only lock RPs sustain certain mode
for 30s"
This reverts commit da089bf741b3c06fa7ae21c2a349f4f96d5c6230.
---
src/freedreno/vulkan/tu_autotune.cc | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index e1e4666768c..338f2b68018 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -1060,9 +1060,6 @@ struct tu_autotune::rp_history {
bool locked = false; /* If true, the probability will no longer be updated. */
uint64_t seed[2] { 0x3bffb83978e24f88, 0x9238d5d56c71cd35 };
- bool is_sysmem_winning = false;
- uint64_t winning_since_ts = 0;
-
public:
profiled_algo(uint64_t hash)
{
@@ -1129,15 +1126,6 @@ struct tu_autotune::rp_history {
constexpr uint32_t MIN_LOCK_DURATION_COUNT = 15;
constexpr uint64_t MIN_LOCK_THRESHOLD = GPU_TICKS_PER_US * 1'000; /* 1ms */
constexpr uint32_t LOCK_PERCENT_DIFF = 30;
- constexpr uint64_t LOCK_TIME_WINDOW_NS = 30'000'000'000; /* 30s */
-
- uint64_t now = os_time_get_nano();
- bool current_sysmem_winning = avg_sysmem < avg_gmem;
-
- if (winning_since_ts == 0 || current_sysmem_winning != is_sysmem_winning) {
- winning_since_ts = now;
- is_sysmem_winning = current_sysmem_winning;
- }
bool has_resolved = sysmem_prob == SLOW_MAX_PROBABILITY || sysmem_prob == SLOW_MIN_PROBABILITY;
bool enough_samples =
@@ -1147,7 +1135,7 @@ struct tu_autotune::rp_history {
uint64_t percent_diff = (100 * (max_avg - min_avg)) / min_avg;
if (has_resolved && enough_samples && max_avg >= MIN_LOCK_THRESHOLD &&
- percent_diff >= LOCK_PERCENT_DIFF && (now - winning_since_ts) >= LOCK_TIME_WINDOW_NS) {
+ percent_diff >= LOCK_PERCENT_DIFF) {
if (avg_gmem < avg_sysmem)
sysmem_prob = 0;
else
--
2.54.0

View File

@ -0,0 +1,56 @@
From 2fa8853519888429f653daf491a0f4b78c3f6081 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 10:54:57 +0200
Subject: [PATCH 07/19] Revert "tu/autotune: Allow 99% max probability in
profiled mode"
This reverts commit c725f2aea31dccb4d6b027d44c5dd464a23f391b.
---
src/freedreno/vulkan/tu_autotune.cc | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index 338f2b68018..cededf09497 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -1100,22 +1100,16 @@ struct tu_autotune::rp_history {
}
/* Adjust probability based on timing results. */
- constexpr uint32_t FAST_STEP_DELTA = 5, FAST_MIN_PROBABILITY = 5, FAST_MAX_PROBABILITY = 95;
- constexpr uint32_t SLOW_STEP_DELTA = 1, SLOW_MIN_PROBABILITY = 1, SLOW_MAX_PROBABILITY = 99;
+ constexpr uint32_t STEP_DELTA = 5; /* 5% */
+ constexpr uint32_t MIN_PROB = 5, MAX_PROB = 95;
uint64_t avg_sysmem = sysmem_ema.get();
uint64_t avg_gmem = gmem_ema.get();
- if (avg_gmem < avg_sysmem) {
- if (sysmem_prob > FAST_MIN_PROBABILITY && sysmem_prob <= FAST_MAX_PROBABILITY)
- sysmem_prob = MAX2(sysmem_prob - FAST_STEP_DELTA, FAST_MIN_PROBABILITY);
- else if (sysmem_prob > SLOW_MIN_PROBABILITY)
- sysmem_prob = MAX2(sysmem_prob - SLOW_STEP_DELTA, SLOW_MIN_PROBABILITY);
- } else if (avg_sysmem < avg_gmem) {
- if (sysmem_prob >= FAST_MIN_PROBABILITY && sysmem_prob < FAST_MAX_PROBABILITY)
- sysmem_prob = MIN2(sysmem_prob + FAST_STEP_DELTA, FAST_MAX_PROBABILITY);
- else if (sysmem_prob < SLOW_MAX_PROBABILITY)
- sysmem_prob = MIN2(sysmem_prob + SLOW_STEP_DELTA, SLOW_MAX_PROBABILITY);
+ if (avg_gmem < avg_sysmem && sysmem_prob > MIN_PROB) {
+ sysmem_prob = MAX2(sysmem_prob - STEP_DELTA, MIN_PROB);
+ } else if (avg_sysmem < avg_gmem && sysmem_prob < MAX_PROB) {
+ sysmem_prob = MIN2(sysmem_prob + STEP_DELTA, MAX_PROB);
}
/* If the RP duration exceeds a certain minimum duration threshold (i.e. has a large impact on frametime)
@@ -1127,7 +1121,7 @@ struct tu_autotune::rp_history {
constexpr uint64_t MIN_LOCK_THRESHOLD = GPU_TICKS_PER_US * 1'000; /* 1ms */
constexpr uint32_t LOCK_PERCENT_DIFF = 30;
- bool has_resolved = sysmem_prob == SLOW_MAX_PROBABILITY || sysmem_prob == SLOW_MIN_PROBABILITY;
+ bool has_resolved = sysmem_prob == MAX_PROB || sysmem_prob == MIN_PROB;
bool enough_samples =
sysmem_ema.count >= MIN_LOCK_DURATION_COUNT && gmem_ema.count >= MIN_LOCK_DURATION_COUNT;
uint64_t min_avg = MIN2(avg_sysmem, avg_gmem);
--
2.54.0

View File

@ -0,0 +1,112 @@
From 978eda7888fde320c31647257cc2c521af7152cb Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 10:55:06 +0200
Subject: [PATCH 08/19] Revert "tu/autotune: Add render mode locking to
PROFILED algorithm"
This reverts commit 3b3ae477f3fe9cff421bb11f272cbc099c7ede56.
---
src/freedreno/vulkan/tu_autotune.cc | 49 ++++++-----------------------
1 file changed, 10 insertions(+), 39 deletions(-)
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index cededf09497..202e68c3a1a 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -1057,7 +1057,6 @@ struct tu_autotune::rp_history {
std::atomic<uint32_t> sysmem_probability = PROBABILITY_MID;
bool should_reset = false; /* If true, will reset sysmem_probability before next update. */
- bool locked = false; /* If true, the probability will no longer be updated. */
uint64_t seed[2] { 0x3bffb83978e24f88, 0x9238d5d56c71cd35 };
public:
@@ -1068,9 +1067,6 @@ struct tu_autotune::rp_history {
void update(rp_history &history, bool immediate)
{
- if (locked)
- return;
-
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);
@@ -1080,13 +1076,15 @@ struct tu_autotune::rp_history {
* 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;
- locked = true;
}
} else {
if (sysmem_ema.count < MIN_PROFILE_DURATION_COUNT || gmem_ema.count < MIN_PROFILE_DURATION_COUNT) {
@@ -1100,41 +1098,14 @@ struct tu_autotune::rp_history {
}
/* Adjust probability based on timing results. */
- constexpr uint32_t STEP_DELTA = 5; /* 5% */
- constexpr uint32_t MIN_PROB = 5, MAX_PROB = 95;
+ 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_PROB) {
- sysmem_prob = MAX2(sysmem_prob - STEP_DELTA, MIN_PROB);
- } else if (avg_sysmem < avg_gmem && sysmem_prob < MAX_PROB) {
- sysmem_prob = MIN2(sysmem_prob + STEP_DELTA, MAX_PROB);
- }
-
- /* If the RP duration exceeds a certain minimum duration threshold (i.e. has a large impact on frametime)
- * and the percentage difference between the modes is large enough, we lock into the optimal mode. This
- * avoids performance hazards from switching to an extremely suboptimal mode even if done very rarely.
- * Note: Due to the potentially huge negative impact of a bad lock, this is a very conservative check.
- */
- constexpr uint32_t MIN_LOCK_DURATION_COUNT = 15;
- constexpr uint64_t MIN_LOCK_THRESHOLD = GPU_TICKS_PER_US * 1'000; /* 1ms */
- constexpr uint32_t LOCK_PERCENT_DIFF = 30;
-
- bool has_resolved = sysmem_prob == MAX_PROB || sysmem_prob == MIN_PROB;
- bool enough_samples =
- sysmem_ema.count >= MIN_LOCK_DURATION_COUNT && gmem_ema.count >= MIN_LOCK_DURATION_COUNT;
- uint64_t min_avg = MIN2(avg_sysmem, avg_gmem);
- uint64_t max_avg = MAX2(avg_sysmem, avg_gmem);
- uint64_t percent_diff = (100 * (max_avg - min_avg)) / min_avg;
-
- if (has_resolved && enough_samples && max_avg >= MIN_LOCK_THRESHOLD &&
- percent_diff >= LOCK_PERCENT_DIFF) {
- if (avg_gmem < avg_sysmem)
- sysmem_prob = 0;
- else
- sysmem_prob = 100;
- locked = true;
+ 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);
}
}
}
@@ -1142,9 +1113,9 @@ struct tu_autotune::rp_history {
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 " locked: %u",
+ " 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, locked);
+ ticks_to_us(sysmem_ema.get()), sysmem_ema.count, sysmem_prob);
}
public:
--
2.54.0

View File

@ -0,0 +1,119 @@
From 4f7224ba2f0991d5773d83dd4a55ac2e6368d383 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 10:55:18 +0200
Subject: [PATCH 09/19] Revert "tu+util: Allow setting autotune mode from
driconf"
This reverts commit ed643d1766dbc16ce9a7457a4f93e1af1b5b3a07.
---
docs/drivers/freedreno.rst | 2 --
src/freedreno/vulkan/tu_autotune.cc | 15 +++++----------
src/freedreno/vulkan/tu_device.cc | 3 ---
src/freedreno/vulkan/tu_device.h | 3 ---
src/util/driconf.h | 4 ----
5 files changed, 5 insertions(+), 22 deletions(-)
diff --git a/docs/drivers/freedreno.rst b/docs/drivers/freedreno.rst
index 60ab3e98c11..90afea283a4 100644
--- a/docs/drivers/freedreno.rst
+++ b/docs/drivers/freedreno.rst
@@ -707,8 +707,6 @@ environment variables:
in some high-confidence cases as well as letting ``TU_AUTOTUNE_FLAGS`` still
be applied.
- The algorithm can be set via the driconf option ``tu_autotune_algorithm`` as well.
-
.. 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 202e68c3a1a..b57c393e06e 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -273,16 +273,11 @@ tu_autotune::get_env_config()
static std::once_flag once;
static config_t at_config;
std::call_once(once, [&] {
+ const char *algo_env_str = os_get_option("TU_AUTOTUNE_ALGO");
algorithm algo = algorithm::DEFAULT;
- const char *algo_str = os_get_option("TU_AUTOTUNE_ALGO");
- std::string_view algo_strv;
- if (algo_str)
- algo_strv = algo_str;
- else if (device->instance->autotune_algo)
- algo_strv = device->instance->autotune_algo;
-
- if (!algo_strv.empty()) {
+ if (algo_env_str) {
+ std::string_view algo_strv(algo_env_str);
if (algo_strv == "bandwidth") {
algo = algorithm::BANDWIDTH;
} else if (algo_strv == "profiled") {
@@ -294,11 +289,11 @@ tu_autotune::get_env_config()
} else if (algo_strv == "prefer_gmem") {
algo = algorithm::PREFER_GMEM;
} else {
- mesa_logw("Unknown TU_AUTOTUNE_ALGO '%s', using default", algo_strv.data());
+ mesa_logw("Unknown TU_AUTOTUNE_ALGO '%s', using default", algo_env_str);
}
if (TU_DEBUG(STARTUP))
- mesa_logi("TU_AUTOTUNE_ALGO=%u (%s)", (uint8_t) algo, algo_strv.data());
+ mesa_logi("TU_AUTOTUNE_ALGO=%u (%s)", (uint8_t) algo, algo_env_str);
}
/* Parse the flags from the environment variable. */
diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc
index a41b93c4948..25e11d45f8f 100644
--- a/src/freedreno/vulkan/tu_device.cc
+++ b/src/freedreno/vulkan/tu_device.cc
@@ -1840,7 +1840,6 @@ static const driOptionDescription tu_dri_options[] = {
DRI_CONF_TU_IGNORE_FRAG_DEPTH_DIRECTION(false)
DRI_CONF_TU_ENABLE_SOFTFLOAT32(false)
DRI_CONF_TU_EMULATE_ALPHA_TO_COVERAGE(false)
- DRI_CONF_TU_AUTOTUNE_ALGORITHM()
DRI_CONF_SECTION_END
};
@@ -1873,8 +1872,6 @@ tu_init_dri_options(struct tu_instance *instance)
driQueryOptionb(&instance->dri_options, "tu_enable_softfloat32");
instance->emulate_alpha_to_coverage =
driQueryOptionb(&instance->dri_options, "tu_emulate_alpha_to_coverage");
- instance->autotune_algo =
- driQueryOptionstr(&instance->dri_options, "tu_autotune_algorithm");
}
static uint32_t instance_count = 0;
diff --git a/src/freedreno/vulkan/tu_device.h b/src/freedreno/vulkan/tu_device.h
index c9f521fcc15..b0ecf2f62ba 100644
--- a/src/freedreno/vulkan/tu_device.h
+++ b/src/freedreno/vulkan/tu_device.h
@@ -237,9 +237,6 @@ struct tu_instance
* instead.
*/
bool emulate_alpha_to_coverage;
-
- /* Configuration option to use a specific autotune algorithm by default. */
- const char *autotune_algo;
};
VK_DEFINE_HANDLE_CASTS(tu_instance, vk.base, VkInstance,
VK_OBJECT_TYPE_INSTANCE)
diff --git a/src/util/driconf.h b/src/util/driconf.h
index 5a73c15ac2f..a0b5e40af0b 100644
--- a/src/util/driconf.h
+++ b/src/util/driconf.h
@@ -692,10 +692,6 @@
DRI_CONF_OPT_B(tu_emulate_alpha_to_coverage, def, \
"Enable emulation of alpha-to-coverage")
-#define DRI_CONF_TU_AUTOTUNE_ALGORITHM() \
- DRI_CONF_OPT_S_NODEF(tu_autotune_algorithm, \
- "Set the preferred autotune algorithm")
-
/**
* \brief Honeykrisp specific configuration options
*/
--
2.54.0

View File

@ -0,0 +1,85 @@
From dad9e8d8725004cb48a0f56982223b5c5a43f765 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 10:55:26 +0200
Subject: [PATCH 10/19] Revert "tu/autotune: Add prefer SYSMEM/GMEM mode"
This reverts commit 180c0de74600079795001993feb31bafb9ba0488.
---
docs/drivers/freedreno.rst | 8 --------
src/freedreno/vulkan/tu_autotune.cc | 19 ++++---------------
2 files changed, 4 insertions(+), 23 deletions(-)
diff --git a/docs/drivers/freedreno.rst b/docs/drivers/freedreno.rst
index 90afea283a4..e5adeeb5e68 100644
--- a/docs/drivers/freedreno.rst
+++ b/docs/drivers/freedreno.rst
@@ -699,14 +699,6 @@ environment variables:
for single-frame traces run multiple times in a CI where this algorithm can
immediately chose the optimal rendering mode for each RP.
- ``prefer_sysmem``/``prefer_gmem``
- Always chooses SYSMEM/GMEM rendering. This is useful for games that work
- better in one mode over the other due to their rendering patterns, setting
- this is better than using ``TU_DEBUG=sysmem``/``TU_DEBUG=gmem`` when done
- for performance reasons, since these still allow the other mode to be used
- in some high-confidence cases as well as letting ``TU_AUTOTUNE_FLAGS`` still
- be applied.
-
.. 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 b57c393e06e..99ad1d495d5 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -94,11 +94,9 @@ render_mode_str(tu_autotune::render_mode mode)
/** Configuration **/
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. */
- PREFER_SYSMEM = 3, /* Always use SYSMEM unless we have strong evidence that GMEM is better. */
- PREFER_GMEM = 4, /* Always use GMEM unless we have strong evidence that SYSMEM is better. */
+ 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. */
};
@@ -209,8 +207,6 @@ struct PACKED tu_autotune::config_t {
ALGO_STR(BANDWIDTH);
ALGO_STR(PROFILED);
ALGO_STR(PROFILED_IMM);
- ALGO_STR(PREFER_SYSMEM);
- ALGO_STR(PREFER_GMEM);
str += ", Mod Flags: 0x" + std::to_string(mod_flags) + " (";
MODF_STR(BIG_GMEM);
@@ -284,10 +280,6 @@ tu_autotune::get_env_config()
algo = algorithm::PROFILED;
} else if (algo_strv == "profiled_imm") {
algo = algorithm::PROFILED_IMM;
- } else if (algo_strv == "prefer_sysmem") {
- algo = algorithm::PREFER_SYSMEM;
- } else if (algo_strv == "prefer_gmem") {
- algo = algorithm::PREFER_GMEM;
} else {
mesa_logw("Unknown TU_AUTOTUNE_ALGO '%s', using default", algo_env_str);
}
@@ -1780,11 +1772,8 @@ tu_autotune::get_optimal_mode(struct tu_cmd_buffer *cmd_buffer, rp_ctx_t *rp_ctx
*/
bool can_early_return = !config.test(mod_flag::PREEMPT_OPTIMIZE);
auto early_return_mode = [&]() -> std::optional<render_mode> {
- if ((config.test(mod_flag::BIG_GMEM) && rp_state->drawcall_count >= 10) ||
- config.is_enabled(algorithm::PREFER_GMEM))
+ if (config.test(mod_flag::BIG_GMEM) && rp_state->drawcall_count >= 10)
return render_mode::GMEM;
- if (config.is_enabled(algorithm::PREFER_SYSMEM))
- return render_mode::SYSMEM;
return std::nullopt;
}();
--
2.54.0

View File

@ -0,0 +1,88 @@
From f514b4c856c652c2c959f8a0cb1f215c191b1d10 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 11:01:43 +0200
Subject: [PATCH 11/19] Revert "tu: Only emit preempt optimization ambles when
active"
This reverts commit 46aac5abaf0fb6382ad5d497d6cf0974fb6e1d84.
---
src/freedreno/vulkan/tu_autotune.cc | 6 ++----
src/freedreno/vulkan/tu_autotune.h | 3 +--
src/freedreno/vulkan/tu_cmd_buffer.cc | 6 +++---
3 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index 99ad1d495d5..c456c248cdb 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -2119,11 +2119,11 @@ tu_autotune::emit_reset_rp_hash_draw_state(struct tu_cmd_buffer *cmd, struct tu_
tu_cs_emit_qw(cs, reset_rp_hash_draw_state.iova);
}
-bool
+void
tu_autotune::emit_preempt_latency_tracking_setup(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
{
if (!cmd->autotune_ctx.tracks_preempt_latency())
- return false;
+ return;
tu_cs_emit_pkt7(cs, CP_MEM_WRITE, 4);
tu_cs_emit_qw(cs, global_iova(cmd, max_preemption_latency));
@@ -2143,8 +2143,6 @@ tu_autotune::emit_preempt_latency_tracking_setup(struct tu_cmd_buffer *cmd, stru
write_preempt_counters_to_iova(cs, true, true, global_iova(cmd, base_preemption_latency),
global_iova(cmd, base_always_count), global_iova(cmd, base_aon));
-
- return true;
}
tu_autotune::rp_key_opt
diff --git a/src/freedreno/vulkan/tu_autotune.h b/src/freedreno/vulkan/tu_autotune.h
index aba8d3e6f95..868c06bb7d6 100644
--- a/src/freedreno/vulkan/tu_autotune.h
+++ b/src/freedreno/vulkan/tu_autotune.h
@@ -355,8 +355,7 @@ struct tu_autotune {
void init_reset_rp_hash_draw_state();
void emit_reset_rp_hash_draw_state(struct tu_cmd_buffer *cmd, struct tu_cs *cs) const;
- /* Returns if preemption latency tracking is enabled for this CB. */
- bool emit_preempt_latency_tracking_setup(struct tu_cmd_buffer *cmd, struct tu_cs *cs);
+ void emit_preempt_latency_tracking_setup(struct tu_cmd_buffer *cmd, struct tu_cs *cs);
/* Returns the RP hash only when preemption latency tracking is enabled. */
rp_key_opt emit_preempt_latency_tracking_rp_hash(struct tu_cmd_buffer *cmd);
};
diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc
index 082825fa84b..c345564dee7 100644
--- a/src/freedreno/vulkan/tu_cmd_buffer.cc
+++ b/src/freedreno/vulkan/tu_cmd_buffer.cc
@@ -2439,7 +2439,7 @@ tu_init_hw(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
tu7_set_thread_br_patchpoint(cmd, cs, false);
}
- bool track_preempt_latency = dev->autotune->emit_preempt_latency_tracking_setup(cmd, cs);
+ dev->autotune->emit_preempt_latency_tracking_setup(cmd, cs);
tu_cs_emit_pkt7(cs, CP_SET_AMBLE, 3);
tu_cs_emit_qw(cs, cmd->device->bin_preamble_entry.bo->iova +
@@ -2465,7 +2465,7 @@ tu_init_hw(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
(1u << TU_PREDICATE_VTX_STATS_NOT_RUNNING));
}
- if (dev->switch_back_amble_entry.size > 0 && track_preempt_latency) {
+ if (dev->switch_back_amble_entry.size > 0) {
tu_cs_emit_pkt7(cs, CP_SET_AMBLE, 3);
tu_cs_emit_qw(cs, dev->switch_back_amble_entry.bo->iova + dev->switch_back_amble_entry.offset);
tu_cs_emit(cs, CP_SET_AMBLE_2_DWORDS(dev->switch_back_amble_entry.size / sizeof(uint32_t)) |
@@ -2476,7 +2476,7 @@ tu_init_hw(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
tu_cs_emit(cs, CP_SET_AMBLE_2_TYPE(PREAMBLE_AMBLE_TYPE));
}
- if (dev->switch_away_amble_entry.size > 0 && track_preempt_latency) {
+ if (dev->switch_away_amble_entry.size > 0) {
tu_cs_emit_pkt7(cs, CP_SET_AMBLE, 3);
tu_cs_emit_qw(cs, dev->switch_away_amble_entry.bo->iova + dev->switch_away_amble_entry.offset);
tu_cs_emit(cs, CP_SET_AMBLE_2_DWORDS(dev->switch_away_amble_entry.size / sizeof(uint32_t)) |
--
2.54.0

View File

@ -0,0 +1,99 @@
From ab7adaf47f2606e6b85a46470a586718cd409517 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 11:01:57 +0200
Subject: [PATCH 12/19] Revert "tu: Disable features using performance counter
for KGSL"
This reverts commit 18437c7a65a909044add3cb78c1e291bbf871743.
---
src/freedreno/vulkan/tu_autotune.cc | 3 +--
src/freedreno/vulkan/tu_device.cc | 2 +-
src/freedreno/vulkan/tu_device.h | 3 ---
src/freedreno/vulkan/tu_knl_drm_msm.cc | 2 --
src/freedreno/vulkan/tu_knl_drm_virtio.cc | 1 -
src/freedreno/vulkan/tu_knl_kgsl.cc | 3 ---
6 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index c456c248cdb..439ac05a845 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -323,8 +323,7 @@ uint32_t
tu_autotune::get_supported_mod_flags(tu_device *device) const
{
uint32_t supported_mod_flags = (uint32_t) mod_flag::BIG_GMEM | (uint32_t) mod_flag::TUNE_SMALL;
- if (device->physical_device->info->props.max_draw_states > TU_DRAW_STATE_AT_WRITE_RP_HASH &&
- device->physical_device->is_perf_cntr_selectable) {
+ if (device->physical_device->info->props.max_draw_states > TU_DRAW_STATE_AT_WRITE_RP_HASH) {
supported_mod_flags |= (uint32_t) mod_flag::PREEMPT_OPTIMIZE;
}
return supported_mod_flags;
diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc
index 25e11d45f8f..24ca3d2391c 100644
--- a/src/freedreno/vulkan/tu_device.cc
+++ b/src/freedreno/vulkan/tu_device.cc
@@ -212,7 +212,7 @@ get_device_extensions(const struct tu_physical_device *device,
.KHR_maintenance8 = tu_is_vk_1_1(device),
.KHR_map_memory2 = true,
.KHR_multiview = tu_has_multiview(device),
- .KHR_performance_query = (TU_DEBUG(PERFC) || TU_DEBUG(PERFCRAW)) && device->is_perf_cntr_selectable,
+ .KHR_performance_query = TU_DEBUG(PERFC) || TU_DEBUG(PERFCRAW),
.KHR_pipeline_executable_properties = true,
.KHR_pipeline_library = true,
#ifdef TU_USE_WSI_PLATFORM
diff --git a/src/freedreno/vulkan/tu_device.h b/src/freedreno/vulkan/tu_device.h
index b0ecf2f62ba..638ea404fa7 100644
--- a/src/freedreno/vulkan/tu_device.h
+++ b/src/freedreno/vulkan/tu_device.h
@@ -140,9 +140,6 @@ struct tu_physical_device
bool has_preemption;
- /* Whether performance counter selector registers can be written by userspace CSes. */
- bool is_perf_cntr_selectable;
-
struct {
uint32_t non_lazy_type_count;
uint32_t type_count;
diff --git a/src/freedreno/vulkan/tu_knl_drm_msm.cc b/src/freedreno/vulkan/tu_knl_drm_msm.cc
index 16e1cb40337..75a6e1a0250 100644
--- a/src/freedreno/vulkan/tu_knl_drm_msm.cc
+++ b/src/freedreno/vulkan/tu_knl_drm_msm.cc
@@ -1667,8 +1667,6 @@ tu_knl_drm_msm_load(struct tu_instance *instance,
device->has_preemption = tu_drm_has_preemption(device);
- device->is_perf_cntr_selectable = true;
-
/* Even if kernel is new enough, the GPU itself may not support it. */
device->has_cached_coherent_memory =
(device->msm_minor_version >= 8) &&
diff --git a/src/freedreno/vulkan/tu_knl_drm_virtio.cc b/src/freedreno/vulkan/tu_knl_drm_virtio.cc
index ea4d31ab665..9dbf9ee166d 100644
--- a/src/freedreno/vulkan/tu_knl_drm_virtio.cc
+++ b/src/freedreno/vulkan/tu_knl_drm_virtio.cc
@@ -1343,7 +1343,6 @@ tu_knl_drm_virtio_load(struct tu_instance *instance,
device->has_set_iova = true;
device->has_lazy_bos = true;
device->has_preemption = has_preemption;
- device->is_perf_cntr_selectable = true;
device->uche_trap_base = uche_trap_base;
device->ubwc_config.bank_swizzle_levels = bank_swizzle_levels;
diff --git a/src/freedreno/vulkan/tu_knl_kgsl.cc b/src/freedreno/vulkan/tu_knl_kgsl.cc
index c01160ea1f3..b960ef16673 100644
--- a/src/freedreno/vulkan/tu_knl_kgsl.cc
+++ b/src/freedreno/vulkan/tu_knl_kgsl.cc
@@ -1868,9 +1868,6 @@ tu_knl_kgsl_load(struct tu_instance *instance, int fd)
/* preemption is always supported on kgsl */
device->has_preemption = true;
- /* KGSL doesn't allow writing the perf counter selector as the expectation is to use the uAPI provided for this. */
- device->is_perf_cntr_selectable = false;
-
device->ubwc_config.highest_bank_bit = highest_bank_bit;
/* The other config values can be partially inferred from the UBWC version,
--
2.54.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
From db5315272229f2df847d663aec61c4204627adc4 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 11:03:15 +0200
Subject: [PATCH 14/19] Revert "tu/autotune: Disable autotuning for small
renderpasses by default"
This reverts commit bf2777c0130954f969c5a1038a01f94ec2d1ac63.
---
docs/drivers/freedreno.rst | 10 +++++-----
src/freedreno/vulkan/tu_autotune.cc | 19 +++++++------------
2 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/docs/drivers/freedreno.rst b/docs/drivers/freedreno.rst
index 9b1992fd628..a2318559526 100644
--- a/docs/drivers/freedreno.rst
+++ b/docs/drivers/freedreno.rst
@@ -709,12 +709,12 @@ environment variables:
GMEM rendering due to less overhead from tiling. This tends to lead to worse
performance in most cases, so it's only useful for testing.
- ``tune_small``
- Enables tuning for small render passes (those with a small number of draw
- calls). By default, small RPs always use SYSMEM mode as they generally don't
- benefit from GMEM rendering due to the overhead of tiling.
+ ``small_sysmem``
+ Always chooses SYSMEM rendering if the amount of draw calls in the render pass
+ is lower than a certain threshold. The benefits of GMEM rendering are less
+ pronounced in these smaller RPs and SYSMEM rendering tends to win more often.
Multiple flags can be combined by separating them with commas, e.g.
- ``TU_AUTOTUNE_FLAGS=big_gmem,tune_small``.
+ ``TU_AUTOTUNE_FLAGS=big_gmem,small_sysmem``.
If no flags are specified, the default behavior is used.
\ No newline at end of file
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index c708c83c044..38d09f5db45 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -97,8 +97,8 @@ enum class tu_autotune::algorithm : uint8_t {
/* Modifier flags, these modify the behavior of the autotuner in a user-defined way. */
enum class tu_autotune::mod_flag : uint8_t {
- BIG_GMEM = BIT(1), /* All RPs with >= 10 draws use GMEM. */
- TUNE_SMALL = BIT(2), /* Try tuning all RPs with <= 5 draws, ignored by default. */
+ BIG_GMEM = BIT(1), /* All RPs with >= 10 draws use GMEM. */
+ SMALL_SYSMEM = BIT(2), /* All RPs with <= 5 draws use SYSMEM. */
};
/* Metric flags, for internal tracking of enabled metrics. */
@@ -198,7 +198,7 @@ struct PACKED tu_autotune::config_t {
str += ", Mod Flags: 0x" + std::to_string(mod_flags) + " (";
MODF_STR(BIG_GMEM);
- MODF_STR(TUNE_SMALL);
+ MODF_STR(SMALL_SYSMEM);
str += ")";
str += ", Metric Flags: 0x" + std::to_string(metric_flags) + " (";
@@ -280,7 +280,7 @@ tu_autotune::get_env_config()
if (flags_env_str) {
static const struct debug_control tu_at_flags_control[] = {
{ "big_gmem", (uint32_t) mod_flag::BIG_GMEM },
- { "tune_small", (uint32_t) mod_flag::TUNE_SMALL },
+ { "small_sysmem", (uint32_t) mod_flag::SMALL_SYSMEM },
{ NULL, 0 }
};
@@ -1256,18 +1256,13 @@ tu_autotune::get_optimal_mode(struct tu_cmd_buffer *cmd_buffer, rp_ctx_t *rp_ctx
*/
bool simultaneous_use = cmd_buffer->usage_flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
- /* These smaller RPs with few draws are too difficult to create a balanced hash for that can independently identify
- * them while not being so unique to not properly identify them across CBs. They're generally insigificant outside of
- * a few edge cases such as during deferred rendering G-buffer passes, as we don't have a good way to deal with those
- * edge cases yet, we just disable the autotuner for small RPs entirely for now unless TUNE_SMALL is specified.
- */
- bool ignore_small_rp = !config.test(mod_flag::TUNE_SMALL) && rp_state->drawcall_count < 5;
-
- if (!enabled || simultaneous_use || ignore_small_rp)
+ if (!enabled || simultaneous_use)
return default_mode;
if (config.test(mod_flag::BIG_GMEM) && rp_state->drawcall_count >= 10)
return render_mode::GMEM;
+ if (config.test(mod_flag::SMALL_SYSMEM) && rp_state->drawcall_count <= 5)
+ return render_mode::SYSMEM;
rp_key key(pass, framebuffer, cmd_buffer);
--
2.54.0

View File

@ -0,0 +1,100 @@
From c70d031b220ca3ed83867bb1cd7e2e179109d13f Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 11:03:25 +0200
Subject: [PATCH 15/19] Revert "tu/autotune: Prefer SYSMEM when only SW binning
is possible"
This reverts commit 8e1fe9da20ceb13c125509fe5665108a57d642cf.
---
src/freedreno/vulkan/tu_cmd_buffer.cc | 14 +++-----------
src/freedreno/vulkan/tu_device.h | 7 ++-----
src/freedreno/vulkan/tu_util.cc | 14 +++++++++-----
3 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc
index 3e04110b4e6..3fe6be1976d 100644
--- a/src/freedreno/vulkan/tu_cmd_buffer.cc
+++ b/src/freedreno/vulkan/tu_cmd_buffer.cc
@@ -1313,7 +1313,7 @@ use_hw_binning(struct tu_cmd_buffer *cmd)
return true;
}
- return vsc->binning_possible && vsc->binning_useful;
+ return vsc->binning;
}
static bool
@@ -1376,16 +1376,8 @@ use_sysmem_rendering(struct tu_cmd_buffer *cmd,
return true;
}
- if (TU_DEBUG(GMEM)) {
- cmd->state.rp.gmem_disable_reason = "TU_DEBUG(GMEM)";
+ if (TU_DEBUG(GMEM))
return false;
- }
-
- /* This is a case where it's better to avoid GMEM, too many tiles but no HW binning possible. */
- if (!vsc->binning_possible && vsc->binning_useful) {
- cmd->state.rp.gmem_disable_reason = "Too many tiles and HW binning is not possible";
- return true;
- }
bool use_sysmem = cmd->device->autotune->get_optimal_mode(cmd, rp_ctx) == tu_autotune::render_mode::SYSMEM;
if (use_sysmem)
@@ -6431,7 +6423,7 @@ tu_emit_subpass_begin_gmem(struct tu_cmd_buffer *cmd, struct tu_resolve_group *r
* (perf queries), then we can't do this optimization since the
* start-of-the-CS geometry condition will have been overwritten.
*/
- bool cond_load_allowed = vsc->binning_possible &&
+ bool cond_load_allowed = vsc->binning &&
cmd->state.pass->has_cond_load_store &&
!cmd->state.rp.draw_cs_writes_to_cond_pred;
diff --git a/src/freedreno/vulkan/tu_device.h b/src/freedreno/vulkan/tu_device.h
index 1be07dcdc43..9665135e0e6 100644
--- a/src/freedreno/vulkan/tu_device.h
+++ b/src/freedreno/vulkan/tu_device.h
@@ -561,11 +561,8 @@ struct tu_vsc_config {
/* Whether binning could be used for gmem rendering using this framebuffer. */
bool binning_possible;
- /* Whether binning is useful for GMEM rendering performance using this framebuffer. This is independent of whether
- * binning is possible, and is determined by the tile count. Not binning when it's useful would be a performance
- * hazard, and GMEM rendering should be avoided in the case where it's useful to bin but not possible to do so.
- */
- bool binning_useful;
+ /* Whether binning should be used for gmem rendering using this framebuffer. */
+ bool binning;
/* pipe register values */
uint32_t pipe_config[MAX_VSC_PIPES];
diff --git a/src/freedreno/vulkan/tu_util.cc b/src/freedreno/vulkan/tu_util.cc
index 68f2d67dda6..77b8ac4ddbb 100644
--- a/src/freedreno/vulkan/tu_util.cc
+++ b/src/freedreno/vulkan/tu_util.cc
@@ -460,12 +460,16 @@ tu_tiling_config_update_pipes(struct tu_vsc_config *vsc,
static void
tu_tiling_config_update_binning(struct tu_vsc_config *vsc, const struct tu_device *device)
{
- vsc->binning_useful = (vsc->tile_count.width * vsc->tile_count.height) > 2;
+ if (vsc->binning_possible) {
+ vsc->binning = (vsc->tile_count.width * vsc->tile_count.height) > 2;
- if (TU_DEBUG(FORCEBIN))
- vsc->binning_useful = true;
- if (TU_DEBUG(NOBIN))
- vsc->binning_useful = false;
+ if (TU_DEBUG(FORCEBIN))
+ vsc->binning = true;
+ if (TU_DEBUG(NOBIN))
+ vsc->binning = false;
+ } else {
+ vsc->binning = false;
+ }
}
void
--
2.54.0

View File

@ -0,0 +1,359 @@
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

View File

@ -0,0 +1,171 @@
From 8137f3552ab872c65db82d57bf490fd18414c1c6 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 11:03:43 +0200
Subject: [PATCH 17/19] Revert "tu/autotune: Improve RP hash"
This reverts commit 44564b966d87a7059b142c268f5457ec8396f5bc.
---
src/freedreno/vulkan/tu_autotune.cc | 71 +++++------------------------
src/freedreno/vulkan/tu_autotune.h | 5 --
2 files changed, 11 insertions(+), 65 deletions(-)
diff --git a/src/freedreno/vulkan/tu_autotune.cc b/src/freedreno/vulkan/tu_autotune.cc
index cfc145e3286..971cc1a9503 100644
--- a/src/freedreno/vulkan/tu_autotune.cc
+++ b/src/freedreno/vulkan/tu_autotune.cc
@@ -434,9 +434,6 @@ struct tu_autotune::rp_entry {
bool sysmem;
uint32_t draw_count;
- /* Amount of repeated RPs so far, used for uniquely identifying instances of the same RPs. */
- uint32_t duplicates = 0;
-
rp_entry(struct tu_device *device, rp_history_handle &&history, config_t config, uint32_t draw_count)
: device(device), map(nullptr), history(std::move(history)), config(config), draw_count(draw_count)
{
@@ -586,25 +583,12 @@ tu_autotune::rp_key::rp_key(const struct tu_render_pass *pass,
const struct tu_framebuffer *framebuffer,
const struct tu_cmd_buffer *cmd)
{
- /* It may be hard to match the same renderpass between frames, or rather it's hard to strike a
- * balance between being too lax with identifying different renderpasses as the same one, and
- * not recognizing the same renderpass between frames when only a small thing changed.
- *
- * This is mainly an issue with translation layers (particularly DXVK), because a layer may
- * break a "renderpass" into smaller ones due to some heuristic that isn't consistent between
- * frames.
- *
- * Note: Not using image IOVA leads to too many false matches.
+ /* Q: Why not make the key from framebuffer + renderpass pointers?
+ * A: At least DXVK creates new framebuffers each frame while keeping renderpasses the same. Hashing the contents
+ * of the framebuffer and renderpass is more stable, and it maintains stability across runs, so we can reliably
+ * identify the same renderpass instance.
*/
- struct PACKED packed_att_properties {
- uint64_t iova;
- bool load;
- bool store;
- bool load_stencil;
- bool store_stencil;
- };
-
auto get_hash = [&](uint32_t *data, size_t size) {
uint32_t *ptr = data;
*ptr++ = framebuffer->width;
@@ -612,18 +596,12 @@ tu_autotune::rp_key::rp_key(const struct tu_render_pass *pass,
*ptr++ = framebuffer->layers;
for (unsigned i = 0; i < pass->attachment_count; i++) {
- packed_att_properties props = {
- .iova = cmd->state.attachments[i]->image->iova + cmd->state.attachments[i]->view.offset,
- .load = pass->attachments[i].load,
- .store = pass->attachments[i].store,
- .load_stencil = pass->attachments[i].load_stencil,
- .store_stencil = pass->attachments[i].store_stencil,
- };
-
- memcpy(ptr, &props, sizeof(packed_att_properties));
- ptr += sizeof(packed_att_properties) / sizeof(uint32_t);
+ *ptr++ = cmd->state.attachments[i]->view.width;
+ *ptr++ = cmd->state.attachments[i]->view.height;
+ *ptr++ = cmd->state.attachments[i]->image->vk.format;
+ *ptr++ = cmd->state.attachments[i]->image->vk.array_layers;
+ *ptr++ = cmd->state.attachments[i]->image->vk.mip_levels;
}
- assert(ptr == data + size);
return XXH3_64bits(data, size * sizeof(uint32_t));
};
@@ -631,8 +609,8 @@ tu_autotune::rp_key::rp_key(const struct tu_render_pass *pass,
/* We do a manual Boost-style "small vector" optimization here where the stack is used for the vast majority of
* cases, while only extreme cases need to allocate on the heap.
*/
- size_t data_count = 3 + (pass->attachment_count * sizeof(packed_att_properties) / sizeof(uint32_t));
- constexpr size_t STACK_MAX_DATA_COUNT = 3 + (5 * 3); /* in u32 units. */
+ size_t data_count = 3 + (pass->attachment_count * 5);
+ constexpr size_t STACK_MAX_DATA_COUNT = 3 + (5 * 5); /* in u32 units. */
if (data_count <= STACK_MAX_DATA_COUNT) {
/* If the data is small enough, we can use the stack. */
@@ -645,11 +623,6 @@ tu_autotune::rp_key::rp_key(const struct tu_render_pass *pass,
}
}
-tu_autotune::rp_key::rp_key(const rp_key &key, uint32_t duplicates)
-{
- hash = XXH3_64bits_withSeed(&key.hash, sizeof(key.hash), duplicates);
-}
-
/* Exponential moving average (EMA) calculator for smoothing successive values of any metric. An alpha (smoothing
* factor) of 0.1 means 10% weight to new values (slow adaptation), while 0.9 means 90% weight (fast adaptation).
*/
@@ -697,7 +670,6 @@ template <typename T = double> class exponential_average {
struct tu_autotune::rp_history {
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. */
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. */
@@ -1007,16 +979,6 @@ tu_autotune::cmd_buf_ctx::attach_rp_entry(struct tu_device *device,
return new_entry.get();
}
-tu_autotune::rp_entry *
-tu_autotune::cmd_buf_ctx::find_rp_entry(const rp_key &key)
-{
- for (auto &entry : batch->entries) {
- if (entry->history->hash == key.hash)
- return entry.get();
- }
- return nullptr;
-}
-
tu_autotune::render_mode
tu_autotune::get_optimal_mode(struct tu_cmd_buffer *cmd_buffer, rp_ctx_t *rp_ctx)
{
@@ -1069,17 +1031,6 @@ tu_autotune::get_optimal_mode(struct tu_cmd_buffer *cmd_buffer, rp_ctx_t *rp_ctx
return render_mode::SYSMEM;
rp_key key(pass, framebuffer, cmd_buffer);
-
- /* When nearly identical renderpasses appear multiple times within the same command buffer, we need to generate a
- * unique hash for each instance to distinguish them. While this approach doesn't address identical renderpasses
- * across different command buffers, it is good enough in most cases.
- */
- rp_entry *entry = cb_ctx.find_rp_entry(key);
- if (entry) {
- entry->duplicates++;
- key = rp_key(key, entry->duplicates);
- }
-
*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);
diff --git a/src/freedreno/vulkan/tu_autotune.h b/src/freedreno/vulkan/tu_autotune.h
index 0f4215e8461..1dc966a20e9 100644
--- a/src/freedreno/vulkan/tu_autotune.h
+++ b/src/freedreno/vulkan/tu_autotune.h
@@ -155,9 +155,6 @@ struct tu_autotune {
const struct tu_framebuffer *framebuffer,
const struct tu_cmd_buffer *cmd);
- /* Further salt the hash to distinguish between multiple instances of the same RP within a single command buffer. */
- rp_key(const rp_key &key, uint32_t duplicates);
-
/* Equality operator, used in unordered_map. */
constexpr bool operator==(const rp_key &other) const noexcept
{
@@ -212,8 +209,6 @@ struct tu_autotune {
rp_entry *
attach_rp_entry(struct tu_device *device, rp_history_handle &&history, config_t config, uint32_t draw_count);
- rp_entry *find_rp_entry(const rp_key &key);
-
friend struct tu_autotune;
public:
--
2.54.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
From 362798e015220647aa46361475b4af999ed90d22 Mon Sep 17 00:00:00 2001
From: Jocelyn Falempe <jfalempe@redhat.com>
Date: Fri, 26 Jun 2026 11:41:20 +0200
Subject: [PATCH 19/19] Fix is_perf_cntr_selectable in tu_device.cc
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
---
src/freedreno/vulkan/tu_device.cc | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc
index 38da9a54ce2..bfc7f7c2ca8 100644
--- a/src/freedreno/vulkan/tu_device.cc
+++ b/src/freedreno/vulkan/tu_device.cc
@@ -1778,9 +1778,6 @@ tu_physical_device_init(struct tu_physical_device *device,
device->vk.pipeline_cache_import_ops = cache_import_ops;
- /* gen8 and onwards must use kernel UAPI for perfcntr management */
- device->is_perf_cntr_selectable &= (device->info->chip <= 7);
-
return VK_SUCCESS;
fail_free_name:
--
2.54.0

View File

@ -1,23 +0,0 @@
VERSION ?= 23.1.4
SANITIZE ?= 1
DIRNAME = mesa-${VERSION}
all: archive
clean:
rm -rf $(DIRNAME)/
rm -f mesa-${VERSION}.tar.xz
clone: clean
curl -O https://archive.mesa3d.org/mesa-${VERSION}.tar.xz
tar xf mesa-${VERSION}.tar.xz
sanitize: clone vl_mpeg12_decoder.c vl_decoder.c
ifdef SANITIZE
cat < vl_mpeg12_decoder.c > $(DIRNAME)/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c
cat < vl_decoder.c > $(DIRNAME)/src/gallium/auxiliary/vl/vl_decoder.c
endif
archive: clone sanitize
tar caf ${DIRNAME}.tar.xz ${DIRNAME}

View File

@ -1,12 +0,0 @@
diff -up mesa-23.1.4/meson.build.dma mesa-23.1.4/meson.build
--- mesa-23.1.4/meson.build.dma 2023-07-28 10:15:41.807945483 +1000
+++ mesa-23.1.4/meson.build 2023-07-28 10:15:46.465030794 +1000
@@ -835,7 +835,7 @@ if get_option('allow-kcmp') \
pre_args += '-DALLOW_KCMP'
endif
-prog_python = import('python').find_installation('python3')
+prog_python = import('python').find_installation('python3.6')
has_mako = run_command(
prog_python, '-c',
'''

View File

@ -1,11 +0,0 @@
diff -up mesa-22.3.0-rc4/src/util/00-mesa-defaults.conf.dma mesa-22.3.0-rc4/src/util/00-mesa-defaults.conf
--- mesa-22.3.0-rc4/src/util/00-mesa-defaults.conf.dma 2022-11-25 10:32:32.175879868 +1000
+++ mesa-22.3.0-rc4/src/util/00-mesa-defaults.conf 2022-11-25 10:32:43.743067470 +1000
@@ -653,6 +653,7 @@ TODO: document the other workarounds.
<application name="gnome-shell" executable="gnome-shell">
<option name="adaptive_sync" value="false" />
<option name="v3d_nonmsaa_texture_size_limit" value="true" />
+ <option name="mesa_glthread" value="false"/>
</application>
<application name="Desktop — Plasma" executable="plasmashell">
<option name="adaptive_sync" value="false" />

View File

@ -1,13 +0,0 @@
diff -up mesa-21.3.0/src/gallium/frontends/lavapipe/lvp_device.cdma mesa-21.3.0/src/gallium/frontends/lavapipe/lvp_device.c
--- mesa-21.3.0/src/gallium/frontends/lavapipe/lvp_device.cdma 2021-11-18 06:16:20.000000000 +1000
+++ mesa-21.3.0/src/gallium/frontends/lavapipe/lvp_device.c 2021-11-18 07:03:17.652283186 +1000
@@ -213,6 +213,9 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_Creat
if (pAllocator == NULL)
pAllocator = vk_default_allocator();
+ if (!getenv("RH_SW_VULKAN"))
+ return VK_ERROR_INITIALIZATION_FAILED;
+
instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (!instance)

View File

@ -1,30 +0,0 @@
diff -up mesa-23.1.4/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c.da mesa-23.1.4/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
--- mesa-23.1.4/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c.da 2025-01-10 13:14:31.119630821 +1000
+++ mesa-23.1.4/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c 2025-01-10 13:15:11.917433170 +1000
@@ -149,6 +149,7 @@ nvc0_validate_fb(struct nvc0_context *nv
unsigned ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
unsigned nr_cbufs = fb->nr_cbufs;
bool serialize = false;
+ bool cbuf_is_linear = false;
nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB);
@@ -203,8 +204,7 @@ nvc0_validate_fb(struct nvc0_context *nv
PUSH_DATA(push, 0);
nvc0_resource_fence(nvc0, res, NOUVEAU_BO_WR);
-
- assert(!fb->zsbuf);
+ cbuf_is_linear = true;
}
if (res->status & NOUVEAU_BUFFER_STATUS_GPU_READING)
@@ -216,7 +216,7 @@ nvc0_validate_fb(struct nvc0_context *nv
BCTX_REFN(nvc0->bufctx_3d, 3D_FB, res, WR);
}
- if (fb->zsbuf) {
+ if (fb->zsbuf && !cbuf_is_linear) {
struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
struct nv50_surface *sf = nv50_surface(fb->zsbuf);
int unk = mt->base.base.target == PIPE_TEXTURE_2D;

View File

@ -1,11 +0,0 @@
diff -up mesa-22.3.3/src/gallium/drivers/radeonsi/driinfo_radeonsi.h.dma mesa-22.3.3/src/gallium/drivers/radeonsi/driinfo_radeonsi.h
--- mesa-22.3.3/src/gallium/drivers/radeonsi/driinfo_radeonsi.h.dma 2023-01-25 06:17:54.993167334 +1000
+++ mesa-22.3.3/src/gallium/drivers/radeonsi/driinfo_radeonsi.h 2023-01-25 06:17:57.363203425 +1000
@@ -1,7 +1,6 @@
// DriConf options specific to radeonsi
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_ADAPTIVE_SYNC(true)
-DRI_CONF_MESA_GLTHREAD(true)
DRI_CONF_SECTION_END
DRI_CONF_SECTION_DEBUG

View File

@ -1,20 +0,0 @@
#include "vl_decoder.h"
bool
vl_profile_supported(struct pipe_screen *screen, enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint)
{
return false;
}
int
vl_level_supported(struct pipe_screen *screen, enum pipe_video_profile profile)
{
return 0;
}
struct pipe_video_codec *
vl_create_decoder(struct pipe_context *pipe,
const struct pipe_video_codec *templat)
{
return NULL;
}

View File

@ -1,7 +0,0 @@
#include "vl_mpeg12_decoder.h"
struct pipe_video_codec *
vl_create_mpeg12_decoder(struct pipe_context *context,
const struct pipe_video_codec *templat)
{
return NULL;
}

File diff suppressed because it is too large Load Diff