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!
0
0
77
3d
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
1.9k
5d
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.4k
1w
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!
1
1
931
1w
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?
0
0
487
1w
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
3k
1w
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.5k
2w
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.5k
2w
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
713
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
159
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.3k
Aug ’26
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
2
0
849
Aug ’26
Metal Shader Converter thread safety
Hello Apple! We've got offline shader compilation from HLSL -> Metallib using DXC -> SPIR-V -> metal.exe. This works okay for the most part, but it requires the creation of intermediate files to pass to/from the metal.exe process and we've had some issues with metal.exe sometimes not launching (probably our fault). Then we noticed Metal Shader Converter (MSC) exists and has a DLL - this looks way better since there's no need to launch processes or store intermediate files. However, upon trying to replace metal.exe with it I quickly ran into rampant heap corruption. I was surprised because the docs claim this: Each thread in your program needs to create its own instance of IRCompiler to avoid race conditions. But once I start calling IRCompilerAllocCompileAndLink in parallel all hell breaks loose, whether or not each thread has its own IRCompiler. I figured I must be doing something wrong, so I removed my attempt and compiled DXC locally with the MSC integration and encountered the exact same heap corruption. So I'm inclined to think the library isn't actually thread safe, but I'm wondering if there's something I'm missing? I tried all 3 versions of MSC just in case it was a problem with 3.0, but I got the same result each time. The only way to make it work was to surround compilation with a mutex, which makes its use pointless in our case.
2
0
1.3k
Aug ’26
How can a local AI agent use MLX/Metal unattended on macOS while remaining confined to an authorized workspace?
How can a local AI agent use MLX/Metal unattended while remaining confined to an authorized workspace? I am developing an AI-driven local media-processing workflow on an Apple-silicon Mac and am trying to understand the correct architecture for allowing it to run unattended without giving the AI agent unrestricted access to my primary personal computer. I am not a software engineer, so I may be missing an established macOS mechanism or using the wrong terminology. I would appreciate guidance from people familiar with MLX, Metal, sandboxing, and macOS security. What I am building I use OpenAI Codex as the local execution/software-development agent. The working system currently: ingests and verifies original video and still media while preserving immutable originals; performs visual semantic analysis and divides video into meaningful time-coded segments; separately analyzes spoken language rather than assuming audio and video are semantically equivalent; uses MLX Whisper locally on Apple silicon for time-coded speech transcription; stores visual and language semantics in a relational SQLite media catalog. These five stages are working. My current test corpus contains 148 original media files, 126 visual semantic segments, and 765 speech segments. The next stages are AI editorial construction from the semantic database and generation of instructions/scripts for a DaVinci Resolve rough cut. The security architecture I want Codex to operate autonomously within a deliberately bounded development environment. I do not want to solve this simply by granting an autonomous agent Full Disk Access to my primary personal Mac. The concern is ordinary fault containment. Codex generates and executes scripts, invokes applications and command-line tools, and manipulates files. A mistaken path or defective generated script should not have unrestricted consequences for the rest of my computer. I therefore separated AI execution from ordinary personal files. Codex is configured for Workspace Write access with explicitly authorized project roots. Canonical media resides on a separately authorized external SSD, and temporary AI working artifacts are kept separately. Ordinary Python and FFmpeg operations now run autonomously within these authorized areas. The problem The difficulty appears when the workflow invokes capabilities that cannot operate inside the ordinary Codex sandbox. The clearest example is MLX Whisper. I am using: MLX Whisper 0.4.3 mlx-community/whisper-small-mlx Apple silicon local transcription MLX Whisper works successfully and its transcription quality is sufficient for my semantic-retrieval application. However, MLX could not access Apple Metal/GPU execution from inside the ordinary Codex sandbox. Codex therefore requested permission to execute the transcription operation outside the sandbox. Once approved, MLX/Metal worked and the entire corpus was successfully transcribed. The processing therefore works, but the workflow cannot run genuinely unattended. A future operation should be able to run: new media → integrity verification → visual semantic analysis → MLX Whisper transcription → language semantic analysis → SQLite update → QA But if execution stops midway waiting for a human to click Allow, the pipeline is not operationally autonomous. What I have already tried I initially encountered permission problems even with ordinary file operations. I therefore: separated Codex work from ordinary personal documents; created dedicated project/work areas; explicitly authorized the required working roots; configured Workspace Write; separately authorized the external media repository; tested shell/Python and FFmpeg operations within those boundaries. Those changes worked. Routine Python and FFmpeg operations now run without approval prompts. The remaining issue occurs with MLX/Metal and some other application/runtime operations that require sandbox escalation. My question Is there a supported architecture for allowing a local AI agent to invoke MLX/Metal and other deliberately authorized development tools unattended, while still confining the agent to defined project/workspace boundaries rather than granting unrestricted access to the entire Mac? For example, should I be investigating: App Sandbox entitlements; a signed helper tool or XPC service; security-scoped resources; a dedicated executable with appropriate entitlements; a different method of launching MLX/Metal; or another macOS mechanism? In particular, can Metal/GPU access coexist with persistent bounded filesystem access without requiring interactive approval each time the AI invokes it? I am also unsure which security layer is actually responsible here: the Codex sandbox, macOS App Sandbox, TCC, executable/code-signing rules, Metal restrictions, or some interaction among them. If this kind of bounded unattended execution is intentionally not supported, that would also be useful to know. My alternative would be a dedicated Apple-silicon Mac containing only the AI-development environment and replaceable project data, where broader permissions would have a much smaller failure domain. I can provide the Codex configuration, exact successful and failing commands, directory/root configuration, macOS/hardware information, and sandbox diagnostics. I would particularly appreciate guidance on which security layer is causing the MLX/Metal escalation and what the supported architecture would be for this use case. Thank you.
0
0
590
Aug ’26
2D Soft Shadows with SpriteKit and Metal
Hi! I'd like to share an implementation of 2D soft shadows using SpriteKit and custom Metal rendering. GitHub Repo SpriteKit-SoftShadows The demo app runs on iOS and Mac Catalyst. The soft shadow implementation is based on Scott Lembcke's algorithm. Pipeline The app uses MTKView to drive the rendering loop at the desired frame rate. Each frame: SpriteKit renders the scene into a Metal texture using SKRenderer. The CPU sends each light's properties and the relevant shape edges to a Metal vertex shader. The vertex shader projects shadow geometry from each edge. A fragment shader calculates the shadow opacity at each pixel, producing a soft shadow mask for each light. A final fragment shader combines the SpriteKit texture, lights, and shadow masks to produce the displayed image. The SwiftUI controls update variables inside the SpriteKit scene through @Observable. The rendering loop consumes the new values on its next cycle. Let me know if you have any feedback!
0
0
662
Aug ’26
Are relaxed threadgroup atomics (atomic_fetch_add) officially supported on the Metal 4.0 feature set, or only 4.1?
I'm writing GPU compute kernels (parallel prefix-sum and histogram) that rely on threadgroup-address-space atomics specifically atomic_fetch_add_explicit on a threadgroup atomic_uint, with memory_order_relaxed. Setup: Device: Apple M5, macOS 26.5 Toolchain reports MSL 4.0 / AIR 2.8 (i.e. the "Metal 4.0" feature level) Note: I'm generating AIR (Apple IR) directly rather than emitting MSL source this is through a custom compute backend (Julia's Metal.jl), not the standard MSL front end. What I observe: These threadgroup atomics compile and produce correct results, and give a meaningful speedup over a non-atomic (scan-based) fallback. I've validated correctness across a 256-bin histogram and a full multi-pass radix sort no mismatches. The question: Some capability checks gate threadgroup atomic support behind Metal 4.1, and my device reports 4.0 yet they clearly work. So: Are relaxed integer threadgroup atomics (atomic_fetch_add on threadgroup atomic_uint, relaxed ordering) officially supported on the Metal 4.0 feature set for current Apple Silicon, or is this unsupported behavior that happens to work? Is there a specific MSL version or GPU family that is the true minimum for these operations? Does the answer differ at the AIR / feature-set level (what I'm targeting) vs. the MSL front end, given I'm feeding AIR to the compiler directly? I ask because a downstream library is (reasonably) hesitant to enable this path unless it's officially supported rather than relying on undefined behavior. Any authoritative guidance or a pointer to the relevant feature-set/GPU-family documentation would be hugely appreciated. Thanks!
1
0
794
Aug ’26
Metal rendering application is not releasing resources
I am developing a metal based ray tracing rendering application (running heavy GPU kernels). I am sometimes "forcefully quitting" my application and I can see the application is not in the activity monitor. But I can see the windowserver is using %97 the GPU. The mac gets hotter and hotter. I kill the windowserver, re-login it is still the case. The only way to fix is to restart the mac. I have checked if there are any zombie processes, there are none. I am 3-4 month into Mac development (I used many rendering APIs e.g. before under Windows and Linux, they release the resources automatically unless the driver is very broken), but I believe when you force quit or exit gracefully, regarding application should release resources. I may be missing some knowledge. Does anybody have an idea? I had added every corner a graceful exit code but once the kernel has some infinite loop the clean up cannot happen. In Windows there are some driver reload mechanisms to recover when GPU is stuck, is there a similar system ?
2
1
2k
Aug ’26
MTL4FXFrameInterpolator no-op on MTL4CommandBuffer
I'm trying to use the new MTL4FX::FrameInterpolator(the Metal 4 variant that encodes to MTL4::CommandBuffer). It creates fine, accepts all texture bindings, and encodes without any error or assertion. The GPU signals completion via shared event. But the output texture is completely untouched — zero bytes changed from before the encode. It's a silent no-op. I'm trying to call metal-cpp from python by making dynamic library with cpp. Environment: macOS 26.6 (build 25G72) Apple M3, arm64 Xcode 26 SDK MetalFX framework (MTL4FX API, macOS 26+) I'm on M3 Summary: MTL4FX::FrameInterpolator::encodeToCommandBuffer(MTL4::CommandBuffer*) records, commits, and the GPU signals completion, but writes zero bytes to the output texture. The encode is a silent no-op — identical to documented issues 146436460 and 146436741 for MTL4FXTemporalScaler/DenoisedScaler. Diagnostic trace: Output texture zeroed before encode: 0/32768 non-zero bytes Output texture after encode (delta=0.5): 0/32768 non-zero bytes Changed bytes: 0/32768 ← definitive no-op Input textures verified: correct (R=1, G=0 vs R=0, G=1) I dont really know how to explain this, the result its just blank.
1
0
773
Aug ’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
94
Activity
3d
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
0
Boosts
0
Views
77
Activity
3d
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
1.9k
Activity
5d
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.4k
Activity
1w
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
1
Boosts
1
Views
931
Activity
1w
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
0
Boosts
0
Views
487
Activity
1w
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
3k
Activity
1w
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.5k
Activity
2w
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.5k
Activity
2w
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
713
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
159
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.3k
Activity
Aug ’26
XCTHitchMetric doesn't work with MTKView
Hello! I was recently trying out XCTHitchMetric with my MTKView and it doesn't seem to record anything. But if I use the Animation Hitches instrument then I do see the hitches get recorded when a frame is presented on screen later than expected. I'm curious if there is a reason for this or maybe I am missing something?
Replies
0
Boosts
0
Views
185
Activity
Aug ’26
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
2
Boosts
0
Views
849
Activity
Aug ’26
Metal Shader Converter thread safety
Hello Apple! We've got offline shader compilation from HLSL -> Metallib using DXC -> SPIR-V -> metal.exe. This works okay for the most part, but it requires the creation of intermediate files to pass to/from the metal.exe process and we've had some issues with metal.exe sometimes not launching (probably our fault). Then we noticed Metal Shader Converter (MSC) exists and has a DLL - this looks way better since there's no need to launch processes or store intermediate files. However, upon trying to replace metal.exe with it I quickly ran into rampant heap corruption. I was surprised because the docs claim this: Each thread in your program needs to create its own instance of IRCompiler to avoid race conditions. But once I start calling IRCompilerAllocCompileAndLink in parallel all hell breaks loose, whether or not each thread has its own IRCompiler. I figured I must be doing something wrong, so I removed my attempt and compiled DXC locally with the MSC integration and encountered the exact same heap corruption. So I'm inclined to think the library isn't actually thread safe, but I'm wondering if there's something I'm missing? I tried all 3 versions of MSC just in case it was a problem with 3.0, but I got the same result each time. The only way to make it work was to surround compilation with a mutex, which makes its use pointless in our case.
Replies
2
Boosts
0
Views
1.3k
Activity
Aug ’26
How can a local AI agent use MLX/Metal unattended on macOS while remaining confined to an authorized workspace?
How can a local AI agent use MLX/Metal unattended while remaining confined to an authorized workspace? I am developing an AI-driven local media-processing workflow on an Apple-silicon Mac and am trying to understand the correct architecture for allowing it to run unattended without giving the AI agent unrestricted access to my primary personal computer. I am not a software engineer, so I may be missing an established macOS mechanism or using the wrong terminology. I would appreciate guidance from people familiar with MLX, Metal, sandboxing, and macOS security. What I am building I use OpenAI Codex as the local execution/software-development agent. The working system currently: ingests and verifies original video and still media while preserving immutable originals; performs visual semantic analysis and divides video into meaningful time-coded segments; separately analyzes spoken language rather than assuming audio and video are semantically equivalent; uses MLX Whisper locally on Apple silicon for time-coded speech transcription; stores visual and language semantics in a relational SQLite media catalog. These five stages are working. My current test corpus contains 148 original media files, 126 visual semantic segments, and 765 speech segments. The next stages are AI editorial construction from the semantic database and generation of instructions/scripts for a DaVinci Resolve rough cut. The security architecture I want Codex to operate autonomously within a deliberately bounded development environment. I do not want to solve this simply by granting an autonomous agent Full Disk Access to my primary personal Mac. The concern is ordinary fault containment. Codex generates and executes scripts, invokes applications and command-line tools, and manipulates files. A mistaken path or defective generated script should not have unrestricted consequences for the rest of my computer. I therefore separated AI execution from ordinary personal files. Codex is configured for Workspace Write access with explicitly authorized project roots. Canonical media resides on a separately authorized external SSD, and temporary AI working artifacts are kept separately. Ordinary Python and FFmpeg operations now run autonomously within these authorized areas. The problem The difficulty appears when the workflow invokes capabilities that cannot operate inside the ordinary Codex sandbox. The clearest example is MLX Whisper. I am using: MLX Whisper 0.4.3 mlx-community/whisper-small-mlx Apple silicon local transcription MLX Whisper works successfully and its transcription quality is sufficient for my semantic-retrieval application. However, MLX could not access Apple Metal/GPU execution from inside the ordinary Codex sandbox. Codex therefore requested permission to execute the transcription operation outside the sandbox. Once approved, MLX/Metal worked and the entire corpus was successfully transcribed. The processing therefore works, but the workflow cannot run genuinely unattended. A future operation should be able to run: new media → integrity verification → visual semantic analysis → MLX Whisper transcription → language semantic analysis → SQLite update → QA But if execution stops midway waiting for a human to click Allow, the pipeline is not operationally autonomous. What I have already tried I initially encountered permission problems even with ordinary file operations. I therefore: separated Codex work from ordinary personal documents; created dedicated project/work areas; explicitly authorized the required working roots; configured Workspace Write; separately authorized the external media repository; tested shell/Python and FFmpeg operations within those boundaries. Those changes worked. Routine Python and FFmpeg operations now run without approval prompts. The remaining issue occurs with MLX/Metal and some other application/runtime operations that require sandbox escalation. My question Is there a supported architecture for allowing a local AI agent to invoke MLX/Metal and other deliberately authorized development tools unattended, while still confining the agent to defined project/workspace boundaries rather than granting unrestricted access to the entire Mac? For example, should I be investigating: App Sandbox entitlements; a signed helper tool or XPC service; security-scoped resources; a dedicated executable with appropriate entitlements; a different method of launching MLX/Metal; or another macOS mechanism? In particular, can Metal/GPU access coexist with persistent bounded filesystem access without requiring interactive approval each time the AI invokes it? I am also unsure which security layer is actually responsible here: the Codex sandbox, macOS App Sandbox, TCC, executable/code-signing rules, Metal restrictions, or some interaction among them. If this kind of bounded unattended execution is intentionally not supported, that would also be useful to know. My alternative would be a dedicated Apple-silicon Mac containing only the AI-development environment and replaceable project data, where broader permissions would have a much smaller failure domain. I can provide the Codex configuration, exact successful and failing commands, directory/root configuration, macOS/hardware information, and sandbox diagnostics. I would particularly appreciate guidance on which security layer is causing the MLX/Metal escalation and what the supported architecture would be for this use case. Thank you.
Replies
0
Boosts
0
Views
590
Activity
Aug ’26
2D Soft Shadows with SpriteKit and Metal
Hi! I'd like to share an implementation of 2D soft shadows using SpriteKit and custom Metal rendering. GitHub Repo SpriteKit-SoftShadows The demo app runs on iOS and Mac Catalyst. The soft shadow implementation is based on Scott Lembcke's algorithm. Pipeline The app uses MTKView to drive the rendering loop at the desired frame rate. Each frame: SpriteKit renders the scene into a Metal texture using SKRenderer. The CPU sends each light's properties and the relevant shape edges to a Metal vertex shader. The vertex shader projects shadow geometry from each edge. A fragment shader calculates the shadow opacity at each pixel, producing a soft shadow mask for each light. A final fragment shader combines the SpriteKit texture, lights, and shadow masks to produce the displayed image. The SwiftUI controls update variables inside the SpriteKit scene through @Observable. The rendering loop consumes the new values on its next cycle. Let me know if you have any feedback!
Replies
0
Boosts
0
Views
662
Activity
Aug ’26
Are relaxed threadgroup atomics (atomic_fetch_add) officially supported on the Metal 4.0 feature set, or only 4.1?
I'm writing GPU compute kernels (parallel prefix-sum and histogram) that rely on threadgroup-address-space atomics specifically atomic_fetch_add_explicit on a threadgroup atomic_uint, with memory_order_relaxed. Setup: Device: Apple M5, macOS 26.5 Toolchain reports MSL 4.0 / AIR 2.8 (i.e. the "Metal 4.0" feature level) Note: I'm generating AIR (Apple IR) directly rather than emitting MSL source this is through a custom compute backend (Julia's Metal.jl), not the standard MSL front end. What I observe: These threadgroup atomics compile and produce correct results, and give a meaningful speedup over a non-atomic (scan-based) fallback. I've validated correctness across a 256-bin histogram and a full multi-pass radix sort no mismatches. The question: Some capability checks gate threadgroup atomic support behind Metal 4.1, and my device reports 4.0 yet they clearly work. So: Are relaxed integer threadgroup atomics (atomic_fetch_add on threadgroup atomic_uint, relaxed ordering) officially supported on the Metal 4.0 feature set for current Apple Silicon, or is this unsupported behavior that happens to work? Is there a specific MSL version or GPU family that is the true minimum for these operations? Does the answer differ at the AIR / feature-set level (what I'm targeting) vs. the MSL front end, given I'm feeding AIR to the compiler directly? I ask because a downstream library is (reasonably) hesitant to enable this path unless it's officially supported rather than relying on undefined behavior. Any authoritative guidance or a pointer to the relevant feature-set/GPU-family documentation would be hugely appreciated. Thanks!
Replies
1
Boosts
0
Views
794
Activity
Aug ’26
Metal rendering application is not releasing resources
I am developing a metal based ray tracing rendering application (running heavy GPU kernels). I am sometimes "forcefully quitting" my application and I can see the application is not in the activity monitor. But I can see the windowserver is using %97 the GPU. The mac gets hotter and hotter. I kill the windowserver, re-login it is still the case. The only way to fix is to restart the mac. I have checked if there are any zombie processes, there are none. I am 3-4 month into Mac development (I used many rendering APIs e.g. before under Windows and Linux, they release the resources automatically unless the driver is very broken), but I believe when you force quit or exit gracefully, regarding application should release resources. I may be missing some knowledge. Does anybody have an idea? I had added every corner a graceful exit code but once the kernel has some infinite loop the clean up cannot happen. In Windows there are some driver reload mechanisms to recover when GPU is stuck, is there a similar system ?
Replies
2
Boosts
1
Views
2k
Activity
Aug ’26
MTL4FXFrameInterpolator no-op on MTL4CommandBuffer
I'm trying to use the new MTL4FX::FrameInterpolator(the Metal 4 variant that encodes to MTL4::CommandBuffer). It creates fine, accepts all texture bindings, and encodes without any error or assertion. The GPU signals completion via shared event. But the output texture is completely untouched — zero bytes changed from before the encode. It's a silent no-op. I'm trying to call metal-cpp from python by making dynamic library with cpp. Environment: macOS 26.6 (build 25G72) Apple M3, arm64 Xcode 26 SDK MetalFX framework (MTL4FX API, macOS 26+) I'm on M3 Summary: MTL4FX::FrameInterpolator::encodeToCommandBuffer(MTL4::CommandBuffer*) records, commits, and the GPU signals completion, but writes zero bytes to the output texture. The encode is a silent no-op — identical to documented issues 146436460 and 146436741 for MTL4FXTemporalScaler/DenoisedScaler. Diagnostic trace: Output texture zeroed before encode: 0/32768 non-zero bytes Output texture after encode (delta=0.5): 0/32768 non-zero bytes Changed bytes: 0/32768 ← definitive no-op Input textures verified: correct (R=1, G=0 vs R=0, G=1) I dont really know how to explain this, the result its just blank.
Replies
1
Boosts
0
Views
773
Activity
Aug ’26