anchor.diff:  
       end
   
  -
  -module TextureExtensionsNew =
  -    
  +[<AutoOpen>]
  +module private ResourceCounts =
  +
  +    // PositiveX = 0,
  +    // NegativeX = 1,
  +    // PositiveY = 2,
  +    // NegativeY = 3,
  +    // PositiveZ = 4,
  +    // NegativeZ = 5,
  +    // cubeSides are sorted like in their implementation (making some things easier)
  +    let cubeSides =
  +        [|
  +            CubeSide.PositiveX, TextureTarget.TextureCubeMapPositiveX
  +            CubeSide.NegativeX, TextureTarget.TextureCubeMapNegativeX
  +
  +            CubeSide.PositiveY, TextureTarget.TextureCubeMapNegativeY
  +            CubeSide.NegativeY, TextureTarget.TextureCubeMapPositiveY
  +                
  +            CubeSide.PositiveZ, TextureTarget.TextureCubeMapPositiveZ
  +            CubeSide.NegativeZ, TextureTarget.TextureCubeMapNegativeZ
  +        |]
  +
  +
  +    let addTexture (ctx:Context) size =
  +        Interlocked.Increment(&ctx.MemoryUsage.TextureCount) |> ignore
  +        Interlocked.Add(&ctx.MemoryUsage.TextureMemory,size) |> ignore
  +
  +    let removeTexture (ctx:Context) size =
  +        Interlocked.Decrement(&ctx.MemoryUsage.TextureCount)  |> ignore
  +        Interlocked.Add(&ctx.MemoryUsage.TextureMemory,-size) |> ignore
  +
  +    let updateTexture (ctx:Context) oldSize newSize =
  +        Interlocked.Add(&ctx.MemoryUsage.TextureMemory,newSize-oldSize) |> ignore
  +
  +    let texSizeInBytes (size : V3i, t : TextureFormat, samples : int) =
  +        let pixelCount = (int64 size.X) * (int64 size.Y) * (int64 size.Z) * (int64 samples)
  +        pixelCount * (int64 (InternalFormat.getSizeInBits (unbox (int t)))) / 8L
  +
  +module TextureTarget =
  +    let ofParameters (dim : TextureDimension) (isArray : bool) (isMS : bool) =
  +        match dim, isArray, isMS with
  +
  +            | TextureDimension.Texture1D,      _,       true     -> failwith "Texture1D cannot be multisampled"
  +            | TextureDimension.Texture1D,      true,    _        -> TextureTarget.Texture1DArray
  +            | TextureDimension.Texture1D,      false,   _        -> TextureTarget.Texture1D
  +                                                   
  +            | TextureDimension.Texture2D,      false,   false    -> TextureTarget.Texture2D
  +            | TextureDimension.Texture2D,      true,    false    -> TextureTarget.Texture2DArray
  +            | TextureDimension.Texture2D,      false,   true     -> TextureTarget.Texture2DMultisample
  +            | TextureDimension.Texture2D,      true,    true     -> TextureTarget.Texture2DMultisampleArray
  +                                                   
  +            | TextureDimension.Texture3D,      false,   false    -> TextureTarget.Texture3D
  +            | TextureDimension.Texture3D,      _,       _        -> failwith "Texture3D cannot be multisampled or an array"
  +                                                  
  +            | TextureDimension.TextureCube,   false,    false    -> TextureTarget.TextureCubeMap
  +            | TextureDimension.TextureCube,   true,     false    -> TextureTarget.TextureCubeMapArray
  +            | TextureDimension.TextureCube,   _,        true     -> failwith "TextureCube cannot be multisampled"
  +
  +            | _ -> failwithf "unknown texture dimension: %A" dim
  +
  +    let ofTexture (texture : Texture) =
  +        ofParameters texture.Dimension texture.IsArray texture.IsMultisampled
  +
  +
  +[<AutoOpen>]
  +module TextureCreationExtensions =
  +    type Context with 
  +        member x.CreateTexture1D(size : int, mipMapLevels : int, t : TextureFormat) =
  +            using x.ResourceLock (fun _ ->
  +                let h = GL.GenTexture()
  +                GL.Check "could not create texture"
  +
  +                addTexture x 0L
  +                let tex = Texture(x, h, TextureDimension.Texture1D, mipMapLevels, 1, V3i.Zero, 1, t, 0L, false)
  +                x.UpdateTexture1D(tex, size, mipMapLevels, t)
  +
  +                tex
  +            )
  +
  +        member x.CreateTexture2D(size : V2i, mipMapLevels : int, t : TextureFormat, samples : int) =
  +            using x.ResourceLock (fun _ ->
  +                let h = GL.GenTexture()
  +                GL.Check "could not create texture"
  +                
  +                addTexture x 0L
  +                let tex = Texture(x, h, TextureDimension.Texture2D, mipMapLevels, 1, V3i.Zero, 1, t, 0L, false)
  +
  +                x.UpdateTexture2D(tex, size, mipMapLevels, t, samples)
  +
  +                tex
  +            )
  +
  +        member x.CreateTexture3D(size : V3i, mipMapLevels : int, t : TextureFormat) =
  +            using x.ResourceLock (fun _ ->
  +                let h = GL.GenTexture()
  +                GL.Check "could not create texture"
  +
  +                addTexture x 0L
  +                let tex = Texture(x, h, TextureDimension.Texture3D, mipMapLevels, 1, V3i.Zero, 1, t, 0L, false)
  +                x.UpdateTexture3D(tex, size, mipMapLevels, t)
  +
  +                tex
  +            )
  +
  +        member x.CreateTextureCube(size : V2i, mipMapLevels : int, t : TextureFormat, samples : int) =
  +            using x.ResourceLock (fun _ ->
  +                let h = GL.GenTexture()
  +                GL.Check "could not create texture"
  +
  +                addTexture x 0L
  +                let tex = Texture(x, h, TextureDimension.TextureCube, mipMapLevels, 1, V3i(size.X, size.Y, 0), 1, t, 0L, false)
  +                x.UpdateTextureCube(tex, size, mipMapLevels, t, samples)
  +
  +                tex
  +            )
  +
  +        member x.CreateTexture1DArray(size : int, count : int, mipMapLevels : int, t : TextureFormat) =
  +            using x.ResourceLock (fun _ ->
  +                let h = GL.GenTexture()
  +                GL.Check "could not create texture"
  +
  +                addTexture x 0L
  +                let tex = Texture(x, h, TextureDimension.Texture1D, mipMapLevels, 1, V3i.Zero, 1, t, 0L, false)
  +                x.UpdateTexture1DArray(tex, size, count, mipMapLevels, t)
  +
  +                tex
  +            ) 
  +
  +        member x.CreateTexture2DArray(size : V2i, count : int, mipMapLevels : int, t : TextureFormat, samples : int) =
  +            using x.ResourceLock (fun _ ->
  +                let h = GL.GenTexture()
  +                GL.Check "could not create texture"
  +                
  +                addTexture x 0L
  +                let tex = Texture(x, h, TextureDimension.Texture2D, mipMapLevels, 1, V3i.Zero, 1, t, 0L, false)
  +
  +                x.UpdateTexture2DArray(tex, size, count, mipMapLevels, t, samples)
  +
  +                tex
  +            )
  +            
  +        member x.UpdateTexture1D(tex : Texture, size : int, mipMapLevels : int, t : TextureFormat) =
  +            using x.ResourceLock (fun _ ->
  +                if tex.ImmutableFormat then
  +                    failwith "cannot update format/size for immutable texture"
  +
  +                GL.BindTexture(TextureTarget.Texture1D, tex.Handle)
  +                GL.Check "could not bind texture"
  +
  +                let sizeInBytes = texSizeInBytes(V3i(size, 1, 1), t, 1)
  +                updateTexture tex.Context tex.SizeInBytes sizeInBytes
  +                tex.SizeInBytes <- sizeInBytes
  +  
  +                GL.TexStorage1D(TextureTarget1d.Texture1D, mipMapLevels, unbox (int t), size)
  +                GL.Check "could not allocate texture"
  +
  +                GL.BindTexture(TextureTarget.Texture1D, 0)
  +                GL.Check "could not unbind texture"
  +
  +                tex.MipMapLevels <- mipMapLevels
  +                tex.Dimension <- TextureDimension.Texture1D
  +                tex.Size <- V3i(size, 0, 0)
  +                tex.Format <- t
  +                tex.ImmutableFormat <- true
  +            )
  +
  +        member x.UpdateTexture2D(tex : Texture, size : V2i, mipMapLevels : int, t : TextureFormat, samples : int) =
  +            using x.ResourceLock (fun _ ->
  +                if tex.ImmutableFormat then
  +                    failwith "cannot update format/size for immutable texture"
  +
  +                let target =
  +                    if samples = 1 then TextureTarget.Texture2D
  +                    else TextureTarget.Texture2DMultisample
  +
  +                GL.BindTexture(target, tex.Handle)
  +                GL.Check "could not bind texture"
  +
  +                let sizeInBytes = texSizeInBytes(size.XYI, t, samples)
  +                updateTexture tex.Context tex.SizeInBytes sizeInBytes
  +                tex.SizeInBytes <- sizeInBytes
  +
  +                if samples = 1 then
  +                    GL.TexStorage2D(TextureTarget2d.Texture2D, mipMapLevels, unbox (int t), size.X, size.Y)
  +                else
  +                    if mipMapLevels > 1 then failwith "multisampled textures cannot have MipMaps"
  +                    GL.TexStorage2DMultisample(TextureTargetMultisample2d.Texture2DMultisample, samples, unbox (int t), size.X, size.Y, false)
  +
  +                GL.Check "could not allocate texture"
  +
  +                GL.TexParameter(target, TextureParameterName.TextureMaxLevel, mipMapLevels)
  +                GL.TexParameter(target, TextureParameterName.TextureBaseLevel, 0)
  +
  +
  +                GL.BindTexture(target, 0)
  +                GL.Check "could not unbind texture"
  +
  +                tex.MipMapLevels <- mipMapLevels
  +                tex.Dimension <- TextureDimension.Texture2D
  +                tex.Multisamples <- samples
  +                tex.Count <- 1
  +                tex.Size <- V3i(size.X, size.Y, 0)
  +                tex.Format <- t
  +                tex.ImmutableFormat <- true
  +            )
  +
  +        member x.UpdateTexture3D(tex : Texture, size : V3i, mipMapLevels : int, t : TextureFormat) =
  +            using x.ResourceLock (fun _ ->
  +                if tex.ImmutableFormat then
  +                    failwith "cannot update format/size for immutable texture"
  +
  +                GL.BindTexture(TextureTarget.Texture3D, tex.Handle)
  +                GL.Check "could not bind texture"
  +
  +                let ifmt = unbox (int t) 
  +
  +                let sizeInBytes = texSizeInBytes(size, t, 1)
  +                updateTexture tex.Context tex.SizeInBytes sizeInBytes
  +                tex.SizeInBytes <- sizeInBytes
  +
  +                GL.TexStorage3D(TextureTarget3d.Texture3D, mipMapLevels, ifmt, size.X, size.Y, size.Z)
  +                GL.Check "could not allocate texture"
  +
  +                GL.BindTexture(TextureTarget.Texture3D, 0)
  +                GL.Check "could not unbind texture"
  +
  +                tex.MipMapLevels <- mipMapLevels
  +                tex.Dimension <- TextureDimension.Texture3D
  +                tex.Count <- 1
  +                tex.Multisamples <- 1
  +                tex.Size <- size
  +                tex.Format <- t
  +                tex.ImmutableFormat <- true
  +            )
  +
  +        member x.UpdateTextureCube(tex : Texture, size : V2i, mipMapLevels : int, t : TextureFormat, samples : int) =
  +            using x.ResourceLock (fun _ ->
  +                if tex.ImmutableFormat then
  +                    failwith "cannot update format/size for immutable texture"
  +
  +                GL.BindTexture(TextureTarget.TextureCubeMap, tex.Handle)
  +                GL.Check "could not bind texture"
  +
  +                if samples = 1 then
  +                    GL.TexStorage2D(TextureTarget2d.TextureCubeMap, mipMapLevels, unbox (int t), size.X, size.Y)
  +                else
  +                    if mipMapLevels > 1 then failwith "multisampled textures cannot have MipMaps"
  +                    // TODO: verify that this works!!
  +                    for f in 0..5 do
  +                        let target = int TextureTarget.TextureCubeMapPositiveX + f
  +                        GL.TexImage2DMultisample(unbox target, samples, unbox (int t), size.X, size.Y, true)
  +
  +                GL.BindTexture(TextureTarget.TextureCubeMap, 0)
  +                GL.Check "could not unbind texture"
  +
  +                let sizeInBytes = texSizeInBytes(size.XYI, t, samples)
  +                let sizeInBytes = sizeInBytes * 6L
  +                updateTexture tex.Context tex.SizeInBytes sizeInBytes
  +                tex.SizeInBytes <- sizeInBytes
  +
  +                tex.MipMapLevels <- mipMapLevels
  +                tex.Dimension <- TextureDimension.TextureCube
  +                tex.Size <- V3i(size.X, size.Y, 0)
  +                tex.Count <- 1
  +                tex.Multisamples <- samples
  +                tex.Format <- t
  +                tex.ImmutableFormat <- true
  +            )
  +
  +        member x.UpdateTexture2DArray(tex : Texture, size : V2i, count : int, mipMapLevels : int, t : TextureFormat, samples : int) =
  +            using x.ResourceLock (fun _ ->
  +                if tex.ImmutableFormat then
  +                    failwith "cannot update format/size for immutable texture"
  +
  +                let target =
  +                    if samples = 1 then TextureTarget.Texture2DArray
  +                    else TextureTarget.Texture2DMultisampleArray
  +
  +                GL.BindTexture(target, tex.Handle)
  +                GL.Check "could not bind texture"
  +
  +
  +                let sizeInBytes = texSizeInBytes(size.XYI, t, samples) * (int64 count)
  +                updateTexture tex.Context tex.SizeInBytes sizeInBytes
  +                tex.SizeInBytes <- sizeInBytes // TODO check multisampling
  +
  +                if samples = 1 then
  +                    GL.TexStorage3D(TextureTarget3d.Texture2DArray, mipMapLevels, unbox (int t), size.X, size.Y, count)
  +                else
  +                    if mipMapLevels > 1 then failwith "multisampled textures cannot have MipMaps"
  +                    GL.TexStorage3DMultisample(TextureTargetMultisample3d.Texture2DMultisampleArray, samples, unbox (int t), size.X, size.Y, count, true)
  +  
  +                GL.Check "could not allocate texture"
  +
  +                GL.TexParameter(target, TextureParameterName.TextureMaxLevel, mipMapLevels)
  +                GL.TexParameter(target, TextureParameterName.TextureBaseLevel, 0)
  +
  +
  +                GL.BindTexture(target, 0)
  +                GL.Check "could not unbind texture"
  +
  +                tex.MipMapLevels <- mipMapLevels
  +                tex.Dimension <- TextureDimension.Texture2D
  +                tex.Count <- count
  +                tex.Multisamples <- samples
  +                tex.Size <- V3i(size.X, size.Y, 0)
  +                tex.Format <- t
  +                tex.ImmutableFormat <- true
  +            )
  +
  +        member x.UpdateTexture1DArray(tex : Texture, size : int, count : int, mipMapLevels : int, t : TextureFormat) =
  +            using x.ResourceLock (fun _ ->
  +                if tex.ImmutableFormat then
  +                    failwith "cannot update format/size for immutable texture"
  +
  +                GL.BindTexture(TextureTarget.Texture1DArray, tex.Handle)
  +                GL.Check "could not bind texture"
  +
  +                let sizeInBytes = texSizeInBytes(V3i(size, 1, 1), t, 1) * (int64 count)
  +                updateTexture tex.Context tex.SizeInBytes sizeInBytes
  +                tex.SizeInBytes <- sizeInBytes
  +  
  +                GL.TexStorage2D(TextureTarget2d.Texture1DArray, mipMapLevels, unbox (int t), size, count)
  +                GL.Check "could not allocate texture"
  +
  +                GL.BindTexture(TextureTarget.Texture1DArray, 0)
  +                GL.Check "could not unbind texture"
  +
  +                tex.MipMapLevels <- mipMapLevels
  +                tex.Dimension <- TextureDimension.Texture1D
  +                tex.Count <- count
  +                tex.Multisamples <- 1
  +                tex.Size <- V3i(size, 0, 0)
  +                tex.Format <- t
  +                tex.ImmutableFormat <- true
  +            )
  +
  +        member x.CreateTextureView(orig : Texture, levels : Range1i, slices : Range1i) =
  +            using x.ResourceLock (fun _ ->
  +                if not orig.ImmutableFormat then
  +                    failwithf "cannot create texture-views for mutable textures"
  +
  +                let handle = GL.GenTexture()
  +                GL.Check "could not create texture"
  +
  +                let dim =
  +                    match orig.Dimension, orig.Count with
  +                        | TextureDimension.TextureCube, 1 -> 
  +                            if slices.Min <> slices.Max then failwithf "cannot take multiple slices from CubeMap"
  +                            TextureDimension.Texture2D
  +                        | d,_ -> d
  +
  +                let tex = Texture(x, handle, dim, 1 + levels.Max - levels.Min, orig.Multisamples, orig.Size, 1 + slices.Max - slices.Min, orig.Format, 0L, true)
  +                let target = TextureTarget.ofTexture tex
  +                  
  +                GL.TextureView(
  +                    handle,
  +                    target,
  +                    orig.Handle,
  +                    unbox (int orig.Format),
  +                    levels.Min, 1 + levels.Max - levels.Min,
  +                    slices.Min, 1
  +                )
  +                GL.Check "could not create texture view"
  +
  +                tex
  +            )
  +
  +        member x.Delete(t : Texture) =
  +            using x.ResourceLock (fun _ ->
  +                removeTexture x t.SizeInBytes
  +                GL.DeleteTexture(t.Handle)
  +                GL.Check "could not delete texture"
  +            )
  +            
  +        member x.Blit(src : Texture, srcLevel : int, srcSlice : int, srcRegion : Box2i, dst : Texture, dstLevel : int, dstSlice : int, dstRegion : Box2i, linear : bool) =
  +            using x.ResourceLock (fun _ ->
  +                let fSrc = GL.GenFramebuffer()
  +                GL.Check "could not create framebuffer"
  +                let fDst = GL.GenFramebuffer()
  +                GL.Check "could not create framebuffer"
  +
  +                GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, fSrc)
  +                GL.Check "could not bind framebuffer"
  +                if src.Count > 1 then GL.FramebufferTextureLayer(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, src.Handle, srcLevel, srcSlice)
  +                else GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, src.Handle, srcLevel)
  +                GL.Check "could not attach texture to framebuffer"
  +
  +                let srcCheck = GL.CheckFramebufferStatus(FramebufferTarget.ReadFramebuffer)
  +                if srcCheck <> FramebufferErrorCode.FramebufferComplete then
  +                    failwithf "could not create input framebuffer: %A" srcCheck
  +
  +                GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, fDst)
  +                GL.Check "could not bind framebuffer"
  +
  +                if src.Count > 1 then GL.FramebufferTextureLayer(FramebufferTarget.DrawFramebuffer, FramebufferAttachment.ColorAttachment0, dst.Handle, dstLevel, dstSlice)
  +                else GL.FramebufferTexture(FramebufferTarget.DrawFramebuffer, FramebufferAttachment.ColorAttachment0, dst.Handle, dstLevel)
  +                GL.Check "could not attach texture to framebuffer"
  +
  +                let dstCheck = GL.CheckFramebufferStatus(FramebufferTarget.DrawFramebuffer)
  +                if dstCheck <> FramebufferErrorCode.FramebufferComplete then
  +                    failwithf "could not create output framebuffer: %A" dstCheck
  +
  +                GL.BlitFramebuffer(
  +                    srcRegion.Min.X, srcRegion.Min.Y,
  +                    srcRegion.Max.X, srcRegion.Max.Y,
  +
  +                    dstRegion.Min.X, dstRegion.Min.Y,
  +                    dstRegion.Max.X, dstRegion.Max.Y,
  +
  +                    ClearBufferMask.ColorBufferBit,
  +                    (if linear then BlitFramebufferFilter.Linear else BlitFramebufferFilter.Nearest)
  +                )
  +                GL.Check "could blit framebuffer"
  +
  +                GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, 0)
  +                GL.Check "could unbind framebuffer"
  +
  +                GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0)
  +                GL.Check "could unbind framebuffer"
  +
  +                GL.DeleteFramebuffer(fSrc)
  +                GL.Check "could delete framebuffer"
  +
  +                GL.DeleteFramebuffer(fDst)
  +                GL.Check "could delete framebuffer"
  +
  +            )
  +
  +        member x.Copy(src : Texture, srcLevel : int, srcSlice : int, srcOffset : V2i, dst : Texture, dstLevel : int, dstSlice : int, dstOffset : V2i, size : V2i) =
  +            using x.ResourceLock (fun _ ->
  +                let fSrc = GL.GenFramebuffer()
  +                GL.Check "could not create framebuffer"
  +
  +                GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, fSrc)
  +                GL.Check "could not bind framebuffer"
  +
  +                if src.Count > 1 then
  +                    GL.FramebufferTextureLayer(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, src.Handle, srcLevel, srcSlice)
  +                else
  +                    GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, src.Handle, srcLevel)
  +                GL.Check "could not attach texture to framebuffer"
  +
  +                let srcCheck = GL.CheckFramebufferStatus(FramebufferTarget.ReadFramebuffer)
  +                if srcCheck <> FramebufferErrorCode.FramebufferComplete then
  +                    failwithf "could not create input framebuffer: %A" srcCheck
  +
  +                GL.ReadBuffer(ReadBufferMode.ColorAttachment0)
  +                GL.Check "could not set readbuffer"
  +
  +
  +                let bindTarget = TextureTarget.ofTexture dst
  +                GL.BindTexture(bindTarget, dst.Handle)
  +                GL.Check "could not bind texture"
  +
  +                let copyTarget =
  +                    match dst.Dimension with
  +                        | TextureDimension.TextureCube -> snd cubeSides.[dstSlice]
  +                        | _ -> bindTarget
  +
  +                GL.CopyTexSubImage2D(
  +                    copyTarget,
  +                    dstLevel,
  +                    dstOffset.X, dstOffset.Y,
  +                    srcOffset.X, srcOffset.Y,
  +                    size.X, size.Y
  +                )
  +                GL.Check "could not copy texture"
  +
  +                GL.ReadBuffer(ReadBufferMode.None)
  +                GL.Check "could not unset readbuffer"
  +
  +                GL.BindTexture(bindTarget, 0)
  +                GL.Check "could not unbind texture"
  +
  +                GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, 0)
  +                GL.Check "could not unbind framebuffer"
  +
  +                GL.DeleteFramebuffer(fSrc)
  +                GL.Check "could not delete framebuffer"
  +
  +            )
  +
  +
  +[<AutoOpen>]
  +module TextureUploadExtensions =
       open Microsoft.FSharp.NativeInterop
   
       module private StructTypes = 
  
positive.code:                         GL.Check "could not bind texture"
  
                          let target = snd cubeSides.[slice]
                          uploadTexture2DLevelInternal target t level source
  
                          GL.BindTexture(target, 0)
                          GL.Check "could not unbind texture"
  
negative.code:                         imgInfo.Size,
                          imgInfo.Delta * elementSize
                      )
                  TextureCopyUtils.Copy(elementType, pSrc, srcInfo, dst, dstInfo)
              finally
                  gc.Free()   
  
  