F#でも XNA が使用できます。
ただし .NET Framework 4.0 ではビルドできませんでした。3.5 なら問題なくビルドできます。
おそらく、 XNA Game Studio 4.0 がリリースされれば .NET Framework 4.0 でもビルドできるようになると思われます。

BasicComponents.fs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
namespace Siki

open System
open System.Collections.Generic
open Microsoft.Xna.Framework

module BasicComponents =
   
    /// 秒を表す単位
    [<Measure>]
    type sec =
        static member Unit v = v * 1.0<sec>
        static member Unit v = v * 1<sec>
           
    /// フレームを表す単位
    [<Measure>]
    type frame =
        /// 1フレームを表す
        static member Unit v = v * 1.0<frame>
        static member Unit v = v * 1<frame>

    /// 1秒あたりの描画フレーム数を計算するコンポーネント
    type FpsComponent(game, syncv, fixedStep, targetFps) =
        inherit DrawableGameComponent(game)
        // フィールド
        let         m_interval   = 1.0<sec>
        let mutable m_fps        = 0.0<frame/sec>
        let mutable m_sec        = 0.0<sec>
        let mutable m_framecount = 0.0<frame>
        let mutable m_lastupdate = 0.0<sec>

        // メインコンストラクタ
        do
            let graphics =
                game.Services.GetService(typeof<IGraphicsDeviceManager>)
                :?> GraphicsDeviceManager
           
            graphics.SynchronizeWithVerticalRetrace <- syncv
            game.IsFixedTimeStep <- fixedStep
            game.TargetElapsedTime <- TimeSpan.FromSeconds(1.0 / targetFps)

        /// カスタムコンストラクタ
        new(game) =
            new FpsComponent(game, false, false, 1.0 / game.TargetElapsedTime.TotalSeconds)

        new(game, syncv) =
            new FpsComponent(game, syncv, false,  1.0 / game.TargetElapsedTime.TotalSeconds)

        new(game, targetFps) =
            new FpsComponent(game, true, true, targetFps)
       
        /// 現在のFPS値を取得する
        member x.Fps
            with get() = m_fps

        /// 現在のFPSを整数に丸めた値を取得する
        member x.RoundFps
            with get() = x.Fps |> float |> Math.Round |> int

        /// 初期化メソッド
        override x.Initialize() =
            base.Initialize()

        /// 更新メソッド
        override x.Update(gametime) =
            base.Update(gametime)

        /// 描画メソッド
        override x.Draw(gametime) =
            let elapsed = gametime.ElapsedGameTime.TotalSeconds |> sec.Unit
            m_framecount <- m_framecount + 1.0<frame>
            m_sec <- m_sec + elapsed
            if m_sec > m_interval then
                m_fps <- m_framecount / m_sec
                x.Game.Window.Title <- sprintf "%d fps" x.RoundFps
                m_framecount <- 0.0<frame> // カウンタリセット
                m_sec <- m_sec - m_interval
            base.Draw(gametime)

Program.fs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
namespace Siki

open System
open System.Collections.Generic
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics

open Siki.BasicComponents

module Main =
    /// ゲームクラス
    type Game1() as x =
        inherit Game(IsMouseVisible=true,
                     IsFixedTimeStep=false)
       
        // フィールド
        let m_rand = new Random()
        let m_graphics = new GraphicsDeviceManager(x)
        let m_fpscomponent = new FpsComponent(x)
        let mutable m_num = 0
        let mutable m_bgc = new Color(80uy, 80uy, 80uy)
        let mutable m_rd = -1
        let mutable m_gd = -1
        let mutable m_bd = -1
        // メインコンストラクタ
        do
            x.Window.Title <- "FPSを表示します"
        /// 初期化メソッド
        override x.Initialize() =
            x.Components.Add(m_fpscomponent)
            base.Initialize()

        /// 更新メソッド
        override x.Update gametime =
            m_num <- m_num + 1
            base.Update gametime

        /// 描画メソッド
        override x.Draw gametime =
            match m_rand.Next(0, 5) with
            | 0 ->
                m_bgc.R <- m_bgc.R + (m_rd |> byte)
                if (m_bgc.R = 0x00uy || m_bgc.R = 0xffuy) then m_rd <- m_rd * -1
            | 1|2 ->
                m_bgc.G <- m_bgc.G + (m_gd |> byte)
                if (m_bgc.G = 0x00uy || m_bgc.G = 0xffuy) then m_gd <- m_gd * -1
            | 3|4|5 ->
                m_bgc.B <- m_bgc.B + (m_bd |> byte)
                if (m_bgc.B = 0x00uy || m_bgc.B = 0xffuy) then m_bd <- m_bd * -1
            | _ -> ()
            m_graphics.GraphicsDevice.Clear(
                m_bgc
            )
            base.Draw gametime
   
    /// プログラムのエントリポイント
    [<EntryPoint>]
    let main(args:string[]) =
        use game = new Game1()
        game.Run()
        0

FPSを計算するだけの簡単なサンプルです。
Update()、Draw()が呼ばれていることを確認するために、少しずつ背景色を変えています。