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

Metal Documentation

Posts under Metal subtopic

Post

Replies

Boosts

Views

Activity

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 ?
0
0
15
9h
Residency set memory not freed if process performs no GPU operation
Feedback report: FB23959296 If a process creates a residency set, calls requestResidency, endResidency, and then releases the residency set without ever having done any GPU operations, the memory from the residency set is not freed. Workaround: if the application runs any GPU operation (even an operation not involving the residency set) at any point in its lifecycle (before/while/after creating/releasing the residency set), the memory is freed properly. This was observed in the context of an application that makes an AI model resident in GPU-accessible memory. If the user unloads the model without running any prompts, the memory is not freed. The model occupies ~16GB of RAM so a lot of memory is being leaked. Reproduction: Store the repro.m and workaround.m files from below Run the following commands (repro.m demonstrates the bug; workaround.m demonstrates the workaround): $ clang -framework Foundation -framework Metal -o repro repro.m $ ./repro Footprint at start: 0.00 GB Footprint after buffer allocation: 4.30 GB Footprint 5s after teardown: 4.30 GB $ clang -framework Foundation -framework Metal -o workaround workaround.m $ ./workaround Footprint at start: 0.00 GB Footprint after buffer allocation: 4.37 GB Footprint 5s after teardown: 0.01 GB Expected behavior: Footprint 5s after teardown should be ~0 GB, i.e., the memory is freed. Observed behavior: Footprint 5s after teardown is 4.30 GB, i.e., the memory is not freed. Versions: XCode: 26.6 (17F113) Clang: 21.0.0 (clang-2100.1.1.101, arm64-apple-darwin25.5.0) macOS: 26.5.2 (25F84) Files: repro.m: // Build: clang -framework Foundation -framework Metal -o repro repro.m #import <Metal/Metal.h> #include <mach/mach.h> // Returns the physical memory footprint of the process. static double footprint_gb(void) { task_vm_info_data_t info; mach_msg_type_number_t n = TASK_VM_INFO_COUNT; task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&info, &n); return (double)info.phys_footprint / 1e9; } int main(int argc, char ** argv) { printf("Footprint at start: %5.2f GB\n", footprint_gb()); @autoreleasepool { id<MTLDevice> dev = MTLCreateSystemDefaultDevice(); // Allocate ~4GB of memory. const size_t size = 4ULL << 30; id<MTLBuffer> buf = [dev newBufferWithLength:size options:MTLResourceStorageModeShared]; memset(buf.contents, 0xab, size); // fault the pages in printf("Footprint after buffer allocation: %5.2f GB\n", footprint_gb()); MTLResidencySetDescriptor * desc = [[MTLResidencySetDescriptor alloc] init]; id<MTLResidencySet> rset = [dev newResidencySetWithDescriptor:desc error:nil]; [desc release]; [rset addAllocation:buf]; [rset commit]; [rset requestResidency]; [rset endResidency]; [rset removeAllAllocations]; [rset commit]; [rset release]; [buf release]; [dev release]; } sleep(5); printf("Footprint 5s after teardown: %5.2f GB\n", footprint_gb()); return 0; } workaround.m: // Build: clang -framework Foundation -framework Metal -o workaround workaround.m #import <Metal/Metal.h> #include <mach/mach.h> // Returns the physical memory footprint of the process. static double footprint_gb(void) { task_vm_info_data_t info; mach_msg_type_number_t n = TASK_VM_INFO_COUNT; task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&info, &n); return (double)info.phys_footprint / 1e9; } // Performing any work on the GPU ensures the memory from the residency set will be released. static void do_dummy_work(id<MTLDevice> dev, id<MTLCommandQueue> queue) { @autoreleasepool { id<MTLBuffer> tmp = [dev newBufferWithLength:1 options:MTLResourceStorageModeShared]; id<MTLCommandBuffer> cb = [queue commandBuffer]; id<MTLBlitCommandEncoder> enc = [cb blitCommandEncoder]; [enc fillBuffer:tmp range:NSMakeRange(0, 1) value:0]; [enc endEncoding]; [cb commit]; [tmp release]; } } int main(int argc, char ** argv) { printf("Footprint at start: %5.2f GB\n", footprint_gb()); @autoreleasepool { id<MTLDevice> dev = MTLCreateSystemDefaultDevice(); id<MTLCommandQueue> queue = [dev newCommandQueue]; // Workaround that ensures the memory will be released. // It also works if we call this after the residency set release or at any point in between. do_dummy_work(dev, queue); // Allocate ~4GB of memory. const size_t size = 4ULL << 30; id<MTLBuffer> buf = [dev newBufferWithLength:size options:MTLResourceStorageModeShared]; memset(buf.contents, 0xab, size); // fault the pages in printf("Footprint after buffer allocation: %5.2f GB\n", footprint_gb()); MTLResidencySetDescriptor * desc = [[MTLResidencySetDescriptor alloc] init]; id<MTLResidencySet> rset = [dev newResidencySetWithDescriptor:desc error:nil]; [desc release]; [rset addAllocation:buf]; [rset commit]; [rset requestResidency]; [rset endResidency]; [rset removeAllAllocations]; [rset commit]; [rset release]; [buf release]; [queue release]; [dev release]; } sleep(5); printf("Footprint 5s after teardown: %5.2f GB\n", footprint_gb()); return 0; }
0
0
233
1d
Core Image kernel sampling broken in iOS27 DB4
I've noticed that my camera app is returning blank images on developer beta 4. After some investigation there is an issue with core image custom kernels where the texture sampler is returning NaN / 0 floats. I have a reproducible demo here: https://github.com/alexfoxy/ci-metal-shader-bug Feedback ticket here: https://feedbackassistant.apple.com/feedback/23895753
1
3
255
4d
M5 Pro external 5K 165Hz display: Window animations and scrolling UI appear to render at ~60Hz/jitter while cursor remains perfectly smooth
Hello Apple engineers, I’m trying to determine whether what I’m seeing is expected behavior or a software issue with the new M5 Pro platform. System MacBook Pro (M5 Pro) Latest macOS Beta External 5K 165Hz monitor connected via DisplayPort Refresh rate correctly detected as 165Hz What I observe The display itself is clearly running at 165Hz. For example: Mouse cursor movement is extremely smooth. Dragging the desktop by holding an empty area is also perfectly smooth. However: Moving application windows feels much closer to 60Hz. Scrolling in Safari, Chrome and other applications also appears to run at a much lower frame rate than the display refresh rate. Mission Control animations sometimes show similar micro-stutters. This makes the cursor and desktop movement noticeably smoother than normal window animations. ⸻ Troubleshooting already performed Different DisplayPort cables Different timing configurations Different resolutions / HiDPI modes DSC enabled and disabled Refresh rate confirmed at 165Hz Same behavior across multiple applications The issue appears unrelated to the monitor itself because the cursor is clearly rendered at the full refresh rate. ⸻ Additional observation Interestingly, I previously used another external 4K 144Hz HDR monitor and did not notice this behavior. I also found another M5 Pro user reporting nearly the same issue: external 165Hz display smooth cursor window dragging jitter / micro-stuttering At the same time, I haven’t found similar reports from M4 Pro or the base M5 running the same monitor. ⸻ My question Could this be related to the new M5 Pro display pipeline (WindowServer, Display Engine, or DCP)? Is there any known issue regarding high-refresh-rate external displays on the M5 Pro platform? Or is there additional diagnostic logging (WindowServer, DCP, Metal, etc.) that would help identify whether frames are actually being presented at the display refresh rate? I’d be happy to provide: sysdiagnose WindowServer logs Screen recordings Display timing information IORegistry dumps if they would be helpful. Thank you!
3
1
182
2w
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.
0
0
220
2w
MDLAsset loads texture in usdz file loaded with wrong colorspace
I have a very basic usdz file from this repo I call loadTextures() after loading the usdz via MDLAsset. Inspecting the MDLTexture object I can tell it is assigning a colorspace of linear rgb instead of srgb although the image file in the usdz is srgb. This causes the textures to ultimately render as over saturated. In the code I later convert the MDLTexture to MTLTexture via MTKTextureLoader but if I set the srgb option it seems to ignore it. This significantly impacts the usefulness of Model I/O if it can't load a simple usdz texture correctly. Am I missing something? Thanks!
6
3
1.3k
3w
Background GPU Access availability
I would love to use Background GPU Access to do some video processing in the background. However the documentation of BGContinuedProcessingTaskRequest.Resources.gpu clearly states: Not all devices support background GPU use. For more information, see Performing long-running tasks on iOS and iPadOS. Is there a list available of currently released devices that do (or don't) support GPU background usage? That would help to understand what part of our user base can use this feature. (And what hardware we need to test this on as developers.) For example it seems that it isn't supported on an iPad Pro M1 with the current iOS 26 beta. The simulators also seem to not support the background GPU resource. So would be great to understand what hardware is capable of using this feature!
7
0
1.6k
3w
Timestamp counter heap always returns zero
Hi, I am trying to use a timestamp counter heap, but it always seems to report timestamp zero. Consider this example program: #include <Metal/Metal.h> #include <assert.h> int main(int argc, char *argv[]) { auto device = MTLCreateSystemDefaultDevice(); assert(device); auto descriptor = [MTL4CounterHeapDescriptor new]; [descriptor setType:MTL4CounterHeapTypeTimestamp]; [descriptor setCount:1]; auto heap = [device newCounterHeapWithDescriptor:descriptor error:nullptr]; assert(heap); [heap invalidateCounterRange:NSMakeRange(0, 1)]; auto command_buffer = [device newCommandBuffer]; assert(command_buffer); auto allocator = [device newCommandAllocator]; assert(allocator); [command_buffer beginCommandBufferWithAllocator:allocator]; auto encoder = [command_buffer computeCommandEncoder]; assert(encoder); [encoder writeTimestampWithGranularity:MTL4TimestampGranularityPrecise intoHeap:heap atIndex:0]; [encoder endEncoding]; [command_buffer endCommandBuffer]; auto queue = [device newMTL4CommandQueue]; assert(queue); auto event = [device newSharedEvent]; assert(event); [queue commit:&command_buffer count:1]; [queue signalEvent:event value:1]; [event waitUntilSignaledValue:1 timeoutMS:UINT64_MAX]; auto data = [heap resolveCounterRange:NSMakeRange(0, 1)]; printf("size %lu: %llu\n", data.length, *(uint64_t*)data.bytes); return 0; } Trying to compile and run: % clang++ -g -O0 -o test test.mm -framework Metal -framework Foundation && MTL_DEBUG_LAYER=1 ./test 2026-06-23 14:44:48.006 test[26472:1588857] Metal API Validation Enabled size 8: 0 I would have expected to receive size 8: [some random non-zero number] that number being a GPU timestamp of when the command was executed, but I always get zero. Does anybody have an idea of what I am doing wrong?
1
0
381
3w
Comprehensive documentation and literature
The WWDC videos like the new "Boost your graphics performance with the M5 and A19 GPUs" contain extremely valuable information and tips on how to discover, diagnose and remedy performance issues. They seem to serve as quick reminders and distilled summaries of more comprehensive documentation that I assume can be found somewhere. Where do we find the underlying comprehensive documentation that explains Apple Silicon GPU architecture? How can I learn to understand the basis of the data presented by the Xcode Metal Debugger? Any hints at external literature and resources are welcome.
1
0
380
Jun ’26
Documentation and literature
The WWDC videos like the new "Boost your graphics performance with the M5 and A19 GPUs" contain extremely valuable information and tips on how to discover, diagnose and remedy performance issues. They seem to serve as quick reminders and distilled summaries of more comprehensive documentation that I assume can be found somewhere. Where do we find the underlying comprehensive documentation that explains Apple Silicon GPU architecture? How can I learn to understand the basis of the data presented by the Xcode Metal Debugger? Any hints at external literature and resources are welcome.
0
0
377
Jun ’26
Performance Optimization for Large-Kernel Image Processing
I am processing large images where each output pixel depends on a large neighborhood of surrounding pixels. As a result, the shader performs a very high number of texture sampling operations, which appears to cause cache misses and becomes a performance bottleneck. Since neighboring threads often process adjacent pixels, many of the sampled pixels overlap between threads. Although each thread operates on a slightly different output pixel, a large portion of the texture accesses are effectively identical. Does Metal provide mechanisms that allow neighboring threads to share or synchronize intermediate results in order to reduce redundant texture fetches? Are there recommended approaches for exploiting data reuse across threads, for example through threadgroup memory or other Metal-specific features? In this type of workload, how effective is texture gathering (gather) for reducing sampling overhead, especially when only the RGB channels of an RGBA texture are required? Would using gather generally improve cache utilization and performance in this scenario? When using gather, what is the preferred way to handle texture borders and edge conditions without introducing per-thread branching (e.g., explicit if statements)? Any recommendations for optimizing large-radius neighborhood operations in Metal would be greatly appreciated.
1
0
405
Jun ’26
Memory allocation of textures in Metal
At which time does Metal allocate and deallocate memory for textures? I've observed that the textures live for the whole time of the commandBuffer. So, if I have multiple large textures that I need in subsequent shaders, it would make sense to work with multiple commandBuffers to enable deallocation in order to reduce peak memory usage. Is that correct? Do you have any other suggestions on how to reduce peak memory usage when working with large metal textures? Hint: I am using compute shaders only.
1
1
387
Jun ’26
MetalFX upscaler/denoiser and instant changes
Hi, What's the best way to handle drastic changes in scene charateristics with the new MTLFXTemporalDenoisedScaler? Let's say a visible object of the scene radically changes its material properties. I can modify the albedo and roughness textures consequently. But I suspect the history will be corrupted. Blending visual information between the new frame and the previous ones might be a nonsense. I guess the problem should be the same when objects appear or disappear instantly. Is the upsacler manage these events for us (by lowering blending), or should we use the reactive or the denoise strength mask or something like that to handle them?
3
0
675
Jun ’26
Metal GPU Driver Crash on M5 Pro + macOS 26.5 — kIOGPUCommandBufferCallbackErrorOutOfMemory with <2GB working sets
Metal GPU Driver Crash on M5 Pro + macOS 26.5 — kIOGPUCommandBufferCallbackErrorOutOfMemory with <2GB working sets Summary The Metal driver AGXMetalG17X 351.2 on macOS 26.5 (25F71) for the M5 Pro chip crashes with kIOGPUCommandBufferCallbackErrorOutOfMemory (00000008) when running LLM inference workloads with working sets as small as ~1.5GB, despite 24GB of unified memory being available and Apple Diagnostics confirming the hardware is fully functional. This affects multiple tools: MLX, llama.cpp (Metal backend), and native apps using Metal for inference. System Component Value Model MacBook Pro (Mac17,9) Chip Apple M5 Pro (applegpu_g17s) GPU Cores 16 RAM 24 GB LPDDR5 macOS 26.5 (25F71) Metal Metal 4 GPU Driver AGXMetalG17X 351.2 Xcode 26.5 (17F42) Reproduction MLX (Python) pip install mlx mlx-lm python -m mlx_lm.generate \ --model mlx-community/Qwen2.5-3B-Instruct-4bit \ --max-tokens 10 \ --prompt "Hello" Expected: Normal text generation Actual: Crash with: libc++abi: terminating due to uncaught exception of type std::runtime_error: [METAL] Command buffer execution failed: Insufficient Memory (00000008:kIOGPUCommandBufferCallbackErrorOutOfMemory) llama.cpp brew install llama.cpp llama-cli --model model.gguf --prompt "Hello" --n-predict 20 --n-gpu-layers 99 Expected: Fast GPU generation Actual: Process hangs indefinitely Test Results Tool Model Peak Memory Result MLX Qwen2.5-0.5B-4bit 0.36 GB ✅ Works MLX Qwen2.5-1.5B-4bit 0.98 GB ✅ Works MLX Qwen3-1.7B-4bit 1.01 GB ✅ Works MLX Qwen2.5-3B-4bit ~1.5 GB ❌ Metal OOM crash MLX Qwen3-4B-4bit ~2.1 GB ❌ Metal OOM crash MLX Qwen3-8B-4bit ~4.5 GB ❌ Metal OOM crash llama.cpp Qwen2.5-0.5B GGUF ~0.5 GB ❌ Hangs with GPU llama.cpp Qwen2.5-0.5B GGUF ~0.5 GB ✅ Works with CPU only Key Evidence Hardware is healthy — Apple Diagnostics passed all tests Basic Metal works — matmul, array ops work fine CPU inference works — llama.cpp with -ngl 0 runs correctly The error is NOT about actual memory exhaustion — kIOGPUCommandBufferCallbackErrorOutOfMemory means the kernel rejects the Metal memory commit, not that physical memory is full. The system reports 17.76GB available for Metal working set. Crash Log Extract Thread 31 Crashed: 0 libsystem_kernel.dylib __pthread_kill + 8 1 libsystem_pthread.dylib pthread_kill + 296 2 libsystem_c.dylib abort + 148 3 Metal MTLReportFailure.cold.1 + 48 4 Metal MTLReportFailure + 576 5 Metal -[_MTLCommandBuffer addCompletedHandler:] + 104 ... Exception Type: EXC_CRASH (SIGABRT) Termination Reason: Namespace SIGNAL, Code 6, Abort trap: 6 Related Issues ml-explore/mlx#3586 — Metal compiler regression on macOS 26.5 ml-explore/mlx#3534 — M5 float32 precision issue ml-explore/mlx#3568 — M5 random divergence ml-explore/mlx#3539 — Metal residency OOM (M4 Max) Request Please investigate the AGXMetalG17X driver for M5 Pro on macOS 26.5. The driver appears to incorrectly reject Metal memory commits for LLM inference workloads, even when the working set is well within the system's reported limits (1.5GB requested vs 17.76GB available). Happy to provide full crash logs, sysdiagnose archives, or run additional tests.
0
0
541
May ’26
Inexplicable Metal crash ever since iOS 26.5 beta 4
Hi all, I'm working on updating my audio visualizer app. I'm adding new visualizers based on Metal 4 compute shaders. They worked in iOS 26.4 and iOS 26.5 up until beta 3. However, after that, the visualizers started crashing the phone and forcing a restart. On the latest version of iOS 26.5, the crash is still there. I submitted feedback, but haven't heard anything back just yet. I was wondering if others have faced this same issue, and if there are any workarounds. Here is my repo if you want to look at the code (forgive me if it's sloppy, I'm quite new to graphics programming and Metal): https://github.com/aabagdi/VisualMan/tree/main Thank you!
4
0
1.7k
May ’26
Using setVertexBytes for index primitives
When using index primitives is there a method to provide the indices using a temp buffer like setVertexBytes? Right now I have to create a temp metal buffer even for a small number of vertices and toss it after rendering using drawIndexedPrimitives.
1
0
838
May ’26
MTL4FXTemporalDenoisedScaler initialization
I’m trying to use MTL4FXTemporalDenoisedScaler, and I’m seeing a crash during initialization even with a very simple sample app. I created a minimal sample here: https://github.com/tatsuya-ogawa/MetalFXInitExample The exception is: NSException: "-[AGXG16XFamilyHeap baseObject]: unrecognized selector sent to instance ..." What I found is: • This works: descriptor.makeTemporalDenoisedScaler(device: device) • This crashes: descriptor.makeTemporalDenoisedScaler(device: device, compiler: metal4Compiler) So the issue seems to happen only with the Metal4FX version. For testing, I’m using an iPhone 15 Pro. According to the Metal Feature Set Tables, MetalFX denoised upscaling should be supported on Apple9 and later, so I believe the device itself should meet the requirements. Reference: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf Has anyone seen this before, or knows what might be causing it? I’d appreciate any advice. Thanks.
4
2
767
Apr ’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
0
Boosts
0
Views
15
Activity
9h
Residency set memory not freed if process performs no GPU operation
Feedback report: FB23959296 If a process creates a residency set, calls requestResidency, endResidency, and then releases the residency set without ever having done any GPU operations, the memory from the residency set is not freed. Workaround: if the application runs any GPU operation (even an operation not involving the residency set) at any point in its lifecycle (before/while/after creating/releasing the residency set), the memory is freed properly. This was observed in the context of an application that makes an AI model resident in GPU-accessible memory. If the user unloads the model without running any prompts, the memory is not freed. The model occupies ~16GB of RAM so a lot of memory is being leaked. Reproduction: Store the repro.m and workaround.m files from below Run the following commands (repro.m demonstrates the bug; workaround.m demonstrates the workaround): $ clang -framework Foundation -framework Metal -o repro repro.m $ ./repro Footprint at start: 0.00 GB Footprint after buffer allocation: 4.30 GB Footprint 5s after teardown: 4.30 GB $ clang -framework Foundation -framework Metal -o workaround workaround.m $ ./workaround Footprint at start: 0.00 GB Footprint after buffer allocation: 4.37 GB Footprint 5s after teardown: 0.01 GB Expected behavior: Footprint 5s after teardown should be ~0 GB, i.e., the memory is freed. Observed behavior: Footprint 5s after teardown is 4.30 GB, i.e., the memory is not freed. Versions: XCode: 26.6 (17F113) Clang: 21.0.0 (clang-2100.1.1.101, arm64-apple-darwin25.5.0) macOS: 26.5.2 (25F84) Files: repro.m: // Build: clang -framework Foundation -framework Metal -o repro repro.m #import <Metal/Metal.h> #include <mach/mach.h> // Returns the physical memory footprint of the process. static double footprint_gb(void) { task_vm_info_data_t info; mach_msg_type_number_t n = TASK_VM_INFO_COUNT; task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&info, &n); return (double)info.phys_footprint / 1e9; } int main(int argc, char ** argv) { printf("Footprint at start: %5.2f GB\n", footprint_gb()); @autoreleasepool { id<MTLDevice> dev = MTLCreateSystemDefaultDevice(); // Allocate ~4GB of memory. const size_t size = 4ULL << 30; id<MTLBuffer> buf = [dev newBufferWithLength:size options:MTLResourceStorageModeShared]; memset(buf.contents, 0xab, size); // fault the pages in printf("Footprint after buffer allocation: %5.2f GB\n", footprint_gb()); MTLResidencySetDescriptor * desc = [[MTLResidencySetDescriptor alloc] init]; id<MTLResidencySet> rset = [dev newResidencySetWithDescriptor:desc error:nil]; [desc release]; [rset addAllocation:buf]; [rset commit]; [rset requestResidency]; [rset endResidency]; [rset removeAllAllocations]; [rset commit]; [rset release]; [buf release]; [dev release]; } sleep(5); printf("Footprint 5s after teardown: %5.2f GB\n", footprint_gb()); return 0; } workaround.m: // Build: clang -framework Foundation -framework Metal -o workaround workaround.m #import <Metal/Metal.h> #include <mach/mach.h> // Returns the physical memory footprint of the process. static double footprint_gb(void) { task_vm_info_data_t info; mach_msg_type_number_t n = TASK_VM_INFO_COUNT; task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&info, &n); return (double)info.phys_footprint / 1e9; } // Performing any work on the GPU ensures the memory from the residency set will be released. static void do_dummy_work(id<MTLDevice> dev, id<MTLCommandQueue> queue) { @autoreleasepool { id<MTLBuffer> tmp = [dev newBufferWithLength:1 options:MTLResourceStorageModeShared]; id<MTLCommandBuffer> cb = [queue commandBuffer]; id<MTLBlitCommandEncoder> enc = [cb blitCommandEncoder]; [enc fillBuffer:tmp range:NSMakeRange(0, 1) value:0]; [enc endEncoding]; [cb commit]; [tmp release]; } } int main(int argc, char ** argv) { printf("Footprint at start: %5.2f GB\n", footprint_gb()); @autoreleasepool { id<MTLDevice> dev = MTLCreateSystemDefaultDevice(); id<MTLCommandQueue> queue = [dev newCommandQueue]; // Workaround that ensures the memory will be released. // It also works if we call this after the residency set release or at any point in between. do_dummy_work(dev, queue); // Allocate ~4GB of memory. const size_t size = 4ULL << 30; id<MTLBuffer> buf = [dev newBufferWithLength:size options:MTLResourceStorageModeShared]; memset(buf.contents, 0xab, size); // fault the pages in printf("Footprint after buffer allocation: %5.2f GB\n", footprint_gb()); MTLResidencySetDescriptor * desc = [[MTLResidencySetDescriptor alloc] init]; id<MTLResidencySet> rset = [dev newResidencySetWithDescriptor:desc error:nil]; [desc release]; [rset addAllocation:buf]; [rset commit]; [rset requestResidency]; [rset endResidency]; [rset removeAllAllocations]; [rset commit]; [rset release]; [buf release]; [queue release]; [dev release]; } sleep(5); printf("Footprint 5s after teardown: %5.2f GB\n", footprint_gb()); return 0; }
Replies
0
Boosts
0
Views
233
Activity
1d
Core Image kernel sampling broken in iOS27 DB4
I've noticed that my camera app is returning blank images on developer beta 4. After some investigation there is an issue with core image custom kernels where the texture sampler is returning NaN / 0 floats. I have a reproducible demo here: https://github.com/alexfoxy/ci-metal-shader-bug Feedback ticket here: https://feedbackassistant.apple.com/feedback/23895753
Replies
1
Boosts
3
Views
255
Activity
4d
M5 Pro external 5K 165Hz display: Window animations and scrolling UI appear to render at ~60Hz/jitter while cursor remains perfectly smooth
Hello Apple engineers, I’m trying to determine whether what I’m seeing is expected behavior or a software issue with the new M5 Pro platform. System MacBook Pro (M5 Pro) Latest macOS Beta External 5K 165Hz monitor connected via DisplayPort Refresh rate correctly detected as 165Hz What I observe The display itself is clearly running at 165Hz. For example: Mouse cursor movement is extremely smooth. Dragging the desktop by holding an empty area is also perfectly smooth. However: Moving application windows feels much closer to 60Hz. Scrolling in Safari, Chrome and other applications also appears to run at a much lower frame rate than the display refresh rate. Mission Control animations sometimes show similar micro-stutters. This makes the cursor and desktop movement noticeably smoother than normal window animations. ⸻ Troubleshooting already performed Different DisplayPort cables Different timing configurations Different resolutions / HiDPI modes DSC enabled and disabled Refresh rate confirmed at 165Hz Same behavior across multiple applications The issue appears unrelated to the monitor itself because the cursor is clearly rendered at the full refresh rate. ⸻ Additional observation Interestingly, I previously used another external 4K 144Hz HDR monitor and did not notice this behavior. I also found another M5 Pro user reporting nearly the same issue: external 165Hz display smooth cursor window dragging jitter / micro-stuttering At the same time, I haven’t found similar reports from M4 Pro or the base M5 running the same monitor. ⸻ My question Could this be related to the new M5 Pro display pipeline (WindowServer, Display Engine, or DCP)? Is there any known issue regarding high-refresh-rate external displays on the M5 Pro platform? Or is there additional diagnostic logging (WindowServer, DCP, Metal, etc.) that would help identify whether frames are actually being presented at the display refresh rate? I’d be happy to provide: sysdiagnose WindowServer logs Screen recordings Display timing information IORegistry dumps if they would be helpful. Thank you!
Replies
3
Boosts
1
Views
182
Activity
2w
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
0
Boosts
0
Views
220
Activity
2w
MDLAsset loads texture in usdz file loaded with wrong colorspace
I have a very basic usdz file from this repo I call loadTextures() after loading the usdz via MDLAsset. Inspecting the MDLTexture object I can tell it is assigning a colorspace of linear rgb instead of srgb although the image file in the usdz is srgb. This causes the textures to ultimately render as over saturated. In the code I later convert the MDLTexture to MTLTexture via MTKTextureLoader but if I set the srgb option it seems to ignore it. This significantly impacts the usefulness of Model I/O if it can't load a simple usdz texture correctly. Am I missing something? Thanks!
Replies
6
Boosts
3
Views
1.3k
Activity
3w
Background GPU Access availability
I would love to use Background GPU Access to do some video processing in the background. However the documentation of BGContinuedProcessingTaskRequest.Resources.gpu clearly states: Not all devices support background GPU use. For more information, see Performing long-running tasks on iOS and iPadOS. Is there a list available of currently released devices that do (or don't) support GPU background usage? That would help to understand what part of our user base can use this feature. (And what hardware we need to test this on as developers.) For example it seems that it isn't supported on an iPad Pro M1 with the current iOS 26 beta. The simulators also seem to not support the background GPU resource. So would be great to understand what hardware is capable of using this feature!
Replies
7
Boosts
0
Views
1.6k
Activity
3w
Timestamp counter heap always returns zero
Hi, I am trying to use a timestamp counter heap, but it always seems to report timestamp zero. Consider this example program: #include <Metal/Metal.h> #include <assert.h> int main(int argc, char *argv[]) { auto device = MTLCreateSystemDefaultDevice(); assert(device); auto descriptor = [MTL4CounterHeapDescriptor new]; [descriptor setType:MTL4CounterHeapTypeTimestamp]; [descriptor setCount:1]; auto heap = [device newCounterHeapWithDescriptor:descriptor error:nullptr]; assert(heap); [heap invalidateCounterRange:NSMakeRange(0, 1)]; auto command_buffer = [device newCommandBuffer]; assert(command_buffer); auto allocator = [device newCommandAllocator]; assert(allocator); [command_buffer beginCommandBufferWithAllocator:allocator]; auto encoder = [command_buffer computeCommandEncoder]; assert(encoder); [encoder writeTimestampWithGranularity:MTL4TimestampGranularityPrecise intoHeap:heap atIndex:0]; [encoder endEncoding]; [command_buffer endCommandBuffer]; auto queue = [device newMTL4CommandQueue]; assert(queue); auto event = [device newSharedEvent]; assert(event); [queue commit:&command_buffer count:1]; [queue signalEvent:event value:1]; [event waitUntilSignaledValue:1 timeoutMS:UINT64_MAX]; auto data = [heap resolveCounterRange:NSMakeRange(0, 1)]; printf("size %lu: %llu\n", data.length, *(uint64_t*)data.bytes); return 0; } Trying to compile and run: % clang++ -g -O0 -o test test.mm -framework Metal -framework Foundation && MTL_DEBUG_LAYER=1 ./test 2026-06-23 14:44:48.006 test[26472:1588857] Metal API Validation Enabled size 8: 0 I would have expected to receive size 8: [some random non-zero number] that number being a GPU timestamp of when the command was executed, but I always get zero. Does anybody have an idea of what I am doing wrong?
Replies
1
Boosts
0
Views
381
Activity
3w
Comprehensive documentation and literature
The WWDC videos like the new "Boost your graphics performance with the M5 and A19 GPUs" contain extremely valuable information and tips on how to discover, diagnose and remedy performance issues. They seem to serve as quick reminders and distilled summaries of more comprehensive documentation that I assume can be found somewhere. Where do we find the underlying comprehensive documentation that explains Apple Silicon GPU architecture? How can I learn to understand the basis of the data presented by the Xcode Metal Debugger? Any hints at external literature and resources are welcome.
Replies
1
Boosts
0
Views
380
Activity
Jun ’26
Documentation and literature
The WWDC videos like the new "Boost your graphics performance with the M5 and A19 GPUs" contain extremely valuable information and tips on how to discover, diagnose and remedy performance issues. They seem to serve as quick reminders and distilled summaries of more comprehensive documentation that I assume can be found somewhere. Where do we find the underlying comprehensive documentation that explains Apple Silicon GPU architecture? How can I learn to understand the basis of the data presented by the Xcode Metal Debugger? Any hints at external literature and resources are welcome.
Replies
0
Boosts
0
Views
377
Activity
Jun ’26
Performance Optimization for Large-Kernel Image Processing
I am processing large images where each output pixel depends on a large neighborhood of surrounding pixels. As a result, the shader performs a very high number of texture sampling operations, which appears to cause cache misses and becomes a performance bottleneck. Since neighboring threads often process adjacent pixels, many of the sampled pixels overlap between threads. Although each thread operates on a slightly different output pixel, a large portion of the texture accesses are effectively identical. Does Metal provide mechanisms that allow neighboring threads to share or synchronize intermediate results in order to reduce redundant texture fetches? Are there recommended approaches for exploiting data reuse across threads, for example through threadgroup memory or other Metal-specific features? In this type of workload, how effective is texture gathering (gather) for reducing sampling overhead, especially when only the RGB channels of an RGBA texture are required? Would using gather generally improve cache utilization and performance in this scenario? When using gather, what is the preferred way to handle texture borders and edge conditions without introducing per-thread branching (e.g., explicit if statements)? Any recommendations for optimizing large-radius neighborhood operations in Metal would be greatly appreciated.
Replies
1
Boosts
0
Views
405
Activity
Jun ’26
Opportunities to use Apple intelligence.
Are there opportunities for developers to use Apple Intelligence models through Metal in ways that unlock new rendering, simulation, or real-time content generation techniques?
Replies
1
Boosts
0
Views
365
Activity
Jun ’26
Memory allocation of textures in Metal
At which time does Metal allocate and deallocate memory for textures? I've observed that the textures live for the whole time of the commandBuffer. So, if I have multiple large textures that I need in subsequent shaders, it would make sense to work with multiple commandBuffers to enable deallocation in order to reduce peak memory usage. Is that correct? Do you have any other suggestions on how to reduce peak memory usage when working with large metal textures? Hint: I am using compute shaders only.
Replies
1
Boosts
1
Views
387
Activity
Jun ’26
MetalFX upscaler/denoiser and instant changes
Hi, What's the best way to handle drastic changes in scene charateristics with the new MTLFXTemporalDenoisedScaler? Let's say a visible object of the scene radically changes its material properties. I can modify the albedo and roughness textures consequently. But I suspect the history will be corrupted. Blending visual information between the new frame and the previous ones might be a nonsense. I guess the problem should be the same when objects appear or disappear instantly. Is the upsacler manage these events for us (by lowering blending), or should we use the reactive or the denoise strength mask or something like that to handle them?
Replies
3
Boosts
0
Views
675
Activity
Jun ’26
metal shader converter library distribution
The documentation is unclear. I need a clarification on metal shader converter library distribution. Am I allowed to distribute the library as a part of my macos app bundle?
Replies
0
Boosts
1
Views
322
Activity
Jun ’26
Metal GPU Driver Crash on M5 Pro + macOS 26.5 — kIOGPUCommandBufferCallbackErrorOutOfMemory with <2GB working sets
Metal GPU Driver Crash on M5 Pro + macOS 26.5 — kIOGPUCommandBufferCallbackErrorOutOfMemory with <2GB working sets Summary The Metal driver AGXMetalG17X 351.2 on macOS 26.5 (25F71) for the M5 Pro chip crashes with kIOGPUCommandBufferCallbackErrorOutOfMemory (00000008) when running LLM inference workloads with working sets as small as ~1.5GB, despite 24GB of unified memory being available and Apple Diagnostics confirming the hardware is fully functional. This affects multiple tools: MLX, llama.cpp (Metal backend), and native apps using Metal for inference. System Component Value Model MacBook Pro (Mac17,9) Chip Apple M5 Pro (applegpu_g17s) GPU Cores 16 RAM 24 GB LPDDR5 macOS 26.5 (25F71) Metal Metal 4 GPU Driver AGXMetalG17X 351.2 Xcode 26.5 (17F42) Reproduction MLX (Python) pip install mlx mlx-lm python -m mlx_lm.generate \ --model mlx-community/Qwen2.5-3B-Instruct-4bit \ --max-tokens 10 \ --prompt "Hello" Expected: Normal text generation Actual: Crash with: libc++abi: terminating due to uncaught exception of type std::runtime_error: [METAL] Command buffer execution failed: Insufficient Memory (00000008:kIOGPUCommandBufferCallbackErrorOutOfMemory) llama.cpp brew install llama.cpp llama-cli --model model.gguf --prompt "Hello" --n-predict 20 --n-gpu-layers 99 Expected: Fast GPU generation Actual: Process hangs indefinitely Test Results Tool Model Peak Memory Result MLX Qwen2.5-0.5B-4bit 0.36 GB ✅ Works MLX Qwen2.5-1.5B-4bit 0.98 GB ✅ Works MLX Qwen3-1.7B-4bit 1.01 GB ✅ Works MLX Qwen2.5-3B-4bit ~1.5 GB ❌ Metal OOM crash MLX Qwen3-4B-4bit ~2.1 GB ❌ Metal OOM crash MLX Qwen3-8B-4bit ~4.5 GB ❌ Metal OOM crash llama.cpp Qwen2.5-0.5B GGUF ~0.5 GB ❌ Hangs with GPU llama.cpp Qwen2.5-0.5B GGUF ~0.5 GB ✅ Works with CPU only Key Evidence Hardware is healthy — Apple Diagnostics passed all tests Basic Metal works — matmul, array ops work fine CPU inference works — llama.cpp with -ngl 0 runs correctly The error is NOT about actual memory exhaustion — kIOGPUCommandBufferCallbackErrorOutOfMemory means the kernel rejects the Metal memory commit, not that physical memory is full. The system reports 17.76GB available for Metal working set. Crash Log Extract Thread 31 Crashed: 0 libsystem_kernel.dylib __pthread_kill + 8 1 libsystem_pthread.dylib pthread_kill + 296 2 libsystem_c.dylib abort + 148 3 Metal MTLReportFailure.cold.1 + 48 4 Metal MTLReportFailure + 576 5 Metal -[_MTLCommandBuffer addCompletedHandler:] + 104 ... Exception Type: EXC_CRASH (SIGABRT) Termination Reason: Namespace SIGNAL, Code 6, Abort trap: 6 Related Issues ml-explore/mlx#3586 — Metal compiler regression on macOS 26.5 ml-explore/mlx#3534 — M5 float32 precision issue ml-explore/mlx#3568 — M5 random divergence ml-explore/mlx#3539 — Metal residency OOM (M4 Max) Request Please investigate the AGXMetalG17X driver for M5 Pro on macOS 26.5. The driver appears to incorrectly reject Metal memory commits for LLM inference workloads, even when the working set is well within the system's reported limits (1.5GB requested vs 17.76GB available). Happy to provide full crash logs, sysdiagnose archives, or run additional tests.
Replies
0
Boosts
0
Views
541
Activity
May ’26
Inexplicable Metal crash ever since iOS 26.5 beta 4
Hi all, I'm working on updating my audio visualizer app. I'm adding new visualizers based on Metal 4 compute shaders. They worked in iOS 26.4 and iOS 26.5 up until beta 3. However, after that, the visualizers started crashing the phone and forcing a restart. On the latest version of iOS 26.5, the crash is still there. I submitted feedback, but haven't heard anything back just yet. I was wondering if others have faced this same issue, and if there are any workarounds. Here is my repo if you want to look at the code (forgive me if it's sloppy, I'm quite new to graphics programming and Metal): https://github.com/aabagdi/VisualMan/tree/main Thank you!
Replies
4
Boosts
0
Views
1.7k
Activity
May ’26
Metal 4 support in iOS simulator
I'm updating our app to support metal 4, but the metal 4 types don't seem to get recognized when targeting simulator. Is it known if metal 4 will be supported in the near future, or am I setting up the app wrong?
Replies
6
Boosts
0
Views
1.6k
Activity
May ’26
Using setVertexBytes for index primitives
When using index primitives is there a method to provide the indices using a temp buffer like setVertexBytes? Right now I have to create a temp metal buffer even for a small number of vertices and toss it after rendering using drawIndexedPrimitives.
Replies
1
Boosts
0
Views
838
Activity
May ’26
MTL4FXTemporalDenoisedScaler initialization
I’m trying to use MTL4FXTemporalDenoisedScaler, and I’m seeing a crash during initialization even with a very simple sample app. I created a minimal sample here: https://github.com/tatsuya-ogawa/MetalFXInitExample The exception is: NSException: "-[AGXG16XFamilyHeap baseObject]: unrecognized selector sent to instance ..." What I found is: • This works: descriptor.makeTemporalDenoisedScaler(device: device) • This crashes: descriptor.makeTemporalDenoisedScaler(device: device, compiler: metal4Compiler) So the issue seems to happen only with the Metal4FX version. For testing, I’m using an iPhone 15 Pro. According to the Metal Feature Set Tables, MetalFX denoised upscaling should be supported on Apple9 and later, so I believe the device itself should meet the requirements. Reference: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf Has anyone seen this before, or knows what might be causing it? I’d appreciate any advice. Thanks.
Replies
4
Boosts
2
Views
767
Activity
Apr ’26