> On Jul 9, 2017, at 4:49 PM, Jens Persson via swift-evolution 
> <[email protected]> wrote:
> 
> Sorry for making so much off topic noise in this thread, but I made a mistake 
> regarding the Metal tutorial:
> Looking more carefully I see now that they rebuild a vertedData: [Float] from 
> their vertices: [Vertex] using the floatBuffer() method of the Vertex struct, 
> which returns an Array with the stored properties of Vertex in correct order.
> 
> While searching the internet about this I saw Joe Groff mentioning on Twitter 
> that:
> "We plan to sort fields in padding order to minimize size, and may also 
> automatically pack bools and enums in bitfields."
> 
> So AFAICS my current image processing code is making the possibly invalid 
> assumption that eg
> struct S {
>     var a, b, c, d: Float
> }
> will have a memory layout of 4*4=16 bytes (stride and size == 16) and an 
> alignment of 4, and most importantly that a, b, c, d will be in that order.

This is currently true, but may not always be.  We want to reserve the right to 
re-order the fields even if it doesn't improve packing — for example, if two 
fields are frequently accessed together, field reordering could yield 
substantial locality benefits.  We've also discussed reordering fields to put 
them in a canonical order for resilience, since it's a little counter-intuitive 
that reordering the fields of a struct should be ABI-breaking.  (There are 
arguments against doing that as well, of course — for example, the programmer 
may have chosen the current order for their own locality optimizations.)

> It looks like I should be defining my structs (the ones for which memory 
> layout is important) in C and import them.

This should always work, yes.

> Although I would be surprised if a Swift-struct containing only same-sized 
> fields (all of the same primitive type) would be reordered, and such changes 
> to the language would probably include some per-struct way to express some 
> sort of layout control (since being able to define structs to be used for low 
> level data manipulation is important in a systems language).

Exactly.  In the long term, Swift will have some explicit tools for layout 
control.

John.

> 
> /Jens
> 
> 
> On Sun, Jul 9, 2017 at 7:01 PM, Jens Persson via swift-evolution 
> <[email protected] <mailto:[email protected]>> wrote:
> I should perhaps add that in my image processing code, I use code like this:
> 
> func withVImageBuffer<Data, R>(for table: Table<Data>, body: (vImage_Buffer) 
> -> R) -> R
>     where
>     Data.Coordinate.Index == VectorIndex2
> {
>     let vib = vImage_Buffer(
>         data: table.baseAddress,
>         height: vImagePixelCount(table.size.e1),
>         width: vImagePixelCount(table.size.e0),
>         rowBytes: table.stride.e1
>     )
>     return withExtendedLifetime(table) { body(vib) }
> }
> 
> Here, Table<Data> is the raster image. Data.Coordinate == VectorIndex2 makes 
> it a 2D table, and a Table's Data also has a type parameter Data.Value which 
> can be eg one of the "pixel"-struct I showed before.
> This works without any problems (I've tested and used the some variant of 
> this type of code for years) but it would surely break if the memory layout 
> of simple structs changed.
> 
> I can't see how this usage is much different from the one in the Metal 
> tutorial. It too uses pointers to point into a data created using the (Swift) 
> struct "Vertex", and the GPU hardware has its expectations on the memory 
> layout of that data, so the code would break if the memory layout of the 
> Vertex struct changed.
> 
> /Jens
> 
> 
> On Sun, Jul 9, 2017 at 6:35 PM, Jens Persson <[email protected] 
> <mailto:[email protected]>> wrote:
> I don't think I'm misunderstanding you, but I might be, so I'll add more 
> detail:
> 
> If you look at the Metal article, you'll see that the (Swift) struct "Vertex" 
> is used to specify the data that is sent to Metal for creating a buffer 
> (using MTLDevice.makeBuffer). The result that the GPU will produce surely 
> depends on the fields of the Vertex struct (x, y, z, r, g, b, a) being in the 
> specified order (ie swapping the red channel with the x coordinate would 
> produce an unexpected result).
> 
> And regarding the second example, pixel structs used for manipulating raster 
> image data. Manipulating raster image data presumably includes stuff like 
> displaying to screen, loading and saving raster images.
> I currently use this way of doing this right now without any problems, but if 
> the order of the fields (eg a, r, g, b) should change in the future, then my 
> code would break (the colors of the images would at least not come out as 
> expected).
> 
> /Jens
> 
> 
> 
> 
> 
> 
> On Sun, Jul 9, 2017 at 5:53 PM, Chris Lattner <[email protected] 
> <mailto:[email protected]>> wrote:
> 
>> On Jul 9, 2017, at 12:23 AM, Jens Persson <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>> 
>> On Sat, Jul 8, 2017 at 6:28 PM, Chris Lattner via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> Hi Susan,
>> 
>> Swift does not currently specify a layout for Swift structs.  You shouldn’t 
>> be using them for memory mapped i/o or writing to a file, because their 
>> layout can change.  When ABI stability for fragile structs lands, you will 
>> be able to count on it, but until then something like this is probably a bad 
>> idea.
>> 
>> -Chris
>> 
>> Does this imply that you should never use Swift structs to eg interact with 
>> Metal?
> 
> No.
> 
>> This seems to be a very common practice. Here is a typical example (from a 
>> Metal tutorial at raywenderlich.com <http://raywenderlich.com/>):
>> 
>> struct Vertex {
>>   var x,y,z: Float     // position data
>>   var r,g,b,a: Float   // color data
>> 
>>   func floatBuffer() -> [Float] {
>>     return [x,y,z,r,g,b,a]
>>   }
>> }
> 
> This doesn’t appear to expose the layout of the struct.
>> Also, does it imply that we cannot use structs (of only primitive types) 
>> like:
>> 
>> struct RgbaFloatsLinearGamma {
>>     var r, g, b, a: Float
>>     …
>> }
>> struct BgraBytesSrgbGamma {
>>     var b, g, r, a: UInt8
>> }
>> 
>> for manipulating raster image data?
> 
> I don’t see why that would be a problem.
> 
>> I vaguely remember a swift evo discussion where it was concluded that such 
>> usage was considered OK provided the stored properties of the structs was 
>> only primitive types, but I can't find it now.
>> 
>> Perhaps it could be considered OK at least when the intended platforms are 
>> known to be only iOS devices?
> 
> I think you’re misunderstanding what I’m saying.  It isn’t correct to take 
> (e.g.) an unsafepointer to the beginning of a struct, and serialize that out 
> to disk, and expect that the fields are emitted in some order with some 
> specific padding between them.  None of the uses above try to do this.
> 
> -Chris
> 
> 
> 
> 
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to