> On Jul 9, 2017, at 6:57 PM, Robert Bennett <rltbenn...@icloud.com> wrote:
> Just a question: how would/does allowing the reordering of fields affect the 
> correctness and performance of the (de)serialization API added in Swift 4?

The design of that is definitely proof against changes to the in-memory layout 
of the type.  I believe it's also proof against reordering but I'm not entirely 
certain about that.

John.

> 
> On Jul 9, 2017, at 6:21 PM, Jens Persson via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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?
>> /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 <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