docs,kk: Add KosmicKrisp documentation
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Adds build instructions and workarounds documentation.
Workarounds documentation only has the biggest offenders and
there are probably way more in code that need yet to be
documented.

Reviewed-by: Arcady Goldmints-Orlov <arcady@lunarg.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38232>
This commit is contained in:
Aitor Camacho 2025-11-03 12:44:38 +09:00 committed by Marge Bot
parent f187b537b5
commit 93460e969e
4 changed files with 236 additions and 31 deletions

View file

@ -0,0 +1,97 @@
KosmicKrisp
###########
KosmicKrisp is a Vulkan conformant implementation for macOS on Apple Silicon
hardware. It is implemented on top of Metal 4, which requires macOS 26 and up.
No iOS support is present as of now. However, iOS was taken into consideration
during development to support A14 Bionic GPUs and upwards.
Building
********
The following build instructions assume Homebrew as the package manager to
install dependencies. Homebrew homepage https://brew.sh/
Homebrew install command line:
.. code-block:: sh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Terminal restart is recommended after Homebrew installation.
Requirements
============
- Xcode and Xcode command line tools
- Homebrew packages
- meson (1.9.1+, can also be installed as a Python package)
- cmake
- pkg-config
- libclc
- llvm
- spirv-llvm-translator
Due to potential conflicts, Homebrew will not add `llvm` to the path. To add
`llvm` to future terminal instances:
.. code-block:: sh
echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> ~/.zshrc
To add `llvm` to current terminal instance:
.. code-block:: sh
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
- Python
- Python packages
- mako
- packaging
- pyyaml
- meson (1.9.1+, if not installed through Homebrew)
Since Homebrew manages the Python environment, it is encouraged to create a
Python virtual environment and install all packages in that environment. To
create a Python virtual environment (e.g. ``$HOME/venv_mesa``):
.. code-block:: sh
python3 -m venv $HOME/venv_mesa
To enable a Python virtual environment:
.. code-block:: sh
source $HOME/venv_mesa/bin/activate
Build instructions
==================
Out of tree build directory is recommended.
Once all requirements have been installed, the following command line can be
used to create a debug build:
.. code-block:: sh
meson setup <path/to/mesa> --buildtype=debug -Dplatforms=macos -Dvulkan-drivers=kosmickrisp -Dgallium-drivers= -Dopengl=false -Dzstd=disabled
Metal workarounds
*****************
Different workarounds are applied throughout the project to avoid issues such
as:
- Metal API and Vulkan API discrepancies
- Metal bugs
- MSL compiler bugs
- MSL compiler crashes
These workarounds can be found in:
.. toctree::
:maxdepth: 1
kosmickrisp/workarounds

View file

@ -0,0 +1,135 @@
KosmicKrisp workarounds
#######################
This file documents the relevant issues found in either Metal, the MSL
compiler or any other component we have no control over that needed to be
worked around to accomplish Vulkan conformance.
All workarounds must be documented here and no code comment info should be
provided other than the name ``KK_WORKAROUND_#``.
Once a workaround was removed from the code, the code comment will be
removed but the documentation here will be kept.
Template
========
Use the following template to create documentation for a new workaround:
.. code-block::
KK_WORKAROUND_#
---------------
| macOS version:
| Metal ticket:
| Metal ticket status:
| CTS test failure/crash:
| Comments:
| Log:
``macOS version`` needs to have the OS version with which it was found.
``Metal ticket`` needs to be either the Metal ticket number with the GitLab
handle of the user that reported the ticket or ``Unreported``.
``Metal ticket status`` needs to be either ``Fixed in macOS # (Build hash)``,
``Waiting resolution`` or empty if unreported. If Apple reported that the issue
was fixed, but no user has verified the fix, append ``[Untested]``.
``CTS test failure/crash`` (remove ``failure`` or ``crash`` based on test
behavior) needs to be the name of the test or test family the issue can be
reproduced with.
``Comments`` needs to include as much information on the issue and how the
workaround fixes it.
``Log`` needs to have the dates (yyyy-mm-dd, the only correct date format) with
info on what was updated.
Workarounds
===========
KK_WORKAROUND_3
---------------
| macOS version: 15.4.x
| Metal ticket: FB20113490 (@aitor)
| Metal ticket status: Waiting resolution
| CTS test failure: ``dEQP-VK.subgroups.ballot_other.*.subgroupballotfindlsb``
| Comments:
``simd_is_first`` does not seem to behave as documented in the MSL
specification. The following code snippet misbehaves:
.. code-block:: c
if (simd_is_first())
temp = 3u;
else
temp = simd_ballot(true); /* <- This will return all active threads... */
The way to fix this is by changing the conditional to:
.. code-block:: c
if (simd_is_first() && (ulong)simd_ballot(true))
temp = 3u;
else
temp = (ulong)simd_ballot(true);
| Log:
| 2025-09-09: Workaround implemented and reported to Apple
KK_WORKAROUND_2
---------------
| macOS version: 15.4.x
| Metal ticket: Not reported
| Metal ticket status:
| CTS test crash: ``dEQP-VK.graphicsfuzz.cov-nested-loops-never-change-array-element-one`` and ``dEQP-VK.graphicsfuzz.disc-and-add-in-func-in-loop``
| Comments:
We need to loop to infinite since MSL compiler crashes if we have something
like (simplified version):
.. code-block:: c
while (true) {
if (some_conditional) {
break_loop = true;
} else {
break_loop = false;
}
if (break_loop) {
break;
}
}
The issue I believe is that ``some_conditional`` wouldn't change the value no
matter in which iteration we are (something like fetching the same value from
a buffer) and the MSL compiler doesn't seem to like that much to the point it
crashes.
The implemented solution is to change the ``while(true)`` loop with
``for (uint64_t no_crash = 0u; no_crash < UINT64_MAX; ++no_crash)``, which
tricks the MSL compiler into believing we are not doing an infinite loop
(wink wink).
| Log:
| 2025-09-08: Workaround implemented
KK_WORKAROUND_1
---------------
| macOS version: 15.4.x
| Metal ticket: FB17604106 (@aitor)
| Metal ticket status: [Untested] Fixed in macOS 26 Beta (25A5279m)
| CTS test crash: ``dEQP-VK.glsl.indexing.tmp_array.vec3_dynamic_loop_write_dynamic_loop_read_fragment``
| Comments:
Uninitialized local scratch variable causes the MSL compiler to crash.
Initialize scratch to avoid issue.
| Log:
| 2025-05-14: Workaround implemented and reported to Apple
| 2025-06-14: Apple reported back saying it is now fixed in macOS 26 Beta (Build 25A5279m)

View file

@ -83,6 +83,7 @@ Linux, FreeBSD, and other operating systems.
drivers/asahi
drivers/d3d12
drivers/freedreno
drivers/kosmickrisp
drivers/lima
drivers/llvmpipe
drivers/nvk

View file

@ -111,6 +111,7 @@ emit_local_vars(struct nir_to_msl_ctx *ctx, nir_shader *shader)
shader->info.shared_size);
}
if (shader->scratch_size) {
/* KK_WORKAROUND_1 */
P_IND(ctx, "uchar scratch[%d] = {0};\n", shader->scratch_size);
}
if (BITSET_TEST(shader->info.system_values_read,
@ -1355,16 +1356,7 @@ intrinsic_to_msl(struct nir_to_msl_ctx *ctx, nir_intrinsic_instr *instr)
P(ctx, ");\n");
break;
case nir_intrinsic_elect:
/* If we don't add && "(ulong)simd_ballot(true)"" the following CTS tests
* fail:
* dEQP-VK.subgroups.ballot_other.graphics.subgroupballotfindlsb
* dEQP-VK.subgroups.ballot_other.compute.subgroupballotfindlsb
* Weird Metal bug:
* if (simd_is_first())
* temp = 3u;
* else
* temp = simd_ballot(true); <- This will return all active threads...
*/
/* KK_WORKAROUND_3 */
P(ctx, "simd_is_first() && (ulong)simd_ballot(true);\n");
break;
case nir_intrinsic_read_first_invocation:
@ -1789,27 +1781,7 @@ cf_node_to_metal(struct nir_to_msl_ctx *ctx, nir_cf_node *node)
case nir_cf_node_loop: {
nir_loop *loop = nir_cf_node_as_loop(node);
assert(!nir_loop_has_continue_construct(loop));
/* We need to loop to infinite since MSL compiler crashes if we have
something like (simplified version):
* // clang-format off
* while (true) {
* if (some_conditional) {
* break_loop = true;
* } else {
* break_loop = false;
* }
* if (break_loop) {
* break;
* }
* }
* // clang-format on
* The issue I believe is that some_conditional wouldn't change the value
* no matter in which iteration we are (something like fetching the same
* value from a buffer) and the MSL compiler doesn't seem to like that
* much to the point it crashes.
* With this for loop now, we trick the MSL compiler into believing we are
* not doing an infinite loop (wink wink)
*/
/* KK_WORKAROUND_2 */
P_IND(ctx,
"for (uint64_t no_crash = 0u; no_crash < %" PRIu64
"; ++no_crash) {\n",