From 280239ebec1bd7599497ed86cd065b04343d8d49 Mon Sep 17 00:00:00 2001 From: Joshua Santosh Ranjan Date: Mon, 28 Jul 2025 14:21:14 +0000 Subject: [PATCH] feature: add support to query metrics hw buffer size Related-To: NEO-13439 Signed-off-by: Joshua Santosh Ranjan --- .../driver/driver_handle_imp_helper.cpp | 2 +- level_zero/include/level_zero/ze_stypes.h | 1 + .../include/level_zero/zet_intel_gpu_metric.h | 29 +++ level_zero/tools/source/metrics/metric.cpp | 12 + level_zero/tools/source/metrics/metric.h | 1 + .../metrics/metric_ip_sampling_streamer.cpp | 17 +- .../metrics/metric_oa_enumeration_imp.h | 1 + .../source/metrics/metric_oa_streamer_imp.cpp | 59 ++++- .../source/metrics/metric_oa_streamer_imp.h | 7 +- .../test_metric_ip_sampling_streamer.cpp | 33 +++ .../metrics/test_metric_oa_streamer_1.cpp | 213 ++++++++++++++++++ .../metrics/test_metric_oa_streamer_3.cpp | 93 +++++++- 12 files changed, 451 insertions(+), 17 deletions(-) diff --git a/level_zero/core/source/driver/driver_handle_imp_helper.cpp b/level_zero/core/source/driver/driver_handle_imp_helper.cpp index cc453529c1..94bccfc3e6 100644 --- a/level_zero/core/source/driver/driver_handle_imp_helper.cpp +++ b/level_zero/core/source/driver/driver_handle_imp_helper.cpp @@ -63,7 +63,7 @@ const std::vector> DriverHandleImp::extensionsS {ZET_INTEL_METRIC_CALCULATE_EXP_NAME, ZET_INTEL_METRIC_CALCULATE_EXP_VERSION_CURRENT}, {ZET_METRICS_RUNTIME_ENABLE_DISABLE_EXP_NAME, ZET_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_CURRENT}, {ZET_INTEL_METRIC_SCOPES_EXP_NAME, ZET_INTEL_METRIC_SCOPES_EXP_VERSION_CURRENT}, - + {ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_NAME, ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_CURRENT}, #include "additional_extensions_support.inl" }; } // namespace L0 diff --git a/level_zero/include/level_zero/ze_stypes.h b/level_zero/include/level_zero/ze_stypes.h index 6d1ffff1c6..bd09a8497c 100644 --- a/level_zero/include/level_zero/ze_stypes.h +++ b/level_zero/include/level_zero/ze_stypes.h @@ -45,6 +45,7 @@ using zes_structure_type_ext_t = uint32_t; #define ZET_INTEL_STRUCTURE_TYPE_METRIC_CALCULATE_DESC_EXP static_cast(0x00010009) #define ZET_INTEL_STRUCTURE_TYPE_METRIC_SOURCE_ID_EXP static_cast(0x0001000a) #define ZET_INTEL_STRUCTURE_TYPE_METRIC_DECODED_BUFFER_PROPERTIES_EXP static_cast(0x0001000b) +#define ZET_INTEL_STRUCTURE_TYPE_METRIC_HW_BUFFER_SIZE_EXP_DESC static_cast(0x00010007) // Sysman structure types #define ZES_INTEL_PCI_LINK_SPEED_DOWNGRADE_EXP_STATE static_cast(0x00040001) diff --git a/level_zero/include/level_zero/zet_intel_gpu_metric.h b/level_zero/include/level_zero/zet_intel_gpu_metric.h index 069d07e8c6..0b50ab4ff2 100644 --- a/level_zero/include/level_zero/zet_intel_gpu_metric.h +++ b/level_zero/include/level_zero/zet_intel_gpu_metric.h @@ -495,6 +495,35 @@ 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 +#ifndef ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_NAME +/// @brief Extension name for query to read the Intel Level Zero Driver Version String +#define ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_NAME "ZET_intel_get_hw_buffer_size" +#endif // ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_NAME + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Maximum Hw Buffer Size extension Version(s) +typedef enum _zet_intel_metric_hw_buffer_size_exp_version_t { + ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0), ///< version 1.0 + ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_CURRENT = ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_1_0, ///< latest known version + ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_FORCE_UINT32 = 0x7fffffff +} zet_intel_metric_hw_buffer_size_exp_version_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Metric hardware buffer size descriptor +/// This descriptor can be used as a "pNext" value to the zet_metric_streamer_desc_t and zet_metric_tracer_exp_desc_t. +/// This descriptor allow to request and query the allocated HW buffer size in bytes. +/// The sizeInBytes should not be used to estimate buffer overflow scenario (Use notifyNReports to detect it). +typedef struct _zet_intel_metric_hw_buffer_size_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). + size_t sizeInBytes; ///< [in,out] size of the hardware buffer size in bytes. + ///< If the requested value cannot be supported, + ///< then the driver may use a value that can be supported and shall update this member. + ///< When hNotificationEvent is set as input has precedence over hw_buffer_size_exp_desc_t when setting HW buffer size. + ///< The actual size used by the HW will be updated in "sizeInBytes" member by the implementation. +} zet_intel_metric_hw_buffer_size_exp_desc_t; + #if defined(__cplusplus) } // extern "C" #endif diff --git a/level_zero/tools/source/metrics/metric.cpp b/level_zero/tools/source/metrics/metric.cpp index ee4a219e7b..3a7a79beba 100644 --- a/level_zero/tools/source/metrics/metric.cpp +++ b/level_zero/tools/source/metrics/metric.cpp @@ -74,6 +74,18 @@ void MetricSource::initComputeMetricScopes(MetricDeviceContext &metricDeviceCont metricDeviceContext.setComputeMetricScopeInitialized(); } +std::optional MetricSource::getHwBufferSizeDesc(zet_base_desc_t *baseDesc) { + + while (baseDesc != nullptr) { + if (baseDesc->stype == ZET_INTEL_STRUCTURE_TYPE_METRIC_HW_BUFFER_SIZE_EXP_DESC) { + return reinterpret_cast(baseDesc); + } + baseDesc = static_cast(const_cast(baseDesc->pNext)); + } + + return std::nullopt; +} + MetricDeviceContext::MetricDeviceContext(Device &inputDevice) : device(inputDevice) { auto deviceNeo = device.getNEODevice(); std::tuple subDeviceMap; diff --git a/level_zero/tools/source/metrics/metric.h b/level_zero/tools/source/metrics/metric.h index 0752632856..e4321da287 100644 --- a/level_zero/tools/source/metrics/metric.h +++ b/level_zero/tools/source/metrics/metric.h @@ -109,6 +109,7 @@ class MetricSource { zet_intel_metric_calculate_operation_exp_handle_t *phCalculateOperation) = 0; virtual bool canDisable() = 0; virtual void initMetricScopes(MetricDeviceContext &metricDeviceContext) = 0; + static std::optional getHwBufferSizeDesc(zet_base_desc_t *baseDesc); protected: uint32_t type = MetricSource::metricSourceTypeUndefined; diff --git a/level_zero/tools/source/metrics/metric_ip_sampling_streamer.cpp b/level_zero/tools/source/metrics/metric_ip_sampling_streamer.cpp index 38f8091022..2205db6f85 100644 --- a/level_zero/tools/source/metrics/metric_ip_sampling_streamer.cpp +++ b/level_zero/tools/source/metrics/metric_ip_sampling_streamer.cpp @@ -56,6 +56,12 @@ ze_result_t IpSamplingMetricGroupImp::streamerOpen( } *phMetricStreamer = pStreamerImp->toHandle(); + + auto hwBufferSizeDesc = MetricSource::getHwBufferSizeDesc(static_cast(const_cast(desc->pNext))); + if (hwBufferSizeDesc.has_value()) { + // EUSS uses fixed max hw buffer size + hwBufferSizeDesc.value()->sizeInBytes = source.getMetricOsInterface()->getRequiredBufferSize(UINT32_MAX); + } return ZE_RESULT_SUCCESS; } @@ -290,7 +296,8 @@ ze_result_t MultiDeviceIpSamplingMetricGroupImp::streamerOpen( ze_result_t result = ZE_RESULT_SUCCESS; std::vector subDeviceStreamers = {}; - subDeviceStreamers.reserve(subDeviceMetricGroup.size()); + const auto numSubDevices = subDeviceMetricGroup.size(); + subDeviceStreamers.reserve(numSubDevices); // Open SubDevice Streamers for (auto &metricGroup : subDeviceMetricGroup) { @@ -309,6 +316,14 @@ ze_result_t MultiDeviceIpSamplingMetricGroupImp::streamerOpen( pStreamerImp->attachEvent(hNotificationEvent); *phMetricStreamer = pStreamerImp->toHandle(); + + auto hwBufferSizeDesc = MetricSource::getHwBufferSizeDesc(static_cast(const_cast(desc->pNext))); + if (hwBufferSizeDesc.has_value()) { + auto device = Device::fromHandle(hDevice); + IpSamplingMetricSourceImp &source = device->getMetricDeviceContext().getMetricSource(); + // EUSS uses fixed max hw buffer size + hwBufferSizeDesc.value()->sizeInBytes = source.getMetricOsInterface()->getRequiredBufferSize(UINT32_MAX) * numSubDevices; + } return result; } diff --git a/level_zero/tools/source/metrics/metric_oa_enumeration_imp.h b/level_zero/tools/source/metrics/metric_oa_enumeration_imp.h index 1bf54339f5..4372cba0ac 100644 --- a/level_zero/tools/source/metrics/metric_oa_enumeration_imp.h +++ b/level_zero/tools/source/metrics/metric_oa_enumeration_imp.h @@ -250,6 +250,7 @@ struct OaMetricGroupImp : public MetricGroupImp { private: ze_result_t openForDevice(Device *pDevice, zet_metric_streamer_desc_t &desc, + const bool isNotificationEnabled, zet_metric_streamer_handle_t *phMetricStreamer); }; diff --git a/level_zero/tools/source/metrics/metric_oa_streamer_imp.cpp b/level_zero/tools/source/metrics/metric_oa_streamer_imp.cpp index a17555348e..728abd9ea0 100644 --- a/level_zero/tools/source/metrics/metric_oa_streamer_imp.cpp +++ b/level_zero/tools/source/metrics/metric_oa_streamer_imp.cpp @@ -152,23 +152,45 @@ ze_result_t OaMetricStreamerImp::initialize(ze_device_handle_t hDevice, return ZE_RESULT_SUCCESS; } -uint32_t OaMetricStreamerImp::getOaBufferSize(const uint32_t notifyEveryNReports) const { +uint32_t OaMetricStreamerImp::getOaBufferSizeForNotification(const uint32_t notifyEveryNReports) const { // Notification is on half full buffer, hence multiplication by 2. return notifyEveryNReports * rawReportSize * 2; } -ze_result_t OaMetricStreamerImp::startMeasurements(uint32_t ¬ifyEveryNReports, - uint32_t &samplingPeriodNs) { - auto metricGroup = static_cast(MetricGroup::fromHandle(hMetricGroup)); - uint32_t requestedOaBufferSize = getOaBufferSize(notifyEveryNReports); +uint32_t OaMetricStreamerImp::getOaBufferSizeForReports(const uint32_t maxReportCount) const { - const ze_result_t result = metricGroup->openIoStream(samplingPeriodNs, requestedOaBufferSize); + return maxReportCount * rawReportSize; +} + +ze_result_t OaMetricStreamerImp::updateStreamerDescriptionAndStartMeasurements(zet_metric_streamer_desc_t &streamerDesc, const bool isNotificationEnabled) { + auto metricGroup = static_cast(MetricGroup::fromHandle(hMetricGroup)); + uint32_t requestedOaBufferSize = 0; + bool useNotifyNReports = true; + auto hwBufferSizeDesc = MetricSource::getHwBufferSizeDesc(static_cast(const_cast(streamerDesc.pNext))); + + if (hwBufferSizeDesc.has_value() && !isNotificationEnabled) { + // Use value inside hwBufferSizeDesc only if notification was not enabled + auto expectReportCount = static_cast(hwBufferSizeDesc.value()->sizeInBytes / rawReportSize); + requestedOaBufferSize = getOaBufferSizeForReports(expectReportCount); + useNotifyNReports = false; + } + + if (useNotifyNReports) { + requestedOaBufferSize = getOaBufferSizeForNotification(streamerDesc.notifyEveryNReports); + } + + const ze_result_t result = metricGroup->openIoStream(streamerDesc.samplingPeriod, requestedOaBufferSize); // Return oa buffer size and notification event aligned to gpu capabilities. if (result == ZE_RESULT_SUCCESS) { oaBufferSize = requestedOaBufferSize; - notifyEveryNReports = getNotifyEveryNReports(requestedOaBufferSize); + if (useNotifyNReports) { + streamerDesc.notifyEveryNReports = getNotifyEveryNReports(requestedOaBufferSize); + } + if (hwBufferSizeDesc != std::nullopt) { + hwBufferSizeDesc.value()->sizeInBytes = requestedOaBufferSize; + } } return result; @@ -226,6 +248,7 @@ uint32_t OaMetricStreamerImp::getRequiredBufferSize(const uint32_t maxReportCoun } ze_result_t OaMetricGroupImp::openForDevice(Device *pDevice, zet_metric_streamer_desc_t &desc, + const bool isNotificationEnabled, zet_metric_streamer_handle_t *phMetricStreamer) { auto &metricSource = pDevice->getMetricDeviceContext().getMetricSource(); @@ -266,8 +289,7 @@ ze_result_t OaMetricGroupImp::openForDevice(Device *pDevice, zet_metric_streamer UNRECOVERABLE_IF(pMetricStreamer == nullptr); pMetricStreamer->initialize(pDevice->toHandle(), toHandle()); - const ze_result_t result = pMetricStreamer->startMeasurements( - desc.notifyEveryNReports, desc.samplingPeriod); + const ze_result_t result = pMetricStreamer->updateStreamerDescriptionAndStartMeasurements(desc, isNotificationEnabled); if (result == ZE_RESULT_SUCCESS) { metricSource.setMetricStreamer(pMetricStreamer); } else { @@ -290,6 +312,7 @@ ze_result_t OaMetricGroupImp::streamerOpen( ze_result_t result = ZE_RESULT_SUCCESS; auto pDevice = Device::fromHandle(hDevice); const auto pDeviceImp = static_cast(pDevice); + const auto isNotificationEnabled = hNotificationEvent != nullptr; if (pDeviceImp->metricContext->isImplicitScalingCapable()) { const uint32_t subDeviceCount = pDeviceImp->numSubDevices; @@ -299,10 +322,19 @@ ze_result_t OaMetricGroupImp::streamerOpen( auto &metricStreamers = pMetricStreamer->getMetricStreamers(); metricStreamers.resize(subDeviceCount); + // for a root-device handle, split the sizeInBytes request considering the sub-device count + auto isHwBufferSizeRequested = false; + auto hwBufferSizeDesc = MetricSource::getHwBufferSizeDesc(static_cast(const_cast(desc->pNext))); + + if (hwBufferSizeDesc != std::nullopt) { + hwBufferSizeDesc.value()->sizeInBytes /= subDeviceCount; + isHwBufferSizeRequested = true; + } + for (uint32_t i = 0; i < subDeviceCount; i++) { auto metricGroupsSubDevice = static_cast(MetricGroup::fromHandle(getMetricGroups()[i])); - result = metricGroupsSubDevice->openForDevice(pDeviceImp->subDevices[i], *desc, &metricStreamers[i]); + result = metricGroupsSubDevice->openForDevice(pDeviceImp->subDevices[i], *desc, isNotificationEnabled, &metricStreamers[i]); if (result != ZE_RESULT_SUCCESS) { for (uint32_t j = 0; j < i; j++) { auto metricStreamerSubDevice = MetricStreamer::fromHandle(metricStreamers[j]); @@ -313,10 +345,15 @@ ze_result_t OaMetricGroupImp::streamerOpen( } } + // for a root-device handle, update the sizeInBytes considering the sub-device count + if (isHwBufferSizeRequested) { + hwBufferSizeDesc.value()->sizeInBytes *= subDeviceCount; + } + *phMetricStreamer = pMetricStreamer->toHandle(); } else { - result = openForDevice(pDevice, *desc, phMetricStreamer); + result = openForDevice(pDevice, *desc, isNotificationEnabled, phMetricStreamer); } if (result == ZE_RESULT_SUCCESS) { diff --git a/level_zero/tools/source/metrics/metric_oa_streamer_imp.h b/level_zero/tools/source/metrics/metric_oa_streamer_imp.h index ee45d2d996..0d285c9eab 100644 --- a/level_zero/tools/source/metrics/metric_oa_streamer_imp.h +++ b/level_zero/tools/source/metrics/metric_oa_streamer_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,7 +20,7 @@ struct OaMetricStreamerImp : MetricStreamer { ze_result_t close() override; ze_result_t initialize(ze_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup); - ze_result_t startMeasurements(uint32_t ¬ifyEveryNReports, uint32_t &samplingPeriodNs); + ze_result_t updateStreamerDescriptionAndStartMeasurements(zet_metric_streamer_desc_t &desc, const bool isNotificationEnabled); Event::State getNotificationState() override; ze_result_t appendStreamerMarker(CommandList &commandList, uint32_t value) override; @@ -28,7 +28,8 @@ struct OaMetricStreamerImp : MetricStreamer { protected: ze_result_t stopMeasurements(); - uint32_t getOaBufferSize(const uint32_t notifyEveryNReports) const; + uint32_t getOaBufferSizeForNotification(const uint32_t notifyEveryNReports) const; + uint32_t getOaBufferSizeForReports(const uint32_t maxReportCount) const; uint32_t getNotifyEveryNReports(const uint32_t oaBufferSize) const; uint32_t getRequiredBufferSize(const uint32_t maxReportCount) const; diff --git a/level_zero/tools/test/unit_tests/sources/metrics/test_metric_ip_sampling_streamer.cpp b/level_zero/tools/test/unit_tests/sources/metrics/test_metric_ip_sampling_streamer.cpp index d0da21fa40..e2e15bab93 100644 --- a/level_zero/tools/test/unit_tests/sources/metrics/test_metric_ip_sampling_streamer.cpp +++ b/level_zero/tools/test/unit_tests/sources/metrics/test_metric_ip_sampling_streamer.cpp @@ -59,6 +59,39 @@ TEST_F(MetricIpSamplingStreamerTest, GivenAllInputsAreCorrectWhenStreamerOpenAnd } } +TEST_F(MetricIpSamplingStreamerTest, GivenAllInputsAreCorrectWhenStreamerOpenWithHwBufferSizeQueryIsCalledExpectedSizeIsReturned) { + + EXPECT_EQ(ZE_RESULT_SUCCESS, testDevices[0]->getMetricDeviceContext().enableMetricApi()); + for (auto device : testDevices) { + + zet_metric_group_handle_t metricGroupHandle = MetricIpSamplingStreamerTest::getMetricGroup(device); + EXPECT_EQ(zetContextActivateMetricGroups(context->toHandle(), device, 1, &metricGroupHandle), ZE_RESULT_SUCCESS); + + ze_event_handle_t eventHandle = {}; + zet_metric_streamer_handle_t streamerHandle = {}; + zet_metric_streamer_desc_t streamerDesc = {}; + streamerDesc.stype = ZET_STRUCTURE_TYPE_METRIC_STREAMER_DESC; + streamerDesc.notifyEveryNReports = 32768; + streamerDesc.samplingPeriod = 1000; + + zet_intel_metric_hw_buffer_size_exp_desc_t hwBufferSizeDesc{}; + hwBufferSizeDesc.sizeInBytes = 128u; + hwBufferSizeDesc.stype = ZET_INTEL_STRUCTURE_TYPE_METRIC_HW_BUFFER_SIZE_EXP_DESC; + hwBufferSizeDesc.pNext = nullptr; + + streamerDesc.pNext = &hwBufferSizeDesc; + EXPECT_EQ(zetMetricStreamerOpen(context->toHandle(), device, metricGroupHandle, &streamerDesc, eventHandle, &streamerHandle), ZE_RESULT_SUCCESS); + EXPECT_NE(streamerHandle, nullptr); + + const uint32_t reportSize = 64; + DeviceImp *deviceImp = static_cast(device); + size_t expectedSize = reportSize * UINT32_MAX; + expectedSize *= (!deviceImp->isSubdevice && deviceImp->isImplicitScalingCapable()) ? deviceImp->numSubDevices : 1u; + EXPECT_EQ(hwBufferSizeDesc.sizeInBytes, expectedSize); + EXPECT_EQ(zetMetricStreamerClose(streamerHandle), ZE_RESULT_SUCCESS); + } +} + TEST_F(MetricIpSamplingStreamerTest, GivenEventHandleIsNullWhenStreamerOpenAndCloseAreCalledThenSuccessIsReturned) { EXPECT_EQ(ZE_RESULT_SUCCESS, testDevices[0]->getMetricDeviceContext().enableMetricApi()); diff --git a/level_zero/tools/test/unit_tests/sources/metrics/test_metric_oa_streamer_1.cpp b/level_zero/tools/test/unit_tests/sources/metrics/test_metric_oa_streamer_1.cpp index 0bd466adec..a2c55f41be 100644 --- a/level_zero/tools/test/unit_tests/sources/metrics/test_metric_oa_streamer_1.cpp +++ b/level_zero/tools/test/unit_tests/sources/metrics/test_metric_oa_streamer_1.cpp @@ -10,6 +10,7 @@ #include "level_zero/core/test/unit_tests/mocks/mock_cmdlist.h" #include "level_zero/core/test/unit_tests/mocks/mock_driver.h" +#include "level_zero/core/test/unit_tests/mocks/mock_event.h" #include "level_zero/tools/source/metrics/metric_oa_source.h" #include "level_zero/tools/test/unit_tests/sources/metrics/mock_metric_oa.h" @@ -1503,5 +1504,217 @@ TEST_F(MetricStreamerTest, givenMultipleMarkerInsertionsWhenZetCommandListAppend EXPECT_EQ(zetMetricStreamerClose(streamerHandle), ZE_RESULT_SUCCESS); } +TEST_F(MetricStreamerTest, WhenStreamerOpenIsCalledWithNotificationEventThenNotifyReportsParameterIsUsedForHwBufferSize) { + + zet_device_handle_t metricDeviceHandle = device->toHandle(); + + zet_metric_streamer_handle_t streamerHandle = {}; + + auto &metricOaSource = (static_cast(device))->getMetricDeviceContext().getMetricSource(); + Mock metricGroup(metricOaSource); + zet_metric_group_handle_t metricGroupHandle = metricGroup.toHandle(); + + metricsDeviceParams.ConcurrentGroupsCount = 1; + + Mock metricsConcurrentGroup; + TConcurrentGroupParams_1_13 metricsConcurrentGroupParams = {}; + metricsConcurrentGroupParams.MetricSetsCount = 1; + metricsConcurrentGroupParams.SymbolName = "OA"; + metricsConcurrentGroupParams.Description = "OA description"; + metricsConcurrentGroupParams.IoMeasurementInformationCount = 1; + + Mock ioReadEquation; + MetricsDiscovery::TEquationElement_1_0 ioEquationElement = {}; + ioEquationElement.Type = MetricsDiscovery::EQUATION_ELEM_IMM_UINT64; + ioEquationElement.ImmediateUInt64 = 0; + + ioReadEquation.getEquationElement.push_back(&ioEquationElement); + + Mock ioMeasurement; + MetricsDiscovery::TInformationParams_1_0 oaInformation = {}; + oaInformation.SymbolName = "BufferOverflow"; + oaInformation.IoReadEquation = &ioReadEquation; + + Mock metricsSet; + MetricsDiscovery::TMetricSetParams_1_11 metricsSetParams = {}; + metricsSetParams.ApiMask = MetricsDiscovery::API_TYPE_IOSTREAM; + metricsSetParams.MetricsCount = 0; + metricsSetParams.SymbolName = "Metric set name"; + metricsSetParams.ShortName = "Metric set description"; + metricsSetParams.RawReportSize = 256; + + openMetricsAdapter(); + + setupDefaultMocksForMetricDevice(metricsDevice); + + metricsDevice.getConcurrentGroupResults.push_back(&metricsConcurrentGroup); + + metricsConcurrentGroup.GetParamsResult = &metricsConcurrentGroupParams; + metricsConcurrentGroup.getMetricSetResult = &metricsSet; + metricsConcurrentGroup.GetIoMeasurementInformationResult = &ioMeasurement; + ioMeasurement.GetParamsResult = &oaInformation; + + metricsSet.GetParamsResult = &metricsSetParams; + + mockMetricsLibrary->initializationState = ZE_RESULT_SUCCESS; + + auto &metricSource = device->getMetricDeviceContext().getMetricSource(); + EXPECT_TRUE(metricSource.loadDependencies()); + EXPECT_TRUE(metricSource.isInitialized()); + + uint32_t metricGroupCount = 0; + EXPECT_EQ(zetMetricGroupGet(metricDeviceHandle, &metricGroupCount, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(metricGroupCount, 1u); + + EXPECT_EQ(zetMetricGroupGet(metricDeviceHandle, &metricGroupCount, &metricGroupHandle), ZE_RESULT_SUCCESS); + EXPECT_EQ(metricGroupCount, 1u); + EXPECT_NE(metricGroupHandle, nullptr); + + EXPECT_EQ(zetContextActivateMetricGroups(context->toHandle(), metricDeviceHandle, 1, &metricGroupHandle), ZE_RESULT_SUCCESS); + + zet_intel_metric_hw_buffer_size_exp_desc_t hwBufferSizeDesc{}; + const uint32_t rawReportSize = 256; + hwBufferSizeDesc.sizeInBytes = 100 * rawReportSize; + hwBufferSizeDesc.stype = ZET_INTEL_STRUCTURE_TYPE_METRIC_HW_BUFFER_SIZE_EXP_DESC; + hwBufferSizeDesc.pNext = nullptr; + + zet_metric_streamer_desc_t streamerDesc = {}; + + streamerDesc.stype = ZET_STRUCTURE_TYPE_METRIC_STREAMER_DESC; + streamerDesc.notifyEveryNReports = 32768; + streamerDesc.samplingPeriod = 1000; + streamerDesc.pNext = &hwBufferSizeDesc; + + const uint32_t expectedOaHWBufferSize = streamerDesc.notifyEveryNReports * 2; + + MockEvent event{}; + + EXPECT_EQ(zetMetricStreamerOpen(context->toHandle(), metricDeviceHandle, metricGroupHandle, &streamerDesc, event.toHandle(), &streamerHandle), ZE_RESULT_SUCCESS); + EXPECT_NE(streamerHandle, nullptr); + EXPECT_EQ(hwBufferSizeDesc.sizeInBytes, static_cast(expectedOaHWBufferSize * rawReportSize)); + + EXPECT_EQ(zetMetricStreamerClose(streamerHandle), ZE_RESULT_SUCCESS); + EXPECT_NE(streamerHandle, nullptr); +} + +TEST_F(MetricStreamerTest, WhenStreamerOpenIsCalledWithoutNotificationEventThenMaximumhwBufferSizeDescriptorIsUsedForHwBufferSize) { + + zet_device_handle_t metricDeviceHandle = device->toHandle(); + + zet_metric_streamer_handle_t streamerHandle = {}; + + auto &metricOaSource = (static_cast(device))->getMetricDeviceContext().getMetricSource(); + Mock metricGroup(metricOaSource); + zet_metric_group_handle_t metricGroupHandle = metricGroup.toHandle(); + + metricsDeviceParams.ConcurrentGroupsCount = 1; + + Mock metricsConcurrentGroup; + TConcurrentGroupParams_1_13 metricsConcurrentGroupParams = {}; + metricsConcurrentGroupParams.MetricSetsCount = 1; + metricsConcurrentGroupParams.SymbolName = "OA"; + metricsConcurrentGroupParams.Description = "OA description"; + metricsConcurrentGroupParams.IoMeasurementInformationCount = 1; + + Mock ioReadEquation; + MetricsDiscovery::TEquationElement_1_0 ioEquationElement = {}; + ioEquationElement.Type = MetricsDiscovery::EQUATION_ELEM_IMM_UINT64; + ioEquationElement.ImmediateUInt64 = 0; + + ioReadEquation.getEquationElement.push_back(&ioEquationElement); + + Mock ioMeasurement; + MetricsDiscovery::TInformationParams_1_0 oaInformation = {}; + oaInformation.SymbolName = "BufferOverflow"; + oaInformation.IoReadEquation = &ioReadEquation; + + Mock metricsSet; + MetricsDiscovery::TMetricSetParams_1_11 metricsSetParams = {}; + metricsSetParams.ApiMask = MetricsDiscovery::API_TYPE_IOSTREAM; + metricsSetParams.MetricsCount = 0; + metricsSetParams.SymbolName = "Metric set name"; + metricsSetParams.ShortName = "Metric set description"; + metricsSetParams.RawReportSize = 256; + + openMetricsAdapter(); + + setupDefaultMocksForMetricDevice(metricsDevice); + + metricsDevice.getConcurrentGroupResults.push_back(&metricsConcurrentGroup); + + metricsConcurrentGroup.GetParamsResult = &metricsConcurrentGroupParams; + metricsConcurrentGroup.getMetricSetResult = &metricsSet; + metricsConcurrentGroup.GetIoMeasurementInformationResult = &ioMeasurement; + ioMeasurement.GetParamsResult = &oaInformation; + + metricsSet.GetParamsResult = &metricsSetParams; + + mockMetricsLibrary->initializationState = ZE_RESULT_SUCCESS; + + auto &metricSource = device->getMetricDeviceContext().getMetricSource(); + EXPECT_TRUE(metricSource.loadDependencies()); + EXPECT_TRUE(metricSource.isInitialized()); + + uint32_t metricGroupCount = 0; + EXPECT_EQ(zetMetricGroupGet(metricDeviceHandle, &metricGroupCount, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(metricGroupCount, 1u); + + EXPECT_EQ(zetMetricGroupGet(metricDeviceHandle, &metricGroupCount, &metricGroupHandle), ZE_RESULT_SUCCESS); + EXPECT_EQ(metricGroupCount, 1u); + EXPECT_NE(metricGroupHandle, nullptr); + + EXPECT_EQ(zetContextActivateMetricGroups(context->toHandle(), metricDeviceHandle, 1, &metricGroupHandle), ZE_RESULT_SUCCESS); + + const uint32_t expectedMaxReportCount = 100; + const uint32_t rawReportSize = 256; + + // Create a chain of descriptors using pNext + // streamerDesc -> dummyhwBufferSizeDesc -> hwBufferSizeDesc -> nullptr + + zet_intel_metric_hw_buffer_size_exp_desc_t hwBufferSizeDesc{}; + hwBufferSizeDesc.sizeInBytes = expectedMaxReportCount * rawReportSize + (rawReportSize - 1); + hwBufferSizeDesc.stype = ZET_INTEL_STRUCTURE_TYPE_METRIC_HW_BUFFER_SIZE_EXP_DESC; + hwBufferSizeDesc.pNext = nullptr; + + zet_intel_metric_hw_buffer_size_exp_desc_t dummyhwBufferSizeDesc{}; + dummyhwBufferSizeDesc.sizeInBytes = 0; + auto dummyStructureType = ZET_INTEL_STRUCTURE_TYPE_METRIC_HW_BUFFER_SIZE_EXP_DESC + 1; + dummyhwBufferSizeDesc.stype = static_cast(dummyStructureType); + dummyhwBufferSizeDesc.pNext = &hwBufferSizeDesc; + + zet_metric_streamer_desc_t streamerDesc = {}; + + streamerDesc.stype = ZET_STRUCTURE_TYPE_METRIC_STREAMER_DESC; + streamerDesc.notifyEveryNReports = 32768; + streamerDesc.samplingPeriod = 1000; + streamerDesc.pNext = &dummyhwBufferSizeDesc; + + EXPECT_EQ(zetMetricStreamerOpen(context->toHandle(), metricDeviceHandle, metricGroupHandle, &streamerDesc, nullptr, &streamerHandle), ZE_RESULT_SUCCESS); + EXPECT_NE(streamerHandle, nullptr); + EXPECT_EQ(hwBufferSizeDesc.sizeInBytes, expectedMaxReportCount * rawReportSize); + + EXPECT_EQ(zetMetricStreamerClose(streamerHandle), ZE_RESULT_SUCCESS); + EXPECT_NE(streamerHandle, nullptr); +} + +using DriverVersionTest = Test; + +TEST_F(DriverVersionTest, givenSupportedExtensionsWhenCheckIfSizeInBytesIsSupportedThenCorrectResultsAreReturned) { + uint32_t count = 0; + ze_result_t res = driverHandle->getExtensionProperties(&count, nullptr); + EXPECT_NE(0u, count); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + std::vector extensionProperties; + extensionProperties.resize(count); + + res = driverHandle->getExtensionProperties(&count, extensionProperties.data()); + EXPECT_EQ(ZE_RESULT_SUCCESS, res); + + auto it = std::find_if(extensionProperties.begin(), extensionProperties.end(), [](const auto &extension) { return (strcmp(extension.name, ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_NAME) == 0); }); + EXPECT_NE(it, extensionProperties.end()); + EXPECT_EQ((*it).version, ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_CURRENT); +} + } // namespace ult } // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/metrics/test_metric_oa_streamer_3.cpp b/level_zero/tools/test/unit_tests/sources/metrics/test_metric_oa_streamer_3.cpp index e69da145f0..2dcac55454 100644 --- a/level_zero/tools/test/unit_tests/sources/metrics/test_metric_oa_streamer_3.cpp +++ b/level_zero/tools/test/unit_tests/sources/metrics/test_metric_oa_streamer_3.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2024 Intel Corporation + * Copyright (C) 2021-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -224,6 +224,97 @@ TEST_F(MetricStreamerMultiDeviceTest, givenValidArgumentsWhenZetMetricGroupCalcu EXPECT_EQ(zetMetricStreamerClose(streamerHandle), ZE_RESULT_SUCCESS); } +TEST_F(MetricStreamerMultiDeviceTest, WhenStreamerOpenIsCalledWithoutNotificationEventThenNotifyReportsParameterIsUsedForHwBufferSize) { + + zet_device_handle_t metricDeviceHandle = devices[0]->toHandle(); + + zet_metric_streamer_handle_t streamerHandle = {}; + zet_metric_streamer_desc_t streamerDesc = {}; + + zet_intel_metric_hw_buffer_size_exp_desc_t hwBufferSizeDesc{}; + const uint32_t rawReportSize = 256; + hwBufferSizeDesc.sizeInBytes = 100 * rawReportSize; + hwBufferSizeDesc.stype = ZET_INTEL_STRUCTURE_TYPE_METRIC_HW_BUFFER_SIZE_EXP_DESC; + hwBufferSizeDesc.pNext = nullptr; + + streamerDesc.stype = ZET_STRUCTURE_TYPE_METRIC_STREAMER_DESC; + streamerDesc.notifyEveryNReports = 32768; + streamerDesc.samplingPeriod = 1000; + streamerDesc.pNext = &hwBufferSizeDesc; + + auto &metricOaSource = (static_cast(devices[0]))->getMetricDeviceContext().getMetricSource(); + Mock metricGroup(metricOaSource); + zet_metric_group_handle_t metricGroupHandle = metricGroup.toHandle(); + + metricsDeviceParams.ConcurrentGroupsCount = 1; + + Mock metricsConcurrentGroup; + TConcurrentGroupParams_1_13 metricsConcurrentGroupParams = {}; + metricsConcurrentGroupParams.MetricSetsCount = 1; + metricsConcurrentGroupParams.SymbolName = "OA"; + metricsConcurrentGroupParams.Description = "OA description"; + metricsConcurrentGroupParams.IoMeasurementInformationCount = 1; + + Mock metricsSet; + MetricsDiscovery::TMetricSetParams_1_11 metricsSetParams = {}; + metricsSetParams.ApiMask = MetricsDiscovery::API_TYPE_IOSTREAM; + metricsSetParams.SymbolName = "Metric set name"; + metricsSetParams.ShortName = "Metric set description"; + metricsSetParams.RawReportSize = 256; + metricsSetParams.MetricsCount = 11; + + Mock ioReadEquation; + MetricsDiscovery::TEquationElement_1_0 ioEquationElement = {}; + ioEquationElement.Type = MetricsDiscovery::EQUATION_ELEM_IMM_UINT64; + ioEquationElement.ImmediateUInt64 = 0; + + ioReadEquation.getEquationElement.push_back(&ioEquationElement); + + Mock ioMeasurement; + MetricsDiscovery::TInformationParams_1_0 oaInformation = {}; + oaInformation.SymbolName = "BufferOverflow"; + oaInformation.IoReadEquation = &ioReadEquation; + + Mock metric; + MetricsDiscovery::TMetricParams_1_13 metricParams = {}; + + uint32_t returnedMetricCount = 1; + + openMetricsAdapter(); + + setupDefaultMocksForMetricDevice(metricsDevice); + + metricsDevice.getConcurrentGroupResults.push_back(&metricsConcurrentGroup); + + metricsConcurrentGroup.GetParamsResult = &metricsConcurrentGroupParams; + metricsConcurrentGroup.getMetricSetResult = &metricsSet; + metricsConcurrentGroup.GetIoMeasurementInformationResult = &ioMeasurement; + + metricsSet.GetParamsResult = &metricsSetParams; + metricsSet.GetMetricResult = &metric; + metricsSet.calculateMetricsOutReportCount = &returnedMetricCount; + + metric.GetParamsResult = &metricParams; + ioMeasurement.GetParamsResult = &oaInformation; + + uint32_t metricGroupCount = 0; + EXPECT_EQ(zetMetricGroupGet(metricDeviceHandle, &metricGroupCount, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(metricGroupCount, 1u); + + EXPECT_EQ(zetMetricGroupGet(metricDeviceHandle, &metricGroupCount, &metricGroupHandle), ZE_RESULT_SUCCESS); + EXPECT_EQ(metricGroupCount, 1u); + EXPECT_NE(metricGroupHandle, nullptr); + + EXPECT_EQ(zetContextActivateMetricGroups(context->toHandle(), metricDeviceHandle, 1, &metricGroupHandle), ZE_RESULT_SUCCESS); + + const size_t expectedOaHWBufferSize = hwBufferSizeDesc.sizeInBytes; + EXPECT_EQ(zetMetricStreamerOpen(context->toHandle(), metricDeviceHandle, metricGroupHandle, &streamerDesc, nullptr, &streamerHandle), ZE_RESULT_SUCCESS); + EXPECT_NE(streamerHandle, nullptr); + EXPECT_EQ(hwBufferSizeDesc.sizeInBytes, expectedOaHWBufferSize); + + EXPECT_EQ(zetMetricStreamerClose(streamerHandle), ZE_RESULT_SUCCESS); +} + using MetricStreamerTest = Test; TEST_F(MetricStreamerTest, givenRawReportSizeIsNotAlignedToOaBufferSizeWhenZetMetricStreamerReadDataIsCalledThenReadSizeIsAlignedToRawReportSize) {