user3894009
user3894009

Reputation: 94

Swift structures causing undefined behaviour

I'm writing a program that uses Metal. I'm defining the uniform buffer layout using a structure. When I declare the struct in swift, it fails to draw. But when I declare the struct in Objective-C and use a bridging header to import it, it works fine. The actual logic for computations are exactly the same. The only change is the declaration. Here are the declarations:

Objective-C declaration (this one works):

struct Uniforms {
    struct Matrix4x4 modelViewMatrix;
    struct Matrix4x4 projectionMatrix;
    struct Matrix3x3 normalMatrix;
    struct Vector3 lightPosition;
};

And the Swift declaration:

struct Uniforms {
    var modelViewMatrix: Matrix4x4!
    var projectionMatrix: Matrix4x4!
    var normalMatrix: Matrix3x3!
    var lightPosition: Vector3!
}

Note that the math types are structs defined in Objective-C, and act as wrappers for Swift.

For more info, here is the Swift code that computes the values and sends them to Metal:

// Declaration:
var uniforms: Uniforms!
...
// Part where I compute the values:
    self.uniforms = Uniforms()

    let eye = vector3Create(0.0, 5.0, 7.0)
    let center = vector3Create(0.0, 0.0, 0.0)
    let up = vector3Create(0.0, 1.0, 0.0)
    self.uniforms.modelViewMatrix = MathOperations.lookAt(eye, center: center, up: up)

    let aspect = Float(self.view.bounds.size.width / self.view.bounds.size.height)
    self.uniforms.projectionMatrix = MathOperations.perspective(45.0, aspect: aspect, near: 0.01, far: 100.0)
    self.uniforms.normalMatrix = getMatrix3x3FromMatrix4x4(self.uniforms.modelViewMatrix)
    self.uniforms.lightPosition = vector3Create(0.0, 5.0, 7.0)

    self.vertexBuffer = device.newBufferWithBytes(self.vertexArray, length: self.vertexArray.count * sizeof(Float), options: .CPUCacheModeDefaultCache)
    self.uniformBuffer = device.newBufferWithBytes(&self.uniforms, length: sizeof(Uniforms), options: .CPUCacheModeDefaultCache)

Sorry for all the code, but please help. Thanks.

Upvotes: 2

Views: 135

Answers (1)

Luca Angeletti
Luca Angeletti

Reputation: 59536

I am trying to explain here the comment I added to the question and that looks to be a correct answer.

The correct way to convert this Objective-C code:

struct Matrix4x4 modelViewMatrix;

to Swift is NOT this

var modelViewMatrix: Matrix4x4!

because this way we are not creating variable of type Matrix4x4. Instead we are creating a variable of type Optional of type Matrix4x4.

This means that in Swift the variable modelViewMatrix is able to assume nil value while in Objective-C it does not.

Let's remember that in Objective-C a variable having a struct as type cannot be nil.

So the correct way to translate the original statement from Objective-C to Swift is the following:

var modelViewMatrix: Matrix4x4

Upvotes: 1

Related Questions