Last Parameter Being Dropped

In my .metal code I have a struct that looks like:

Code Block c
struct MixerParameters
{
    float2 firstScreenPosition;
    float2 firstScreenSize;
    float2 secondScreenPosition;
    float2 secondScreenSize;
    int sessionType;
    int secondScreenCameraPosition;
}


On the swift side, I also have a struct:

Code Block swift
struct MixerParameters {
        var firstScreenPosition: SIMD2<Float>
        var firstScreenSize: SIMD2<Float>
        var secondScreenPosition: SIMD2<Float>
        var secondScreenSize: SIMD2<Float>
        var sessionType: Int
        var secondScreenCameraPosition: Int
        var isFrontCamera: Bool
    }


And the data is being sent to the metal shader function via:

Code Block swift
commandEncoder.setBytes(&parameters, length: MemoryLayout<MixerParameters>.stride, index: 0)


I am using the session type to switch on in the metal code, and everything was working fine until I tried to add a switch case.

The new case is unable to correctly see the secondScreenCameraPosition int value, which it always interprets as 0. It's not being reset anywhere else in code, and the value getting passed to the metal shader is the correct value.

If the metal shader is handling any of the other switch cases, everything was working fine. It's just on the ONE switch case.

I found that if I added another value at the end of my structs, and passed this into the metal shader, it has trouble with this very last value, but all the other values work, so as of right now, I am passing in a dummy bool value, just so I can access my secondScreenCameraPosition value properly.

This work around is very hacky, and makes no sense to me. Could anyone give a hint as to why this might be happening? Maybe my stride calculation is off somehow?

I am very new to Metal (and GPU coding in general), and am finding the learning curve to be rather steep. It's a fun journey, but there is just so much to learn. Thanks for your help and feedback!
Answered by OOPer in 618105022
In Metal, int is a 32-bit signed integer, but in Swift, Int is a platform-dependent signed integer. In recent platforms, it is 64-bit.

So, I'm very curious why your hacky workaround works as expected, very strange...

Can you try and tell us how it works if you use the right size of integer types in Swift.
Code Block
struct MixerParameters {
    var firstScreenPosition: SIMD2<Float>
    var firstScreenSize: SIMD2<Float>
    var secondScreenPosition: SIMD2<Float>
    var secondScreenSize: SIMD2<Float>
    var sessionType: Int32
    var secondScreenCameraPosition: Int32
}



Accepted Answer
In Metal, int is a 32-bit signed integer, but in Swift, Int is a platform-dependent signed integer. In recent platforms, it is 64-bit.

So, I'm very curious why your hacky workaround works as expected, very strange...

Can you try and tell us how it works if you use the right size of integer types in Swift.
Code Block
struct MixerParameters {
    var firstScreenPosition: SIMD2<Float>
    var firstScreenSize: SIMD2<Float>
    var secondScreenPosition: SIMD2<Float>
    var secondScreenSize: SIMD2<Float>
    var sessionType: Int32
    var secondScreenCameraPosition: Int32
}



Thank you @OOPer, that did it!
Thanks for reporting.

Generally, it is hard to write a Swift struct with exactly the same layout with some Metal struct.
You may need to have all the related info, such as data sizes, alignments, paddings, etc.. in mind.

I usually create a C-compatible header and write such struct in it, and then import it from both Metal and Swift.
(Of course through bridging header in case of Swift.)

Even if it is hard to write a header file importable from Metal and Swift, experiences importing some C-struct will give you a good insight.

Anyway, I am very happy to hear my reply has helped. Good luck.
I am just learning about doing the bridging header in the Ray Wenderlich book I have on Metal. Seems like doing that will help prevent future problems, as well.
Last Parameter Being Dropped
 
 
Q