cycle: add --adreno-cs-samplers for the CS sampler opt-in

installed-fresh --adreno-cs-samplers appends the guest boot-arg
adreno_cs_samplers=1, the run-time half of SnapAdreno's
ADRENO_IB_CS_SAMPLERS: the IB validator admits CS sampler loads of up
to 8 units and AdrenoX2 publishes AdrenoIBComputeSamplers, so the
ADRENO_SETTINGS_ICONS plug-in encodes CoreImage's multi-input kernels.
An AdrenoX2 built without the define ignores the boot-arg. Without the
option the boot-argument addition is unchanged.

tools/test-adreno-cs-samplers.py: the default addition is unchanged,
the flag adds the boot-arg once (also beside --edp-backlight,
--input-fnkeys and --single-user), cycle.py's parser reaches the
namespace, AdrenoX2 reads exactly this name under the define, and the
desktop, desktop-nocoherent, desktop-backlight and desktop-next
profiles build AdrenoX2 and adreno-ib-command with it. A misspelt
boot-arg in installed_fresh.py fails it. docs/RUNNING.md lists the
flag and drops "no option yet".
This commit is contained in:
Acelogic committed 2026-10-24 03:48:50 -04:00
1 parent a254f01fc9
commit cf01e689d7
4 files changed
+103 -3

No files matched your search

+4 -3
View File
@@ -142,7 +142,7 @@ The flags fall into these groups:
| Console and early stop | `--console`, `--single-user`, `--early-stop-delay`, `--let-panic`, `--panic-serve` |
| Input | `--input`, `--input-touchpad`, `--input-ptp`, `--input-active-us` |
| Present path | `--present-dartpool`, `--present-resident`, `--present-beam`, `--present-va-reclaim`, `--present-maint`, `--present-latch`, `--present-pipeline` |
| GPU | `--ib-async`, `--gpu-recover`, `--gpu-va-wide`, `--gpu-coherent`, `--resident-mib`, `--adreno-fill-br`, `--adreno-fence-br`, `--gpu-x290-survey` |
| GPU | `--ib-async`, `--gpu-recover`, `--gpu-va-wide`, `--gpu-coherent`, `--resident-mib`, `--adreno-fill-br`, `--adreno-fence-br`, `--adreno-cs-samplers`, `--gpu-x290-survey` |
| Panel brightness | `--edp-backlight`, `--edp-backlight-mode` |
| Clocks and bandwidth | `--thermal-guard`, `--gpu-dvfs`, `--gpu-dvfs-ceiling`, `--cpu-dvfs`, `--ddr-vote`, `--llcc`, `--bw-probe` |
| Storage | `--nvme-async`, `--nvme-converted` |
@@ -229,8 +229,9 @@ installed and only continues the boot).
The kext side of the icons inside System Settings panes, `ADRENO_IB_CS_SAMPLERS`
in the desktop AdrenoX2 profiles, is off unless the guest boots with
`adreno_cs_samplers=1`. `tools/cycle.py` has no option that adds that boot-arg
yet.
`adreno_cs_samplers=1`, which `tools/cycle.py installed-fresh --adreno-cs-samplers`
adds (`tools/test-adreno-cs-samplers.py`). An AdrenoX2 built without the define
ignores the boot-arg.
## Exit codes
+6
View File
@@ -491,6 +491,12 @@ def parse(argv=None):
help='guest boot-arg adreno_present_maint=1: AdrenoDisplay keeps its layer-0 clean+invalidate pass '
'even while the beam is LOCKED (tear-free fix2 skips it then); for b12v8\'s stale bands; '
'give it to every mode of the attempt')
p.add_argument('--adreno-cs-samplers', action='store_true',
help='guest boot-arg adreno_cs_samplers=1: an AdrenoX2 built with ADRENO_IB_CS_SAMPLERS (the desktop '
'profiles since agents/settings-icons; others ignore it) lets the IB validator admit CS sampler '
'loads of up to 8 units and publishes AdrenoIBComputeSamplers, so an ADRENO_SETTINGS_ICONS '
'plug-in encodes CoreImage\'s multi-input kernels (folder, document and Safari icons in System '
'Settings panes); give it to every mode of the attempt')
p.add_argument('--spmi-scratch', action='store_true',
help='SNAP_SPMI_SCRATCH: the emulated SPMI controller also serves the PMU scratch-pad registers '
'(f700-f7ff, 8f80-8fff) from RAM, so AppleDialogSPMIPMU::_readRegs stops failing with e00002bc '
+2
View File
@@ -1158,6 +1158,8 @@ def boot_addition(args):
extra = []
if getattr(args, 'present_maint', False):
extra.append('adreno_present_maint=1')
if getattr(args, 'adreno_cs_samplers', False):
extra.append('adreno_cs_samplers=1') # read only by an ADRENO_IB_CS_SAMPLERS AdrenoX2 (configureDevice)
if getattr(args, 'gpu_coherent', False):
extra.append('adreno_coherent=1') # the kext still skips only after the monitor's self-test said ON
if getattr(args, 'gpu_coherent_force', False):
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
"""Host test for cycle.py installed-fresh --adreno-cs-samplers. No A16 access.
Without the option the boot-argument addition is exactly what earlier attempts qualified; with it, it appends
adreno_cs_samplers=1 once. The other half of the contract is SnapAdreno's: the boot-arg name is the one AdrenoX2's
configureDevice reads, that read sits under ADRENO_IB_CS_SAMPLERS, and the desktop profiles build AdrenoX2 and
adreno-ib-command with that define (a kext without it ignores the boot-arg).
"""
import argparse
import importlib.util
import os
import re
import subprocess
import sys
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / 'tools'))
from cycle_lib import installed_fresh as fresh # noqa: E402
spec = importlib.util.spec_from_file_location('cycle_cli', ROOT / 'tools/cycle.py')
cli = importlib.util.module_from_spec(spec)
spec.loader.exec_module(cli)
BASE = ' '.join([fresh.TIMESYNC_FLAG, fresh.COMPRESSOR_SW_FLAG])
KEXT = ROOT / 'gpu/adreno-kext/kext'
BOOT_ARG = 'adreno_cs_samplers'
DEFINE = 'ADRENO_IB_CS_SAMPLERS'
def ns(**kw):
return argparse.Namespace(**kw)
def profile_units(name):
"""{unit: defines} of a SnapAdreno profile, as build.sh sources it."""
script = f'. "$D/profiles/{name}.sh"; set | grep "^U_"'
out = subprocess.run(['sh', '-c', script], env=dict(os.environ, D=str(KEXT)), capture_output=True, text=True,
check=True).stdout
units = {}
for line in out.splitlines():
unit, _, value = line.partition('=')
units[unit[2:]] = value.strip('\'"').split()
return units
class AdrenoCsSamplers(unittest.TestCase):
def test_default_unchanged(self):
self.assertEqual(fresh.boot_addition(ns()), BASE)
self.assertEqual(fresh.boot_addition(ns(adreno_cs_samplers=False)), BASE)
def test_flag_adds_the_boot_arg_once(self):
self.assertEqual(fresh.boot_addition(ns(adreno_cs_samplers=True)), f'{BASE} {BOOT_ARG}=1')
line = fresh.boot_addition(ns(console=True, single_user=True, adreno_cs_samplers=True, edp_backlight=True,
input=True, input_fnkeys=3, resident_mib=1536))
words = line.split()
self.assertEqual(words.count(f'{BOOT_ARG}=1'), 1, line)
for word in ('adreno_backlight=1', 'snap_i2c_fnkeys=3', 'adreno_resident_mib=1536', fresh.SINGLE_USER_FLAG):
self.assertIn(word, words, line)
def test_cli_reaches_args(self):
base = ['installed-fresh', '--prefix', 'x', '--variant', 'fast', '--check']
self.assertFalse(cli.parse(base).adreno_cs_samplers)
self.assertTrue(cli.parse(base + ['--adreno-cs-samplers']).adreno_cs_samplers)
def test_kext_reads_this_boot_arg_under_its_define(self):
src = (KEXT / 'src/AdrenoX2/device.cpp').read_text()
reads = re.findall(r'PE_parse_boot_argn\("(adreno_cs_samplers)"', src)
self.assertEqual(reads, [BOOT_ARG])
depth, guarded = [], None
for line in src.splitlines():
s = line.strip()
if s.startswith('#if'):
depth.append(DEFINE in s)
elif s.startswith('#endif'):
depth.pop()
elif f'"{BOOT_ARG}"' in s and 'PE_parse_boot_argn' in s:
guarded = any(depth)
self.assertTrue(guarded, 'the boot-arg read is not under ADRENO_IB_CS_SAMPLERS')
def test_desktop_profiles_build_the_opt_in(self):
for name in ('desktop-nocoherent', 'desktop', 'desktop-backlight', 'desktop-next'):
units = profile_units(name)
for unit in ('AdrenoX2', 'adreno_ib_command'):
self.assertIn(f'-D{DEFINE}=1', units.get(unit, []), f'{name} {unit}')
if __name__ == '__main__':
unittest.main()