Metrics Library Performance Counters implementation.

Signed-off-by: Piotr Maciejewski <piotr.maciejewski@intel.com>
Change-Id: I0f00dca1892f4857baaebc75ba2208a4f33db1bf
This commit is contained in:
Piotr Maciejewski
2019-05-20 11:19:27 +02:00
committed by sys_ocldev
parent 369982995d
commit d1d794c658
67 changed files with 2154 additions and 2617 deletions

View File

@@ -14,6 +14,8 @@ set(RUNTIME_SRCS_OS_INTERFACE_BASE
${CMAKE_CURRENT_SOURCE_DIR}/debug_settings_manager.h
${CMAKE_CURRENT_SOURCE_DIR}/device_factory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_factory.h
${CMAKE_CURRENT_SOURCE_DIR}/metrics_library.cpp
${CMAKE_CURRENT_SOURCE_DIR}/metrics_library.h
${CMAKE_CURRENT_SOURCE_DIR}/os_context.h
${CMAKE_CURRENT_SOURCE_DIR}/os_inc_base.h
${CMAKE_CURRENT_SOURCE_DIR}/os_interface.h

View File

@@ -44,6 +44,7 @@ set(RUNTIME_SRCS_OS_INTERFACE_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/os_library.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_library.h
${CMAKE_CURRENT_SOURCE_DIR}/os_memory_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_metrics_library.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_thread_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_thread_linux.h
${CMAKE_CURRENT_SOURCE_DIR}/os_time_linux.cpp

View File

@@ -19,10 +19,6 @@ OSInterface::~OSInterface() {
delete osInterfaceImpl;
}
uint32_t OSInterface::getHwContextId() const {
return 0;
}
bool OSInterface::are64kbPagesEnabled() {
return osEnabled64kbPages;
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/os_interface/metrics_library.h"
namespace NEO {
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::oaConfigurationActivate
//////////////////////////////////////////////////////
bool MetricsLibrary::oaConfigurationActivate(
const ConfigurationHandle_1_0 &handle) {
ConfigurationActivateData_1_0 data = {};
data.Type = GpuConfigurationActivationType::Tbs;
return api->functions.ConfigurationActivate(
handle,
&data) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::oaConfigurationDeactivate
//////////////////////////////////////////////////////
bool MetricsLibrary::oaConfigurationDeactivate(
const ConfigurationHandle_1_0 &handle) {
return api->functions.ConfigurationDeactivate(
handle) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::userConfigurationCreate
//////////////////////////////////////////////////////
bool MetricsLibrary::userConfigurationCreate(
const ContextHandle_1_0 &context,
ConfigurationHandle_1_0 &handle) {
// Not supported on Linux.
return true;
}
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::userConfigurationDelete
//////////////////////////////////////////////////////
bool MetricsLibrary::userConfigurationDelete(
const ConfigurationHandle_1_0 &handle) {
// Not supported on Linux.
return true;
}
} // namespace NEO

View File

@@ -7,66 +7,58 @@
#include "performance_counters_linux.h"
#include "runtime/device/device.h"
#include "runtime/helpers/hw_helper.h"
namespace NEO {
////////////////////////////////////////////////////
// PerformanceCounters::create
////////////////////////////////////////////////////
std::unique_ptr<PerformanceCounters> PerformanceCounters::create(Device *device) {
auto counter = std::make_unique<PerformanceCountersLinux>();
auto gen = device->getHardwareInfo().platform.eRenderCoreFamily;
auto &hwHelper = HwHelper::get(gen);
UNRECOVERABLE_IF(counter == nullptr);
std::unique_ptr<PerformanceCounters> PerformanceCounters::create(OSTime *osTime) {
return std::unique_ptr<PerformanceCounters>(new PerformanceCountersLinux(osTime));
}
PerformanceCountersLinux::PerformanceCountersLinux(OSTime *osTime) : PerformanceCounters(osTime) {
mdLibHandle = nullptr;
perfmonLoadConfigFunc = nullptr;
counter->clientType.Gen = static_cast<MetricsLibraryApi::ClientGen>(hwHelper.getMetricsLibraryGenId());
return counter;
}
PerformanceCountersLinux::~PerformanceCountersLinux() {
if (pAutoSamplingInterface) {
autoSamplingStopFunc(&pAutoSamplingInterface);
pAutoSamplingInterface = nullptr;
available = false;
}
//////////////////////////////////////////////////////
// PerformanceCountersLinux::enableCountersConfiguration
//////////////////////////////////////////////////////
bool PerformanceCountersLinux::enableCountersConfiguration() {
// Release previous counters configuration so the user
// can change configuration between kernels.
releaseCountersConfiguration();
if (mdLibHandle) {
dlcloseFunc(mdLibHandle);
mdLibHandle = nullptr;
}
}
void PerformanceCountersLinux::initialize(const HardwareInfo *hwInfo) {
PerformanceCounters::initialize(hwInfo);
mdLibHandle = dlopenFunc("libmd.so", RTLD_LAZY | RTLD_LOCAL);
if (mdLibHandle) {
perfmonLoadConfigFunc = reinterpret_cast<perfmonLoadConfig_t>(dlsymFunc(mdLibHandle, "drm_intel_perfmon_load_config"));
}
setPlatformInfoFunc(hwInfo->platform.eProductFamily, (void *)(&hwInfo->featureTable));
}
void PerformanceCountersLinux::enableImpl() {
if (mdLibHandle && perfmonLoadConfigFunc) {
PerformanceCounters::enableImpl();
}
}
bool PerformanceCountersLinux::verifyPmRegsCfg(InstrPmRegsCfg *pCfg, uint32_t *pLastPmRegsCfgHandle, bool *pLastPmRegsCfgPending) {
if (perfmonLoadConfigFunc == nullptr) {
// Create oa configuration.
if (!metricsLibrary->oaConfigurationCreate(
context,
oaConfiguration)) {
DEBUG_BREAK_IF(true);
return false;
}
if (PerformanceCounters::verifyPmRegsCfg(pCfg, pLastPmRegsCfgHandle, pLastPmRegsCfgPending)) {
return getPerfmonConfig(pCfg);
}
return false;
}
bool PerformanceCountersLinux::getPerfmonConfig(InstrPmRegsCfg *pCfg) {
unsigned int oaCfgHandle = pCfg->OaCounters.Handle;
unsigned int gpCfgHandle = pCfg->GpCounters.Handle;
int fd = osInterface->get()->getDrm()->getFileDescriptor();
if (perfmonLoadConfigFunc(fd, nullptr, &oaCfgHandle, &gpCfgHandle) != 0) {
return false;
}
if (pCfg->OaCounters.Handle != 0 && oaCfgHandle != pCfg->OaCounters.Handle) {
return false;
}
if (pCfg->GpCounters.Handle != 0 && gpCfgHandle != pCfg->GpCounters.Handle) {
// Enable oa configuration.
if (!metricsLibrary->oaConfigurationActivate(
oaConfiguration)) {
DEBUG_BREAK_IF(true);
return false;
}
return true;
}
//////////////////////////////////////////////////////
// PerformanceCountersLinux::releaseCountersConfiguration
//////////////////////////////////////////////////////
void PerformanceCountersLinux::releaseCountersConfiguration() {
// Oa configuration.
if (oaConfiguration.IsValid()) {
metricsLibrary->oaConfigurationDeactivate(oaConfiguration);
metricsLibrary->oaConfigurationDelete(oaConfiguration);
oaConfiguration.data = nullptr;
}
}
} // namespace NEO

View File

@@ -8,35 +8,17 @@
#pragma once
#include "runtime/os_interface/performance_counters.h"
#include "os_interface.h"
#include <dlfcn.h>
typedef struct _drm_intel_context drm_intel_context;
namespace NEO {
class PerformanceCountersLinux : virtual public PerformanceCounters {
public:
PerformanceCountersLinux(OSTime *osTime);
~PerformanceCountersLinux() override;
void initialize(const HardwareInfo *hwInfo) override;
void enableImpl() override;
PerformanceCountersLinux() = default;
~PerformanceCountersLinux() override = default;
protected:
virtual bool getPerfmonConfig(InstrPmRegsCfg *pCfg);
bool verifyPmRegsCfg(InstrPmRegsCfg *pCfg, uint32_t *pLastPmRegsCfgHandle, bool *pLastPmRegsCfgPending) override;
typedef int (*perfmonLoadConfig_t)(int fd, drm_intel_context *ctx, uint32_t *oaCfgId, uint32_t *gpCfgId);
typedef void *(*dlopenFunc_t)(const char *, int);
typedef void *(*dlsymFunc_t)(void *, const char *);
void *mdLibHandle;
perfmonLoadConfig_t perfmonLoadConfigFunc;
dlopenFunc_t dlopenFunc = dlopen;
dlsymFunc_t dlsymFunc = dlsym;
decltype(&dlclose) dlcloseFunc = dlclose;
decltype(&instrSetPlatformInfo) setPlatformInfoFunc = instrSetPlatformInfo;
/////////////////////////////////////////////////////
// Gpu oa/mmio configuration.
/////////////////////////////////////////////////////
bool enableCountersConfiguration() override;
void releaseCountersConfiguration() override;
};
} // namespace NEO

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/os_interface/metrics_library.h"
#include "runtime/helpers/hw_helper.h"
#include "runtime/os_interface/os_inc_base.h"
namespace NEO {
///////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::MetricsLibrary
///////////////////////////////////////////////////////
MetricsLibrary::MetricsLibrary() {
api = std::make_unique<MetricsLibraryInterface>();
osLibrary.reset(OsLibrary::load(Os::metricsLibraryDllName));
}
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::open
//////////////////////////////////////////////////////
bool MetricsLibrary::open() {
UNRECOVERABLE_IF(osLibrary.get() == nullptr);
if (osLibrary->isLoaded()) {
api->contextCreate = reinterpret_cast<ContextCreateFunction_1_0>(osLibrary->getProcAddress(METRICS_LIBRARY_CONTEXT_CREATE_1_0));
api->contextDelete = reinterpret_cast<ContextDeleteFunction_1_0>(osLibrary->getProcAddress(METRICS_LIBRARY_CONTEXT_DELETE_1_0));
} else {
api->contextCreate = nullptr;
api->contextDelete = nullptr;
}
if (!api->contextCreate) {
return false;
}
if (!api->contextDelete) {
return false;
}
return true;
}
//////////////////////////////////////////////////////
// MetricsLibrary::createContext
//////////////////////////////////////////////////////
bool MetricsLibrary::contextCreate(
const ClientType_1_0 &clientType,
ClientData_1_0 &clientData,
ContextCreateData_1_0 &createData,
ContextHandle_1_0 &handle) {
createData.Api = &api->functions;
createData.ClientCallbacks = &api->callbacks;
createData.ClientData = &clientData;
return api->contextCreate(
clientType,
&createData,
&handle) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// MetricsLibrary::contextDelete
//////////////////////////////////////////////////////
bool MetricsLibrary::contextDelete(
const ContextHandle_1_0 &handle) {
return api->contextDelete(handle) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// MetricsLibrary::hwCountersCreate
//////////////////////////////////////////////////////
bool MetricsLibrary::hwCountersCreate(
const ContextHandle_1_0 &context,
const uint32_t slots,
const ConfigurationHandle_1_0 user,
QueryHandle_1_0 &query) {
QueryCreateData_1_0 data = {};
data.HandleContext = context;
data.Type = ObjectType::QueryHwCounters;
data.Slots = slots;
return api->functions.QueryCreate(
&data,
&query) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// MetricsLibrary::hwCountersDelete
//////////////////////////////////////////////////////
bool MetricsLibrary::hwCountersDelete(
const QueryHandle_1_0 &query) {
return api->functions.QueryDelete(query) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// MetricsLibrary::hwCountersGetReport
//////////////////////////////////////////////////////
bool MetricsLibrary::hwCountersGetReport(
const QueryHandle_1_0 &handle,
const uint32_t slot,
const uint32_t slotsCount,
const uint32_t dataSize,
void *data) {
GetReportData_1_0 report = {};
report.Type = ObjectType::QueryHwCounters;
report.Query.Handle = handle;
report.Query.Slot = slot;
report.Query.SlotsCount = slotsCount;
report.Query.Data = data;
report.Query.DataSize = dataSize;
return api->functions.GetData(&report) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// MetricsLibrary::hwCountersGetApiReportSize
//////////////////////////////////////////////////////
uint32_t MetricsLibrary::hwCountersGetApiReportSize() {
ValueType type = ValueType::Uint32;
TypedValue_1_0 value = {};
return api->functions.GetParameter(ParameterType::QueryHwCountersReportApiSize, &type, &value) == StatusCode::Success
? value.ValueUInt32
: 0;
}
//////////////////////////////////////////////////////
// MetricsLibrary::hwCountersGetGpuReportSize
//////////////////////////////////////////////////////
uint32_t MetricsLibrary::hwCountersGetGpuReportSize() {
ValueType type = ValueType::Uint32;
TypedValue_1_0 value = {};
return api->functions.GetParameter(ParameterType::QueryHwCountersReportGpuSize, &type, &value) == StatusCode::Success
? value.ValueUInt32
: 0;
}
//////////////////////////////////////////////////////
// MetricsLibrary::commandBufferGet
//////////////////////////////////////////////////////
bool MetricsLibrary::commandBufferGet(
CommandBufferData_1_0 &data) {
return api->functions.CommandBufferGet(
&data) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// MetricsLibrary::commandBufferGetSize
//////////////////////////////////////////////////////
bool MetricsLibrary::commandBufferGetSize(
const CommandBufferData_1_0 &commandBufferData,
CommandBufferSize_1_0 &commandBufferSize) {
return api->functions.CommandBufferGetSize(
&commandBufferData,
&commandBufferSize) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// MetricsLibrary::oaConfigurationCreate
//////////////////////////////////////////////////////
bool MetricsLibrary::oaConfigurationCreate(
const ContextHandle_1_0 &context,
ConfigurationHandle_1_0 &handle) {
ConfigurationCreateData_1_0 data = {};
data.HandleContext = context;
data.Type = ObjectType::ConfigurationHwCountersOa;
return api->functions.ConfigurationCreate(
&data,
&handle) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// MetricsLibrary::oaConfigurationDelete
//////////////////////////////////////////////////////
bool MetricsLibrary::oaConfigurationDelete(
const ConfigurationHandle_1_0 &handle) {
return api->functions.ConfigurationDelete(handle) == StatusCode::Success;
}
} // namespace NEO

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "runtime/os_interface/os_library.h"
#include "instrumentation.h"
#include <memory>
namespace NEO {
using MetricsLibraryApi::ClientApi;
using MetricsLibraryApi::ClientCallbacks_1_0;
using MetricsLibraryApi::ClientData_1_0;
using MetricsLibraryApi::ClientGen;
using MetricsLibraryApi::ClientType_1_0;
using MetricsLibraryApi::CommandBufferData_1_0;
using MetricsLibraryApi::CommandBufferSize_1_0;
using MetricsLibraryApi::ConfigurationActivateData_1_0;
using MetricsLibraryApi::ConfigurationCreateData_1_0;
using MetricsLibraryApi::ConfigurationHandle_1_0;
using MetricsLibraryApi::ContextCreateData_1_0;
using MetricsLibraryApi::ContextCreateFunction_1_0;
using MetricsLibraryApi::ContextDeleteFunction_1_0;
using MetricsLibraryApi::ContextHandle_1_0;
using MetricsLibraryApi::GetReportData_1_0;
using MetricsLibraryApi::GpuConfigurationActivationType;
using MetricsLibraryApi::GpuMemory_1_0;
using MetricsLibraryApi::Interface_1_0;
using MetricsLibraryApi::ObjectType;
using MetricsLibraryApi::ParameterType;
using MetricsLibraryApi::QueryCreateData_1_0;
using MetricsLibraryApi::QueryHandle_1_0;
using MetricsLibraryApi::StatusCode;
using MetricsLibraryApi::TypedValue_1_0;
using MetricsLibraryApi::ValueType;
class MetricsLibraryInterface {
public:
ContextCreateFunction_1_0 contextCreate = nullptr;
ContextDeleteFunction_1_0 contextDelete = nullptr;
Interface_1_0 functions = {};
ClientCallbacks_1_0 callbacks = {};
};
class MetricsLibrary {
public:
MetricsLibrary();
MOCKABLE_VIRTUAL ~MetricsLibrary(){};
// Library open function.
MOCKABLE_VIRTUAL bool open();
// Context create / destroy functions.
MOCKABLE_VIRTUAL bool contextCreate(const ClientType_1_0 &client, ClientData_1_0 &clientData, ContextCreateData_1_0 &createData, ContextHandle_1_0 &handle);
MOCKABLE_VIRTUAL bool contextDelete(const ContextHandle_1_0 &handle);
// HwCounters functions.
MOCKABLE_VIRTUAL bool hwCountersCreate(const ContextHandle_1_0 &context, const uint32_t slots, const ConfigurationHandle_1_0 mmio, QueryHandle_1_0 &handle);
MOCKABLE_VIRTUAL bool hwCountersDelete(const QueryHandle_1_0 &handle);
MOCKABLE_VIRTUAL bool hwCountersGetReport(const QueryHandle_1_0 &handle, const uint32_t slot, const uint32_t slotsCount, const uint32_t dataSize, void *data);
MOCKABLE_VIRTUAL uint32_t hwCountersGetApiReportSize();
MOCKABLE_VIRTUAL uint32_t hwCountersGetGpuReportSize();
// Oa configuration functions.
MOCKABLE_VIRTUAL bool oaConfigurationCreate(const ContextHandle_1_0 &context, ConfigurationHandle_1_0 &handle);
MOCKABLE_VIRTUAL bool oaConfigurationDelete(const ConfigurationHandle_1_0 &handle);
MOCKABLE_VIRTUAL bool oaConfigurationActivate(const ConfigurationHandle_1_0 &handle);
MOCKABLE_VIRTUAL bool oaConfigurationDeactivate(const ConfigurationHandle_1_0 &handle);
// User mmio configuration functions.
MOCKABLE_VIRTUAL bool userConfigurationCreate(const ContextHandle_1_0 &context, ConfigurationHandle_1_0 &handle);
MOCKABLE_VIRTUAL bool userConfigurationDelete(const ConfigurationHandle_1_0 &handle);
// Command buffer functions.
MOCKABLE_VIRTUAL bool commandBufferGet(CommandBufferData_1_0 &data);
MOCKABLE_VIRTUAL bool commandBufferGetSize(const CommandBufferData_1_0 &commandBufferData, CommandBufferSize_1_0 &commandBufferSize);
public:
std::unique_ptr<OsLibrary> osLibrary;
std::unique_ptr<MetricsLibraryInterface> api;
};
} // namespace NEO

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Intel Corporation
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -18,4 +18,7 @@ extern const char *testDllName;
extern const char *fileSeparator;
// Pci Path
extern const char *sysFsPciPath;
// Os specific Metrics Library name
extern const char *metricsLibraryDllName;
}; // namespace Os

View File

@@ -21,7 +21,6 @@ class OSInterface {
OSInterfaceImpl *get() const {
return osInterfaceImpl;
};
unsigned int getHwContextId() const;
static bool osEnabled64kbPages;
static bool osEnableLocalMemory;
static bool are64kbPagesEnabled();

View File

@@ -7,175 +7,240 @@
#include "runtime/os_interface/performance_counters.h"
#include "runtime/helpers/debug_helpers.h"
#include "runtime/os_interface/os_interface.h"
#include "runtime/os_interface/os_time.h"
#include "runtime/utilities/tag_allocator.h"
#include "CL/cl.h"
using namespace MetricsLibraryApi;
namespace NEO {
decltype(&instrGetPerfCountersQueryData) getPerfCountersQueryDataFactory[IGFX_MAX_CORE] = {
nullptr,
};
size_t perfCountersQuerySize[IGFX_MAX_CORE] = {
0,
};
PerformanceCounters::PerformanceCounters(OSTime *osTime) {
this->osTime = osTime;
DEBUG_BREAK_IF(osTime == nullptr);
gfxFamily = IGFX_UNKNOWN_CORE;
cbData = {
0,
};
this->osInterface = osTime->getOSInterface();
hwMetricsEnabled = false;
useMIRPC = false;
pAutoSamplingInterface = nullptr;
cpuRawTimestamp = 0;
refCounter = 0;
available = false;
reportId = 0;
//////////////////////////////////////////////////////
// PerformanceCounters constructor.
//////////////////////////////////////////////////////
PerformanceCounters::PerformanceCounters() {
metricsLibrary = std::make_unique<MetricsLibrary>();
UNRECOVERABLE_IF(metricsLibrary == nullptr);
}
//////////////////////////////////////////////////////
// PerformanceCounters::getReferenceNumber
//////////////////////////////////////////////////////
uint32_t PerformanceCounters::getReferenceNumber() {
std::lock_guard<std::mutex> lockMutex(mutex);
return referenceCounter;
}
//////////////////////////////////////////////////////
// PerformanceCounters::isAvailable
//////////////////////////////////////////////////////
bool PerformanceCounters::isAvailable() {
return available;
}
//////////////////////////////////////////////////////
// PerformanceCounters::enable
//////////////////////////////////////////////////////
void PerformanceCounters::enable() {
mutex.lock();
std::lock_guard<std::mutex> lg(mutex, std::adopt_lock);
if (refCounter == 0) {
enableImpl();
std::lock_guard<std::mutex> lockMutex(mutex);
if (referenceCounter == 0) {
available = openMetricsLibrary();
}
refCounter++;
referenceCounter++;
}
//////////////////////////////////////////////////////
// PerformanceCounters::shutdown
//////////////////////////////////////////////////////
void PerformanceCounters::shutdown() {
mutex.lock();
std::lock_guard<std::mutex> lg(mutex, std::adopt_lock);
if (refCounter >= 1) {
if (refCounter == 1) {
shutdownImpl();
std::lock_guard<std::mutex> lockMutex(mutex);
if (referenceCounter >= 1) {
if (referenceCounter == 1) {
available = false;
closeMetricsLibrary();
}
refCounter--;
referenceCounter--;
}
}
void PerformanceCounters::initialize(const HardwareInfo *hwInfo) {
useMIRPC = !(hwInfo->workaroundTable.waDoNotUseMIReportPerfCount);
gfxFamily = hwInfo->platform.eRenderCoreFamily;
//////////////////////////////////////////////////////
// PerformanceCounters::getMetricsLibraryInterface
//////////////////////////////////////////////////////
MetricsLibrary *PerformanceCounters::getMetricsLibraryInterface() {
return metricsLibrary.get();
}
if (getPerfCountersQueryDataFactory[gfxFamily] != nullptr) {
getPerfCountersQueryDataFunc = getPerfCountersQueryDataFactory[gfxFamily];
} else {
perfCountersQuerySize[gfxFamily] = sizeof(GTDI_QUERY);
//////////////////////////////////////////////////////
// PerformanceCounters::setMetricsLibraryInterface
//////////////////////////////////////////////////////
void PerformanceCounters::setMetricsLibraryInterface(std::unique_ptr<MetricsLibrary> newMetricsLibrary) {
metricsLibrary = std::move(newMetricsLibrary);
}
//////////////////////////////////////////////////////
// PerformanceCounters::getMetricsLibraryContext
//////////////////////////////////////////////////////
ContextHandle_1_0 PerformanceCounters::getMetricsLibraryContext() {
return context;
}
//////////////////////////////////////////////////////
// PerformanceCounters::openMetricsLibrary
//////////////////////////////////////////////////////
bool PerformanceCounters::openMetricsLibrary() {
// Open metrics library.
bool result = metricsLibrary->open();
DEBUG_BREAK_IF(!result);
// Create metrics library context.
if (result) {
result = metricsLibrary->contextCreate(
clientType,
clientData,
contextData,
context);
// Validate gpu report size.
DEBUG_BREAK_IF(!metricsLibrary->hwCountersGetGpuReportSize());
}
// Error handling.
if (!result) {
closeMetricsLibrary();
}
return result;
}
//////////////////////////////////////////////////////
// PerformanceCounters::closeMetricsLibrary
//////////////////////////////////////////////////////
void PerformanceCounters::closeMetricsLibrary() {
// Destroy oa/user mmio configuration.
releaseCountersConfiguration();
// Destroy hw counters query.
if (query.IsValid()) {
metricsLibrary->hwCountersDelete(query);
}
// Destroy metrics library context.
if (context.IsValid()) {
metricsLibrary->contextDelete(context);
}
}
void PerformanceCounters::enableImpl() {
hwMetricsEnabled = hwMetricsEnableFunc(cbData, true);
if (!pAutoSamplingInterface && hwMetricsEnabled) {
autoSamplingStartFunc(cbData, &pAutoSamplingInterface);
if (pAutoSamplingInterface) {
available = true;
//////////////////////////////////////////////////////
// PerformanceCounters::getQueryHandle
//////////////////////////////////////////////////////
QueryHandle_1_0 PerformanceCounters::getQueryHandle() {
if (!query.IsValid()) {
metricsLibrary->hwCountersCreate(
context,
1,
userConfiguration,
query);
}
DEBUG_BREAK_IF(!query.IsValid());
return query;
}
//////////////////////////////////////////////////////
// PerformanceCounters::getGpuCommandsSize
//////////////////////////////////////////////////////
uint32_t PerformanceCounters::getGpuCommandsSize(
const bool begin) {
CommandBufferData_1_0 bufferData = {};
CommandBufferSize_1_0 bufferSize = {};
if (begin) {
// Load currently activated (through metrics discovery) oa/user mmio configuration and use it.
// It will allow to change counters configuration between subsequent clEnqueueNDCommandRange calls.
if (!enableCountersConfiguration()) {
return 0;
}
}
bufferData.HandleContext = context;
bufferData.Type = GpuCommandBufferType::Render;
bufferData.CommandsType = ObjectType::QueryHwCounters;
bufferData.QueryHwCounters.Begin = begin;
bufferData.QueryHwCounters.Handle = getQueryHandle();
bufferData.QueryHwCounters.HandleUserConfiguration = userConfiguration;
return metricsLibrary->commandBufferGetSize(bufferData, bufferSize)
? bufferSize.GpuMemorySize
: 0;
}
void PerformanceCounters::shutdownImpl() {
if (hwMetricsEnabled) {
hwMetricsEnableFunc(cbData, false);
hwMetricsEnabled = false;
}
if (pAutoSamplingInterface) {
autoSamplingStopFunc(&pAutoSamplingInterface);
pAutoSamplingInterface = nullptr;
available = false;
}
//////////////////////////////////////////////////////
// PerformanceCounters::getGpuCommands
//////////////////////////////////////////////////////
bool PerformanceCounters::getGpuCommands(
TagNode<HwPerfCounter> &performanceCounters,
const bool begin,
const uint32_t bufferSize,
void *pBuffer) {
// Command Buffer data.
CommandBufferData_1_0 bufferData = {};
bufferData.HandleContext = context;
bufferData.Type = GpuCommandBufferType::Render;
bufferData.CommandsType = ObjectType::QueryHwCounters;
bufferData.Data = pBuffer;
bufferData.Size = bufferSize;
// Gpu memory allocation for query hw counters.
bufferData.Allocation.CpuAddress = reinterpret_cast<uint8_t *>(performanceCounters.tagForCpuAccess);
bufferData.Allocation.GpuAddress = performanceCounters.getGpuAddress();
// Query hw counters specific data.
bufferData.QueryHwCounters.Begin = begin;
bufferData.QueryHwCounters.Handle = getQueryHandle();
bufferData.QueryHwCounters.HandleUserConfiguration = userConfiguration;
return metricsLibrary->commandBufferGet(bufferData);
}
void PerformanceCounters::setCpuTimestamp() {
cpuRawTimestamp = osTime->getCpuRawTimestamp();
//////////////////////////////////////////////////////
// PerformanceCounters::getApiReportSize
//////////////////////////////////////////////////////
uint32_t PerformanceCounters::getApiReportSize() {
return metricsLibrary->hwCountersGetApiReportSize();
}
InstrPmRegsCfg *PerformanceCounters::getPmRegsCfg(uint32_t configuration) {
if (!hwMetricsEnabled) {
return nullptr;
//////////////////////////////////////////////////////
// PerformanceCounters::getGpuReportSize
//////////////////////////////////////////////////////
uint32_t PerformanceCounters::getGpuReportSize() {
return metricsLibrary->hwCountersGetGpuReportSize();
}
//////////////////////////////////////////////////////
// PerformanceCounters::getApiReport
//////////////////////////////////////////////////////
bool PerformanceCounters::getApiReport(const size_t inputParamSize, void *pInputParam, size_t *pOutputParamSize, bool isEventComplete) {
const uint32_t outputSize = metricsLibrary->hwCountersGetApiReportSize();
if (pOutputParamSize) {
*pOutputParamSize = outputSize;
}
switch (configuration) {
case GTDI_CONFIGURATION_SET_DYNAMIC:
case GTDI_CONFIGURATION_SET_1:
case GTDI_CONFIGURATION_SET_2:
case GTDI_CONFIGURATION_SET_3:
break;
default:
return nullptr;
}
InstrPmRegsCfg *pPmRegsCfg = new InstrPmRegsCfg();
pPmRegsCfg->OaCounters.Handle = INSTR_PM_REGS_CFG_INVALID;
mutex.lock();
std::lock_guard<std::mutex> lg(mutex, std::adopt_lock);
if (getPmRegsCfgFunc(cbData, configuration, pPmRegsCfg, nullptr)) {
return pPmRegsCfg;
}
delete pPmRegsCfg;
return nullptr;
}
bool PerformanceCounters::verifyPmRegsCfg(InstrPmRegsCfg *pCfg, uint32_t *pLastPmRegsCfgHandle, bool *pLastPmRegsCfgPending) {
if (pCfg == nullptr || pLastPmRegsCfgHandle == nullptr || pLastPmRegsCfgPending == nullptr) {
return false;
}
if (checkPmRegsCfgFunc(pCfg, pLastPmRegsCfgHandle, pAutoSamplingInterface)) {
if (loadPmRegsCfgFunc(cbData, pCfg, 1)) {
return true;
}
}
return false;
}
bool PerformanceCounters::sendPmRegsCfgCommands(InstrPmRegsCfg *pCfg, uint32_t *pLastPmRegsCfgHandle, bool *pLastPmRegsCfgPending) {
if (verifyPmRegsCfg(pCfg, pLastPmRegsCfgHandle, pLastPmRegsCfgPending)) {
*pLastPmRegsCfgPending = true;
if (pInputParam == nullptr && inputParamSize == 0 && pOutputParamSize) {
return true;
}
return false;
}
bool PerformanceCounters::processEventReport(size_t inputParamSize, void *inputParam, size_t *outputParamSize, HwPerfCounter *pPrivateData, InstrPmRegsCfg *countersConfiguration, bool isEventComplete) {
size_t outputSize = perfCountersQuerySize[gfxFamily];
if (outputParamSize) {
*outputParamSize = outputSize;
}
if (inputParam == nullptr && inputParamSize == 0 && outputParamSize) {
return true;
}
if (inputParam == nullptr || isEventComplete == false) {
if (pInputParam == nullptr || isEventComplete == false) {
return false;
}
if (inputParamSize < outputSize) {
return false;
}
GTDI_QUERY *pClientData = static_cast<GTDI_QUERY *>(inputParam);
getPerfCountersQueryDataFunc(cbData, pClientData, &pPrivateData->HWPerfCounters,
cpuRawTimestamp, pAutoSamplingInterface, countersConfiguration, useMIRPC, true, nullptr);
return true;
}
int PerformanceCounters::sendPerfConfiguration(uint32_t count, uint32_t *pOffsets, uint32_t *pValues) {
bool ret = false;
if (count == 0 || pOffsets == NULL || pValues == NULL) {
return CL_INVALID_VALUE;
}
mutex.lock();
std::lock_guard<std::mutex> lg(mutex, std::adopt_lock);
if (pOffsets[0] != INSTR_READ_REGS_CFG_TAG) {
ret = setPmRegsCfgFunc(cbData, count, pOffsets, pValues);
} else if (count > 1) {
ret = sendReadRegsCfgFunc(cbData, count - 1, pOffsets + 1, pValues + 1);
}
return ret ? CL_SUCCESS : CL_PROFILING_INFO_NOT_AVAILABLE;
}
uint32_t PerformanceCounters::getCurrentReportId() {
return (osInterface->getHwContextId() << 12) | getReportId();
return metricsLibrary->hwCountersGetReport(query, 0, 1, outputSize, pInputParam);
}
} // namespace NEO

View File

@@ -7,71 +7,105 @@
#pragma once
#include "runtime/event/perf_counter.h"
#include "runtime/helpers/hw_info.h"
#include "runtime/os_interface/metrics_library.h"
#include "CL/cl.h"
#include <memory>
#include <mutex>
namespace NEO {
struct HardwareInfo;
class OSInterface;
class OSTime;
//////////////////////////////////////////////////////
// Forward declaration.
//////////////////////////////////////////////////////
template <typename Node>
struct TagNode;
//////////////////////////////////////////////////////
// Performance counters implementation.
//////////////////////////////////////////////////////
class PerformanceCounters {
public:
static std::unique_ptr<PerformanceCounters> create(OSTime *osTime);
//////////////////////////////////////////////////////
// Constructor/destructor.
//////////////////////////////////////////////////////
PerformanceCounters();
virtual ~PerformanceCounters() = default;
//////////////////////////////////////////////////////
// Performance counters creation.
//////////////////////////////////////////////////////
static std::unique_ptr<PerformanceCounters> create(class Device *device);
void enable();
void shutdown();
virtual void initialize(const HardwareInfo *hwInfo);
InstrPmRegsCfg *getPmRegsCfg(uint32_t configuration);
bool sendPmRegsCfgCommands(InstrPmRegsCfg *pCfg, uint32_t *pLastPmRegsCfgHandle, bool *pLastPmRegsCfgPending);
void setCpuTimestamp();
bool processEventReport(size_t pClientDataSize, void *pClientData, size_t *outputSize, HwPerfCounter *pPrivateData, InstrPmRegsCfg *countersConfiguration, bool isEventComplete);
int sendPerfConfiguration(uint32_t count, uint32_t *pOffsets, uint32_t *pValues);
uint32_t getCurrentReportId();
bool isAvailable();
uint32_t getReferenceNumber();
uint32_t getPerfCountersReferenceNumber() {
mutex.lock();
std::lock_guard<std::mutex> lg(mutex, std::adopt_lock);
/////////////////////////////////////////////////////
// Gpu oa/mmio configuration.
/////////////////////////////////////////////////////
virtual bool enableCountersConfiguration() = 0;
virtual void releaseCountersConfiguration() = 0;
return refCounter;
}
//////////////////////////////////////////////////////
// Gpu commands.
//////////////////////////////////////////////////////
uint32_t getGpuCommandsSize(const bool begin);
bool getGpuCommands(TagNode<HwPerfCounter> &performanceCounters, const bool begin, const uint32_t bufferSize, void *pBuffer);
bool isAvailable() {
return available;
}
/////////////////////////////////////////////////////
// Gpu/Api reports.
/////////////////////////////////////////////////////
uint32_t getApiReportSize();
uint32_t getGpuReportSize();
bool getApiReport(const size_t inputParamSize, void *pClientData, size_t *pOutputSize, bool isEventComplete);
/////////////////////////////////////////////////////
// Metrics Library interface.
/////////////////////////////////////////////////////
MetricsLibrary *getMetricsLibraryInterface();
void setMetricsLibraryInterface(std::unique_ptr<MetricsLibrary> newMetricsLibrary);
bool openMetricsLibrary();
void closeMetricsLibrary();
/////////////////////////////////////////////////////
// Metrics Library context/query handles.
/////////////////////////////////////////////////////
ContextHandle_1_0 getMetricsLibraryContext();
QueryHandle_1_0 getQueryHandle();
protected:
PerformanceCounters(OSTime *osTime);
virtual bool verifyPmRegsCfg(InstrPmRegsCfg *pCfg, uint32_t *pLastPmRegsCfgHandle, bool *pLastPmRegsCfgPending);
virtual void enableImpl();
void shutdownImpl();
MOCKABLE_VIRTUAL uint32_t getReportId() {
return ++reportId & 0xFFF;
}
GFXCORE_FAMILY gfxFamily;
InstrEscCbData cbData;
OSInterface *osInterface;
OSTime *osTime;
bool hwMetricsEnabled;
bool useMIRPC;
void *pAutoSamplingInterface;
uint64_t cpuRawTimestamp;
/////////////////////////////////////////////////////
// Common members.
/////////////////////////////////////////////////////
std::mutex mutex;
uint32_t refCounter;
bool available;
uint32_t reportId;
decltype(&instrAutoSamplingStart) autoSamplingStartFunc = instrAutoSamplingStart;
decltype(&instrAutoSamplingStop) autoSamplingStopFunc = instrAutoSamplingStop;
decltype(&instrCheckPmRegsCfg) checkPmRegsCfgFunc = instrCheckPmRegsCfg;
decltype(&instrGetPerfCountersQueryData) getPerfCountersQueryDataFunc = instrGetPerfCountersQueryData;
decltype(&instrEscGetPmRegsCfg) getPmRegsCfgFunc = instrEscGetPmRegsCfg;
decltype(&instrEscHwMetricsEnable) hwMetricsEnableFunc = instrEscHwMetricsEnable;
decltype(&instrEscLoadPmRegsCfg) loadPmRegsCfgFunc = instrEscLoadPmRegsCfg;
decltype(&instrEscSetPmRegsCfg) setPmRegsCfgFunc = instrEscSetPmRegsCfg;
decltype(&instrEscSendReadRegsCfg) sendReadRegsCfgFunc = instrEscSendReadRegsCfg;
uint32_t referenceCounter = 0;
bool available = false;
/////////////////////////////////////////////////////
// Metrics Library interface.
/////////////////////////////////////////////////////
std::unique_ptr<MetricsLibrary> metricsLibrary = {};
/////////////////////////////////////////////////////
// Metrics Library client data.
/////////////////////////////////////////////////////
ClientData_1_0 clientData = {};
ClientType_1_0 clientType = {ClientApi::OpenCL, ClientGen::Unknown};
/////////////////////////////////////////////////////
// Metrics Library context.
/////////////////////////////////////////////////////
ContextCreateData_1_0 contextData = {};
ContextHandle_1_0 context = {};
/////////////////////////////////////////////////////
// Metrics Library oa/mmio counters configuration.
/////////////////////////////////////////////////////
ConfigurationHandle_1_0 oaConfiguration = {};
ConfigurationHandle_1_0 userConfiguration = {};
/////////////////////////////////////////////////////
// Metrics Library query object.
/////////////////////////////////////////////////////
QueryHandle_1_0 query = {};
};
} // namespace NEO

View File

@@ -36,6 +36,7 @@ set(RUNTIME_SRCS_OS_INTERFACE_WINDOWS
${CMAKE_CURRENT_SOURCE_DIR}/os_library.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_library.h
${CMAKE_CURRENT_SOURCE_DIR}/os_memory_win.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_metrics_library.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_socket.h
${CMAKE_CURRENT_SOURCE_DIR}/os_thread_win.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_thread_win.h

View File

@@ -22,10 +22,6 @@ OSInterface::~OSInterface() {
delete osInterfaceImpl;
}
uint32_t OSInterface::getHwContextId() const {
return osInterfaceImpl->getHwContextId();
}
uint32_t OSInterface::getDeviceHandle() const {
return static_cast<uint32_t>(osInterfaceImpl->getDeviceHandle());
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/os_interface/metrics_library.h"
namespace NEO {
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::oaConfigurationActivate
//////////////////////////////////////////////////////
bool MetricsLibrary::oaConfigurationActivate(
const ConfigurationHandle_1_0 &handle) {
ConfigurationActivateData_1_0 data = {};
data.Type = GpuConfigurationActivationType::EscapeCode;
return api->functions.ConfigurationActivate(
handle,
&data) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::oaConfigurationDeactivate
//////////////////////////////////////////////////////
bool MetricsLibrary::oaConfigurationDeactivate(
const ConfigurationHandle_1_0 &handle) {
return api->functions.ConfigurationDeactivate(
handle) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::userConfigurationCreate
//////////////////////////////////////////////////////
bool MetricsLibrary::userConfigurationCreate(
const ContextHandle_1_0 &context,
ConfigurationHandle_1_0 &handle) {
ConfigurationCreateData_1_0 data = {};
data.HandleContext = context;
data.Type = ObjectType::ConfigurationHwCountersUser;
return api->functions.ConfigurationCreate(
&data,
&handle) == StatusCode::Success;
}
//////////////////////////////////////////////////////
// FUNCTION: MetricsLibrary::userConfigurationDelete
//////////////////////////////////////////////////////
bool MetricsLibrary::userConfigurationDelete(
const ConfigurationHandle_1_0 &handle) {
return api->functions.ConfigurationDelete(handle) == StatusCode::Success;
}
} // namespace NEO

View File

@@ -7,31 +7,82 @@
#include "performance_counters_win.h"
#include "runtime/device/device.h"
#include "runtime/helpers/hw_helper.h"
#include "runtime/os_interface/windows/os_interface.h"
#include "runtime/os_interface/windows/windows_wrapper.h"
#include "runtime/os_interface/windows/os_time_win.h"
namespace NEO {
std::unique_ptr<PerformanceCounters> PerformanceCounters::create(OSTime *osTime) {
return std::unique_ptr<PerformanceCounters>(new PerformanceCountersWin(osTime));
}
PerformanceCountersWin::PerformanceCountersWin(OSTime *osTime) : PerformanceCounters(osTime) {
cbData.hAdapter = (void *)(UINT_PTR)osInterface->get()->getAdapterHandle();
cbData.hDevice = (void *)(UINT_PTR)osInterface->get()->getDeviceHandle();
cbData.pfnEscapeCb = osInterface->get()->getEscapeHandle();
/////////////////////////////////////////////////////
// PerformanceCounters::create
/////////////////////////////////////////////////////
std::unique_ptr<PerformanceCounters> PerformanceCounters::create(Device *device) {
auto counter = std::make_unique<PerformanceCountersWin>();
auto osInterface = device->getOSTime()->getOSInterface()->get();
auto gen = device->getHardwareInfo().platform.eRenderCoreFamily;
auto &hwHelper = HwHelper::get(gen);
UNRECOVERABLE_IF(counter == nullptr);
counter->clientData.Windows.Adapter = reinterpret_cast<void *>(static_cast<UINT_PTR>(osInterface->getAdapterHandle()));
counter->clientData.Windows.Device = reinterpret_cast<void *>(static_cast<UINT_PTR>(osInterface->getDeviceHandle()));
counter->clientData.Windows.Device = reinterpret_cast<void *>(static_cast<UINT_PTR>(osInterface->getDeviceHandle()));
counter->clientData.Windows.Escape = osInterface->getEscapeHandle();
counter->clientData.Windows.KmdInstrumentationEnabled = device->getHardwareInfo().capabilityTable.instrumentationEnabled;
counter->contextData.ClientData = &counter->clientData;
counter->clientType.Gen = static_cast<MetricsLibraryApi::ClientGen>(hwHelper.getMetricsLibraryGenId());
return counter;
}
PerformanceCountersWin::~PerformanceCountersWin() {
if (pAutoSamplingInterface) {
autoSamplingStopFunc(&pAutoSamplingInterface);
pAutoSamplingInterface = nullptr;
available = false;
//////////////////////////////////////////////////////
// PerformanceCountersWin::enableCountersConfiguration
//////////////////////////////////////////////////////
bool PerformanceCountersWin::enableCountersConfiguration() {
// Release previous counters configuration so the user
// can change configuration between kernels.
releaseCountersConfiguration();
// Create mmio user configuration.
if (!metricsLibrary->userConfigurationCreate(
context,
userConfiguration)) {
DEBUG_BREAK_IF(true);
return false;
}
// Create oa configuration.
if (!metricsLibrary->oaConfigurationCreate(
context,
oaConfiguration)) {
DEBUG_BREAK_IF(true);
return false;
}
// Enable oa configuration.
if (!metricsLibrary->oaConfigurationActivate(
oaConfiguration)) {
DEBUG_BREAK_IF(true);
return false;
}
return true;
}
//////////////////////////////////////////////////////
// PerformanceCountersWin::releaseCountersConfiguration
//////////////////////////////////////////////////////
void PerformanceCountersWin::releaseCountersConfiguration() {
// Mmio user configuration.
if (userConfiguration.IsValid()) {
metricsLibrary->userConfigurationDelete(userConfiguration);
userConfiguration.data = nullptr;
}
// Oa configuration.
if (oaConfiguration.IsValid()) {
metricsLibrary->oaConfigurationDeactivate(oaConfiguration);
metricsLibrary->oaConfigurationDelete(oaConfiguration);
oaConfiguration.data = nullptr;
}
}
void PerformanceCountersWin::initialize(const HardwareInfo *hwInfo) {
PerformanceCounters::initialize(hwInfo);
setAvailableFunc(true);
verifyEnableFunc(cbData);
}
} // namespace NEO

View File

@@ -7,18 +7,18 @@
#pragma once
#include "runtime/os_interface/performance_counters.h"
#include "runtime/os_interface/windows/os_interface.h"
namespace NEO {
class PerformanceCountersWin : virtual public PerformanceCounters {
public:
PerformanceCountersWin(OSTime *osTime);
~PerformanceCountersWin() override;
void initialize(const HardwareInfo *hwInfo) override;
PerformanceCountersWin() = default;
~PerformanceCountersWin() override = default;
protected:
decltype(&instrSetAvailable) setAvailableFunc = instrSetAvailable;
decltype(&instrEscVerifyEnable) verifyEnableFunc = instrEscVerifyEnable;
/////////////////////////////////////////////////////
// Gpu oa/mmio configuration.
/////////////////////////////////////////////////////
bool enableCountersConfiguration() override;
void releaseCountersConfiguration() override;
};
} // namespace NEO