[swift-users] UnsafeMutablePointer Swift 3 conversion

Gerard Iglesias gerard_iglesias at me.com
Thu Sep 8 06:04:32 CDT 2016


Andrew,

Thank you for the compliment ;)

And thank you for the 2 advices

And the question about use of size or stride ? I understand that the underlaying float data are aligned in this specific case, but I wonder in fact if the shader compiler align memory the same way the swift compiler do, I suppose yes unless it would be a nightmare, but murphy’s principle says me … take care ;)

Thanks in advance

Gerard

> On 8 Sep 2016, at 07:21, Andrew Trick <atrick at apple.com> wrote:
> 
>> 
>> On Sep 3, 2016, at 6:03 PM, Gerard Iglesias via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>> 
>> This is my funny version… I succeeded and I didn’t come back to find an other way…
>> 
>> // Grab a pointer to the constant buffer's data store
>> // Since we are using Swift, it is easier to cast the pointer to the ShadowPass type to fill the constant buffer
>> // We need to make a copy of these so the block captures the correct data
>>     
>> //let shadowPtr = UnsafeMutablePointer<ShadowPass>(constantBufferForFrame.contents())
>> let shadowPtr = constantBufferForFrame.contents().assumingMemoryBound(to: ShadowPass.self)
>> shadowPtr.pointee = shadowPassData[0]
>> 		
>> //More Swift specific stuff - advance pointer and cast to MainPass
>>     
>> //let mainPtr = UnsafeMutablePointer<MainPass>(shadowPtr.advanced(by: 1))
>> let mainPtr = constantBufferForFrame.contents().advanced(by: MemoryLayout<ShadowPass>.size).assumingMemoryBound(to: MainPass.self)
>> mainPtr.pointee = mainPassFrameData
>> 		
>> //Advance and cast to ObjectData
>> 
>> //var ptr = UnsafeMutablePointer<ObjectData>(mainPtr.advanced(by: 1))
>> var ptr = constantBufferForFrame.contents().advanced(by: MemoryLayout<ShadowPass>.size + MemoryLayout<MainPass>.size).assumingMemoryBound(to: ObjectData.self)
> 
> Gerard,
> 
> I like your code. A couple of things to consider:
> 
> 1. If the memory has never been bound to a type (i.e. it's straight from MTLBuffer.newBuffer), then rather than “assuming” memory is bound to these types, you should just bind it here (substitute all your assumingMemoryBound(to: _) with bindMemory(to: _, capacity: 1). Think of it as two-phase initialization of the memory. First declare the memory's type (e.g. some structure that holds a bunch of floats), then write individual float values into the memory.
> 
> 2. If you want the compiler to compute byte offsets for you like the original code, then can be done as follows:
> 
>   let mainPtr = UnsafeMutableRawPointer(shadowPtr + 1).bindMemory(
>     to: MainPass.self, capacity: 1)
>   mainPtr.pointee = mainPassFrameData
>   ...
> 
> However, your approach of computing byte offsets is more explicit.
> 
> My migration guide landed on swift.org <http://swift.org/> today! I think it will be a big help.
> https://swift.org/migration-guide/se-0107-migrate.html <https://swift.org/migration-guide/se-0107-migrate.html>
> 
> -Andy
> 
>>> On 3 Sep 2016, at 19:22, Patrice Kouame <pkouame at me.com <mailto:pkouame at me.com>> wrote:
>>> 
>>> Gerard- 
>>> 
>>> Excellent!  Looking forward to seeing your fix (hoping you get your book back soon ;-) )
>>> 
>>> I think Xcode/Swift gags on the last ptr advance to objectData.  I recently tried another variant using withUnsafeMutablePointer like this:
>>> 
>>>         var ptr : UnsafeMutablePointer<ObjectData>  = withUnsafeMutablePointer(to: &mainPtr) {
>>>             $0.withMemoryRebound(to: ObjectData.self, capacity: objectsToRender) {
>>>                 $0.pointee = renderables[0].objectData
>>>             }
>>>         }
>>> 
>>> ..but still crashes with no hints.
>>> 
>>> My bug report also mentions that the Xcode migration/conversion tool is incomplete.  
>>> It handles the “simpler" UnsafeMutableRawPointer<X> to UnsafeMutablePonter<Y> with bindMemory cases correctly (one still has to mind the capacity value though)
>>> In all fairness, migrating/converting automagically in these cases is always a little bit tricky - the proposed Xcode fixes should always be reviewed by a human...
>>> 
>>> Patrice
>>> 
>>>> On Sep 3, 2016, at 1:05 PM, Gerard Iglesias via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>>> 
>>>> Ok
>>>> 
>>>> For the record I succeeded this transformation phase last week
>>>> 
>>>> I remember the tedious stuff to advance pointer from one struct to the other kind of struct... it worked
>>>> 
>>>> But I don't have my MacBook with me, only the phone, the six :)
>>>> 
>>>> Gérard 
>>>> 
>>>> Le 3 sept. 2016 à 18:22, Patrice Kouame <pkouame at me.com <mailto:pkouame at me.com>> a écrit :
>>>> 
>>>>> Indeed. There is a difference between stride and size, but I interpreted capacity incorrectly for my purposes.  It should indicate the number of <T> elements (not their size - right?) and the snippets below should work.
>>>>> 
>>>>> Still, compiler crashes and Xcode IDE is left in inconsistent state.  So I filed this Apple radar against Developer Tools.
>>>>> 
>>>>> 	28150447 - Swift 3 UnsafeMutablePointer conversion crashes the compiler and IDE
>>>>> Should I file a Swift bug too? Would that be helpful?
>>>>> 
>>>>> Regards, Patrice
>>>>> 
>>>>>> On Sep 3, 2016, at 11:39 AM, Gerard Iglesias via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>>>>> 
>>>>>> Hello,
>>>>>> 
>>>>>> I think that it is more secure to use stride in place of size, sometimes it is not the same value.
>>>>>> 
>>>>>> I use it in my own use of raw bindings 
>>>>>> 
>>>>>> Regards
>>>>>> 
>>>>>> Gérard 
>>>>>> 
>>>>>> Le 3 sept. 2016 à 10:03, Patrice Kouame via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> a écrit :
>>>>>> 
>>>>>>> Hi Jacob - 
>>>>>>> 
>>>>>>> I think you’re right. “capacity” should be the count of type T elements in my buffer.  So in my case that line should read
>>>>>>> 
>>>>>>>         let shadowPtr = constantBufferForFrame.contents().bindMemory(to: ShadowPass.self, capacity: shadowPassData.count)
>>>>>>> 
>>>>>>> The withMemoryRebound calls need similar adjustments. The pointer to MainPass is actually a single structure to it should be safe to do this
>>>>>>> 
>>>>>>>         let mainPtr : UnsafeMutablePointer<MainPass> = shadowPtr.advanced(by: 1).withMemoryRebound(to: MainPass.self, capacity: 1) {
>>>>>>>             $0.pointee = mainPassFrameData
>>>>>>>         }
>>>>>>> 
>>>>>>> Whereas the unsafe pointer to <ObjectData> is actually a buffer of renderable objects, so this should work:
>>>>>>> 
>>>>>>>         var ptr : UnsafeMutablePointer<ObjectData> = mainPtr.advanced(by: 1).withMemoryRebound(to: ObjectData.self, capacity: objectsToRender) {_ in
>>>>>>> 	}
>>>>>>> 
>>>>>>> There are surely ways to refactor and simplify this, but I’m trying to retain as much of the original sample code approach as possible.
>>>>>>> 
>>>>>>> However, the compiler still segs badly. 
>>>>>>> Xcode also borks an internal error often. Only cleaning or restarting the project can clear up that state.
>>>>>>> Compilers (or Playgrounds for that matter) should never crash, and I’m not sure where to file this bug : Swift or Apple radar against Xcode or both? I now Xcode 8 is beta but…it’s been doing this for quite a while now...
>>>>>>> 
>>>>>>> In both our “close to the metal” (no pun intended) cases, it seems like a lot of churning for very little gain. Don’t you think? The easier, but “unsafe” casting afforded previously did the trick with the normal caveats.
>>>>>>> Don’t get me wrong, I love Swift and “get" all the neat type safety features. Guess we can’t have our cake and eat it too, especially when interfacing with “unsafe” C APIs.
>>>>>>> 
>>>>>>> Anyway, back to rtfm … maybe some of the Swift Gods can chime in?  ;-) 
>>>>>>> 
>>>>>>> I must be doing something stupid...Patrice
>>>>>>> 
>>>>>>>> On Sep 3, 2016, at 2:32 AM, Jacob Bandes-Storch <jtbandes at gmail.com <mailto:jtbandes at gmail.com>> wrote:
>>>>>>>> 
>>>>>>>> Hi Patrice,
>>>>>>>> I don't have a solution for you, but I just wanted to point out what I think may be an error with your use of the new UnsafeRawPointer APIs:
>>>>>>>> 
>>>>>>>> constantBufferForFrame.contents().bindMemory(to: ShadowPass.self, capacity: MemoryLayout<ShadowPass>.size)
>>>>>>>> 
>>>>>>>> I believe the `capacity` should actually be the number of ShadowPass elements in the buffer, not the size of each element. Using `bindMemory(to: ShadowPass.self` already implies that MemoryLayout<ShadowPass>.size is the size of each element.
>>>>>>>> 
>>>>>>>> More info at https://developer.apple.com/reference/swift/unsaferawpointer/2428875-bindmemory <https://developer.apple.com/reference/swift/unsaferawpointer/2428875-bindmemory>
>>>>>>>> 
>>>>>>>> I just updated a small Metal project of mine to Swift 3. I ran into some compiler (playground) crashes, but it does seem to work most of the time. Although I only have 1 buffer :-) https://github.com/jtbandes/Metalbrot.playground <https://github.com/jtbandes/Metalbrot.playground>
>>>>>>>> 
>>>>>>>> Jacob
>>>>>>>> 
>>>>>>>> On Fri, Sep 2, 2016 at 11:00 AM, Patrice Kouame via swift-users <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>>>>>>> Hi all - 
>>>>>>>> 
>>>>>>>> I’m converting Apple’s Swift Sample "Adopting Metal II: Designing and Implementing a Real-World Metal Renderer” in Xcode 8 beta6 to the latest UnsafeMutablePointer API for untyped memory access.  
>>>>>>>> Changes are necessary in MetalView.swift (Apple hasn’t updated their sample code for the latest beta yet…) 
>>>>>>>> The Swift Compiler crashes (Segmentation Fault: 11) on the attempt:
>>>>>>>> 
>>>>>>>>         // Grab a pointer to the constant buffer's data store
>>>>>>>>         // Since we are using Swift, it is easier to cast the pointer to the ShadowPass type to fill the constant buffer
>>>>>>>>         // We need to make a copy of these so the block captures the correct data
>>>>>>>> 
>>>>>>>> //      let shadowPtr = UnsafeMutablePointer<ShadowPass>(constantBufferForFrame.contents())
>>>>>>>>         let shadowPtr = constantBufferForFrame.contents().bindMemory(to: ShadowPass.self, capacity: MemoryLayout<ShadowPass>.size)
>>>>>>>>         shadowPtr.pointee = shadowPassData[0]
>>>>>>>> 
>>>>>>>>         //More Swift specific stuff - advance pointer and cast to MainPass
>>>>>>>> 
>>>>>>>> //      let mainPtr = UnsafeMutablePointer<MainPass>(shadowPtr.advanced(by: 1))
>>>>>>>> //      mainPtr.pointee = mainPassFrameData
>>>>>>>>         let mainPtr : UnsafeMutablePointer<MainPass>  = shadowPtr.advanced(by: 1).withMemoryRebound(to: MainPass.self, capacity: MemoryLayout<MainPass>.size) {
>>>>>>>>             $0.pointee = mainPassFrameData
>>>>>>>>         }
>>>>>>>>         
>>>>>>>>         //Advance and cast to ObjectData
>>>>>>>>         
>>>>>>>> //      var ptr = UnsafeMutablePointer<ObjectData>(mainPtr.advanced(by: 1))
>>>>>>>>         var ptr : UnsafeMutablePointer<ObjectData> = mainPtr.advanced(by: 1).withMemoryRebound(to: ObjectData.self, capacity: MemoryLayout<ObjectData>.size) {_ in
>>>>>>>>         }
>>>>>>>> 
>>>>>>>>         let shadowOffset = 0
>>>>>>>>         let mainPassOffset = MemoryLayout<ShadowPass>.size + shadowOffset
>>>>>>>>         let objectDataOffset = MemoryLayout<MainPass>.size + mainPassOffset
>>>>>>>> 
>>>>>>>>         // Update position of all the objects
>>>>>>>>         if multithreadedUpdate {
>>>>>>>>             DispatchQueue.concurrentPerform(iterations: objectsToRender) { i in
>>>>>>>>                 let thisPtr = ptr.advanced(by: i)
>>>>>>>>                 _ = self.renderables[i].UpdateData(ptr, deltaTime: 1.0/60.0)
>>>>>>>>             }
>>>>>>>>         }
>>>>>>>>         else {
>>>>>>>>             for index in 0..<objectsToRender {
>>>>>>>>                 ptr = renderables[index].UpdateData(ptr, deltaTime: 1.0/60.0)
>>>>>>>>             }
>>>>>>>>         }
>>>>>>>>         
>>>>>>>>         ptr = ptr.advanced(by: objectsToRender)
>>>>>>>>         
>>>>>>>>         _ = groundPlane!.UpdateData(ptr, deltaTime: 1.0/60.0)
>>>>>>>> 
>>>>>>>> Any help is appreciated.  I have the latest Xcode log handy if necessary.  Here’s a clip of the stack trace.
>>>>>>>> 
>>>>>>>> 0  swift                    0x000000010714a99d PrintStackTraceSignalHandler(void*) + 45
>>>>>>>> 1  swift                    0x000000010714a3e6 SignalHandler(int) + 470
>>>>>>>> 2  libsystem_platform.dylib 0x00007fff91461bba _sigtramp + 26
>>>>>>>> 3  libsystem_platform.dylib 000000000000000000 _sigtramp + 1857676384
>>>>>>>> 4  swift                    0x00000001047207b3 (anonymous namespace)::SILGenApply::visitExpr(swift::Expr*) + 51
>>>>>>>> 5  swift                    0x0000000104723ace (anonymous namespace)::SILGenApply::visitApplyExpr(swift::ApplyExpr*) + 5182
>>>>>>>> 6  swift                    0x0000000104711cc1 prepareApplyExpr(swift::Lowering::SILGenFunction&, swift::Expr*) + 273
>>>>>>>> 7  swift                    0x00000001047624e7 swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 103
>>>>>>>> 8  swift                    0x0000000104762313 swift::Lowering::SILGenFunction::emitExprInto(swift::Expr*, swift::Lowering::Initialization*) + 195
>>>>>>>> 9  swift                    0x000000010474fbc3 swift::Lowering::SILGenFunction::emitPatternBinding(swift::PatternBindingDecl*, unsigned int) + 195
>>>>>>>> 10 swift                    0x00000001047077bd swift::ASTVisitor<swift::Lowering::SILGenFunction, void, void, void, void, void, void>::visit(swift::Decl*) + 125
>>>>>>>> 11 swift                    0x00000001047c0019 swift::ASTVisitor<(anonymous namespace)::StmtEmitter, void, void, void, void, void, void>::visit(swift::Stmt*) + 4169
>>>>>>>> 12 swift                    0x00000001047809ba swift::Lowering::SILGenFunction::emitFunction(swift::FuncDecl*) + 314
>>>>>>>> 13 swift                    0x00000001046fd775 swift::Lowering::SILGenModule::emitFunction(swift::FuncDecl*)::$_1::operator()(swift::SILFunction*) const + 1877
>>>>>>>> 14 swift                    0x00000001046fc322 swift::Lowering::SILGenModule::emitFunction(swift::FuncDecl*) + 626
>>>>>>>> 15 swift                    0x00000001047c7007 (anonymous namespace)::SILGenType::emitType() + 1271
>>>>>>>> 16 swift                    0x00000001047c6a9e swift::Lowering::SILGenModule::visitNominalTypeDecl(swift::NominalTypeDecl*) + 30
>>>>>>>> 17 swift                    0x0000000104709093 swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*, unsigned int) + 1795
>>>>>>>> 18 swift                    0x000000010470ad4d swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&, swift::FileUnit*, llvm::Optional<unsigned int>, bool, bool) + 1629
>>>>>>>> 19 swift                    0x00000001045621bf performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*) + 19487
>>>>>>>> 20 swift                    0x000000010455b2c5 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 17029
>>>>>>>> 21 swift                    0x000000010451888d main + 8685
>>>>>>>> 22 libdyld.dylib            0x00007fff91255255 start + 1
>>>>>>>> 
>>>>>>>> 
>>>>>>>> Patrice
>>>>>>>> 
>>>>>>>> 
>>>>>>>> _______________________________________________
>>>>>>>> swift-users mailing list
>>>>>>>> swift-users at swift.org <mailto:swift-users at swift.org>
>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
>>>>>>>> 
>>>>>>>> 
>>>>>>> 
>>>>>>> _______________________________________________
>>>>>>> swift-users mailing list
>>>>>>> swift-users at swift.org <mailto:swift-users at swift.org>
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
>>>>>> _______________________________________________
>>>>>> swift-users mailing list
>>>>>> swift-users at swift.org <mailto:swift-users at swift.org>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
>>>>> 
>>>> _______________________________________________
>>>> swift-users mailing list
>>>> swift-users at swift.org <mailto:swift-users at swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-users <https://lists.swift.org/mailman/listinfo/swift-users>
>>> 
>> 
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org <mailto:swift-users at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160908/8bccaf37/attachment.html>


More information about the swift-users mailing list