packages feed

tracy-profiler 0.1.2.1 → 0.2.0.0

raw patch · 19 files changed

+1717/−244 lines, 19 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

- System.Tracy.FFI: emitMessage :: ConstPtr CChar -> CSize -> CInt -> IO ()
- System.Tracy.FFI: emitMessageC :: ConstPtr CChar -> CSize -> Color -> CInt -> IO ()
- System.Tracy.FFI: emitMessageL :: ConstPtr CChar -> CInt -> IO ()
- System.Tracy.FFI: emitMessageLC :: ConstPtr CChar -> Color -> CInt -> IO ()
- System.Tracy.FFI: shutdownProfiler :: IO ()
- System.Tracy.FFI: startupProfiler :: IO ()
- System.Tracy.FFI.Types: instance GHC.Internal.Enum.Bounded System.Tracy.FFI.Types.PlotFormat
- System.Tracy.FFI.Types: instance GHC.Internal.Enum.Enum System.Tracy.FFI.Types.PlotFormat
- System.Tracy.FFI.Types: instance GHC.Internal.Foreign.Storable.Storable System.Tracy.FFI.Types.Color
- System.Tracy.FFI.Types: instance GHC.Internal.Foreign.Storable.Storable System.Tracy.FFI.Types.SourceLocationData
- System.Tracy.FFI.Types: instance GHC.Internal.Foreign.Storable.Storable System.Tracy.FFI.Types.SrcLoc
- System.Tracy.FFI.Types: instance GHC.Internal.Foreign.Storable.Storable System.Tracy.FFI.Types.TracyCZoneCtx
- System.Tracy.FFI.Types: instance GHC.Internal.Num.Num System.Tracy.FFI.Types.Color
- System.Tracy.FFI.Types: instance GHC.Internal.Show.Show System.Tracy.FFI.Types.Color
- System.Tracy.FFI.Types: instance GHC.Internal.Show.Show System.Tracy.FFI.Types.PlotFormat
- System.Tracy.FFI.Types: instance GHC.Internal.Show.Show System.Tracy.FFI.Types.SrcLoc
- System.Tracy.FFI.Types: instance GHC.Internal.Show.Show System.Tracy.FFI.Types.TracyCZoneCtx
- System.Tracy.FFI.Types: instance WebColor.Labels.IsWebColorAlpha s => GHC.Internal.OverloadedLabels.IsLabel s System.Tracy.FFI.Types.Color
+ System.Tracy: MessageSeverityDebug :: MessageSeverity
+ System.Tracy: MessageSeverityError :: MessageSeverity
+ System.Tracy: MessageSeverityFatal :: MessageSeverity
+ System.Tracy: MessageSeverityInfo :: MessageSeverity
+ System.Tracy: MessageSeverityTrace :: MessageSeverity
+ System.Tracy: MessageSeverityWarning :: MessageSeverity
+ System.Tracy: beginSamplingProfiling :: MonadIO m => m Bool
+ System.Tracy: data MessageSeverity
+ System.Tracy: enabled :: Bool
+ System.Tracy: endSamplingProfiling :: MonadIO m => m ()
+ System.Tracy: frameImage :: MonadIO m => Ptr pixels -> Word16 -> Word16 -> Word8 -> Bool -> m ()
+ System.Tracy: getTime :: MonadIO m => m Int64
+ System.Tracy: logString :: MonadIO m => MessageSeverity -> Color -> Text -> m ()
+ System.Tracy: logStringL :: MonadIO m => MessageSeverity -> Color -> Addr# -> m ()
+ System.Tracy.FFI: afterLockLockableCtx :: TracyCLockCtx -> IO ()
+ System.Tracy.FFI: afterLockSharedLockableCtx :: TracyCSharedLockCtx -> IO ()
+ System.Tracy.FFI: afterLockSharedSharedLockableCtx :: TracyCSharedLockCtx -> IO ()
+ System.Tracy.FFI: afterTryLockLockableCtx :: TracyCLockCtx -> Int32 -> IO ()
+ System.Tracy.FFI: afterTryLockSharedLockableCtx :: TracyCSharedLockCtx -> Int32 -> IO ()
+ System.Tracy.FFI: afterTryLockSharedSharedLockableCtx :: TracyCSharedLockCtx -> Int32 -> IO ()
+ System.Tracy.FFI: announceLockableCtx :: ConstPtr SourceLocationData -> IO TracyCLockCtx
+ System.Tracy.FFI: announceSharedLockableCtx :: ConstPtr SourceLocationData -> IO TracyCSharedLockCtx
+ System.Tracy.FFI: beforeLockLockableCtx :: TracyCLockCtx -> IO Int32
+ System.Tracy.FFI: beforeLockSharedLockableCtx :: TracyCSharedLockCtx -> IO Int32
+ System.Tracy.FFI: beforeLockSharedSharedLockableCtx :: TracyCSharedLockCtx -> IO Int32
+ System.Tracy.FFI: beforeUnlockLockableCtx :: TracyCLockCtx -> IO ()
+ System.Tracy.FFI: beforeUnlockSharedLockableCtx :: TracyCSharedLockCtx -> IO ()
+ System.Tracy.FFI: beforeUnlockSharedSharedLockableCtx :: TracyCSharedLockCtx -> IO ()
+ System.Tracy.FFI: beginSamplingProfiling :: IO CInt
+ System.Tracy.FFI: customNameLockableCtx :: TracyCLockCtx -> ConstPtr CChar -> CSize -> IO ()
+ System.Tracy.FFI: customNameSharedLockableCtx :: TracyCSharedLockCtx -> ConstPtr CChar -> CSize -> IO ()
+ System.Tracy.FFI: emitGpuCalibration :: Int64 -> Int64 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuCalibrationSerial :: Int64 -> Int64 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuContextName :: Word8 -> ConstPtr CChar -> Word16 -> IO ()
+ System.Tracy.FFI: emitGpuContextNameSerial :: Word8 -> ConstPtr CChar -> Word16 -> IO ()
+ System.Tracy.FFI: emitGpuNewContext :: Int64 -> Float -> Word8 -> Word8 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuNewContextSerial :: Int64 -> Float -> Word8 -> Word8 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuTime :: Int64 -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuTimeSerial :: Int64 -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuTimeSync :: Int64 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuTimeSyncSerial :: Int64 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneBegin :: ConstPtr SourceLocationData -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneBeginAlloc :: SrcLoc -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneBeginAllocCallstack :: SrcLoc -> Int32 -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneBeginAllocCallstackSerial :: SrcLoc -> Int32 -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneBeginAllocSerial :: SrcLoc -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneBeginCallstack :: ConstPtr SourceLocationData -> Int32 -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneBeginCallstackSerial :: ConstPtr SourceLocationData -> Int32 -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneBeginSerial :: ConstPtr SourceLocationData -> Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneEnd :: Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitGpuZoneEndSerial :: Word16 -> Word8 -> IO ()
+ System.Tracy.FFI: emitLogString :: Int8 -> Color -> CInt -> CSize -> ConstPtr CChar -> IO ()
+ System.Tracy.FFI: emitLogStringL :: Int8 -> Color -> CInt -> ConstPtr CChar -> IO ()
+ System.Tracy.FFI: emitMemoryDiscard :: ConstPtr CChar -> IO ()
+ System.Tracy.FFI: emitMemoryDiscardCallstack :: ConstPtr CChar -> CInt -> IO ()
+ System.Tracy.FFI: endSamplingProfiling :: IO ()
+ System.Tracy.FFI: getTime :: IO Int64
+ System.Tracy.FFI: markLockableCtx :: TracyCLockCtx -> ConstPtr SourceLocationData -> IO ()
+ System.Tracy.FFI: markSharedLockableCtx :: TracyCSharedLockCtx -> ConstPtr SourceLocationData -> IO ()
+ System.Tracy.FFI: sectionEnter :: Word16 -> ConstPtr CChar -> CSize -> IO Word32
+ System.Tracy.FFI: sectionLeave :: Word32 -> IO ()
+ System.Tracy.FFI: sectionSetup :: Word16 -> ConstPtr CChar -> CSize -> IO ()
+ System.Tracy.FFI: terminateLockableCtx :: TracyCLockCtx -> IO ()
+ System.Tracy.FFI: terminateSharedLockableCtx :: TracyCSharedLockCtx -> IO ()
+ System.Tracy.FFI.Types: GpuContextTypeCUDA :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeCustom :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeDirect3D11 :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeDirect3D12 :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeMetal :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeOpenCL :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeOpenGl :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeRocprof :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeVulkan :: GpuContextType
+ System.Tracy.FFI.Types: GpuContextTypeWebGPU :: GpuContextType
+ System.Tracy.FFI.Types: MessageSeverityDebug :: MessageSeverity
+ System.Tracy.FFI.Types: MessageSeverityError :: MessageSeverity
+ System.Tracy.FFI.Types: MessageSeverityFatal :: MessageSeverity
+ System.Tracy.FFI.Types: MessageSeverityInfo :: MessageSeverity
+ System.Tracy.FFI.Types: MessageSeverityTrace :: MessageSeverity
+ System.Tracy.FFI.Types: MessageSeverityWarning :: MessageSeverity
+ System.Tracy.FFI.Types: TracyCLockCtx :: Ptr TracyCLockCtx -> TracyCLockCtx
+ System.Tracy.FFI.Types: TracyCSharedLockCtx :: Ptr TracyCSharedLockCtx -> TracyCSharedLockCtx
+ System.Tracy.FFI.Types: clampTextBytes :: Int -> CSize
+ System.Tracy.FFI.Types: data GpuContextType
+ System.Tracy.FFI.Types: data MessageSeverity
+ System.Tracy.FFI.Types: gpuContextTypeCode :: GpuContextType -> Word8
+ System.Tracy.FFI.Types: instance Foreign.Storable.Storable System.Tracy.FFI.Types.Color
+ System.Tracy.FFI.Types: instance Foreign.Storable.Storable System.Tracy.FFI.Types.SourceLocationData
+ System.Tracy.FFI.Types: instance Foreign.Storable.Storable System.Tracy.FFI.Types.SrcLoc
+ System.Tracy.FFI.Types: instance Foreign.Storable.Storable System.Tracy.FFI.Types.TracyCLockCtx
+ System.Tracy.FFI.Types: instance Foreign.Storable.Storable System.Tracy.FFI.Types.TracyCSharedLockCtx
+ System.Tracy.FFI.Types: instance Foreign.Storable.Storable System.Tracy.FFI.Types.TracyCZoneCtx
+ System.Tracy.FFI.Types: instance GHC.Classes.Eq System.Tracy.FFI.Types.GpuContextType
+ System.Tracy.FFI.Types: instance GHC.Classes.Eq System.Tracy.FFI.Types.MessageSeverity
+ System.Tracy.FFI.Types: instance GHC.Classes.Eq System.Tracy.FFI.Types.TracyCLockCtx
+ System.Tracy.FFI.Types: instance GHC.Classes.Eq System.Tracy.FFI.Types.TracyCSharedLockCtx
+ System.Tracy.FFI.Types: instance GHC.Classes.Ord System.Tracy.FFI.Types.GpuContextType
+ System.Tracy.FFI.Types: instance GHC.Classes.Ord System.Tracy.FFI.Types.MessageSeverity
+ System.Tracy.FFI.Types: instance GHC.Classes.Ord System.Tracy.FFI.Types.TracyCLockCtx
+ System.Tracy.FFI.Types: instance GHC.Classes.Ord System.Tracy.FFI.Types.TracyCSharedLockCtx
+ System.Tracy.FFI.Types: instance GHC.Enum.Bounded System.Tracy.FFI.Types.GpuContextType
+ System.Tracy.FFI.Types: instance GHC.Enum.Bounded System.Tracy.FFI.Types.MessageSeverity
+ System.Tracy.FFI.Types: instance GHC.Enum.Bounded System.Tracy.FFI.Types.PlotFormat
+ System.Tracy.FFI.Types: instance GHC.Enum.Enum System.Tracy.FFI.Types.MessageSeverity
+ System.Tracy.FFI.Types: instance GHC.Enum.Enum System.Tracy.FFI.Types.PlotFormat
+ System.Tracy.FFI.Types: instance GHC.Num.Num System.Tracy.FFI.Types.Color
+ System.Tracy.FFI.Types: instance GHC.Show.Show System.Tracy.FFI.Types.Color
+ System.Tracy.FFI.Types: instance GHC.Show.Show System.Tracy.FFI.Types.GpuContextType
+ System.Tracy.FFI.Types: instance GHC.Show.Show System.Tracy.FFI.Types.MessageSeverity
+ System.Tracy.FFI.Types: instance GHC.Show.Show System.Tracy.FFI.Types.PlotFormat
+ System.Tracy.FFI.Types: instance GHC.Show.Show System.Tracy.FFI.Types.SrcLoc
+ System.Tracy.FFI.Types: instance GHC.Show.Show System.Tracy.FFI.Types.TracyCLockCtx
+ System.Tracy.FFI.Types: instance GHC.Show.Show System.Tracy.FFI.Types.TracyCSharedLockCtx
+ System.Tracy.FFI.Types: instance GHC.Show.Show System.Tracy.FFI.Types.TracyCZoneCtx
+ System.Tracy.FFI.Types: instance WebColor.Labels.IsWebColorAlpha s => GHC.OverloadedLabels.IsLabel s System.Tracy.FFI.Types.Color
+ System.Tracy.FFI.Types: maxTextBytes :: Int
+ System.Tracy.FFI.Types: newtype TracyCLockCtx
+ System.Tracy.FFI.Types: newtype TracyCSharedLockCtx
+ System.Tracy.FFI.Types: pointerBytes :: Int
+ System.Tracy.Gpu: Context :: Word8 -> Context
+ System.Tracy.Gpu: GpuContextTypeCUDA :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeCustom :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeDirect3D11 :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeDirect3D12 :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeMetal :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeOpenCL :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeOpenGl :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeRocprof :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeVulkan :: GpuContextType
+ System.Tracy.Gpu: GpuContextTypeWebGPU :: GpuContextType
+ System.Tracy.Gpu: Zone :: Maybe Context -> Zone
+ System.Tracy.Gpu: beginSourceLocation :: MonadIO m => Context -> SourceLocation -> m Word16 -> m Zone
+ System.Tracy.Gpu: beginSrcLoc :: MonadIO m => Context -> ByteString -> Color -> m Word16 -> m Zone
+ System.Tracy.Gpu: calibration :: MonadIO m => Context -> Int64 -> Int64 -> m ()
+ System.Tracy.Gpu: contextName :: MonadIO m => Context -> Text -> m ()
+ System.Tracy.Gpu: data GpuContextType
+ System.Tracy.Gpu: end :: MonadIO m => Zone -> m Word16 -> m ()
+ System.Tracy.Gpu: instance GHC.Classes.Eq System.Tracy.Gpu.Context
+ System.Tracy.Gpu: instance GHC.Classes.Eq System.Tracy.Gpu.Zone
+ System.Tracy.Gpu: instance GHC.Classes.Ord System.Tracy.Gpu.Context
+ System.Tracy.Gpu: instance GHC.Classes.Ord System.Tracy.Gpu.Zone
+ System.Tracy.Gpu: instance GHC.Show.Show System.Tracy.Gpu.Context
+ System.Tracy.Gpu: instance GHC.Show.Show System.Tracy.Gpu.Zone
+ System.Tracy.Gpu: newCalibratedContext :: MonadIO m => Context -> GpuContextType -> Float -> Int64 -> m ()
+ System.Tracy.Gpu: newContext :: MonadIO m => Context -> GpuContextType -> Float -> Int64 -> m ()
+ System.Tracy.Gpu: newtype Context
+ System.Tracy.Gpu: newtype Zone
+ System.Tracy.Gpu: time :: MonadIO m => Context -> Word16 -> Int64 -> m ()
+ System.Tracy.Gpu: timeSync :: MonadIO m => Context -> Int64 -> m ()
+ System.Tracy.Gpu: withSourceLocation :: Context -> SourceLocation -> m Word16 -> m Word16 -> m a -> m a
+ System.Tracy.Gpu: withSrcLoc :: Context -> ByteString -> Color -> m Word16 -> m Word16 -> m a -> m a
+ System.Tracy.Lock: Lock :: TracyCLockCtx -> Lock
+ System.Tracy.Lock: acquire :: Lock -> a -> a
+ System.Tracy.Lock: announce :: MonadIO m => SourceLocation -> m Lock
+ System.Tracy.Lock: customName :: MonadIO m => Lock -> Text -> m ()
+ System.Tracy.Lock: mark :: MonadIO m => Lock -> SourceLocation -> m ()
+ System.Tracy.Lock: newtype Lock
+ System.Tracy.Lock: release :: Lock -> a -> a
+ System.Tracy.Lock: terminate :: MonadIO m => Lock -> m ()
+ System.Tracy.Lock: tryAcquire :: Lock -> a -> a
+ System.Tracy.Memory: discard :: MonadIO m => Addr# -> m ()
+ System.Tracy.Section: Section :: Word32 -> Section
+ System.Tracy.Section: enter :: MonadIO m => Text -> m Section
+ System.Tracy.Section: enterCategory :: MonadIO m => Word16 -> Text -> m Section
+ System.Tracy.Section: leave :: MonadIO m => Section -> m ()
+ System.Tracy.Section: newtype Section
+ System.Tracy.Section: setup :: MonadIO m => Word16 -> Text -> m ()
+ System.Tracy.Section: with :: Text -> a -> a
+ System.Tracy.Section: withCategory :: Word16 -> Text -> a -> a
+ System.Tracy.SharedLock: SharedLock :: TracyCSharedLockCtx -> SharedLock
+ System.Tracy.SharedLock: acquire :: SharedLock -> a -> a
+ System.Tracy.SharedLock: acquireShared :: SharedLock -> a -> a
+ System.Tracy.SharedLock: announce :: MonadIO m => SourceLocation -> m SharedLock
+ System.Tracy.SharedLock: customName :: MonadIO m => SharedLock -> Text -> m ()
+ System.Tracy.SharedLock: mark :: MonadIO m => SharedLock -> SourceLocation -> m ()
+ System.Tracy.SharedLock: newtype SharedLock
+ System.Tracy.SharedLock: release :: SharedLock -> a -> a
+ System.Tracy.SharedLock: releaseShared :: SharedLock -> a -> a
+ System.Tracy.SharedLock: terminate :: MonadIO m => SharedLock -> m ()
+ System.Tracy.SharedLock: tryAcquire :: SharedLock -> a -> a
+ System.Tracy.SharedLock: tryAcquireShared :: SharedLock -> a -> a
+ System.Tracy.SourceLocation: SourceLocation :: ConstPtr SourceLocationData -> SourceLocation
+ System.Tracy.SourceLocation: newSourceLocation :: MonadIO m => ByteString -> Color -> m SourceLocation
+ System.Tracy.SourceLocation: newtype SourceLocation
+ System.Tracy.Zone: withSourceLocation :: forall {k} m (a :: k). SourceLocation -> ((?zoneCtx :: TracyCZoneCtx) => m a) -> m a
- System.Tracy: plotIntegral :: (Integral a, MonadIO m) => Addr# -> a -> m ()
+ System.Tracy: plotIntegral :: Monad m => Addr# -> a -> m ()
- System.Tracy: withProfiler :: MonadUnliftIO m => m a -> m a
+ System.Tracy: withProfiler :: a -> a
- System.Tracy: withSrcLoc :: (HasCallStack, MonadUnliftIO m) => ByteString -> Color -> ((?zoneCtx :: TracyCZoneCtx) => m a) -> m a
+ System.Tracy: withSrcLoc :: forall {k} m (a :: k). ByteString -> Color -> ((?zoneCtx :: TracyCZoneCtx) => m a) -> m a
- System.Tracy.FFI: connected :: IO Int
+ System.Tracy.FFI: connected :: IO Int32
- System.Tracy.FFI: emitMemoryAlloc :: ConstPtr () -> CSize -> CInt -> IO ()
+ System.Tracy.FFI: emitMemoryAlloc :: ConstPtr () -> CSize -> IO ()
- System.Tracy.FFI: emitMemoryAllocCallstack :: ConstPtr () -> CSize -> CInt -> CInt -> IO ()
+ System.Tracy.FFI: emitMemoryAllocCallstack :: ConstPtr () -> CSize -> CInt -> IO ()
- System.Tracy.FFI: emitMemoryAllocCallstackNamed :: ConstPtr () -> CSize -> CInt -> CInt -> ConstPtr CChar -> IO ()
+ System.Tracy.FFI: emitMemoryAllocCallstackNamed :: ConstPtr () -> CSize -> CInt -> ConstPtr CChar -> IO ()
- System.Tracy.FFI: emitMemoryAllocNamed :: ConstPtr () -> CSize -> CInt -> ConstPtr CChar -> IO ()
+ System.Tracy.FFI: emitMemoryAllocNamed :: ConstPtr () -> CSize -> ConstPtr CChar -> IO ()
- System.Tracy.FFI: emitMemoryFree :: ConstPtr () -> CInt -> IO ()
+ System.Tracy.FFI: emitMemoryFree :: ConstPtr () -> IO ()
- System.Tracy.FFI: emitMemoryFreeCallstack :: ConstPtr () -> CInt -> CInt -> IO ()
+ System.Tracy.FFI: emitMemoryFreeCallstack :: ConstPtr () -> CInt -> IO ()
- System.Tracy.FFI: emitMemoryFreeCallstackNamed :: ConstPtr () -> CInt -> CInt -> ConstPtr CChar -> IO ()
+ System.Tracy.FFI: emitMemoryFreeCallstackNamed :: ConstPtr () -> CInt -> ConstPtr CChar -> IO ()
- System.Tracy.FFI: emitMemoryFreeNamed :: ConstPtr () -> CInt -> ConstPtr CChar -> IO ()
+ System.Tracy.FFI: emitMemoryFreeNamed :: ConstPtr () -> ConstPtr CChar -> IO ()
- System.Tracy.FFI: profilerStarted :: Int
+ System.Tracy.FFI: profilerStarted :: IO Int32
- System.Tracy.Memory: alloc :: MonadIO m => Bool -> Ptr a -> Int -> m ()
+ System.Tracy.Memory: alloc :: MonadIO m => Ptr a -> Int -> m ()
- System.Tracy.Memory: allocNamed :: MonadIO m => Bool -> Ptr a -> Int -> Addr# -> m ()
+ System.Tracy.Memory: allocNamed :: MonadIO m => Ptr a -> Int -> Addr# -> m ()
- System.Tracy.Memory: free :: MonadIO m => Bool -> Ptr a -> m ()
+ System.Tracy.Memory: free :: MonadIO m => Ptr a -> m ()
- System.Tracy.Memory: freeNamed :: MonadIO m => Bool -> Ptr a -> Addr# -> m ()
+ System.Tracy.Memory: freeNamed :: MonadIO m => Ptr a -> Addr# -> m ()
- System.Tracy.Zone: color :: (MonadIO m, ?zoneCtx :: TracyCZoneCtx) => Color -> m ()
+ System.Tracy.Zone: color :: MonadIO m => Color -> m ()
- System.Tracy.Zone: name :: (MonadIO m, ?zoneCtx :: TracyCZoneCtx) => Text -> m ()
+ System.Tracy.Zone: name :: MonadIO m => Text -> m ()
- System.Tracy.Zone: text :: (MonadIO m, ?zoneCtx :: TracyCZoneCtx) => Text -> m ()
+ System.Tracy.Zone: text :: MonadIO m => Text -> m ()
- System.Tracy.Zone: value :: (MonadIO m, ?zoneCtx :: TracyCZoneCtx) => Word64 -> m ()
+ System.Tracy.Zone: value :: MonadIO m => Word64 -> m ()
- System.Tracy.Zone: withSrcLoc :: (HasCallStack, MonadUnliftIO m) => ByteString -> Color -> ((?zoneCtx :: TracyCZoneCtx) => m a) -> m a
+ System.Tracy.Zone: withSrcLoc :: forall {k} m (a :: k). ByteString -> Color -> ((?zoneCtx :: TracyCZoneCtx) => m a) -> m a

Files

CHANGELOG.md view
@@ -6,6 +6,57 @@ and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). +## 0.2.0.0 - 2026-11-09++Now targets Tracy 0.15. The library, `tracy-capture` and `tracy-profiler` must all come from that release.++### Breaking++- Removed the `secure` argument from `System.Tracy.Memory.alloc`, `free`, `allocNamed` and `freeNamed`.+  Tracy dropped the distinction and always uses the secure code path.+- The matching `System.Tracy.FFI.emitMemory*` imports lost their `secure` argument.+- `System.Tracy.FFI.emitMessage`, `emitMessageL`, `emitMessageC` and `emitMessageLC` are replaced by `emitLogString` and `emitLogStringL`, following the upstream API.+  The `System.Tracy.message*` wrappers keep their types and log at the info severity.+- `System.Tracy.FFI.TracyCZoneCtx` has a different representation under the `on_demand` flag.+- `System.Tracy.FFI.connected` now returns `Int32`, matching the C function.+- `System.Tracy.FFI.profilerStarted` is now an `IO Int32` action.+  The old pure `Int` could keep its first result under `manual_lifetime` even after the profiler started or stopped.+- Raised the `base` lower bound to 4.18, the first release with `Foreign.C.ConstPtr`.++### Added++- `logString` and `logStringL` take a `MessageSeverity`.+- `System.Tracy.Section`, `System.Tracy.Lock`, `System.Tracy.SharedLock` and `System.Tracy.SourceLocation`.+- `getTime`, `beginSamplingProfiling`, `endSamplingProfiling` and `System.Tracy.Memory.discard`.+- `enabled` tells whether the package was built with the `enable` flag.+- `System.Tracy.Gpu` for GPU contexts and zones.+  The GPU functions in `System.Tracy.FFI` go through a small C shim.+  The GHC FFI can't pass the structures the C API takes by value.+- `System.Tracy.Zone.withSourceLocation` runs a zone from a location made once with `newSourceLocation`.+- `frameImage` attaches a screenshot to a frame.+- `make DEBUG=1` builds everything in debug mode in `upstream/_build-debug`.++### Fixed++- `on_demand` builds now go through a small C shim.+  Since Tracy 0.14, the zone context in that mode has a size the GHC FFI can't pass by value.+- Zones now work on the non-threaded RTS without `zones_unsafe`.+  The bound-thread check only applies when the runtime has bound threads.+  A capture fails if zones from different Haskell threads overlap there.+- Text given to `message`, `messageC`, `appInfo`, `Zone.text` and `Zone.name` is now cut at 65534 bytes instead of tripping a Tracy assertion.+  The cut may split a multibyte character.+- `fiberLeave` now compiles with `fibers` and `enable` both set.+- `System.Tracy.FFI.Types` no longer goes stale after changing the `enable` or `on_demand` flags in an existing build directory.+- The Makefile's paths now match where it clones Tracy.+  The clone is pinned to the supported release.+- The Makefile now builds in release mode by default.+  CMake's Makefile generator ignored its `--config Release` and built the client library without optimizations.+- The Makefile now builds the client library without Tracy's crash handler.+  The handler treats `SIGPIPE` as a crash.+  GHC's threaded runtime sends that signal to cancel `interruptible` foreign calls.+  This aborted the program while a profiler was connected.+  Existing checkouts need `make clean && make all` to pick this up.+ ## 0.1.2.1 - 2025-11-02  - Fix `-enable` build without having libtracyclient installed.
README.md view
@@ -6,8 +6,11 @@  ### Installing -You can install the prebuilt package from your distribution if it has one:+This version of the bindings targets Tracy 0.15.+Older releases have a different C API and will fail to link or misbehave. +You can install the prebuilt package from your distribution if it ships that release:+ ```sh sudo apt install libtracy-dev tracy-capture tracy-profiler ```@@ -26,12 +29,25 @@ ```sh make all # fetch and build stuff make test # run the example-_build/profiler/tracy-profiler & disown # launch the profiler GUI+upstream/_build/profiler/tracy-profiler & disown # launch the profiler GUI ``` +Everything is built in release mode.+Add `DEBUG=1` to any of those `make` commands for a debug build in `upstream/_build-debug`.+Debug builds keep Tracy's assertions on.+To use the debug library in your own project, point `extra-lib-dirs` at `upstream/_build-debug/library`.+ This way you can customize configuration. Make sure you update package flags to match. +The Makefile builds the library with `TRACY_NO_CRASH_HANDLER`.+That means the viewer won't get crash reports.+Tracy's crash handler treats `SIGPIPE` as a crash.+GHC's threaded runtime sends that signal to cancel `interruptible` foreign calls.+With the handler in place, `killThread` on a thread inside such a call aborts the program while a profiler is connected.+Any library built with the handler has this problem.+Check whether a distribution package was built with it.+ Either way, you have to ensure that `tracy-capture`/`tracy-profiler` is built with the same version. Otherwise it will connect and immediately refuse to record anything. @@ -49,9 +65,17 @@   tracy-profiler:     enable: true     # manual_lifetime: false+    # on_demand: false     # fibers: false ``` +To use on-demand mode, set the `on_demand` flag and link against a library built with `TRACY_ON_DEMAND`.+`make library-on-demand` builds one in `upstream/_build/library-on-demand`.+Point `extra-lib-dirs` there to use it.+The flag has to match the library.+The C API symbols don't encode that setting.+A mismatch links fine and then misbehaves at runtime.+ ## Instrumentation  Use the functions from `System.Tracy` and `System.Tracy.Zone` to collect data:@@ -63,12 +87,18 @@  module Main where +import Control.Monad (unless, when)+import System.Exit (die)+import System.IO (hPutStrLn, stderr) import qualified System.Tracy as Tracy import qualified Data.Text as Text  main :: IO () main = Tracy.withProfiler $ do-  Tracy.waitConnected_       -- wait for the tracy-capture to connect+  when Tracy.enabled do+    hPutStrLn stderr "Waiting for tracy-capture or tracy-profiler to connect on port 8086"+    isConnected <- Tracy.waitConnected 100000 (Just 30_000_000)+    unless isConnected $ die "Nothing connected within 30 seconds"   Tracy.withSrcLoc "main.nowhereInParticular" #f0fa do     Tracy.messageL "hi there"# -- static strings require no copying to be logged     mapM_ runFrame [0..600]@@ -84,6 +114,51 @@   Tracy.plotInt "digits"# digits ``` +Other modules cover more of the C API:++- `System.Tracy.Memory` reports allocations and frees.+- `System.Tracy.Section` marks high-level stretches of execution, such as a game level.+  Sections can overlap and aren't tied to a thread.+- `System.Tracy.Lock` and `System.Tracy.SharedLock` report waiting on and holding a lock.+  Give each one a location from `System.Tracy.SourceLocation.newSourceLocation`.+  The location stays allocated for the rest of the program because Tracy reads it later.+  Wait, obtain, shared release and mark events are recorded against the current OS thread.+  Use a bound thread to get them on the right timeline.+  Tracy 0.15's C API records a successful `SharedLock.tryAcquireShared` as an exclusive hold.+  The matching `releaseShared` doesn't end that hold.+- `System.Tracy.Zone.withSourceLocation` runs a zone from a location made once with `newSourceLocation`.+  `withSrcLoc` allocates a new location for every zone instead.+- `System.Tracy.Gpu` reports work done on the GPU.+  You issue the GPU timestamp queries yourself.+  Zones take an action that writes one and returns its query id.+  They call it at each end of the zone.+  Once the GPU has the results, pass each query id and its timestamp to `Gpu.time` in the order the queries were written.+  After that, the id can be reused.+  Tracy takes the first timestamp it gets for a zone as its start.+  `newContext` takes the length of a GPU tick in nanoseconds and a current GPU timestamp.+  Use `newCalibratedContext` instead for contexts that will get `calibration` events.+  The C API doesn't hand out context ids.+  Choose them from 0 to 255 yourself.+  Don't reuse ids of contexts made by C++ code in the same program.+  Tracy keeps one zone stack per context created through the C API.+  Zones in a context have to nest even across threads.+  With `on_demand`, a zone that starts before a viewer connects isn't recorded.+  Its timestamp actions aren't called.+  The module uses Tracy's serialized queue.+  It works from any thread.+  The unserialized GPU functions in `System.Tracy.FFI` are cheaper.+  They need all events for a context to come from one OS thread.+- `frameImage pixels width height lag flipped` attaches a screenshot to a frame.+  The pixels are RGBA.+  The width and height have to be multiples of 4.+  Tracy copies the pixels before `frameImage` returns.+  `lag` counts how many frames ago the image was taken.+  `flipped` means the rows go from bottom to top, as in OpenGL.++Call stack depths are only available through `System.Tracy.FFI` so far.++`beginSamplingProfiling` and `endSamplingProfiling` only take effect in a library built with `TRACY_SAMPLING_PROFILER_MANUAL_START`.+ ## Collecting and viewing  Start `tracy-capture` before running the test to avoid empty areas where nothing happens:@@ -92,7 +167,7 @@ tracy-capture -fo output.tracy & ``` -Run the code, then upload the collected data to [the viewer](https://tracy.nereid.pl/).+After running the code, upload the collected data to [the viewer](https://tracy.nereid.pl/).  You'll see something like this: @@ -100,8 +175,28 @@  > Are those are GC pauses we're looking at? 🤔 +### Sampling++On Linux, Tracy also samples call stacks and records context switches when `kernel.perf_event_paranoid` allows it.+Otherwise it logs a series of debug messages about failing to set up system tracing and carries on without it.++Sampled call stacks show up as ghost zones on threads that have no zones of their own.+In Haskell code, only the top frame of each sample can be trusted.+Tracy has the kernel build the rest by following frame pointers.+GHC uses the frame pointer register (`rbp` on x86-64) as its Haskell stack pointer instead.+The frames past the top one are leftovers from the Haskell stack.+Set `TRACY_NO_SAMPLING=1` in the program's environment to skip sampling while keeping context switches.+Ghost zones can also be hidden in the viewer.++Tracy names sampled frames from debug info or from the symbols an executable exports.+A GHC-built program has neither by default.+Its own frames show as `[unknown]`.+Add `-optl-rdynamic` to the executable's `ghc-options` to export them.+That names frames in the RTS, the Tracy client and Haskell code.+Haskell names come out in GHC's encoded form, such as `Main_main_info`.+ ## RTFM -You really should go read the official [manual](https://github.com/wolfpld/tracy/blob/master/manual/tracy.md).+You really should go read the official [manual](https://github.com/wolfpld/tracy/releases/download/v0.15.0/tracy.pdf).  Yes, BEFORE you run into corrupted memory, surprising grouppings, or otherwise botched profiling runs.
+ cbits/gpu_shim.c view
@@ -0,0 +1,124 @@+#include <stddef.h>+#include <stdint.h>++#include "TracyC.h"++void hs_tracy_emit_gpu_zone_begin(const struct ___tracy_source_location_data* srcloc, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_begin_data data = { .srcloc = (uint64_t)(uintptr_t)srcloc, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_begin(data);+}++void hs_tracy_emit_gpu_zone_begin_callstack(const struct ___tracy_source_location_data* srcloc, int32_t depth, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_begin_callstack_data data = { .srcloc = (uint64_t)(uintptr_t)srcloc, .depth = depth, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_begin_callstack(data);+}++void hs_tracy_emit_gpu_zone_begin_alloc(uint64_t srcloc, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_begin_data data = { .srcloc = srcloc, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_begin_alloc(data);+}++void hs_tracy_emit_gpu_zone_begin_alloc_callstack(uint64_t srcloc, int32_t depth, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_begin_callstack_data data = { .srcloc = srcloc, .depth = depth, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_begin_alloc_callstack(data);+}++void hs_tracy_emit_gpu_zone_end(uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_end_data data = { .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_end(data);+}++void hs_tracy_emit_gpu_time(int64_t gpuTime, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_time_data data = { .gpuTime = gpuTime, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_time(data);+}++void hs_tracy_emit_gpu_new_context(int64_t gpuTime, float period, uint8_t context, uint8_t flags, uint8_t type)+{+    struct ___tracy_gpu_new_context_data data = { .gpuTime = gpuTime, .period = period, .context = context, .flags = flags, .type = type };+    ___tracy_emit_gpu_new_context(data);+}++void hs_tracy_emit_gpu_context_name(uint8_t context, const char* name, uint16_t len)+{+    struct ___tracy_gpu_context_name_data data = { .context = context, .name = name, .len = len };+    ___tracy_emit_gpu_context_name(data);+}++void hs_tracy_emit_gpu_calibration(int64_t gpuTime, int64_t cpuDelta, uint8_t context)+{+    struct ___tracy_gpu_calibration_data data = { .gpuTime = gpuTime, .cpuDelta = cpuDelta, .context = context };+    ___tracy_emit_gpu_calibration(data);+}++void hs_tracy_emit_gpu_time_sync(int64_t gpuTime, uint8_t context)+{+    struct ___tracy_gpu_time_sync_data data = { .gpuTime = gpuTime, .context = context };+    ___tracy_emit_gpu_time_sync(data);+}++void hs_tracy_emit_gpu_zone_begin_serial(const struct ___tracy_source_location_data* srcloc, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_begin_data data = { .srcloc = (uint64_t)(uintptr_t)srcloc, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_begin_serial(data);+}++void hs_tracy_emit_gpu_zone_begin_callstack_serial(const struct ___tracy_source_location_data* srcloc, int32_t depth, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_begin_callstack_data data = { .srcloc = (uint64_t)(uintptr_t)srcloc, .depth = depth, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_begin_callstack_serial(data);+}++void hs_tracy_emit_gpu_zone_begin_alloc_serial(uint64_t srcloc, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_begin_data data = { .srcloc = srcloc, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_begin_alloc_serial(data);+}++void hs_tracy_emit_gpu_zone_begin_alloc_callstack_serial(uint64_t srcloc, int32_t depth, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_begin_callstack_data data = { .srcloc = srcloc, .depth = depth, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_begin_alloc_callstack_serial(data);+}++void hs_tracy_emit_gpu_zone_end_serial(uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_zone_end_data data = { .queryId = queryId, .context = context };+    ___tracy_emit_gpu_zone_end_serial(data);+}++void hs_tracy_emit_gpu_time_serial(int64_t gpuTime, uint16_t queryId, uint8_t context)+{+    struct ___tracy_gpu_time_data data = { .gpuTime = gpuTime, .queryId = queryId, .context = context };+    ___tracy_emit_gpu_time_serial(data);+}++void hs_tracy_emit_gpu_new_context_serial(int64_t gpuTime, float period, uint8_t context, uint8_t flags, uint8_t type)+{+    struct ___tracy_gpu_new_context_data data = { .gpuTime = gpuTime, .period = period, .context = context, .flags = flags, .type = type };+    ___tracy_emit_gpu_new_context_serial(data);+}++void hs_tracy_emit_gpu_context_name_serial(uint8_t context, const char* name, uint16_t len)+{+    struct ___tracy_gpu_context_name_data data = { .context = context, .name = name, .len = len };+    ___tracy_emit_gpu_context_name_serial(data);+}++void hs_tracy_emit_gpu_calibration_serial(int64_t gpuTime, int64_t cpuDelta, uint8_t context)+{+    struct ___tracy_gpu_calibration_data data = { .gpuTime = gpuTime, .cpuDelta = cpuDelta, .context = context };+    ___tracy_emit_gpu_calibration_serial(data);+}++void hs_tracy_emit_gpu_time_sync_serial(int64_t gpuTime, uint8_t context)+{+    struct ___tracy_gpu_time_sync_data data = { .gpuTime = gpuTime, .context = context };+    ___tracy_emit_gpu_time_sync_serial(data);+}
+ cbits/layout_check.c view
@@ -0,0 +1,14 @@+#include <stddef.h>+#include <stdint.h>++#include "TracyC.h"++#define POINTER_BYTES sizeof(void*)++_Static_assert(offsetof(struct ___tracy_source_location_data, name) == 0, "SourceLocationData name offset");+_Static_assert(offsetof(struct ___tracy_source_location_data, function) == POINTER_BYTES, "SourceLocationData function offset");+_Static_assert(offsetof(struct ___tracy_source_location_data, file) == 2 * POINTER_BYTES, "SourceLocationData file offset");+_Static_assert(offsetof(struct ___tracy_source_location_data, line) == 3 * POINTER_BYTES, "SourceLocationData line offset");+_Static_assert(offsetof(struct ___tracy_source_location_data, color) == 3 * POINTER_BYTES + 4, "SourceLocationData color offset");+_Static_assert(sizeof(struct ___tracy_source_location_data) == 3 * POINTER_BYTES + 8, "SourceLocationData size");+_Static_assert(_Alignof(struct ___tracy_source_location_data) == _Alignof(void*), "SourceLocationData alignment");
+ cbits/section_shim.c view
@@ -0,0 +1,14 @@+#include <stddef.h>+#include <stdint.h>++#include "TracyC.h"++uint32_t hs_tracy_section_enter(uint16_t category, const char* text, size_t size)+{+    return ___tracy_section_enter(category, "%.*s", (int)size, text ? text : "");+}++void hs_tracy_section_setup(uint16_t category, const char* text, size_t size)+{+    ___tracy_section_setup(category, "%.*s", (int)size, text ? text : "");+}
+ cbits/zone_shim.c view
@@ -0,0 +1,64 @@+#include <stddef.h>+#include <stdint.h>++#include "TracyC.h"++static void pack(TracyCZoneCtx ctx, uint64_t* out)+{+    out[0] = (uint64_t)ctx.id | ((uint64_t)(uint32_t)ctx.active << 32);+    out[1] = ctx.connectionId;+}++static TracyCZoneCtx unpack(uint64_t idAndActive, uint64_t connectionId)+{+    TracyCZoneCtx ctx;+    ctx.id = (uint32_t)idAndActive;+    ctx.active = (int32_t)(idAndActive >> 32);+    ctx.connectionId = connectionId;+    return ctx;+}++void hs_tracy_emit_zone_begin(const struct ___tracy_source_location_data* srcloc, int32_t active, uint64_t* out)+{+    pack(___tracy_emit_zone_begin(srcloc, active), out);+}++void hs_tracy_emit_zone_begin_callstack(const struct ___tracy_source_location_data* srcloc, int32_t depth, int32_t active, uint64_t* out)+{+    pack(___tracy_emit_zone_begin_callstack(srcloc, depth, active), out);+}++void hs_tracy_emit_zone_begin_alloc(uint64_t srcloc, int32_t active, uint64_t* out)+{+    pack(___tracy_emit_zone_begin_alloc(srcloc, active), out);+}++void hs_tracy_emit_zone_begin_alloc_callstack(uint64_t srcloc, int32_t depth, int32_t active, uint64_t* out)+{+    pack(___tracy_emit_zone_begin_alloc_callstack(srcloc, depth, active), out);+}++void hs_tracy_emit_zone_end(uint64_t idAndActive, uint64_t connectionId)+{+    ___tracy_emit_zone_end(unpack(idAndActive, connectionId));+}++void hs_tracy_emit_zone_text(uint64_t idAndActive, uint64_t connectionId, const char* txt, size_t size)+{+    ___tracy_emit_zone_text(unpack(idAndActive, connectionId), txt, size);+}++void hs_tracy_emit_zone_name(uint64_t idAndActive, uint64_t connectionId, const char* txt, size_t size)+{+    ___tracy_emit_zone_name(unpack(idAndActive, connectionId), txt, size);+}++void hs_tracy_emit_zone_color(uint64_t idAndActive, uint64_t connectionId, uint32_t color)+{+    ___tracy_emit_zone_color(unpack(idAndActive, connectionId), color);+}++void hs_tracy_emit_zone_value(uint64_t idAndActive, uint64_t connectionId, uint64_t value)+{+    ___tracy_emit_zone_value(unpack(idAndActive, connectionId), value);+}
src/System/Tracy.hs view
@@ -2,26 +2,44 @@ {-# LANGUAGE MagicHash #-}  module System.Tracy-  ( withProfiler+  ( -- * Profiler+    withProfiler+  , enabled   , connected   , waitConnected   , waitConnected_ +    -- * Program information   , setThreadName   , appInfo +    -- * Zones   , Zone.withSrcLoc +    -- * Frames   , frameMark   , frameMark_   , frameMarkStart   , frameMarkEnd+  , frameImage +    -- * Messages   , message   , messageC   , messageL   , messageLC+  , logString+  , logStringL+  , MessageSeverity(..) +    -- * Time+  , getTime++    -- * Sampling profiler+  , beginSamplingProfiling+  , endSamplingProfiling++    -- * Plots   , plot   , plotFloat   , plotInt@@ -30,30 +48,34 @@   , PlotFormat(..)  #ifdef TRACY_FIBERS+    -- * Fibers   , fiberEnter   , fiberLeave #endif +    -- * Colors   , Color   ) where  import Control.Monad (void) import Control.Monad.IO.Class (MonadIO(..))+import Data.Int (Int64) import Data.Text (Text)-import GHC.Exts (Addr#)+import Data.Word (Word8, Word16)+import GHC.Exts (Addr#, Ptr(..))  #if defined(TRACY_ENABLE) import Control.Concurrent (threadDelay) import Data.Maybe (fromMaybe) import Data.Text.Foreign qualified as Text-import Foreign (nullPtr)+import Foreign (castPtr, fromBool, nullPtr) import Foreign.C.ConstPtr (ConstPtr(..))-import GHC.Exts(Ptr(..)) import System.Timeout (timeout) import System.Tracy.FFI qualified as FFI+import System.Tracy.FFI.Types (clampTextBytes) #endif -import System.Tracy.FFI.Types (Color, PlotFormat(..))+import System.Tracy.FFI.Types (Color, MessageSeverity(..), PlotFormat(..)) import System.Tracy.Zone qualified as Zone  #if defined(TRACY_ENABLE) && defined(TRACY_MANUAL_LIFETIME)@@ -74,6 +96,13 @@ withProfiler = id #endif +enabled :: Bool+#if defined(TRACY_ENABLE)+enabled = True+#else+enabled = False+#endif+ {- | Check whether the profiler is connected. -} connected :: IO Bool@@ -155,45 +184,70 @@ frameMarkEnd _name = pure () #endif --- TODO: nicer wrapper for emitFrameImage+{-# INLINE frameImage #-}+frameImage :: MonadIO m => Ptr pixels -> Word16 -> Word16 -> Word8 -> Bool -> m ()+#if defined(TRACY_ENABLE)+frameImage image width height lag flipped = liftIO $+  FFI.emitFrameImage (ConstPtr $ castPtr image) width height lag (fromBool flipped)+#else+frameImage _image _width _height _lag _flipped = pure ()+#endif  {-# INLINE message #-} message :: MonadIO m => Text -> m ()+message = messageC 0++{-# INLINE messageC #-}+messageC :: MonadIO m => Color -> Text -> m ()+messageC = logString MessageSeverityInfo++{-# INLINE messageL #-}+messageL :: MonadIO m => Addr# -> m ()+messageL = messageLC 0++{-# INLINE messageLC #-}+messageLC :: MonadIO m => Color -> Addr# -> m ()+messageLC = logStringL MessageSeverityInfo++{-# INLINE logString #-}+logString :: MonadIO m => MessageSeverity -> Color -> Text -> m () #if defined(TRACY_ENABLE)-message txt = liftIO $+logString severity color txt = liftIO $   Text.withCStringLen txt \(txtPtr, txtSz) ->-    FFI.emitMessage (ConstPtr txtPtr) (fromIntegral txtSz) 0+    FFI.emitLogString (fromIntegral $ fromEnum severity) color 0 (clampTextBytes txtSz) (ConstPtr txtPtr) #else-message _txt = pure ()+logString _severity _color _txt = pure () #endif -{-# INLINE messageC #-}-messageC :: MonadIO m => Color -> Text -> m ()+{-# INLINE logStringL #-}+logStringL :: MonadIO m => MessageSeverity -> Color -> Addr# -> m () #if defined(TRACY_ENABLE)-messageC color txt = liftIO $-  Text.withCStringLen txt \(txtPtr, txtSz) ->-    FFI.emitMessageC (ConstPtr txtPtr) (fromIntegral txtSz) color 0+logStringL severity color txt = liftIO $+  FFI.emitLogStringL (fromIntegral $ fromEnum severity) color 0 (ConstPtr (Ptr txt)) #else-messageC _color _txt = pure ()+logStringL _severity _color _txt = pure () #endif +{-# INLINE getTime #-}+getTime :: MonadIO m => m Int64+#if defined(TRACY_ENABLE)+getTime = liftIO FFI.getTime+#else+getTime = pure 0+#endif -{-# INLINE messageL #-}-messageL :: MonadIO m => Addr# -> m ()+beginSamplingProfiling :: MonadIO m => m Bool #if defined(TRACY_ENABLE)-messageL txt = liftIO $-  FFI.emitMessageL (ConstPtr (Ptr txt)) 0+beginSamplingProfiling = liftIO $ (/= 0) <$> FFI.beginSamplingProfiling #else-messageL _txt = pure ()+beginSamplingProfiling = pure False #endif -{-# INLINE messageLC #-}-messageLC :: MonadIO m => Color -> Addr# -> m ()+endSamplingProfiling :: MonadIO m => m () #if defined(TRACY_ENABLE)-messageLC color txt = liftIO $-  FFI.emitMessageLC (ConstPtr (Ptr txt)) color 0+endSamplingProfiling = liftIO FFI.endSamplingProfiling #else-messageLC _color _txt = pure ()+endSamplingProfiling = pure () #endif  {-# INLINE plot #-}@@ -260,7 +314,7 @@ #if defined(TRACY_ENABLE) appInfo txt = liftIO $   Text.withCStringLen txt \(txtPtr, txtSz) ->-    FFI.emitMessageAppinfo (ConstPtr txtPtr) (fromIntegral txtSz)+    FFI.emitMessageAppinfo (ConstPtr txtPtr) (clampTextBytes txtSz) #else appInfo _txt = pure () #endif@@ -278,8 +332,7 @@ {-# INLINE fiberLeave #-} fiberLeave :: MonadIO m => m () #if defined(TRACY_ENABLE)-fiberLeave name val = liftIO $-  FFI.fiberLeave+fiberLeave = liftIO FFI.fiberLeave #else fiberLeave = pure () #endif
src/System/Tracy/FFI.hs view
@@ -1,13 +1,154 @@ {-# LANGUAGE BlockArguments #-} {-# LANGUAGE CPP #-} -module System.Tracy.FFI where+module System.Tracy.FFI+  ( -- * Profiler+    profilerStarted+#ifdef TRACY_MANUAL_LIFETIME+  , startupProfiler+  , shutdownProfiler+#endif+  , connected +    -- * Threads+  , setThreadName++    -- * Source locations+  , allocSrcloc+  , allocSrclocName++    -- * Zones+  , emitZoneBegin+  , emitZoneBeginCallstack+  , emitZoneBeginAlloc+  , emitZoneBeginAllocCallstack+  , emitZoneEnd+  , emitZoneText+  , emitZoneName+  , emitZoneColor+  , emitZoneValue+#ifdef TRACY_ON_DEMAND++    -- * On-demand zone shim+  , receiveZoneCtx+  , hsEmitZoneBegin+  , hsEmitZoneBeginCallstack+  , hsEmitZoneBeginAlloc+  , hsEmitZoneBeginAllocCallstack+  , hsEmitZoneEnd+  , hsEmitZoneText+  , hsEmitZoneName+  , hsEmitZoneColor+  , hsEmitZoneValue+#endif++    -- * GPU+  , emitGpuZoneBegin+  , emitGpuZoneBeginCallstack+  , emitGpuZoneBeginAlloc+  , emitGpuZoneBeginAllocCallstack+  , emitGpuZoneEnd+  , emitGpuTime+  , emitGpuNewContext+  , emitGpuContextName+  , emitGpuCalibration+  , emitGpuTimeSync++    -- * Serialized GPU+  , emitGpuZoneBeginSerial+  , emitGpuZoneBeginCallstackSerial+  , emitGpuZoneBeginAllocSerial+  , emitGpuZoneBeginAllocCallstackSerial+  , emitGpuZoneEndSerial+  , emitGpuTimeSerial+  , emitGpuNewContextSerial+  , emitGpuContextNameSerial+  , emitGpuCalibrationSerial+  , emitGpuTimeSyncSerial++    -- * Memory+  , emitMemoryAlloc+  , emitMemoryAllocCallstack+  , emitMemoryFree+  , emitMemoryFreeCallstack+  , emitMemoryAllocNamed+  , emitMemoryAllocCallstackNamed+  , emitMemoryFreeNamed+  , emitMemoryFreeCallstackNamed+  , emitMemoryDiscard+  , emitMemoryDiscardCallstack++    -- * Messages+  , emitLogString+  , emitLogStringL+  , emitMessageAppinfo++    -- * Frames+  , emitFrameMark+  , emitFrameMarkStart+  , emitFrameMarkEnd+  , emitFrameImage++    -- * Plots+  , emitPlot+  , emitPlotFloat+  , emitPlotInt+  , emitPlotConfig++    -- * Locks+  , announceLockableCtx+  , terminateLockableCtx+  , beforeLockLockableCtx+  , afterLockLockableCtx+  , beforeUnlockLockableCtx+  , afterTryLockLockableCtx+  , markLockableCtx+  , customNameLockableCtx++    -- * Shared locks+  , announceSharedLockableCtx+  , terminateSharedLockableCtx+  , beforeLockSharedLockableCtx+  , afterLockSharedLockableCtx+  , beforeUnlockSharedLockableCtx+  , afterTryLockSharedLockableCtx+  , beforeLockSharedSharedLockableCtx+  , afterLockSharedSharedLockableCtx+  , beforeUnlockSharedSharedLockableCtx+  , afterTryLockSharedSharedLockableCtx+  , markSharedLockableCtx+  , customNameSharedLockableCtx++    -- * Sections+  , sectionEnter+  , sectionLeave+  , sectionSetup++    -- * Time+  , getTime++    -- * Sampling profiler+  , beginSamplingProfiling+  , endSamplingProfiling++#ifdef TRACY_FIBERS+    -- * Fibers+  , fiberEnter+  , fiberLeave+#endif+  ) where+ import Data.Int import Data.Word import Foreign.C import Foreign.C.ConstPtr (ConstPtr(..)) +#ifdef TRACY_ON_DEMAND+import Foreign.Marshal.Array (allocaArray)+import Foreign.Ptr (Ptr)+import Foreign.Storable (peekElemOff)+#endif+ import System.Tracy.FFI.Types  ----------------------------------------------------------------@@ -30,10 +171,10 @@  foreign import ccall unsafe "___tracy_profiler_started"   profilerStarted-    :: Int+    :: IO Int32 #else-profilerStarted :: Int-profilerStarted = 1+profilerStarted :: IO Int32+profilerStarted = pure 1 #endif  ----------------------------------------------------------------@@ -62,6 +203,76 @@  ---------------------------------------------------------------- +#ifdef TRACY_ON_DEMAND+receiveZoneCtx :: (Ptr Word64 -> IO ()) -> IO TracyCZoneCtx+receiveZoneCtx begin =+  allocaArray 2 \out -> do+    begin out+    TracyCZoneCtx <$> peekElemOff out 0 <*> peekElemOff out 1++foreign import ccall unsafe "hs_tracy_emit_zone_begin"+  hsEmitZoneBegin :: ConstPtr SourceLocationData -> Int -> Ptr Word64 -> IO ()++emitZoneBegin :: ConstPtr SourceLocationData -> Int -> IO TracyCZoneCtx+emitZoneBegin srcloc active =+  receiveZoneCtx (hsEmitZoneBegin srcloc active)++foreign import ccall unsafe "hs_tracy_emit_zone_begin_callstack"+  hsEmitZoneBeginCallstack :: ConstPtr SourceLocationData -> Int -> Int -> Ptr Word64 -> IO ()++emitZoneBeginCallstack :: ConstPtr SourceLocationData -> Int -> Int -> IO TracyCZoneCtx+emitZoneBeginCallstack srcloc depth active =+  receiveZoneCtx (hsEmitZoneBeginCallstack srcloc depth active)++foreign import ccall unsafe "hs_tracy_emit_zone_begin_alloc"+  hsEmitZoneBeginAlloc :: SrcLoc -> Int -> Ptr Word64 -> IO ()++emitZoneBeginAlloc :: SrcLoc -> Int -> IO TracyCZoneCtx+emitZoneBeginAlloc srcloc active =+  receiveZoneCtx (hsEmitZoneBeginAlloc srcloc active)++foreign import ccall unsafe "hs_tracy_emit_zone_begin_alloc_callstack"+  hsEmitZoneBeginAllocCallstack :: SrcLoc -> Int -> Int -> Ptr Word64 -> IO ()++emitZoneBeginAllocCallstack :: SrcLoc -> Int -> Int -> IO TracyCZoneCtx+emitZoneBeginAllocCallstack srcloc depth active =+  receiveZoneCtx (hsEmitZoneBeginAllocCallstack srcloc depth active)++foreign import ccall unsafe "hs_tracy_emit_zone_end"+  hsEmitZoneEnd :: Word64 -> Word64 -> IO ()++emitZoneEnd :: TracyCZoneCtx -> IO ()+emitZoneEnd TracyCZoneCtx{..} =+  hsEmitZoneEnd idAndActive connectionId++foreign import ccall unsafe "hs_tracy_emit_zone_text"+  hsEmitZoneText :: Word64 -> Word64 -> ConstPtr CChar -> CSize -> IO ()++emitZoneText :: TracyCZoneCtx -> ConstPtr CChar -> CSize -> IO ()+emitZoneText TracyCZoneCtx{..} =+  hsEmitZoneText idAndActive connectionId++foreign import ccall unsafe "hs_tracy_emit_zone_name"+  hsEmitZoneName :: Word64 -> Word64 -> ConstPtr CChar -> CSize -> IO ()++emitZoneName :: TracyCZoneCtx -> ConstPtr CChar -> CSize -> IO ()+emitZoneName TracyCZoneCtx{..} =+  hsEmitZoneName idAndActive connectionId++foreign import ccall unsafe "hs_tracy_emit_zone_color"+  hsEmitZoneColor :: Word64 -> Word64 -> Color -> IO ()++emitZoneColor :: TracyCZoneCtx -> Color -> IO ()+emitZoneColor TracyCZoneCtx{..} =+  hsEmitZoneColor idAndActive connectionId++foreign import ccall unsafe "hs_tracy_emit_zone_value"+  hsEmitZoneValue :: Word64 -> Word64 -> Word64 -> IO ()++emitZoneValue :: TracyCZoneCtx -> Word64 -> IO ()+emitZoneValue TracyCZoneCtx{..} =+  hsEmitZoneValue idAndActive connectionId+#else foreign import ccall unsafe "___tracy_emit_zone_begin"   emitZoneBegin     :: ConstPtr SourceLocationData -- ^ srcloc@@ -118,38 +329,77 @@     :: TracyCZoneCtx     -> Word64     -> IO ()+#endif  ---------------------------------------------------------------- -{--TRACY_API void ___tracy_emit_gpu_zone_begin( const struct ___tracy_gpu_zone_begin_data );-TRACY_API void ___tracy_emit_gpu_zone_begin_callstack( const struct ___tracy_gpu_zone_begin_callstack_data );-TRACY_API void ___tracy_emit_gpu_zone_begin_alloc( const struct ___tracy_gpu_zone_begin_data );-TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_callstack( const struct ___tracy_gpu_zone_begin_callstack_data );-TRACY_API void ___tracy_emit_gpu_zone_end( const struct ___tracy_gpu_zone_end_data data );-TRACY_API void ___tracy_emit_gpu_time( const struct ___tracy_gpu_time_data );-TRACY_API void ___tracy_emit_gpu_new_context( const struct ___tracy_gpu_new_context_data );-TRACY_API void ___tracy_emit_gpu_context_name( const struct ___tracy_gpu_context_name_data );-TRACY_API void ___tracy_emit_gpu_calibration( const struct ___tracy_gpu_calibration_data );-TRACY_API void ___tracy_emit_gpu_time_sync( const struct ___tracy_gpu_time_sync_data );+foreign import ccall unsafe "hs_tracy_emit_gpu_zone_begin"+  emitGpuZoneBegin :: ConstPtr SourceLocationData -> Word16 -> Word8 -> IO () -TRACY_API void ___tracy_emit_gpu_zone_begin_serial( const struct ___tracy_gpu_zone_begin_data );-TRACY_API void ___tracy_emit_gpu_zone_begin_callstack_serial( const struct ___tracy_gpu_zone_begin_callstack_data );-TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_serial( const struct ___tracy_gpu_zone_begin_data );-TRACY_API void ___tracy_emit_gpu_zone_begin_alloc_callstack_serial( const struct ___tracy_gpu_zone_begin_callstack_data );-TRACY_API void ___tracy_emit_gpu_zone_end_serial( const struct ___tracy_gpu_zone_end_data data );-TRACY_API void ___tracy_emit_gpu_time_serial( const struct ___tracy_gpu_time_data );-TRACY_API void ___tracy_emit_gpu_new_context_serial( const struct ___tracy_gpu_new_context_data );-TRACY_API void ___tracy_emit_gpu_context_name_serial( const struct ___tracy_gpu_context_name_data );-TRACY_API void ___tracy_emit_gpu_calibration_serial( const struct ___tracy_gpu_calibration_data );-TRACY_API void ___tracy_emit_gpu_time_sync_serial( const struct ___tracy_gpu_time_sync_data );--}+foreign import ccall unsafe "hs_tracy_emit_gpu_zone_begin_callstack"+  emitGpuZoneBeginCallstack :: ConstPtr SourceLocationData -> Int32 -> Word16 -> Word8 -> IO () +foreign import ccall unsafe "hs_tracy_emit_gpu_zone_begin_alloc"+  emitGpuZoneBeginAlloc :: SrcLoc -> Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_zone_begin_alloc_callstack"+  emitGpuZoneBeginAllocCallstack :: SrcLoc -> Int32 -> Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_zone_end"+  emitGpuZoneEnd :: Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_time"+  emitGpuTime :: Int64 -> Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_new_context"+  emitGpuNewContext :: Int64 -> Float -> Word8 -> Word8 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_context_name"+  emitGpuContextName :: Word8 -> ConstPtr CChar -> Word16 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_calibration"+  emitGpuCalibration :: Int64 -> Int64 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_time_sync"+  emitGpuTimeSync :: Int64 -> Word8 -> IO ()+ ---------------------------------------------------------------- +foreign import ccall unsafe "hs_tracy_emit_gpu_zone_begin_serial"+  emitGpuZoneBeginSerial :: ConstPtr SourceLocationData -> Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_zone_begin_callstack_serial"+  emitGpuZoneBeginCallstackSerial :: ConstPtr SourceLocationData -> Int32 -> Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_zone_begin_alloc_serial"+  emitGpuZoneBeginAllocSerial :: SrcLoc -> Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_zone_begin_alloc_callstack_serial"+  emitGpuZoneBeginAllocCallstackSerial :: SrcLoc -> Int32 -> Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_zone_end_serial"+  emitGpuZoneEndSerial :: Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_time_serial"+  emitGpuTimeSerial :: Int64 -> Word16 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_new_context_serial"+  emitGpuNewContextSerial :: Int64 -> Float -> Word8 -> Word8 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_context_name_serial"+  emitGpuContextNameSerial :: Word8 -> ConstPtr CChar -> Word16 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_calibration_serial"+  emitGpuCalibrationSerial :: Int64 -> Int64 -> Word8 -> IO ()++foreign import ccall unsafe "hs_tracy_emit_gpu_time_sync_serial"+  emitGpuTimeSyncSerial :: Int64 -> Word8 -> IO ()++----------------------------------------------------------------+ foreign import ccall unsafe "___tracy_connected"   connected-    :: IO Int+    :: IO Int32  ---------------------------------------------------------------- @@ -157,7 +407,6 @@   emitMemoryAlloc     :: ConstPtr () -- ^ ptr     -> CSize       -- ^ size-    -> CInt        -- ^ secure     -> IO ()  foreign import ccall unsafe "___tracy_emit_memory_alloc_callstack"@@ -165,27 +414,23 @@     :: ConstPtr () -- ^ ptr     -> CSize       -- ^ size     -> CInt        -- ^ depth-    -> CInt        -- ^ secure     -> IO ()  foreign import ccall unsafe "___tracy_emit_memory_free"   emitMemoryFree     :: ConstPtr () -- ^ ptr-    -> CInt        -- ^ secure     -> IO ()  foreign import ccall unsafe "___tracy_emit_memory_free_callstack"   emitMemoryFreeCallstack     :: ConstPtr () -- ^ ptr     -> CInt        -- ^ depth-    -> CInt        -- ^ secure     -> IO ()  foreign import ccall unsafe "___tracy_emit_memory_alloc_named"   emitMemoryAllocNamed     :: ConstPtr ()    -- ^ ptr     -> CSize          -- ^ size-    -> CInt           -- ^ secure     -> ConstPtr CChar -- ^ name     -> IO () @@ -194,14 +439,12 @@     :: ConstPtr ()    -- ^ ptr     -> CSize          -- ^ size     -> CInt           -- ^ depth-    -> CInt           -- ^ secure     -> ConstPtr CChar -- ^ name     -> IO ()  foreign import ccall unsafe "___tracy_emit_memory_free_named"   emitMemoryFreeNamed     :: ConstPtr ()    -- ^ ptr-    -> CInt           -- ^ secure     -> ConstPtr CChar -- ^ name     -> IO () @@ -209,38 +452,32 @@   emitMemoryFreeCallstackNamed     :: ConstPtr ()    -- ^ ptr     -> CInt           -- ^ depth-    -> CInt           -- ^ secure     -> ConstPtr CChar -- ^ name     -> IO () -----------------------------------------------------------------+foreign import ccall unsafe "___tracy_emit_memory_discard"+  emitMemoryDiscard :: ConstPtr CChar -> IO () -foreign import ccall unsafe "___tracy_emit_message"-  emitMessage-    :: ConstPtr CChar -- ^ txt-    -> CSize          -- ^ size-    -> CInt           -- ^ callstack-    -> IO ()+foreign import ccall unsafe "___tracy_emit_memory_discard_callstack"+  emitMemoryDiscardCallstack :: ConstPtr CChar -> CInt -> IO () -foreign import ccall unsafe "___tracy_emit_messageL"-  emitMessageL-    :: ConstPtr CChar -- ^ txt-    -> CInt           -- ^ callstack-    -> IO ()+---------------------------------------------------------------- -foreign import ccall unsafe "___tracy_emit_messageC"-  emitMessageC-    :: ConstPtr CChar -- ^ txt-    -> CSize          -- ^ size-    -> Color          -- ^ color-    -> CInt           -- ^ callstack+foreign import ccall unsafe "___tracy_emit_logString"+  emitLogString+    :: Int8+    -> Color+    -> CInt+    -> CSize+    -> ConstPtr CChar     -> IO () -foreign import ccall unsafe "___tracy_emit_messageLC"-  emitMessageLC-    :: ConstPtr CChar -- ^ txt-    -> Color          -- ^ color-    -> CInt           -- ^ callstack+foreign import ccall unsafe "___tracy_emit_logStringL"+  emitLogStringL+    :: Int8+    -> Color+    -> CInt+    -> ConstPtr CChar     -> IO ()  ----------------------------------------------------------------@@ -307,16 +544,89 @@  ---------------------------------------------------------------- -{--TRACY_API struct __tracy_lockable_context_data* ___tracy_announce_lockable_ctx( const struct ___tracy_source_location_data* srcloc );-TRACY_API void ___tracy_terminate_lockable_ctx( struct __tracy_lockable_context_data* lockdata );-TRACY_API int ___tracy_before_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata );-TRACY_API void ___tracy_after_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata );-TRACY_API void ___tracy_after_unlock_lockable_ctx( struct __tracy_lockable_context_data* lockdata );-TRACY_API void ___tracy_after_try_lock_lockable_ctx( struct __tracy_lockable_context_data* lockdata, int acquired );-TRACY_API void ___tracy_mark_lockable_ctx( struct __tracy_lockable_context_data* lockdata, const struct ___tracy_source_location_data* srcloc );-TRACY_API void ___tracy_custom_name_lockable_ctx( struct __tracy_lockable_context_data* lockdata, const char* name, size_t nameSz );--}+foreign import ccall unsafe "___tracy_announce_lockable_ctx"+  announceLockableCtx :: ConstPtr SourceLocationData -> IO TracyCLockCtx++foreign import ccall unsafe "___tracy_terminate_lockable_ctx"+  terminateLockableCtx :: TracyCLockCtx -> IO ()++foreign import ccall unsafe "___tracy_before_lock_lockable_ctx"+  beforeLockLockableCtx :: TracyCLockCtx -> IO Int32++foreign import ccall unsafe "___tracy_after_lock_lockable_ctx"+  afterLockLockableCtx :: TracyCLockCtx -> IO ()++foreign import ccall unsafe "___tracy_before_unlock_lockable_ctx"+  beforeUnlockLockableCtx :: TracyCLockCtx -> IO ()++foreign import ccall unsafe "___tracy_after_try_lock_lockable_ctx"+  afterTryLockLockableCtx :: TracyCLockCtx -> Int32 -> IO ()++foreign import ccall unsafe "___tracy_mark_lockable_ctx"+  markLockableCtx :: TracyCLockCtx -> ConstPtr SourceLocationData -> IO ()++foreign import ccall unsafe "___tracy_custom_name_lockable_ctx"+  customNameLockableCtx :: TracyCLockCtx -> ConstPtr CChar -> CSize -> IO ()++----------------------------------------------------------------++foreign import ccall unsafe "___tracy_announce_shared_lockable_ctx"+  announceSharedLockableCtx :: ConstPtr SourceLocationData -> IO TracyCSharedLockCtx++foreign import ccall unsafe "___tracy_terminate_shared_lockable_ctx"+  terminateSharedLockableCtx :: TracyCSharedLockCtx -> IO ()++foreign import ccall unsafe "___tracy_before_lock_shared_lockable_ctx"+  beforeLockSharedLockableCtx :: TracyCSharedLockCtx -> IO Int32++foreign import ccall unsafe "___tracy_after_lock_shared_lockable_ctx"+  afterLockSharedLockableCtx :: TracyCSharedLockCtx -> IO ()++foreign import ccall unsafe "___tracy_before_unlock_shared_lockable_ctx"+  beforeUnlockSharedLockableCtx :: TracyCSharedLockCtx -> IO ()++foreign import ccall unsafe "___tracy_after_try_lock_shared_lockable_ctx"+  afterTryLockSharedLockableCtx :: TracyCSharedLockCtx -> Int32 -> IO ()++foreign import ccall unsafe "___tracy_before_lock_shared_shared_lockable_ctx"+  beforeLockSharedSharedLockableCtx :: TracyCSharedLockCtx -> IO Int32++foreign import ccall unsafe "___tracy_after_lock_shared_shared_lockable_ctx"+  afterLockSharedSharedLockableCtx :: TracyCSharedLockCtx -> IO ()++foreign import ccall unsafe "___tracy_before_unlock_shared_shared_lockable_ctx"+  beforeUnlockSharedSharedLockableCtx :: TracyCSharedLockCtx -> IO ()++foreign import ccall unsafe "___tracy_after_try_lock_shared_shared_lockable_ctx"+  afterTryLockSharedSharedLockableCtx :: TracyCSharedLockCtx -> Int32 -> IO ()++foreign import ccall unsafe "___tracy_mark_shared_lockable_ctx"+  markSharedLockableCtx :: TracyCSharedLockCtx -> ConstPtr SourceLocationData -> IO ()++foreign import ccall unsafe "___tracy_custom_name_shared_lockable_ctx"+  customNameSharedLockableCtx :: TracyCSharedLockCtx -> ConstPtr CChar -> CSize -> IO ()++----------------------------------------------------------------++foreign import ccall unsafe "hs_tracy_section_enter"+  sectionEnter :: Word16 -> ConstPtr CChar -> CSize -> IO Word32++foreign import ccall unsafe "___tracy_section_leave"+  sectionLeave :: Word32 -> IO ()++foreign import ccall unsafe "hs_tracy_section_setup"+  sectionSetup :: Word16 -> ConstPtr CChar -> CSize -> IO ()++----------------------------------------------------------------++foreign import ccall unsafe "___tracy_get_time"+  getTime :: IO Int64++foreign import ccall safe "___tracy_begin_sampling_profiling"+  beginSamplingProfiling :: IO CInt++foreign import ccall safe "___tracy_end_sampling_profiling"+  endSamplingProfiling :: IO ()  ---------------------------------------------------------------- 
+ src/System/Tracy/FFI/Types.hs view
@@ -0,0 +1,164 @@+{-# LANGUAGE CPP #-}++module System.Tracy.FFI.Types+  ( -- * Colors+    Color(..)++    -- * Source locations+  , SrcLoc(..)+  , SourceLocationData(..)+  , pointerBytes++    -- * Contexts+  , TracyCZoneCtx(..)+  , nullTracyCZoneCtx+  , TracyCLockCtx(..)+  , TracyCSharedLockCtx(..)++    -- * Plots+  , PlotFormat(..)++    -- * Messages+  , MessageSeverity(..)++    -- * GPU+  , GpuContextType(..)+  , gpuContextTypeCode++    -- * Text limits+  , maxTextBytes+  , clampTextBytes+  ) where++import Data.Word+import Foreign+import Foreign.C++import WebColor.Labels+import GHC.OverloadedLabels++{- | Packed 32-bit color++Hex literals can be used as @0xRRGGBB@.+Alternatively, "webcolors" notation is supported via labels: @#rgb@, @#rrggbb@, even some @#red@.+-}+newtype Color = Color Word32+  deriving (Show)+  deriving newtype (Eq, Ord, Storable, Num)++instance IsWebColorAlpha s => IsLabel s Color where+  fromLabel = webColorAlpha @s \r g b a ->+    Color $+      shiftL (fromIntegral a) 24 .|.+      shiftL (fromIntegral r) 16 .|.+      shiftL (fromIntegral g)  8 .|.+      fromIntegral b++newtype SrcLoc = SrcLoc Word64+  deriving (Show)+  deriving newtype (Eq, Ord, Storable)++data SourceLocationData = SourceLocationData+  { name     :: Ptr CChar+  , function :: Ptr CChar+  , file     :: Ptr CChar+  , line     :: Word32+  , color    :: Color+  }++pointerBytes :: Int+pointerBytes = sizeOf (nullPtr :: Ptr ())++instance Storable SourceLocationData where+  sizeOf (~_undef) = 3 * pointerBytes + 8++  alignment (~_undef) = pointerBytes++  peek ptr = do+    name     <- peekByteOff ptr 0+    function <- peekByteOff ptr pointerBytes+    file     <- peekByteOff ptr (2 * pointerBytes)+    line     <- peekByteOff ptr (3 * pointerBytes)+    color    <- peekByteOff ptr (3 * pointerBytes + 4)+    pure SourceLocationData{..}++  poke ptr SourceLocationData{..} = do+    pokeByteOff ptr 0 name+    pokeByteOff ptr pointerBytes function+    pokeByteOff ptr (2 * pointerBytes) file+    pokeByteOff ptr (3 * pointerBytes) line+    pokeByteOff ptr (3 * pointerBytes + 4) color++#ifdef TRACY_ON_DEMAND+data TracyCZoneCtx = TracyCZoneCtx+  { idAndActive  :: Word64+  , connectionId :: Word64+  }+  deriving (Eq, Ord, Show)++nullTracyCZoneCtx :: TracyCZoneCtx+nullTracyCZoneCtx = TracyCZoneCtx 0 0+#else+newtype TracyCZoneCtx = TracyCZoneCtx (Ptr TracyCZoneCtx)+  deriving (Show)+  deriving newtype (Eq, Ord, Storable)++nullTracyCZoneCtx :: TracyCZoneCtx+nullTracyCZoneCtx = TracyCZoneCtx nullPtr+#endif++newtype TracyCLockCtx = TracyCLockCtx (Ptr TracyCLockCtx)+  deriving (Show)+  deriving newtype (Eq, Ord, Storable)++newtype TracyCSharedLockCtx = TracyCSharedLockCtx (Ptr TracyCSharedLockCtx)+  deriving (Show)+  deriving newtype (Eq, Ord, Storable)++data PlotFormat+  = PlotFormatNumber -- ^ values will be displayed as plain numbers.+  | PlotFormatMemory -- ^ treats the values as memory sizes. Will display kilobytes, megabytes, etc.+  | PlotFormatPercentage -- ^ values will be displayed as percentage (with value @100@ being equal to 100%).+  | PlotFormatWatt+  deriving (Eq, Ord, Show, Enum, Bounded)++data MessageSeverity+  = MessageSeverityTrace+  | MessageSeverityDebug+  | MessageSeverityInfo+  | MessageSeverityWarning+  | MessageSeverityError+  | MessageSeverityFatal+  deriving (Eq, Ord, Show, Enum, Bounded)++data GpuContextType+  = GpuContextTypeOpenGl+  | GpuContextTypeVulkan+  | GpuContextTypeOpenCL+  | GpuContextTypeDirect3D12+  | GpuContextTypeDirect3D11+  | GpuContextTypeMetal+  | GpuContextTypeCustom+  | GpuContextTypeCUDA+  | GpuContextTypeRocprof+  | GpuContextTypeWebGPU+  deriving (Eq, Ord, Show, Bounded)++gpuContextTypeCode :: GpuContextType -> Word8+gpuContextTypeCode = \case+  GpuContextTypeOpenGl -> 1+  GpuContextTypeVulkan -> 2+  GpuContextTypeOpenCL -> 3+  GpuContextTypeDirect3D12 -> 4+  GpuContextTypeDirect3D11 -> 5+  GpuContextTypeMetal -> 6+  GpuContextTypeCustom -> 7+  GpuContextTypeCUDA -> 8+  GpuContextTypeRocprof -> 9+  GpuContextTypeWebGPU -> 10++maxTextBytes :: Int+maxTextBytes = 65534++clampTextBytes :: Int -> CSize+clampTextBytes = fromIntegral . min maxTextBytes
− src/System/Tracy/FFI/Types.hsc
@@ -1,76 +0,0 @@-module System.Tracy.FFI.Types where--import Data.Word-import Foreign-import Foreign.C--import WebColor.Labels-import GHC.OverloadedLabels--{- | Packed 32-bit color--Hex literals can be used as @0xRRGGBB@.-Alternatively, "webcolors" notation is supported via labels: @#rgb@, @#rrggbb@, even some @#red@.--}-newtype Color = Color Word32-  deriving (Show)-  deriving newtype (Eq, Ord, Storable, Num)--instance IsWebColorAlpha s => IsLabel s Color where-  fromLabel = webColorAlpha @s \r g b a ->-    Color $-      shiftL (fromIntegral a) 24 .|.-      shiftL (fromIntegral r) 16 .|.-      shiftL (fromIntegral g)  8 .|.-      fromIntegral b--newtype SrcLoc = SrcLoc Word64-  deriving (Show)-  deriving newtype (Eq, Ord, Storable)--data SourceLocationData = SourceLocationData-  { name     :: Ptr CChar-  , function :: Ptr CChar-  , file     :: Ptr CChar-  , line     :: Word32-  , color    :: Color-  }--#ifdef TRACY_ENABLE-#include "TracyC.h"--instance Storable SourceLocationData where-  sizeOf (~_undef) = (#size struct ___tracy_source_location_data)--  alignment (~_undef) = (#alignment struct ___tracy_source_location_data)--  peek ptr = do-    name     <- (#peek struct ___tracy_source_location_data, name) ptr-    function <- (#peek struct ___tracy_source_location_data, function) ptr-    file     <- (#peek struct ___tracy_source_location_data, file) ptr-    line     <- (#peek struct ___tracy_source_location_data, line) ptr-    color    <- (#peek struct ___tracy_source_location_data, color) ptr-    pure SourceLocationData{..}--  poke ptr SourceLocationData{..} = do-    (#poke struct ___tracy_source_location_data, name) ptr name-    (#poke struct ___tracy_source_location_data, function) ptr function-    (#poke struct ___tracy_source_location_data, file) ptr file-    (#poke struct ___tracy_source_location_data, line) ptr line-    (#poke struct ___tracy_source_location_data, color) ptr color--#endif--newtype TracyCZoneCtx = TracyCZoneCtx (Ptr TracyCZoneCtx)-  deriving (Show)-  deriving newtype (Eq, Ord, Storable)--nullTracyCZoneCtx :: TracyCZoneCtx-nullTracyCZoneCtx = TracyCZoneCtx nullPtr--data PlotFormat-  = PlotFormatNumber -- ^ values will be displayed as plain numbers.-  | PlotFormatMemory -- ^ treats the values as memory sizes. Will display kilobytes, megabytes, etc.-  | PlotFormatPercentage -- ^ values will be displayed as percentage (with value @100@ being equal to 100%).-  | PlotFormatWatt-  deriving (Eq, Ord, Show, Enum, Bounded)
+ src/System/Tracy/Gpu.hs view
@@ -0,0 +1,219 @@+{-# LANGUAGE CPP #-}++module System.Tracy.Gpu+  ( -- * Contexts+    Context(..)+  , GpuContextType(..)+  , newContext+  , newCalibratedContext+  , contextName++    -- * Scoped zones+  , withSrcLoc+  , withSourceLocation++    -- * Manual zones+  , Zone(..)+  , beginSrcLoc+  , beginSourceLocation+  , end++    -- * Timestamps+  , time+  , calibration+  , timeSync+  ) where++import Control.Monad.IO.Class (MonadIO(..))+import Data.ByteString (ByteString)+import Data.Int (Int64)+import Data.Text (Text)+import Data.Word (Word8, Word16)++#ifdef TRACY_ENABLE+import Control.Exception (bracket)+import Control.Monad.IO.Unlift (MonadUnliftIO, withRunInIO)+import Data.ByteString.Char8 qualified as ByteString+import Data.Text.Foreign qualified as Text+import Foreign.C.ConstPtr (ConstPtr(..))+import GHC.Stack (HasCallStack, SrcLoc(..), callStack, getCallStack, withFrozenCallStack)++import System.Tracy.FFI qualified as FFI+import System.Tracy.FFI.Types (gpuContextTypeCode, maxTextBytes)+import System.Tracy.Zone qualified as Zone+#endif++import System.Tracy.FFI.Types (Color, GpuContextType(..))+import System.Tracy.SourceLocation (SourceLocation(..))++newtype Context = Context Word8+  deriving (Eq, Ord, Show)++newtype Zone = Zone (Maybe Context)+  deriving (Eq, Ord, Show)++uncalibratedFlags :: Word8+uncalibratedFlags = 0++calibratedFlags :: Word8+calibratedFlags = 1++{-# INLINE newContext #-}+newContext :: MonadIO m => Context -> GpuContextType -> Float -> Int64 -> m ()+newContext = emitNewContext uncalibratedFlags++{-# INLINE newCalibratedContext #-}+newCalibratedContext :: MonadIO m => Context -> GpuContextType -> Float -> Int64 -> m ()+newCalibratedContext = emitNewContext calibratedFlags++{-# INLINE emitNewContext #-}+emitNewContext :: MonadIO m => Word8 -> Context -> GpuContextType -> Float -> Int64 -> m ()+#ifdef TRACY_ENABLE+emitNewContext flags (Context contextId) contextType period gpuTime = liftIO $+  FFI.emitGpuNewContextSerial gpuTime period contextId flags (gpuContextTypeCode contextType)+#else+emitNewContext _flags _context _contextType _period _gpuTime = pure ()+#endif++{-# INLINE contextName #-}+contextName :: MonadIO m => Context -> Text -> m ()+#ifdef TRACY_ENABLE+contextName (Context contextId) txt = liftIO $+  Text.withCStringLen txt \(txtPtr, txtSz) ->+    FFI.emitGpuContextNameSerial contextId (ConstPtr txtPtr) (fromIntegral $ min maxTextBytes txtSz)+#else+contextName _context _txt = pure ()+#endif++{-# INLINE withSrcLoc #-}+{-# INLINE withSourceLocation #-}+#ifdef TRACY_ENABLE+withSrcLoc+  :: (HasCallStack, MonadUnliftIO m)+  => Context+  -> ByteString+  -> Color+  -> m Word16+  -> m Word16+  -> m a+  -> m a+withSrcLoc context function col writeBeginTimestamp =+  withZone (withFrozenCallStack (beginSrcLoc context function col writeBeginTimestamp))++withSourceLocation+  :: MonadUnliftIO m+  => Context+  -> SourceLocation+  -> m Word16+  -> m Word16+  -> m a+  -> m a+withSourceLocation context location writeBeginTimestamp =+  withZone (beginSourceLocation context location writeBeginTimestamp)++{-# INLINE withZone #-}+withZone :: MonadUnliftIO m => m Zone -> m Word16 -> m a -> m a+withZone begin writeEndTimestamp action =+  withRunInIO \run ->+    bracket+      (run begin)+      (\zone -> run $ end zone writeEndTimestamp)+      (\_zone -> run action)+#else+withSrcLoc :: Context -> ByteString -> Color -> m Word16 -> m Word16 -> m a -> m a+withSrcLoc _context _function _col _writeBeginTimestamp _writeEndTimestamp action = action++withSourceLocation :: Context -> SourceLocation -> m Word16 -> m Word16 -> m a -> m a+withSourceLocation _context _location _writeBeginTimestamp _writeEndTimestamp action = action+#endif++{-# INLINE beginSrcLoc #-}+#ifdef TRACY_ENABLE+beginSrcLoc :: (HasCallStack, MonadIO m) => Context -> ByteString -> Color -> m Word16 -> m Zone+beginSrcLoc context@(Context contextId) function col writeTimestamp =+  case getCallStack callStack of+    (_called, SrcLoc{srcLocFile, srcLocStartLine}) : _callers ->+      beginWith context writeTimestamp \queryId -> do+        srcloc <-+          Zone.allocSrcloc+            (fromIntegral srcLocStartLine)+            (ByteString.pack srcLocFile)+            function+            Nothing+            col+        FFI.emitGpuZoneBeginAllocSerial srcloc queryId contextId+    [] ->+      error "beginSrcLoc ought to have HasCallStack in context"+#else+beginSrcLoc :: MonadIO m => Context -> ByteString -> Color -> m Word16 -> m Zone+beginSrcLoc _context _function _col _writeTimestamp = pure $ Zone Nothing+#endif++{-# INLINE beginSourceLocation #-}+beginSourceLocation :: MonadIO m => Context -> SourceLocation -> m Word16 -> m Zone+#ifdef TRACY_ENABLE+beginSourceLocation context@(Context contextId) (SourceLocation locationData) writeTimestamp =+  beginWith context writeTimestamp \queryId ->+    FFI.emitGpuZoneBeginSerial locationData queryId contextId+#else+beginSourceLocation _context _location _writeTimestamp = pure $ Zone Nothing+#endif++#ifdef TRACY_ENABLE+{-# INLINE beginWith #-}+beginWith :: MonadIO m => Context -> m Word16 -> (Word16 -> IO ()) -> m Zone+beginWith context writeTimestamp emitBegin = do+  recording <- liftIO isRecording+  if recording then do+    queryId <- writeTimestamp+    liftIO $ emitBegin queryId+    pure . Zone $ Just context+  else+    pure $ Zone Nothing++{-# INLINE isRecording #-}+isRecording :: IO Bool+#ifdef TRACY_ON_DEMAND+isRecording = (/= 0) <$> FFI.connected+#else+isRecording = pure True+#endif+#endif++{-# INLINE end #-}+end :: MonadIO m => Zone -> m Word16 -> m ()+#ifdef TRACY_ENABLE+end (Zone (Just (Context contextId))) writeTimestamp = do+  queryId <- writeTimestamp+  liftIO $ FFI.emitGpuZoneEndSerial queryId contextId+end (Zone Nothing) _writeTimestamp = pure ()+#else+end _zone _writeTimestamp = pure ()+#endif++{-# INLINE time #-}+time :: MonadIO m => Context -> Word16 -> Int64 -> m ()+#ifdef TRACY_ENABLE+time (Context contextId) queryId gpuTime = liftIO $+  FFI.emitGpuTimeSerial gpuTime queryId contextId+#else+time _context _queryId _gpuTime = pure ()+#endif++{-# INLINE calibration #-}+calibration :: MonadIO m => Context -> Int64 -> Int64 -> m ()+#ifdef TRACY_ENABLE+calibration (Context contextId) gpuTime cpuDelta = liftIO $+  FFI.emitGpuCalibrationSerial gpuTime cpuDelta contextId+#else+calibration _context _gpuTime _cpuDelta = pure ()+#endif++{-# INLINE timeSync #-}+timeSync :: MonadIO m => Context -> Int64 -> m ()+#ifdef TRACY_ENABLE+timeSync (Context contextId) gpuTime = liftIO $+  FFI.emitGpuTimeSyncSerial gpuTime contextId+#else+timeSync _context _gpuTime = pure ()+#endif
+ src/System/Tracy/Lock.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE CPP #-}++module System.Tracy.Lock+  ( -- * Lifetime+    Lock(..)+  , announce+  , terminate++    -- * Locking+  , acquire+  , tryAcquire+  , release++    -- * Annotations+  , mark+  , customName+  ) where++import Control.Monad.IO.Class (MonadIO(..))+import Data.Text (Text)++#ifdef TRACY_ENABLE+import Control.Monad (when)+import Data.Text.Foreign qualified as Text+import Foreign.C.ConstPtr (ConstPtr(..))+import Foreign.Marshal.Utils (fromBool)++import System.Tracy.FFI qualified as FFI+#else+import Foreign.Ptr (nullPtr)+#endif++import System.Tracy.FFI.Types qualified as FFI+import System.Tracy.SourceLocation (SourceLocation(..))++newtype Lock = Lock FFI.TracyCLockCtx++{-# INLINE announce #-}+announce :: MonadIO m => SourceLocation -> m Lock+#ifdef TRACY_ENABLE+announce (SourceLocation location) = liftIO $ Lock <$> FFI.announceLockableCtx location+#else+announce _location = pure . Lock $ FFI.TracyCLockCtx nullPtr+#endif++{-# INLINE terminate #-}+terminate :: MonadIO m => Lock -> m ()+#ifdef TRACY_ENABLE+terminate (Lock ctx) = liftIO $ FFI.terminateLockableCtx ctx+#else+terminate _lock = pure ()+#endif++{-# INLINE acquire #-}+#ifdef TRACY_ENABLE+acquire :: MonadIO m => Lock -> m a -> m a+acquire (Lock ctx) takeLock = do+  waitRecorded <- liftIO $ FFI.beforeLockLockableCtx ctx+  result <- takeLock+  when (waitRecorded /= 0) . liftIO $ FFI.afterLockLockableCtx ctx+  pure result+#else+acquire :: Lock -> a -> a+acquire _lock takeLock = takeLock+#endif++{-# INLINE tryAcquire #-}+#ifdef TRACY_ENABLE+tryAcquire :: MonadIO m => Lock -> m Bool -> m Bool+tryAcquire (Lock ctx) tryTakeLock = do+  acquired <- tryTakeLock+  liftIO . FFI.afterTryLockLockableCtx ctx $ fromBool acquired+  pure acquired+#else+tryAcquire :: Lock -> a -> a+tryAcquire _lock tryTakeLock = tryTakeLock+#endif++{-# INLINE release #-}+#ifdef TRACY_ENABLE+release :: MonadIO m => Lock -> m a -> m a+release (Lock ctx) releaseLock = do+  liftIO $ FFI.beforeUnlockLockableCtx ctx+  releaseLock+#else+release :: Lock -> a -> a+release _lock releaseLock = releaseLock+#endif++{-# INLINE mark #-}+mark :: MonadIO m => Lock -> SourceLocation -> m ()+#ifdef TRACY_ENABLE+mark (Lock ctx) (SourceLocation location) = liftIO $ FFI.markLockableCtx ctx location+#else+mark _lock _location = pure ()+#endif++{-# INLINE customName #-}+customName :: MonadIO m => Lock -> Text -> m ()+#ifdef TRACY_ENABLE+customName (Lock ctx) txt = liftIO $+  Text.withCStringLen txt \(txtPtr, txtSz) ->+    FFI.customNameLockableCtx ctx (ConstPtr txtPtr) (FFI.clampTextBytes txtSz)+#else+customName _lock _txt = pure ()+#endif
src/System/Tracy/Memory.hs view
@@ -3,7 +3,11 @@  {-| Tracing memory allocations -https://github.com/wolfpld/tracy/blob/master/manual/tracy.md#memory-profiling-memoryprofiling+https://github.com/wolfpld/tracy/releases/download/v0.15.0/tracy.pdf++Events have to reach Tracy in the order the allocations and frees really happened.+If several threads allocate at once, hold a lock across each allocation or free and its report.+Otherwise a freed address can be handed out again and reported before its free is, which fails the capture. -}  module System.Tracy.Memory@@ -13,6 +17,7 @@     -- * Memory pools   , allocNamed   , freeNamed+  , discard   ) where  import Control.Monad.IO.Class (MonadIO(..))@@ -30,55 +35,63 @@ {-# INLINE alloc #-} alloc   :: MonadIO m-  => Bool  -- ^ secure-  -> Ptr a -- ^ address to register+  => Ptr a -- ^ address to register   -> Int   -- ^ size   -> m () #ifdef TRACY_ENABLE-alloc secure ptr size =-  liftIO $ FFI.emitMemoryAlloc (ConstPtr $ castPtr ptr) (fromIntegral size) (fromIntegral $ fromEnum secure)+alloc ptr size =+  liftIO $ FFI.emitMemoryAlloc (ConstPtr $ castPtr ptr) (fromIntegral size) #else-alloc _secure _ptr _size = pure ()+alloc _ptr _size = pure () #endif  {-# INLINE free #-} free   :: MonadIO m-  => Bool  -- ^ secure-  -> Ptr a -- ^ address that was registered+  => Ptr a -- ^ address that was registered   -> m () #ifdef TRACY_ENABLE-free secure ptr =-  liftIO $ FFI.emitMemoryFree (ConstPtr $ castPtr ptr) (fromIntegral $ fromEnum secure)+free ptr =+  liftIO $ FFI.emitMemoryFree (ConstPtr $ castPtr ptr) #else-free _secure _ptr = pure ()+free _ptr = pure () #endif  {-# INLINE allocNamed #-} allocNamed   :: MonadIO m-  => Bool  -- ^ secure-  -> Ptr a -- ^ address to register+  => Ptr a -- ^ address to register   -> Int   -- ^ size   -> Addr# -- ^ memory pool name   -> m () #ifdef TRACY_ENABLE-allocNamed secure ptr size name =-  liftIO $ FFI.emitMemoryAllocNamed (ConstPtr $ castPtr ptr) (fromIntegral size) (fromIntegral $ fromEnum secure) (ConstPtr $ Ptr name)+allocNamed ptr size name =+  liftIO $ FFI.emitMemoryAllocNamed (ConstPtr $ castPtr ptr) (fromIntegral size) (ConstPtr $ Ptr name) #else-allocNamed _secure _ptr _size _name = pure ()+allocNamed _ptr _size _name = pure () #endif  {-# INLINE freeNamed #-} freeNamed   :: MonadIO m-  => Bool  -- ^ secure-  -> Ptr a -- ^ address that was registered+  => Ptr a -- ^ address that was registered   -> Addr# -- ^ memory pool name   -> m () #ifdef TRACY_ENABLE-freeNamed secure ptr name =-  liftIO $ FFI.emitMemoryFreeNamed (ConstPtr $ castPtr ptr) (fromIntegral $ fromEnum secure) (ConstPtr $ Ptr name)+freeNamed ptr name =+  liftIO $ FFI.emitMemoryFreeNamed (ConstPtr $ castPtr ptr) (ConstPtr $ Ptr name) #else-freeNamed _secure _ptr _name = pure ()+freeNamed _ptr _name = pure ()+#endif++{-# INLINE discard #-}+discard+  :: MonadIO m+  => Addr# -- ^ memory pool name+  -> m ()+#ifdef TRACY_ENABLE+discard name =+  liftIO $ FFI.emitMemoryDiscard (ConstPtr $ Ptr name)+#else+discard _name = pure () #endif
+ src/System/Tracy/Section.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE CPP #-}++module System.Tracy.Section+  ( -- * Scoped sections+    with+  , withCategory++    -- * Manual sections+  , Section(..)+  , enter+  , enterCategory+  , leave++    -- * Categories+  , setup+  ) where++import Control.Monad.IO.Class (MonadIO(..))+import Data.Text (Text)+import Data.Word (Word16, Word32)++#ifdef TRACY_ENABLE+import Control.Exception (bracket)+import Control.Monad.IO.Unlift (MonadUnliftIO, withRunInIO)+import Data.Text.Foreign qualified as Text+import Foreign.C.ConstPtr (ConstPtr(..))++import System.Tracy.FFI qualified as FFI+import System.Tracy.FFI.Types (clampTextBytes)+#endif++newtype Section = Section Word32++{-# INLINE enter #-}+enter :: MonadIO m => Text -> m Section+enter = enterCategory 0++{-# INLINE enterCategory #-}+enterCategory :: MonadIO m => Word16 -> Text -> m Section+#ifdef TRACY_ENABLE+enterCategory category txt = liftIO $+  Text.withCStringLen txt \(txtPtr, txtSz) ->+    Section <$> FFI.sectionEnter category (ConstPtr txtPtr) (clampTextBytes txtSz)+#else+enterCategory _category _txt = pure $ Section 0+#endif++{-# INLINE leave #-}+leave :: MonadIO m => Section -> m ()+#ifdef TRACY_ENABLE+leave (Section sectionId) = liftIO $ FFI.sectionLeave sectionId+#else+leave _section = pure ()+#endif++{-# INLINE setup #-}+setup :: MonadIO m => Word16 -> Text -> m ()+#ifdef TRACY_ENABLE+setup category txt = liftIO $+  Text.withCStringLen txt \(txtPtr, txtSz) ->+    FFI.sectionSetup category (ConstPtr txtPtr) (clampTextBytes txtSz)+#else+setup _category _txt = pure ()+#endif++#ifdef TRACY_ENABLE+with :: MonadUnliftIO m => Text -> m a -> m a+with = withCategory 0++withCategory :: MonadUnliftIO m => Word16 -> Text -> m a -> m a+withCategory category txt action =+  withRunInIO \run ->+    bracket (enterCategory category txt) leave \_section -> run action+#else+with :: Text -> a -> a+with _txt action = action++withCategory :: Word16 -> Text -> a -> a+withCategory _category _txt action = action+#endif
+ src/System/Tracy/SharedLock.hs view
@@ -0,0 +1,147 @@+{-# LANGUAGE CPP #-}++module System.Tracy.SharedLock+  ( -- * Lifetime+    SharedLock(..)+  , announce+  , terminate++    -- * Exclusive locking+  , acquire+  , tryAcquire+  , release++    -- * Shared locking+  , acquireShared+  , tryAcquireShared+  , releaseShared++    -- * Annotations+  , mark+  , customName+  ) where++import Control.Monad.IO.Class (MonadIO(..))+import Data.Text (Text)++#ifdef TRACY_ENABLE+import Control.Monad (when)+import Data.Text.Foreign qualified as Text+import Foreign.C.ConstPtr (ConstPtr(..))+import Foreign.Marshal.Utils (fromBool)++import System.Tracy.FFI qualified as FFI+#else+import Foreign.Ptr (nullPtr)+#endif++import System.Tracy.FFI.Types qualified as FFI+import System.Tracy.SourceLocation (SourceLocation(..))++newtype SharedLock = SharedLock FFI.TracyCSharedLockCtx++{-# INLINE announce #-}+announce :: MonadIO m => SourceLocation -> m SharedLock+#ifdef TRACY_ENABLE+announce (SourceLocation location) = liftIO $ SharedLock <$> FFI.announceSharedLockableCtx location+#else+announce _location = pure . SharedLock $ FFI.TracyCSharedLockCtx nullPtr+#endif++{-# INLINE terminate #-}+terminate :: MonadIO m => SharedLock -> m ()+#ifdef TRACY_ENABLE+terminate (SharedLock ctx) = liftIO $ FFI.terminateSharedLockableCtx ctx+#else+terminate _lock = pure ()+#endif++{-# INLINE acquire #-}+#ifdef TRACY_ENABLE+acquire :: MonadIO m => SharedLock -> m a -> m a+acquire (SharedLock ctx) takeLock = do+  waitRecorded <- liftIO $ FFI.beforeLockSharedLockableCtx ctx+  result <- takeLock+  when (waitRecorded /= 0) . liftIO $ FFI.afterLockSharedLockableCtx ctx+  pure result+#else+acquire :: SharedLock -> a -> a+acquire _lock takeLock = takeLock+#endif++{-# INLINE tryAcquire #-}+#ifdef TRACY_ENABLE+tryAcquire :: MonadIO m => SharedLock -> m Bool -> m Bool+tryAcquire (SharedLock ctx) tryTakeLock = do+  acquired <- tryTakeLock+  liftIO . FFI.afterTryLockSharedLockableCtx ctx $ fromBool acquired+  pure acquired+#else+tryAcquire :: SharedLock -> a -> a+tryAcquire _lock tryTakeLock = tryTakeLock+#endif++{-# INLINE release #-}+#ifdef TRACY_ENABLE+release :: MonadIO m => SharedLock -> m a -> m a+release (SharedLock ctx) releaseLock = do+  liftIO $ FFI.beforeUnlockSharedLockableCtx ctx+  releaseLock+#else+release :: SharedLock -> a -> a+release _lock releaseLock = releaseLock+#endif++{-# INLINE acquireShared #-}+#ifdef TRACY_ENABLE+acquireShared :: MonadIO m => SharedLock -> m a -> m a+acquireShared (SharedLock ctx) takeLock = do+  waitRecorded <- liftIO $ FFI.beforeLockSharedSharedLockableCtx ctx+  result <- takeLock+  when (waitRecorded /= 0) . liftIO $ FFI.afterLockSharedSharedLockableCtx ctx+  pure result+#else+acquireShared :: SharedLock -> a -> a+acquireShared _lock takeLock = takeLock+#endif++{-# INLINE tryAcquireShared #-}+#ifdef TRACY_ENABLE+tryAcquireShared :: MonadIO m => SharedLock -> m Bool -> m Bool+tryAcquireShared (SharedLock ctx) tryTakeLock = do+  acquired <- tryTakeLock+  liftIO . FFI.afterTryLockSharedSharedLockableCtx ctx $ fromBool acquired+  pure acquired+#else+tryAcquireShared :: SharedLock -> a -> a+tryAcquireShared _lock tryTakeLock = tryTakeLock+#endif++{-# INLINE releaseShared #-}+#ifdef TRACY_ENABLE+releaseShared :: MonadIO m => SharedLock -> m a -> m a+releaseShared (SharedLock ctx) releaseLock = do+  liftIO $ FFI.beforeUnlockSharedSharedLockableCtx ctx+  releaseLock+#else+releaseShared :: SharedLock -> a -> a+releaseShared _lock releaseLock = releaseLock+#endif++{-# INLINE mark #-}+mark :: MonadIO m => SharedLock -> SourceLocation -> m ()+#ifdef TRACY_ENABLE+mark (SharedLock ctx) (SourceLocation location) = liftIO $ FFI.markSharedLockableCtx ctx location+#else+mark _lock _location = pure ()+#endif++{-# INLINE customName #-}+customName :: MonadIO m => SharedLock -> Text -> m ()+#ifdef TRACY_ENABLE+customName (SharedLock ctx) txt = liftIO $+  Text.withCStringLen txt \(txtPtr, txtSz) ->+    FFI.customNameSharedLockableCtx ctx (ConstPtr txtPtr) (FFI.clampTextBytes txtSz)+#else+customName _lock _txt = pure ()+#endif
+ src/System/Tracy/SourceLocation.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE CPP #-}++module System.Tracy.SourceLocation+  ( SourceLocation(..)+  , newSourceLocation+  ) where++import Control.Monad.IO.Class (MonadIO(..))+import Data.ByteString (ByteString)+import Foreign.C.ConstPtr (ConstPtr(..))+import Foreign.Ptr (nullPtr)++#ifdef TRACY_ENABLE+import Data.ByteString.Char8 qualified as ByteString+import Foreign.C.String (newCAString)+import Foreign.Marshal.Utils (new)+import GHC.Stack (HasCallStack, SrcLoc(..), callStack, getCallStack)+#endif++import System.Tracy.FFI.Types qualified as FFI++newtype SourceLocation = SourceLocation (ConstPtr FFI.SourceLocationData)++#ifdef TRACY_ENABLE+newSourceLocation :: (HasCallStack, MonadIO m) => ByteString -> FFI.Color -> m SourceLocation+newSourceLocation function color = liftIO case getCallStack callStack of+  (_called, SrcLoc{srcLocFile, srcLocStartLine}) : _callers -> do+    functionName <- newCAString (ByteString.unpack function)+    fileName <- newCAString srcLocFile+    SourceLocation . ConstPtr <$>+      new (FFI.SourceLocationData nullPtr functionName fileName (fromIntegral srcLocStartLine) color)+  [] ->+    error "newSourceLocation ought to have HasCallStack in context"+#else+newSourceLocation :: MonadIO m => ByteString -> FFI.Color -> m SourceLocation+newSourceLocation _function _color = pure $ SourceLocation (ConstPtr nullPtr)+#endif
src/System/Tracy/Zone.hs view
@@ -4,6 +4,7 @@ module System.Tracy.Zone   ( -- * Declare zones     withSrcLoc+  , withSourceLocation      -- * Update zone context   , text@@ -28,23 +29,26 @@ import Data.ByteString.Unsafe (unsafeUseAsCStringLen) import Data.Text.Foreign qualified as Text import Foreign.C.ConstPtr (ConstPtr(..))+import Foreign.C.String (peekCAString)+import Foreign.Storable (peek) import GHC.Stack import GHC.Stack.Types qualified as GHC  #ifndef ZONES_UNSAFE-import Control.Concurrent (isCurrentThreadBound)+import Control.Concurrent (isCurrentThreadBound, rtsSupportsBoundThreads)+-- !unsafe+#endif #ifdef ZONES_PEDANTIC import System.Exit (die) -- pedantic #endif--- !unsafe-#endif  import System.Tracy.FFI qualified as FFI -- enable #endif  import System.Tracy.FFI.Types qualified as FFI+import System.Tracy.SourceLocation (SourceLocation(..))  {- | Allocate SrcLoc and run a Zone with it. @@ -60,8 +64,11 @@   -- ... @ -NB: Zones can only be used on a bound thread.-Main thread is safe, but the rest should use one of forkOn/asyncBound/runInBoundThread.+NB: With the threaded runtime, zones can only be used on a bound thread.+Main thread is safe, but the rest should use one of forkOS/asyncBound/runInBoundThread.++The non-threaded runtime has no bound threads and runs everything on a single OS thread, so the check is skipped there.+Zones from different Haskell threads must not overlap in that case, or the capture will fail. -} {-# INLINE withSrcLoc #-} withSrcLoc@@ -112,35 +119,77 @@ withSrcLocImpl _line _file _function _col inIO action =   inIO $ let ?zoneCtx = FFI.nullTracyCZoneCtx in action #else-withSrcLocImpl line file function col inIO action = do-#ifdef ZONES_UNSAFE+withSrcLocImpl line file function col inIO action =   runZone+    (pure $ ByteString.unpack file <> ":" <> show line)+    inIO+    (allocSrcloc line file function Nothing col >>= \srcloc -> FFI.emitZoneBeginAlloc srcloc 1)+    action+-- TRACY_ENABLE+#endif++{-# INLINE withSourceLocation #-}+#ifdef TRACY_ENABLE+withSourceLocation+  :: MonadUnliftIO m+  => SourceLocation+  -> ((?zoneCtx :: FFI.TracyCZoneCtx) => m a)+  -> m a+withSourceLocation location@(SourceLocation locationData) action = withRunInIO \inIO ->+  runZone+    (describeSourceLocation location)+    inIO+    (FFI.emitZoneBegin locationData 1)+    action #else-  bound <- isCurrentThreadBound-  if bound then-    runZone+withSourceLocation+  :: SourceLocation+  -> ((?zoneCtx :: FFI.TracyCZoneCtx) => m a)+  -> m a+withSourceLocation _location action = let ?zoneCtx = FFI.nullTracyCZoneCtx in action+#endif++#ifdef TRACY_ENABLE+{-# INLINE runZone #-}+runZone+  :: IO String+  -> (m a -> IO a)+  -> IO FFI.TracyCZoneCtx+  -> ((?zoneCtx :: FFI.TracyCZoneCtx) => m a)+  -> IO a+runZone location inIO beginZone action = do+  onStableOsThread <- canStartZone+  if onStableOsThread then+    bracket beginZone FFI.emitZoneEnd \ctx -> inIO $ let ?zoneCtx = ctx in action   else-#ifdef ZONES_PEDANTIC-    {--      XXX: Will not actually crash the whole program, only the thread.-      But at least there would be a console notice when this happens.-    -}-    die $ ByteString.unpack file <> ":" <> show line <> " Starting a zone on unbound thread"+    unboundZone location . inIO $ let ?zoneCtx = FFI.nullTracyCZoneCtx in action++{-# INLINE canStartZone #-}+canStartZone :: IO Bool+#ifdef ZONES_UNSAFE+canStartZone = pure True #else-    inIO $ let ?zoneCtx = FFI.nullTracyCZoneCtx in action+canStartZone = if rtsSupportsBoundThreads then isCurrentThreadBound else pure True #endif --- ZONES_UNSAFE+unboundZone :: IO String -> IO a -> IO a+#ifdef ZONES_PEDANTIC+unboundZone location _withoutZone = do+  {-+    XXX: Will not actually crash the whole program, only the thread.+    But at least there would be a console notice when this happens.+  -}+  zoneLocation <- location+  die $ zoneLocation <> " Starting a zone on unbound thread"+#else+unboundZone _location withoutZone = withoutZone #endif-  where-    {-# INLINE runZone #-}-    runZone = do-      srcloc <- allocSrcloc line file function Nothing col-      bracket-        (FFI.emitZoneBeginAlloc srcloc 1)-        FFI.emitZoneEnd-        (\ctx -> inIO $ let ?zoneCtx = ctx in action)--- TRACY_ENABLE++describeSourceLocation :: SourceLocation -> IO String+describeSourceLocation (SourceLocation (ConstPtr locationData)) = do+  FFI.SourceLocationData{file, line} <- peek locationData+  fileName <- peekCAString file+  pure $ fileName <> ":" <> show line #endif  {- | Prepare a single-use location identifier@@ -183,16 +232,6 @@             col #endif -{- TODO: Wrap emitZoneBegin--This needs keeping SourceLocationData structures filled with pinned pointers.-Otherwise the data would be pulled much later, outside a potential with/bracket scope-with garbage/crashes as a result.--Some nice solution would require interning SourceLocationData and its data.-Otherwise it's a copying galore and Tracy may fail to deduplicate the locations.--}- {-# INLINE text #-} #ifndef TRACY_ENABLE text :: MonadIO m => Text -> m ()@@ -201,7 +240,7 @@ text :: (MonadIO m, ?zoneCtx :: FFI.TracyCZoneCtx) => Text -> m () text txt = liftIO $   Text.withCStringLen txt \(txtPtr, txtSz) ->-    FFI.emitZoneText ?zoneCtx (ConstPtr txtPtr) (fromIntegral txtSz)+    FFI.emitZoneText ?zoneCtx (ConstPtr txtPtr) (FFI.clampTextBytes txtSz) #endif  {-# INLINE name #-}@@ -212,7 +251,7 @@ name :: (MonadIO m, ?zoneCtx :: FFI.TracyCZoneCtx) => Text -> m () name txt = liftIO $   Text.withCStringLen txt \(txtPtr, txtSz) ->-    FFI.emitZoneName ?zoneCtx (ConstPtr txtPtr) (fromIntegral txtSz)+    FFI.emitZoneName ?zoneCtx (ConstPtr txtPtr) (FFI.clampTextBytes txtSz) #endif  {-# INLINE color #-}
test/Readme.hs view
@@ -4,12 +4,18 @@  module Main where +import Control.Monad (unless, when)+import System.Exit (die)+import System.IO (hPutStrLn, stderr) import qualified System.Tracy as Tracy import qualified Data.Text as Text  main :: IO () main = Tracy.withProfiler $ do-  Tracy.waitConnected_       -- wait for the tracy-capture to connect+  when Tracy.enabled do+    hPutStrLn stderr "Waiting for tracy-capture or tracy-profiler to connect on port 8086"+    isConnected <- Tracy.waitConnected 100000 (Just 30_000_000)+    unless isConnected $ die "Nothing connected within 30 seconds"   Tracy.withSrcLoc "main.nowhereInParticular" #f0fa do     Tracy.messageL "hi there"# -- static strings require no copying to be logged     mapM_ runFrame [0..600]
tracy-profiler.cabal view
@@ -1,11 +1,11 @@ cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.38.1.+-- This file has been generated from package.yaml by hpack version 0.39.6. -- -- see: https://github.com/sol/hpack  name:           tracy-profiler-version:        0.1.2.1+version:        0.2.0.0 synopsis:       Haskell bindings for Tracy frame profiler category:       Profiling homepage:       https://github.com/haskell-game/tracy-profiler#readme@@ -65,7 +65,12 @@       System.Tracy       System.Tracy.FFI       System.Tracy.FFI.Types+      System.Tracy.Gpu+      System.Tracy.Lock       System.Tracy.Memory+      System.Tracy.Section+      System.Tracy.SharedLock+      System.Tracy.SourceLocation       System.Tracy.Zone   other-modules:       Paths_tracy_profiler@@ -87,7 +92,7 @@       ImplicitParams   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -O2   build-depends:-      base >=4.16 && <5+      base >=4.18 && <5     , bytestring     , text >=2.0 && <3     , unliftio-core@@ -95,13 +100,21 @@   default-language: GHC2021   if flag(enable)     cpp-options: -DTRACY_ENABLE+    cc-options: -DTRACY_ENABLE+    c-sources:+        cbits/gpu_shim.c+        cbits/layout_check.c+        cbits/section_shim.c     extra-libraries:         TracyClient         stdc+++    if flag(on_demand)+      cpp-options: -DTRACY_ON_DEMAND+      cc-options: -DTRACY_ON_DEMAND+      c-sources:+          cbits/zone_shim.c   if flag(manual_lifetime)     cpp-options: -DTRACY_MANUAL_LIFETIME-  if flag(on_demand)-    cpp-options: -DTRACY_ON_DEMAND   if flag(fibers)     cpp-options: -DTRACY_FIBERS   if flag(has_callstack)@@ -134,7 +147,7 @@       ImplicitParams   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N   build-depends:-      base >=4.16 && <5+      base >=4.18 && <5     , random     , text     , tracy-profiler