update to 26.1.1

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

Resolves: RHEL-135263

Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
This commit is contained in:
Jocelyn Falempe 2026-06-16 11:08:31 +02:00
parent 1a6b6007f3
commit f49ef1410d
28 changed files with 6675 additions and 574 deletions

1
.gitignore vendored
View File

@ -17,3 +17,4 @@ mesa-*/
/rustc-hash-*.tar.gz
/wayland-protocols-*.tar.xz
/llvm-project-22.1.1.src.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,59 +0,0 @@
From 102d282d8add081f5f1aab35974218f151744ac5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= <jose.exposito89@gmail.com>
Date: Mon, 23 Feb 2026 08:40:07 +0100
Subject: [PATCH] Revert "dri: fix __DRI_IMAGE_FORMAT* to PIPE_FORMAT*
mappings"
This reverts commit 2ae8d0362bec12e84f787f226d2ba7a18130084f.
---
src/loader/loader_dri_helper.h | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/loader/loader_dri_helper.h b/src/loader/loader_dri_helper.h
index 169e36b5d80..0d801e99648 100644
--- a/src/loader/loader_dri_helper.h
+++ b/src/loader/loader_dri_helper.h
@@ -61,8 +61,10 @@ struct loader_screen_resources {
/**
- * These formats are endian independent they result in the same layout
- * regradless of a big or little endian cpu.
+ * These formats correspond to the similarly named MESA_FORMAT_*
+ * tokens, except in the native endian of the CPU. For example, on
+ * little endian __DRI_IMAGE_FORMAT_XRGB8888 corresponds to
+ * MESA_FORMAT_XRGB8888, but MESA_FORMAT_XRGB8888_REV on big endian.
*
* __DRI_IMAGE_FORMAT_NONE is for images that aren't directly usable
* by the driver (YUV planar formats) but serve as a base image for
@@ -73,21 +75,21 @@ struct loader_screen_resources {
* createImageFromNames (NONE, see above) and fromPlane (R8 & GR88).
*/
#define __DRI_IMAGE_FORMAT_RGB565 PIPE_FORMAT_B5G6R5_UNORM
-#define __DRI_IMAGE_FORMAT_XRGB8888 PIPE_FORMAT_B8G8R8X8_UNORM
-#define __DRI_IMAGE_FORMAT_ARGB8888 PIPE_FORMAT_B8G8R8A8_UNORM
-#define __DRI_IMAGE_FORMAT_ABGR8888 PIPE_FORMAT_R8G8B8A8_UNORM
-#define __DRI_IMAGE_FORMAT_XBGR8888 PIPE_FORMAT_R8G8B8X8_UNORM
+#define __DRI_IMAGE_FORMAT_XRGB8888 PIPE_FORMAT_BGRX8888_UNORM
+#define __DRI_IMAGE_FORMAT_ARGB8888 PIPE_FORMAT_BGRA8888_UNORM
+#define __DRI_IMAGE_FORMAT_ABGR8888 PIPE_FORMAT_RGBA8888_UNORM
+#define __DRI_IMAGE_FORMAT_XBGR8888 PIPE_FORMAT_RGBX8888_UNORM
#define __DRI_IMAGE_FORMAT_RGB888 PIPE_FORMAT_B8G8R8_UNORM
#define __DRI_IMAGE_FORMAT_BGR888 PIPE_FORMAT_R8G8B8_UNORM
#define __DRI_IMAGE_FORMAT_R8 PIPE_FORMAT_R8_UNORM
-#define __DRI_IMAGE_FORMAT_GR88 PIPE_FORMAT_R8G8_UNORM
+#define __DRI_IMAGE_FORMAT_GR88 PIPE_FORMAT_RG88_UNORM
#define __DRI_IMAGE_FORMAT_NONE PIPE_FORMAT_NONE
#define __DRI_IMAGE_FORMAT_XRGB2101010 PIPE_FORMAT_B10G10R10X2_UNORM
#define __DRI_IMAGE_FORMAT_ARGB2101010 PIPE_FORMAT_B10G10R10A2_UNORM
#define __DRI_IMAGE_FORMAT_SARGB8 PIPE_FORMAT_BGRA8888_SRGB
#define __DRI_IMAGE_FORMAT_ARGB1555 PIPE_FORMAT_B5G5R5A1_UNORM
#define __DRI_IMAGE_FORMAT_R16 PIPE_FORMAT_R16_UNORM
-#define __DRI_IMAGE_FORMAT_GR1616 PIPE_FORMAT_R16G16_UNORM
+#define __DRI_IMAGE_FORMAT_GR1616 PIPE_FORMAT_RG1616_UNORM
#define __DRI_IMAGE_FORMAT_XBGR2101010 PIPE_FORMAT_R10G10B10X2_UNORM
#define __DRI_IMAGE_FORMAT_ABGR2101010 PIPE_FORMAT_R10G10B10A2_UNORM
#define __DRI_IMAGE_FORMAT_SABGR8 PIPE_FORMAT_RGBA8888_SRGB
--
2.53.0

View File

@ -1,149 +0,0 @@
From b0158d174d297276397b21a6657ea0ef14652183 Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Wed, 5 Nov 2025 11:01:05 +1000
Subject: [PATCH 1/2] device-select: add a layer setting to disable device
selection logic
There are cases like zink where we have a file descriptors we are searching
for devices for, so we don't need device selecting reordering, we just want
the fastest path to get the devices so we can match them.
This also helps avoid some cases of deadlock inside compositors where
zink/vulkan initialises later and tries to connect to the compositor.
This uses a VK_EXT_layer_setting to add a bypass setting.
---
.../VkLayer_MESA_device_select.json.in | 6 +++
.../device-select-layer/device_select_layer.c | 53 +++++++++++++++----
2 files changed, 48 insertions(+), 11 deletions(-)
diff --git a/src/vulkan/device-select-layer/VkLayer_MESA_device_select.json.in b/src/vulkan/device-select-layer/VkLayer_MESA_device_select.json.in
index 40d6ea8cd8b..1623381a81a 100644
--- a/src/vulkan/device-select-layer/VkLayer_MESA_device_select.json.in
+++ b/src/vulkan/device-select-layer/VkLayer_MESA_device_select.json.in
@@ -7,6 +7,12 @@
"api_version": "1.4.303",
"implementation_version": "1",
"description": "Linux device selection layer",
+ "instance_extensions": [
+ {
+ "name": "VK_EXT_layer_settings",
+ "spec_version": "2"
+ }
+ ],
"functions": {
"vkNegotiateLoaderLayerInterfaceVersion": "vkNegotiateLoaderLayerInterfaceVersion"
},
diff --git a/src/vulkan/device-select-layer/device_select_layer.c b/src/vulkan/device-select-layer/device_select_layer.c
index 19cfc556f54..c03938b82c0 100644
--- a/src/vulkan/device-select-layer/device_select_layer.c
+++ b/src/vulkan/device-select-layer/device_select_layer.c
@@ -54,7 +54,9 @@ struct instance_info {
PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
bool has_pci_bus, has_vulkan11;
bool has_wayland, has_xcb;
- bool zink, xwayland, xserver;
+ bool xserver;
+ /* don't do device selection */
+ bool bypass_device_select;
};
static struct hash_table *device_select_instance_ht = NULL;
@@ -118,10 +120,34 @@ static VkResult device_select_CreateInstance(const VkInstanceCreateInfo *pCreate
const VkAllocationCallbacks *pAllocator,
VkInstance *pInstance)
{
- VkLayerInstanceCreateInfo *chain_info;
- for(chain_info = (VkLayerInstanceCreateInfo*)pCreateInfo->pNext; chain_info; chain_info = (VkLayerInstanceCreateInfo*)chain_info->pNext)
- if(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == VK_LAYER_LINK_INFO)
+ VkLayerInstanceCreateInfo *chain_info = NULL;
+ bool bypass_device_select = false;
+ vk_foreach_struct_const(s, pCreateInfo->pNext) {
+ switch (s->sType) {
+ case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: {
+ const VkLayerInstanceCreateInfo *this_info = (const void *)s;
+ if (this_info->function == VK_LAYER_LINK_INFO)
+ chain_info = (VkLayerInstanceCreateInfo *)this_info; /* loses const */
break;
+ }
+ case VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT: {
+ const VkLayerSettingsCreateInfoEXT *lsci = (const void *)s;
+ for (unsigned i = 0; i < lsci->settingCount; i++) {
+ const VkLayerSettingEXT *ls = &lsci->pSettings[i];
+ if (!strcmp(ls->pLayerName, "MESA_device_select")) {
+ if (!strcmp(ls->pSettingName, "no_device_select")) {
+ assert(ls->type == VK_LAYER_SETTING_TYPE_BOOL32_EXT);
+ uint32_t *values = (uint32_t *)ls->pValues;
+ bypass_device_select = values[0];
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
assert(chain_info->u.pLayerInfo);
@@ -140,10 +166,10 @@ static VkResult device_select_CreateInstance(const VkInstanceCreateInfo *pCreate
return result;
}
+ bool zink = !strcmp(engineName, "mesa zink");
+ bool xwayland = !strcmp(applicationName, "Xwayland");
struct instance_info *info = (struct instance_info *)calloc(1, sizeof(struct instance_info));
info->GetInstanceProcAddr = GetInstanceProcAddr;
- info->zink = !strcmp(engineName, "mesa zink");
- info->xwayland = !strcmp(applicationName, "Xwayland");
info->xserver = !strcmp(applicationName, "Xorg") || !strcmp(applicationName, "Xephyr");
bool has_wayland = getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET");
@@ -155,16 +181,20 @@ static VkResult device_select_CreateInstance(const VkInstanceCreateInfo *pCreate
info->has_wayland = true;
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
- if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) && has_xcb)
- info->has_xcb = !info->xserver || !info->zink;
+ if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) &&
+ has_xcb)
+ info->has_xcb = !info->xserver || !zink;
#endif
}
+ if (zink && xwayland)
+ bypass_device_select = true;
/*
* The loader is currently not able to handle GetPhysicalDeviceProperties2KHR calls in
* EnumeratePhysicalDevices when there are other layers present. To avoid mysterious crashes
* for users just use only the vulkan version for now.
*/
+ info->bypass_device_select = bypass_device_select;
info->has_vulkan11 = pCreateInfo->pApplicationInfo &&
pCreateInfo->pApplicationInfo->apiVersion >= VK_MAKE_VERSION(1, 1, 0);
@@ -558,7 +588,7 @@ static VkResult device_select_EnumeratePhysicalDevices(VkInstance instance,
uint32_t selected_physical_device_count = 0;
const char* selection = getenv("MESA_VK_DEVICE_SELECT");
bool expose_only_one_dev = false;
- if (info->zink && info->xwayland)
+ if (info->bypass_device_select)
return info->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
VkResult result = info->EnumeratePhysicalDevices(instance, &physical_device_count, NULL);
VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, pPhysicalDevices, pPhysicalDeviceCount);
@@ -643,8 +673,9 @@ static VkResult device_select_EnumeratePhysicalDeviceGroups(VkInstance instance,
struct instance_info *info = device_select_layer_get_instance(instance);
uint32_t physical_device_group_count = 0;
uint32_t selected_physical_device_group_count = 0;
- if (info->zink && info->xwayland)
- return info->EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroups);
+ if (info->bypass_device_select)
+ return info->EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount,
+ pPhysicalDeviceGroups);
VkResult result = info->EnumeratePhysicalDeviceGroups(instance, &physical_device_group_count, NULL);
VK_OUTARRAY_MAKE_TYPED(VkPhysicalDeviceGroupProperties, out, pPhysicalDeviceGroups, pPhysicalDeviceGroupCount);
--
2.51.1

View File

@ -1,74 +0,0 @@
From 17ab0f2ece0a45dd5df507a466ecf6f40d452e1a Mon Sep 17 00:00:00 2001
From: Lucas Fryzek <lfryzek@igalia.com>
Date: Wed, 3 Dec 2025 19:33:57 -0500
Subject: [PATCH 1/2] drisw: Modify drisw_swap_buffers_with_damage to swap
entire buffer
When swapping buffer with damage regions, to be strictly correct we
need to swap the entire back buffer to the front buffer. This needs to
be done in case the compositor does not support damage regions. This
means we need to ignore the input damage region and tell drisw to swap
the entire buffer.
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38817>
---
src/gallium/frontends/dri/drisw.c | 28 ++++++++--------------------
1 file changed, 8 insertions(+), 20 deletions(-)
diff --git a/src/gallium/frontends/dri/drisw.c b/src/gallium/frontends/dri/drisw.c
index 4359ca569e5..394b6986832 100644
--- a/src/gallium/frontends/dri/drisw.c
+++ b/src/gallium/frontends/dri/drisw.c
@@ -225,6 +225,13 @@ drisw_copy_to_front(struct pipe_context *pipe,
static void
drisw_swap_buffers_with_damage(struct dri_drawable *drawable, int nrects, const int *rects)
{
+ /* Damage regions still require us to update the whole front buffer
+ * in case the compositor doesn't obey them, so we will just ignore
+ * the passed in damage regions and swap the whole buffer
+ */
+ (void)nrects;
+ (void)rects;
+
struct dri_context *ctx = dri_get_current();
struct dri_screen *screen = drawable->screen;
struct pipe_resource *ptex;
@@ -242,25 +249,6 @@ drisw_swap_buffers_with_damage(struct dri_drawable *drawable, int nrects, const
if (ptex) {
struct pipe_fence_handle *fence = NULL;
- struct pipe_box stack_boxes[64];
- if (nrects > ARRAY_SIZE(stack_boxes))
- nrects = 0;
- if (nrects) {
- for (unsigned int i = 0; i < nrects; i++) {
- const int *rect = &rects[i * 4];
-
- int w = MIN2(rect[2], ptex->width0);
- int h = MIN2(rect[3], ptex->height0);
- int x = CLAMP(rect[0], 0, ptex->width0);
- int y = CLAMP(ptex->height0 - rect[1] - h, 0, ptex->height0);
-
- if (h > ptex->height0 - y)
- h = ptex->height0 - y;
-
- u_box_2d(x, y, w, h, &stack_boxes[i]);
- }
- }
-
if (ctx->pp)
pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
@@ -279,7 +267,7 @@ drisw_swap_buffers_with_damage(struct dri_drawable *drawable, int nrects, const
screen->base.screen->fence_finish(screen->base.screen, ctx->st->pipe,
fence, OS_TIMEOUT_INFINITE);
screen->base.screen->fence_reference(screen->base.screen, &fence, NULL);
- drisw_copy_to_front(ctx->st->pipe, drawable, ptex, nrects, nrects ? stack_boxes : NULL);
+ drisw_copy_to_front(ctx->st->pipe, drawable, ptex, 0, NULL);
drawable->buffer_age = 1;
/* TODO: remove this if the framebuffer state doesn't change. */
--
2.52.0

View File

@ -1,36 +0,0 @@
From c016346b50e9085b531f9bcbd7cfd63d3806a3e1 Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Wed, 11 Feb 2026 05:47:57 +1000
Subject: [PATCH] gallivm: handle u16 correct on const loads.
I somehow screwed this up on my previous attempt at fixing this bug,
This should fix the loop limiter bug on big endian properly.
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Cc: mesa-stable
Fixes: e28cfb2bada2 ("gallivm: handle u8/u16 const loads properly on big-endian.")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39813>
---
src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c
index 770f1cc6592..e755225dce9 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_nir_soa.c
@@ -1269,10 +1269,7 @@ emit_load_const(struct lp_build_nir_soa_context *bld,
for (unsigned i = 0; i < instr->def.num_components; i++) {
outval[i] = lp_build_const_int_vec(bld->base.gallivm, int_bld->type,
- bits == 8 ? instr->value[i].u8 :
- bits == 16 ? instr->value[i].u32 :
- bits == 32 ? instr->value[i].u32 :
- instr->value[i].u64);
+ nir_const_value_as_uint(instr->value[i], bits));
}
for (unsigned i = instr->def.num_components; i < NIR_MAX_VEC_COMPONENTS; i++) {
outval[i] = NULL;
--
2.53.0

36
0002-Fix-enum.patch Normal file
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

@ -1,72 +0,0 @@
From 48799005d7f3b099cb2e93d09ce6dc211f619887 Mon Sep 17 00:00:00 2001
From: Lucas Fryzek <lfryzek@igalia.com>
Date: Wed, 3 Dec 2025 19:19:56 -0500
Subject: [PATCH 2/2] Revert "drisw: Copy entire buffer ignoring damage
regions"
This reverts commit 755e795e4c0d2660129c14998425f7dd3299bdf9.
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38817>
---
src/gallium/winsys/sw/dri/dri_sw_winsys.c | 38 +++++++++++++++++------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/src/gallium/winsys/sw/dri/dri_sw_winsys.c b/src/gallium/winsys/sw/dri/dri_sw_winsys.c
index 7d18b6138ea..0b2c8754ec5 100644
--- a/src/gallium/winsys/sw/dri/dri_sw_winsys.c
+++ b/src/gallium/winsys/sw/dri/dri_sw_winsys.c
@@ -352,21 +352,41 @@ dri_sw_displaytarget_display(struct sw_winsys *ws,
struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
struct dri_drawable *dri_drawable = (struct dri_drawable *)context_private;
- unsigned width, height;
+ unsigned width, height, x = 0, y = 0;
unsigned blsize = util_format_get_blocksize(dri_sw_dt->format);
bool is_shm = dri_sw_dt->shmid != -1;
/* Set the width to 'stride / cpp'.
*
* PutImage correctly clips to the width of the dst drawable.
*/
- width = dri_sw_dt->stride / blsize;
- height = dri_sw_dt->height;
- if (is_shm)
- dri_sw_ws->lf->put_image_shm(dri_drawable, dri_sw_dt->shmid, dri_sw_dt->data, 0, 0,
- 0, 0, width, height, dri_sw_dt->stride);
- else
- dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
- return;
+ if (!nboxes) {
+ width = dri_sw_dt->stride / blsize;
+ height = dri_sw_dt->height;
+ if (is_shm)
+ dri_sw_ws->lf->put_image_shm(dri_drawable, dri_sw_dt->shmid, dri_sw_dt->data, 0, 0,
+ 0, 0, width, height, dri_sw_dt->stride);
+ else
+ dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
+ return;
+ }
+ for (unsigned i = 0; i < nboxes; i++) {
+ unsigned offset = dri_sw_dt->stride * box[i].y;
+ unsigned offset_x = box[i].x * blsize;
+ char *data = dri_sw_dt->data + offset;
+ x = box[i].x;
+ y = box[i].y;
+ width = box[i].width;
+ height = box[i].height;
+ if (is_shm) {
+ /* don't add x offset for shm, the put_image_shm will deal with it */
+ dri_sw_ws->lf->put_image_shm(dri_drawable, dri_sw_dt->shmid, dri_sw_dt->data, offset, offset_x,
+ x, y, width, height, dri_sw_dt->stride);
+ } else {
+ data += offset_x;
+ dri_sw_ws->lf->put_image2(dri_drawable, data,
+ x, y, width, height, dri_sw_dt->stride);
+ }
+ }
}
static void
--
2.52.0

View File

@ -1,106 +0,0 @@
From 30c754624ab73b180c66658701814ec5e3d12a31 Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Wed, 5 Nov 2025 11:02:26 +1000
Subject: [PATCH 2/2] zink: use device select layer settings to disable device
selection
In the case where we have a device that we want to choose after
probing, there is no point in asking the device select layer to do
any reordering at all.
This helps avoid a deadlock inside compositors where we don't need
device selection anyways.
---
src/gallium/drivers/zink/zink_instance.py | 18 ++++++++++++++++++
src/gallium/drivers/zink/zink_screen.c | 9 ++++++++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/gallium/drivers/zink/zink_instance.py b/src/gallium/drivers/zink/zink_instance.py
index 1ab36bee2ca..c0e813be164 100644
--- a/src/gallium/drivers/zink/zink_instance.py
+++ b/src/gallium/drivers/zink/zink_instance.py
@@ -37,6 +37,7 @@ import platform
# - nonstandard: Disables validation (cross-checking with vk.xml) if True.
EXTENSIONS = [
Extension("VK_EXT_debug_utils"),
+ Extension("VK_EXT_layer_settings"),
Extension("VK_KHR_get_physical_device_properties2"),
Extension("VK_KHR_external_memory_capabilities"),
Extension("VK_KHR_external_semaphore_capabilities"),
@@ -62,8 +63,10 @@ LAYERS = [
conditions=["zink_debug & ZINK_DEBUG_VALIDATION"]),
Layer("VK_LAYER_LUNARG_standard_validation",
conditions=["zink_debug & ZINK_DEBUG_VALIDATION", "!have_layer_KHRONOS_validation"]),
+ Layer("VK_LAYER_MESA_device_select")
]
+
REPLACEMENTS = {
"VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION_NAME" : "VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME"
}
@@ -87,6 +90,7 @@ struct zink_screen;
struct zink_instance_info {
uint32_t loader_version;
+ bool no_device_select;
%for ext in extensions:
bool have_${ext.name_with_vendor()};
@@ -261,6 +265,20 @@ zink_create_instance(struct zink_screen *screen, struct zink_instance_info *inst
ici.ppEnabledLayerNames = layers;
ici.enabledLayerCount = num_layers;
+ VkLayerSettingEXT ds_layer = {0};
+ VkLayerSettingsCreateInfoEXT lsci = {0};
+ uint32_t no_device_select_value = instance_info->no_device_select;
+ if (have_EXT_layer_settings && have_layer_MESA_device_select) {
+ ds_layer.pLayerName = "MESA_device_select";
+ ds_layer.pSettingName = "no_device_select";
+ ds_layer.type = VK_LAYER_SETTING_TYPE_BOOL32_EXT;
+ ds_layer.valueCount = 1;
+ ds_layer.pValues = &no_device_select_value;
+ lsci.sType = VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT;
+ lsci.settingCount = 1;
+ lsci.pSettings = &ds_layer;
+ ici.pNext = &lsci;
+ }
GET_PROC_ADDR_INSTANCE_LOCAL(screen, NULL, CreateInstance);
assert(vk_CreateInstance);
diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c
index 7ec86d0090a..34eee2ba113 100644
--- a/src/gallium/drivers/zink/zink_screen.c
+++ b/src/gallium/drivers/zink/zink_screen.c
@@ -1576,6 +1576,12 @@ zink_destroy_screen(struct pipe_screen *pscreen)
glsl_type_singleton_decref();
}
+static bool
+zink_picks_device(int dev_major, uint64_t adapter_luid)
+{
+ return (dev_major > 0 && dev_major < 255) || adapter_luid;
+}
+
static int
zink_get_display_device(const struct zink_screen *screen, uint32_t pdev_count,
const VkPhysicalDevice *pdevs, int64_t dev_major,
@@ -1647,7 +1653,7 @@ choose_pdev(struct zink_screen *screen, int64_t dev_major, int64_t dev_minor, ui
bool cpu = debug_get_bool_option("LIBGL_ALWAYS_SOFTWARE", false) ||
debug_get_bool_option("D3D_ALWAYS_SOFTWARE", false);
- if (cpu || (dev_major > 0 && dev_major < 255) || adapter_luid) {
+ if (cpu || zink_picks_device(dev_major, adapter_luid)) {
uint32_t pdev_count;
int idx;
VkPhysicalDevice *pdevs;
@@ -3309,6 +3315,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
simple_mtx_lock(&instance_lock);
if (++instance_refcount == 1) {
instance_info.loader_version = zink_get_loader_version(screen);
+ instance_info.no_device_select = zink_picks_device(dev_major, adapter_luid);
instance = zink_create_instance(screen, &instance_info);
}
if (!instance) {
--
2.51.1

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

175
mesa.spec
View File

@ -3,7 +3,6 @@
%global with_radeonsi 1
%global with_vmware 1
%global with_vulkan_hw 1
%global with_vdpau 1
%if !0%{?rhel}
%global with_r300 1
%global with_r600 1
@ -52,7 +51,7 @@
%if 0%{?with_asahi}
%global asahi_platform_vulkan %{?with_vulkan_hw:,asahi}%{!?with_vulkan_hw:%{nil}}
%endif
%global extra_platform_vulkan %{?with_vulkan_hw:,broadcom,freedreno,panfrost,imagination-experimental}%{!?with_vulkan_hw:%{nil}}
%global extra_platform_vulkan %{?with_vulkan_hw:,broadcom,freedreno,panfrost,imagination}%{!?with_vulkan_hw:%{nil}}
%endif
%if !0%{?rhel}
@ -80,9 +79,9 @@
Name: mesa
Summary: Mesa graphics libraries
%global ver 25.2.7
%global ver 26.1.1
Version: %{lua:ver = string.gsub(rpm.expand("%{ver}"), "-", "~"); print(ver)}
Release: 4%{?dist}
Release: 1%{?dist}
License: MIT AND BSD-3-Clause AND SGI-B-2.0
URL: http://www.mesa3d.org
@ -99,16 +98,16 @@ Source2: https://github.com/mesonbuild/meson/releases/download/%{meson_ver}/meso
# libclc is not available in RHEL but it is required for Intel drivers since
# mesa >= 24.1.0
%global libclc_version 21.1.3
Source3: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{libclc_version}/libclc-%{libclc_version}.src.tar.xz
%global libclc_version 22.1.1
Source3: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{libclc_version}/llvm-project-%{libclc_version}.src.tar.xz
BuildRequires: libedit-devel
BuildRequires: clang-devel >= %{libclc_version}
# Build our own version
# BuildRequires: spirv-llvm-translator-tools
# spirv-llvm-translator is a dependency of libclc
%global spirv_llvm_trans_ver 21.1.2
%global spirv_llvm_trans_commit a37544fc0bb90b4e8b8d755580119c018891dfa4
%global spirv_llvm_trans_ver 22.1.1
%global spirv_llvm_trans_commit 114f5ee1cec66fe2ca733c12770c1bc196675d32
%global spirv_llvm_trans_shortcommit %(c=%{spirv_llvm_trans_commit}; echo ${c:0:7})
Source4: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/%{spirv_llvm_trans_commit}/spirv-llvm-translator-%{spirv_llvm_trans_shortcommit}.tar.gz
BuildRequires: cmake
@ -128,10 +127,10 @@ BuildRequires: wayland-devel
# https://gitlab.freedesktop.org/mesa/mesa/-/tree/main/subprojects
# but we generally want the latest compatible versions
%global rust_paste_ver 1.0.15
%global rust_proc_macro2_ver 1.0.101
%global rust_quote_ver 1.0.40
%global rust_syn_ver 2.0.106
%global rust_unicode_ident_ver 1.0.18
%global rust_proc_macro2_ver 1.0.106
%global rust_quote_ver 1.0.44
%global rust_syn_ver 2.0.115
%global rust_unicode_ident_ver 1.0.23
%global rustc_hash_ver 2.1.1
Source10: https://crates.io/api/v1/crates/paste/%{rust_paste_ver}/download#/paste-%{rust_paste_ver}.tar.gz
Source11: https://crates.io/api/v1/crates/proc-macro2/%{rust_proc_macro2_ver}/download#/proc-macro2-%{rust_proc_macro2_ver}.tar.gz
@ -140,18 +139,25 @@ Source13: https://crates.io/api/v1/crates/syn/%{rust_syn_ver}/download#/sy
Source14: https://crates.io/api/v1/crates/unicode-ident/%{rust_unicode_ident_ver}/download#/unicode-ident-%{rust_unicode_ident_ver}.tar.gz
Source15: https://crates.io/api/v1/crates/rustc-hash/%{rustc_hash_ver}/download#/rustc-hash-%{rustc_hash_ver}.tar.gz
# fix zink/device-select bug
Patch11: 0001-device-select-add-a-layer-setting-to-disable-device-.patch
Patch12: 0002-zink-use-device-select-layer-settings-to-disable-dev.patch
# Fix s390x regressions:
# https://issues.redhat.com/browse/RHEL-151315
Patch13: 0001-gallivm-handle-u16-correct-on-const-loads.patch
Patch14: 0001-Revert-dri-fix-__DRI_IMAGE_FORMAT-to-PIPE_FORMAT-map.patch
# Fix performance issue with Xorg
Patch21: 0001-drisw-Modify-drisw_swap_buffers_with_damage-to-swap-.patch
Patch22: 0002-Revert-drisw-Copy-entire-buffer-ignoring-damage-regi.patch
Patch: 0001-Fix-build-with-python-3.9.patch
Patch: 0002-Fix-enum.patch
Patch: 0003-Revert-tu-autotune-Clear-active_batches-before-histo.patch
Patch: 0004-Revert-tu-autotune-Allocate-performance-counters-fro.patch
Patch: 0005-Revert-tu-autotune-Fail-gracefully-when-CP-counters-.patch
Patch: 0006-Revert-tu-autotune-Only-lock-RPs-sustain-certain-mod.patch
Patch: 0007-Revert-tu-autotune-Allow-99-max-probability-in-profi.patch
Patch: 0008-Revert-tu-autotune-Add-render-mode-locking-to-PROFIL.patch
Patch: 0009-Revert-tu-util-Allow-setting-autotune-mode-from-dric.patch
Patch: 0010-Revert-tu-autotune-Add-prefer-SYSMEM-GMEM-mode.patch
Patch: 0011-Revert-tu-Only-emit-preempt-optimization-ambles-when.patch
Patch: 0012-Revert-tu-Disable-features-using-performance-counter.patch
Patch: 0013-Revert-tu-autotune-Add-Preempt-Optimize-mode.patch
Patch: 0014-Revert-tu-autotune-Disable-autotuning-for-small-rend.patch
Patch: 0015-Revert-tu-autotune-Prefer-SYSMEM-when-only-SW-binnin.patch
Patch: 0016-Revert-tu-autotune-Add-Profiled-algorithm.patch
Patch: 0017-Revert-tu-autotune-Improve-RP-hash.patch
Patch: 0018-Revert-tu-Rewrite-autotune-in-C.patch
Patch: 0019-Fix-is_perf_cntr_selectable-in-tu_device.cc.patch
BuildRequires: meson
BuildRequires: gcc
@ -200,9 +206,6 @@ BuildRequires: flex
%if 0%{?with_lmsensors}
BuildRequires: lm_sensors-devel
%endif
%if 0%{?with_vdpau}
BuildRequires: pkgconfig(vdpau) >= 1.1
%endif
%if 0%{?with_va}
BuildRequires: pkgconfig(libva) >= 0.38.0
%endif
@ -247,6 +250,7 @@ BuildRequires: pkgconfig(vulkan)
%if 0%{?with_d3d12}
BuildRequires: pkgconfig(DirectX-Headers) >= 1.614.1
%endif
BuildRequires: libatomic
%description
%{summary}.
@ -257,6 +261,7 @@ Provides: mesa-dri-filesystem = %{?epoch:%{epoch}:}%{version}-%{release}
Obsoletes: mesa-omx-drivers < %{?epoch:%{epoch}:}%{version}-%{release}
Obsoletes: mesa-libd3d < %{?epoch:%{epoch}:}%{version}-%{release}
Obsoletes: mesa-libd3d-devel < %{?epoch:%{epoch}:}%{version}-%{release}
Obsoletes: mesa-vdpau-drivers < %{?epoch:%{epoch}:}%{version}-%{release}
%description filesystem
%{summary}.
@ -330,15 +335,6 @@ Obsoletes: %{name}-vaapi-drivers < 22.2.0-5
%{summary}.
%endif
%if 0%{?with_vdpau}
%package vdpau-drivers
Summary: Mesa-based VDPAU drivers
Requires: %{name}-filesystem%{?_isa} = %{?epoch:%{epoch}:}%{version}-%{release}
%description vdpau-drivers
%{summary}.
%endif
%package libgbm
Summary: Mesa gbm runtime library
Provides: libgbm
@ -448,9 +444,9 @@ path = "src/nouveau/nil/lib.rs"
# only direct dependencies need to be listed here
[dependencies]
paste = "$(grep ^directory subprojects/paste.wrap | sed 's|.*-||')"
syn = { version = "$(grep ^directory subprojects/syn.wrap | sed 's|.*-||')", features = ["clone-impls"] }
rustc-hash = "$(grep ^directory subprojects/rustc-hash.wrap | sed 's|.*-||')"
paste = "$(grep ^directory subprojects/paste*.wrap | sed 's|.*-||')"
syn = { version = "$(grep ^directory subprojects/syn*.wrap | sed 's|.*-||')", features = ["clone-impls"] }
rustc-hash = "$(grep ^directory subprojects/rustc-hash*.wrap | sed 's|.*-||')"
_EOF
%if 0%{?vendor_nvk_crates}
%cargo_prep -v subprojects/packagecache
@ -500,14 +496,19 @@ export PKG_CONFIG_PATH=%{buildroot}%{_libdir}/pkgconfig:%{buildroot}%{_datadir}/
export PATH=%{buildroot}%{_bindir}:$PATH
# Build libclc
cd libclc-%{libclc_version}.src
cd llvm-project-%{libclc_version}.src/libclc
export CFLAGS="%{build_cflags} -D__extern_always_inline=inline"
export CC=clang
%cmake -GNinja \
-DCMAKE_INSTALL_DATADIR:PATH=%{_lib} \
-DLLVM_DIR="/usr/lib64/cmake/llvm/" \
-DLIBCLC_TARGETS_TO_BUILD="spirv-mesa3d-;spirv64-mesa3d-" \
-DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" \
-DLLVM_SPIRV=%{buildroot}%{_bindir}/llvm-spirv
%cmake_build
%cmake_install
unset CC
unset CFLAGS
cd -
sed -e "s!libexecdir=!libexecdir=\/%{buildroot}!" -i %{buildroot}%{_libdir}/pkgconfig/libclc.pc
@ -528,7 +529,7 @@ export RUSTFLAGS="%build_rustflags"
export MESON_PACKAGE_CACHE_DIR="%{cargo_registry}/"
%endif
rewrite_wrap_file() {
sed -e "/source.*/d" -e "s/${1}-.*/$(basename ${MESON_PACKAGE_CACHE_DIR:-subprojects/packagecache}/${1}-*)/" -i subprojects/${1}.wrap
sed -e "/source.*/d" -e "s/^directory = ${1}-.*/directory = $(basename ${MESON_PACKAGE_CACHE_DIR:-subprojects/packagecache}/${1}-*)/" -i subprojects/${1}*.wrap
}
rewrite_wrap_file proc-macro2
@ -546,7 +547,6 @@ rewrite_wrap_file rustc-hash
%else
-Dgallium-drivers=llvmpipe,virgl \
%endif
-Dgallium-vdpau=%{?with_vdpau:enabled}%{!?with_vdpau:disabled} \
-Dgallium-va=%{?with_va:enabled}%{!?with_va:disabled} \
-Dgallium-mediafoundation=disabled \
-Dteflon=%{?with_teflon:true}%{!?with_teflon:false} \
@ -568,6 +568,7 @@ rewrite_wrap_file rustc-hash
-Dshared-llvm=enabled \
-Dvalgrind=%{?with_valgrind:enabled}%{!?with_valgrind:disabled} \
-Dbuild-tests=false \
-Ddisplay-info=disabled \
%if !0%{?with_libunwind}
-Dlibunwind=disabled \
%endif
@ -622,15 +623,51 @@ rm -f %{buildroot}%{_libdir}/pkgconfig/LLVMSPIRVLib.pc
rm -f %{buildroot}%{_datadir}/pkgconfig/wayland-protocols.pc
rm -fr %{buildroot}%{_datadir}/wayland-protocols/
# libvdpau opens the versioned name, don't bother including the unversioned
rm -vf %{buildroot}%{_libdir}/vdpau/*.so
# likewise glvnd
rm -vf %{buildroot}%{_libdir}/libGLX_mesa.so
rm -vf %{buildroot}%{_libdir}/libEGL_mesa.so
# XXX can we just not build this
rm -vf %{buildroot}%{_libdir}/libGLES*
# Remove some unused kmsro driver on x86_64
%ifarch x86_64 i686 ppc64le
rm -f %{buildroot}%{_libdir}/dri/armada-drm_dri.so
rm -f %{buildroot}%{_libdir}/dri/exynos_dri.so
rm -f %{buildroot}%{_libdir}/dri/gm12u320_dri.so
rm -f %{buildroot}%{_libdir}/dri/hdlcd_dri.so
rm -f %{buildroot}%{_libdir}/dri/hx8357d_dri.so
rm -f %{buildroot}%{_libdir}/dri/ili9163_dri.so
rm -f %{buildroot}%{_libdir}/dri/ili9225_dri.so
rm -f %{buildroot}%{_libdir}/dri/ili9341_dri.so
rm -f %{buildroot}%{_libdir}/dri/ili9486_dri.so
rm -f %{buildroot}%{_libdir}/dri/imx-dcss_dri.so
rm -f %{buildroot}%{_libdir}/dri/mediatek_dri.so
rm -f %{buildroot}%{_libdir}/dri/meson_dri.so
rm -f %{buildroot}%{_libdir}/dri/mi0283qt_dri.so
rm -f %{buildroot}%{_libdir}/dri/panel-mipi-dbi_dri.so
rm -f %{buildroot}%{_libdir}/dri/pl111_dri.so
rm -f %{buildroot}%{_libdir}/dri/repaper_dri.so
rm -f %{buildroot}%{_libdir}/dri/rockchip_dri.so
rm -f %{buildroot}%{_libdir}/dri/rzg2l-du_dri.so
rm -f %{buildroot}%{_libdir}/dri/ssd130x_dri.so
rm -f %{buildroot}%{_libdir}/dri/st7586_dri.so
rm -f %{buildroot}%{_libdir}/dri/st7735r_dri.so
rm -f %{buildroot}%{_libdir}/dri/sti_dri.so
rm -f %{buildroot}%{_libdir}/dri/sun4i-drm_dri.so
rm -f %{buildroot}%{_libdir}/dri/vkms_dri.so
rm -f %{buildroot}%{_libdir}/dri/zynqmp-dpsub_dri.so
rm -f %{buildroot}%{_libdir}/dri/ingenic-drm_dri.so
rm -f %{buildroot}%{_libdir}/dri/imx-drm_dri.so
rm -f %{buildroot}%{_libdir}/dri/imx-lcdif_dri.so
rm -f %{buildroot}%{_libdir}/dri/kirin_dri.so
rm -f %{buildroot}%{_libdir}/dri/komeda_dri.so
rm -f %{buildroot}%{_libdir}/dri/mali-dp_dri.so
rm -f %{buildroot}%{_libdir}/dri/mcde_dri.so
rm -f %{buildroot}%{_libdir}/dri/mxsfb-drm_dri.so
rm -f %{buildroot}%{_libdir}/dri/rcar-du_dri.so
rm -f %{buildroot}%{_libdir}/dri/stm_dri.so
%endif
%if ! 0%{?with_asahi}
# This symlink is unconditionally created when any kmsro driver is enabled
# We don't want this one so delete it
@ -719,14 +756,8 @@ popd
%{_libdir}/dri/i915_dri.so
%endif
%endif
%ifarch %{arm} aarch64
%if 0%{?with_asahi}
%{_libdir}/dri/apple_dri.so
%{_libdir}/dri/asahi_dri.so
%endif
%if 0%{?with_d3d12}
%{_libdir}/dri/d3d12_dri.so
%endif
%ifarch aarch64
%{_libdir}/dri/ingenic-drm_dri.so
%{_libdir}/dri/imx-drm_dri.so
%{_libdir}/dri/imx-lcdif_dri.so
@ -738,6 +769,16 @@ popd
%{_libdir}/dri/rcar-du_dri.so
%{_libdir}/dri/stm_dri.so
%endif
%ifarch %{arm} aarch64
%if 0%{?with_asahi}
%{_libdir}/dri/apple_dri.so
%{_libdir}/dri/asahi_dri.so
%endif
%if 0%{?with_d3d12}
%{_libdir}/dri/d3d12_dri.so
%endif
%endif
%if 0%{?with_vc4}
%{_libdir}/dri/vc4_dri.so
%endif
@ -794,6 +835,10 @@ popd
%{_libdir}/dri/vkms_dri.so
%{_libdir}/dri/zynqmp-dpsub_dri.so
%endif
%ifarch x86_64 i686 ppc64le
%{_libdir}/dri/udl_dri.so
%endif
%if 0%{?with_vulkan_hw}
%{_libdir}/dri/zink_dri.so
%endif
@ -813,22 +858,6 @@ popd
%{_libdir}/dri/virtio_gpu_drv_video.so
%endif
%if 0%{?with_vdpau}
%files vdpau-drivers
%dir %{_libdir}/vdpau
%{_libdir}/vdpau/libvdpau_nouveau.so.1*
%if 0%{?with_r600}
%{_libdir}/vdpau/libvdpau_r600.so.1*
%endif
%if 0%{?with_radeonsi}
%{_libdir}/vdpau/libvdpau_radeonsi.so.1*
%endif
%if 0%{?with_d3d12}
%{_libdir}/vdpau/libvdpau_d3d12.so.1*
%endif
%{_libdir}/vdpau/libvdpau_virtio_gpu.so.1*
%endif
%if 0%{?with_d3d12}
%files dxil-devel
%{_bindir}/spirv2dxil
@ -869,24 +898,28 @@ popd
%{_libdir}/libvulkan_intel_hasvk.so
%{_datadir}/vulkan/icd.d/intel_hasvk_icd.*.json
%endif
%ifarch %{arm} aarch64
%ifarch aarch64 x86_64 %{ix86}
%if 0%{?with_asahi}
%{_libdir}/libvulkan_asahi.so
%{_datadir}/vulkan/icd.d/asahi_icd.*.json
%endif
%ifarch aarch64
%{_libdir}/libvulkan_broadcom.so
%{_datadir}/vulkan/icd.d/broadcom_icd.*.json
%{_libdir}/libvulkan_freedreno.so
%{_datadir}/vulkan/icd.d/freedreno_icd.*.json
%{_libdir}/libvulkan_panfrost.so
%{_datadir}/vulkan/icd.d/panfrost_icd.*.json
%{_libdir}/libpowervr_rogue.so
%{_libdir}/libvulkan_powervr_mesa.so
%{_datadir}/vulkan/icd.d/powervr_mesa_icd.*.json
%endif
%endif
%endif
%changelog
* Tue Jun 16 2026 Jocelyn Falempe <jfalempe@redhat.com> - 26.1.1-1
Resolves: https://redhat.atlassian.net/browse/RHEL-135263
* Mon Feb 23 2026 José Expósito <jexposit@redhat.com> - 25.2.7-4
- Fix s390x regressions
Resolves: https://issues.redhat.com/browse/RHEL-151315

14
sources
View File

@ -1,11 +1,11 @@
SHA512 (libclc-21.1.3.src.tar.xz) = daf38b915bcc8065c56a581ccbca90ccc0d41a54489392a2ae6ec3e0a8782ea231bc6edb9624cd879d698074017ee3c1d2b038e388cb75ea08a80ee3e27a57d1
SHA512 (mesa-25.2.7.tar.xz) = 87dd815e0d11d6ec0eb969ee93d3f376103bb899d90599e0b7902394e41c58139384df79f89633e132ca969348d3320f55308a74651d409b454d51f1bcda27bc
SHA512 (llvm-project-22.1.1.src.tar.xz) = dddf09651c0e77caa83284788765016b023a9e239cfe35820bab7be64b68218e86bcf39bb07ee14dcddf7b0974b551344d2bff0e109cc9458b0394a3c940917c
SHA512 (mesa-26.1.1.tar.xz) = 384a7db33d2f06e287337329f2f17503082ba6b1cd876a1884e940fdb6193ffae6d6b14344625256f3b3b39972ad697130a4d2ea25c40979f7aa76c2176f7988
SHA512 (meson-1.7.0.tar.gz) = a5d1f00b193ca37ae64f85c9dfc29a2661c167d82d9953b9acd1393b222b05fa5fc03ffdf00fd1ae7a2014da3a7366c35f70bf02e3204e929b74f7b00c17c840
SHA512 (paste-1.0.15.tar.gz) = 5026d3ec7141ec4e2517a0b1283912d0801e9356f77b703d954b379439b8d85e3886d42fb28f7835edaeeac465582da14233564fb010c71425a59c9e1cbd46b4
SHA512 (proc-macro2-1.0.101.tar.gz) = 3171c807d24371da2931f9c706fb3129bb9bf3ac40418e5d14cfc372baf96e5fee9ede72091163858e3ba0b4f88594efa1031b0bb7128ca68e7b847dead6856c
SHA512 (quote-1.0.40.tar.gz) = 45a76e22a2b0bec47e4ba73c3b73cc41d821dfcce9876134c5d8eed514da214aee4ce7612e372c8709f888c0d8b9b7e5442f27adb7a59f3571f0339ed7e2ac99
SHA512 (proc-macro2-1.0.106.tar.gz) = b726e2c92af434bfa88cd4f53c3fe6db647503567675fb439890dee3d15f5111137e3242b28d164114ce081c10acf3fd11950753ddb349190c87ee04e7d97744
SHA512 (quote-1.0.44.tar.gz) = 6c1e9b31e0c8bd13cd865e6846dc243d88f2c057adeb8e674117bdcb46947219a6a352a6a50be1132c483f55331e6556275ac514513dbf017825c64e5d96010d
SHA512 (rustc-hash-2.1.1.tar.gz) = 87097d98d47f327d000041ab13acddc366f1500d9c3e5c82169c3358112c7a7c03701c9b3c2c81d9f9da65b7ebac1c479b179dfaf7c059cd0b929b4673e51084
SHA512 (spirv-llvm-translator-a37544f.tar.gz) = 9e790322beead5fd2934140e8f4870978a860fe03aaffd042ff74578b76f7f404dcd0dbaea1d6ee2a408b477e5de9819910a5b86ce4ba8a018e21b7d60ed5e97
SHA512 (syn-2.0.106.tar.gz) = e07e1058770fa3f1039eaf335340cefb597c0dd11bb90fec9fa777ca5815d0e0bb1711bb4db52cac77e205dd68fbe2bce0e1aa9895c2a52a1ea6d7758d13424c
SHA512 (unicode-ident-1.0.18.tar.gz) = d11f89fb696f9e2953c96a40b5478832651b268c83b9c7a700b07e768e795d6e8dc346597d1226df21219d36866768d1f640bd8edb68db8bd3d5d437b2bfd324
SHA512 (spirv-llvm-translator-114f5ee.tar.gz) = 5e983a5b4a7353448a5ccbf75ab37600e9f2157a1bcc6920e79cd762ffb4d07985ee54d9809f7f97b4495d44d89ccd66bebb67325569e9eef63014230c44bf56
SHA512 (syn-2.0.115.tar.gz) = 47afe5cd05da90d116e35259b4e3c03236e719ef8f62fbf1d32e4e7e78b454571f9e88e77e86665e815d5dcfe065c75fff987f57ba66942277f8f16fb680ead3
SHA512 (unicode-ident-1.0.23.tar.gz) = f2e57950b87ab93456a74788c22b8f865fe8864147104507ed40cc87979c0a06007eec17c2c2241cb586b5e9600e5b518059611fde6325c7a3a79265751f8fe0
SHA512 (wayland-protocols-1.41.tar.xz) = 6122fe4f20a1a0908abd631ff31302b56018050e5e835c1413d5b40a527980c30859ed9cddf595213f7d5eb1d50baaf6adc312cef9279d60b8a15e447e259863