diff --git a/runtime/os_interface/linux/os_time_linux.cpp b/runtime/os_interface/linux/os_time_linux.cpp index 6548633e7a..57f1a8dbab 100644 --- a/runtime/os_interface/linux/os_time_linux.cpp +++ b/runtime/os_interface/linux/os_time_linux.cpp @@ -139,6 +139,18 @@ double OSTimeLinux::getHostTimerResolution() const { } double OSTimeLinux::getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const { + if (pDrm) { + drm_i915_getparam_t getParam; + int frequency = 0; + + getParam.param = I915_PARAM_CS_TIMESTAMP_FREQUENCY; + getParam.value = &frequency; + auto error = pDrm->ioctl(DRM_IOCTL_I915_GETPARAM, &getParam); + + if (!error) { + return 1000000000.0 / frequency; + } + } return OSTime::getDeviceTimerResolution(hwInfo); } diff --git a/unit_tests/os_interface/linux/device_command_stream_fixture.h b/unit_tests/os_interface/linux/device_command_stream_fixture.h index 4c99743768..e58f2299d7 100644 --- a/unit_tests/os_interface/linux/device_command_stream_fixture.h +++ b/unit_tests/os_interface/linux/device_command_stream_fixture.h @@ -86,6 +86,7 @@ class DrmMockCustom : public Drm { gemWait = 0; gemClose = 0; regRead = 0; + getParam = 0; contextGetParam = 0; contextCreate = 0; contextDestroy = 0; @@ -104,6 +105,7 @@ class DrmMockCustom : public Drm { std::atomic gemWait; std::atomic gemClose; std::atomic regRead; + std::atomic getParam; std::atomic contextGetParam; std::atomic contextCreate; std::atomic contextDestroy; @@ -134,6 +136,7 @@ class DrmMockCustom : public Drm { NEO_IOCTL_EXPECT_EQ(gemWait); NEO_IOCTL_EXPECT_EQ(gemClose); NEO_IOCTL_EXPECT_EQ(regRead); + NEO_IOCTL_EXPECT_EQ(getParam); NEO_IOCTL_EXPECT_EQ(contextGetParam); NEO_IOCTL_EXPECT_EQ(contextCreate); NEO_IOCTL_EXPECT_EQ(contextDestroy); @@ -173,6 +176,9 @@ class DrmMockCustom : public Drm { __u32 setDomainHandle = 0; __u32 setDomainReadDomains = 0; __u32 setDomainWriteDomain = 0; + //DRM_IOCTL_I915_GETPARAM + drm_i915_getparam_t recordedGetParam = {0}; + int getParamRetValue = 0; //DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM drm_i915_gem_context_param recordedGetContextParam = {0}; __u64 getContextParamRetValue = 0; @@ -261,6 +267,13 @@ class DrmMockCustom : public Drm { ioctl_cnt.regRead++; break; + case DRM_IOCTL_I915_GETPARAM: { + ioctl_cnt.contextGetParam++; + auto getParam = (drm_i915_getparam_t *)arg; + recordedGetParam = *getParam; + *getParam->value = getParamRetValue; + } break; + case DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM: { ioctl_cnt.contextGetParam++; auto getContextParam = (drm_i915_gem_context_param *)arg; diff --git a/unit_tests/os_interface/linux/os_time_test.cpp b/unit_tests/os_interface/linux/os_time_test.cpp index bdee5a5009..c037833a1b 100644 --- a/unit_tests/os_interface/linux/os_time_test.cpp +++ b/unit_tests/os_interface/linux/os_time_test.cpp @@ -194,6 +194,40 @@ TEST_F(DrmTimeTest, detect) { delete drm; } +TEST_F(DrmTimeTest, givenGpuTimestampResolutionQueryWhenIoctlFailsThenDefaultResolutionIsReturned) { + auto defaultResolution = platformDevices[0]->capabilityTable.defaultProfilingTimerResolution; + + auto drm = std::make_unique(); + osTime->updateDrm(drm.get()); + + drm->getParamRetValue = 0; + drm->ioctl_res = -1; + + auto result = osTime->getDynamicDeviceTimerResolution(*platformDevices[0]); + EXPECT_DOUBLE_EQ(result, defaultResolution); +} + +TEST_F(DrmTimeTest, givenGpuTimestampResolutionQueryWhenNoDrmThenDefaultResolutionIsReturned) { + osTime->updateDrm(nullptr); + + auto defaultResolution = platformDevices[0]->capabilityTable.defaultProfilingTimerResolution; + + auto result = osTime->getDynamicDeviceTimerResolution(*platformDevices[0]); + EXPECT_DOUBLE_EQ(result, defaultResolution); +} + +TEST_F(DrmTimeTest, givenGpuTimestampResolutionQueryWhenIoctlSuccedsThenCorrectResolutionIsReturned) { + auto drm = std::make_unique(); + osTime->updateDrm(drm.get()); + + // 19200000 is frequency yelding 52.083ns resolution + drm->getParamRetValue = 19200000; + drm->ioctl_res = 0; + + auto result = osTime->getDynamicDeviceTimerResolution(*platformDevices[0]); + EXPECT_DOUBLE_EQ(result, 52.08333333333333); +} + TEST_F(DrmTimeTest, givenAlwaysFailingResolutionFuncWhenGetHostTimerResolutionIsCalledThenReturnsZero) { osTime->setResolutionFunc(resolutionFuncFalse); auto retVal = osTime->getHostTimerResolution();