Render advanced 3D graphics and perform data-parallel computations using graphics processors using Metal.

Posts under Metal tag

200 Posts

Post

Replies

Boosts

Views

Activity

Xcode 27.0 Metal Toolchain download stuck at "Beginning asset download..."
Hi everyone, I downloaded Xcode 27.0 today because I need the Metal Toolchain for Unreal Engine 5.6 on my Mac. Xcode itself is installed and working, but Unreal is having issues because the Metal Toolchain doesn't seem to be installed. When I run: xcrun metal --version I get: error: error: cannot execute tool 'metal' due to missing Metal Toolchain; use: xcodebuild -downloadComponent MetalToolchain I tried: sudo xcodebuild -downloadComponent MetalToolchain but it just stays on: Beginning asset download... If I cancel it, I get: xcodebuild: error: Download was cancelled. (Asset download for com.apple.MobileAsset.MetalToolchain ...) I've also run: xcodebuild -runFirstLaunch and installed the latest Command Line Tools for Xcode 27.0 through Software Update. xcrun --find metal does find the executable, but the actual Metal Toolchain appears to be missing. I'm mainly trying to get this working so I can use Unreal Engine 5.6. Has anyone had this issue with Xcode 27, or know the correct way to install the Metal Toolchain when xcodebuild -downloadComponent gets stuck at "Beginning asset download"? Thanks!
1
1
444
4h
D3DMetal: present hangs permanently when the game window becomes occluded
Environment macOS 27.0.1 (26A434), Apple M4 Pro Apple Game Porting Toolkit 4.0b2 (D3DMetal.framework) via CrossOver 27 D3D12 game, borderless fullscreen window (2540x1650) Symptom When the game window becomes occluded — Mission Control, a system OSD (volume/brightness), or another window being brought to the front — the game never renders another frame. It does not crash: GPU utilization drops to 0%, the process stays alive with near-zero CPU, and it never recovers. Killing and restarting the game is the only way out. D3DMetal log at the moment it happens: [D3DMetal:FATAL:%llX][%s:%d] Failed to get drawable for HWND. Run with D3DM_NO_WINDOW=1 env. Question When CAMetalLayer/nextDrawable has no drawable (window not visible), is there a supported way for D3DMetal to skip frames instead of blocking forever? Is there an environment variable or configuration that makes D3DMetal treat "no drawable" as a recoverable condition? Does D3DM_NO_WINDOW=1 apply here, or is it only for headless/offscreen use? I understand apps should handle a nil drawable and continue, but this path is inside D3DMetal. Any guidance would help.
3
0
1.2k
16h
iOS app running on macOS 27.0.1 terminated on suspension due to a Metal archiveUsage.db file lock (0xDEAD10CC)
Hello, We are investigating an issue where our iOS app, running as a “Designed for iPad” app on an Apple Silicon Mac, is terminated when it is suspended in the background. Environment OS: macOS 27.0.1 Hardware: Apple Silicon Mac App type: An iOS/iPadOS app running on Mac, rather than a separately developed macOS app The app uses Core Image’s CIContext to generate some image effects Steps to reproduce Launch the app on Mac and start playing a podcast. Move the app to the background. Start playback on another device. Our app’s cross-device playback coordination pauses playback on the Mac. After a short period, the Mac app is terminated. We have also observed similar termination after visiting a screen that uses Core Image image effects. Actual result The debugger reports: Terminated due to signal 9 RunningBoard logs indicate that the app was terminated with code 0xDEAD10CC because it was suspended while holding a disallowed shared file lock. The file identified in the log is: /var/folders/.../C/app.podcast.cosmos/app.podcast.cosmos/com.apple.metal/archiveUsage.db/lock.mdb The relevant log message includes: suspended while holding a shared file lock Investigation so far Using breakpoints on open and openat, we captured a call stack corresponding to: App creates a CIContext → Core Image CI::MetalContext → Metal recordBinaryArchiveUsage → archiveUsage.db/lock.mdb is opened We also tried: CIContext(options: [.useSoftwareRenderer: true]) However, in our test environment, we still observed Metal initialization and access to the relevant cache files. This option did not avoid the issue. For the gradient-mask generation code we had identified, we replaced the Core Image implementation with a CPU implementation using CGContext and CGGradient, avoiding CIContext creation on that path. After repeatedly testing the same reproduction steps, we could no longer reproduce the termination in that scenario. This suggests a connection to the Metal cache file lock accessed during Core Image initialization. However, we have not established the exact lifetime or internal owner of the lock, and we have not confirmed a thread deadlock. Questions Is this a known issue involving Core Image/Metal and suspension of iOS apps running on macOS 27.0.1? Why would a system-managed Metal cache file lock cause the app to be terminated with 0xDEAD10CC when suspended? Is there a recommended context configuration, resource cleanup procedure, or lifecycle handling approach that allows us to continue using Core Image safely in this environment?
1
0
54
1d
Xcode 27 - Device Hub - backboardd crashes when displaying multiple apps under iPadOS 27
I'm getting persistent backboardd crashes in the iPadOS 27 simulator when my app and another app (Safari, Photos or Calendar, etc.) has windows visible on the screen at the same time, including slide over, etc. Steps to reproduce: Launch my app in an iPadOS 27 simulator. Open Safari or Photos in another window. Arrange both app windows so they're visible. Within a second backboardd crashes with EXC_CRASH (SIGABRT) in a com.apple.coreanimation.display.primary thread. The simulator log reports… -[MTLTextureDescriptorInternal validateWithDevice:]: error 'Texture Descriptor Validation MTLTextureDescriptor has invalid pixelFormat (0).' Xcode subsequently reports connection-interrupted messages and ends the app's debug session with: “Debug session ended with code 9: Terminated due to signal 9.” This works correctly in iPadOS 26.x simulators and on a physical device running iPadOS 27. I can reproduce this with both Xcode 27 and 27.1. Resetting the simulator and testing different simulated iPad models does not resolve it. Is anyone else seeing anything like this? It's presumably something I'm doing wrong, so I've double checked my UIScene handling and all seems well (it's been in there for a while) so I'm somewhat at a loss as to where to look next. This is on a Mac Mini M4 Pro running macOS 27.0.1 (26A434).
1
0
247
4d
Metal Compositor Service & Persona (VisionOS)
Hello, I'm currently trying to make a collaborative app. But it just works only on Reality View, when I tried to use Compositor Layer like below, the personas disappeared. ImmersiveSpace(id: "ImmersiveSpace-Metal") { CompositorLayer(configuration: MetalLayerConfiguration()) { layerRenderer in SpatialRenderer_InitAndRun(layerRenderer) } } Is there any potential solution too see Personas in Metal view? Thanks in advance!
3
0
2k
2w
Photogrammetry with Object masks hangs and terminates with masks of objects
[PhotogrammetrySample]) with objectMask set and traps on my ios26.5.2, see the attached screenshot on feedback FB24379913 , it gets to the function and hangs . Even the folder reconstruction with lazy sequence as recommended from your video sample also doesn;t complete as it can't find alignment and displays the CoreOC.PhotogrammetrySession.Error error 6 means alignment failed. What can be done or do you guys expose any functions that can be used to check or trace or handle these internally The ObjectMasks are actually segmentation masks from an segmentation algorithm I will appreciate a timely response and willing to provide more clarity and informations, thank you so much for your understanding
3
0
1.4k
2w
Clarifying Fence Behavior in Metal 4
I have some clarifying questions on how fences work in Metal 4. If two encoders A, B update the same fence and encoder C waits on that fence, is the work encoded by C guaranteed to execute after both A and B have completed, or after either A or B have completed? The following quotes in the waitForFence() documentation seem contradictory. "Encodes a command that instructs the GPU to pause before starting one or more stages of the pass until a pass updates a fence." "When encoding a pass that reuses a fence, wait for other passes to update the fence before repurposing that fence..." Are fences unsignaled when they are waited on? Specifically, can two (or more) encoders wait on a fence that is only updated in a single prior encoder? If an encoder updates a fence, no subsequent encoders in the command queue wait on the fence, and the command queue is committed, is that fence still signaled when used in a subsequent command buffer?
1
0
2.1k
3w
On-screen RealityView starves CADisplayLink to 30 Hz on ProMotion (Mac Catalyst)
FB24536235 On Mac Catalyst under macOS 27, a plain CADisplayLink asking for CAFrameRateRange(minimum: 60, maximum: 60, preferred: 60) gets serviced at 30 Hz for as long as a RealityView is on screen in the same window. The link does nothing per tick but count, so there's nothing of mine to blame it on. RealityKit's own statistics overlay reads 60.41 fps in the same frame. Click a segmented control that removes the RealityView and the same link goes straight back to 60. Nothing else changes. That's the whole reproducer, and I've attached it to the radar. It only happens while the display panel is in ProMotion mode. Set the built-in to a fixed 60 Hz and it's correct again. With an external 60 Hz display attached the roles swap: the built-in is fine and the external drops to somewhere between 18 and 30, and setting the built-in to 60 Hz fixes that one too without touching the external's own settings. A raw MTKView presenting continuously at 60, at 120, and on a 120 Hz link presenting every second callback are all fine, so it isn't continuous presentation and it isn't the requested rate. It's RealityKit specifically. Worth knowing if you're testing: RealityView on Catalyst is an ARView underneath, so both paths give you the same answer. This is VERY rough for anything that puts RealityKit next to a UI. In an editor that's the sidebar, the inspector, gizmos, drag handles, every display-link-driven or UIKit animation in the window running at half rate around a viewport that stays smooth. Likely Related to FB24091347, which is the same defect seen as SwiftUI scroll judder. If you can reproduce either, please file a duplicate. Attached two screenshots; first with promotion enabled, second with promotion off. PLEASE fix this, it drives me crazy and there seems to be no workaround. On release day of macOS 27 our app will likely be blamed for it by users and my hands are tied. Thank you!
2
1
1.3k
3w
Contribution route for native Metal point-cloud operators used with PyTorch MPS
I maintain mps-pointops, an open-source library implementing farthest-point sampling (FPS), k-nearest-neighbor search, and radius / Ball Query operations with custom Metal kernels for PyTorch MPS tensors. The intended use is 3D point-cloud pipelines whose existing extensions depend on CUDA. I would like to prepare a contribution proposal at the appropriate layer. Apple’s PyTorch/MPS page links to the PyTorch MPS backend contribution guide and directs backend issues to PyTorch’s GitHub tracker with the module: mps label. The current implementation has numerical-contract tests for selection order, ties, radius boundaries, and padding, plus benchmark records from physical M1 and M5 Pro Macs. The repository contains the kernels, Python interfaces, tests, and measurement conditions: https://github.com/gamzerA/mps-pointops My questions are: For specialized operators such as FPS and radius search, is the recommended contribution structure to keep the operator/API in a domain library (for example, a point-cloud or graph library), while proposing only reusable backend primitives to PyTorch MPS? Is there a public Apple-maintained contribution or technical-review channel relevant to this work, beyond the PyTorch route linked from Apple’s page? For an external library that dispatches custom Metal work alongside PyTorch MPS operations, which documented extension/interoperability path should be the long-term target for command-stream ordering and buffer lifetime? I would like to minimize reliance on backend internals when preparing an upstream proposal. Pointers to the appropriate public interface, maintainers, or contribution requirements would help me scope a small, reviewable proposal. I understand that inclusion in an upstream project is subject to its maintainers’ review. Apple documentation referenced: https://developer.apple.com/metal/pytorch/
0
0
193
Oct ’26
Is there a way to directly go from VideoToolbox to Metal for 10-bit/BT.2020 YCbCr HEVC?
tl;dr how can I get raw YUV in a Metal fragment shader from a VideoToolbox 10-bit/BT.2020 HEVC stream without any extra/secret format conversions? With VideoToolbox and 10-bit HEVC, I've found that it defaults to CVPixelBuffers w/ formats kCVPixelFormatType_Lossless_420YpCbCr10PackedBiPlanarFullRange or kCVPixelFormatType_Lossy_420YpCbCr10PackedBiPlanarFullRange. To mitigate this, I have the following snippet of code to my application: // We need our pixels unpacked for 10-bit so that the Metal textures actually work var pixelFormat:OSType? = nil let bpc = getBpcForVideoFormat(videoFormat!) let isFullRange = getIsFullRangeForVideoFormat(videoFormat!) // TODO: figure out how to check for 422/444, CVImageBufferChromaLocationBottomField? if bpc == 10 { pixelFormat = isFullRange ? kCVPixelFormatType_420YpCbCr10BiPlanarFullRange : kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange } let videoDecoderSpecification:[NSString: AnyObject] = [kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder:kCFBooleanTrue] var destinationImageBufferAttributes:[NSString: AnyObject] = [kCVPixelBufferMetalCompatibilityKey: true as NSNumber, kCVPixelBufferPoolMinimumBufferCountKey: 3 as NSNumber] if pixelFormat != nil { destinationImageBufferAttributes[kCVPixelBufferPixelFormatTypeKey] = pixelFormat! as NSNumber } var decompressionSession:VTDecompressionSession? = nil err = VTDecompressionSessionCreate(allocator: nil, formatDescription: videoFormat!, decoderSpecification: videoDecoderSpecification as CFDictionary, imageBufferAttributes: destinationImageBufferAttributes as CFDictionary, outputCallback: nil, decompressionSessionOut: &decompressionSession) In short, I need kCVPixelFormatType_420YpCbCr10BiPlanar so that I have a straightforward MTLPixelFormat.r16Unorm/MTLPixelFormat.rg16Unorm texture binding for Y/CbCr. Metal, seemingly, has no direct pixel format for 420YpCbCr10PackedBiPlanar. I'd also rather not use any color conversion in VideoToolbox, in order to save on processing (and to ensure that the color transforms/transfer characteristics match between streamer/client, since I also have a custom transfer characteristic to mitigate blocking in dark scenes). However, I noticed that in visionOS 2, the CVPixelBuffer I receive is no longer a compressed render target (likely a bug), which caused GPU texture read bandwidth to skyrocket from 2GiB/s to 30GiB/s. More importantly, this implies that VideoToolbox may in fact be doing an extra color conversion step, wasting memory bandwidth. Does Metal actually have no way to handle 420YpCbCr10PackedBiPlanar? Are there any examples for reading 10-bit HDR HEVC buffers directly with Metal?
3
0
2.1k
Sep ’26
macOS 27 beta: ProMotion refresh cadence is unstable, causing constant scroll judder
FB24091347 On macOS 27.0 beta (26A5388g), MacBook Pro M4 Pro, the built-in ProMotion display never settles on a stable refresh cadence. Scrolling in SwiftUI judders constantly. The same app binary was smooth on macOS 26, and is smooth on a 120 Hz ProMotion iPad. I captured two 60-second Instruments traces — same app, same scene, same scrolling, no external display — changing only the display's refresh-rate setting. On ProMotion the vsync interval standard deviation is 4.093 ms across six different cadences, mostly flip-flopping between 120 Hz and 60 Hz. Forced to a fixed 60 Hz it drops to 0.391 ms with a single cadence. The app presented an identical 59 fps median in both runs — frame production is perfectly steady, the display just holds each frame for an unpredictable length of time. That's what makes this nasty: it's invisible to every frame-rate metric, so it looks like the app got slow when nothing about the app changed. I spent most of a day profiling my own code before realising the app was never the problem. Workaround: force the built-in display to 60 Hz. Worth noting, because it complicates the picture: attaching a 60 Hz Studio Display makes the built-in smooth, but the Studio itself then judders — despite its own vsync cadence measuring perfectly stable. So refresh rate alone isn't the whole story, and there may be a second mechanism. The clean, reproducible, single-variable result is the ProMotion vs forced-60 Hz comparison on the built-in panel. If you can reproduce this on an M-series MacBook Pro on 27 beta, please file a duplicate referencing FB24091347.
6
2
2.7k
Sep ’26
Metal FP32 arithmetic rounding-mode and denormal controls for deterministic shaders
Metal already provides a strong precise floating-point contract. With fast math disabled (mathMode = .safe and mathFloatingPointFunctions = .precise, or -fno-fast-math), the Metal Shading Language specification requires correctly rounded FP32 add, subtract, multiply, reciprocal, divide, sqrt, rsqrt, and fma. I am looking for clarification and, if necessary, API support for the two remaining pieces needed for portable bit-exact numerical shaders: Arithmetic rounding mode MSL §8.2 says either round-to-nearest-ties-to-even or round-toward-zero may be supported for floating-point operations. I cannot find a way to select or query the arithmetic rounding mode. The newer MTLCompileOptions.floatingPointConversionRoundingMode appears to apply only to narrowing float-to-float conversions, not arithmetic operations. Do all currently supported Apple GPU families use round-to-nearest-ties-to-even for precise FP32 add/subtract/multiply/divide/sqrt? If so, could that be made a documented guarantee? Otherwise, could Metal expose an arithmetic rounding-mode compile option and a corresponding MTLDevice capability query? Denormal behavior MSL §8.1 and §8.5 permit denormalized FP32 operands and results to be flushed to zero, including with fast math disabled. I cannot find a control or capability query for preserving denormal inputs and results. Do current Apple GPU families support denormal-preserving FP32 arithmetic? Could Metal expose a preserve/flush mode and a MTLDevice query? A convenient end state would be a queryable strict FP32 configuration combining: safe math; precise FP32 functions; contraction disabled when separate rounding points are required; round-to-nearest-ties-to-even arithmetic; preserved FP32 denormal inputs and results; defined signed-zero, infinity, and NaN behavior. My use case is deterministic GPU numerical simulation. A small compute-shader probe can identify effective rounding and denormal behavior on one GPU/OS/compiler combination, but it cannot provide the portable or future-proof contract needed by applications and higher-level APIs such as WebGPU. Related cross-API work: SPIR-V/Vulkan: https://github.com/KhronosGroup/SPIRV-Registry/issues/448 HLSL/DXIL/D3D12: https://github.com/microsoft/hlsl-specs/issues/926 WebGPU/WGSL umbrella issue: https://github.com/gpuweb/gpuweb/issues/2259 Relevant Metal documentation: Metal Shading Language Specification, §§1.6.3 and 8.1–8.5: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf MTLCompileOptions.mathMode: https://developer.apple.com/documentation/metal/mtlcompileoptions/mathmode MTLCompileOptions.floatingPointConversionRoundingMode: https://developer.apple.com/documentation/metal/mtlcompileoptions/floatingpointconversionroundingmode
2
0
3.2k
Sep ’26
Data corruption when using MTLBlitCommandEncoder.copy from buffer to texture
When we use MTLBlitCommandEncoder.copy to copy from buffer to textures with specific size, we find that the texture content is corruppt. The specific rules we found are: On Apple GPUs (reproduced on Apple M5, macOS 26.3 and iPhone 13 / A15), for ASTC textures uploaded to private storage via the blit encoder, the sampler / texel-fetch mis-addresses the tail of a mip level when ALL of the following hold: that level's texel width is an exact multiple of the 16 KB page width (32 blocks) — 128 texels for ASTC 4x4, 192 for 6x6, 256 for 8x8; the texture width is not divisible by 2^level (a partial block column exists in the chain); that level is taller than one page (>32 block rows). The level's first 128 texel rows (first page row, 4x4) are always read correctly; everything beyond is mis-addressed. Reads landing on unmapped/invalid memory decode as opaque magenta (1,0,1); reads aliasing valid memory show wrong image content. This produced visible purple artifacts in a shipping game (impostor tree atlas, 514x1024 ASTC 4x4, mip2 bottom half). The minimum reproduce code is: ASTCMipTailBugRepro.swift The output is: 514x1024 blit(private) mip2: CORRUPTED (bottom of mip2 mis-addressed) 512x1024 blit(private) mip2: INTACT 514x1024 replaceRegion mip2: INTACT
1
0
1.6k
Sep ’26
Metal 4 and object lifetime
I have a metal kit view and drain the draw method of its delegate like shown below. Let's say I have one or more MTLBuffers with vertex resources bound via the argument table. When is it ok to drop these buffers? As far as I know one cannot schedule a completion handler In Metal 4 and I haven't been able to find any documentation about the lifetime requirements here. Any pointers/ideas appreciated. class RenderCoordinator: NSObject, MTKViewDelegate { public func draw(in view: MTKView) { let commandAllocator: any MTL4CommandAllocator = ... let commandBuffer: any MTL4CommandBuffer = ... let commandQueue: any MTL4CommandQueue = ... guard let drawable = view.currentDrawable else { return } commandBuffer.beginCommandBuffer(allocator: commandAllocator) let state: any MTLRenderPipelineState = ... let encoder: any MTL4RenderCommandEncoder = ... let argTable: any MTL4ArgumentTable = ... encoder.setRenderPipelineState(state) encoder.setArgumentTable(argTable, stages: .vertex) commandBuffer.endCommandBuffer() commandQueue.waitForDrawable(drawable) commandQueue.commit([commandBuffer]) commandQueue.signalDrawable(drawable) drawable.present() } }
2
0
1.6k
Sep ’26
Stress-testing Metal compute pipelines using Autolykos workload characteristics
I have been using a small macOS research project to exercise Metal with a workload that differs from rendering and dense machine-learning kernels. Autolykos v2 is useful for this because it combines a large, height-dependent working set with pseudo-random reads, integer-heavy hashing, sustained execution, and periodic replacement of the dataset. The project happens to be a miner, but my question here is strictly about Metal compute behaviour. On the Apple M4 system used for these measurements, the full dataset contained 216,430,305 elements of 32 bytes each: 6.93 GB, or about 6.45 GiB, held in a .storageModePrivate buffer. For every nonce, the search kernel: computes an index seed, performs 32 pseudo-random 32-byte dataset reads, accumulates the eight 32-bit limbs into a 256-bit sum, and applies a final BLAKE2b compression and target comparison. The normal dispatch uses 128 threads per threadgroup. The wider pipeline also builds the next height's dataset in chunks on a separate command queue while search continues, and keeps two search command buffers in flight. I record command-buffer wall time, gpuStartTime/gpuEndTime, unions of overlapping intervals, and thermal state. To estimate the ceiling imposed by the random gathers, I added a non-consensus microbenchmark. It retains the normal seed calculation, index distribution, all 32 dataset reads, and the complete accumulation, but omits the final BLAKE2b compression. The accumulated result remains observable through a comparison, so the gather loop cannot simply disappear. I expected this stripped kernel to be at least slightly faster. Instead, an order-balanced campaign on an M4 produced: complete search kernel: 3.108 million nonces/s median active throughput gather-only kernel: 2.952 million nonces/s ratio: 105.3% All four same-round ratios were between 103.18% and 105.74%. Each measured run used the full dataset, a 30-second search interval, an excluded warm-up, and a start-temperature gate below 50 °C. Both compute pipeline states reported maxTotalThreadsPerThreadgroup == 1024. My conservative conclusion was not to pursue speculative register-pressure or manual memory-level-parallelism rewrites. The access pattern appears sufficiently dominant, while the supposedly simpler microbenchmark may have changed the compiled pipeline in a way that makes it a poor upper-bound model. My questions are: Can removing the trailing arithmetic legitimately make a memory-latency-heavy Metal kernel slower by changing register allocation, instruction scheduling, or the amount of useful latency hiding? Or would you first suspect a flaw in this kind of gather-only benchmark construction? Also, which Metal GPU counters are the most reliable way to distinguish memory-latency saturation from register-limited occupancy in a long-running compute kernel? I am looking at compute occupancy, buffer and ALU limiters, bandwidth, and cache behaviour, but maxTotalThreadsPerThreadgroup alone is clearly too coarse to explain the result. This is one hardware-specific observation rather than a general claim about Apple GPUs. If useful, I can reduce the workload to a smaller standalone reproducer. The source code, benchmark driver, and complete campaign report are available here: https://github.com/giffeler/ergometal The detailed measurements and validation procedure for this comparison are documented here: https://github.com/giffeler/ergometal/blob/main/Benchmarks/2026-08-15-search-gather-ceiling-ab.md
0
0
789
Aug ’26
Xcode 27 Beta 5 unable to link Core Image kernels unless MACOSX_DEPLOYMENT_TARGET = macOS 27
The Metal linker in the latest Xcode 27 Beta 5 is failing to link against the Core Image framework unless the current MACOSX_DEPLOYMENT_TARGET is set to macOS 27 Golden Gate Beta. MTLLINKER_FLAGS = -framework CoreImage It looks like the CoreImage framework that shipped in the Beta 5 SDK fails to include versions of CoreImage.metallib to support prior versions of macOS. If your current deployment target is, for example, macOS 13.5, the build log will show a warning: air-lld: warning: ignoring file '/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage.metallib', file AIR version (2.9) is bigger than the one of the target being linked (2.5) ...and produce this error: air-lld: error: symbol(s) not found for target 'air64_v25-apple-macosx13.5.0' metal: error: air-lld command failed with exit code 1 (use -v to see invocation) The above warning + error happen for any MACOSX_DEPLOYMENT_TARGET up to and including macOS 26. Only when setting it to macOS 27 does the linker succeed. Linking against the Core Image framework is required to package your own CIKernels that use Metal’s [[stitchable]] attribute, in lieu of the previous method based on: MTL_COMPILER_FLAGS = -fcikernel and MTLLINKER_FLAGS = -fcikernel. Has anyone else run into this very same issue? (Filed as FB24345950) Any workarounds you’d be willing to share? Would pulling an older version of the CoreImage framework from a previous SDK, and linking explicitly against it work too? Thanks! Gabe
1
1
190
Aug ’26
Xcode 27.0 b5, macOS 26.6.1, Metal build fails: symbols not found for air64_v28
I've just downloaded the Xcode 27.0 beta 5 on a macOS 26.6.1 machine and tried to build my app (which includes Metal CoreImage kernels). I'm met with a new (to me) error; /Users/…/Developer/…/air-lld:1:1 symbol(s) not found for target 'air64_v28-apple-macosx26.0.0' and from the build log; air-lld: warning: ignoring file '/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage.metallib', file AIR version (2.9) is bigger than the one of the target being linked (2.8) air-lld: error: symbol(s) not found for target 'air64_v28-apple-macosx26.0.0' metal: error: air-lld command failed with exit code 1 (use -v to see invocation) I have no MTL_LANGUAGE_REVISION in my build settings. If I add one, with value Metal41 the app builds fine, but crashes at runtime as Metal 4.1 isn't supported on macOS 26. I imagine this is a beta Xcode and or macOS SDK bug, is there a workaround?
1
1
1.4k
Aug ’26
Xcode 27.0 Metal Toolchain download stuck at "Beginning asset download..."
Hi everyone, I downloaded Xcode 27.0 today because I need the Metal Toolchain for Unreal Engine 5.6 on my Mac. Xcode itself is installed and working, but Unreal is having issues because the Metal Toolchain doesn't seem to be installed. When I run: xcrun metal --version I get: error: error: cannot execute tool 'metal' due to missing Metal Toolchain; use: xcodebuild -downloadComponent MetalToolchain I tried: sudo xcodebuild -downloadComponent MetalToolchain but it just stays on: Beginning asset download... If I cancel it, I get: xcodebuild: error: Download was cancelled. (Asset download for com.apple.MobileAsset.MetalToolchain ...) I've also run: xcodebuild -runFirstLaunch and installed the latest Command Line Tools for Xcode 27.0 through Software Update. xcrun --find metal does find the executable, but the actual Metal Toolchain appears to be missing. I'm mainly trying to get this working so I can use Unreal Engine 5.6. Has anyone had this issue with Xcode 27, or know the correct way to install the Metal Toolchain when xcodebuild -downloadComponent gets stuck at "Beginning asset download"? Thanks!
Replies
1
Boosts
1
Views
444
Activity
4h
D3DMetal: present hangs permanently when the game window becomes occluded
Environment macOS 27.0.1 (26A434), Apple M4 Pro Apple Game Porting Toolkit 4.0b2 (D3DMetal.framework) via CrossOver 27 D3D12 game, borderless fullscreen window (2540x1650) Symptom When the game window becomes occluded — Mission Control, a system OSD (volume/brightness), or another window being brought to the front — the game never renders another frame. It does not crash: GPU utilization drops to 0%, the process stays alive with near-zero CPU, and it never recovers. Killing and restarting the game is the only way out. D3DMetal log at the moment it happens: [D3DMetal:FATAL:%llX][%s:%d] Failed to get drawable for HWND. Run with D3DM_NO_WINDOW=1 env. Question When CAMetalLayer/nextDrawable has no drawable (window not visible), is there a supported way for D3DMetal to skip frames instead of blocking forever? Is there an environment variable or configuration that makes D3DMetal treat "no drawable" as a recoverable condition? Does D3DM_NO_WINDOW=1 apply here, or is it only for headless/offscreen use? I understand apps should handle a nil drawable and continue, but this path is inside D3DMetal. Any guidance would help.
Replies
3
Boosts
0
Views
1.2k
Activity
16h
iOS app running on macOS 27.0.1 terminated on suspension due to a Metal archiveUsage.db file lock (0xDEAD10CC)
Hello, We are investigating an issue where our iOS app, running as a “Designed for iPad” app on an Apple Silicon Mac, is terminated when it is suspended in the background. Environment OS: macOS 27.0.1 Hardware: Apple Silicon Mac App type: An iOS/iPadOS app running on Mac, rather than a separately developed macOS app The app uses Core Image’s CIContext to generate some image effects Steps to reproduce Launch the app on Mac and start playing a podcast. Move the app to the background. Start playback on another device. Our app’s cross-device playback coordination pauses playback on the Mac. After a short period, the Mac app is terminated. We have also observed similar termination after visiting a screen that uses Core Image image effects. Actual result The debugger reports: Terminated due to signal 9 RunningBoard logs indicate that the app was terminated with code 0xDEAD10CC because it was suspended while holding a disallowed shared file lock. The file identified in the log is: /var/folders/.../C/app.podcast.cosmos/app.podcast.cosmos/com.apple.metal/archiveUsage.db/lock.mdb The relevant log message includes: suspended while holding a shared file lock Investigation so far Using breakpoints on open and openat, we captured a call stack corresponding to: App creates a CIContext → Core Image CI::MetalContext → Metal recordBinaryArchiveUsage → archiveUsage.db/lock.mdb is opened We also tried: CIContext(options: [.useSoftwareRenderer: true]) However, in our test environment, we still observed Metal initialization and access to the relevant cache files. This option did not avoid the issue. For the gradient-mask generation code we had identified, we replaced the Core Image implementation with a CPU implementation using CGContext and CGGradient, avoiding CIContext creation on that path. After repeatedly testing the same reproduction steps, we could no longer reproduce the termination in that scenario. This suggests a connection to the Metal cache file lock accessed during Core Image initialization. However, we have not established the exact lifetime or internal owner of the lock, and we have not confirmed a thread deadlock. Questions Is this a known issue involving Core Image/Metal and suspension of iOS apps running on macOS 27.0.1? Why would a system-managed Metal cache file lock cause the app to be terminated with 0xDEAD10CC when suspended? Is there a recommended context configuration, resource cleanup procedure, or lifecycle handling approach that allows us to continue using Core Image safely in this environment?
Replies
1
Boosts
0
Views
54
Activity
1d
Xcode 27 - Device Hub - backboardd crashes when displaying multiple apps under iPadOS 27
I'm getting persistent backboardd crashes in the iPadOS 27 simulator when my app and another app (Safari, Photos or Calendar, etc.) has windows visible on the screen at the same time, including slide over, etc. Steps to reproduce: Launch my app in an iPadOS 27 simulator. Open Safari or Photos in another window. Arrange both app windows so they're visible. Within a second backboardd crashes with EXC_CRASH (SIGABRT) in a com.apple.coreanimation.display.primary thread. The simulator log reports… -[MTLTextureDescriptorInternal validateWithDevice:]: error 'Texture Descriptor Validation MTLTextureDescriptor has invalid pixelFormat (0).' Xcode subsequently reports connection-interrupted messages and ends the app's debug session with: “Debug session ended with code 9: Terminated due to signal 9.” This works correctly in iPadOS 26.x simulators and on a physical device running iPadOS 27. I can reproduce this with both Xcode 27 and 27.1. Resetting the simulator and testing different simulated iPad models does not resolve it. Is anyone else seeing anything like this? It's presumably something I'm doing wrong, so I've double checked my UIScene handling and all seems well (it's been in there for a while) so I'm somewhat at a loss as to where to look next. This is on a Mac Mini M4 Pro running macOS 27.0.1 (26A434).
Replies
1
Boosts
0
Views
247
Activity
4d
Metal Compositor Service & Persona (VisionOS)
Hello, I'm currently trying to make a collaborative app. But it just works only on Reality View, when I tried to use Compositor Layer like below, the personas disappeared. ImmersiveSpace(id: "ImmersiveSpace-Metal") { CompositorLayer(configuration: MetalLayerConfiguration()) { layerRenderer in SpatialRenderer_InitAndRun(layerRenderer) } } Is there any potential solution too see Personas in Metal view? Thanks in advance!
Replies
3
Boosts
0
Views
2k
Activity
2w
Photogrammetry with Object masks hangs and terminates with masks of objects
[PhotogrammetrySample]) with objectMask set and traps on my ios26.5.2, see the attached screenshot on feedback FB24379913 , it gets to the function and hangs . Even the folder reconstruction with lazy sequence as recommended from your video sample also doesn;t complete as it can't find alignment and displays the CoreOC.PhotogrammetrySession.Error error 6 means alignment failed. What can be done or do you guys expose any functions that can be used to check or trace or handle these internally The ObjectMasks are actually segmentation masks from an segmentation algorithm I will appreciate a timely response and willing to provide more clarity and informations, thank you so much for your understanding
Replies
3
Boosts
0
Views
1.4k
Activity
2w
Clarifying Fence Behavior in Metal 4
I have some clarifying questions on how fences work in Metal 4. If two encoders A, B update the same fence and encoder C waits on that fence, is the work encoded by C guaranteed to execute after both A and B have completed, or after either A or B have completed? The following quotes in the waitForFence() documentation seem contradictory. "Encodes a command that instructs the GPU to pause before starting one or more stages of the pass until a pass updates a fence." "When encoding a pass that reuses a fence, wait for other passes to update the fence before repurposing that fence..." Are fences unsignaled when they are waited on? Specifically, can two (or more) encoders wait on a fence that is only updated in a single prior encoder? If an encoder updates a fence, no subsequent encoders in the command queue wait on the fence, and the command queue is committed, is that fence still signaled when used in a subsequent command buffer?
Replies
1
Boosts
0
Views
2.1k
Activity
3w
On-screen RealityView starves CADisplayLink to 30 Hz on ProMotion (Mac Catalyst)
FB24536235 On Mac Catalyst under macOS 27, a plain CADisplayLink asking for CAFrameRateRange(minimum: 60, maximum: 60, preferred: 60) gets serviced at 30 Hz for as long as a RealityView is on screen in the same window. The link does nothing per tick but count, so there's nothing of mine to blame it on. RealityKit's own statistics overlay reads 60.41 fps in the same frame. Click a segmented control that removes the RealityView and the same link goes straight back to 60. Nothing else changes. That's the whole reproducer, and I've attached it to the radar. It only happens while the display panel is in ProMotion mode. Set the built-in to a fixed 60 Hz and it's correct again. With an external 60 Hz display attached the roles swap: the built-in is fine and the external drops to somewhere between 18 and 30, and setting the built-in to 60 Hz fixes that one too without touching the external's own settings. A raw MTKView presenting continuously at 60, at 120, and on a 120 Hz link presenting every second callback are all fine, so it isn't continuous presentation and it isn't the requested rate. It's RealityKit specifically. Worth knowing if you're testing: RealityView on Catalyst is an ARView underneath, so both paths give you the same answer. This is VERY rough for anything that puts RealityKit next to a UI. In an editor that's the sidebar, the inspector, gizmos, drag handles, every display-link-driven or UIKit animation in the window running at half rate around a viewport that stays smooth. Likely Related to FB24091347, which is the same defect seen as SwiftUI scroll judder. If you can reproduce either, please file a duplicate. Attached two screenshots; first with promotion enabled, second with promotion off. PLEASE fix this, it drives me crazy and there seems to be no workaround. On release day of macOS 27 our app will likely be blamed for it by users and my hands are tied. Thank you!
Replies
2
Boosts
1
Views
1.3k
Activity
3w
Contribution route for native Metal point-cloud operators used with PyTorch MPS
I maintain mps-pointops, an open-source library implementing farthest-point sampling (FPS), k-nearest-neighbor search, and radius / Ball Query operations with custom Metal kernels for PyTorch MPS tensors. The intended use is 3D point-cloud pipelines whose existing extensions depend on CUDA. I would like to prepare a contribution proposal at the appropriate layer. Apple’s PyTorch/MPS page links to the PyTorch MPS backend contribution guide and directs backend issues to PyTorch’s GitHub tracker with the module: mps label. The current implementation has numerical-contract tests for selection order, ties, radius boundaries, and padding, plus benchmark records from physical M1 and M5 Pro Macs. The repository contains the kernels, Python interfaces, tests, and measurement conditions: https://github.com/gamzerA/mps-pointops My questions are: For specialized operators such as FPS and radius search, is the recommended contribution structure to keep the operator/API in a domain library (for example, a point-cloud or graph library), while proposing only reusable backend primitives to PyTorch MPS? Is there a public Apple-maintained contribution or technical-review channel relevant to this work, beyond the PyTorch route linked from Apple’s page? For an external library that dispatches custom Metal work alongside PyTorch MPS operations, which documented extension/interoperability path should be the long-term target for command-stream ordering and buffer lifetime? I would like to minimize reliance on backend internals when preparing an upstream proposal. Pointers to the appropriate public interface, maintainers, or contribution requirements would help me scope a small, reviewable proposal. I understand that inclusion in an upstream project is subject to its maintainers’ review. Apple documentation referenced: https://developer.apple.com/metal/pytorch/
Replies
0
Boosts
0
Views
193
Activity
Oct ’26
How to restrict an App Store distribution exclusively to Metal 4 devices?
I am developing an application exclusively for devices that support Metal 4. Is it possible to publish this app on the App Store and restrict its availability solely to compatible hardware? The iphone-performance-gaming-tier key is not an option, as we need to maintain support for older devices.
Replies
0
Boosts
0
Views
263
Activity
Sep ’26
Is there a way to directly go from VideoToolbox to Metal for 10-bit/BT.2020 YCbCr HEVC?
tl;dr how can I get raw YUV in a Metal fragment shader from a VideoToolbox 10-bit/BT.2020 HEVC stream without any extra/secret format conversions? With VideoToolbox and 10-bit HEVC, I've found that it defaults to CVPixelBuffers w/ formats kCVPixelFormatType_Lossless_420YpCbCr10PackedBiPlanarFullRange or kCVPixelFormatType_Lossy_420YpCbCr10PackedBiPlanarFullRange. To mitigate this, I have the following snippet of code to my application: // We need our pixels unpacked for 10-bit so that the Metal textures actually work var pixelFormat:OSType? = nil let bpc = getBpcForVideoFormat(videoFormat!) let isFullRange = getIsFullRangeForVideoFormat(videoFormat!) // TODO: figure out how to check for 422/444, CVImageBufferChromaLocationBottomField? if bpc == 10 { pixelFormat = isFullRange ? kCVPixelFormatType_420YpCbCr10BiPlanarFullRange : kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange } let videoDecoderSpecification:[NSString: AnyObject] = [kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder:kCFBooleanTrue] var destinationImageBufferAttributes:[NSString: AnyObject] = [kCVPixelBufferMetalCompatibilityKey: true as NSNumber, kCVPixelBufferPoolMinimumBufferCountKey: 3 as NSNumber] if pixelFormat != nil { destinationImageBufferAttributes[kCVPixelBufferPixelFormatTypeKey] = pixelFormat! as NSNumber } var decompressionSession:VTDecompressionSession? = nil err = VTDecompressionSessionCreate(allocator: nil, formatDescription: videoFormat!, decoderSpecification: videoDecoderSpecification as CFDictionary, imageBufferAttributes: destinationImageBufferAttributes as CFDictionary, outputCallback: nil, decompressionSessionOut: &decompressionSession) In short, I need kCVPixelFormatType_420YpCbCr10BiPlanar so that I have a straightforward MTLPixelFormat.r16Unorm/MTLPixelFormat.rg16Unorm texture binding for Y/CbCr. Metal, seemingly, has no direct pixel format for 420YpCbCr10PackedBiPlanar. I'd also rather not use any color conversion in VideoToolbox, in order to save on processing (and to ensure that the color transforms/transfer characteristics match between streamer/client, since I also have a custom transfer characteristic to mitigate blocking in dark scenes). However, I noticed that in visionOS 2, the CVPixelBuffer I receive is no longer a compressed render target (likely a bug), which caused GPU texture read bandwidth to skyrocket from 2GiB/s to 30GiB/s. More importantly, this implies that VideoToolbox may in fact be doing an extra color conversion step, wasting memory bandwidth. Does Metal actually have no way to handle 420YpCbCr10PackedBiPlanar? Are there any examples for reading 10-bit HDR HEVC buffers directly with Metal?
Replies
3
Boosts
0
Views
2.1k
Activity
Sep ’26
macOS 27 beta: ProMotion refresh cadence is unstable, causing constant scroll judder
FB24091347 On macOS 27.0 beta (26A5388g), MacBook Pro M4 Pro, the built-in ProMotion display never settles on a stable refresh cadence. Scrolling in SwiftUI judders constantly. The same app binary was smooth on macOS 26, and is smooth on a 120 Hz ProMotion iPad. I captured two 60-second Instruments traces — same app, same scene, same scrolling, no external display — changing only the display's refresh-rate setting. On ProMotion the vsync interval standard deviation is 4.093 ms across six different cadences, mostly flip-flopping between 120 Hz and 60 Hz. Forced to a fixed 60 Hz it drops to 0.391 ms with a single cadence. The app presented an identical 59 fps median in both runs — frame production is perfectly steady, the display just holds each frame for an unpredictable length of time. That's what makes this nasty: it's invisible to every frame-rate metric, so it looks like the app got slow when nothing about the app changed. I spent most of a day profiling my own code before realising the app was never the problem. Workaround: force the built-in display to 60 Hz. Worth noting, because it complicates the picture: attaching a 60 Hz Studio Display makes the built-in smooth, but the Studio itself then judders — despite its own vsync cadence measuring perfectly stable. So refresh rate alone isn't the whole story, and there may be a second mechanism. The clean, reproducible, single-variable result is the ProMotion vs forced-60 Hz comparison on the built-in panel. If you can reproduce this on an M-series MacBook Pro on 27 beta, please file a duplicate referencing FB24091347.
Replies
6
Boosts
2
Views
2.7k
Activity
Sep ’26
Metal FP32 arithmetic rounding-mode and denormal controls for deterministic shaders
Metal already provides a strong precise floating-point contract. With fast math disabled (mathMode = .safe and mathFloatingPointFunctions = .precise, or -fno-fast-math), the Metal Shading Language specification requires correctly rounded FP32 add, subtract, multiply, reciprocal, divide, sqrt, rsqrt, and fma. I am looking for clarification and, if necessary, API support for the two remaining pieces needed for portable bit-exact numerical shaders: Arithmetic rounding mode MSL §8.2 says either round-to-nearest-ties-to-even or round-toward-zero may be supported for floating-point operations. I cannot find a way to select or query the arithmetic rounding mode. The newer MTLCompileOptions.floatingPointConversionRoundingMode appears to apply only to narrowing float-to-float conversions, not arithmetic operations. Do all currently supported Apple GPU families use round-to-nearest-ties-to-even for precise FP32 add/subtract/multiply/divide/sqrt? If so, could that be made a documented guarantee? Otherwise, could Metal expose an arithmetic rounding-mode compile option and a corresponding MTLDevice capability query? Denormal behavior MSL §8.1 and §8.5 permit denormalized FP32 operands and results to be flushed to zero, including with fast math disabled. I cannot find a control or capability query for preserving denormal inputs and results. Do current Apple GPU families support denormal-preserving FP32 arithmetic? Could Metal expose a preserve/flush mode and a MTLDevice query? A convenient end state would be a queryable strict FP32 configuration combining: safe math; precise FP32 functions; contraction disabled when separate rounding points are required; round-to-nearest-ties-to-even arithmetic; preserved FP32 denormal inputs and results; defined signed-zero, infinity, and NaN behavior. My use case is deterministic GPU numerical simulation. A small compute-shader probe can identify effective rounding and denormal behavior on one GPU/OS/compiler combination, but it cannot provide the portable or future-proof contract needed by applications and higher-level APIs such as WebGPU. Related cross-API work: SPIR-V/Vulkan: https://github.com/KhronosGroup/SPIRV-Registry/issues/448 HLSL/DXIL/D3D12: https://github.com/microsoft/hlsl-specs/issues/926 WebGPU/WGSL umbrella issue: https://github.com/gpuweb/gpuweb/issues/2259 Relevant Metal documentation: Metal Shading Language Specification, §§1.6.3 and 8.1–8.5: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf MTLCompileOptions.mathMode: https://developer.apple.com/documentation/metal/mtlcompileoptions/mathmode MTLCompileOptions.floatingPointConversionRoundingMode: https://developer.apple.com/documentation/metal/mtlcompileoptions/floatingpointconversionroundingmode
Replies
2
Boosts
0
Views
3.2k
Activity
Sep ’26
Data corruption when using MTLBlitCommandEncoder.copy from buffer to texture
When we use MTLBlitCommandEncoder.copy to copy from buffer to textures with specific size, we find that the texture content is corruppt. The specific rules we found are: On Apple GPUs (reproduced on Apple M5, macOS 26.3 and iPhone 13 / A15), for ASTC textures uploaded to private storage via the blit encoder, the sampler / texel-fetch mis-addresses the tail of a mip level when ALL of the following hold: that level's texel width is an exact multiple of the 16 KB page width (32 blocks) — 128 texels for ASTC 4x4, 192 for 6x6, 256 for 8x8; the texture width is not divisible by 2^level (a partial block column exists in the chain); that level is taller than one page (>32 block rows). The level's first 128 texel rows (first page row, 4x4) are always read correctly; everything beyond is mis-addressed. Reads landing on unmapped/invalid memory decode as opaque magenta (1,0,1); reads aliasing valid memory show wrong image content. This produced visible purple artifacts in a shipping game (impostor tree atlas, 514x1024 ASTC 4x4, mip2 bottom half). The minimum reproduce code is: ASTCMipTailBugRepro.swift The output is: 514x1024 blit(private) mip2: CORRUPTED (bottom of mip2 mis-addressed) 512x1024 blit(private) mip2: INTACT 514x1024 replaceRegion mip2: INTACT
Replies
1
Boosts
0
Views
1.6k
Activity
Sep ’26
Metal 4 and object lifetime
I have a metal kit view and drain the draw method of its delegate like shown below. Let's say I have one or more MTLBuffers with vertex resources bound via the argument table. When is it ok to drop these buffers? As far as I know one cannot schedule a completion handler In Metal 4 and I haven't been able to find any documentation about the lifetime requirements here. Any pointers/ideas appreciated. class RenderCoordinator: NSObject, MTKViewDelegate { public func draw(in view: MTKView) { let commandAllocator: any MTL4CommandAllocator = ... let commandBuffer: any MTL4CommandBuffer = ... let commandQueue: any MTL4CommandQueue = ... guard let drawable = view.currentDrawable else { return } commandBuffer.beginCommandBuffer(allocator: commandAllocator) let state: any MTLRenderPipelineState = ... let encoder: any MTL4RenderCommandEncoder = ... let argTable: any MTL4ArgumentTable = ... encoder.setRenderPipelineState(state) encoder.setArgumentTable(argTable, stages: .vertex) commandBuffer.endCommandBuffer() commandQueue.waitForDrawable(drawable) commandQueue.commit([commandBuffer]) commandQueue.signalDrawable(drawable) drawable.present() } }
Replies
2
Boosts
0
Views
1.6k
Activity
Sep ’26
Stress-testing Metal compute pipelines using Autolykos workload characteristics
I have been using a small macOS research project to exercise Metal with a workload that differs from rendering and dense machine-learning kernels. Autolykos v2 is useful for this because it combines a large, height-dependent working set with pseudo-random reads, integer-heavy hashing, sustained execution, and periodic replacement of the dataset. The project happens to be a miner, but my question here is strictly about Metal compute behaviour. On the Apple M4 system used for these measurements, the full dataset contained 216,430,305 elements of 32 bytes each: 6.93 GB, or about 6.45 GiB, held in a .storageModePrivate buffer. For every nonce, the search kernel: computes an index seed, performs 32 pseudo-random 32-byte dataset reads, accumulates the eight 32-bit limbs into a 256-bit sum, and applies a final BLAKE2b compression and target comparison. The normal dispatch uses 128 threads per threadgroup. The wider pipeline also builds the next height's dataset in chunks on a separate command queue while search continues, and keeps two search command buffers in flight. I record command-buffer wall time, gpuStartTime/gpuEndTime, unions of overlapping intervals, and thermal state. To estimate the ceiling imposed by the random gathers, I added a non-consensus microbenchmark. It retains the normal seed calculation, index distribution, all 32 dataset reads, and the complete accumulation, but omits the final BLAKE2b compression. The accumulated result remains observable through a comparison, so the gather loop cannot simply disappear. I expected this stripped kernel to be at least slightly faster. Instead, an order-balanced campaign on an M4 produced: complete search kernel: 3.108 million nonces/s median active throughput gather-only kernel: 2.952 million nonces/s ratio: 105.3% All four same-round ratios were between 103.18% and 105.74%. Each measured run used the full dataset, a 30-second search interval, an excluded warm-up, and a start-temperature gate below 50 °C. Both compute pipeline states reported maxTotalThreadsPerThreadgroup == 1024. My conservative conclusion was not to pursue speculative register-pressure or manual memory-level-parallelism rewrites. The access pattern appears sufficiently dominant, while the supposedly simpler microbenchmark may have changed the compiled pipeline in a way that makes it a poor upper-bound model. My questions are: Can removing the trailing arithmetic legitimately make a memory-latency-heavy Metal kernel slower by changing register allocation, instruction scheduling, or the amount of useful latency hiding? Or would you first suspect a flaw in this kind of gather-only benchmark construction? Also, which Metal GPU counters are the most reliable way to distinguish memory-latency saturation from register-limited occupancy in a long-running compute kernel? I am looking at compute occupancy, buffer and ALU limiters, bandwidth, and cache behaviour, but maxTotalThreadsPerThreadgroup alone is clearly too coarse to explain the result. This is one hardware-specific observation rather than a general claim about Apple GPUs. If useful, I can reduce the workload to a smaller standalone reproducer. The source code, benchmark driver, and complete campaign report are available here: https://github.com/giffeler/ergometal The detailed measurements and validation procedure for this comparison are documented here: https://github.com/giffeler/ergometal/blob/main/Benchmarks/2026-08-15-search-gather-ceiling-ab.md
Replies
0
Boosts
0
Views
789
Activity
Aug ’26
Xcode 27 Beta 5 unable to link Core Image kernels unless MACOSX_DEPLOYMENT_TARGET = macOS 27
The Metal linker in the latest Xcode 27 Beta 5 is failing to link against the Core Image framework unless the current MACOSX_DEPLOYMENT_TARGET is set to macOS 27 Golden Gate Beta. MTLLINKER_FLAGS = -framework CoreImage It looks like the CoreImage framework that shipped in the Beta 5 SDK fails to include versions of CoreImage.metallib to support prior versions of macOS. If your current deployment target is, for example, macOS 13.5, the build log will show a warning: air-lld: warning: ignoring file '/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage.metallib', file AIR version (2.9) is bigger than the one of the target being linked (2.5) ...and produce this error: air-lld: error: symbol(s) not found for target 'air64_v25-apple-macosx13.5.0' metal: error: air-lld command failed with exit code 1 (use -v to see invocation) The above warning + error happen for any MACOSX_DEPLOYMENT_TARGET up to and including macOS 26. Only when setting it to macOS 27 does the linker succeed. Linking against the Core Image framework is required to package your own CIKernels that use Metal’s [[stitchable]] attribute, in lieu of the previous method based on: MTL_COMPILER_FLAGS = -fcikernel and MTLLINKER_FLAGS = -fcikernel. Has anyone else run into this very same issue? (Filed as FB24345950) Any workarounds you’d be willing to share? Would pulling an older version of the CoreImage framework from a previous SDK, and linking explicitly against it work too? Thanks! Gabe
Replies
1
Boosts
1
Views
190
Activity
Aug ’26
Xcode 27.0 b5, macOS 26.6.1, Metal build fails: symbols not found for air64_v28
I've just downloaded the Xcode 27.0 beta 5 on a macOS 26.6.1 machine and tried to build my app (which includes Metal CoreImage kernels). I'm met with a new (to me) error; /Users/…/Developer/…/air-lld:1:1 symbol(s) not found for target 'air64_v28-apple-macosx26.0.0' and from the build log; air-lld: warning: ignoring file '/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage.metallib', file AIR version (2.9) is bigger than the one of the target being linked (2.8) air-lld: error: symbol(s) not found for target 'air64_v28-apple-macosx26.0.0' metal: error: air-lld command failed with exit code 1 (use -v to see invocation) I have no MTL_LANGUAGE_REVISION in my build settings. If I add one, with value Metal41 the app builds fine, but crashes at runtime as Metal 4.1 isn't supported on macOS 26. I imagine this is a beta Xcode and or macOS SDK bug, is there a workaround?
Replies
1
Boosts
1
Views
1.4k
Activity
Aug ’26