<commit_before>﻿namespace Aardvark.Rendering.GL.Compiler

open Aardvark.Base.Incremental
open Aardvark.Base
open Aardvark.Base.Rendering
open Aardvark.Rendering.GL

module Instructions =
    
    let setDepthTest (m : IMod<DepthTestMode>) =
        m |> Mod.map (fun dt ->
            if dt <> DepthTestMode.None then
                [ 
                    Instruction.Enable(int OpenGl.Enums.State.DepthTest)
                    Instruction.DepthFunc(Translations.toGLComparison dt) 
                ]
            else
                [ Instruction.Disable(int OpenGl.Enums.State.DepthTest) ]
        )

    let setFillMode (m : IMod<FillMode>) =
        m |> Mod.map (fun fm -> 
            [ Instruction.PolygonMode (int OpenGl.Enums.Face.FrontAndBack) (Translations.toGLPolygonMode fm) ]
        )

    let setCullMode (m : IMod<CullMode>) =
        m |> Mod.map (fun cm -> 
            if cm <> CullMode.None then
                [ 
                    Instruction.Enable(int OpenGl.Enums.State.CullFace)
                    Instruction.CullFace(Translations.toGLFace cm) 
                ]
            else
                [ Instruction.Disable(int OpenGl.Enums.State.CullFace) ]
        )

    let setBlendMode (m : IMod<BlendMode>) =
        m |> Mod.map (fun bm -> 
            //TODO: actually depending on the Framebuffer (premultiplied alpha)
            if bm.Enabled then
                let src = Translations.toGLFactor bm.SourceFactor
                let dst = Translations.toGLFactor bm.DestinationFactor
                let op = Translations.toGLOperation bm.Operation

                let srcA = Translations.toGLFactor bm.SourceAlphaFactor
                let dstA = Translations.toGLFactor bm.DestinationAlphaFactor
                let opA = Translations.toGLOperation bm.AlphaOperation

                [ 
                    Instruction.Enable(int OpenGl.Enums.State.Blend)
                    Instruction.BlendFuncSeparate src dst srcA dstA
                    Instruction.BlendEquationSeparate op opA
                ]
            else
                [ Instruction.Disable(int OpenGl.Enums.State.Blend) ]
        )

    let setStencilMode (m : IMod<StencilMode>) =
        m |> Mod.map (fun sm -> 
            //TODO: actually depending on the Framebuffer (premultiplied alpha)
            if sm.IsEnabled then
                let cmpFront = Translations.toGLFunction sm.CompareFront.Function
                let cmpBack= Translations.toGLFunction sm.CompareBack.Function
                let opFrontSF = Translations.toGLStencilOperation sm.OperationFront.StencilFail
                let opBackSF = Translations.toGLStencilOperation sm.OperationBack.StencilFail
                let opFrontDF = Translations.toGLStencilOperation sm.OperationFront.DepthFail
                let opBackDF = Translations.toGLStencilOperation sm.OperationBack.DepthFail
                let opFrontP = Translations.toGLStencilOperation sm.OperationFront.DepthPass
                let opBackP = Translations.toGLStencilOperation sm.OperationBack.DepthPass

                [ 
                    Instruction.Enable(int OpenGl.Enums.State.StencilTest) 
                    Instruction.StencilFuncSeparate(int OpenGl.Enums.Face.Front) cmpFront sm.CompareFront.Reference (int sm.CompareFront.Mask)
                    Instruction.StencilFuncSeparate(int OpenGl.Enums.Face.Back) cmpBack sm.CompareBack.Reference (int sm.CompareBack.Mask)
                    Instruction.StencilOpSeparate(int OpenGl.Enums.Face.Front) opFrontSF opFrontDF opFrontP
                    Instruction.StencilOpSeparate(int OpenGl.Enums.Face.Back) opBackSF opBackDF opBackP
                ]
            else
                [ Instruction.Disable(int OpenGl.Enums.State.StencilTest) ]
        )

    let bindProgram (p : ChangeableResource<Program>) =
        p.Resource |> Mod.map (fun r -> Instruction.BindProgram(r.Handle))

    let bindUniformBuffer (index : int) (u : ChangeableResource<UniformBuffer>) =   
        u.Resource |> Mod.map (fun r -> 
            //ExecutionContext.bindUniformBuffer index r
            Instruction.BindBufferRange (int OpenGl.Enums.BufferTarget.UniformBuffer) index r.Handle 0n (nativeint r.Size)
        )

    let setActiveTexture (index : int) =
        Instruction.ActiveTexture ((int OpenGl.Enums.TextureUnit.Texture0) + index)

    let bindSampler (index : int) (sampler : ChangeableResource<Sampler>) =
        sampler.Resource |> Mod.map (fun r -> [Instruction.BindSampler index r.Handle])

    let bindTexture (tex : ChangeableResource<Texture>) =
        tex.Resource |> Mod.map(fun r -> 
            let target = Translations.toGLTarget r.Dimension r.IsArray r.Multisamples
            [ Instruction.BindTexture target r.Handle ]
        )

    let bindVertexArray (vao : ChangeableResource<VertexArrayObject>) =
        fun (ctx : ContextHandle) -> Instruction.BindVertexArray(vao.Resource.GetValue().Handle)

    let draw (program : Program) (indexArray : IMod<System.Array>) (call : IMod<DrawCallInfo>) (isActive : IMod<bool>) =
        let hasTess = program.Shaders |> List.exists (fun s -> s.Stage = ShaderStage.TessControl)

        let indexType = 
            if indexArray <> null then
                indexArray |> Mod.map (fun ia -> (ia <> null, if ia <> null then ia.GetType().GetElementType() else typeof<obj>))
            else
                Mod.constant (false, typeof<obj>)

        let patchSize (mode : IndexedGeometryMode) =
            match mode with<commit_msg>GL backend can now render without using VAOs;<commit_after>﻿namespace Aardvark.Rendering.GL.Compiler

open Aardvark.Base.Incremental
open Aardvark.Base
open Aardvark.Base.Rendering
open Aardvark.Rendering.GL

module Instructions =
    
    let setDepthTest (m : IMod<DepthTestMode>) =
        m |> Mod.map (fun dt ->
            if dt <> DepthTestMode.None then
                [ 
                    Instruction.Enable(int OpenGl.Enums.State.DepthTest)
                    Instruction.DepthFunc(Translations.toGLComparison dt) 
                ]
            else
                [ Instruction.Disable(int OpenGl.Enums.State.DepthTest) ]
        )

    let setFillMode (m : IMod<FillMode>) =
        m |> Mod.map (fun fm -> 
            [ Instruction.PolygonMode (int OpenGl.Enums.Face.FrontAndBack) (Translations.toGLPolygonMode fm) ]
        )

    let setCullMode (m : IMod<CullMode>) =
        m |> Mod.map (fun cm -> 
            if cm <> CullMode.None then
                [ 
                    Instruction.Enable(int OpenGl.Enums.State.CullFace)
                    Instruction.CullFace(Translations.toGLFace cm) 
                ]
            else
                [ Instruction.Disable(int OpenGl.Enums.State.CullFace) ]
        )

    let setBlendMode (m : IMod<BlendMode>) =
        m |> Mod.map (fun bm -> 
            //TODO: actually depending on the Framebuffer (premultiplied alpha)
            if bm.Enabled then
                let src = Translations.toGLFactor bm.SourceFactor
                let dst = Translations.toGLFactor bm.DestinationFactor
                let op = Translations.toGLOperation bm.Operation

                let srcA = Translations.toGLFactor bm.SourceAlphaFactor
                let dstA = Translations.toGLFactor bm.DestinationAlphaFactor
                let opA = Translations.toGLOperation bm.AlphaOperation

                [ 
                    Instruction.Enable(int OpenGl.Enums.State.Blend)
                    Instruction.BlendFuncSeparate src dst srcA dstA
                    Instruction.BlendEquationSeparate op opA
                ]
            else
                [ Instruction.Disable(int OpenGl.Enums.State.Blend) ]
        )

    let setStencilMode (m : IMod<StencilMode>) =
        m |> Mod.map (fun sm -> 
            //TODO: actually depending on the Framebuffer (premultiplied alpha)
            if sm.IsEnabled then
                let cmpFront = Translations.toGLFunction sm.CompareFront.Function
                let cmpBack= Translations.toGLFunction sm.CompareBack.Function
                let opFrontSF = Translations.toGLStencilOperation sm.OperationFront.StencilFail
                let opBackSF = Translations.toGLStencilOperation sm.OperationBack.StencilFail
                let opFrontDF = Translations.toGLStencilOperation sm.OperationFront.DepthFail
                let opBackDF = Translations.toGLStencilOperation sm.OperationBack.DepthFail
                let opFrontP = Translations.toGLStencilOperation sm.OperationFront.DepthPass
                let opBackP = Translations.toGLStencilOperation sm.OperationBack.DepthPass

                [ 
                    Instruction.Enable(int OpenGl.Enums.State.StencilTest) 
                    Instruction.StencilFuncSeparate(int OpenGl.Enums.Face.Front) cmpFront sm.CompareFront.Reference (int sm.CompareFront.Mask)
                    Instruction.StencilFuncSeparate(int OpenGl.Enums.Face.Back) cmpBack sm.CompareBack.Reference (int sm.CompareBack.Mask)
                    Instruction.StencilOpSeparate(int OpenGl.Enums.Face.Front) opFrontSF opFrontDF opFrontP
                    Instruction.StencilOpSeparate(int OpenGl.Enums.Face.Back) opBackSF opBackDF opBackP
                ]
            else
                [ Instruction.Disable(int OpenGl.Enums.State.StencilTest) ]
        )

    let bindProgram (p : ChangeableResource<Program>) =
        p.Resource |> Mod.map (fun r -> Instruction.BindProgram(r.Handle))

    let bindUniformBuffer (index : int) (u : ChangeableResource<UniformBuffer>) =   
        u.Resource |> Mod.map (fun r -> 
            //ExecutionContext.bindUniformBuffer index r
            Instruction.BindBufferRange (int OpenGl.Enums.BufferTarget.UniformBuffer) index r.Handle 0n (nativeint r.Size)
        )

    let setActiveTexture (index : int) =
        Instruction.ActiveTexture ((int OpenGl.Enums.TextureUnit.Texture0) + index)

    let bindSampler (index : int) (sampler : ChangeableResource<Sampler>) =
        sampler.Resource |> Mod.map (fun r -> [Instruction.BindSampler index r.Handle])

    let bindTexture (tex : ChangeableResource<Texture>) =
        tex.Resource |> Mod.map(fun r -> 
            let target = Translations.toGLTarget r.Dimension r.IsArray r.Multisamples
            [ Instruction.BindTexture target r.Handle ]
        )

    let bindVertexArray (vao : ChangeableResource<VertexArrayObject>) =
        if ExecutionContext.vertexArrayObjectsSupported then
            fun (ctx : ContextHandle) -> 
                [Instruction.BindVertexArray(vao.Resource.GetValue().Handle)]
        else
            let vao = vao.Resource.GetValue()

            fun (ctx : ContextHandle) ->
                [
                    for (i,b) in vao.Bindings do
                        yield Instruction.BindBuffer (int OpenTK.Graphics.OpenGL4.BufferTarget.ArrayBuffer) b.Buffer.Handle
                        yield Instruction.EnableVertexAttribArray i
                        yield Instruction.VertexAttribPointer i b.Dimension (int b.VertexAttributeType) b.Normalized b.Stride 0n
                    
                    match vao.Index with
                        | Some i -> yield Instruction.BindBuffer (int OpenTK.Graphics.OpenGL4.BufferTarget.ElementArrayBuffer) i.Handle
                        | None -> yield Instruction.BindBuffer (int OpenTK.Graphics.OpenGL4.BufferTarget.ElementArrayBuffer) 0
                ]

    let draw (program : Program) (indexArray : IMod<System.Array>) (call : IMod<DrawCallInfo>) (isActive : IMod<bool>) =
        let hasTess = program.Shaders |> List.exists (fun s -> s.Stage = ShaderStage.TessControl)

        let indexType = 
            if indexArray <> null then
                indexArray |> Mod.map (fun ia -> (ia <> null, if ia <> null then ia.GetType().GetElementType() else typeof<obj>))
            else
                Mod.constant (false, typeof<obj>)

        let patchSize (mode : IndexedGeometryMode) =
            match mode with
{'fraction_non_alphanumeric': 0.08182881979271146, 'fraction_numerical': 0.0007522567703109327, 'mean_word_length': 2.063236047107015, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 92, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4264093', 'n_tokens_mistral': 3461, 'n_tokens_neox': 3227, 'n_words': 694}