Delve into the world of graphics and game development. Discuss creating stunning visuals, optimizing game mechanics, and share resources for game developers.

All subtopics
Posts under Graphics & Games topic

Post

Replies

Boosts

Views

Activity

MetalFX FI on iPhone: ~18 ms in our game and ~11 ms in a triangle demo — optimization guidance?
We are game developers, evaluating MetalFX frame interpolation for an iPhone game. After integrating MTLFXFrameInterpolator into our game, we observed approximately 18 ms per interpolated frame. To investigate the cost, we created a standalone rotating-triangle demo. Even this demo takes approximately 11 ms shortly after launch at 2622 x 1206 output resolution. This baseline cost is already high for our mobile frame budget, so our main question is whether there is meaningful room for optimization while keeping this output resolution and 30-to-60 presentation. The demo runs on iPhone 17 (A19), iOS 26.6, using Xcode 27.1 and a Release build. It uses standalone FI with RGBA16Float color/history/output, Depth32Float depth, and RG16Float motion vectors. The demo's depth and motion inputs are also 2622 x 1206. Presentation and synchronization are adapted from Apple's PresentThread reference. The game and demo are different workloads, so these observations are not a controlled comparison at identical GPU states. We measure the FI interval using GPU timestamp counter samples, with source-readiness and presentation-pacing waits outside the interval. It includes framework-internal synchronization and our profiling barriers; we have not yet completed a same-state comparison with those markers removed. After sustained running, the demo can rise to approximately 30 ms. A same-process trace shows a Maximum-to-Minimum GPU performance-state transition, so performance scaling may contribute to that increase. Our primary concern remains the initial approximately 11 ms cost, even during the Maximum-state period. Is this baseline cost expected on A19? Could you review whether our integration and measurement are correct, and suggest optimizations such as supported texture formats, depth/motion input sizes, or binding a temporal scaler? A recommended iPhone configuration or reference performance range would also help. We have prepared a triangle-only Xcode project with reproduction steps and timing logs, and can provide it for review.
1
0
324
1w
EXC_BAD_ACCESS in SkyLight SLSWindowServerClientManagedDisplayGetCurrentSpace called from `-[NSScreen _notchFrame]` during display cycle (macOS 14.7.4, Intel MacBook Pro)
Our macOS app crashes intermittently on the main thread inside system frames only. No frame of our own code is in the crashed thread's stack. I would like to know whether others have seen this, and whether there is a known cause or workaround. Environment macOS 14.7.4 (23H420) MacBookPro16,1 (16-inch, 2019), Intel Core i7-9750H, dual GPU (Intel UHD Graphics 630 + AMD Radeon Pro 5300M, automatic graphics switching) Built-in display only, as far as we can tell. We have no record of an external display being connected. The same machine crashed 3 times in 7 days with this same crash signature. Crash Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x000000010a5f9008 Crashed Thread: 0 Dispatch queue: com.apple.main-thread Time Since Wake: 4798 seconds VM Region Info: 0x10a5f9008 is not in any region. CoreAnimation 10a5f8000-10a5f9000 [4K] rw-/rwx ---> GAP OF 0x2000 BYTES CoreAnimation 10a5fb000-10a5fd000 [8K] r--/r-- Thread 0 Crashed: 0 SkyLight SLSWindowServerClientManagedDisplayGetCurrentSpace + 181 1 AppKit -[NSScreen _notchFrame] + 85 2 AppKit _NSScreenFrameByAdjustingFrameForNotch + 55 3 AppKit -[NSScreen _layoutFrame] + 130 4 AppKit -[NSScreen visibleFrame] + 47 5 AppKit -[NSWindow(NSWindowResizing) _resizableEdgesForGrowing:shrinking:] + 589 6 AppKit -[NSWindow(NSWindowResizing) _getEdgeResizingRects:] + 37 7 AppKit -[NSWindow(NSWindow_Theme) _regionForOpaqueViewsModifiedForResizing:] + 53 8 AppKit -[NSWindow(NSWindow_Theme) _resetDragMargins] + 343 9 AppKit -[NSWindow(NSWindow_Theme) _resetDragMarginsIfNeeded] + 43 10 AppKit __NSWindowGetDisplayCycleObserverForUpdateStructuralRegions_block_invoke + 375 11 AppKit NSDisplayCycleObserverInvoke + 140 12 AppKit NSDisplayCycleFlush + 878 13 QuartzCore CA::Transaction::run_commit_handlers(CATransactionPhase) + 95 14 QuartzCore CA::Transaction::commit() + 377 15 AppKit -[_NSScrollingConcurrentMainThreadSynchronizer _synchronize:preCommitHandler:completionHandler:] + 336 ...What we know The faulting address is just past a mapped 4K CoreAnimation region, which suggests a stale pointer into a dynamically mapped region. Near the faulting instruction there is a loop that advances by 0x14 bytes per iteration, which might be a table walk. This is our reading of the disassembly only, not confirmed. About 1 second before the crash, our app closed a secondary window (a standalone chat window). This is the only UI action we see just before the crash, and it happened once, so we cannot say it is the trigger. The crash is not tied to a specific app feature, and it was not right after wake (about 80 minutes after the last wake). Separately, we see crashes on other Intel Macs inside SkyLight called from NSDisplayTiming, across macOS 13 to 26, with the same kind of "address outside any mapped region" fault. We believe they may share a root cause, but we have not proven it. Questions Has anyone seen _notchFrame / SLSWindowServerClientManagedDisplayGetCurrentSpace crashing like this, especially on a Mac with no physical notch? Is -[NSWindow _resetDragMargins] known to read screen geometry at a time when the display configuration or active space can change? Is there anything an app can do (for example, when and how it closes windows, or where it reads NSScreen.visibleFrame) to avoid this, or is this a system bug that should go to Feedback Assistant? I can share the full crash report if it helps. I'll also file a Feedback and post the FB number here.
1
0
587
2w
Game Center Access Point does not appear on iOS 26 (Simulator)
Attempting to bring up the access point yields the following error log: [GameCenterOverlayService] Failed to create GameOverlayUI Dashboard Remote Proxy [GameCenterOverlayService] Could not create endpoint for service name: com.apple.GameOverlayUI.dashboard-service [GameCenterOverlayService] Failed to create GameOverlayUI Dashboard Remote Proxy [GameCenterOverlayService] Could not create endpoint for service name: com.apple.GameOverlayUI.dashboard-service [GameCenterOverlayService] Failed to create GameOverlayUI Dashboard Remote Proxy [GameCenterOverlayService] Failed to create GameOverlayUI Dashboard Remote Proxy The same code (which is a single line setting 'active' to true) works on physical devices and on the simulator in iOS 18.6 I haven't been able to find any mention of this issue online. Any suggestions or help greatly appreciated.
4
1
2.2k
2w
PHASE occluder silences direct sound instead of muffling it
I’m using PHASE for an outdoor soundscape with only .directPathTransmission enabled. A point source and listener are 2 metres apart. Between them is a PHASEOccluder built from a 2 × 2 × 0.02 metre MDLMesh box, with a .cardboard material assigned to every shape element. Without the occluder, the sound is loud. With it, the sound is completely inaudible. Switching to .glass and setting the sampler’s cullOption to .doNotCull makes no audible difference. This happens on both iOS Simulator and a physical iPhone. Adding .lateReverb produces faint audible sound, but room reverb is inappropriate for this outdoor scene and doesn’t establish whether direct transmission works. Is this expected attenuation, or is additional configuration required to hear muffled sound through an occluder? Is there a working sample demonstrating material-dependent transmission with reverb disabled?
3
1
2.0k
2w
System protocol CPU performance question
Hello guys In my game the player sits in the middle of the screen and shoots on enemies coming all around it. (none vr/ar game) I have 3 :systems protocol already to spawn the enemies using timer and budget a different one to move them to the player direction pool system that turned off dead enemies Because reality kit is a high level framework i dont know what is the fastest way to design the bullet system for better cpu speed A. Seperated system for the bullets, asking to know the closest enemy to travel to, hit, and move to the disable pool system if died. or B. Use the same system that moving the enemies but in a seperated loop (prabably one before moving the enemies) Thanks for the help
1
0
75
2w
NSOpenGLView / NSOpenGLContext setView: get no drawable on macOS 15.8.2 RC (24H219), windows render blank (FB25133383)
After updating a MacBook Pro (M1 Pro) from macOS 15.8 to the 15.8.2 release candidate (24H219), every OpenGL context that is attached to a window has no default framebuffer. NSOpenGLView and -[NSOpenGLContext setView:] are both affected, so anything drawn that way shows a blank window. I filed FB25133383 with a minimal sample, kernel log and call trace. Symptoms kCGLCPHasDrawable is 0, glCheckFramebufferStatus(GL_FRAMEBUFFER) returns GL_FRAMEBUFFER_UNDEFINED (0x8219), and glClear raises GL_INVALID_FRAMEBUFFER_OPERATION (0x506). For every attach attempt the kernel logs: (IOGPUFamily) IOGPUGLDrawableUserClient::set_surface(sIOGPUGLDrawableClientSetSurfaceData *): Invalid surface ID = N CGLSetSurface returns kCGLBadDrawable (10005). Stepping through it, CGSBindSurface succeeds and the IOGPU user-client call then fails with kIOReturnBadArgument. What still works Offscreen FBOs in the same context. CAOpenGLLayer and NSOpenGLLayer render correctly in the same process. Only the window-surface path is broken. Minimal sample (public API only) // clang -fobjc-arc -Wno-deprecated-declarations -framework Cocoa -framework OpenGL repro.m -o repro && ./repro #define GL_SILENCE_DEPRECATION 1 #import <Cocoa/Cocoa.h> #import <OpenGL/OpenGL.h> #import <OpenGL/gl.h> #import <OpenGL/glext.h> @interface ReproView : NSOpenGLView @end @implementation ReproView - (void)drawRect:(NSRect)dirtyRect { NSOpenGLContext *ctx = [self openGLContext]; [ctx makeCurrentContext]; GLint hasDrawable = -1; CGLGetParameter(ctx.CGLContextObj, kCGLCPHasDrawable, &hasDrawable); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glClearColor(0, 1, 0, 1); glClear(GL_COLOR_BUFFER_BIT); GLenum err = glGetError(); printf("hasDrawable=%d status=0x%x glError=0x%x\n", hasDrawable, status, err); fflush(stdout); [ctx flushBuffer]; } @end int main(void) { @autoreleasepool { NSApplication *app = [NSApplication sharedApplication]; [app setActivationPolicy:NSApplicationActivationPolicyRegular]; NSWindow *win = [[NSWindow alloc] initWithContentRect:NSMakeRect(200, 300, 240, 240) styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:NO]; NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAAccelerated, 0 }; NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; [win.contentView addSubview:[[ReproView alloc] initWithFrame:NSMakeRect(20, 20, 200, 200) pixelFormat:pf]]; [win makeKeyAndOrderFront:nil]; [app activateIgnoringOtherApps:YES]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ [app terminate:nil]; }); [app run]; } return 0; } Expected: a green square and hasDrawable=1 status=0x8cd5 glError=0x0. On 24H219: nothing is drawn and it prints hasDrawable=0 status=0x8219 glError=0x506. Scope Same result for arm64 and x86_64 under Rosetta, layer-backed or not, main thread or background thread. Affected on my Mac: Sony Imaging Edge Desktop Viewer (NSOpenGLView), DJI Studio (Qt 6, NSOpenGLContext) and its Quick Look extension. Public reports with the same symptom on 24H219: kitty #10645, Alacritty #9067, Godot #124311, Bambu Studio #12530 (all on GitHub). They cover M1, M4, M4 Pro and M4 Max, and the Alacritty report says 15.8.1 was fine. Questions Is this a known issue in the 15.8.2 RC, and will it be fixed before 15.8.2 ships? Is anyone seeing it on the macOS 26.7.2 RC or the 27.2 beta? Workaround for developers in the meantime: render into an IOSurface-backed FBO and present that surface in a CALayer, or use CAOpenGLLayer.
8
4
22k
3w
macOS 27.2 RC (26B118) Built-in display canvas cropped with black bar at bottom-right after login
Description: MacBook Air M5, using only built-in display. The login window renders full screen normally. After logging into desktop session, the display canvas gets cropped with a black bar on the bottom-right corner. This issue is reproducible in Safe Mode and with a brand-new admin user account. No third-party display or window management software installed. Suspected WindowServer display coordinate calculation bug within user session. Environment Device: MacBook Air M5 OS: macOS 27.2 RC (26B118) Display: Built-in display only, no external monitor Reproduction steps Boot to login window, display works fine Log into desktop session Display canvas cropped, black bar appears at bottom-right
1
0
1.1k
3w
M5 Pro external display pipeline width limits and native HiDPI support
Hello Apple Engineering Team, I would like to clarify a technical question regarding the external display architecture of the M5 Pro MacBook Pro. I use a single ultrawide monitor with a native resolution of 3440 × 1440. To achieve true 2× HiDPI rendering at this logical resolution, macOS would need to render a framebuffer of 6880 × 2880. Third-party diagnostic tools and firmware reverse-engineering reports appear to indicate that M5 Pro has display-pipeline source-width limits of 6720 and 7680 pixels. Could you please clarify the following? Are these reported source-width limits accurate for the M5 Pro? Can macOS assign a single external display to the display pipeline that supports a 7680-pixel source width? Is there a supported way to influence or change this pipeline allocation, such as changing the connection port, connection order, or display configuration? Can a single 3440 × 1440 external monitor use native 2× HiDPI rendering (6880 × 2880) on the M5 Pro without virtual-display mirroring? If this configuration is unsupported, is the limitation imposed by hardware, firmware, or macOS display allocation policy? I understand that Apple may not disclose all internal implementation details. Any clarification regarding supported configurations or known limitations would be greatly appreciated. Thank you.
0
0
516
3w
Game Center Dashboard overlay doesn't have Done or x button
From this WWDC video -> https://developer.apple.com/videos/play/wwdc2020/10618/ I see the examples show that almost each screen have a "Done" button on top trailing, document sites also show the x button on top trailing, however, in my app, the overlay shows without any Done or x button, it doesn't look very apparent how to "close" this popup. I soon learned the hardware that the trick is to tap on empty areas. Is there a way to enable the Done or x button in it?
0
0
475
3w
Photogrammetry with Object masks hangs and terminates with masks of objects
[PhotogrammetrySample]) with objectMask set and traps on my ios26.5.2, see the attached screenshot on feedback FB24379913 , it gets to the function and hangs . Even the folder reconstruction with lazy sequence as recommended from your video sample also doesn;t complete as it can't find alignment and displays the CoreOC.PhotogrammetrySession.Error error 6 means alignment failed. What can be done or do you guys expose any functions that can be used to check or trace or handle these internally The ObjectMasks are actually segmentation masks from an segmentation algorithm I will appreciate a timely response and willing to provide more clarity and informations, thank you so much for your understanding
3
0
1.5k
3w
Metal CSM Shadows GPU Culling+Indirect+Vertex Amplification - empty some Shadow Cascades
Hi! I'm porting Cascaded Shadow Maps(CSM) from HLSL Direct3D12/Vulkan I'm using GPU Culling, indirect Call + Vertex Amplification for shadow Casters for creating Shadow map texture. Shadow map texture - Texture2DArray Shadow castes are rendering using Instancing and IndirectDraw, VS shader are checking [amplification_id]] and view mask CS shader are finding shadow caster using InstanceId and view mask for each shadow cascade: // dataIndex - Instance index for featching Instance Matrix // viewMask - for VS [[amplification_id]] uint PackInstanceData(uint viewMask, uint dataIndex) { return (viewMask << 28u) | dataIndex; } kernel void CullObjects(uint2 DTid [[thread_position_in_grid]], constant ArgBuf& argBuf [[buffer(0)]], uint groupIndex [[thread_index_in_threadgroup]]) { threadgroup atomic_uint sharedNumObjects; threadgroup uint sharedInstanceId[32]; threadgroup uint globalBufferIndex; constant auto& cbData = *argBuf.cbData; uint index = DTid.x; if (!groupIndex) { atomic_store_explicit(&sharedNumObjects, 0u, memory_order_relaxed); globalBufferIndex = 0u; } threadgroup_barrier(mem_flags::mem_threadgroup); bool visible = false; uint viewMask = 0; if (index < cbData.numInstanceObjects) { const device CullingObjInfo& cullingObjectInfo = argBuf.cullingObjInfo[index]; // find shadow casters for each shadow cascade for (uint i = 0u; i < NUM_FRUSTUMS; ++i) { constant Frustum& frustum = cbData.frustums[i]; visible = SphereInFrustum(frustum, cullingObjectInfo.boundingSphere); if (visible) { visible = BoundingBoxInFrustum(frustum, cullingObjectInfo.boundingBox.minPoint, cullingObjectInfo.boundingBox.maxPoint); } if (visible) { viewMask |= (1u << i); } } visible = bool(viewMask); } } if (visible) { uint bufferIndex = atomic_fetch_add_explicit(&sharedNumObjects, 1u, memory_order_relaxed); sharedInstanceId[bufferIndex] = PackInstanceData(viewMask, index); } threadgroup_barrier(mem_flags::mem_threadgroup); uint localNumObjects = atomic_load_explicit(&sharedNumObjects, memory_order_relaxed); if (!groupIndex && localNumObjects) { globalBufferIndex = atomic_fetch_add_explicit(&argBuf.numObjects->instanceCount, localNumObjects, memory_order_relaxed); } threadgroup_barrier(mem_flags::mem_threadgroup); if (groupIndex < localNumObjects) { argBuf.instanceId[globalBufferIndex + groupIndex] = sharedInstanceId[groupIndex]; } } VS shader for depth shadow map rendering: // struct PSOutput { float4 pos [[position]]; float2 Depth [[user(locn0)]]; float CullDist [[clip_distance]]; uint layer [[render_target_array_index]]; }; struct VS { float4 pos [[attribute(0)]]; uint InstanceId [[attribute(9)]]; }; struct b { float4x4 lightViewProj[NUM_SM_CASCADES]; }; struct Arg { const device float3x4* InstanceData [[id(0)]]; constant b* cb [[id(1)]]; }; uint UnpackViewInstancingMask(uint packedData) { return packedData >> 28u; } uint UnpackInstanceIndex(uint packedData) { return packedData & 0x0FFFFFFFu; } vertex PSOutput vsMain(VS In [[stage_in]], constant Arg& arg [[buffer(VSArgumentBufferIndex)]], ushort ampID [[amplification_id]]) { constant auto& b0 = *arg.cb; PSOutput output; float4 WorldPos = float4(In.pos.xyz, 1.0f); uint viewMask = UnpackViewInstancingMask(In.InstanceId); output.layer = ampID; // check shadow caster rendering for each cascade using ampID and viewMask if (viewMask & (1u << ampID)) { float3x4 instanceMatrix = arg.InstanceData[UnpackInstanceIndex(In.InstanceId)]; WorldPos = float4((WorldPos * instanceMatrix).xyz, 1.0f); output.CullDist = 1.0f; } else { output.pos = float4(0.0f, 0.0f, 2.0f, 1.0f); // skeep unvisible object for this cascade output.CullDist = -1.0f; return output; } output.pos = b0.lightViewProj[ampID] * WorldPos; output.Depth.xy = output.pos.zz; return output; } I have result left part: CPU Version - separate rendering for each layer for texture2Darray shadow map right part: GPU culling + Indirect + Vertex Amplification Got to fix error ? Why 1 and 3 cascade are empty? 0 cascade has duplicate data from other cascades.
2
0
787
3w
Processing RAW files using CIRAWFilter slows down after opening a few different images
Is there some cleanup required if you are opening multiple different RAW files - I am seeing a slow down each time I open a new file and things grind to a halt after opening 5 or 6 files, one after the other - even allowing some time between opening them. Currently I have a single view with a CAMetalLayer and a single Renderer and CIContent - should I be creating a new CAMetalLayer, render and CIContext each time a new image is opened ? Alternately is there some way to clear the cache or something to maintain performance.
1
0
502
3w
GKMatch: GameKitServices crashes in GCKSessionReceiveDOOB on the second real-time match — the finished session is never reclaimed
We ship a two-player real-time GameKit game. On iOS 27 the app crashes inside GameKitServices on the second real-time match of any app session — nine times out of nine yesterday. Filed as FB24789094 (and FB24788999 for a separate reinvitation problem). Posting the measurements here because the unified log makes the mechanism visible, and because everything I tried at the app level failed — maybe somebody has the missing piece. THE CRASH Main thread, no application frame anywhere on the stack: CFRetain + 52 GCKSessionReceiveDOOB + 1632 -[GKSessionInternal receiveDOOB:fromPeer:inSession:context:] + 320 -[GKSessionInternal(_private) tellDelegate_didReceiveBand_RetryICE:] + 212 __NSThreadPerformPerform + 264 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ EXC_BAD_ACCESS (SIGBUS), EXC_ARM_DA_ALIGN at 0x9 (0xa in one report). In every report the faulting address is exactly x0 + 8, and x0 is 1 or 2 — CFRetain is handed a small integer, not a pointer. A use-after-free would fault on a large plausible-looking address; 1 and 2 are not addresses at all. Address Sanitizer agrees: no heap error is reported before the fault, only __asan::ReportDeadlySignal directly above the same three GameKitServices frames. It reads like type confusion in the RetryICE band path. Not the SDK: a build made with Xcode 26.6 against iphoneos26.5 crashes identically — same stack, same registers. The peer's OS does not matter either (iPadOS 17.7.11, iOS 26.6.1 and iOS 27.0 all seen on the other side, and in one case an older build of our own app). Only the crashing device is always on iOS 27.0 (24A435), an iPhone 15 Pro. RECIPE Two devices, two Game Center accounts. Form a two-player real-time GKMatch — GKMatchmaker.findMatch(for:) or an invitation, both reproduce. Wait for the peer to connect, call finishMatchmaking(for:). Play for ten seconds or so, so data really flows. End it: match.disconnect(), release the GKMatch. In the SAME process, form a SECOND real-time match. Play. The crash lands roughly ten to thirty seconds after the second match starts exchanging data. A first match in a freshly launched process has never crashed for us. Out of eleven app sessions that reached a second match, two were force quit by hand during other tests and the remaining nine all crashed here. THE SESSION IS NEVER RECLAIMED GameKit runs one "com.apple.gamekitservices.gcksession.recvproc" / "sendproc" thread pair per live real-time session, in the app's own process. You can count them from inside the app, which turns out to be the only way to see what is going on: var threads: thread_act_array_t? var count: mach_msg_type_number_t = 0 task_threads(mach_task_self_, &threads, &count) // then pthread_from_mach_thread_np(threads[i]) + pthread_getname_np, and compare the name Measured across one app session: after Game Center authentication, before any match ......... 0 first match live ........................................... 1 right after match.disconnect() returns ..................... 1 <- not reclaimed before the second match is adopted ......................... 2 right after the second match's disconnect() ................ 2 Every crash report shows two of those pairs alive, although the app holds exactly one GKMatch at a time and releases the finished one the instant disconnect() returns. The same leak is visible on iOS 26.6.1 (an iPhone 11 Pro leaks identically) — it just does not crash there. WHAT THE LEFTOVER SESSION DOES Each match gets its own CDXClient. The first match's is never torn down, and keeps poking its hole on a 30-second keep-alive, on the same local port (:16402) the second match then binds: 15:28:05.117 <CDXClient: 0x155872e40> requesting-hole-punch <- match 1 15:28:35.289 <CDXClient: 0x155872e40> requesting-hole-punch <- match 1, +30s, match already over 15:28:50.197 <CDXClient: 0x12d4bda40> requesting-hole-punch <- match 2 15:29:05.287 <CDXClient: 0x155872e40> requesting-hole-punch <- match 1 again, 4s before the crash GCKSessionCreate:6425 globalscopelaunch appears once per process; the second match only does 6509 globalscoperequest and reuses the global scope. During the second match's ICE setup a packet arrives belonging to no live session: -[CDXClient handleFDEvent]:1066 packet-from-unknown-session -[CDXClient handleFDEvent]:1067 Incoming packet from unknown session. SID = ... immediately followed by [ERROR] ICEStopConnectivityCheck:2763 ICEStopConnectivityCheck() found no ICE check with call id (...) [ERROR] gckSessionCheckPendingConnections:1545 iICEChecksLeft=0, iUnconnectedNodeCount=0, iDDsExpected=1 Those lines appear exactly three times in a 28-minute window, all three in the two processes that went on to crash, never during a first match. About fourteen seconds later the RetryICE band is delivered and CFRetain is called on the garbage. WHAT DID NOT WORK Releasing the GKMatch immediately after disconnect(). The session threads stay. Waiting. Gaps of 17, 19, 22, 25, 30 and 45 seconds between the two matches all crashed. Tearing the match down cleanly. I suspected that calling disconnect() while match.players was still non-empty was the trigger — five out of five such teardowns were followed by a crash. So I made the quitting side announce its departure, wait for match(_:player:didChange:) to report the peer gone, and only then disconnect. It works (disconnect now runs with players == 0) and it changes nothing: the count still reads 1 afterwards, and the next match still crashes. Worth saying explicitly, because the correlation was strong enough to look causal. Skipping finishMatchmaking(for:). No effect. The only thing that reliably avoids it is allowing a single real-time match per app launch, which is a poor thing to ship. QUESTIONS Is there a supported way to make GameKit release a finished GKMatch's session inside the process? A GKMatch that never connected (peer wait timed out, disconnect() on an empty match) appears to leave the same residue, so it is not about how the match ended. And has anyone else seen GCKSessionReceiveDOOB / tellDelegate_didReceiveBand_RetryICE? I could not find a single mention of these symbols anywhere.
3
2
1.6k
3w
Public API for system-wide SDR luminance control on built-in XDR?
I am investigating whether a macOS display utility can adjust the luminance of normal SDR desktop content system-wide, including other apps, on the built-in Liquid Retina XDR display of a 2021 M1 Max MacBook Pro. Is there a documented public API, or combination of public APIs, for this scope? The research target is SDR white around 1000 cd/m² while retaining HDR highlight capability, where supported by the hardware and OS. This is a feasibility question, not a claim that this output has been achieved or is supported. The approach must preserve OS color management and respect thermal, power and brightness limits, including protective dimming. I am not seeking gamma-table changes, screen capture and HDR re-display, private APIs, or bypasses of system protections. I understand that enabling EDR for an app's own layer is different from controlling ordinary SDR content in other apps. I am specifically asking about the latter. If this is supported, could you point to the API names, primary documentation, applicable macOS versions and hardware limitations? If it is not supported through public APIs, an explicit clarification would also be helpful.
2
0
1.4k
4w
Clarifying Fence Behavior in Metal 4
I have some clarifying questions on how fences work in Metal 4. If two encoders A, B update the same fence and encoder C waits on that fence, is the work encoded by C guaranteed to execute after both A and B have completed, or after either A or B have completed? The following quotes in the waitForFence() documentation seem contradictory. "Encodes a command that instructs the GPU to pause before starting one or more stages of the pass until a pass updates a fence." "When encoding a pass that reuses a fence, wait for other passes to update the fence before repurposing that fence..." Are fences unsignaled when they are waited on? Specifically, can two (or more) encoders wait on a fence that is only updated in a single prior encoder? If an encoder updates a fence, no subsequent encoders in the command queue wait on the fence, and the command queue is committed, is that fence still signaled when used in a subsequent command buffer?
1
0
2.1k
Oct ’26
MetalFX FI on iPhone: ~18 ms in our game and ~11 ms in a triangle demo — optimization guidance?
We are game developers, evaluating MetalFX frame interpolation for an iPhone game. After integrating MTLFXFrameInterpolator into our game, we observed approximately 18 ms per interpolated frame. To investigate the cost, we created a standalone rotating-triangle demo. Even this demo takes approximately 11 ms shortly after launch at 2622 x 1206 output resolution. This baseline cost is already high for our mobile frame budget, so our main question is whether there is meaningful room for optimization while keeping this output resolution and 30-to-60 presentation. The demo runs on iPhone 17 (A19), iOS 26.6, using Xcode 27.1 and a Release build. It uses standalone FI with RGBA16Float color/history/output, Depth32Float depth, and RG16Float motion vectors. The demo's depth and motion inputs are also 2622 x 1206. Presentation and synchronization are adapted from Apple's PresentThread reference. The game and demo are different workloads, so these observations are not a controlled comparison at identical GPU states. We measure the FI interval using GPU timestamp counter samples, with source-readiness and presentation-pacing waits outside the interval. It includes framework-internal synchronization and our profiling barriers; we have not yet completed a same-state comparison with those markers removed. After sustained running, the demo can rise to approximately 30 ms. A same-process trace shows a Maximum-to-Minimum GPU performance-state transition, so performance scaling may contribute to that increase. Our primary concern remains the initial approximately 11 ms cost, even during the Maximum-state period. Is this baseline cost expected on A19? Could you review whether our integration and measurement are correct, and suggest optimizations such as supported texture formats, depth/motion input sizes, or binding a temporal scaler? A recommended iPhone configuration or reference performance range would also help. We have prepared a triangle-only Xcode project with reproduction steps and timing logs, and can provide it for review.
Replies
1
Boosts
0
Views
324
Activity
1w
EXC_BAD_ACCESS in SkyLight SLSWindowServerClientManagedDisplayGetCurrentSpace called from `-[NSScreen _notchFrame]` during display cycle (macOS 14.7.4, Intel MacBook Pro)
Our macOS app crashes intermittently on the main thread inside system frames only. No frame of our own code is in the crashed thread's stack. I would like to know whether others have seen this, and whether there is a known cause or workaround. Environment macOS 14.7.4 (23H420) MacBookPro16,1 (16-inch, 2019), Intel Core i7-9750H, dual GPU (Intel UHD Graphics 630 + AMD Radeon Pro 5300M, automatic graphics switching) Built-in display only, as far as we can tell. We have no record of an external display being connected. The same machine crashed 3 times in 7 days with this same crash signature. Crash Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x000000010a5f9008 Crashed Thread: 0 Dispatch queue: com.apple.main-thread Time Since Wake: 4798 seconds VM Region Info: 0x10a5f9008 is not in any region. CoreAnimation 10a5f8000-10a5f9000 [4K] rw-/rwx ---> GAP OF 0x2000 BYTES CoreAnimation 10a5fb000-10a5fd000 [8K] r--/r-- Thread 0 Crashed: 0 SkyLight SLSWindowServerClientManagedDisplayGetCurrentSpace + 181 1 AppKit -[NSScreen _notchFrame] + 85 2 AppKit _NSScreenFrameByAdjustingFrameForNotch + 55 3 AppKit -[NSScreen _layoutFrame] + 130 4 AppKit -[NSScreen visibleFrame] + 47 5 AppKit -[NSWindow(NSWindowResizing) _resizableEdgesForGrowing:shrinking:] + 589 6 AppKit -[NSWindow(NSWindowResizing) _getEdgeResizingRects:] + 37 7 AppKit -[NSWindow(NSWindow_Theme) _regionForOpaqueViewsModifiedForResizing:] + 53 8 AppKit -[NSWindow(NSWindow_Theme) _resetDragMargins] + 343 9 AppKit -[NSWindow(NSWindow_Theme) _resetDragMarginsIfNeeded] + 43 10 AppKit __NSWindowGetDisplayCycleObserverForUpdateStructuralRegions_block_invoke + 375 11 AppKit NSDisplayCycleObserverInvoke + 140 12 AppKit NSDisplayCycleFlush + 878 13 QuartzCore CA::Transaction::run_commit_handlers(CATransactionPhase) + 95 14 QuartzCore CA::Transaction::commit() + 377 15 AppKit -[_NSScrollingConcurrentMainThreadSynchronizer _synchronize:preCommitHandler:completionHandler:] + 336 ...What we know The faulting address is just past a mapped 4K CoreAnimation region, which suggests a stale pointer into a dynamically mapped region. Near the faulting instruction there is a loop that advances by 0x14 bytes per iteration, which might be a table walk. This is our reading of the disassembly only, not confirmed. About 1 second before the crash, our app closed a secondary window (a standalone chat window). This is the only UI action we see just before the crash, and it happened once, so we cannot say it is the trigger. The crash is not tied to a specific app feature, and it was not right after wake (about 80 minutes after the last wake). Separately, we see crashes on other Intel Macs inside SkyLight called from NSDisplayTiming, across macOS 13 to 26, with the same kind of "address outside any mapped region" fault. We believe they may share a root cause, but we have not proven it. Questions Has anyone seen _notchFrame / SLSWindowServerClientManagedDisplayGetCurrentSpace crashing like this, especially on a Mac with no physical notch? Is -[NSWindow _resetDragMargins] known to read screen geometry at a time when the display configuration or active space can change? Is there anything an app can do (for example, when and how it closes windows, or where it reads NSScreen.visibleFrame) to avoid this, or is this a system bug that should go to Feedback Assistant? I can share the full crash report if it helps. I'll also file a Feedback and post the FB number here.
Replies
1
Boosts
0
Views
587
Activity
2w
Game Center Access Point does not appear on iOS 26 (Simulator)
Attempting to bring up the access point yields the following error log: [GameCenterOverlayService] Failed to create GameOverlayUI Dashboard Remote Proxy [GameCenterOverlayService] Could not create endpoint for service name: com.apple.GameOverlayUI.dashboard-service [GameCenterOverlayService] Failed to create GameOverlayUI Dashboard Remote Proxy [GameCenterOverlayService] Could not create endpoint for service name: com.apple.GameOverlayUI.dashboard-service [GameCenterOverlayService] Failed to create GameOverlayUI Dashboard Remote Proxy [GameCenterOverlayService] Failed to create GameOverlayUI Dashboard Remote Proxy The same code (which is a single line setting 'active' to true) works on physical devices and on the simulator in iOS 18.6 I haven't been able to find any mention of this issue online. Any suggestions or help greatly appreciated.
Replies
4
Boosts
1
Views
2.2k
Activity
2w
Update license of D3DMetal for redistribution
CrossOvers and Whisky both redistribute D3DMetal in their app. We would like to do so as well but the included license does not make it clear. Please update the license to make the exception clear so we can distribute under the same terms as those apps. FB24262864 is also filed regarding this issue.
Replies
2
Boosts
0
Views
791
Activity
2w
PHASE occluder silences direct sound instead of muffling it
I’m using PHASE for an outdoor soundscape with only .directPathTransmission enabled. A point source and listener are 2 metres apart. Between them is a PHASEOccluder built from a 2 × 2 × 0.02 metre MDLMesh box, with a .cardboard material assigned to every shape element. Without the occluder, the sound is loud. With it, the sound is completely inaudible. Switching to .glass and setting the sampler’s cullOption to .doNotCull makes no audible difference. This happens on both iOS Simulator and a physical iPhone. Adding .lateReverb produces faint audible sound, but room reverb is inappropriate for this outdoor scene and doesn’t establish whether direct transmission works. Is this expected attenuation, or is additional configuration required to hear muffled sound through an occluder? Is there a working sample demonstrating material-dependent transmission with reverb disabled?
Replies
3
Boosts
1
Views
2.0k
Activity
2w
System protocol CPU performance question
Hello guys In my game the player sits in the middle of the screen and shoots on enemies coming all around it. (none vr/ar game) I have 3 :systems protocol already to spawn the enemies using timer and budget a different one to move them to the player direction pool system that turned off dead enemies Because reality kit is a high level framework i dont know what is the fastest way to design the bullet system for better cpu speed A. Seperated system for the bullets, asking to know the closest enemy to travel to, hit, and move to the disable pool system if died. or B. Use the same system that moving the enemies but in a seperated loop (prabably one before moving the enemies) Thanks for the help
Replies
1
Boosts
0
Views
75
Activity
2w
NSOpenGLView / NSOpenGLContext setView: get no drawable on macOS 15.8.2 RC (24H219), windows render blank (FB25133383)
After updating a MacBook Pro (M1 Pro) from macOS 15.8 to the 15.8.2 release candidate (24H219), every OpenGL context that is attached to a window has no default framebuffer. NSOpenGLView and -[NSOpenGLContext setView:] are both affected, so anything drawn that way shows a blank window. I filed FB25133383 with a minimal sample, kernel log and call trace. Symptoms kCGLCPHasDrawable is 0, glCheckFramebufferStatus(GL_FRAMEBUFFER) returns GL_FRAMEBUFFER_UNDEFINED (0x8219), and glClear raises GL_INVALID_FRAMEBUFFER_OPERATION (0x506). For every attach attempt the kernel logs: (IOGPUFamily) IOGPUGLDrawableUserClient::set_surface(sIOGPUGLDrawableClientSetSurfaceData *): Invalid surface ID = N CGLSetSurface returns kCGLBadDrawable (10005). Stepping through it, CGSBindSurface succeeds and the IOGPU user-client call then fails with kIOReturnBadArgument. What still works Offscreen FBOs in the same context. CAOpenGLLayer and NSOpenGLLayer render correctly in the same process. Only the window-surface path is broken. Minimal sample (public API only) // clang -fobjc-arc -Wno-deprecated-declarations -framework Cocoa -framework OpenGL repro.m -o repro && ./repro #define GL_SILENCE_DEPRECATION 1 #import <Cocoa/Cocoa.h> #import <OpenGL/OpenGL.h> #import <OpenGL/gl.h> #import <OpenGL/glext.h> @interface ReproView : NSOpenGLView @end @implementation ReproView - (void)drawRect:(NSRect)dirtyRect { NSOpenGLContext *ctx = [self openGLContext]; [ctx makeCurrentContext]; GLint hasDrawable = -1; CGLGetParameter(ctx.CGLContextObj, kCGLCPHasDrawable, &hasDrawable); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); glClearColor(0, 1, 0, 1); glClear(GL_COLOR_BUFFER_BIT); GLenum err = glGetError(); printf("hasDrawable=%d status=0x%x glError=0x%x\n", hasDrawable, status, err); fflush(stdout); [ctx flushBuffer]; } @end int main(void) { @autoreleasepool { NSApplication *app = [NSApplication sharedApplication]; [app setActivationPolicy:NSApplicationActivationPolicyRegular]; NSWindow *win = [[NSWindow alloc] initWithContentRect:NSMakeRect(200, 300, 240, 240) styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:NO]; NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAAccelerated, 0 }; NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; [win.contentView addSubview:[[ReproView alloc] initWithFrame:NSMakeRect(20, 20, 200, 200) pixelFormat:pf]]; [win makeKeyAndOrderFront:nil]; [app activateIgnoringOtherApps:YES]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ [app terminate:nil]; }); [app run]; } return 0; } Expected: a green square and hasDrawable=1 status=0x8cd5 glError=0x0. On 24H219: nothing is drawn and it prints hasDrawable=0 status=0x8219 glError=0x506. Scope Same result for arm64 and x86_64 under Rosetta, layer-backed or not, main thread or background thread. Affected on my Mac: Sony Imaging Edge Desktop Viewer (NSOpenGLView), DJI Studio (Qt 6, NSOpenGLContext) and its Quick Look extension. Public reports with the same symptom on 24H219: kitty #10645, Alacritty #9067, Godot #124311, Bambu Studio #12530 (all on GitHub). They cover M1, M4, M4 Pro and M4 Max, and the Alacritty report says 15.8.1 was fine. Questions Is this a known issue in the 15.8.2 RC, and will it be fixed before 15.8.2 ships? Is anyone seeing it on the macOS 26.7.2 RC or the 27.2 beta? Workaround for developers in the meantime: render into an IOSurface-backed FBO and present that surface in a CALayer, or use CAOpenGLLayer.
Replies
8
Boosts
4
Views
22k
Activity
3w
macOS 27.2 RC (26B118) Built-in display canvas cropped with black bar at bottom-right after login
Description: MacBook Air M5, using only built-in display. The login window renders full screen normally. After logging into desktop session, the display canvas gets cropped with a black bar on the bottom-right corner. This issue is reproducible in Safe Mode and with a brand-new admin user account. No third-party display or window management software installed. Suspected WindowServer display coordinate calculation bug within user session. Environment Device: MacBook Air M5 OS: macOS 27.2 RC (26B118) Display: Built-in display only, no external monitor Reproduction steps Boot to login window, display works fine Log into desktop session Display canvas cropped, black bar appears at bottom-right
Replies
1
Boosts
0
Views
1.1k
Activity
3w
M5 Pro external display pipeline width limits and native HiDPI support
Hello Apple Engineering Team, I would like to clarify a technical question regarding the external display architecture of the M5 Pro MacBook Pro. I use a single ultrawide monitor with a native resolution of 3440 × 1440. To achieve true 2× HiDPI rendering at this logical resolution, macOS would need to render a framebuffer of 6880 × 2880. Third-party diagnostic tools and firmware reverse-engineering reports appear to indicate that M5 Pro has display-pipeline source-width limits of 6720 and 7680 pixels. Could you please clarify the following? Are these reported source-width limits accurate for the M5 Pro? Can macOS assign a single external display to the display pipeline that supports a 7680-pixel source width? Is there a supported way to influence or change this pipeline allocation, such as changing the connection port, connection order, or display configuration? Can a single 3440 × 1440 external monitor use native 2× HiDPI rendering (6880 × 2880) on the M5 Pro without virtual-display mirroring? If this configuration is unsupported, is the limitation imposed by hardware, firmware, or macOS display allocation policy? I understand that Apple may not disclose all internal implementation details. Any clarification regarding supported configurations or known limitations would be greatly appreciated. Thank you.
Replies
0
Boosts
0
Views
516
Activity
3w
Game Center Dashboard overlay doesn't have Done or x button
From this WWDC video -> https://developer.apple.com/videos/play/wwdc2020/10618/ I see the examples show that almost each screen have a "Done" button on top trailing, document sites also show the x button on top trailing, however, in my app, the overlay shows without any Done or x button, it doesn't look very apparent how to "close" this popup. I soon learned the hardware that the trick is to tap on empty areas. Is there a way to enable the Done or x button in it?
Replies
0
Boosts
0
Views
475
Activity
3w
Photogrammetry with Object masks hangs and terminates with masks of objects
[PhotogrammetrySample]) with objectMask set and traps on my ios26.5.2, see the attached screenshot on feedback FB24379913 , it gets to the function and hangs . Even the folder reconstruction with lazy sequence as recommended from your video sample also doesn;t complete as it can't find alignment and displays the CoreOC.PhotogrammetrySession.Error error 6 means alignment failed. What can be done or do you guys expose any functions that can be used to check or trace or handle these internally The ObjectMasks are actually segmentation masks from an segmentation algorithm I will appreciate a timely response and willing to provide more clarity and informations, thank you so much for your understanding
Replies
3
Boosts
0
Views
1.5k
Activity
3w
Metal CSM Shadows GPU Culling+Indirect+Vertex Amplification - empty some Shadow Cascades
Hi! I'm porting Cascaded Shadow Maps(CSM) from HLSL Direct3D12/Vulkan I'm using GPU Culling, indirect Call + Vertex Amplification for shadow Casters for creating Shadow map texture. Shadow map texture - Texture2DArray Shadow castes are rendering using Instancing and IndirectDraw, VS shader are checking [amplification_id]] and view mask CS shader are finding shadow caster using InstanceId and view mask for each shadow cascade: // dataIndex - Instance index for featching Instance Matrix // viewMask - for VS [[amplification_id]] uint PackInstanceData(uint viewMask, uint dataIndex) { return (viewMask << 28u) | dataIndex; } kernel void CullObjects(uint2 DTid [[thread_position_in_grid]], constant ArgBuf& argBuf [[buffer(0)]], uint groupIndex [[thread_index_in_threadgroup]]) { threadgroup atomic_uint sharedNumObjects; threadgroup uint sharedInstanceId[32]; threadgroup uint globalBufferIndex; constant auto& cbData = *argBuf.cbData; uint index = DTid.x; if (!groupIndex) { atomic_store_explicit(&sharedNumObjects, 0u, memory_order_relaxed); globalBufferIndex = 0u; } threadgroup_barrier(mem_flags::mem_threadgroup); bool visible = false; uint viewMask = 0; if (index < cbData.numInstanceObjects) { const device CullingObjInfo& cullingObjectInfo = argBuf.cullingObjInfo[index]; // find shadow casters for each shadow cascade for (uint i = 0u; i < NUM_FRUSTUMS; ++i) { constant Frustum& frustum = cbData.frustums[i]; visible = SphereInFrustum(frustum, cullingObjectInfo.boundingSphere); if (visible) { visible = BoundingBoxInFrustum(frustum, cullingObjectInfo.boundingBox.minPoint, cullingObjectInfo.boundingBox.maxPoint); } if (visible) { viewMask |= (1u << i); } } visible = bool(viewMask); } } if (visible) { uint bufferIndex = atomic_fetch_add_explicit(&sharedNumObjects, 1u, memory_order_relaxed); sharedInstanceId[bufferIndex] = PackInstanceData(viewMask, index); } threadgroup_barrier(mem_flags::mem_threadgroup); uint localNumObjects = atomic_load_explicit(&sharedNumObjects, memory_order_relaxed); if (!groupIndex && localNumObjects) { globalBufferIndex = atomic_fetch_add_explicit(&argBuf.numObjects->instanceCount, localNumObjects, memory_order_relaxed); } threadgroup_barrier(mem_flags::mem_threadgroup); if (groupIndex < localNumObjects) { argBuf.instanceId[globalBufferIndex + groupIndex] = sharedInstanceId[groupIndex]; } } VS shader for depth shadow map rendering: // struct PSOutput { float4 pos [[position]]; float2 Depth [[user(locn0)]]; float CullDist [[clip_distance]]; uint layer [[render_target_array_index]]; }; struct VS { float4 pos [[attribute(0)]]; uint InstanceId [[attribute(9)]]; }; struct b { float4x4 lightViewProj[NUM_SM_CASCADES]; }; struct Arg { const device float3x4* InstanceData [[id(0)]]; constant b* cb [[id(1)]]; }; uint UnpackViewInstancingMask(uint packedData) { return packedData >> 28u; } uint UnpackInstanceIndex(uint packedData) { return packedData & 0x0FFFFFFFu; } vertex PSOutput vsMain(VS In [[stage_in]], constant Arg& arg [[buffer(VSArgumentBufferIndex)]], ushort ampID [[amplification_id]]) { constant auto& b0 = *arg.cb; PSOutput output; float4 WorldPos = float4(In.pos.xyz, 1.0f); uint viewMask = UnpackViewInstancingMask(In.InstanceId); output.layer = ampID; // check shadow caster rendering for each cascade using ampID and viewMask if (viewMask & (1u << ampID)) { float3x4 instanceMatrix = arg.InstanceData[UnpackInstanceIndex(In.InstanceId)]; WorldPos = float4((WorldPos * instanceMatrix).xyz, 1.0f); output.CullDist = 1.0f; } else { output.pos = float4(0.0f, 0.0f, 2.0f, 1.0f); // skeep unvisible object for this cascade output.CullDist = -1.0f; return output; } output.pos = b0.lightViewProj[ampID] * WorldPos; output.Depth.xy = output.pos.zz; return output; } I have result left part: CPU Version - separate rendering for each layer for texture2Darray shadow map right part: GPU culling + Indirect + Vertex Amplification Got to fix error ? Why 1 and 3 cascade are empty? 0 cascade has duplicate data from other cascades.
Replies
2
Boosts
0
Views
787
Activity
3w
Processing RAW files using CIRAWFilter slows down after opening a few different images
Is there some cleanup required if you are opening multiple different RAW files - I am seeing a slow down each time I open a new file and things grind to a halt after opening 5 or 6 files, one after the other - even allowing some time between opening them. Currently I have a single view with a CAMetalLayer and a single Renderer and CIContent - should I be creating a new CAMetalLayer, render and CIContext each time a new image is opened ? Alternately is there some way to clear the cache or something to maintain performance.
Replies
1
Boosts
0
Views
502
Activity
3w
GKMatch: GameKitServices crashes in GCKSessionReceiveDOOB on the second real-time match — the finished session is never reclaimed
We ship a two-player real-time GameKit game. On iOS 27 the app crashes inside GameKitServices on the second real-time match of any app session — nine times out of nine yesterday. Filed as FB24789094 (and FB24788999 for a separate reinvitation problem). Posting the measurements here because the unified log makes the mechanism visible, and because everything I tried at the app level failed — maybe somebody has the missing piece. THE CRASH Main thread, no application frame anywhere on the stack: CFRetain + 52 GCKSessionReceiveDOOB + 1632 -[GKSessionInternal receiveDOOB:fromPeer:inSession:context:] + 320 -[GKSessionInternal(_private) tellDelegate_didReceiveBand_RetryICE:] + 212 __NSThreadPerformPerform + 264 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ EXC_BAD_ACCESS (SIGBUS), EXC_ARM_DA_ALIGN at 0x9 (0xa in one report). In every report the faulting address is exactly x0 + 8, and x0 is 1 or 2 — CFRetain is handed a small integer, not a pointer. A use-after-free would fault on a large plausible-looking address; 1 and 2 are not addresses at all. Address Sanitizer agrees: no heap error is reported before the fault, only __asan::ReportDeadlySignal directly above the same three GameKitServices frames. It reads like type confusion in the RetryICE band path. Not the SDK: a build made with Xcode 26.6 against iphoneos26.5 crashes identically — same stack, same registers. The peer's OS does not matter either (iPadOS 17.7.11, iOS 26.6.1 and iOS 27.0 all seen on the other side, and in one case an older build of our own app). Only the crashing device is always on iOS 27.0 (24A435), an iPhone 15 Pro. RECIPE Two devices, two Game Center accounts. Form a two-player real-time GKMatch — GKMatchmaker.findMatch(for:) or an invitation, both reproduce. Wait for the peer to connect, call finishMatchmaking(for:). Play for ten seconds or so, so data really flows. End it: match.disconnect(), release the GKMatch. In the SAME process, form a SECOND real-time match. Play. The crash lands roughly ten to thirty seconds after the second match starts exchanging data. A first match in a freshly launched process has never crashed for us. Out of eleven app sessions that reached a second match, two were force quit by hand during other tests and the remaining nine all crashed here. THE SESSION IS NEVER RECLAIMED GameKit runs one "com.apple.gamekitservices.gcksession.recvproc" / "sendproc" thread pair per live real-time session, in the app's own process. You can count them from inside the app, which turns out to be the only way to see what is going on: var threads: thread_act_array_t? var count: mach_msg_type_number_t = 0 task_threads(mach_task_self_, &threads, &count) // then pthread_from_mach_thread_np(threads[i]) + pthread_getname_np, and compare the name Measured across one app session: after Game Center authentication, before any match ......... 0 first match live ........................................... 1 right after match.disconnect() returns ..................... 1 <- not reclaimed before the second match is adopted ......................... 2 right after the second match's disconnect() ................ 2 Every crash report shows two of those pairs alive, although the app holds exactly one GKMatch at a time and releases the finished one the instant disconnect() returns. The same leak is visible on iOS 26.6.1 (an iPhone 11 Pro leaks identically) — it just does not crash there. WHAT THE LEFTOVER SESSION DOES Each match gets its own CDXClient. The first match's is never torn down, and keeps poking its hole on a 30-second keep-alive, on the same local port (:16402) the second match then binds: 15:28:05.117 <CDXClient: 0x155872e40> requesting-hole-punch <- match 1 15:28:35.289 <CDXClient: 0x155872e40> requesting-hole-punch <- match 1, +30s, match already over 15:28:50.197 <CDXClient: 0x12d4bda40> requesting-hole-punch <- match 2 15:29:05.287 <CDXClient: 0x155872e40> requesting-hole-punch <- match 1 again, 4s before the crash GCKSessionCreate:6425 globalscopelaunch appears once per process; the second match only does 6509 globalscoperequest and reuses the global scope. During the second match's ICE setup a packet arrives belonging to no live session: -[CDXClient handleFDEvent]:1066 packet-from-unknown-session -[CDXClient handleFDEvent]:1067 Incoming packet from unknown session. SID = ... immediately followed by [ERROR] ICEStopConnectivityCheck:2763 ICEStopConnectivityCheck() found no ICE check with call id (...) [ERROR] gckSessionCheckPendingConnections:1545 iICEChecksLeft=0, iUnconnectedNodeCount=0, iDDsExpected=1 Those lines appear exactly three times in a 28-minute window, all three in the two processes that went on to crash, never during a first match. About fourteen seconds later the RetryICE band is delivered and CFRetain is called on the garbage. WHAT DID NOT WORK Releasing the GKMatch immediately after disconnect(). The session threads stay. Waiting. Gaps of 17, 19, 22, 25, 30 and 45 seconds between the two matches all crashed. Tearing the match down cleanly. I suspected that calling disconnect() while match.players was still non-empty was the trigger — five out of five such teardowns were followed by a crash. So I made the quitting side announce its departure, wait for match(_:player:didChange:) to report the peer gone, and only then disconnect. It works (disconnect now runs with players == 0) and it changes nothing: the count still reads 1 afterwards, and the next match still crashes. Worth saying explicitly, because the correlation was strong enough to look causal. Skipping finishMatchmaking(for:). No effect. The only thing that reliably avoids it is allowing a single real-time match per app launch, which is a poor thing to ship. QUESTIONS Is there a supported way to make GameKit release a finished GKMatch's session inside the process? A GKMatch that never connected (peer wait timed out, disconnect() on an empty match) appears to leave the same residue, so it is not about how the match ended. And has anyone else seen GCKSessionReceiveDOOB / tellDelegate_didReceiveBand_RetryICE? I could not find a single mention of these symbols anywhere.
Replies
3
Boosts
2
Views
1.6k
Activity
3w
Public API for system-wide SDR luminance control on built-in XDR?
I am investigating whether a macOS display utility can adjust the luminance of normal SDR desktop content system-wide, including other apps, on the built-in Liquid Retina XDR display of a 2021 M1 Max MacBook Pro. Is there a documented public API, or combination of public APIs, for this scope? The research target is SDR white around 1000 cd/m² while retaining HDR highlight capability, where supported by the hardware and OS. This is a feasibility question, not a claim that this output has been achieved or is supported. The approach must preserve OS color management and respect thermal, power and brightness limits, including protective dimming. I am not seeking gamma-table changes, screen capture and HDR re-display, private APIs, or bypasses of system protections. I understand that enabling EDR for an app's own layer is different from controlling ordinary SDR content in other apps. I am specifically asking about the latter. If this is supported, could you point to the API names, primary documentation, applicable macOS versions and hardware limitations? If it is not supported through public APIs, an explicit clarification would also be helpful.
Replies
2
Boosts
0
Views
1.4k
Activity
4w
Clarifying Fence Behavior in Metal 4
I have some clarifying questions on how fences work in Metal 4. If two encoders A, B update the same fence and encoder C waits on that fence, is the work encoded by C guaranteed to execute after both A and B have completed, or after either A or B have completed? The following quotes in the waitForFence() documentation seem contradictory. "Encodes a command that instructs the GPU to pause before starting one or more stages of the pass until a pass updates a fence." "When encoding a pass that reuses a fence, wait for other passes to update the fence before repurposing that fence..." Are fences unsignaled when they are waited on? Specifically, can two (or more) encoders wait on a fence that is only updated in a single prior encoder? If an encoder updates a fence, no subsequent encoders in the command queue wait on the fence, and the command queue is committed, is that fence still signaled when used in a subsequent command buffer?
Replies
1
Boosts
0
Views
2.1k
Activity
Oct ’26