using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Profiling.LowLevel;
using Unity.Profiling.LowLevel.Unsafe;
namespace Unity.Profiling
{
///
/// Reports a value of an integer or floating point type to the Unity Profiler.
///
/// int, uint, long, ulong, float or double type.
#if ENABLE_PROFILER
[StructLayout(LayoutKind.Sequential)]
#else
[StructLayout(LayoutKind.Sequential, Size = 0)]
#endif
public readonly struct ProfilerCounter where T : unmanaged
{
#if ENABLE_PROFILER
[NativeDisableUnsafePtrRestriction]
[NonSerialized]
readonly IntPtr m_Ptr;
[NonSerialized]
readonly byte m_Type;
#endif
///
/// Constructs a **ProfilerCounter** that is reported to the Unity Profiler whenever you call Sample().
///
/// Profiler category.
/// Name of ProfilerCounter.
/// Value unit type.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ProfilerCounter(ProfilerCategory category, string name, ProfilerMarkerDataUnit dataUnit)
{
#if ENABLE_PROFILER
m_Type = ProfilerUtility.GetProfilerMarkerDataType();
m_Ptr = ProfilerUnsafeUtility.CreateMarker(name, category, MarkerFlags.Counter, 1);
ProfilerUnsafeUtility.SetMarkerMetadata(m_Ptr, 0, null, m_Type, (byte)dataUnit);
#endif
}
///
/// Sends the value to Unity Profiler immediately.
///
/// Does nothing in Release Players.
/// The value to send to the profiler.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Conditional("ENABLE_PROFILER")]
[Pure]
public void Sample(T value)
{
#if ENABLE_PROFILER
unsafe
{
var data = new ProfilerMarkerData
{
Type = m_Type,
Size = (uint)UnsafeUtility.SizeOf(),
Ptr = UnsafeUtility.AddressOf(ref value)
};
ProfilerUnsafeUtility.SingleSampleWithMetadata(m_Ptr, 1, &data);
}
#endif
}
}
}