/*
 * Copyright (C) 2023-2025 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 *
 */

#ifndef _ZET_INTEL_GPU_METRIC_H
#define _ZET_INTEL_GPU_METRIC_H

#include "level_zero/include/level_zero/ze_stypes.h"
#include <level_zero/zet_api.h>

#if defined(__cplusplus)
#pragma once
extern "C" {
#endif

#include <stdint.h>

#define ZET_INTEL_GPU_METRIC_VERSION_MAJOR 0
#define ZET_INTEL_GPU_METRIC_VERSION_MINOR 2
#define ZET_INTEL_MAX_METRIC_GROUP_NAME_PREFIX_EXP 64u
#define ZET_INTEL_METRIC_PROGRAMMABLE_PARAM_TYPE_GENERIC_EXP (0x7ffffffe)

#ifndef ZET_INTEL_METRIC_SOURCE_ID_EXP_NAME
/// @brief Extension name for query to read the Intel Metric source ID
#define ZET_INTEL_METRIC_SOURCE_ID_EXP_NAME "ZET_intel_metric_source_id"
#endif // ZET_INTEL_METRIC_SOURCE_ID_EXP_NAME

///////////////////////////////////////////////////////////////////////////////
/// @brief Metric Source Id extension Version(s)
typedef enum _zet_intel_metric_source_id_exp_version_t {
    ZET_INTEL_METRIC_SOURCE_ID_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),     ///< version 1.0
    ZET_INTEL_METRIC_SOURCE_ID_EXP_VERSION_CURRENT = ZE_MAKE_VERSION(1, 0), ///< latest known version
    ZET_INTEL_METRIC_SOURCE_ID_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_source_id_exp_version_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Query an unique identifier representing the source of a metric group
/// This structure can be passed in the 'pNext' of zet_metric_group_properties_t
typedef struct _zet_intel_metric_source_id_exp_t {
    zet_structure_type_ext_t stype; ///< [in] type of this structure
    const void *pNext;              ///< [in][optional] must be null or a pointer to an extension-specific
                                    ///< structure (i.e. contains stype and pNext).
    uint32_t sourceId;              ///< [out] Returns an unique source Id of the metric group
} zet_intel_metric_source_id_exp_t;

#ifndef ZET_INTEL_METRIC_APPEND_MARKER_EXP_NAME
/// @brief Extension name for query to read the Intel Metric append marker
#define ZET_INTEL_METRIC_APPEND_MARKER_EXP_NAME "ZET_intel_metric_append_marker"
#endif // ZET_INTEL_APPEND_MARKER_EXP_NAME

///////////////////////////////////////////////////////////////////////////////
/// @brief Append Marker extension Version(s)
typedef enum _zet_intel_metric_append_marker_exp_version_t {
    ZET_INTEL_METRIC_APPEND_MARKER_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),     ///< version 1.0
    ZET_INTEL_METRIC_APPEND_MARKER_EXP_VERSION_CURRENT = ZE_MAKE_VERSION(1, 0), ///< latest known version
    ZET_INTEL_METRIC_APPEND_MARKER_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_append_marker_exp_version_t;

#define ZET_INTEL_METRIC_GROUP_TYPE_EXP_FLAG_MARKER (static_cast<zet_metric_group_type_exp_flags_t>(ZE_BIT(3)))

///////////////////////////////////////////////////////////////////////////////
/// @brief Appends a metric marker to the command list based on the metricGroup
/// Metrics can be generated by multiple sources in the HW
/// This API generates a marker through the same source as the metric group
ze_result_t ZE_APICALL zetIntelCommandListAppendMarkerExp(zet_command_list_handle_t hCommandList,
                                                          zet_metric_group_handle_t hMetricGroup,
                                                          uint32_t value);

typedef zet_metric_tracer_exp_desc_t zet_intel_metric_tracer_exp_desc_t;
typedef zet_metric_tracer_exp_handle_t zet_intel_metric_tracer_exp_handle_t;
typedef zet_metric_decoder_exp_handle_t zet_intel_metric_decoder_exp_handle_t;
typedef zet_metric_entry_exp_t zet_intel_metric_entry_exp_t;

ze_result_t ZE_APICALL zetIntelMetricTracerCreateExp(
    zet_context_handle_t hContext,                       ///< [in] handle of the context object
    zet_device_handle_t hDevice,                         ///< [in] handle of the device
    uint32_t metricGroupCount,                           ///< [in] metric group count
    zet_metric_group_handle_t *phMetricGroups,           ///< [in][range(0, metricGroupCount )] handles of the metric groups to
                                                         ///< trace
    zet_intel_metric_tracer_exp_desc_t *desc,            ///< [in,out] metric tracer descriptor
    ze_event_handle_t hNotificationEvent,                ///< [in][optional] event used for report availability notification. Note:
                                                         ///< If buffer is not drained when the event it flagged, there is a risk of
                                                         ///< HW event buffer being overrun
    zet_intel_metric_tracer_exp_handle_t *phMetricTracer ///< [out] handle of the metric tracer
);

ze_result_t ZE_APICALL zetIntelMetricTracerDestroyExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer ///< [in] handle of the metric tracer
);

ze_result_t ZE_APICALL zetIntelMetricTracerEnableExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer, ///< [in] handle of the metric tracer
    ze_bool_t synchronous                               ///< [in] request synchronous behavior. Confirmation of successful
                                                        ///< asynchronous operation is done by calling ::zetMetricTracerReadDataExp()
                                                        ///< and checking the return status: ::ZE_RESULT_NOT_READY will be returned
                                                        ///< when the tracer is inactive. ::ZE_RESULT_SUCCESS will be returned
                                                        ///< when the tracer is active.
);

ze_result_t ZE_APICALL zetIntelMetricTracerDisableExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer, ///< [in] handle of the metric tracer
    ze_bool_t synchronous                               ///< [in] request synchronous behavior. Confirmation of successful
                                                        ///< asynchronous operation is done by calling ::zetMetricTracerReadDataExp()
                                                        ///< and checking the return status: ::ZE_RESULT_SUCCESS will be returned
                                                        ///< when the tracer is active or when it is inactive but still has data.
                                                        ///< ::ZE_RESULT_NOT_READY will be returned when the tracer is inactive and
                                                        ///< has no more data to be retrieved.
);

ze_result_t ZE_APICALL zetIntelMetricTracerReadDataExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer, ///< [in] handle of the metric tracer
    size_t *pRawDataSize,                               ///< [in,out] pointer to size in bytes of raw data requested to read.
                                                        ///< if size is zero, then the driver will update the value with the total
                                                        ///< size in bytes needed for all data available.
                                                        ///< if size is non-zero, then driver will only retrieve that amount of
                                                        ///< data.
                                                        ///< if size is larger than size needed for all data, then driver will
                                                        ///< update the value with the actual size needed.
    uint8_t *pRawData                                   ///< [in,out][optional][range(0, *pRawDataSize)] buffer containing tracer
                                                        ///< data in raw format
);

ze_result_t ZE_APICALL zetIntelMetricDecoderCreateExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer,    ///< [in] handle of the metric tracer
    zet_intel_metric_decoder_exp_handle_t *phMetricDecoder ///< [out] handle of the metric decoder object
);

ze_result_t ZE_APICALL zetIntelMetricDecoderDestroyExp(
    zet_intel_metric_decoder_exp_handle_t phMetricDecoder ///< [in] handle of the metric decoder object
);

ze_result_t ZE_APICALL zetIntelMetricDecoderGetDecodableMetricsExp(
    zet_intel_metric_decoder_exp_handle_t hMetricDecoder, ///< [in] handle of the metric decoder object
    uint32_t *pCount,                                     ///< [in,out] pointer to number of decodable metric in the hMetricDecoder
                                                          ///< handle. If count is zero, then the driver shall
                                                          ///< update the value with the total number of decodable metrics available
                                                          ///< in the decoder. if count is greater than zero
                                                          ///< but less than the total number of decodable metrics available in the
                                                          ///< decoder, then only that number will be returned.
                                                          ///< if count is greater than the number of decodable metrics available in
                                                          ///< the decoder, then the driver shall update the
                                                          ///< value with the actual number of decodable metrics available.
    zet_metric_handle_t *phMetrics                        ///< [in,out] [range(0, *pCount)] array of handles of decodable metrics in
                                                          ///< the hMetricDecoder handle provided.
);

ze_result_t ZE_APICALL zetIntelMetricTracerDecodeExp(
    zet_intel_metric_decoder_exp_handle_t phMetricDecoder, ///< [in] handle of the metric decoder object
    size_t *pRawDataSize,                                  ///< [in,out] size in bytes of raw data buffer. If pMetricEntriesCount is
                                                           ///< greater than zero but less than total number of
                                                           ///< decodable metrics available in the raw data buffer, then driver shall
                                                           ///< update this value with actual number of raw
                                                           ///< data bytes processed.
    uint8_t *pRawData,                                     ///< [in,out][optional][range(0, *pRawDataSize)] buffer containing tracer
                                                           ///< data in raw format
    uint32_t metricsCount,                                 ///< [in] number of decodable metrics in the tracer for which the
                                                           ///< hMetricDecoder handle was provided. See
                                                           ///< ::zetMetricDecoderGetDecodableMetricsExp(). If metricCount is greater
                                                           ///< than zero but less than the number decodable
                                                           ///< metrics available in the raw data buffer, then driver shall only
                                                           ///< decode those.
    zet_metric_handle_t *phMetrics,                        ///< [in] [range(0, metricsCount)] array of handles of decodable metrics in
                                                           ///< the decoder for which the hMetricDecoder handle was
                                                           ///< provided. Metrics handles are expected to be for decodable metrics,
                                                           ///< see ::zetMetricDecoderGetDecodableMetricsExp()
    uint32_t *pSetCount,                                   ///< [in,out] pointer to number of metric sets. If count is zero, then the
                                                           ///< driver shall update the value with the total
                                                           ///< number of metric sets to be decoded. If count is greater than the
                                                           ///< number available in the raw data buffer, then the
                                                           ///< driver shall update the value with the actual number of metric sets to
                                                           ///< be decoded. There is a 1:1 relation between
                                                           ///< the number of sets and sub-devices returned in the decoded entries.
    uint32_t *pMetricEntriesCountPerSet,                   ///< [in,out][optional][range(0, *pSetCount)] buffer of metric entries
                                                           ///< counts per metric set, one value per set.
    uint32_t *pMetricEntriesCount,                         ///< [in,out]  pointer to the total number of metric entries decoded, for
                                                           ///< all metric sets. If count is zero, then the
                                                           ///< driver shall update the value with the total number of metric entries
                                                           ///< to be decoded. If count is greater than zero
                                                           ///< but less than the total number of metric entries available in the raw
                                                           ///< data, then user provided number will be decoded.
                                                           ///< If count is greater than the number available in the raw data buffer,
                                                           ///< then the driver shall update the value with
                                                           ///< the actual number of decodable metric entries decoded. If set to null,
                                                           ///< then driver will only update the value of
                                                           ///< pSetCount.
    zet_intel_metric_entry_exp_t *pMetricEntries           ///< [in,out][optional][range(0, *pMetricEntriesCount)] buffer containing
                                                           ///< decoded metric entries
);

#ifndef ZET_INTEL_METRIC_CALCULATE_EXP_NAME
/// @brief Extension name to query Intel Metric Calculate operations
#define ZET_INTEL_METRIC_CALCULATE_EXP_NAME "ZET_intel_metric_calculate"
#endif // ZET_INTEL_METRIC_CALCULATE_EXP_NAME
///////////////////////////////////////////////////////////////////////////////
/// @brief Metric Calculate extension Version(s)
typedef enum _zet_intel_metric_calculate_exp_version_t {
    ZET_INTEL_METRIC_CALCULATE_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0), ///< version 1.0
    ZET_INTEL_METRIC_CALCULATE_EXP_VERSION_2_0 = ZE_MAKE_VERSION(2, 0),
    ZET_INTEL_METRIC_CALCULATE_EXP_VERSION_CURRENT = ZET_INTEL_METRIC_CALCULATE_EXP_VERSION_2_0, ///< latest known version
    ZET_INTEL_METRIC_CALCULATE_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_calculate_exp_version_t;

#ifndef ZET_STRUCTURE_TYPE_INTEL_METRIC_CALCULATE_PROPERTIES_EXP
#define ZET_STRUCTURE_TYPE_INTEL_METRIC_CALCULATE_PROPERTIES_EXP 0x7fffffff
#endif // ZET_STRUCTURE_TYPE_INTEL_METRIC_CALCULATE_PROPERTIES_EXP

///////////////////////////////////////////////////////////////////////////////
/// @brief Query an metric group calculate properties
/// This structure can be passed in the 'pNext' of zet_metric_group_properties_t
typedef struct _zet_intel_metric_group_calculate_properties_exp_t {
    zet_structure_type_ext_t stype; ///< [in] type of this structure
    void *pNext;                    ///< [in][optional] must be null or a pointer to an extension-specific
                                    ///< structure (i.e. contains stype and pNext).
    bool isTimeFilterSupported;     ///< [out] Flag to indicate if the metric group supports time filtering for
                                    ///< metrics calculation.
} zet_intel_metric_group_calculate_properties_exp_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of metric calculate operation
struct _zet_intel_metric_calculate_operation_exp_handle_t {};
typedef struct _zet_intel_metric_calculate_operation_exp_handle_t *zet_intel_metric_calculate_operation_exp_handle_t;

typedef struct _zet_intel_metric_calculate_time_window_exp_t {
    uint64_t windowStart; ///< [in] starting time in nanoseconds of the raw data to where WindowSize
                          ///< is selected. If WindowStart + WindowSize is bigger than the total
                          ///< time of the raw data collected, only a fraction of the window will be used.
    uint64_t windowSize;  ///< [in] size in nanoseconds of the faction of the raw data used for calculation.
} zet_intel_metric_calculate_time_window_exp_t;

typedef struct _zet_intel_metric_calculate_exp_desc_t {
    zet_structure_type_ext_t stype;                                      ///< [in] type of this structure
    const void *pNext;                                                   ///< [in][optional] must be null or a pointer to an extension-specific
                                                                         ///< structure (i.e. contains stype and pNext).
    uint32_t metricGroupCount;                                           ///< [in] [in] count for metric group handles in metric hMetricGroups array.
                                                                         ///< If set to 0, then phMetricGroups must be null
    zet_metric_group_handle_t *phMetricGroups;                           ///< [in] [optional][range(0, metricGroupCount)] array of metric group
                                                                         ///< handles to filter metric groups to be calculated.
    uint32_t metricCount;                                                ///< [in] number of metrics handles in the phMetrics array. If set to 0, then
                                                                         ///< phMetrics must be null.
    zet_metric_handle_t *phMetrics;                                      ///< [in][optional] [range(0, metricsCount)] array of metrics handles to filter
                                                                         ///< metrics to be calculated. phMetrics are additionally calculated even if repeated
                                                                         ///< in phMetricGroups.
    uint32_t timeWindowsCount;                                           ///< [in] number of time windows in pCalculateTimeWindows. Must be 0 if disabled.
                                                                         ///< If set to 0, then pCalculateTimeWindows must be null
    zet_intel_metric_calculate_time_window_exp_t *pCalculateTimeWindows; ///< [in][optional][range(0,timeWindowsCount)] array containing the list of time windows
                                                                         ///< to filter metrics data
                                                                         ///< to be used for metrics calculation. Must be null if disabled.
    uint64_t timeAggregationWindow;                                      ///< [in] size in nanoseconds used to divide the raw data and calculate a result for
                                                                         ///< each metric. When enabled, the API will return one report per aggregation
                                                                         ///< window. Must not be 0. When set to uint64_t_MAX will include all rawdata
                                                                         ///< in a single window. If the timeAggregationWindow is bigger than the total
                                                                         ///< time of the raw data collected, will be same as uint64_t_MAX. When
                                                                         ///< timeAggregationWindow is not a perfect divisor of the total time,
                                                                         ///< the last window is expected to be smaller. When CalculateTimeWindows
                                                                         ///< are used, the API will limit the maximum timeAggregationWindow to
                                                                         ///< the size of each CalculateTimeWindow individually. When timeAggregationWindow
                                                                         ///< is smaller than a given CalculateTimeWindow, the CalculateTimeWindow will
                                                                         ///< be divided into timeAggregationWindow sections for aggregation, with the
                                                                         ///< last fraction being smaller when there is no perfect division.
} zet_intel_metric_calculate_exp_desc_t;
typedef enum _zet_intel_metric_calculate_result_status_exp_t {
    ZET_INTEL_METRIC_CALCULATE_EXP_RESULT_VALID = 0,
    ZET_INTEL_METRIC_CALCULATE_EXP_RESULT_INVALID,
    ZET_INTEL_METRIC_CALCULATE_EXP_RESULT_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_calculate_result_status_exp_t;

typedef struct _zet_intel_metric_result_exp_t {
    zet_value_t value;                                           ///< [out] metric result calculated metric value
    zet_intel_metric_calculate_result_status_exp_t resultStatus; ///< [out] type of the result for the filters applied to the calculation.
} zet_intel_metric_result_exp_t;
typedef struct _zet_intel_metric_decoded_buffer_exp_properties_t {
    zet_structure_type_ext_t stype; ///< [in] type of this structure
    void *pNext;                    ///< [in][optional] must be null or a pointer to an extension-specific
                                    ///< structure (i.e. contains stype and pNext).
    uint64_t minTimeStamp;          ///< [out] minimum timestamp contained in the raw data buffer
    uint64_t maxTimeStamp;          ///< [out] maximum timestamp contained in the raw data buffer
} zet_intel_metric_decoded_buffer_exp_properties_t;

ze_result_t ZE_APICALL
zetIntelMetricCalculateOperationCreateExp(
    zet_context_handle_t hContext,                                            ///< [in] handle of the context object
    zet_device_handle_t hDevice,                                              ///< [in] handle of the device
    zet_intel_metric_calculate_exp_desc_t *pCalculateDesc,                    ///< [in] pointer to structure with filters and operations to perform
                                                                              ///< at calculation time.
    uint32_t *pExcludedMetricCount,                                           ///< [out] pointer to number of excluded metrics. These are metrics in the
                                                                              ///< input list in pcalculateDesc that do not allow calculation
    zet_metric_handle_t *phExcludedMetrics,                                   ///< [in,out] [range(0, *pCount)] array of handles of excluded metrics
                                                                              ///< from the phCalculateOperation handle.
    zet_intel_metric_calculate_operation_exp_handle_t *phCalculateOperation); ///< [out] Calculate operation handle

ze_result_t ZE_APICALL
zetIntelMetricCalculateOperationDestroyExp(
    zet_intel_metric_calculate_operation_exp_handle_t hCalculateOperation); ///< [in] Calculate operation handle

ze_result_t ZE_APICALL zetIntelMetricCalculateGetReportFormatExp(
    zet_intel_metric_calculate_operation_exp_handle_t phCalculateOperation, ///< [in] Calculate operation handle
    uint32_t *pCount,                                                       ///< [in,out] pointer to the number of metrics in the output report from
                                                                            ///< calculate operations. If set to zero, then the driver shall update
                                                                            ///< the value with the total number of metrics to be included in the
                                                                            ///< calculate results report. If count is greater than the total number
                                                                            ///< of metrics to be included in the calculate results report, then the
                                                                            ///< driver shall update the value with the actual number.  If count is
                                                                            ///< smaller than the total number of metrics to be included in the
                                                                            ///< calculate results report, then ZE_RESULT_ERROR_INVALID_ARGUMENT
                                                                            ///< will be returned since this parameter is not intended for
                                                                            ///< filtering metrics.
    zet_metric_handle_t *phMetrics);                                        ///< [out][optional] [range(0, pMetricsCount)] array of metrics handles
                                                                            ///< with the order in which results will be found in output report of
                                                                            ///< calculate operations

ze_result_t ZE_APICALL
zetIntelMetricDecodeCalculateMultipleValuesExp(
    zet_metric_decoder_exp_handle_t hMetricDecoder,                        ///< [in] handle of the metric decoder object
    const size_t rawDataSize,                                              ///< [in] size in bytes of raw data buffer.
    size_t *offset,                                                        ///< [in,out] On input, the offset from the beginning of pRawData to decode
                                                                           ///< and calculate. On output, the number raw bytes processed
    const uint8_t *pRawData,                                               ///< [in,out][range(0, *rawDataSize)] buffer containing tracer
                                                                           ///< data in raw format
    zet_intel_metric_calculate_operation_exp_handle_t hCalculateOperation, ///< [in] Calculate operation handle
    uint32_t *pSetCount,                                                   ///< [in,out] pointer to number of metric sets. if count is zero, then the
                                                                           ///< driver shall update the value with the total number of metric sets to
                                                                           ///< be decoded and calculated. If count is greater than the number available
                                                                           ///< in the raw data buffer, then the driver shall update the value with the
                                                                           ///< actual number of metric sets to be decoded and calculated.  There is a
                                                                           ///< 1:1 relationship between the number of sets and the number sub-devices
                                                                           ///< metrics results that can be calculated from the provided data
    uint32_t *pMetricReportCountPerSet,                                    ///< [in,out][optional][range(0, *pSetCount)] buffer of metric reports counts
                                                                           ///< per metric set, one value per set
    uint32_t *pTotalMetricReportCount,                                     ///< [in,out] [optional] pointer to the total number of metric reports decoded and
                                                                           ///< calculated, for all metric sets. If count is zero, then the driver shall update
                                                                           ///< the value with the total number of metric reports to be decoded and calculated.
                                                                           ///< If count is greater than zero but less than the total number of reports available
                                                                           ///< in the raw data, then only that number of reports will be decoded and calculated.
                                                                           ///< If count is greater than the number of reports available in the raw data buffer,
                                                                           ///< then the driver shall update the value with the actual number of metric reports
                                                                           ///< decoded and calculated. If set to null, then driver will only update the value
                                                                           ///< of pSetCount
    zet_intel_metric_result_exp_t *pMetricResults);                        ///< [in,out][optional][range(0, *pTotalMetricResultsCount)] buffer of decoded and
                                                                           ///< calculated metrics results.

ze_result_t ZE_APICALL
zetIntelMetricDecodeToBinaryBufferExp(
    zet_metric_decoder_exp_handle_t hMetricDecoder,                         ///< [in] handle of the metric decoder object
    size_t *pRawDataSize,                                                   ///< [in,out] size in bytes of raw data buffer. If pDecodedBufferSize is greater
                                                                            ///< than 0 but smaller than the total number of bytes required for decoding
                                                                            ///< the entire input raw data, then driver shall update this value with
                                                                            ///< actual number of raw data bytes processed
    const uint8_t *pRawData,                                                ///< [in,out][range(0, *pRawDataSize)] buffer containing tracer
                                                                            ///< data in raw format
    zet_intel_metric_calculate_operation_exp_handle_t phCalculateOperation, ///< [in] Calculate operation handle, to filter metrics to decode
    zet_intel_metric_decoded_buffer_exp_properties_t *pProperties,          ///< [in] Properties of the decoded buffer.
    size_t *pDecodedBufferSize,                                             ///< [in] Pointer to the size of the decoded binary buffer. If set to 0,
                                                                            ///< [in,out] Then driver shall update this value with total size in bytes required
                                                                            ///< for the decoded binary buffer. If size is greater than 0 but smaller
                                                                            ///< than the total number of bytes required for decoding entire input
                                                                            ///< raw data, then driver shall only decode an approximate to that number
                                                                            ///< of bytes. If size is greater than the total number of bytes required
                                                                            ///< for decoding entire input raw data, then the driver shall update the
                                                                            ///< value with the actual number of bytes decoded.
    uint8_t *pDecodedBuffer);                                               ///< [in,out][optional] binary buffer containing decoded raw data.

ze_result_t ZE_APICALL
zetIntelMetricCalculateMultipleValuesExp(
    const size_t rawDataSize,                                              ///< [in] size in bytes of raw data buffer.
    size_t *offset,                                                        ///< [in,out] On input, the offset from the beginning of pRawData calculate. On output,
                                                                           ///< the number raw bytes processed
    const uint8_t *pRawData,                                               ///< [in,out][range(0, *rawDataSize)] buffer containing tracer
                                                                           ///< data in raw format
    zet_intel_metric_calculate_operation_exp_handle_t hCalculateOperation, ///< [in] Calculate operation handle
    uint32_t *pSetCount,                                                   ///< [in,out] pointer to number of metric sets. if count is zero, then the
                                                                           ///< driver shall update the value with the total number of metric sets to
                                                                           ///< be calculated. If count is greater than the number available in the raw
                                                                           ///< data buffer, then the driver shall update the value with the actual number
                                                                           ///< of metric sets to be calculated. There is a 1:1 relationship between the
                                                                           ///< number of sets and the number sub-devices metrics results that can be
                                                                           ///< calculated from the provided data.
    uint32_t *pMetricReportCountPerSet,                                    ///< [in,out][optional][range(0, *pSetCount)] buffer of metric reports counts
                                                                           ///< per metric set, one value per set
    uint32_t *pTotalMetricReportCount,                                     ///< [in,out] [optional] pointer to the total number of metric reports calculated,
                                                                           ///< for all metric sets. If count is zero, then the driver shall update the value
                                                                           ///< with the total number of metric reports to be calculated. If count is greater
                                                                           ///< than zero but less than the total number of reports available in the raw data,
                                                                           ///< then only that number of reports will be calculated. If count is greater than
                                                                           ///< the number of reports available in the raw data buffer, then the driver shall
                                                                           ///< update the value with the actual number of metric reports calculated. If set
                                                                           ///< to null, then driver will only update the value of pSetCount
    zet_intel_metric_result_exp_t *pMetricResults);                        ///< [in,out][optional][range(0, *pTotalMetricResultsCount)] buffer of calculated
                                                                           ///< metrics results.

ze_result_t ZE_APICALL
zetIntelMetricCalculateValuesExp(
    const size_t rawDataSize,                                              ///< [in] size in bytes of raw data buffer.
    size_t *pOffset,                                                       ///< [in,out] On input, the offset from the beginning of the pRawData to calculate
                                                                           ///< On output, the number raw bytes processed
    const uint8_t *pRawData,                                               ///< [in,out][range(0, *rawDataSize)] buffer containing tracer
                                                                           ///< data in raw format
    zet_intel_metric_calculate_operation_exp_handle_t hCalculateOperation, ///< [in] Calculate operation handle
    uint32_t *pTotalMetricReportCount,                                     ///< [in,out] [optional] pointer to the total number of metric reports calculated,
                                                                           ///< If count is zero, then the driver shall update the value with the total number of
                                                                           ///< metric reports to be calculated. If count is greater than zero but less than the
                                                                           ///< total number of reports available in the raw data, then only that number of
                                                                           ///< reports will be calculated. If count is greater than the number of reports
                                                                           ///< available in the raw data buffer, then the driver shall update the value with
                                                                           ///< the actual number of metric reports calculated.
    zet_intel_metric_result_exp_t *pMetricResults);                        ///< [in,out][optional][range(0, *pTotalMetricResultsCount)] buffer of calculated
                                                                           ///< metrics results.

#ifndef ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_NAME
/// @brief Extension name for enabling and disabling Intel Metrics collection
#define ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_NAME "ZET_intel_metrics_runtime_enable_disable"
#endif // ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_NAME

///////////////////////////////////////////////////////////////////////////////
/// @brief Metrics Runtime Enable Disable extension Version(s)
typedef enum _zet_intel_metrics_runtime_enable_disable_exp_version_t {
    ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),                                        ///< version 1.0
    ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_CURRENT = ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_1_0, ///< latest known version
    ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metrics_runtime_enable_disable_exp_version_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief This API Enables Metric collection for a device if not already enabled.
/// If device is a root-device, then its sub-devices are also enabled.
/// This API can be used as runtime alternative to setting ZET_ENABLE_METRICS=1.
ze_result_t ZE_APICALL zetIntelDeviceEnableMetricsExp(zet_device_handle_t hDevice);

///////////////////////////////////////////////////////////////////////////////
/// @brief This API Disables Metric for a device, if it was previously enabled.
/// If device is a root-device, then its sub-devices are also disabled.
/// The application has to ensure that all metric operations are complete and
/// all metric resources are released before this API is called.
/// If there are metric operations in progress, then ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE
/// is returned.
ze_result_t ZE_APICALL zetIntelDeviceDisableMetricsExp(zet_device_handle_t hDevice);

#ifndef ZET_INTEL_METRIC_SCOPES_EXP_NAME
/// @brief Extension name to query Intel Metric Scopes operations
#define ZET_INTEL_METRIC_SCOPES_EXP_NAME "ZET_intel_metric_scopes"
#endif // ZET_INTEL_METRIC_SCOPES_EXP_NAME
typedef enum _zet_intel_metric_scopes_exp_version_t {
    ZET_INTEL_METRIC_SCOPES_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),                       ///< version 1.0
    ZET_INTEL_METRIC_SCOPES_EXP_VERSION_CURRENT = ZET_INTEL_METRIC_SCOPES_EXP_VERSION_1_0, ///< latest known version
    ZET_INTEL_METRIC_SCOPES_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_scopes_exp_version_t;

/// @brief Handle of metric scope
struct _zet_intel_metric_scope_exp_handle_t {};
typedef struct _zet_intel_metric_scope_exp_handle_t *zet_intel_metric_scope_exp_handle_t;

#define ZET_INTEL_MAX_METRIC_SCOPE_NAME_EXP 64u
#define ZET_INTEL_MAX_METRIC_SCOPE_DESCRIPTION_EXP 128u

#ifndef ZET_STRUCTURE_TYPE_INTEL_METRIC_SCOPE_PROPERTIES_EXP
#define ZET_STRUCTURE_TYPE_INTEL_METRIC_SCOPE_PROPERTIES_EXP 0x7fffffff
#endif // ZET_STRUCTURE_TYPE_INTEL_METRIC_SCOPE_PROPERTIES_EXP

/// @brief Query an metric scope properties
typedef struct _zet_intel_metric_scope_properties_exp_t {
    zet_structure_type_ext_t stype;                               ///< [in] type of this structure
    void *pNext;                                                  ///< [in][optional] must be null or a pointer to an extension-specific
                                                                  ///< structure (i.e. contains stype and pNext).
    uint16_t iD;                                                  ///< [out ]ID will be equal to the index of the metric scope in the
                                                                  ///> array returned by zetMetricScopesGet()
    char name[ZET_INTEL_MAX_METRIC_SCOPE_NAME_EXP];               ///< [out] name of the metric scope, which is unique for the device.
                                                                  ///< The name is expected to be a human readable string.
                                                                  ///< The name can be used to identify the metric scope in the UI.
    char description[ZET_INTEL_MAX_METRIC_SCOPE_DESCRIPTION_EXP]; ///< [out] description of the metric scope, which is unique for the device.
                                                                  ///< The description is expected to be a human readable string.
                                                                  ///< The description can be used to provide additional information about
                                                                  ///< the metric scope in the UI.
} zet_intel_metric_scope_properties_exp_t;

ze_result_t ZE_APICALL zetIntelMetricScopesGetExp(
    zet_context_handle_t hContext,                        ///< [in] handle of the context object
    zet_device_handle_t hDevice,                          ///< [in] handle of the device
    uint32_t *pMetricScopesCount,                         ///< [in,out] pointer to the number of metric scopes available for the device.
                                                          ///< If set to zero, then the driver shall update the value with the total
                                                          ///< number of metric scopes available for the device.
    zet_intel_metric_scope_exp_handle_t *phMetricScopes); ///< [out][optional] [range(0, *pMetricScopesCount)] array of metric scopes handles
                                                          ///< available for the device. If pMetricScopesCount is greater than zero but
                                                          ///< less than the total number of metric scopes available for the device,
                                                          ///< then driver shall only return that number of metric scopes.

ze_result_t ZE_APICALL zetIntelMetricScopeGetPropertiesExp(
    zet_intel_metric_scope_exp_handle_t hMetricScope,                 ///< [in] handle of the metric scope
    zet_intel_metric_scope_properties_exp_t *pMetricScopeProperties); ///< [out] pointer to the metric scope properties structure

#if defined(__cplusplus)
} // extern "C"
#endif

#endif //_ZET_INTEL_GPU_METRIC_H
