From a3b33e4103e0a90112a730d249635c2c766e57d3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:35:51 +0200 Subject: [PATCH] MathUtils: make SMatrixGPU compile as MSL Three separate issues: * Metal has no static storage duration inside a function, so MatRepSymGPU::off() drops the static on its offset table. Nothing is lost by dropping it everywhere rather than forking: arrays, unlike scalars, are emitted into read-only data either way. On the host it is marginally better, since the static form reached the table through the GOT. * operator=(Expr) now takes the expression by value. MSL folds the address space into a deduced parameter, so the generic operator=(const M&) deduced M = thread Expr<...>, matched exactly, beat the Expr overload and then tried mRep = rhs.mRep on an expression. A by-value parameter has no address space to deduce, so the Expr overload wins on Metal as it already did elsewhere. Expr is two references, so there is no copy cost. * Metal supports up to C++17, so it needs the same treatment as OpenCL for a requires-clause. --- Common/MathUtils/include/MathUtils/SMatrixGPU.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Common/MathUtils/include/MathUtils/SMatrixGPU.h b/Common/MathUtils/include/MathUtils/SMatrixGPU.h index 8158a93666a92..2e551aac98d24 100644 --- a/Common/MathUtils/include/MathUtils/SMatrixGPU.h +++ b/Common/MathUtils/include/MathUtils/SMatrixGPU.h @@ -340,7 +340,7 @@ class MatRepSymGPU static GPUdi() int off(int i) { - static constexpr auto v = row_offsets_utils::make(off1); + constexpr auto v = row_offsets_utils::make(off1); return v[i]; } @@ -453,7 +453,7 @@ class SMatrixGPU GPUd() SMatrixGPU(const SMatrixGPU& rhs); template GPUd() SMatrixGPU(const Expr& rhs); - template + template GPUd() SMatrixGPU& operator=(const M& rhs); template GPUd() SMatrixGPU& operator=(const Expr& rhs); @@ -518,7 +518,7 @@ class SMatrixGPU R mRep; }; -#ifndef __OPENCL__ // TODO: current C++ for OpenCL 2021 is at C++17, so no concepts. But we don't need this trick for OpenCL anyway, so we can just hide it. +#if !defined(__OPENCL__) && !defined(__METAL__) // TODO: current C++ for OpenCL 2021 and MSL 4.1 are both at C++17, so no concepts. But we don't need this trick there anyway, so we can just hide it. template requires(sizeof(typename X::traits_type::pos_type) != 0) // do not provide a template to fair::Logger, etc... (pos_type is a member type of all std::ostream classes) GPUd() X& operator<<(Y& y, const SMatrixGPU&) @@ -684,8 +684,8 @@ GPUdi() SMatrixGPU& SMatrixGPU::operator=(const Expr } template -template -GPUdi() SMatrixGPU& SMatrixGPU::operator=(const M & rhs) +template +GPUdi() SMatrixGPU& SMatrixGPU::operator=(const M& rhs) { mRep = rhs.mRep; return *this;