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

What would case a compute kernel to run 100x slower only if it's run after a previous kernel.
I have two compute kernels. The first kernel pre_initization_0 initializes some buffers using a parallel random number generator initialize some buffers. The second kernel pre_sum_weights_0 effectively sums weighted values buffer of a much smaller dimension. #include <metal_stdlib> #include <metal_simdgroup> using namespace metal; struct mt_state { array<uint32_t, 624> array; uint16_t index; }; float random(device mt_state &state) { uint16_t k = state.index; uint16_t j = (k + 1) % 624; uint32_t x = (state.array[k] & 0x80000000U) | (state.array[j] & 0x7fffffffU); uint32_t xA = x >> 1; if (x & 0x00000001U) { xA ^= 0x9908b0dfU; } j = (k + 397) % 624; x = state.array[j]^xA; state.array[k] = x; state.index = (k + 1) % 624; uint32_t y = x^(x >> 11); y = y^((y << 7) & 0x9d2c5680U); y = y^((y << 15) & 0xefc60000U); return static_cast<float> (y^(y >> 18)); } kernel void pre_initization_0( device float *vc30c09b98 [[buffer(0)]], // x used 0 device float *vc30c09c38 [[buffer(1)]], // v_{||} used 0 device float *vc30c09cd8 [[buffer(2)]], // v_{\perp} used 0 device mt_state *sc30c50c18 [[buffer(3)]], constant uint32_t &offset [[buffer(4)]], uint index [[thread_position_in_grid]]) { if (offset + index < 3000000) { device mt_state &rc30c50c18 = sc30c50c18[index]; // used 4 const float rc30c06218 = 2.17689351e-08; // used 1 const float rc30c06318 = -46.7484322; // used 1 const float rc30c0a458 = fma(rc30c06218, random(rc30c50c18), rc30c06318); // used 1 const float rc30c07718 = 5.18059896e-05; // used 1 const float rc30c06798 = -1; // used 1 const float rc30c06618 = 2.32830644e-10; // used 2 const float rc30c06718 = 1.17549435e-38; // used 2 const float rc30c0a4f8 = fma(rc30c06618, random(rc30c50c18), rc30c06718); // used 1 const float r1034f02f8 = log(rc30c0a4f8); // used 1 const float rc30c06818 = rc30c06798*r1034f02f8; // used 1 const float r1034eedf8 = sqrt(rc30c06818); // used 1 const float rc30c06418 = 1.46291812e-09; // used 1 const float rc30c06498 = rc30c06418*random(rc30c50c18); // used 1 const float r1034eee68 = sin(rc30c06498); // used 1 const float rc30c06a18 = r1034eedf8*r1034eee68; // used 1 const float rc30c07698 = rc30c07718*rc30c06a18; // used 1 const float rc30c07598 = 3.3356411e-09; // used 1 const float rc30c07318 = -241213328; // used 1 const float rc30c0a598 = fma(rc30c06618, random(rc30c50c18), rc30c06718); // used 1 const float r1034ef238 = log(rc30c0a598); // used 1 const float rc30c06c98 = rc30c07318*r1034ef238; // used 1 const float rc310b0018 = sqrt(rc30c06c98); // used 1 const float rc30c07618 = rc30c07598*rc310b0018; // used 1 vc30c09b98[offset + index] = rc30c0a458; vc30c09c38[offset + index] = rc30c07698; vc30c09cd8[offset + index] = rc30c07618; } } kernel void pre_sum_weights_0( constant float *vc30c09b98 [[buffer(0)]], // x used 7 device atomic_float *vc30c0a098 [[buffer(1)]], const texture1d<float, access::read> ac310a9000 [[texture(0)]], const texture1d<float, access::read> ac310d8000 [[texture(1)]], const texture1d<float, access::read> ac310d9000 [[texture(2)]], const texture1d<float, access::read> ac310da000 [[texture(3)]], uint index [[thread_position_in_grid]]) { if (index < 3000000) { const float rc30c09b98 = vc30c09b98[index]; // x used 7 const float rc30c07798 = 0.0935904533; // used 2 const float rc30d08318 = rc30c09b98 - rc30c07798; // used 1 const ushort ic30d08398 = (ushort)min(max((rc30d08318 - -46.7484322)/0.0935904533,(float)0),(float)999); // used 1 const float rc30c07c98 = -5.34242535; // used 1 const ushort ic30d08018 = (ushort)min(max((rc30c09b98 - -46.7484322)/0.0935904533,(float)0),(float)999); // used 5 const float rc30c51018 = ac310da000.read(ic30d08018).r; // used 1 const float rc30c0a6d8 = fma(rc30c07c98, rc30c09b98, rc30c51018); // used 1 const float rc30c07a18 = -10.6848507; // used 1 const float rc30c50e98 = ac310d8000.read(ic30d08018).r; // used 1 const float rc30c0a778 = fma(rc30c07a18, rc30c09b98, rc30c50e98); // used 1 const float rc30c07b98 = rc30c0a6d8*rc30c0a778; // used 1 atomic_fetch_add_explicit(&vc30c0a098[ic30d08398], rc30c07b98, memory_order_relaxed); // used 1 const float rc30c07c18 = 0.75; // used 1 const float rc30c07e18 = 114.166031; // used 1 const float rc30c50d18 = ac310a9000.read(ic30d08018).r; // used 1 const float rc30d08098 = rc30c50d18 - rc30c09b98; // used 1 const float rc30c07d98 = rc30d08098*rc30d08098; // used 1 const float rc30c07e98 = rc30c07e18*rc30c07d98; // used 1 const float rc30d08218 = rc30c07c18 - rc30c07e98; // used 1 atomic_fetch_add_explicit(&vc30c0a098[ic30d08018], rc30d08218, memory_order_relaxed); // used 1 const float rc30d08498 = rc30c07798 + rc30c09b98; // used 1 const ushort ic30d08418 = (ushort)min(max((rc30d08498 - -46.7484322)/0.0935904533,(float)0),(float)999); // used 1 const float rc30c07b18 = 0.5; // used 1 const float rc30c07918 = 1.5; // used 1 const float rc30c07818 = 10.6848507; // used 1 const float rc30c50f98 = ac310d9000.read(ic30d08018).r; // used 1 const float rc30d08298 = rc30c50f98 - rc30c09b98; // used 1 const float rc30c07a98 = rc30c07818*rc30d08298; // used 1 const float rc30d08118 = rc30c07918 - rc30c07a98; // used 1 const float rc30d34018 = rc30d08118*rc30d08118; // used 1 const float rc30d34098 = rc30c07b18*rc30d34018; // used 1 atomic_fetch_add_explicit(&vc30c0a098[ic30d08418], rc30d34098, memory_order_relaxed); // used 1 } } Running some timing experiments, If I initialize [[buffer(0)]] of the pre_sum_weights_0 kernel on the CPU, and run the kernel, it will run in 0.0489688 s measured using GPUEndTime - GPUStartTime in a completedHander for the command buffer. If I run the initialization kernel pre_initization_0 before this, the kernel execution time of pre_sum_weights_0 slows to 7.20396 s. Note I am launching these kernels from different command buffers.
1
0
745
Aug ’26
GroundingShadowComponent — working on iOS/iPadOS by anyone?
Following up on thread 733918 (visionOS grounding shadows, solved by applying GroundingShadowComponent(castsShadow: true) to every ModelEntity in a hierarchy, not just the root). I've implemented that exact fix in an ARKit + RealityKit app on iOS/iPadOS (LiDAR devices, iOS 18+) — recursively applying the component to every entity with a ModelComponent, confirmed via logging that it's actually set. Real-world grounding shadows still never appear, under every configuration tried: Object anchored via a .plane-type AnchoringComponent.Target ARView.debugOptions.showAnchorGeometry confirms real collision geometry exactly where the object rests Ruled out the debug scene-understanding overlay visually masking the shadow (disabled it, no change) Inter-object shadows (virtual-on-virtual, via DirectionalLightComponent.Shadow) work fine — lighting itself isn't broken, just shadows onto the real-world mesh The pre-iOS 18 path (ARView.environment.sceneUnderstanding.options.insert(.receivesLighting)) also no longer produces a real-floor shadow — tried DirectionalLightComponent(isRealWorldProxy: true) and intensity from 800 up to 4000, no visual change either way. Two questions: Has anyone actually confirmed GroundingShadowComponent rendering a real-world shadow on iOS/iPadOS, or is it visionOS-only in practice despite being available on the iOS 18+ SDK? visionOS's documented fix for the same "lights don't affect passthrough" limitation is the ShadowReceivingOcclusionSurface Shader Graph node — is there an iOS/iPadOS equivalent, or is that visionOS-exclusive? Trying to determine if this is an unreported regression worth filing, or if there's an undocumented step I'm missing.
0
0
472
Aug ’26
Pinch gesture not recognized on MTKView when attaching it to a RealityView using a ViewAttachmentComponent in a immersive space
Hello! We are seeing a problem with a SwiftUI view that wraps an MTKView and that MTKView uses gesture recognizers from UIKit. One of those gestures we are using is UIPinchGestureRecognizer. And that gesture isn’t recognized at all when the SwiftUI view is attached to a RealityView using the ViewAttachmentComponent AND the RealityView is being shown in an ImmersiveSpace. If the SwiftUI view is attached to the RealityView using the init that has an attachment closure then pinching works fine there. So this definitely seems like a bug. Here is some code to help you reproduce the problem. Run this on a Vision Pro device. A simple red square will be rendered and if a single tap or pinch gesture is recognized on the red square, it will print to the console. App Code: import SwiftUI @main struct VisionPinchProblemsApp: App { var body: some Scene { WindowGroup { MenuView() } ImmersiveSpace(id: "RedSquare") { RedSquareView() } } } View code: import MetalKit import RealityKit import SwiftUI import UIKit struct MenuView: View { @Environment(\.openImmersiveSpace) private var openImmersiveSpace @Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace @State private var showImmersiveSpace = false @State private var immersiveSpaceIsOpen = false var body: some View { Form { Toggle("Show red square", isOn: $showImmersiveSpace) .task(id: showImmersiveSpace) { if showImmersiveSpace { await openImmersiveSpace(id: "RedSquare") immersiveSpaceIsOpen = true } else { if immersiveSpaceIsOpen { await dismissImmersiveSpace() immersiveSpaceIsOpen = false } } } } .onDisappear { // Attempt to close the immersive space on the way out. Task { if immersiveSpaceIsOpen { await dismissImmersiveSpace() } } } } } struct RedSquareView: View { let metalViewAttachmentID = "metalID" var body: some View { // Adds SwiftUI view using attachments closure. // Pinching and single taps are recognized here! // RealityView { content, attachments in // if let metalViewEntity = attachments.entity(for: metalViewAttachmentID) { // metalViewEntity.position = [0, 1, -1.25] // content.add(metalViewEntity) // } // } placeholder: { // ProgressView() // } attachments: { // Attachment(id: metalViewAttachmentID) { // MetalView() // } // } // Add SwiftUI view using ViewAttachmentComponent. // Pinching is not recognized here! // Single tapping is recognized ! // Why doesn't the red square show up in the Vision Pro simulator? RealityView { content in let metalViewEntity = Entity() let metalView = MetalView() .frame(width: 500, height: 500) let component = ViewAttachmentComponent(rootView: metalView) metalViewEntity.components.set(component) metalViewEntity.position = [0, 1, -1.25] content.add(metalViewEntity) } placeholder: { ProgressView() } } } struct MetalView: UIViewRepresentable { var device: MTLDevice? init() { self.device = MTLCreateSystemDefaultDevice() } func makeUIView(context: Context) -> MTKView { let mtkView = MTKView() mtkView.device = device mtkView.clearColor = MTLClearColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) mtkView.delegate = context.coordinator let pinchGesture = UIPinchGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handlePinch(_:))) mtkView.addGestureRecognizer(pinchGesture) let tapGesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handleTap(_:))) mtkView.addGestureRecognizer(tapGesture) return mtkView } func updateUIView(_ uiView: MTKView, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, MTKViewDelegate { var parent: MetalView init(_ parent: MetalView) { self.parent = parent } func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { } func draw(in view: MTKView) { guard let drawable = view.currentDrawable else { return } guard let descriptor = view.currentRenderPassDescriptor else { return } let commandQueue = parent.device?.makeCommandQueue() let commandBuffer = commandQueue?.makeCommandBuffer() let renderEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: descriptor) renderEncoder?.endEncoding() commandBuffer?.present(drawable) commandBuffer?.commit() } @objc func handlePinch(_ sender: UIPinchGestureRecognizer) { print("Pinch detected") } @objc func handleTap(_ sender: UITapGestureRecognizer) { print("Tap detected") } } }
1
0
854
Aug ’26
ManipulationComponent causes makeUIView(context:) to get called twice
Here I have some demo code that is rendering a cylinder "platter" using RealityKit and there is a red circle rendered on top of it which uses Metal and SwiftUI. When the platter appears you will see in the console that makeUIView(context:) is called twice while it is documented that it will only be called once when the view appears for the first time. So this seems like a bug. If you remove ManipulationComponent from the platter's components you will see that this problem goes away so it seems like that is the cause of the problem. Any insight here would be appreciated! Thank you. Here is what is printed in the console: Entity returned from EntityWrapper.makeEntity(context:) was already parented to another entity. This is not supported and may lead to unexpected behavior. SwiftUI adds entities to internally-managed entity hierarchies. Make UI View! This should be called once. Make UI View! This should be called once. Here is the app code: import SwiftUI @main struct SomeApp: App { var body: some Scene { WindowGroup { ContentView() } ImmersiveSpace(id: "TableTop") { TableTopPlatterView() } } } Here is the view code: import MetalKit import RealityKit import SwiftUI struct ContentView: View { @Environment(\.openImmersiveSpace) private var openImmersiveSpace @Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace @State private var showImmersiveSpace = false @State private var immersiveSpaceIsOpen = false var body: some View { Form { Toggle("Show table top", isOn: $showImmersiveSpace) .task(id: showImmersiveSpace) { if showImmersiveSpace { await openImmersiveSpace(id: "TableTop") immersiveSpaceIsOpen = true } else { if immersiveSpaceIsOpen { await dismissImmersiveSpace() immersiveSpaceIsOpen = false } } } } .onDisappear { // Attempt to close the immersive space on the way out. Task { if immersiveSpaceIsOpen { await dismissImmersiveSpace() } } } } } struct TableTopPlatterView: View { private var attachmentID: String { "RedCircle" } var body: some View { RealityView { content, attachments in if let redCircleEntity = attachments.entity(for: attachmentID) { // Lays the red circle in the platter. let rotation = Rotation3D(redCircleEntity.orientation) .rotated(by: .init(angle: .degrees(-90), axis: .x)) redCircleEntity.setOrientation(.init(rotation), relativeTo: nil) redCircleEntity.position.y = 0.026 platterEntity.addChild(redCircleEntity) content.add(platterEntity) } } placeholder: { ProgressView() } attachments: { Attachment(id: attachmentID) { MetalView() .clipShape(.circle) } } } /// The platter entity that the red circle lays on top of. private let platterEntity: ModelEntity = { let anchor = AnchorEntity( .plane( .horizontal, classification: .table, minimumBounds: [0.01, 0.01] ) ) let material = SimpleMaterial( color: .lightGray, roughness: 0.5, isMetallic: false ) let platter = ModelEntity( mesh: .generateCylinder(height: 0.05, radius: 0.475), materials: [material] ) platter.generateCollisionShapes(recursive: false) let components: [any Component] = [ InputTargetComponent(), GroundingShadowComponent(castsShadow: true), ManipulationComponent() // MARK: This is causing makeUIView to get called twice! ] platter.components.set(components) // Placed closer to the user when booted up. platter.position = [0, 1, -1.25] anchor.addChild(platter) return platter }() } // Metal view that renders a red square. struct MetalView: UIViewRepresentable { var device: MTLDevice? init() { self.device = MTLCreateSystemDefaultDevice() } func makeUIView(context: Context) -> MTKView { print("Make UI View! This should be called once.") let mtkView = MTKView() mtkView.device = device mtkView.clearColor = MTLClearColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) mtkView.delegate = context.coordinator return mtkView } func updateUIView(_ uiView: MTKView, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, MTKViewDelegate { var metalView: MetalView init(_ metalView: MetalView) { self.metalView = metalView } func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { } func draw(in view: MTKView) { guard let drawable = view.currentDrawable else { return } guard let descriptor = view.currentRenderPassDescriptor else { return } let commandQueue = metalView.device?.makeCommandQueue() let commandBuffer = commandQueue?.makeCommandBuffer() let renderEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: descriptor) renderEncoder?.endEncoding() commandBuffer?.present(drawable) commandBuffer?.commit() } } }
3
0
1.7k
Aug ’26
TextComponent Renders Inverted Text on Mac Catalyst
On Mac Catalyst, RealityKit TextComponent renders vertically inverted text. The issue occurs with both ARView and RealityView. The same text renders correctly on iOS and in a native macOS RealityView application (not Catalyst). Tested on macOS 26 and macOS 27 beta, with Xcode 26 and Xcode 27 Beta. Here is a screenshot of a text entity with a text component rendering the string "Text Component": Workaround On Mac Catalyst: Detect when the model generated by TextComponent becomes available on the text entity. Find the generated UnlitMaterial in the ModelComponent of the text entity. Disable face culling on the material. Invert the Y scale of the text entity. Here is the result: Reproduce Below is the full code that reproduces the problem, with both ARView and RealityView, as well as the workaround implementation. import SwiftUI import RealityKit import Combine // MARK: Text func createTextEntity() -> Entity { let textEntity = Entity() let attributes: [NSAttributedString.Key: Any] = [ .font: MeshResource.Font.systemFont(ofSize: 48, weight: .bold), .foregroundColor: Material.Color.white ] let attributedText = AttributedString( NSAttributedString( string: "Text Component", attributes: attributes ) ) var textComponent = TextComponent() textComponent.text = attributedText textComponent.size = CGSize(width: 400, height: 200) textComponent.backgroundColor = Material.Color.darkGray.cgColor textEntity.components.set(textComponent) return textEntity } // MARK: Camera func createCameraEntity() -> Entity { let cameraEntity = Entity() cameraEntity.components.set(PerspectiveCameraComponent()) cameraEntity.look(at: .zero, from: [0, 0, 0.3], relativeTo: nil) return cameraEntity } // MARK: ARView struct CatalystTextBugARView: UIViewRepresentable { let applyWorkaround: Bool = true func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) arView.cameraMode = .nonAR arView.automaticallyConfigureSession = false arView.environment.background = .color(.black) let rootEntity = AnchorEntity() let textEntity = createTextEntity() #if targetEnvironment(macCatalyst) if applyWorkaround { /// React when the text entity's ModelComponent becomes available or changes context.coordinator.modelDidAddSubscription = arView.scene.subscribe( to: ComponentEvents.DidAdd.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } context.coordinator.modelDidChangeSubscription = arView.scene.subscribe( to: ComponentEvents.DidChange.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } } #endif rootEntity.addChild(textEntity) rootEntity.addChild(createCameraEntity()) arView.scene.addAnchor(rootEntity) return arView } func updateUIView(_ uiView: ARView, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator { /// Retain the scene subscriptions for the lifetime of the ARView. var modelDidAddSubscription: (any Cancellable)? var modelDidChangeSubscription: (any Cancellable)? } } // MARK: RealityView struct CatalystTextBugRealityView: View { let applyWorkaround: Bool = true /// Retain the RealityView subscriptions for the lifetime of the view. @State private var modelDidAddSubscription: EventSubscription? @State private var modelDidChangeSubscription: EventSubscription? var body: some View { RealityView { content in let textEntity = createTextEntity() #if targetEnvironment(macCatalyst) if applyWorkaround { /// React when the text entity's ModelComponent becomes available or changes. modelDidAddSubscription = content.subscribe( to: ComponentEvents.DidAdd.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } modelDidChangeSubscription = content.subscribe( to: ComponentEvents.DidChange.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } } #endif content.add(textEntity) content.add(createCameraEntity()) } .background(.black) } } // MARK: Workaround func applyTextBugWorkaround(to textEntity: Entity) { #if targetEnvironment(macCatalyst) guard var modelComponent = textEntity.components[ModelComponent.self] else { return } var foundTextMaterial = false var changedMaterial = false for materialIndex in modelComponent.materials.indices { guard var textMaterial = modelComponent.materials[materialIndex] as? UnlitMaterial else { continue } foundTextMaterial = true /// If face culling is already disabled, skip if case .none = textMaterial.faceCulling { continue } textMaterial.faceCulling = .none modelComponent.materials[materialIndex] = textMaterial changedMaterial = true } guard foundTextMaterial else { return } if changedMaterial { textEntity.components.set(modelComponent) } /// Counteract vertically inverted text. textEntity.scale.y = -abs(textEntity.scale.y) #endif } Usage Run either CatalystTextBugRealityView() or CatalystTextBugARView() on a Mac Catalyst target. Toggle applyWorkaround on either view to try with and without the workaround.
1
0
724
Aug ’26
Using CARenderer for off-screen rendering of WKWebView results in a blank screen for the web page content on iOS 16 system version.
Using the CRenderer off-screen rendering method for WKWebView results in a blank screen for the web page content on the iOS 16 system version, but it can successfully obtain the web page content screen on the iOS 18 system version. I need a solution to achieve the display of web page content on the 16 system version, with a frame rate of more than 60 frames per second.
1
0
1.3k
Jul ’26
Draw WKWebView into OpenGL Texture
I'm trying to figure out how to display a Web Browser inside my iOS VR app (Obj-c, SceneKit and raw OpenGL), and the part i'm not fully understanding is how to get the WKWebView to draw it's content into a Pixel Buffer of some sort, so I can use the speed of CVOpenGLESTextureCacheCreateTextureFromImage to convert the pixel data into a OpenGl Texture quickly/efficently and display it on a floating surface.I'm already doing something simular with the video portion of my app, but it has a AVPlayerItemVideoOutput, which produced the pixel buffer, but I can't figure out how to massage the CALayer into a Buffer so I can convert it into a texture to then draw in opengl.I know it has something to do with drawLayer:(Layer) ,(Context), but searching online hasn't been very fruitful.And i'm not using SceneKit like you would assume, the app was built before GVR for Scenekit was a thing, so every part of VR is handled manually (scenekit to textures, textures to opengl for Left/Right eye distortion mesh).
3
0
2.8k
Jul ’26
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
2
4
2.4k
Jul ’26
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
924
Jul ’26
WatchBlocks v1.5 is now available: a sandbox game built for Apple Watch
Hi everyone! After about 4-5 months of development, I released WatchBlocks v1.5 today. The project started as an experiment to answer a simple question: Could you build a real sandbox survival game that runs well on Apple Watch? It eventually grew into a cross-platform game supporting Apple Watch, iPhone, iPad, and Mac. Some of the technical challenges I enjoyed solving included: Optimizing rendering and gameplay for watchOS. Designing controls around the Digital Crown and the watch display. Building multiplayer across Apple platforms. Creating a content system that lets players make and share their own blocks, items, mobs, and biomes. The new update also transitions the game to a free-to-start model, making it easier for people to try it before deciding whether to unlock the full experience. I’d love to hear from other developers building for watchOS. It’s a platform that doesn’t get much attention for games, but I think there’s a lot of untapped potential. If anyone has questions about developing games for Apple Watch, I’m happy to answer them. App Store: https://apps.apple.com/us/app/watchblocks-craft-build/id6760209351
0
0
934
Jul ’26
Refresh Rate Drops from 144Hz to 98Hz After Monitor Power Cycle on macOS Golden Gate 27
Hello, I use a Gigabyte M32U monitor with my Mac mini. After updating to macOS Golden Gate 27 Release 3, I started experiencing an issue with my external display. Whenever I turn my monitor off and then turn it back on, the refresh rate automatically changes from 144Hz to 98Hz, and the 144Hz option disappears from the display settings. However, if I unplug the display cable and plug it back in, the monitor is detected again and the 144Hz option returns, allowing me to select it normally. This issue only started after updating to macOS Golden Gate 27 Release 3. Before the update, the monitor consistently worked at 144Hz without any problems. Could you please investigate this issue? Thank you.
1
0
918
Jul ’26
Import models into my game
Hello, Im watching this tutorial: https://www.youtube.com/watch?v=tNkvu-YUVro&t=241s I have a reality composer project saved But she does not explain step by step what directory to import, how exactly to import it, and where exactly to import it to I tried to drag and drop every folder level into xcode and also into finder, 1 by 1, nothing works. it does not recognize my contentBundle in code. if someone from apple can upload 2 screenshots sowing the proper way to do this in 2026 it will be awesome Thanks guys :)
2
0
622
Jul ’26
How can I determine which side of a RoomPlan wall surface contains the wall thickness?
I am using Apple RoomPlan and working with CapturedRoom.Surface objects representing walls. From RoomPlan, I can get information such as: transform dimensions polygonCorners completedEdges However, I am not sure how the returned wall surface should be interpreted geometrically. Is the wall surface returned by RoomPlan: the centerline of the physical wall; the interior face of the wall; the exterior face of the wall; or simply an estimated 2D surface without any guarantee about wall thickness? If I want to create a wall with thickness, for example when converting RoomPlan data to IFC or another BIM format, how can I determine which side of the returned surface the wall should be extruded toward? Does RoomPlan provide any information such as: wall thickness; interior or exterior wall side; inward or outward normal; wall centerline; a full 3D wall boundary; or the opposite face of the wall? I can calculate the surface normal from the third column of the wall transform and obtain the wall-face boundary using polygonCorners, but I do not know whether the positive normal points toward the room interior or exterior. Is there an official or recommended way to determine the correct wall side, or must applications infer it from the room geometry and apply an assumed wall thickness? Any clarification about the coordinate convention and intended geometric meaning of a RoomPlan wall surface would be appreciated.
1
0
545
Jul ’26
iPad Pro M4 (11-inch) – Persistent Gaming Performance Issues Across Multiple iPadOS Versions
Hello everyone, I am posting this to determine whether other iPad Pro M4 users are experiencing the same issue. Device: iPad Pro 11-inch (M4) Original Apple charger Tested on multiple iPadOS versions, stebal and beta including 26.2, 26.3, 26.4, 26.5.2 Games Tested: BGMI PUBG Mobile Global Call of Duty: Mobile Fortnite Issue: Despite using one of Apple's most powerful tablets, I continue to experience gaming performance problems. The issues include: FPS drops during long gaming sessions. Frame pacing inconsistencies. Reduced responsiveness during intense fights. Inconsistent hit registration and spray accuracy after extended play. Performance sometimes changes when gaming while charging with the original Apple charger. I have tested multiple iPadOS versions and multiple game updates over several months, but the issue has never been completely resolved. Interestingly, iPadOS feels more consistent for me than some previous versions, but the overall gaming experience is still not what I would expect from the M4 hardware. I have also noticed that many other iPad Pro M4 users have reported similar concerns on Reddit, Apple Communities, and other gaming forums. Questions: Are other iPad Pro M4 users experiencing the same FPS drops and gameplay inconsistencies? Has anyone found a reliable solution? Is Apple aware of these gaming performance issues on the M4 iPad Pro? Is this an iPadOS optimization issue, a GPU scheduling issue, or something related to game optimization? I hope Apple and game developers investigate this further because the M4 hardware should be capable of delivering a consistently excellent gaming experience. Thank you.
0
0
810
Jul ’26
M5 Pro WindowServer/Display Engine: Window animations and UI scrolling capped at ~60Hz on external 5K 165Hz display while hardware cursor remains smooth
On the new M5 Pro platform running macOS, UI animations (window dragging, Safari/Chrome scrolling, Mission Control) on an external 5K 165Hz display appear to render at a much lower frame rate (~60Hz) or exhibit severe micro-stuttering. However, the mouse cursor and desktop wallpaper dragging remain perfectly fluid at 165Hz, indicating a potential issue in the WindowServer compositor or display pipeline rather than the physical link. Environment • Hardware: MacBook Pro (M5 Pro) • OS: macOS 27.0 beta 3 (26A5378j) • External Display: 5K 165Hz monitor connected via DisplayPort (DSC confirmed via IORegistry). System Settings correctly detects and selects 165Hz. Expected Behavior All UI elements, including window movement, application scrolling, and system animations, should render smoothly at the native 165Hz refresh rate matching the hardware capabilities. Actual Behavior The display output appears split between two different refresh rates: 1. Full 165Hz: The hardware mouse cursor and desktop dragging (empty area selection) are perfectly smooth. 2. ~60Hz / Jitter: Application windows (Finder, Safari, Chrome) stutter heavily when dragged or scrolled. Mission Control animations suffer from micro-stutters. Note: This specific combination suggests the Hardware Cursor layer is running at full rate, but the WindowServer compositor layer is throttled or dropping frames. Troubleshooting Performed (No Change) • Verified with multiple certified DisplayPort cables. • Tested across various resolutions (Scaled/HiDPI modes) and toggling DSC. • Regression Check: This issue did not occur on a 4K 144Hz HDR monitor previously, and initial community feedback shows other M5 Pro users experiencing this specific 165Hz window-dragging jitter, while M4 Pro / base M5 users on the same macOS beta do not seem impacted. Questions & Diagnostics 1. Is this a known regression related to the new M5 Pro display engine / Display Coprocessor (DCP) pipeline handling 5K high-refresh-rate timings? 2. Are there specific defaults write commands, Quartz Debug profiles, or custom logging arguments (WindowServer, DCP, or Metal) we can enable to capture frame presentation metrics? I have captured a sysdiagnose, IORegistry dump, and high-frame-rate screen recordings, and am ready to attach them as soon as this feedback is processed. Case / Feedback Reference Feedback ID: FB23616959 (Captured after the system format)
0
0
422
Jul ’26
Archived achievements
Hi! With my next update i want to archive 6 of my 18 achievements, and add 7 new ones. I've archived the 6, and added the 7 new ones, but i can distritibute any points due to the archived 6 still holding the active point amount. It's been about 12 hours since i archived them, so do i just wait another 12 hours or is there a better way ?
4
0
705
Jul ’26
HidHide on MacOS
I was wondering if there's a method on MacOS to have my application hide a hid device such as a game controller and instead have the receiving game/application see my app's virtual controller? Is this possible via DriverKit or some other form of kernel level coding? On Windows we have a tool known as HidHide that hids a game controller from all other applications. Is it possible to implement such behavior into an app or is that system level?
7
0
3.7k
Jul ’26
SKView showsFields draws only on a portion of the screen
The SKView.showsFields = true only draws on a portion of the screen - nothing shows on the bottom-left. This can be easily tested using Apple's default game playground. I only removed the action for the Hello World label and added a radialGravityField into the scene. Also other fields like electricField do not draw anything on the screen. Tested in Xcode 11.7 and Xcode 12.5.1. Is this a bug in the recent releases? override func didMove(to view: SKView) { // ... let field = SKFieldNode.radialGravityField() addChild(field) } and sceneView.showsFields = true
5
1
2.0k
Jul ’26
How do I work with the BlendMask node in the animation graph in RCP3?
In RCP3, is it possible to mask out joints in a pose at runtime? I want to have two poses running for my character, one for the upper body and one for the lower body and I was hoping to do that from the animation graph. It seems like I should be able to have two State Machine nodes running, and use the Blend Mask node to make sure only joints from the upper body animation comes through from the upper body state machine, and the same for the lower body. The description of the Blend Mask node say "Filter a pose by applying per-joint weights from a blend mask" so that seems like what I want. But I can't figure out how to author a blend mask resources in RCP3. It seems to be possible to do programmatically via the SkeletonResource.BlendMask struct but how do I do it in RCP3? Also, the Blend Mask node takes two poses as parameters, whereas I was expecting it to take a pose and a blend mask.
0
0
371
Jul ’26
Xcode 26 – "Manage Game Progress" not showing achievements/leaderboards on macOS
Hello, When testing GameKit "Manage Game Progress" in Xcode 26: On iOS devices, achievements, leaderboards, and party code data display and work correctly. On macOS devices, none of these data appear in "Manage Game Progress." Is this a known issue with macOS GameKit, or is there a limitation compared to iOS? If it is not a bug, is there any additional configuration needed to make achievements and leaderboards visible on macOS? I also included the GameKit bundle in my macOS app and enabled Enable Debug Mode in GameKit Configuration in the scheme options. Thank you.
4
1
1.5k
Jul ’26
What would case a compute kernel to run 100x slower only if it's run after a previous kernel.
I have two compute kernels. The first kernel pre_initization_0 initializes some buffers using a parallel random number generator initialize some buffers. The second kernel pre_sum_weights_0 effectively sums weighted values buffer of a much smaller dimension. #include <metal_stdlib> #include <metal_simdgroup> using namespace metal; struct mt_state { array<uint32_t, 624> array; uint16_t index; }; float random(device mt_state &state) { uint16_t k = state.index; uint16_t j = (k + 1) % 624; uint32_t x = (state.array[k] & 0x80000000U) | (state.array[j] & 0x7fffffffU); uint32_t xA = x >> 1; if (x & 0x00000001U) { xA ^= 0x9908b0dfU; } j = (k + 397) % 624; x = state.array[j]^xA; state.array[k] = x; state.index = (k + 1) % 624; uint32_t y = x^(x >> 11); y = y^((y << 7) & 0x9d2c5680U); y = y^((y << 15) & 0xefc60000U); return static_cast<float> (y^(y >> 18)); } kernel void pre_initization_0( device float *vc30c09b98 [[buffer(0)]], // x used 0 device float *vc30c09c38 [[buffer(1)]], // v_{||} used 0 device float *vc30c09cd8 [[buffer(2)]], // v_{\perp} used 0 device mt_state *sc30c50c18 [[buffer(3)]], constant uint32_t &offset [[buffer(4)]], uint index [[thread_position_in_grid]]) { if (offset + index < 3000000) { device mt_state &rc30c50c18 = sc30c50c18[index]; // used 4 const float rc30c06218 = 2.17689351e-08; // used 1 const float rc30c06318 = -46.7484322; // used 1 const float rc30c0a458 = fma(rc30c06218, random(rc30c50c18), rc30c06318); // used 1 const float rc30c07718 = 5.18059896e-05; // used 1 const float rc30c06798 = -1; // used 1 const float rc30c06618 = 2.32830644e-10; // used 2 const float rc30c06718 = 1.17549435e-38; // used 2 const float rc30c0a4f8 = fma(rc30c06618, random(rc30c50c18), rc30c06718); // used 1 const float r1034f02f8 = log(rc30c0a4f8); // used 1 const float rc30c06818 = rc30c06798*r1034f02f8; // used 1 const float r1034eedf8 = sqrt(rc30c06818); // used 1 const float rc30c06418 = 1.46291812e-09; // used 1 const float rc30c06498 = rc30c06418*random(rc30c50c18); // used 1 const float r1034eee68 = sin(rc30c06498); // used 1 const float rc30c06a18 = r1034eedf8*r1034eee68; // used 1 const float rc30c07698 = rc30c07718*rc30c06a18; // used 1 const float rc30c07598 = 3.3356411e-09; // used 1 const float rc30c07318 = -241213328; // used 1 const float rc30c0a598 = fma(rc30c06618, random(rc30c50c18), rc30c06718); // used 1 const float r1034ef238 = log(rc30c0a598); // used 1 const float rc30c06c98 = rc30c07318*r1034ef238; // used 1 const float rc310b0018 = sqrt(rc30c06c98); // used 1 const float rc30c07618 = rc30c07598*rc310b0018; // used 1 vc30c09b98[offset + index] = rc30c0a458; vc30c09c38[offset + index] = rc30c07698; vc30c09cd8[offset + index] = rc30c07618; } } kernel void pre_sum_weights_0( constant float *vc30c09b98 [[buffer(0)]], // x used 7 device atomic_float *vc30c0a098 [[buffer(1)]], const texture1d<float, access::read> ac310a9000 [[texture(0)]], const texture1d<float, access::read> ac310d8000 [[texture(1)]], const texture1d<float, access::read> ac310d9000 [[texture(2)]], const texture1d<float, access::read> ac310da000 [[texture(3)]], uint index [[thread_position_in_grid]]) { if (index < 3000000) { const float rc30c09b98 = vc30c09b98[index]; // x used 7 const float rc30c07798 = 0.0935904533; // used 2 const float rc30d08318 = rc30c09b98 - rc30c07798; // used 1 const ushort ic30d08398 = (ushort)min(max((rc30d08318 - -46.7484322)/0.0935904533,(float)0),(float)999); // used 1 const float rc30c07c98 = -5.34242535; // used 1 const ushort ic30d08018 = (ushort)min(max((rc30c09b98 - -46.7484322)/0.0935904533,(float)0),(float)999); // used 5 const float rc30c51018 = ac310da000.read(ic30d08018).r; // used 1 const float rc30c0a6d8 = fma(rc30c07c98, rc30c09b98, rc30c51018); // used 1 const float rc30c07a18 = -10.6848507; // used 1 const float rc30c50e98 = ac310d8000.read(ic30d08018).r; // used 1 const float rc30c0a778 = fma(rc30c07a18, rc30c09b98, rc30c50e98); // used 1 const float rc30c07b98 = rc30c0a6d8*rc30c0a778; // used 1 atomic_fetch_add_explicit(&vc30c0a098[ic30d08398], rc30c07b98, memory_order_relaxed); // used 1 const float rc30c07c18 = 0.75; // used 1 const float rc30c07e18 = 114.166031; // used 1 const float rc30c50d18 = ac310a9000.read(ic30d08018).r; // used 1 const float rc30d08098 = rc30c50d18 - rc30c09b98; // used 1 const float rc30c07d98 = rc30d08098*rc30d08098; // used 1 const float rc30c07e98 = rc30c07e18*rc30c07d98; // used 1 const float rc30d08218 = rc30c07c18 - rc30c07e98; // used 1 atomic_fetch_add_explicit(&vc30c0a098[ic30d08018], rc30d08218, memory_order_relaxed); // used 1 const float rc30d08498 = rc30c07798 + rc30c09b98; // used 1 const ushort ic30d08418 = (ushort)min(max((rc30d08498 - -46.7484322)/0.0935904533,(float)0),(float)999); // used 1 const float rc30c07b18 = 0.5; // used 1 const float rc30c07918 = 1.5; // used 1 const float rc30c07818 = 10.6848507; // used 1 const float rc30c50f98 = ac310d9000.read(ic30d08018).r; // used 1 const float rc30d08298 = rc30c50f98 - rc30c09b98; // used 1 const float rc30c07a98 = rc30c07818*rc30d08298; // used 1 const float rc30d08118 = rc30c07918 - rc30c07a98; // used 1 const float rc30d34018 = rc30d08118*rc30d08118; // used 1 const float rc30d34098 = rc30c07b18*rc30d34018; // used 1 atomic_fetch_add_explicit(&vc30c0a098[ic30d08418], rc30d34098, memory_order_relaxed); // used 1 } } Running some timing experiments, If I initialize [[buffer(0)]] of the pre_sum_weights_0 kernel on the CPU, and run the kernel, it will run in 0.0489688 s measured using GPUEndTime - GPUStartTime in a completedHander for the command buffer. If I run the initialization kernel pre_initization_0 before this, the kernel execution time of pre_sum_weights_0 slows to 7.20396 s. Note I am launching these kernels from different command buffers.
Replies
1
Boosts
0
Views
745
Activity
Aug ’26
GroundingShadowComponent — working on iOS/iPadOS by anyone?
Following up on thread 733918 (visionOS grounding shadows, solved by applying GroundingShadowComponent(castsShadow: true) to every ModelEntity in a hierarchy, not just the root). I've implemented that exact fix in an ARKit + RealityKit app on iOS/iPadOS (LiDAR devices, iOS 18+) — recursively applying the component to every entity with a ModelComponent, confirmed via logging that it's actually set. Real-world grounding shadows still never appear, under every configuration tried: Object anchored via a .plane-type AnchoringComponent.Target ARView.debugOptions.showAnchorGeometry confirms real collision geometry exactly where the object rests Ruled out the debug scene-understanding overlay visually masking the shadow (disabled it, no change) Inter-object shadows (virtual-on-virtual, via DirectionalLightComponent.Shadow) work fine — lighting itself isn't broken, just shadows onto the real-world mesh The pre-iOS 18 path (ARView.environment.sceneUnderstanding.options.insert(.receivesLighting)) also no longer produces a real-floor shadow — tried DirectionalLightComponent(isRealWorldProxy: true) and intensity from 800 up to 4000, no visual change either way. Two questions: Has anyone actually confirmed GroundingShadowComponent rendering a real-world shadow on iOS/iPadOS, or is it visionOS-only in practice despite being available on the iOS 18+ SDK? visionOS's documented fix for the same "lights don't affect passthrough" limitation is the ShadowReceivingOcclusionSurface Shader Graph node — is there an iOS/iPadOS equivalent, or is that visionOS-exclusive? Trying to determine if this is an unreported regression worth filing, or if there's an undocumented step I'm missing.
Replies
0
Boosts
0
Views
472
Activity
Aug ’26
Pinch gesture not recognized on MTKView when attaching it to a RealityView using a ViewAttachmentComponent in a immersive space
Hello! We are seeing a problem with a SwiftUI view that wraps an MTKView and that MTKView uses gesture recognizers from UIKit. One of those gestures we are using is UIPinchGestureRecognizer. And that gesture isn’t recognized at all when the SwiftUI view is attached to a RealityView using the ViewAttachmentComponent AND the RealityView is being shown in an ImmersiveSpace. If the SwiftUI view is attached to the RealityView using the init that has an attachment closure then pinching works fine there. So this definitely seems like a bug. Here is some code to help you reproduce the problem. Run this on a Vision Pro device. A simple red square will be rendered and if a single tap or pinch gesture is recognized on the red square, it will print to the console. App Code: import SwiftUI @main struct VisionPinchProblemsApp: App { var body: some Scene { WindowGroup { MenuView() } ImmersiveSpace(id: "RedSquare") { RedSquareView() } } } View code: import MetalKit import RealityKit import SwiftUI import UIKit struct MenuView: View { @Environment(\.openImmersiveSpace) private var openImmersiveSpace @Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace @State private var showImmersiveSpace = false @State private var immersiveSpaceIsOpen = false var body: some View { Form { Toggle("Show red square", isOn: $showImmersiveSpace) .task(id: showImmersiveSpace) { if showImmersiveSpace { await openImmersiveSpace(id: "RedSquare") immersiveSpaceIsOpen = true } else { if immersiveSpaceIsOpen { await dismissImmersiveSpace() immersiveSpaceIsOpen = false } } } } .onDisappear { // Attempt to close the immersive space on the way out. Task { if immersiveSpaceIsOpen { await dismissImmersiveSpace() } } } } } struct RedSquareView: View { let metalViewAttachmentID = "metalID" var body: some View { // Adds SwiftUI view using attachments closure. // Pinching and single taps are recognized here! // RealityView { content, attachments in // if let metalViewEntity = attachments.entity(for: metalViewAttachmentID) { // metalViewEntity.position = [0, 1, -1.25] // content.add(metalViewEntity) // } // } placeholder: { // ProgressView() // } attachments: { // Attachment(id: metalViewAttachmentID) { // MetalView() // } // } // Add SwiftUI view using ViewAttachmentComponent. // Pinching is not recognized here! // Single tapping is recognized ! // Why doesn't the red square show up in the Vision Pro simulator? RealityView { content in let metalViewEntity = Entity() let metalView = MetalView() .frame(width: 500, height: 500) let component = ViewAttachmentComponent(rootView: metalView) metalViewEntity.components.set(component) metalViewEntity.position = [0, 1, -1.25] content.add(metalViewEntity) } placeholder: { ProgressView() } } } struct MetalView: UIViewRepresentable { var device: MTLDevice? init() { self.device = MTLCreateSystemDefaultDevice() } func makeUIView(context: Context) -> MTKView { let mtkView = MTKView() mtkView.device = device mtkView.clearColor = MTLClearColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) mtkView.delegate = context.coordinator let pinchGesture = UIPinchGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handlePinch(_:))) mtkView.addGestureRecognizer(pinchGesture) let tapGesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.handleTap(_:))) mtkView.addGestureRecognizer(tapGesture) return mtkView } func updateUIView(_ uiView: MTKView, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, MTKViewDelegate { var parent: MetalView init(_ parent: MetalView) { self.parent = parent } func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { } func draw(in view: MTKView) { guard let drawable = view.currentDrawable else { return } guard let descriptor = view.currentRenderPassDescriptor else { return } let commandQueue = parent.device?.makeCommandQueue() let commandBuffer = commandQueue?.makeCommandBuffer() let renderEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: descriptor) renderEncoder?.endEncoding() commandBuffer?.present(drawable) commandBuffer?.commit() } @objc func handlePinch(_ sender: UIPinchGestureRecognizer) { print("Pinch detected") } @objc func handleTap(_ sender: UITapGestureRecognizer) { print("Tap detected") } } }
Replies
1
Boosts
0
Views
854
Activity
Aug ’26
ManipulationComponent causes makeUIView(context:) to get called twice
Here I have some demo code that is rendering a cylinder "platter" using RealityKit and there is a red circle rendered on top of it which uses Metal and SwiftUI. When the platter appears you will see in the console that makeUIView(context:) is called twice while it is documented that it will only be called once when the view appears for the first time. So this seems like a bug. If you remove ManipulationComponent from the platter's components you will see that this problem goes away so it seems like that is the cause of the problem. Any insight here would be appreciated! Thank you. Here is what is printed in the console: Entity returned from EntityWrapper.makeEntity(context:) was already parented to another entity. This is not supported and may lead to unexpected behavior. SwiftUI adds entities to internally-managed entity hierarchies. Make UI View! This should be called once. Make UI View! This should be called once. Here is the app code: import SwiftUI @main struct SomeApp: App { var body: some Scene { WindowGroup { ContentView() } ImmersiveSpace(id: "TableTop") { TableTopPlatterView() } } } Here is the view code: import MetalKit import RealityKit import SwiftUI struct ContentView: View { @Environment(\.openImmersiveSpace) private var openImmersiveSpace @Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace @State private var showImmersiveSpace = false @State private var immersiveSpaceIsOpen = false var body: some View { Form { Toggle("Show table top", isOn: $showImmersiveSpace) .task(id: showImmersiveSpace) { if showImmersiveSpace { await openImmersiveSpace(id: "TableTop") immersiveSpaceIsOpen = true } else { if immersiveSpaceIsOpen { await dismissImmersiveSpace() immersiveSpaceIsOpen = false } } } } .onDisappear { // Attempt to close the immersive space on the way out. Task { if immersiveSpaceIsOpen { await dismissImmersiveSpace() } } } } } struct TableTopPlatterView: View { private var attachmentID: String { "RedCircle" } var body: some View { RealityView { content, attachments in if let redCircleEntity = attachments.entity(for: attachmentID) { // Lays the red circle in the platter. let rotation = Rotation3D(redCircleEntity.orientation) .rotated(by: .init(angle: .degrees(-90), axis: .x)) redCircleEntity.setOrientation(.init(rotation), relativeTo: nil) redCircleEntity.position.y = 0.026 platterEntity.addChild(redCircleEntity) content.add(platterEntity) } } placeholder: { ProgressView() } attachments: { Attachment(id: attachmentID) { MetalView() .clipShape(.circle) } } } /// The platter entity that the red circle lays on top of. private let platterEntity: ModelEntity = { let anchor = AnchorEntity( .plane( .horizontal, classification: .table, minimumBounds: [0.01, 0.01] ) ) let material = SimpleMaterial( color: .lightGray, roughness: 0.5, isMetallic: false ) let platter = ModelEntity( mesh: .generateCylinder(height: 0.05, radius: 0.475), materials: [material] ) platter.generateCollisionShapes(recursive: false) let components: [any Component] = [ InputTargetComponent(), GroundingShadowComponent(castsShadow: true), ManipulationComponent() // MARK: This is causing makeUIView to get called twice! ] platter.components.set(components) // Placed closer to the user when booted up. platter.position = [0, 1, -1.25] anchor.addChild(platter) return platter }() } // Metal view that renders a red square. struct MetalView: UIViewRepresentable { var device: MTLDevice? init() { self.device = MTLCreateSystemDefaultDevice() } func makeUIView(context: Context) -> MTKView { print("Make UI View! This should be called once.") let mtkView = MTKView() mtkView.device = device mtkView.clearColor = MTLClearColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) mtkView.delegate = context.coordinator return mtkView } func updateUIView(_ uiView: MTKView, context: Context) { } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, MTKViewDelegate { var metalView: MetalView init(_ metalView: MetalView) { self.metalView = metalView } func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { } func draw(in view: MTKView) { guard let drawable = view.currentDrawable else { return } guard let descriptor = view.currentRenderPassDescriptor else { return } let commandQueue = metalView.device?.makeCommandQueue() let commandBuffer = commandQueue?.makeCommandBuffer() let renderEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: descriptor) renderEncoder?.endEncoding() commandBuffer?.present(drawable) commandBuffer?.commit() } } }
Replies
3
Boosts
0
Views
1.7k
Activity
Aug ’26
TextComponent Renders Inverted Text on Mac Catalyst
On Mac Catalyst, RealityKit TextComponent renders vertically inverted text. The issue occurs with both ARView and RealityView. The same text renders correctly on iOS and in a native macOS RealityView application (not Catalyst). Tested on macOS 26 and macOS 27 beta, with Xcode 26 and Xcode 27 Beta. Here is a screenshot of a text entity with a text component rendering the string "Text Component": Workaround On Mac Catalyst: Detect when the model generated by TextComponent becomes available on the text entity. Find the generated UnlitMaterial in the ModelComponent of the text entity. Disable face culling on the material. Invert the Y scale of the text entity. Here is the result: Reproduce Below is the full code that reproduces the problem, with both ARView and RealityView, as well as the workaround implementation. import SwiftUI import RealityKit import Combine // MARK: Text func createTextEntity() -> Entity { let textEntity = Entity() let attributes: [NSAttributedString.Key: Any] = [ .font: MeshResource.Font.systemFont(ofSize: 48, weight: .bold), .foregroundColor: Material.Color.white ] let attributedText = AttributedString( NSAttributedString( string: "Text Component", attributes: attributes ) ) var textComponent = TextComponent() textComponent.text = attributedText textComponent.size = CGSize(width: 400, height: 200) textComponent.backgroundColor = Material.Color.darkGray.cgColor textEntity.components.set(textComponent) return textEntity } // MARK: Camera func createCameraEntity() -> Entity { let cameraEntity = Entity() cameraEntity.components.set(PerspectiveCameraComponent()) cameraEntity.look(at: .zero, from: [0, 0, 0.3], relativeTo: nil) return cameraEntity } // MARK: ARView struct CatalystTextBugARView: UIViewRepresentable { let applyWorkaround: Bool = true func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) arView.cameraMode = .nonAR arView.automaticallyConfigureSession = false arView.environment.background = .color(.black) let rootEntity = AnchorEntity() let textEntity = createTextEntity() #if targetEnvironment(macCatalyst) if applyWorkaround { /// React when the text entity's ModelComponent becomes available or changes context.coordinator.modelDidAddSubscription = arView.scene.subscribe( to: ComponentEvents.DidAdd.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } context.coordinator.modelDidChangeSubscription = arView.scene.subscribe( to: ComponentEvents.DidChange.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } } #endif rootEntity.addChild(textEntity) rootEntity.addChild(createCameraEntity()) arView.scene.addAnchor(rootEntity) return arView } func updateUIView(_ uiView: ARView, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator { /// Retain the scene subscriptions for the lifetime of the ARView. var modelDidAddSubscription: (any Cancellable)? var modelDidChangeSubscription: (any Cancellable)? } } // MARK: RealityView struct CatalystTextBugRealityView: View { let applyWorkaround: Bool = true /// Retain the RealityView subscriptions for the lifetime of the view. @State private var modelDidAddSubscription: EventSubscription? @State private var modelDidChangeSubscription: EventSubscription? var body: some View { RealityView { content in let textEntity = createTextEntity() #if targetEnvironment(macCatalyst) if applyWorkaround { /// React when the text entity's ModelComponent becomes available or changes. modelDidAddSubscription = content.subscribe( to: ComponentEvents.DidAdd.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } modelDidChangeSubscription = content.subscribe( to: ComponentEvents.DidChange.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } } #endif content.add(textEntity) content.add(createCameraEntity()) } .background(.black) } } // MARK: Workaround func applyTextBugWorkaround(to textEntity: Entity) { #if targetEnvironment(macCatalyst) guard var modelComponent = textEntity.components[ModelComponent.self] else { return } var foundTextMaterial = false var changedMaterial = false for materialIndex in modelComponent.materials.indices { guard var textMaterial = modelComponent.materials[materialIndex] as? UnlitMaterial else { continue } foundTextMaterial = true /// If face culling is already disabled, skip if case .none = textMaterial.faceCulling { continue } textMaterial.faceCulling = .none modelComponent.materials[materialIndex] = textMaterial changedMaterial = true } guard foundTextMaterial else { return } if changedMaterial { textEntity.components.set(modelComponent) } /// Counteract vertically inverted text. textEntity.scale.y = -abs(textEntity.scale.y) #endif } Usage Run either CatalystTextBugRealityView() or CatalystTextBugARView() on a Mac Catalyst target. Toggle applyWorkaround on either view to try with and without the workaround.
Replies
1
Boosts
0
Views
724
Activity
Aug ’26
Using CARenderer for off-screen rendering of WKWebView results in a blank screen for the web page content on iOS 16 system version.
Using the CRenderer off-screen rendering method for WKWebView results in a blank screen for the web page content on the iOS 16 system version, but it can successfully obtain the web page content screen on the iOS 18 system version. I need a solution to achieve the display of web page content on the 16 system version, with a frame rate of more than 60 frames per second.
Replies
1
Boosts
0
Views
1.3k
Activity
Jul ’26
Draw WKWebView into OpenGL Texture
I'm trying to figure out how to display a Web Browser inside my iOS VR app (Obj-c, SceneKit and raw OpenGL), and the part i'm not fully understanding is how to get the WKWebView to draw it's content into a Pixel Buffer of some sort, so I can use the speed of CVOpenGLESTextureCacheCreateTextureFromImage to convert the pixel data into a OpenGl Texture quickly/efficently and display it on a floating surface.I'm already doing something simular with the video portion of my app, but it has a AVPlayerItemVideoOutput, which produced the pixel buffer, but I can't figure out how to massage the CALayer into a Buffer so I can convert it into a texture to then draw in opengl.I know it has something to do with drawLayer:(Layer) ,(Context), but searching online hasn't been very fruitful.And i'm not using SceneKit like you would assume, the app was built before GVR for Scenekit was a thing, so every part of VR is handled manually (scenekit to textures, textures to opengl for Left/Right eye distortion mesh).
Replies
3
Boosts
0
Views
2.8k
Activity
Jul ’26
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
2
Boosts
4
Views
2.4k
Activity
Jul ’26
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
924
Activity
Jul ’26
WatchBlocks v1.5 is now available: a sandbox game built for Apple Watch
Hi everyone! After about 4-5 months of development, I released WatchBlocks v1.5 today. The project started as an experiment to answer a simple question: Could you build a real sandbox survival game that runs well on Apple Watch? It eventually grew into a cross-platform game supporting Apple Watch, iPhone, iPad, and Mac. Some of the technical challenges I enjoyed solving included: Optimizing rendering and gameplay for watchOS. Designing controls around the Digital Crown and the watch display. Building multiplayer across Apple platforms. Creating a content system that lets players make and share their own blocks, items, mobs, and biomes. The new update also transitions the game to a free-to-start model, making it easier for people to try it before deciding whether to unlock the full experience. I’d love to hear from other developers building for watchOS. It’s a platform that doesn’t get much attention for games, but I think there’s a lot of untapped potential. If anyone has questions about developing games for Apple Watch, I’m happy to answer them. App Store: https://apps.apple.com/us/app/watchblocks-craft-build/id6760209351
Replies
0
Boosts
0
Views
934
Activity
Jul ’26
Refresh Rate Drops from 144Hz to 98Hz After Monitor Power Cycle on macOS Golden Gate 27
Hello, I use a Gigabyte M32U monitor with my Mac mini. After updating to macOS Golden Gate 27 Release 3, I started experiencing an issue with my external display. Whenever I turn my monitor off and then turn it back on, the refresh rate automatically changes from 144Hz to 98Hz, and the 144Hz option disappears from the display settings. However, if I unplug the display cable and plug it back in, the monitor is detected again and the 144Hz option returns, allowing me to select it normally. This issue only started after updating to macOS Golden Gate 27 Release 3. Before the update, the monitor consistently worked at 144Hz without any problems. Could you please investigate this issue? Thank you.
Replies
1
Boosts
0
Views
918
Activity
Jul ’26
Import models into my game
Hello, Im watching this tutorial: https://www.youtube.com/watch?v=tNkvu-YUVro&t=241s I have a reality composer project saved But she does not explain step by step what directory to import, how exactly to import it, and where exactly to import it to I tried to drag and drop every folder level into xcode and also into finder, 1 by 1, nothing works. it does not recognize my contentBundle in code. if someone from apple can upload 2 screenshots sowing the proper way to do this in 2026 it will be awesome Thanks guys :)
Replies
2
Boosts
0
Views
622
Activity
Jul ’26
How can I determine which side of a RoomPlan wall surface contains the wall thickness?
I am using Apple RoomPlan and working with CapturedRoom.Surface objects representing walls. From RoomPlan, I can get information such as: transform dimensions polygonCorners completedEdges However, I am not sure how the returned wall surface should be interpreted geometrically. Is the wall surface returned by RoomPlan: the centerline of the physical wall; the interior face of the wall; the exterior face of the wall; or simply an estimated 2D surface without any guarantee about wall thickness? If I want to create a wall with thickness, for example when converting RoomPlan data to IFC or another BIM format, how can I determine which side of the returned surface the wall should be extruded toward? Does RoomPlan provide any information such as: wall thickness; interior or exterior wall side; inward or outward normal; wall centerline; a full 3D wall boundary; or the opposite face of the wall? I can calculate the surface normal from the third column of the wall transform and obtain the wall-face boundary using polygonCorners, but I do not know whether the positive normal points toward the room interior or exterior. Is there an official or recommended way to determine the correct wall side, or must applications infer it from the room geometry and apply an assumed wall thickness? Any clarification about the coordinate convention and intended geometric meaning of a RoomPlan wall surface would be appreciated.
Replies
1
Boosts
0
Views
545
Activity
Jul ’26
iPad Pro M4 (11-inch) – Persistent Gaming Performance Issues Across Multiple iPadOS Versions
Hello everyone, I am posting this to determine whether other iPad Pro M4 users are experiencing the same issue. Device: iPad Pro 11-inch (M4) Original Apple charger Tested on multiple iPadOS versions, stebal and beta including 26.2, 26.3, 26.4, 26.5.2 Games Tested: BGMI PUBG Mobile Global Call of Duty: Mobile Fortnite Issue: Despite using one of Apple's most powerful tablets, I continue to experience gaming performance problems. The issues include: FPS drops during long gaming sessions. Frame pacing inconsistencies. Reduced responsiveness during intense fights. Inconsistent hit registration and spray accuracy after extended play. Performance sometimes changes when gaming while charging with the original Apple charger. I have tested multiple iPadOS versions and multiple game updates over several months, but the issue has never been completely resolved. Interestingly, iPadOS feels more consistent for me than some previous versions, but the overall gaming experience is still not what I would expect from the M4 hardware. I have also noticed that many other iPad Pro M4 users have reported similar concerns on Reddit, Apple Communities, and other gaming forums. Questions: Are other iPad Pro M4 users experiencing the same FPS drops and gameplay inconsistencies? Has anyone found a reliable solution? Is Apple aware of these gaming performance issues on the M4 iPad Pro? Is this an iPadOS optimization issue, a GPU scheduling issue, or something related to game optimization? I hope Apple and game developers investigate this further because the M4 hardware should be capable of delivering a consistently excellent gaming experience. Thank you.
Replies
0
Boosts
0
Views
810
Activity
Jul ’26
M5 Pro WindowServer/Display Engine: Window animations and UI scrolling capped at ~60Hz on external 5K 165Hz display while hardware cursor remains smooth
On the new M5 Pro platform running macOS, UI animations (window dragging, Safari/Chrome scrolling, Mission Control) on an external 5K 165Hz display appear to render at a much lower frame rate (~60Hz) or exhibit severe micro-stuttering. However, the mouse cursor and desktop wallpaper dragging remain perfectly fluid at 165Hz, indicating a potential issue in the WindowServer compositor or display pipeline rather than the physical link. Environment • Hardware: MacBook Pro (M5 Pro) • OS: macOS 27.0 beta 3 (26A5378j) • External Display: 5K 165Hz monitor connected via DisplayPort (DSC confirmed via IORegistry). System Settings correctly detects and selects 165Hz. Expected Behavior All UI elements, including window movement, application scrolling, and system animations, should render smoothly at the native 165Hz refresh rate matching the hardware capabilities. Actual Behavior The display output appears split between two different refresh rates: 1. Full 165Hz: The hardware mouse cursor and desktop dragging (empty area selection) are perfectly smooth. 2. ~60Hz / Jitter: Application windows (Finder, Safari, Chrome) stutter heavily when dragged or scrolled. Mission Control animations suffer from micro-stutters. Note: This specific combination suggests the Hardware Cursor layer is running at full rate, but the WindowServer compositor layer is throttled or dropping frames. Troubleshooting Performed (No Change) • Verified with multiple certified DisplayPort cables. • Tested across various resolutions (Scaled/HiDPI modes) and toggling DSC. • Regression Check: This issue did not occur on a 4K 144Hz HDR monitor previously, and initial community feedback shows other M5 Pro users experiencing this specific 165Hz window-dragging jitter, while M4 Pro / base M5 users on the same macOS beta do not seem impacted. Questions & Diagnostics 1. Is this a known regression related to the new M5 Pro display engine / Display Coprocessor (DCP) pipeline handling 5K high-refresh-rate timings? 2. Are there specific defaults write commands, Quartz Debug profiles, or custom logging arguments (WindowServer, DCP, or Metal) we can enable to capture frame presentation metrics? I have captured a sysdiagnose, IORegistry dump, and high-frame-rate screen recordings, and am ready to attach them as soon as this feedback is processed. Case / Feedback Reference Feedback ID: FB23616959 (Captured after the system format)
Replies
0
Boosts
0
Views
422
Activity
Jul ’26
Archived achievements
Hi! With my next update i want to archive 6 of my 18 achievements, and add 7 new ones. I've archived the 6, and added the 7 new ones, but i can distritibute any points due to the archived 6 still holding the active point amount. It's been about 12 hours since i archived them, so do i just wait another 12 hours or is there a better way ?
Replies
4
Boosts
0
Views
705
Activity
Jul ’26
HidHide on MacOS
I was wondering if there's a method on MacOS to have my application hide a hid device such as a game controller and instead have the receiving game/application see my app's virtual controller? Is this possible via DriverKit or some other form of kernel level coding? On Windows we have a tool known as HidHide that hids a game controller from all other applications. Is it possible to implement such behavior into an app or is that system level?
Replies
7
Boosts
0
Views
3.7k
Activity
Jul ’26
SKView showsFields draws only on a portion of the screen
The SKView.showsFields = true only draws on a portion of the screen - nothing shows on the bottom-left. This can be easily tested using Apple's default game playground. I only removed the action for the Hello World label and added a radialGravityField into the scene. Also other fields like electricField do not draw anything on the screen. Tested in Xcode 11.7 and Xcode 12.5.1. Is this a bug in the recent releases? override func didMove(to view: SKView) { // ... let field = SKFieldNode.radialGravityField() addChild(field) } and sceneView.showsFields = true
Replies
5
Boosts
1
Views
2.0k
Activity
Jul ’26
How do I work with the BlendMask node in the animation graph in RCP3?
In RCP3, is it possible to mask out joints in a pose at runtime? I want to have two poses running for my character, one for the upper body and one for the lower body and I was hoping to do that from the animation graph. It seems like I should be able to have two State Machine nodes running, and use the Blend Mask node to make sure only joints from the upper body animation comes through from the upper body state machine, and the same for the lower body. The description of the Blend Mask node say "Filter a pose by applying per-joint weights from a blend mask" so that seems like what I want. But I can't figure out how to author a blend mask resources in RCP3. It seems to be possible to do programmatically via the SkeletonResource.BlendMask struct but how do I do it in RCP3? Also, the Blend Mask node takes two poses as parameters, whereas I was expecting it to take a pose and a blend mask.
Replies
0
Boosts
0
Views
371
Activity
Jul ’26
Xcode 26 – "Manage Game Progress" not showing achievements/leaderboards on macOS
Hello, When testing GameKit "Manage Game Progress" in Xcode 26: On iOS devices, achievements, leaderboards, and party code data display and work correctly. On macOS devices, none of these data appear in "Manage Game Progress." Is this a known issue with macOS GameKit, or is there a limitation compared to iOS? If it is not a bug, is there any additional configuration needed to make achievements and leaderboards visible on macOS? I also included the GameKit bundle in my macOS app and enabled Enable Debug Mode in GameKit Configuration in the scheme options. Thank you.
Replies
4
Boosts
1
Views
1.5k
Activity
Jul ’26