anchor.diff:                  else
                       yield None
           |]
  +
  +    let connectedDevices = Mod.custom (fun _ -> lock deviceCache (fun () -> Seq.choose id deviceCache |> HRefSet.ofSeq))
  +    let connectedAll = connectedDevices |> ASet.ofMod
  +    let connectedHmds = connectedAll |> ASet.filter (fun d -> d.Type = VrDeviceType.Hmd)
  +    let connectedControllers = connectedAll |> ASet.filter (fun d -> d.Type = VrDeviceType.Controller)
  +
  +    let updateDevice (i : uint32) =
  +        if i >= 0u && i < uint32 deviceCache.Length then
  +            lock deviceCache (fun () ->
  +                let deviceType = system.GetTrackedDeviceClass i
  +                if deviceType <> ETrackedDeviceClass.Invalid then
  +                    let d = VrDevice(system, VrDeviceType.ofETrackedDeviceClass deviceType, int i)
  +                    deviceCache.[int i] <- Some d
  +                else
  +                    deviceCache.[int i] <- None
  +            )
  +            transact connectedDevices.MarkOutdated
  +
  +    let tryGetDevice (i : uint32) =
  +        if i >= 0u && i < uint32 deviceCache.Length then
  +            let mutable changed = false
  +            let result = 
  +                lock deviceCache (fun () ->
  +                    match deviceCache.[int i] with
  +                    | Some d -> Some d
  +                    | None -> 
  +                        let deviceType = system.GetTrackedDeviceClass i
  +                        if deviceType <> ETrackedDeviceClass.Invalid then
  +                            let d = VrDevice(system, VrDeviceType.ofETrackedDeviceClass deviceType, int i)
  +                            deviceCache.[int i] <- Some d
  +                            changed <- true
  +                            Some d
  +                        else
  +                            None
  +                )
  +            if changed then 
  +                transact connectedDevices.MarkOutdated
  +            result
  +        else
  +            None
  +
  +    let getAllDevices() = 
  +        Seq.init (int OpenVR.k_unMaxTrackedDeviceCount) uint32 |> Seq.choose tryGetDevice
   
       static let sEyeIndex = Symbol.Create "EyeIndex"
       static let sRCoord = Symbol.Create "RCoord"
  
positive.code:                 swUpdatePoses.Start()
                  // update all poses
                  transact (fun () ->
                      for d in devices do d.Update(renderPoses)
                  )
  
                  x.UpdatePoses(renderPoses)
  
negative.code:                 ]
          )
  
      //let devices = devicesPerIndex |> Array.choose id
          
      let hmds = getAllDevices() |> Seq.filter (fun d -> d.Type = VrDeviceType.Hmd) |> Seq.toArray 
  
      let getDistortionGeometry (gridSize : V2i) =
          
  