> 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