> On Jul 9, 2017, at 6:14 PM, Jens Persson <j...@bitcycle.com> wrote:
> 
> Thanks for that clarification John McCall.
> My code is using a lot of generic structs (in which memory layout is 
> important) though, an example would be:
> struct Vector4<E> : Vector {
>     typealias Index = VectorIndex4
>     typealias Element = E
>     var e0, e1, e2, e3: Element
>     …
> }
> And I guess I'm out of luck trying to represent those as C structs?
> So AFAICS it looks like it is currently impossible to write generic low level 
> code in Swift, unless I just keep doing what I've been doing (It does 
> currently work after all) knowing that it will probably break in some future 
> versions of Swift. But in that possible future version of Swift, I could 
> probably find a way to make it work again (using some possible explicit tools 
> for layout control present in that version of Swift).
> Correct?

Correct.

John.

> /Jens
> 
> 
> On Sun, Jul 9, 2017 at 11:41 PM, John McCall <rjmcc...@apple.com 
> <mailto:rjmcc...@apple.com>> wrote:
> 
>> On Jul 9, 2017, at 4:49 PM, Jens Persson via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 <j...@bitcycle.com 
>> <mailto:j...@bitcycle.com>> 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 <clatt...@nondot.org 
>> <mailto:clatt...@nondot.org>> wrote:
>> 
>>> On Jul 9, 2017, at 12:23 AM, Jens Persson <j...@bitcycle.com 
>>> <mailto:j...@bitcycle.com>> wrote:
>>> 
>>> 
>>> On Sat, Jul 8, 2017 at 6:28 PM, Chris Lattner via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to