Group Group Group Group Group Group Group Group Group

SIMD BADACCESS Error?

Having a very strange error when building tutorials Chapter 5 onwards with the Arcball camera on macOS (Catalina 10.15.4 and 10.15.3):

I get a Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) in Camera.swift as part of the ArcBall logic. This only pops once the rotation calculation is executed.

Adding print statements in-between those lines fixes this. (can’t post second image in to show; new user)

Curious if anyone has had this problem, it looks like it is a problem from some people?
https://forums.developer.apple.com/message/402225#402225

Example of the print state solution

I have encountered this occasionally, but I haven’t yet dived into it to check the cause, which is something I suspect I can’t fix.

I get around it by assigning the whole [x, y, z] float3 value to the rotation at one time, and not by assigning rotation.x separately.

Ah! I should have tried that. I will reach out to Apple Dev and see if they can advise. It looked like 10.15.4 should have that update but it might be a patch coming later?

I spent most of the day trying to track this down as it just started happening to me also. And I have no idea what I did. Anyway, I made no real progress besides trying a ton of things as you can see from the following code and comments. Maybe you can see a pattern here. I cannot.

override func rotate(delta: float2) {
let sensitivity: Float = 0.005
print(rotation) // does not cause crash
print(delta) // does not cause crash
print(rotation.x) // does not cause crash
print(delta.x) // does not cause crash
rotation.y += sensitivity // does not cause crash
print(rotation.y) // does not cause crash
print(10.0 * sensitivity) // does not cause crash
let temp = 10.0 * sensitivity; print(temp) // does not cause crash
// var temp2 = 10.0 * sensitivity // causes crash at rotation.x += delta.y * sensitivity
// rotation.y = temp // causes crash
// rotation.y += 10.0 * sensitivity // causes crash
// rotation.y += delta.x * sensitivity // causes crash
rotation.x += delta.y * sensitivity // does not cause crash
print(rotation) // does not cause crash
print(rotation.x) // does not cause crash
rotation.x += delta.y * sensitivity // does not cause crash
// temp = rotation.x; print(temp)
// rotation.x = max(-Float.pi/2, min(rotation.x, Float.pi/2)) // causes crash
_viewMatrix = updateViewMatrix()
}

I also tried:
rotation += float3(delta,0) * sensitivity // causes crash

but that didn’t work.

Unfortunately this sounds like one of those things that depending on your CPU it will be a problem (until the patch for it is released)

my solution was as simple as:

override func rotate(delta: float2) {
    let sensitivity: Float = 0.005
    var x = rotation.x + delta.y * sensitivity
    x = max(-Float.pi/2, min(x, Float.pi/2))
    rotation = [
        x,
        rotation.y + delta.x * sensitivity,
        rotation.z
    ]
    _viewMatrix = updateViewMatrix()
  }
2 Likes

UPDATE: Here is a better version of it, bit more readable IMO:

override func rotate(delta: float2) {
    let sensitivity: Float = 0.005
    let y = rotation.y + delta.x * sensitivity
    var x = rotation.x + delta.y * sensitivity
    x = max(-Float.pi/2, min((x), Float.pi/2))
    rotation = [x, y, 0]
    _viewMatrix = updateViewMatrix()
1 Like

I found that simply comment out the override of rotation property would work.

Oh interesting! now the question is if this is a SIMD alignment issue or if the didSet closure is doing some weirdness. I wonder if the ‘didSet’ events are getting tangled?

Unfortunately that method needs to be there to update the view matrix if the code changes the rotation of the camera (rather than the user through gestures).

For example, if you comment out that rotation method and in draw(in:), add a rotation:

timer += 0.005
camera.rotation.y = sin(timer)

Then the camera doesn’t rotate.

If you uncomment that override, that code doesn’t crash until you add

camera.rotation.x = sin(timer)

Then it does crash.

So I think that you’re right, it does seem to be the didSet that’s causing it, but I am loathe to change that method. Setting the entire rotation:

timer += 0.005
camera.rotation = [sin(timer), sin(timer), camera.rotation.z]

works, and I think is the way to go for the moment.