[swift-users] UnsafeMutablePointer Swift 3 conversion
Patrice Kouame
pkouame at me.com
Sat Sep 3 16:03:04 CDT 2016
Not sure what you mean?
The positional arg $0 is never used outside the closure whatever the version...
No attempt is ever made to save and reuse after withMemoryRebound?
Why would I use a separate function?
Are we looking at the same code? 🤓
rédigé sur mon iPhone.
> On Sep 3, 2016, at 4:16 PM, Jacob Bandes-Storch <jtbandes at gmail.com> wrote:
>
> Yikes! That's unsafe! When using withMemoryRebound, I think you're only supposed to use the argument $0 inside the block. Saving it and using it after withMemoryRebound is probably undefined behavior. But maybe you can move your ".pointee = x" into a separate function rather than using a closure?
>
>> On Sat, Sep 3, 2016 at 1:12 PM, Patrice Kouame via swift-users <swift-users at swift.org> wrote:
>> Finally Success! I’m seeing my pretty little 3D twirling Metal Renderer cubes again… Here’s how
>>
>> Snippet of old sample code which no longer compiles in Xcode 8 beta 6 with stricter Swift3 unsafe type casting restrictions
>> (in MetalView.swift from # Adopting Metal II: Designing and Implementing a Real-World Metal Renderer)
>>
>> let shadowPtr = UnsafeMutablePointer<ShadowPass>(constantBufferForFrame.contents())
>> let mainPtr = UnsafeMutablePointer<MainPass>(shadowPtr.advanced(by: 1))
>> mainPtr.pointee = mainPassFrameData
>> var ptr = UnsafeMutablePointer<ObjectData>(mainPtr.advanced(by: 1))
>>
>> My conversion attempt that crashes Swift 3 Xcode 8 beta 6 (see RADAR 28150447 - Swift 3 UnsafeMutablePointer conversion crashes the compiler and IDE)
>>
>> let shadowPtr = constantBufferForFrame.contents().bindMemory(to: ShadowPass.self, capacity: MemoryLayout<shadowPassData>.size)
>> let mainPtr : UnsafeMutablePointer<MainPass> = shadowPtr.advanced(by: 1).withMemoryRebound(to: MainPass.self, capacity: 1) {
>> $0.pointee = mainPassFrameData
>> }
>> var ptr : UnsafeMutablePointer<ObjectData> = mainPtr.advanced(by: 1).withMemoryRebound(to: ObjectData.self, capacity: MemoryLayout< ObjectData >.size) {$0}
>>
>> Latest conversion that make Xcode and Swift 3 smile again...
>>
>> let shadowPtr = constantBufferForFrame.contents().bindMemory(to: ShadowPass.self, capacity: shadowPassData.count)
>> let mainPtr : UnsafeMutablePointer<MainPass> = shadowPtr.advanced(by: 1).withMemoryRebound(to: MainPass.self, capacity: 1) {$0}
>> mainPtr.pointee = mainPassFrameData
>> var ptr : UnsafeMutablePointer<ObjectData> = mainPtr.advanced(by: 1).withMemoryRebound(to: ObjectData.self, capacity: objectsToRender) {$0}
>>
>> Yes… Xcode/Swift3 SIL generation definitely did NOT like my "$0.pointee = mainPassFrameData" statement.
>> Apparently, reassigning the pointee within the closure makes Swift gag out of disgust. Sorry ;-(
>> That’s what I get for trying to be fancy…
>> And fixed my “capacity” issues thanks to some previous posters.
>>
>> Hope this helps anyone trying to get the Metal projects to compile again.
>>
>> At least I got a Radar out of this ;-) Compilers should never burn and crash out like this...
>>
>> Regards to all, Patrice
>>
>>
>>> On Sep 3, 2016, at 1:22 PM, Patrice Kouame via swift-users <swift-users at swift.org> 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> 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> 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> 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> 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> 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
>>>>>>>>
>>>>>>>> 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
>>>>>>>>
>>>>>>>> Jacob
>>>>>>>>
>>>>>>>>> On Fri, Sep 2, 2016 at 11:00 AM, Patrice Kouame via swift-users <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
>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> swift-users mailing list
>>>>>>> swift-users at swift.org
>>>>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>>>> _______________________________________________
>>>>>> swift-users mailing list
>>>>>> swift-users at swift.org
>>>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>> _______________________________________________
>>>> swift-users mailing list
>>>> swift-users at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>
>>> _______________________________________________
>>> swift-users mailing list
>>> swift-users at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>> _______________________________________________
>> swift-users mailing list
>> 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/20160903/1e66c8c9/attachment.html>
More information about the swift-users
mailing list