anchor.diff:  
   
   
  -type AdaptiveBufferResource(device : Device, usage : VkBufferUsageFlags, input : IMod<IBuffer>) =
  -    inherit AdaptiveResource<Buffer, VkBuffer>() 
  -
  -    let mutable pointer = NativePtr.create VkBuffer.Null
  -    let mutable last : Option<IBuffer * Buffer> = None
  +
  +
  +
  +// level 0 resources
  +
  +[<AbstractClass>]
  +type AdaptiveRecreateResource<'a, 'h, 'n when 'h : equality and 'n : unmanaged>(input : IMod<'a>) as this =
  +    inherit AdaptiveResource<'h, 'n>()
  +    
  +    let mutable pointer = NativePtr.create Unchecked.defaultof<'n>
  +    let mutable last : Option<'a * 'h> = None
       let mutable locks = HSet.empty
  -
  -    let tryUpdateInPlace (old : Buffer) (n : IBuffer) =
  -        false
  -
  -    override x.Handle = 
  -        match last with
  -            | Some (_,h) -> h
  -            | None -> failwith "[Buffer] cannot get handle for disposed buffer"
  -            
  -    override x.Pointer = pointer
  -
  -    override x.LockedInputs = locks
  -
  -    override x.Destroy() =
  -        match last with
  -            | Some (_,b) ->
  -                x.DestroyCallbacks()
  -                device.Delete b
  -                last <- None
  -                locks <- HSet.empty
  -                NativePtr.free pointer
  -                pointer <- NativePtr.zero
  -            | _ ->
  -                ()
  -
  -    override x.PerformUpdate(token : AdaptiveToken) =
  +    let mutable ownsHandle = false
  +
  +    do this.update AdaptiveResource.CurrentToken |> ignore           
  +
  +    member private x.update(token : AdaptiveToken) : UpdateKind =
           let current = input.GetValue token
  -
  -        match current with
  +        let currentObj = current :> obj
  +
  +        match currentObj with
               | :? ILockedResource as l ->
                   locks <- HSet.ofList [l]
               | _ ->
                   locks <- HSet.empty
   
  +        match currentObj with
  +            | :? 'h as handle ->
  +                match last with
  +                    | Some (_,o) when o = handle && not ownsHandle ->
  +                        UpdateKind.Untouched
  +
  +                    | Some (_,o) -> 
  +                        if ownsHandle then
  +                            x.Destroy o
  +                            ownsHandle <- false
  +                        last <- Some (current, handle)
  +                        NativePtr.write pointer (x.View handle)
  +                        UpdateKind.HandleChanged
  +
  +                    | None ->
  +                        ownsHandle <- false
  +                        last <- Some (current, handle)
  +                        NativePtr.write pointer (x.View handle)
  +                        UpdateKind.HandleChanged
  +            | _ ->
  +                match last with
  +                    | None ->
  +                        let n = x.Create current
  +                        ownsHandle <- true
  +                        last <- Some (current, n)
  +                        NativePtr.write pointer (x.View n)
  +                        UpdateKind.HandleChanged
  +                    | Some (oi, oh) when Unchecked.equals oi current && ownsHandle ->
  +                        UpdateKind.Untouched
  +                    | Some (oi, oh) ->
  +                        if ownsHandle then x.Destroy oh
  +
  +                        let n = x.Create current
  +                        ownsHandle <- true
  +                        last <- Some (current, n)
  +                        NativePtr.write pointer (x.View n)
  +
  +                        UpdateKind.HandleChanged
  +             
  +    abstract member Destroy : 'h -> unit
  +    abstract member Create : 'a -> 'h
  +    abstract member View : 'h -> 'n
  +
  +    override x.LockedInputs = locks
  +    override x.Handle =
  +        match last with
  +            | Some (_,h) -> h
  +            | None -> failwith "cannot access disposed resource"
  +
  +    override x.Pointer = pointer
  +        
  +    override x.Destroy() =
  +        match last with
  +            | Some(_,h) ->
  +                if ownsHandle then x.Destroy h
  +                last <- None
  +                locks <- HSet.empty
  +                ownsHandle <- false
  +                NativePtr.free pointer
  +            | _ ->
  +                ()
  +
  +    override x.PerformUpdate t = x.update t
  +  
  +[<AbstractClass>]
  +type AdaptiveRecreateResource<'a, 'b, 'h, 'n when 'h : equality and 'n : unmanaged>(ia : IMod<'a>, ib : IMod<'b>) as this =
  +    inherit AdaptiveResource<'h, 'n>()
  +    
  +    let mutable pointer = NativePtr.create Unchecked.defaultof<'n>
  +    let mutable last : Option<'a * 'b * 'h> = None
  +    do this.update AdaptiveResource.CurrentToken |> ignore           
  +
  +    member private x.update(token : AdaptiveToken) : UpdateKind =
  +        let ca = ia.GetValue token
  +        let cb = ib.GetValue token
  +
           match last with
               | None ->
  -                let n = device.CreateBuffer(usage, current)
  -                NativePtr.write pointer n.Handle
  -                last <- Some(current, n)
  +                let n = x.Create(ca, cb)
  +                last <- Some (ca, cb, n)
  +                NativePtr.write pointer (x.View n)
                   UpdateKind.HandleChanged
  -
  -            | Some(old,_) when old = current ->
  +            | Some (oa, ob, oh) when Unchecked.equals oa ca && Unchecked.equals ob cb ->
                   UpdateKind.Untouched
  -
  -            | Some(_,o) ->
  -                if tryUpdateInPlace o current then
  -                    UpdateKind.ContentChanged
  -                else
  -                    device.Delete o
  -                    let n = device.CreateBuffer(usage, current)
  -                    NativePtr.write pointer n.Handle
  -                    last <- Some(current, n)
  -                    UpdateKind.HandleChanged
  +            | Some (oa, ob, oh) ->
  +                x.Destroy oh
  +                let n = x.Create(ca, cb)
  +                last <- Some (ca, cb, n)
  +                NativePtr.write pointer (x.View n)
  +
  +                UpdateKind.HandleChanged
  +             
  +    abstract member Destroy : 'h -> unit
  +    abstract member Create : 'a * 'b -> 'h
  +    abstract member View : 'h -> 'n
  +
  +    override x.LockedInputs = HSet.empty
  +    override x.Handle =
  +        match last with
  +            | Some (_,_,h) -> h
  +            | None -> failwith "cannot access disposed resource"
  +
  +    override x.Pointer = pointer
  +        
  +    override x.Destroy() =
  +        match last with
  +            | Some(_,_,h) ->
  +                x.Destroy h
  +                last <- None
  +                NativePtr.free pointer
  +            | _ ->
  +                ()
  +
  +    override x.PerformUpdate t = x.update t
  +   
  +[<AbstractClass>]
  +type AdaptiveRecreateResource<'a, 'b, 'c, 'h, 'n when 'h : equality and 'n : unmanaged>(ia : IMod<'a>, ib : IMod<'b>, ic : IMod<'c>) as this =
  +    inherit AdaptiveResource<'h, 'n>()
  +    
  +    let mutable pointer = NativePtr.create Unchecked.defaultof<'n>
  +    let mutable last : Option<'a * 'b * 'c * 'h> = None
  +    do this.update AdaptiveResource.CurrentToken |> ignore           
  +
  +    member private x.update(token : AdaptiveToken) : UpdateKind =
  +        let ca = ia.GetValue token
  +        let cb = ib.GetValue token
  +        let cc = ic.GetValue token
  +
  +        match last with
  +            | None ->
  +                let n = x.Create(ca, cb, cc)
  +                last <- Some (ca, cb, cc, n)
  +                NativePtr.write pointer (x.View n)
  +                UpdateKind.HandleChanged
  +            | Some (oa, ob, oc, oh) when Unchecked.equals oa ca && Unchecked.equals ob cb && Unchecked.equals oc cc ->
  +                UpdateKind.Untouched
  +            | Some (_,_,_,oh) ->
  +                x.Destroy oh
  +                let n = x.Create(ca, cb, cc)
  +                last <- Some (ca, cb, cc, n)
  +                NativePtr.write pointer (x.View n)
  +
  +                UpdateKind.HandleChanged
  +             
  +    abstract member Destroy : 'h -> unit
  +    abstract member Create : 'a * 'b * 'c -> 'h
  +    abstract member View : 'h -> 'n
  +
  +    override x.LockedInputs = HSet.empty
  +    override x.Handle =
  +        match last with
  +            | Some (_,_,_,h) -> h
  +            | None -> failwith "cannot access disposed resource"
  +
  +    override x.Pointer = pointer
  +        
  +    override x.Destroy() =
  +        match last with
  +            | Some(_,_,_,h) ->
  +                x.Destroy h
  +                last <- None
  +                NativePtr.free pointer
  +            | _ ->
  +                ()
  +
  +    override x.PerformUpdate t = x.update t 
  +
  +type AdaptiveBufferResource(device : Device, usage : VkBufferUsageFlags, input : IMod<IBuffer>) =
  +    inherit AdaptiveRecreateResource<IBuffer, Buffer, VkBuffer>(input) 
  +    
  +    override x.Create (b : IBuffer) = device.CreateBuffer(usage, b)
  +    override x.Destroy (b : Buffer) = device.Delete b
  +    override x.View (b : Buffer) = b.Handle
  +
  +type AdaptiveIndirectBufferResource(device : Device, indexed : bool, input : IMod<IIndirectBuffer>) =
  +    inherit AdaptiveRecreateResource<IIndirectBuffer, IndirectBuffer, VkBuffer>(input) 
  +
  +    override x.Create (b : IIndirectBuffer) = device.CreateIndirectBuffer(indexed, b)
  +    override x.Destroy (b : IndirectBuffer) = device.Delete b
  +    override x.View (b : IndirectBuffer) = b.Handle
  +
  +
  +type AdaptiveUniformBufferResource(device : Device, layout : UniformBufferLayout, writers : list<IMod * UniformWriters.IWriter>) =
  +    inherit AdaptiveResource<UniformBuffer, VkBuffer>()
  +
  +    let buffer = device.CreateUniformBuffer(layout)
  +    do  let t = AdaptiveResource.CurrentToken
  +        for (m,w) in writers do w.Write(t, m, buffer.Storage.Pointer)
  +
  +    let pointer = NativePtr.create buffer.Handle
  +
  +    override x.LockedInputs = HSet.empty
  +    override x.Handle = buffer
  +    override x.Pointer = pointer
  +    override x.PerformUpdate(t : AdaptiveToken) =
  +        for (m,w) in writers do w.Write(t, m, buffer.Storage.Pointer)
  +        UpdateKind.ContentChanged
  +
  +    override x.Destroy() =
  +        device.Delete buffer
  +
  +type AdaptiveImageResource(device : Device, input : IMod<ITexture>) =
  +    inherit AdaptiveRecreateResource<ITexture, Image, VkImage>(input) 
  +    
  +    override x.Create (b : ITexture) = device.CreateImage(b)
  +    override x.Destroy (b : Image) = device.Delete b
  +    override x.View (b : Image) = b.Handle
  +
  +type AdaptiveSamplerResource(device : Device, input : IMod<SamplerStateDescription>) =
  +    inherit AdaptiveRecreateResource<SamplerStateDescription, Sampler, VkSampler>(input) 
  +    
  +    override x.Create (b : SamplerStateDescription) = device.CreateSampler(b)
  +    override x.Destroy (b : Sampler) = device.Delete b
  +    override x.View (b : Sampler) = b.Handle
  +
  +type AdaptiveShaderProgramResource(device : Device, renderPass : RenderPass, input : IMod<ISurface>) =
  +    inherit AdaptiveRecreateResource<ISurface, ShaderProgram, nativeint>(input) 
  +        
  +    override x.Create (b : ISurface) = device.CreateShaderProgram(renderPass, b)
  +    override x.Destroy (b : ShaderProgram) = device.Delete b
  +    override x.View (b : ShaderProgram) = 0n
  +
  +
  +type AdaptiveInputAssemblyStateResource(input : IMod<IndexedGeometryMode>) =
  +    inherit AdaptiveRecreateResource<IndexedGeometryMode, VkPipelineInputAssemblyStateCreateInfo, VkPipelineInputAssemblyStateCreateInfo>(input)
  +
  +    override x.Create m = 
  +        let res = InputAssemblyState.ofIndexedGeometryMode m
  +        VkPipelineInputAssemblyStateCreateInfo(
  +            VkStructureType.PipelineInputAssemblyStateCreateInfo, 0n,
  +            VkPipelineInputAssemblyStateCreateFlags.MinValue,
  +            res.topology,
  +            (if res.restartEnable then 1u else 0u)
  +        )
  +        
  +    override x.Destroy _ = ()
  +    override x.View h = h
  +    
  +type AdaptiveDepthStencilStateResource(depthWrite : bool, depth : IMod<DepthTestMode>, stencil : IMod<StencilMode>) =
  +    inherit AdaptiveRecreateResource<DepthTestMode, StencilMode, VkPipelineDepthStencilStateCreateInfo, VkPipelineDepthStencilStateCreateInfo>(depth, stencil)
  +
  +    override x.Create(depth, stencil) =
  +        let depth = DepthState.create depthWrite depth
  +        let stencil = StencilState.create stencil
  +
  +        VkPipelineDepthStencilStateCreateInfo(
  +            VkStructureType.PipelineDepthStencilStateCreateInfo, 0n,
  +            VkPipelineDepthStencilStateCreateFlags.MinValue,
  +            (if depth.testEnabled then 1u else 0u),
  +            (if depth.writeEnabled then 1u else 0u),
  +            depth.compare,
  +            (if depth.boundsTest then 1u else 0u),
  +            (if stencil.enabled then 1u else 0u),
  +            stencil.front,
  +            stencil.back,
  +            float32 depth.depthBounds.Min,
  +            float32 depth.depthBounds.Max
  +        )
  +
  +    override x.Destroy _ = ()
  +    override x.View a = a
  +
  +type AdaptiveRasterizerStateResource(depth : IMod<DepthTestMode>, cull : IMod<CullMode>, fill : IMod<FillMode>) =
  +    inherit AdaptiveRecreateResource<DepthTestMode, CullMode, FillMode, VkPipelineRasterizationStateCreateInfo, VkPipelineRasterizationStateCreateInfo>(depth, cull, fill)
  +
  +    override x.Create(depth, cull, fill) =
  +        let state = RasterizerState.create false depth cull fill
  +
  +        VkPipelineRasterizationStateCreateInfo(
  +            VkStructureType.PipelineRasterizationStateCreateInfo, 0n,
  +            VkPipelineRasterizationStateCreateFlags.MinValue,
  +            (if state.depthClampEnable then 1u else 0u),
  +            0u,
  +            state.polygonMode,
  +            state.cullMode,
  +            state.frontFace,
  +            (if state.depthBiasEnable then 1u else 0u),
  +            float32 state.depthBiasConstantFactor,
  +            float32 state.depthBiasClamp,
  +            float32 state.depthBiasSlopeFactor,
  +            float32 state.lineWidth
  +        )
  +
  +    override x.Destroy _ = ()
  +    override x.View a = a
  +
  +type AdaptiveColorBlendStateResource(writeMasks : bool[], blend : IMod<BlendMode>) =
  +    inherit AdaptiveRecreateResource<BlendMode, VkPipelineColorBlendStateCreateInfo, VkPipelineColorBlendStateCreateInfo>(blend)
  +
  +    override x.Create(blend) =
  +        let state = ColorBlendState.create writeMasks writeMasks.Length blend
  +        let pAttStates = NativePtr.alloc writeMasks.Length
  +
  +        for i in 0 .. state.attachmentStates.Length - 1 do
  +            let s = state.attachmentStates.[i]
  +            let att = 
  +                VkPipelineColorBlendAttachmentState(
  +                    (if s.enabled then 1u else 0u),
  +                    s.srcFactor,
  +                    s.dstFactor,
  +                    s.operation,
  +                    s.srcFactorAlpha,
  +                    s.dstFactorAlpha,
  +                    s.operationAlpha,
  +                    s.colorWriteMask
  +                )
  +            NativePtr.set pAttStates i att
  +
  +
  +        VkPipelineColorBlendStateCreateInfo(
  +            VkStructureType.PipelineColorBlendStateCreateInfo, 0n,
  +            VkPipelineColorBlendStateCreateFlags.MinValue,
  +            (if state.logicOpEnable then 1u else 0u),
  +            state.logicOp,
  +            uint32 writeMasks.Length,
  +            pAttStates,
  +            state.constants
  +        )
  +
  +    override x.Destroy h =
  +        NativePtr.free h.pAttachments
  +
  +    override x.View h = h
  +
  +type AdaptiveDirectDrawCallResource(indexed : bool, calls : IMod<list<DrawCallInfo>>) =
  +    inherit AdaptiveRecreateResource<list<DrawCallInfo>, DrawCall, DrawCall>(calls)
  +
  +    override x.Create(calls : list<DrawCallInfo>) =
  +        DrawCall.Direct(indexed, List.toArray calls)
  +
  +    override x.Destroy h = h.Dispose()
  +    override x.View a = a
  +    
  +
  +// derived resources
  +
   
   type DescriptorSetResource(pool : DescriptorPool, layout : DescriptorSetLayout, bindings : AdaptiveDescriptor[]) =
       inherit AbstractResource<DescriptorSet, VkDescriptorSet>(bindings |> Seq.collect AdaptiveDescriptor.resources)
  
positive.code:     abstract member PerformUpdate : AdaptiveToken -> UpdateKind
  
      override x.PerformUpdate() =
          self.EvaluateIfNeeded AdaptiveToken.Top UpdateKind.Untouched (fun t ->
              x.PerformUpdate t
          )
  
  
negative.code:                         if all.Contains o then
                              queue.Add(o.Level, o) |> ignore
      
      member x.Use(t : AdaptiveToken, action : unit -> 'r) =
          x.EvaluateAlways t (fun t ->
              AdaptiveResource.Evaluate(t, action)
          )
  
      member x.Update(t : AdaptiveToken) =
          x.EvaluateIfNeeded t (fun t -> 
              AdaptiveResource.Evaluate(t, fun () ->
                  update()
              )
          )
  
      member x.Add(r : IResource) =
          if all.Add r then
  