From 4a4fdb40e7d62ba95a86109e9290dd5230af8019 Mon Sep 17 00:00:00 2001 From: Igor Surmin Date: Mon, 27 Aug 2018 04:24:45 +0300 Subject: [PATCH] Implement Intel performance counters support for D3D11 --- renderdoc.sln | 11 + renderdoc/driver/d3d11/d3d11_counters.cpp | 106 +- renderdoc/driver/d3d11/d3d11_replay.cpp | 21 + renderdoc/driver/d3d11/d3d11_replay.h | 5 + .../driver/d3d11/renderdoc_d3d11.vcxproj | 3 + renderdoc/driver/ihv/intel/Intel.vcxproj | 107 ++ renderdoc/driver/ihv/intel/intel_counters.cpp | 440 +++++++ renderdoc/driver/ihv/intel/intel_counters.h | 97 ++ .../ihv/intel/official/DriverStorePath.h | 333 +++++ .../intel/official/metrics_discovery_api.h | 1168 +++++++++++++++++ renderdoc/renderdoc.vcxproj | 5 +- 11 files changed, 2294 insertions(+), 2 deletions(-) create mode 100644 renderdoc/driver/ihv/intel/Intel.vcxproj create mode 100644 renderdoc/driver/ihv/intel/intel_counters.cpp create mode 100644 renderdoc/driver/ihv/intel/intel_counters.h create mode 100644 renderdoc/driver/ihv/intel/official/DriverStorePath.h create mode 100644 renderdoc/driver/ihv/intel/official/metrics_discovery_api.h diff --git a/renderdoc.sln b/renderdoc.sln index 4997e4305..238132a9f 100644 --- a/renderdoc.sln +++ b/renderdoc.sln @@ -81,6 +81,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NV", "renderdoc\driver\ihv\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD_RGP", "renderdoc\driver\ihv\amd\AMD_RGP.vcxproj", "{B33F8FFD-3C04-4779-9C3B-E2858387971B}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Intel", "renderdoc\driver\ihv\intel\Intel.vcxproj", "{7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Development|x64 = Development|x64 @@ -273,6 +275,14 @@ Global {B33F8FFD-3C04-4779-9C3B-E2858387971B}.Release|x64.Build.0 = Release|x64 {B33F8FFD-3C04-4779-9C3B-E2858387971B}.Release|x86.ActiveCfg = Release|Win32 {B33F8FFD-3C04-4779-9C3B-E2858387971B}.Release|x86.Build.0 = Release|Win32 + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Development|x64.ActiveCfg = Development|x64 + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Development|x64.Build.0 = Development|x64 + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Development|x86.ActiveCfg = Development|Win32 + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Development|x86.Build.0 = Development|Win32 + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Release|x64.ActiveCfg = Release|x64 + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Release|x64.Build.0 = Release|x64 + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Release|x86.ActiveCfg = Release|Win32 + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -307,5 +317,6 @@ Global {37955C79-D91D-423F-8C6C-8F5BCF4F28D4} = {B5A783D9-AEB9-420D-8E77-D4D930F8D88C} {40349AD9-5558-4DF4-84E2-11934DE90A11} = {4DA2F3E3-9A65-45DD-A69B-82C7757D4904} {B33F8FFD-3C04-4779-9C3B-E2858387971B} = {4DA2F3E3-9A65-45DD-A69B-82C7757D4904} + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5} = {4DA2F3E3-9A65-45DD-A69B-82C7757D4904} EndGlobalSection EndGlobal diff --git a/renderdoc/driver/d3d11/d3d11_counters.cpp b/renderdoc/driver/d3d11/d3d11_counters.cpp index b47bbae1e..9e7932852 100644 --- a/renderdoc/driver/d3d11/d3d11_counters.cpp +++ b/renderdoc/driver/d3d11/d3d11_counters.cpp @@ -26,6 +26,7 @@ #include #include "common/common.h" #include "driver/ihv/amd/amd_counters.h" +#include "driver/ihv/intel/intel_counters.h" #include "driver/ihv/nv/nv_counters.h" #include "d3d11_context.h" #include "d3d11_debug.h" @@ -61,6 +62,12 @@ vector D3D11Replay::EnumerateCounters() ret.insert(ret.end(), nvCounters.begin(), nvCounters.end()); } + if(m_pIntelCounters) + { + vector intelCounters = m_pIntelCounters->GetPublicCounterIds(); + ret.insert(ret.end(), intelCounters.begin(), intelCounters.end()); + } + return ret; } @@ -87,6 +94,15 @@ CounterDescription D3D11Replay::DescribeCounter(GPUCounter counterID) } } + // Intel + if(IsIntelCounter(counterID)) + { + if(m_pIntelCounters) + { + return m_pIntelCounters->GetCounterDescription(counterID); + } + } + // 448A0516-B50E-4312-A6DC-CFE7222FC1AC desc.uuid.words[0] = 0x448A0516; desc.uuid.words[1] = 0xB50E4312; @@ -383,6 +399,41 @@ void D3D11Replay::FillTimersNV(uint32_t &eventStartID, uint32_t &sampleIndex, } } +void D3D11Replay::FillTimersIntel(uint32_t &eventStartID, uint32_t &sampleIndex, + vector &eventIDs, const DrawcallDescription &drawnode) +{ + if(drawnode.children.empty()) + return; + + for(size_t i = 0; i < drawnode.children.size(); i++) + { + const DrawcallDescription &d = drawnode.children[i]; + + FillTimersIntel(eventStartID, sampleIndex, eventIDs, drawnode.children[i]); + + if(d.events.empty() || (!(drawnode.children[i].flags & DrawFlags::Drawcall) && + !(drawnode.children[i].flags & DrawFlags::Dispatch))) + continue; + + eventIDs.push_back(d.eventId); + + m_pDevice->ReplayLog(eventStartID, d.eventId, eReplay_WithoutDraw); + + SerializeImmediateContext(); + + m_pIntelCounters->BeginSample(); + + m_pDevice->ReplayLog(eventStartID, d.eventId, eReplay_OnlyDraw); + + SerializeImmediateContext(); + + m_pIntelCounters->EndSample(); + + eventStartID = d.eventId + 1; + sampleIndex++; + } +} + vector D3D11Replay::FetchCountersAMD(const vector &counters) { ID3D11Device *d3dDevice = m_pDevice->GetReal(); @@ -472,6 +523,45 @@ vector D3D11Replay::FetchCountersNV(const vector &cou return ret; } +vector D3D11Replay::FetchCountersIntel(const vector &counters) +{ + m_pIntelCounters->DisableAllCounters(); + + // enable counters it needs + for(size_t i = 0; i < counters.size(); i++) + { + // This function is only called internally, and violating this assertion means our + // caller has invoked this method incorrectly + RDCASSERT(IsIntelCounter(counters[i])); + m_pIntelCounters->EnableCounter(counters[i]); + } + + m_pIntelCounters->BeginSession(); + + uint32_t passCount = m_pIntelCounters->GetPassCount(); + + uint32_t sampleIndex = 0; + + vector eventIDs; + + for(uint32_t p = 0; p < passCount; p++) + { + m_pIntelCounters->BeginPass(); + uint32_t eventStartID = 0; + + sampleIndex = 0; + + eventIDs.clear(); + + FillTimersIntel(eventStartID, sampleIndex, eventIDs, m_pImmediateContext->GetRootDraw()); + m_pIntelCounters->EndPass(); + } + + m_pIntelCounters->EndSession(); + + return m_pIntelCounters->GetCounterData(eventIDs, counters); +} + vector D3D11Replay::FetchCounters(const vector &counters) { vector ret; @@ -486,7 +576,9 @@ vector D3D11Replay::FetchCounters(const vector &count vector d3dCounters; std::copy_if(counters.begin(), counters.end(), std::back_inserter(d3dCounters), - [](const GPUCounter &c) { return !IsAMDCounter(c) && !IsNvidiaCounter(c); }); + [](const GPUCounter &c) { + return !IsAMDCounter(c) && !IsNvidiaCounter(c) && !IsIntelCounter(c); + }); if(m_pAMDCounters) { @@ -514,6 +606,18 @@ vector D3D11Replay::FetchCounters(const vector &count } } + if(m_pIntelCounters) + { + vector intelCounters; + std::copy_if(counters.begin(), counters.end(), std::back_inserter(intelCounters), + [](const GPUCounter &c) { return IsIntelCounter(c); }); + + if(!intelCounters.empty()) + { + ret = FetchCountersIntel(intelCounters); + } + } + if(d3dCounters.empty()) { return ret; diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 0a04d84fb..974b02e44 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -26,6 +26,7 @@ #include "d3d11_replay.h" #include "driver/dx/official/d3dcompiler.h" #include "driver/ihv/amd/amd_counters.h" +#include "driver/ihv/intel/intel_counters.h" #include "driver/ihv/nv/nv_counters.h" #include "driver/shaders/dxbc/dxbc_debug.h" #include "maths/camera.h" @@ -159,6 +160,7 @@ void D3D11Replay::CreateResources() AMDCounters *countersAMD = NULL; NVCounters *countersNV = NULL; + IntelCounters *countersIntel = NULL; if(m_Vendor == GPUVendor::AMD) { @@ -170,6 +172,11 @@ void D3D11Replay::CreateResources() RDCLOG("nVidia GPU detected - trying to initialise nVidia counters"); countersNV = new NVCounters(); } + else if(m_Vendor == GPUVendor::Intel) + { + RDCLOG("Intel GPU detected - trying to initialize Intel counters"); + countersIntel = new IntelCounters(); + } else { RDCLOG("%s GPU detected - no counters available", ToStr(m_Vendor).c_str()); @@ -196,6 +203,17 @@ void D3D11Replay::CreateResources() delete countersNV; m_pNVCounters = NULL; } + + if(countersIntel && countersIntel->Init(d3dDevice)) + { + m_pIntelCounters = countersIntel; + } + else + { + delete countersIntel; + m_pIntelCounters = NULL; + } + RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 1.0f); } @@ -214,6 +232,7 @@ void D3D11Replay::DestroyResources() SAFE_DELETE(m_pAMDCounters); SAFE_DELETE(m_pNVCounters); + SAFE_DELETE(m_pIntelCounters); ShutdownStreamOut(); ClearPostVSCache(); @@ -3533,6 +3552,8 @@ ReplayStatus D3D11_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) { RDCDEBUG("Creating a D3D11 replay device"); + IntelCounters::Load(); + HMODULE lib = NULL; lib = LoadLibraryA("d3d11.dll"); if(lib == NULL) diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index c411df9d8..fa183f2c5 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -38,6 +38,7 @@ class WrappedID3D11DeviceContext; class AMDCounters; class NVCounters; +class IntelCounters; struct D3D11CounterContext; struct D3D11PostVSData @@ -255,12 +256,15 @@ private: std::vector FetchCountersAMD(const vector &counters); std::vector FetchCountersNV(const vector &counters); + std::vector FetchCountersIntel(const vector &counters); void FillTimers(D3D11CounterContext &ctx, const DrawcallDescription &drawnode); void FillTimersAMD(uint32_t &eventStartID, uint32_t &sampleIndex, vector &eventIDs, const DrawcallDescription &drawnode); void FillTimersNV(uint32_t &eventStartID, uint32_t &sampleIndex, vector &eventIDs, const DrawcallDescription &drawnode); + void FillTimersIntel(uint32_t &eventStartID, uint32_t &sampleIndex, vector &eventIDs, + const DrawcallDescription &drawnode); void SerializeImmediateContext(); @@ -301,6 +305,7 @@ private: AMDCounters *m_pAMDCounters = NULL; NVCounters *m_pNVCounters = NULL; + IntelCounters *m_pIntelCounters = NULL; WrappedID3D11Device *m_pDevice = NULL; WrappedID3D11DeviceContext *m_pImmediateContext = NULL; diff --git a/renderdoc/driver/d3d11/renderdoc_d3d11.vcxproj b/renderdoc/driver/d3d11/renderdoc_d3d11.vcxproj index 26ba82a7e..f9b51daca 100644 --- a/renderdoc/driver/d3d11/renderdoc_d3d11.vcxproj +++ b/renderdoc/driver/d3d11/renderdoc_d3d11.vcxproj @@ -158,6 +158,9 @@ {5de5a561-548a-4dd7-90f0-06a2b39eae9a} + + {7fcb5fc5-1dbd-4da6-83a0-6ba4e945bda5} + {c43ff27e-a155-4852-88ec-5ce9334c07a8} false diff --git a/renderdoc/driver/ihv/intel/Intel.vcxproj b/renderdoc/driver/ihv/intel/Intel.vcxproj new file mode 100644 index 000000000..90c5803bc --- /dev/null +++ b/renderdoc/driver/ihv/intel/Intel.vcxproj @@ -0,0 +1,107 @@ + + + + + Development + Win32 + + + Development + x64 + + + Release + Win32 + + + Release + x64 + + + + {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5} + Intel + 8.1 + + + + StaticLibrary + true + Unicode + v140 + + + true + + + + + + + $(SolutionDir)$(Platform)\$(Configuration)\ + $(ExecutablePath) + $(SolutionDir)\breakpad;$(IncludePath) + $(LibraryPath) + $(ExcludePath) + driver_$(ProjectName) + + + $(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\ + + + + WIN64;%(PreprocessorDefinitions) + + + + + RELEASE;%(PreprocessorDefinitions) + + + + + $(SolutionDir)renderdoc\;$(SolutionDir)renderdoc\3rdparty\ + RENDERDOC_EXPORTS;RENDERDOC_PLATFORM_WIN32;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + Level4 + MultiThreadedDLL + false + true + true + false + ProgramDatabase + 4100 + + + Windows + true + + + + + Disabled + + + + + MaxSpeed + Default + true + true + + + true + true + + + + + + + + + + + + + + \ No newline at end of file diff --git a/renderdoc/driver/ihv/intel/intel_counters.cpp b/renderdoc/driver/ihv/intel/intel_counters.cpp new file mode 100644 index 000000000..c43b30c39 --- /dev/null +++ b/renderdoc/driver/ihv/intel/intel_counters.cpp @@ -0,0 +1,440 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2018 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "common/common.h" + +#include "official/DriverStorePath.h" +#include "intel_counters.h" + +#include + +const static std::vector metricSetBlacklist = {"TestOa"}; + +HMODULE IntelCounters::m_MDLibraryHandle = 0; +IMetricsDevice_1_5 *IntelCounters::m_metricsDevice = NULL; +OpenMetricsDevice_fn IntelCounters::OpenMetricsDevice = NULL; +CloseMetricsDevice_fn IntelCounters::CloseMetricsDevice = NULL; + +IntelCounters::IntelCounters() + : m_device(NULL), m_deviceContext(NULL), m_counter(NULL), m_passIndex(0), m_sampleIndex(0) +{ +} + +IntelCounters::~IntelCounters() +{ + if(CloseMetricsDevice) + { + CloseMetricsDevice(m_metricsDevice); + m_metricsDevice = NULL; + } + + if(m_MDLibraryHandle) + FreeLibrary(m_MDLibraryHandle); +} + +void IntelCounters::Load() +{ + if(m_metricsDevice) + return; + + m_MDLibraryHandle = LoadDynamicLibrary(L"igdmd64.dll", NULL, 0); + if(!m_MDLibraryHandle) + return; + + OpenMetricsDevice = (OpenMetricsDevice_fn)GetProcAddress(m_MDLibraryHandle, "OpenMetricsDevice"); + if(!OpenMetricsDevice) + return; + + CloseMetricsDevice = + (CloseMetricsDevice_fn)GetProcAddress(m_MDLibraryHandle, "CloseMetricsDevice"); + if(!CloseMetricsDevice) + return; + + OpenMetricsDevice(&m_metricsDevice); +} + +bool IntelCounters::Init(void *pContext) +{ + if(!pContext) + return false; + + if(!m_metricsDevice) + return false; + + m_device = (ID3D11Device *)pContext; + m_device->GetImmediateContext(&m_deviceContext); + if(!m_deviceContext) + return false; + + TMetricsDeviceParams_1_2 *deviceParams = m_metricsDevice->GetParams(); + if(deviceParams->Version.MajorNumber < 1 || + (deviceParams->Version.MajorNumber == 1 && deviceParams->Version.MinorNumber < 1)) + { + CloseMetricsDevice(m_metricsDevice); + FreeLibrary(m_MDLibraryHandle); + m_metricsDevice = NULL; + m_MDLibraryHandle = (HMODULE)0; + return false; + } + + m_Counters = EnumerateCounters(); + + return true; +} + +CounterDescription IntelCounters::GetCounterDescription(GPUCounter counter) +{ + return m_Counters[GPUCounterToCounterIndex(counter)]; +} + +std::vector IntelCounters::EnumerateCounters() +{ + m_Counters.clear(); + m_allMetricSets.clear(); + std::set addedMetrics; + TMetricsDeviceParams_1_2 *deviceParams = m_metricsDevice->GetParams(); + for(unsigned int i = 0; i < deviceParams->ConcurrentGroupsCount; ++i) + { + IConcurrentGroup_1_1 *concurrentGroup = m_metricsDevice->GetConcurrentGroup(i); + TConcurrentGroupParams_1_0 *groupParams = concurrentGroup->GetParams(); + if(strcmp(groupParams->SymbolName, "OA") != 0) + continue; + + m_subscribedMetricsByCounterSet.resize(groupParams->MetricSetsCount); + + for(unsigned int j = 0; j < groupParams->MetricSetsCount; ++j) + { + IMetricSet_1_1 *metricSet = concurrentGroup->GetMetricSet(j); + metricSet->SetApiFiltering(API_TYPE_DX11); + m_allMetricSets.push_back(metricSet); + TMetricSetParams_1_0 *setParams = metricSet->GetParams(); + + if(std::find(metricSetBlacklist.begin(), metricSetBlacklist.end(), setParams->SymbolName) != + metricSetBlacklist.end()) + continue; + + for(unsigned int k = 0; k < setParams->MetricsCount; ++k) + { + IMetric_1_0 *metric = metricSet->GetMetric(k); + TMetricParams_1_0 *metricParams = metric->GetParams(); + + if((metricParams->UsageFlagsMask & EMetricUsageFlag::USAGE_FLAG_OVERVIEW) == 0) + continue; + + if(metricParams->ResultType == TMetricResultType::RESULT_BOOL) + continue; + + if(addedMetrics.count(metricParams->ShortName) > 0) + continue; + + CounterDescription counterDesc; + counterDesc.name = metricParams->ShortName; + counterDesc.description = metricParams->LongName; + counterDesc.category = metricParams->GroupName; + counterDesc.resultByteWidth = 8; + counterDesc.resultType = CompType::Double; + switch(metricParams->ResultType) + { + case RESULT_UINT32: + counterDesc.resultType = CompType::UInt; + counterDesc.resultByteWidth = sizeof(uint32_t); + break; + case RESULT_UINT64: + counterDesc.resultType = CompType::UInt; + counterDesc.resultByteWidth = sizeof(uint64_t); + break; + case RESULT_FLOAT: + counterDesc.resultType = CompType::Float; + counterDesc.resultByteWidth = sizeof(float); + break; + default: break; + } + + counterDesc.unit = CounterUnit::Absolute; + if(strcmp(metricParams->MetricResultUnits, "cycles") == 0) + counterDesc.unit = CounterUnit::Cycles; + else if(strcmp(metricParams->MetricResultUnits, "bytes") == 0) + counterDesc.unit = CounterUnit::Bytes; + else if(strcmp(metricParams->MetricResultUnits, "percent") == 0) + counterDesc.unit = CounterUnit::Percentage; + else if(strcmp(metricParams->MetricResultUnits, "ns") == 0) + { + counterDesc.unit = CounterUnit::Seconds; + counterDesc.resultType = CompType::Float; + counterDesc.resultByteWidth = sizeof(float); + } + + uint32_t counterId = (uint32_t)GPUCounter::FirstIntel + (uint32_t)m_Counters.size(); + counterDesc.counter = (GPUCounter)counterId; + m_Counters.push_back(counterDesc); + addedMetrics.insert(counterDesc.name); + m_metricLocation[(GPUCounter)counterId] = std::pair(j, k); + m_counterIds.push_back((GPUCounter)counterId); + } + } + } + + return m_Counters; +} + +uint32_t IntelCounters::GetPassCount() +{ + return (uint32_t)m_subscribedMetricSets.size(); +} + +uint32_t IntelCounters::BeginSession() +{ + if(!m_metricsDevice) + return 0; + + m_passIndex = 0; + TMetricsDeviceParams_1_2 *deviceParams = m_metricsDevice->GetParams(); + if(deviceParams->Version.MajorNumber < 1 || + (deviceParams->Version.MajorNumber == 1 && deviceParams->Version.MinorNumber < 2)) + return 0; + + IOverride_1_2 *frequencyOverride = m_metricsDevice->GetOverrideByName("FrequencyOverride"); + if(!frequencyOverride) + return 0; + + TTypedValue_1_0 *maxFreqSymbol = + m_metricsDevice->GetGlobalSymbolValueByName("GpuMaxFrequencyMHz"); + if(!maxFreqSymbol) + return 0; + + TSetFrequencyOverrideParams_1_2 params; + params.Enable = true; + params.FrequencyMhz = maxFreqSymbol->ValueUInt32; + params.Pid = 0; + frequencyOverride->SetOverride(¶ms, sizeof(params)); + Sleep(500); + + return 0; +} + +void IntelCounters::EndSession() +{ + if(!m_metricsDevice) + return; + + TMetricsDeviceParams_1_2 *deviceParams = m_metricsDevice->GetParams(); + if(deviceParams->Version.MajorNumber > 1 || + (deviceParams->Version.MajorNumber == 1 && deviceParams->Version.MinorNumber >= 2)) + { + IOverride_1_2 *frequencyOverride = m_metricsDevice->GetOverrideByName("FrequencyOverride"); + + if(frequencyOverride) + { + TSetFrequencyOverrideParams_1_2 params; + params.Enable = false; + params.Pid = 0; + frequencyOverride->SetOverride(¶ms, sizeof(params)); + } + } +} + +void IntelCounters::BeginPass() +{ + m_sampleIndex = 0; + TMetricSetParams_1_0 *metricSetParams = m_subscribedMetricSets[m_passIndex]->GetParams(); + m_queryResult.resize(metricSetParams->MetricsCount + metricSetParams->InformationCount); +} + +void IntelCounters::EndPass() +{ + m_passIndex++; +} + +void IntelCounters::EnableCounter(GPUCounter index) +{ + uint32_t metricSetIdx = m_metricLocation[index].first; + IMetricSet_1_1 *metricSet = m_allMetricSets[metricSetIdx]; + auto iter = std::find(m_subscribedMetricSets.begin(), m_subscribedMetricSets.end(), metricSet); + if(iter == m_subscribedMetricSets.end()) + { + m_subscribedMetricSets.push_back(metricSet); + metricSetIdx = (uint32_t)m_subscribedMetricSets.size() - 1; + } + else + { + metricSetIdx = (uint32_t)(iter - m_subscribedMetricSets.begin()); + } + m_subscribedMetricsByCounterSet[metricSetIdx].push_back(index); +} + +void IntelCounters::DisableAllCounters() +{ + m_subscribedMetricSets.clear(); + for(size_t i = 0; i < m_subscribedMetricsByCounterSet.size(); i++) + m_subscribedMetricsByCounterSet[i].clear(); +} + +void IntelCounters::BeginSample() +{ + if(!m_metricsDevice) + return; + + D3D11_COUNTER_DESC counter_desc; + counter_desc.MiscFlags = 0; + counter_desc.Counter = + (D3D11_COUNTER)m_subscribedMetricSets[m_passIndex]->GetParams()->ApiSpecificId.D3D1XDevDependentId; + + if(counter_desc.Counter == 0) + return; + + TCompletionCode res = m_subscribedMetricSets[m_passIndex]->Activate(); + if(res != TCompletionCode::CC_OK) + return; + + HRESULT hr = m_device->CreateCounter(&counter_desc, &m_counter); + if(FAILED(hr)) + { + m_subscribedMetricSets[m_passIndex]->Deactivate(); + return; + } + + res = m_subscribedMetricSets[m_passIndex]->Deactivate(); + if(res != TCompletionCode::CC_OK) + return; + + m_deviceContext->Begin(m_counter); +} + +void IntelCounters::EndSample() +{ + if(!m_metricsDevice) + return; + + m_deviceContext->End(m_counter); + HRESULT hr = S_OK; + uint32_t iteration = 0; + const uint32_t max_attempts = 0xFFFF; + void *counter_data = NULL; + + do + { + uint32_t flags = (iteration == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH; + hr = m_deviceContext->GetData(m_counter, &counter_data, m_counter->GetDataSize(), flags); + iteration++; + } while(hr != S_OK && iteration < max_attempts); + m_counter->Release(); + + if(hr != S_OK) + return; + + IMetricSet_1_1 *metricSet = m_subscribedMetricSets[m_passIndex]; + TMetricSetParams_1_0 *metricSetParams = metricSet->GetParams(); + + uint32_t calculatedReportCount = 0; + TCompletionCode res = m_subscribedMetricSets[m_passIndex]->CalculateMetrics( + (const unsigned char *)counter_data, metricSetParams->QueryReportSize, m_queryResult.data(), + (uint32_t)m_queryResult.size() * sizeof(TTypedValue_1_0), &calculatedReportCount, false); + + if(res != TCompletionCode::CC_OK) + return; + + for(size_t i = 0; i < m_subscribedMetricsByCounterSet[m_passIndex].size(); i++) + { + GPUCounter counterId = m_subscribedMetricsByCounterSet[m_passIndex][i]; + uint32_t counterIndex = m_metricLocation[counterId].second; + + m_results[std::pair(counterId, m_sampleIndex)] = + m_queryResult[counterIndex]; + } + m_sampleIndex++; +} + +std::vector IntelCounters::GetCounterData(const std::vector &eventIDs, + const std::vector &counters) +{ + std::vector ret; + for(uint32_t sample = 0; sample < (uint32_t)eventIDs.size(); sample++) + { + for(size_t counter = 0; counter < counters.size(); counter++) + { + const CounterDescription desc = GetCounterDescription(counters[counter]); + + switch(desc.resultType) + { + case CompType::UInt: + { + if(desc.resultByteWidth == sizeof(uint32_t)) + { + uint32_t value = + m_results[std::pair(desc.counter, sample)].ValueUInt32; + if(desc.unit == CounterUnit::Percentage) + { + value = RDCCLAMP(value, 0U, 100U); + } + + ret.push_back(CounterResult(eventIDs[sample], counters[counter], value)); + } + else if(desc.resultByteWidth == sizeof(uint64_t)) + { + uint64_t value = + m_results[std::pair(desc.counter, sample)].ValueUInt64; + + if(desc.unit == CounterUnit::Percentage) + { + value = RDCCLAMP(value, 0ULL, 100ULL); + } + + ret.push_back(CounterResult(eventIDs[sample], counters[counter], value)); + } + else + { + RDCERR("Unexpected byte width %u", desc.resultByteWidth); + } + } + break; + case CompType::Float: + { + float value = m_results[std::pair(desc.counter, sample)].ValueFloat; + if(desc.unit == CounterUnit::Seconds) + { + float nanoseconds = + (float)m_results[std::pair(desc.counter, sample)].ValueUInt64; + value = nanoseconds / 1e9f; + } + + if(fabs(value) < 1e-9) + { + value = 0.0f; + } + + if(desc.unit == CounterUnit::Percentage) + { + value = RDCCLAMP(value, 0.0f, 100.0f); + } + + ret.push_back(CounterResult(eventIDs[sample], counters[counter], value)); + } + break; + default: RDCASSERT(0); break; + }; + } + } + + return ret; +} diff --git a/renderdoc/driver/ihv/intel/intel_counters.h b/renderdoc/driver/ihv/intel/intel_counters.h new file mode 100644 index 000000000..b0af8f665 --- /dev/null +++ b/renderdoc/driver/ihv/intel/intel_counters.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* The MIT License (MIT) +* +* Copyright (c) 2018 Baldur Karlsson +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +******************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "api/replay/renderdoc_replay.h" +#include "official/metrics_discovery_api.h" + +using namespace MetricsDiscovery; + +inline constexpr GPUCounter MakeIntelCounter(int index) +{ + return GPUCounter((int)GPUCounter::FirstIntel + index); +} + +class IntelCounters +{ +public: + IntelCounters(); + + static void Load(); + + bool Init(void *pDevice); + ~IntelCounters(); + + std::vector GetPublicCounterIds() const { return m_counterIds; } + CounterDescription GetCounterDescription(GPUCounter index); + + void EnableCounter(GPUCounter index); + void DisableAllCounters(); + + uint32_t GetPassCount(); + + uint32_t BeginSession(); + void EndSession(); + + void BeginPass(); + void EndPass(); + + void BeginSample(); + void EndSample(); + + std::vector GetCounterData(const std::vector &eventIDs, + const std::vector &counters); + +private: + static uint32_t GPUCounterToCounterIndex(GPUCounter counter) + { + return (uint32_t)(counter) - (uint32_t)(GPUCounter::FirstIntel); + } + + std::vector EnumerateCounters(); + std::vector m_counterIds; + std::vector m_Counters; + std::vector m_allMetricSets; + std::vector m_subscribedMetricSets; + std::map> m_metricLocation; + std::vector> m_subscribedMetricsByCounterSet; + ID3D11Device *m_device; + ID3D11DeviceContext *m_deviceContext; + ID3D11Counter *m_counter; + std::vector m_queryResult; + uint32_t m_passIndex; + uint32_t m_sampleIndex; + std::map, TTypedValue_1_0> m_results; + + static HMODULE m_MDLibraryHandle; + static IMetricsDevice_1_5 *m_metricsDevice; + static OpenMetricsDevice_fn OpenMetricsDevice; + static CloseMetricsDevice_fn CloseMetricsDevice; +}; diff --git a/renderdoc/driver/ihv/intel/official/DriverStorePath.h b/renderdoc/driver/ihv/intel/official/DriverStorePath.h new file mode 100644 index 000000000..c603d9a77 --- /dev/null +++ b/renderdoc/driver/ihv/intel/official/DriverStorePath.h @@ -0,0 +1,333 @@ +/* +// Copyright (c) 2018 Intel Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +*/ +#pragma once + +#include +#include +#include +#include +#include + +#define DEBUG 0 + +#if DEBUG +#define DBG(std, fmt, ...) fprintf_s(stderr, fmt, __VA_ARGS__) +#else +#define DBG(std, fmt, ...) +#endif + +/********************************************************************************************/ +/* GetPropertyFromDevice */ +/* */ +/* This function can be used to request a value of any device property. */ +/* There are many types of properties values. Refer to devpkey.h for more details. */ +/* Function SetupDiGetDeviceProperty() inside GetPropertyFromDevice() fills a property value*/ +/* in a correct format, but always returns the value as a pointer to a string of bytes. */ +/* The string of bytes must be casted outside of the function GetPropertyFromDevice() */ +/* to get a value in a format suitable for the given type of property. */ +/* */ +/********************************************************************************************/ +static bool GetPropertyFromDevice( + void* pDevInfo, + PSP_DEVINFO_DATA pDevInfoData, + const DEVPROPKEY* pPropertyKey, + unsigned char** ppStringOut, + unsigned long* pStringOutSize) +{ + unsigned long propertyType = 0; + unsigned long propertySize = 0; + + // request a size, in bytes, required for a buffer in which property value will be stored + // SetupDiGetDeviceProperty() returns false and ERROR_INSUFFICIENT_BUFFER for the call + if (SetupDiGetDevicePropertyW(pDevInfo, pDevInfoData, pPropertyKey, &propertyType, NULL, 0, &propertySize, 0)) + { + DBG(stderr, "%s [%d] ---> SetupDiGetDeviceProperty() failed with the error code 0x%02x\n", __FUNCTION__, __LINE__, GetLastError()); + return false; + } + + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + DBG(stderr, "%s [%d] ---> SetupDiGetDeviceProperty() failed with the error code 0x%02x\n", __FUNCTION__, __LINE__, GetLastError()); + return false; + } + + if (ppStringOut == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + DBG(stderr, "%s [%d] ---> Error: input parameter ppStringOut = NULL\n", __FUNCTION__, __LINE__); + return false; + } + + // allocate memory for the buffer + *ppStringOut = new (std::nothrow) unsigned char[propertySize]; + if (*ppStringOut == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + DBG(stderr, "%s [%d] ---> Error: *ppStringOut = NULL\n", __FUNCTION__, __LINE__); + return false; + } + + // fill in the buffer with property value + if (!SetupDiGetDevicePropertyW(pDevInfo, pDevInfoData, pPropertyKey, &propertyType, *ppStringOut, propertySize, NULL, 0)) + { + DBG(stderr, "%s [%d] ---> SetupDiGetDeviceProperty() failed with the error code 0x%02x\n", __FUNCTION__, __LINE__, GetLastError()); + delete[] *ppStringOut; + *ppStringOut = NULL; + return false; + } + + if (pStringOutSize) + { + *pStringOutSize = propertySize; + } + + return true; +} + +/************************************************************************/ +/* GetIntelDriverStoreFullPath */ +/************************************************************************/ +static bool GetIntelDriverStoreFullPath( + wchar_t* pDriverStorePath, + unsigned long driverStorePathSizeInCharacters, + unsigned long* pDriverStorePathLengthInCharacters) +{ + bool result = false; + // allocated memory must be freed with delete operation + unsigned char* pPropertyInfName = NULL; + // allocated memory must be freed with delete operation + unsigned char* pPropertyDevServiceName = NULL; + + // guid defined for display adapters + const GUID guid = GUID_DISPLAY_DEVICE_ARRIVAL; + + // create device information set containing display adapters which support interfaces and are currently present in the system + void* pDevInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + if (pDevInfo == INVALID_HANDLE_VALUE) + { + DBG(stderr, "%s [%d] ---> SetupDiGetClassDevs() failed with the error code 0x%02x, pDevInfo = INVALID_HANDLE_VALUE\n", __FUNCTION__, __LINE__, GetLastError()); + goto END; + } + + unsigned long deviceIndex = 0; + SP_DEVINFO_DATA devInfoData; + ZeroMemory(&devInfoData, sizeof(SP_DEVINFO_DATA)); + unsigned long interfaceIndex = 0; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA)); + DEVPROPKEY devPropKey; + ZeroMemory(&devPropKey, sizeof(DEVPROPKEY)); + unsigned long driverStorePathLengthInCharacters = 0; + + // enumerate display adapters + while (true) + { + ZeroMemory(&devInfoData, sizeof(SP_DEVINFO_DATA)); + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + if (!SetupDiEnumDeviceInfo(pDevInfo, deviceIndex, &devInfoData)) + { + if (GetLastError() != ERROR_NO_MORE_ITEMS) + { + DBG(stderr, "%s [%d] ---> SetupDiEnumDeviceInfo() failed with the error code 0x%02x\n", __FUNCTION__, __LINE__, GetLastError()); + } + + deviceIndex = 0; + goto END; + } + + // enumerate interfaces of display adapters + while (true) + { + ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA)); + deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + if (!SetupDiEnumDeviceInterfaces(pDevInfo, &devInfoData, &guid, interfaceIndex, &deviceInterfaceData)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + { + interfaceIndex = 0; + break; + } + else + { + DBG(stderr, "%s [%d] ---> SetupDiEnumDeviceInterfaces() failed with the error code 0x%02x\n", __FUNCTION__, __LINE__, GetLastError()); + interfaceIndex = 0; + goto END; + } + } + + // get an inf file name for a display adapter + if (GetPropertyFromDevice(pDevInfo, &devInfoData, &DEVPKEY_Device_DriverInfPath, &pPropertyInfName, NULL) == false) + { + DBG(stderr, "%s [%d] ---> GetPropertyFromDevice() failed with the error code 0x%02x\n", __FUNCTION__, __LINE__, GetLastError()); + goto END; + } + + // to read DEVPKEY_Device_DriverInfPath property value correctly just cast unsigned char* (means PBYTE) to const wchar_t* + const wchar_t* pInfName = reinterpret_cast(pPropertyInfName); + DBG(stdout, "\n"); + DBG(stdout, "pPropertyInfName = %ws\n", pInfName); + wchar_t driverStorePath[MAX_PATH]; + ZeroMemory(driverStorePath, sizeof(driverStorePath)); + + // get a fully qualified name of an inf file (directory path and file name) + if (!SetupGetInfDriverStoreLocationW(pInfName, NULL, NULL, driverStorePath, ARRAYSIZE(driverStorePath), NULL)) + { + DBG(stderr, "%s [%d] ---> SetupGetInfDriverStoreLocation() failed with the error code 0x%02x\n", __FUNCTION__, __LINE__, GetLastError()); + goto END; + } + + // remove backslash and file name from the fully qualified name + PathRemoveFileSpecW(driverStorePath); + DBG(stdout, "driverStorePath = %ws\n", driverStorePath); + driverStorePathLengthInCharacters = (unsigned long)wcsnlen_s(driverStorePath, ARRAYSIZE(driverStorePath)); + DBG(stdout, "driverStorePathLengthInCharacters = %d\n", driverStorePathLengthInCharacters); + + // get service name for a display adapter + if (GetPropertyFromDevice(pDevInfo, &devInfoData, &DEVPKEY_Device_Service, &pPropertyDevServiceName, NULL) == false) + { + DBG(stderr, "%s [%d] ---> GetPropertyFromDevice() failed with the error code 0x%02x\n", __FUNCTION__, __LINE__, GetLastError()); + goto END; + } + + // to read DEVPKEY_Device_Service property value correctly just cast unsigned char* (means PBYTE) to const wchar_t* + const wchar_t* pDevServiceName = reinterpret_cast(pPropertyDevServiceName); + DBG(stdout, "pDevServiceName = %ws\n", pDevServiceName); + + // check if a given display adapter is from Intel based on driver device service name "igfx" + // check if pDevServiceName contains "igfx" name + if (wcsstr(pDevServiceName, L"igfx")) + { + // display adapter is from Intel + DBG(stdout, "this display adapter is from Intel\n"); + + if (pDriverStorePath == NULL) + { + DBG(stderr, "%s [%d] ---> Error: input parameter pDriverStorePath = NULL\n", __FUNCTION__, __LINE__); + goto END; + } + + if (driverStorePathSizeInCharacters < driverStorePathLengthInCharacters + 1) + { + DBG(stderr, "%s [%d] ---> Error: input parameter driverStorePathSizeInCharacters = %d is too small, the required size is %d\n", __FUNCTION__, __LINE__, driverStorePathSizeInCharacters, driverStorePathLengthInCharacters + 1); + goto END; + } + + wcscpy_s(pDriverStorePath, driverStorePathSizeInCharacters, driverStorePath); + + if (pDriverStorePathLengthInCharacters) + { + *pDriverStorePathLengthInCharacters = driverStorePathLengthInCharacters; + } + + result = (driverStorePathLengthInCharacters > 0) ? true : false; + if (result == false) + { + SetLastError(ERROR_BAD_LENGTH); + DBG(stderr, "%s [%d] ---> Error: driverStorePathLengthInCharacters = 0, result = false\n", __FUNCTION__, __LINE__); + } + goto END; + } + else + { + // display adapter is from other vendor + DBG(stdout, "this display adapter is NOT from Intel\n"); + + if (pPropertyDevServiceName) + { + delete[] pPropertyDevServiceName; + pPropertyDevServiceName = NULL; + } + + if (pPropertyInfName) + { + delete[] pPropertyInfName; + pPropertyInfName = NULL; + } + } + + ++interfaceIndex; + } + + ++deviceIndex; + } + +END: + DBG(stdout, "\n"); + + if (pPropertyDevServiceName) + { + delete[] pPropertyDevServiceName; + pPropertyDevServiceName = NULL; + } + + if (pPropertyInfName) + { + delete[] pPropertyInfName; + pPropertyInfName = NULL; + } + + if (pDevInfo) + { + SetupDiDestroyDeviceInfoList(pDevInfo); + pDevInfo = NULL; + } + + return result; +} + +/************************************************************************/ +/* LoadDynamicLibrary */ +/************************************************************************/ +static HMODULE LoadDynamicLibrary(const wchar_t* pFileName, HANDLE hFile = NULL, unsigned long flags = 0) +{ + HMODULE hModule = NULL; + unsigned long driverStorePathLengthInCharacters = 0; + // contains fully qualified name of DriverStore (directory path only without backslash at the end) for Intel display driver + // for example: C:\Windows\System32\DriverStore\FileRepository\igdlh64.inf_amd64_1d1d318ad2d391db + wchar_t driverStorePath[MAX_PATH] = { 0 }; + + // find fully qualified name of DriverStore for Intel graphics driver + if (GetIntelDriverStoreFullPath(driverStorePath, ARRAYSIZE(driverStorePath), &driverStorePathLengthInCharacters) == true) + { + std::wstring driverStoreFullPath(driverStorePath); + + if (driverStorePathLengthInCharacters) + { + driverStoreFullPath += L"\\"; + driverStoreFullPath += pFileName; + } + + DBG(stdout, "full path: %ws\n\n", driverStoreFullPath.c_str()); + + // load dll from DriverStore full path + hModule = LoadLibraryExW(driverStoreFullPath.c_str(), NULL, 0); + } + else + { + DBG(stderr, "%s [%d] ---> GetIntelDriverStoreFullPath() failed\n", __FUNCTION__, __LINE__); + hModule = NULL; + } + + return hModule; +} \ No newline at end of file diff --git a/renderdoc/driver/ihv/intel/official/metrics_discovery_api.h b/renderdoc/driver/ihv/intel/official/metrics_discovery_api.h new file mode 100644 index 000000000..c5edc2d01 --- /dev/null +++ b/renderdoc/driver/ihv/intel/official/metrics_discovery_api.h @@ -0,0 +1,1168 @@ +/*****************************************************************************\ + + Copyright © 2018, Intel Corporation + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + + File Name: metrics_discovery_api.h + + Abstract: Interface for metrics discovery DLL + + Notes: + +\*****************************************************************************/ +#include + +#ifndef __METRICS_DISCOVERY_H_ +#define __METRICS_DISCOVERY_H_ + +#ifdef _MSC_VER + #define MD_STDCALL __stdcall +#else + #define MD_STDCALL +#endif // _MSC_VER + +namespace MetricsDiscovery +{ +//*****************************************************************************/ +// API major version number: +//*****************************************************************************/ + typedef enum EMD_API_MAJOR_VERSION + { + MD_API_MAJOR_NUMBER_1 = 1, + MD_API_MAJOR_NUMBER_CURRENT = MD_API_MAJOR_NUMBER_1, + MD_API_MAJOR_NUMBER_CEIL = 0xFFFFFFFF + + } MD_API_MAJOR_VERSION; + +//*****************************************************************************/ +// API minor version number: +//*****************************************************************************/ + typedef enum EMD_API_MINOR_VERSION + { + MD_API_MINOR_NUMBER_0 = 0, + MD_API_MINOR_NUMBER_1 = 1, // CalculationAPI + MD_API_MINOR_NUMBER_2 = 2, // OverridesAPI + MD_API_MINOR_NUMBER_3 = 3, // BatchBuffer Sampling (aka DMA Sampling) + MD_API_MINOR_NUMBER_4 = 4, // GT dependent MetricSets + MD_API_MINOR_NUMBER_5 = 5, // MaxValue calculation for CalculationAPI + MD_API_MINOR_NUMBER_CURRENT = MD_API_MINOR_NUMBER_5, + MD_API_MINOR_NUMBER_CEIL = 0xFFFFFFFF + + } MD_API_MINOR_VERSION; + +//*****************************************************************************/ +// API build number: +//*****************************************************************************/ + #define MD_API_BUILD_NUMBER_CURRENT 94 + +//*****************************************************************************/ +// Completion codes: +//*****************************************************************************/ + typedef enum ECompletionCode + { + CC_OK = 0, + CC_READ_PENDING = 1, + CC_ALREADY_INITIALIZED = 2, + CC_STILL_INITIALIZED = 3, + CC_CONCURRENT_GROUP_LOCKED = 4, + CC_WAIT_TIMEOUT = 5, + CC_TRY_AGAIN = 6, + CC_INTERRUPTED = 7, + // ... + CC_ERROR_INVALID_PARAMETER = 40, + CC_ERROR_NO_MEMORY = 41, + CC_ERROR_GENERAL = 42, + CC_ERROR_FILE_NOT_FOUND = 43, + CC_ERROR_NOT_SUPPORTED = 44, + // ... + CC_LAST_1_0 = 45 + + } TCompletionCode; + + +/* Forward declarations */ + +//*******************************************************************************/ +// Abstract interface for the GPU metrics root object. +//*******************************************************************************/ + class IMetricsDevice_1_0; + class IMetricsDevice_1_1; + class IMetricsDevice_1_2; + class IMetricsDevice_1_5; + +//*******************************************************************************/ +// Abstract interface for Metrics Device overrides. +//*******************************************************************************/ + class IOverride_1_2; + +//*******************************************************************************/ +// Abstract interface for the metrics groups that can be collected concurrently +// to another group. +//*******************************************************************************/ + class IConcurrentGroup_1_0; + class IConcurrentGroup_1_1; + class IConcurrentGroup_1_5; + +//*******************************************************************************/ +// Abstract interface for the metric sets mapping to different HW configuration +// that should be used exclusively to each other metric set in the concurrent +// group. +//*******************************************************************************/ + class IMetricSet_1_0; + class IMetricSet_1_1; + class IMetricSet_1_4; + class IMetricSet_1_5; + +//*******************************************************************************/ +// Abstract interface for the metric that is sampled. +//*******************************************************************************/ + class IMetric_1_0; + +//*******************************************************************************/ +// Abstract interface for the measurement information (report reason, etc.). +//*******************************************************************************/ + class IInformation_1_0; + +//*******************************************************************************/ +// Abstract interface for the metric read and normalization equation. +//*******************************************************************************/ + class IEquation_1_0; + + +//*******************************************************************************/ +// Value types: +//*******************************************************************************/ + typedef enum EValueType + { + VALUE_TYPE_UINT32, + VALUE_TYPE_UINT64, + VALUE_TYPE_FLOAT, + VALUE_TYPE_BOOL, + VALUE_TYPE_CSTRING, + // ... + VALUE_TYPE_LAST, + + } TValueType; + +//*******************************************************************************/ +// Typed value: +//*******************************************************************************/ + typedef struct STypedValue_1_0 + { + TValueType ValueType; + union { + uint32_t ValueUInt32; + uint64_t ValueUInt64; + struct + { + uint32_t Low; + uint32_t High; + } ValueUInt64Fields; + float ValueFloat; + bool ValueBool; + char* ValueCString; + }; + + } TTypedValue_1_0; + +//*******************************************************************************/ +// Global symbol: +// Global symbols will be available to describe SKU specific information. +// Example global symbols: +// "EuCoresTotalCount", "EuThreadsCount", "EuSlicesTotalCount", "EuSubslicesTotalCount", +// "SamplersTotalCount", "PciDeviceId", "NumberOfShadingUnits", "GpuTimestampFrequency", +// "MaxTimestamp", "GpuMinFrequencyMHz", "GpuMaxFrequencyMHz" +//*******************************************************************************/ + typedef struct SGlobalSymbol_1_0 + { + const char* SymbolName; + TTypedValue_1_0 SymbolTypedValue; + + } TGlobalSymbol_1_0; + +//*******************************************************************************/ +// Global parameters of Metrics Device: +//*******************************************************************************/ + typedef struct SMetricsDeviceParams_1_0 + { + // API version + struct SApiVersion + { + uint32_t MajorNumber; + uint32_t MinorNumber; + uint32_t BuildNumber; + } Version; + + uint32_t ConcurrentGroupsCount; + + uint32_t GlobalSymbolsCount; + uint32_t DeltaFunctionsCount; + uint32_t EquationElementTypesCount; + uint32_t EquationOperationsCount; + + const char* DeviceName; + + } TMetricsDeviceParams_1_0; + +//*******************************************************************************/ +// Global parameters of Metrics Device 1.2: +//*******************************************************************************/ + typedef struct SMetricsDeviceParams_1_2 : public SMetricsDeviceParams_1_0 + { + uint32_t OverrideCount; + + } TMetricsDeviceParams_1_2; + +//*******************************************************************************/ +// Metric API types: +//*******************************************************************************/ + typedef enum EMetricApiType + { + API_TYPE_IOSTREAM = 0x00000001, // API independent method + API_TYPE_DX9 = 0x00000002, + API_TYPE_DX10 = 0x00000004, + API_TYPE_DX11 = 0x00000008, + API_TYPE_OGL = 0x00000010, + API_TYPE_OGL4_X = 0x00000020, + API_TYPE_OCL = 0x00000040, + API_TYPE_MEDIA = 0x00000080, // Only option would be using DmaBuffer sampling + API_TYPE_DX12 = 0x00000100, + API_TYPE_BBSTREAM = 0x00000200, + API_TYPE_VULKAN = 0x00000400, + API_TYPE_RESERVED = 0x00000800, + API_TYPE_ALL = 0xffffffff + + } TMetricApiType; + +//*******************************************************************************/ +// Measurement types: +//*******************************************************************************/ + typedef enum EMeasurementType + { + MEASUREMENT_TYPE_SNAPSHOT_IO = 0x00000001, + MEASUREMENT_TYPE_SNAPSHOT_QUERY = 0x00000002, + MEASUREMENT_TYPE_DELTA_QUERY = 0x00000004, + MEASUREMENT_TYPE_ALL = 0x0000ffff, + + } TMeasurementType; + +//*******************************************************************************/ +// Usage flags: +//*******************************************************************************/ + typedef enum EMetricUsageFlag + { + USAGE_FLAG_OVERVIEW = 0x00000001, // GPU system overview metric + // Useful for high level workload characterization + USAGE_FLAG_INDICATE = 0x00000002, // Metric indicating a performance problem + // Useful when comparing with threshold + USAGE_FLAG_CORRELATE = 0x00000004, // Metric correlating with performance problem + // Useful for proving to false only + //... + USAGE_FLAG_SYSTEM = 0x00000020, // Metric useful at system level + USAGE_FLAG_FRAME = 0x00000040, // Metric useful at frame level + USAGE_FLAG_BATCH = 0x00000080, // Metric useful at batch level + USAGE_FLAG_DRAW = 0x00000100, // Metric useful at draw level + + // ... + USAGE_FLAG_TIER_1 = 0x00000400, + USAGE_FLAG_TIER_2 = 0x00000800, + USAGE_FLAG_TIER_3 = 0x00001000, + USAGE_FLAG_TIER_4 = 0x00002000, + USAGE_FLAG_GLASS_JAW = 0x00004000, + + USAGE_FLAG_ALL = 0x0000ffff, + + } TMetricUsageFlag; + +//*******************************************************************************/ +// Sampling types: +//*******************************************************************************/ + typedef enum ESamplingType + { + SAMPLING_TYPE_OA_TIMER = 0x00000001, + SAMPLING_TYPE_OA_EVENT = 0x00000002, + SAMPLING_TYPE_GPU_QUERY = 0x00000004, + SAMPLING_TYPE_DMA_BUFFER = 0x00000008,// Possible future extension for media + SAMPLING_TYPE_ALL = 0x0000ffff, + + } TSamplingType; + +//*******************************************************************************/ +// Metric categories: +//*******************************************************************************/ + typedef enum EMetricCategory + { + GPU_RENDER = 0x0001, + GPU_COMPUTE = 0x0002, + GPU_MEDIA = 0x0004, + GPU_GENERIC = 0x0008, // Does not belong to any specific category like memory traffic + + } TMetricCategory; + +//*******************************************************************************/ +// IoStream read flags: +//*******************************************************************************/ + typedef enum EIoReadFlag + { + IO_READ_FLAG_DROP_OLD_REPORTS = 0x00000001, + IO_READ_FLAG_GET_CONTEXT_ID_TAGS = 0x00000002, + + } TIoReadFlag; + +//*******************************************************************************/ +// Override modes: +//*******************************************************************************/ + typedef enum EOverrideMode + { + OVERRIDE_MODE_GLOBAL = 0x0001, + OVERRIDE_MODE_LOCAL = 0x0002, + + } TOverrideMode; + +//*******************************************************************************/ +// Global parameters of Concurrent Group: +//*******************************************************************************/ + typedef struct SConcurrentGroupParams_1_0 + { + const char* SymbolName; // For example "PerfMon" or "OA" or "PipeStats" + const char* Description; // For example "PerfMon and ODLAT Uncore ring counters" + + uint32_t MeasurementTypeMask; + + uint32_t MetricSetsCount; + uint32_t IoMeasurementInformationCount; + uint32_t IoGpuContextInformationCount; + + } TConcurrentGroupParams_1_0; + +//*******************************************************************************/ +// Global parameters of an Override: +//*******************************************************************************/ + typedef struct SOverrideParams_1_2 + { + const char* SymbolName; // For example "FrequencyOverride" + const char* Description; // For example "Overrides device GPU frequency with a static value." + + uint32_t ApiMask; + uint32_t PlatformMask; + + uint32_t OverrideModeMask; + + } TOverrideParams_1_2; + +//*******************************************************************************/ +// Base params of SetOverride method: +//*******************************************************************************/ + typedef struct SSetOverrideParams_1_2 + { + bool Enable; + + } TSetOverrideParams_1_2; + +//*******************************************************************************/ +// Frequency override specific SetOverride params: +//*******************************************************************************/ + typedef struct SSetFrequencyOverrideParams_1_2 : SSetOverrideParams_1_2 + { + uint32_t FrequencyMhz; + uint32_t Pid; + + } TSetFrequencyOverrideParams_1_2; + + +//*******************************************************************************/ +// Query override specific SetOverride params: +//*******************************************************************************/ + typedef struct SSetQueryOverrideParams_1_2 : SSetOverrideParams_1_2 + { + uint32_t Period; // Nanoseconds + + } TSetQueryOverrideParams_1_2; + +//*******************************************************************************/ +// Driver override params: +//*******************************************************************************/ + typedef struct SSetDriverOverrideParams_1_2 : SSetOverrideParams_1_2 + { + uint32_t Value; + + } SSetDriverOverrideParams_1_2; + +//*******************************************************************************/ +// API specific id: +//*******************************************************************************/ + typedef struct SApiSpecificId_1_0 + { + uint32_t D3D9QueryId; // D3D9 Query ID + uint32_t D3D9Fourcc; // D3D9 FourCC + uint32_t D3D1XQueryId; // D3D1X Query ID + uint32_t D3D1XDevDependentId; // D3D1X device dependent counter ID + const char* D3D1XDevDependentName; // Device dependent counter name + uint32_t OGLQueryIntelId; // Intel OGL query extension ID + const char* OGLQueryIntelName; // Intel OGL query extension name + uint32_t OGLQueryARBTargetId; // ARB OGL Query Target ID + uint32_t OCL; // OCL configuration ID + uint32_t HwConfigId; // Config ID for IO stream + uint32_t placeholder[1]; + + } TApiSpecificId_1_0; + +//*******************************************************************************/ +// Global parameters of Metric set: +//*******************************************************************************/ + typedef struct SMetricSetParams_1_0 + { + const char* SymbolName; // For example "Dx11Tessellation" + const char* ShortName; // For example "DX11 Tessellation Metrics Set" + + uint32_t ApiMask; + uint32_t CategoryMask; + + uint32_t RawReportSize; // As in HW + uint32_t QueryReportSize; // As in Query API + + uint32_t MetricsCount; + uint32_t InformationCount; + uint32_t ComplementarySetsCount; + + TApiSpecificId_1_0 ApiSpecificId; + + uint32_t PlatformMask; + //... + + } TMetricSetParams_1_0; + +//*******************************************************************************/ +// GT differenced MetricSet params: +//*******************************************************************************/ + typedef struct SMetricSetParams_1_4 : SMetricSetParams_1_0 + { + uint32_t GtMask; + + } TMetricSetParams_1_4; + +//*******************************************************************************/ +// Metric result types: +//*******************************************************************************/ + typedef enum EMetricResultType + { + RESULT_UINT32, + RESULT_UINT64, + RESULT_BOOL, + RESULT_FLOAT, + // ... + RESULT_LAST + + } TMetricResultType; + +//*******************************************************************************/ +// Metric types: +//*******************************************************************************/ + typedef enum EMetricType + { + METRIC_TYPE_DURATION, + METRIC_TYPE_EVENT, + METRIC_TYPE_EVENT_WITH_RANGE, + METRIC_TYPE_THROUGHPUT, + METRIC_TYPE_TIMESTAMP, + METRIC_TYPE_FLAG, + METRIC_TYPE_RATIO, + METRIC_TYPE_RAW, + // ... + METRIC_TYPE_LAST + + } TMetricType; + +//*******************************************************************************/ +// Information types: +//*******************************************************************************/ + typedef enum EInformationType + { + INFORMATION_TYPE_REPORT_REASON, + INFORMATION_TYPE_VALUE, + INFORMATION_TYPE_FLAG, + INFORMATION_TYPE_TIMESTAMP, + INFORMATION_TYPE_CONTEXT_ID_TAG, + INFORMATION_TYPE_SAMPLE_PHASE, + INFORMATION_TYPE_GPU_NODE, + // ... + INFORMATION_TYPE_LAST + + } TInformationType; + +//*******************************************************************************/ +// Report reasons: +//*******************************************************************************/ + typedef enum EReportReason + { + REPORT_REASON_UNDEFINED = 0x0000, + REPORT_REASON_INTERNAL_TIMER = 0x0001, + REPORT_REASON_INTERNAL_TRIGGER1 = 0x0002, + REPORT_REASON_INTERNAL_TRIGGER2 = 0x0004, + REPORT_REASON_INTERNAL_CONTEXT_SWITCH = 0x0008, + REPORT_REASON_INTERNAL_GO = 0x0010, + REPORT_REASON_INTERNAL_FREQUENCY_CHANGE = 0x0020, + REPORT_REASON_QUERY_DEFAULT = 0x0100, + REPORT_REASON_QUERY_INTERNAL_RESOLVE = 0x0200, + REPORT_REASON_QUERY_INTERNAL_CLEAR = 0x0400, + + } TReportReason; + +//*******************************************************************************/ +// Sample phase: +//*******************************************************************************/ + typedef enum ESamplePhase + { + SAMPLE_PHASE_END, + SAMPLE_PHASE_BEGIN, + // ... + SAMPLE_PHASE_LAST + + } TSamplePhase; + +//*******************************************************************************/ +// Gpu Node: +//*******************************************************************************/ + typedef enum EInformationGpuNode + { + INFORMATION_GPUNODE_3D = 0, // Available by default on all platform + INFORMATION_GPUNODE_VIDEO = 1, // Available on CTG+ + INFORMATION_GPUNODE_BLT = 2, // Available on GT + INFORMATION_GPUNODE_VE = 3, // Available on HSW+ (VideoEnhancement) + INFORMATION_GPUNODE_VCS2 = 4, // Available on BDW+ GT3+ + INFORMATION_GPUNODE_REAL_MAX = 5, // All nodes beyond this are virtual nodes - they don't have an actual GPU engine + // ... + INFORMATION_GPUNODE_LAST + + } TInformationGpuNode; + +//*******************************************************************************/ +// Hardware unit types: +//*******************************************************************************/ + typedef enum EHwUnitType + { + HW_UNIT_GPU, + HW_UNIT_SLICE, + HW_UNIT_SUBSLICE, + HW_UNIT_SUBSLICE_BANK, + HW_UNIT_EU_UNIT, + HW_UNIT_UNCORE, + // ... + HW_UNIT_LAST + + } THwUnitType; + +//*******************************************************************************/ +// Delta function types: +//*******************************************************************************/ + typedef enum EDeltaFunctionType + { + DELTA_FUNCTION_NULL = 0, + DELTA_N_BITS, + DELTA_BOOL_OR, // Logic OR - good for exceptions + DELTA_BOOL_XOR, // Logic XOR - good to check if bits were changed + DELTA_GET_PREVIOUS, // Preserve previous value + DELTA_GET_LAST, // Preserve last value + DELTA_NS_TIME, // Delta for nanosecond timestamps (GPU timestamp wraps at 32 bits but was value multiplied by 80) + DELTA_FUNCTION_LAST_1_0 + + } TDeltaFunctionType; + +//*******************************************************************************/ +// Delta function: +//*******************************************************************************/ + typedef struct SDeltaFunction_1_0 + { + TDeltaFunctionType FunctionType; + union { + uint32_t BitsCount; // Used for DELTA_N_BITS to specify bits count + }; + + } TDeltaFunction_1_0; + +//*******************************************************************************/ +// Equation element types: +//*******************************************************************************/ + typedef enum EEquationElementType + { + EQUATION_ELEM_OPERATION, // See TEquationOperation enumeration + + EQUATION_ELEM_RD_BITFIELD, + EQUATION_ELEM_RD_UINT8, + EQUATION_ELEM_RD_UINT16, + EQUATION_ELEM_RD_UINT32, + EQUATION_ELEM_RD_UINT64, + EQUATION_ELEM_RD_FLOAT, + + // Extended RD operation + EQUATION_ELEM_RD_40BIT_CNTR, // Assemble 40 bit counter that is in two locations, result in unsigned integer 64b + + EQUATION_ELEM_IMM_UINT64, + EQUATION_ELEM_IMM_FLOAT, + EQUATION_ELEM_SELF_COUNTER_VALUE, // Defined by $Self token, the UINT64 result of DeltaFunction for IO or QueryReadEquation + EQUATION_ELEM_GLOBAL_SYMBOL, // Defined by $"SymbolName", available in MetricsDevice SymbolTable + EQUATION_ELEM_LOCAL_COUNTER_SYMBOL, // Defined by $"SymbolName", refers to counter delta value in the local set + EQUATION_ELEM_OTHER_SET_COUNTER_SYMBOL, // Defined by concatenated string of $"setSymbolName/SymbolName", refers to counter + // Delta value in the other set + + EQUATION_ELEM_LOCAL_METRIC_SYMBOL, // Defined by $$"SymbolName", refers to metric normalized value in the local set + EQUATION_ELEM_OTHER_SET_METRIC_SYMBOL, // Defined by concatenated string of $$"setSymbolName/SymbolName", refers to metric + // Normalized value in the other set + + EQUATION_ELEM_INFORMATION_SYMBOL, // Defined by i$"SymbolName", refers to information value type only + + // Extended types - standard normalization functions + EQUATION_ELEM_STD_NORM_GPU_DURATION, // Action is $Self $GpuCoreClocks FDIV 100 FMUL + EQUATION_ELEM_STD_NORM_EU_AGGR_DURATION, // Action is $Self $GpuCoreClocks $EuCoresTotalCount UMUL FDIV 100 FMUL + + EQUATION_ELEM_LAST_1_0 + + } TEquationElementType; + +//*******************************************************************************/ +// Equation operations: +//*******************************************************************************/ + typedef enum EEquationOperation + { + EQUATION_OPER_RSHIFT, // 64b unsigned integer right shift + EQUATION_OPER_LSHIFT, // 64b unsigned integer left shift + EQUATION_OPER_AND, // Bitwise AND of two unsigned integers, 64b each + EQUATION_OPER_OR, // Bitwise OR of two unsigned integers, 64b each + EQUATION_OPER_XOR, // Bitwise XOR of two unsigned integers, 64b each + EQUATION_OPER_XNOR, // Bitwise XNOR of two unsigned integers, 64b each + EQUATION_OPER_AND_L, // Logical AND (C-like "&&") of two unsigned integers, 64b each, result is true(1) if both values are true(greater than 0) + EQUATION_OPER_EQUALS, // Equality (C-like "==") of two unsigned integers, 64b each, result is true(1) or false(0) + EQUATION_OPER_UADD, // Unsigned integer add, arguments are casted to be 64b unsigned integers, result is unsigned integer 64b + EQUATION_OPER_USUB, // Unsigned integer subtract, arguments are casted to be 64b unsigned integers, result is unsigned integer 64b + EQUATION_OPER_UMUL, // Unsigned integer mul, arguments are casted to be 64b unsigned integers, result is unsigned integer 64b + EQUATION_OPER_UDIV, // Unsigned integer div, arguments are casted to be 64b unsigned integers, result is unsigned integer 64b + EQUATION_OPER_FADD, // Floating point add, arguments are casted to be 32b floating points, result is a 32b float + EQUATION_OPER_FSUB, // Floating point subtract, arguments are casted to be 32b floating points, result is a 32b float + EQUATION_OPER_FMUL, // Floating point multiply, arguments are casted to be 32b floating points, result is a 32b float + EQUATION_OPER_FDIV, // Floating point divide, arguments are casted to be 32b floating points, result is a 32b float + + EQUATION_OPER_UGT, // 64b unsigned integers comparison of is greater than, result is bool true(1) or false(0) + EQUATION_OPER_ULT, // 64b unsigned integers comparison of is less than, result is bool true(1) or false(0) + EQUATION_OPER_UGTE, // 64b unsigned integers comparison of is greater than or equal, result is bool true(1) or false(0) + EQUATION_OPER_ULTE, // 64b unsigned integers comparison of is less than or equal, result is bool true(1) or false(0) + + EQUATION_OPER_FGT, // 32b floating point numbers comparison of is greater than, result is bool true(1) or false(0) + EQUATION_OPER_FLT, // 32b floating point numbers comparison of is less than, result is bool true(1) or false(0) + EQUATION_OPER_FGTE, // 32b floating point numbers comparison of is greater than or equal, result is bool true(1) or false(0) + EQUATION_OPER_FLTE, // 32b floating point numbers comparison of is less than or equal, result is bool true(1) or false(0) + + EQUATION_OPER_UMIN, // Unsigned integer MIN function, arguments are casted to be 64b unsigned integers, result is unsigned integer 64b + EQUATION_OPER_UMAX, // Unsigned integer MAX function, arguments are casted to be 64b unsigned integers, result is unsigned integer 64b + + EQUATION_OPER_FMIN, // Floating point MIN function, arguments are casted to be 32b floating points, result is a 32b float + EQUATION_OPER_FMAX, // Floating point MAX function, arguments are casted to be 32b floating points, result is a 32b float + + EQUATION_OPER_LAST_1_0 + + } TEquationOperation; + +//*******************************************************************************/ +// Read params: +//*******************************************************************************/ + typedef struct SReadParams_1_0 + { + uint32_t ByteOffset; + uint32_t BitOffset; + uint32_t BitsCount; + uint32_t ByteOffsetExt; + + } TReadParams_1_0; + +//*******************************************************************************/ +// Equation element: +//*******************************************************************************/ + typedef struct SEquationElement_1_0 + { + TEquationElementType Type; + union + { + uint64_t ImmediateUInt64; + float ImmediateFloat; + TEquationOperation Operation; + TReadParams_1_0 ReadParams; + }; + char* SymbolName; + + } TEquationElement_1_0; + +/*****************************************************************************\ + +Class: + IEquation_1_0 + +Description: + Abstract interface for the equation object. + +\*****************************************************************************/ + class IEquation_1_0 + { + public: + virtual ~IEquation_1_0(); + + virtual uint32_t GetEquationElementsCount( void ); + virtual TEquationElement_1_0* GetEquationElement( uint32_t index ); + }; + +//*******************************************************************************/ +// Global parameters of Metric: +//*******************************************************************************/ + typedef struct SMetricParams_1_0 + { + uint32_t IdInSet; // Position in the set + uint32_t GroupId; // Specific metric group id + const char* SymbolName; // Symbol name, used in equations + const char* ShortName; // Consistent metric name, not changed platform to platform + const char* GroupName; // VertexShader for example + const char* LongName; // Hint about the metric shown to users + + const char* DxToOglAlias; // To replace DX pixels with OGL fragments + + uint32_t UsageFlagsMask; + uint32_t ApiMask; + + TMetricResultType ResultType; + const char* MetricResultUnits; + TMetricType MetricType; + + uint64_t LowWatermark; // Low watermark for hotspot indication (USAGE_FLAG_INDICATE only) + uint64_t HighWatermark; // High watermark for hotspot indication (USAGE_FLAG_INDICATE only) + + THwUnitType HwUnitType; + + // Read equation specification for IO stream (accessing raw values potentially spread in report in several locations) + IEquation_1_0* IoReadEquation; + // Read equation specification for query (accessing calculated delta values) + IEquation_1_0* QueryReadEquation; + + TDeltaFunction_1_0 DeltaFunction; + + // Normalization equation to get normalized value to bytes transfered or to a percentage of utilization + IEquation_1_0* NormEquation; + + // To calculate metrics max value as a function of other metrics and device parameters (e.g. 100 for percentage) + IEquation_1_0* MaxValueEquation; + + } TMetricParams_1_0; + +//*******************************************************************************/ +// Global parameters of Information: +//*******************************************************************************/ + typedef struct SInformationParams_1_0 + { + uint32_t IdInSet; // Position in the set + const char* SymbolName; // Symbol name, used in equations + const char* ShortName; // Consistent name, not changed platform to platform + const char* GroupName; // Some more global context of the information + const char* LongName; // Hint about the information shown to users + + uint32_t ApiMask; + + TInformationType InfoType; + const char* InfoUnits; + + // Read equation specification for IO stream (accessing raw values potentially spread in report in several locations) + IEquation_1_0* IoReadEquation; + // Read equation specification for query (accessing calculated delta values) + IEquation_1_0* QueryReadEquation; + + TDeltaFunction_1_0 OverflowFunction; + + } TInformationParams_1_0; + +/*****************************************************************************\ + +Class: + IInformation_1_0 + +Description: + Abstract interface for the measurement information parameter. + +\*****************************************************************************/ + class IInformation_1_0 + { + public: + virtual ~IInformation_1_0(); + + virtual TInformationParams_1_0* GetParams(); + }; + +/*****************************************************************************\ + +Class: + IMetric_1_0 + +Description: + Abstract interface for the metric that is sampled. + +\*****************************************************************************/ + class IMetric_1_0 + { + public: + virtual ~IMetric_1_0(); + + virtual TMetricParams_1_0* GetParams(); + }; + +/*****************************************************************************\ + +Class: + IMetricSet_1_0 + +Description: + Abstract interface for the metric sets mapping to different HW configuration that should be used + exclusively to each other metric set in the concurrent group. + +\*****************************************************************************/ + class IMetricSet_1_0 + { + public: + virtual ~IMetricSet_1_0(); + + virtual TMetricSetParams_1_0* GetParams( void ); + + // To get particular metric + virtual IMetric_1_0* GetMetric( uint32_t index ); + + // To get particular information about measurement + virtual IInformation_1_0* GetInformation( uint32_t index ); + + // Below proposal to address multi-passes at the set level + virtual IMetricSet_1_0* GetComplementaryMetricSet( uint32_t index ); + + // To enable this configuration before query instance is created + virtual TCompletionCode Activate( void ); + + // To disable this configuration after query instance is created + virtual TCompletionCode Deactivate( void ); + + // To add an additional custom metric to this set + virtual IMetric_1_0* AddCustomMetric( + const char* symbolName, const char* shortName, const char* groupName, const char* longName, const char* dxToOglAlias, + uint32_t usageFlagsMask, uint32_t apiMask, TMetricResultType resultType, const char* resultUnits, TMetricType metricType, + int64_t loWatermark, int64_t hiWatermark, THwUnitType hwType, const char* ioReadEquation, const char* deltaFunction, + const char* queryReadEquation, const char* normalizationEquation, const char* maxValueEquation, const char* signalName ); + }; + +/*****************************************************************************\ + +Class: + IMetricSet_1_1 + +Description: + Updated 1.0 version to use with 1.1 interface version. + Introduces an ability to calculate metrics from raw data. + + New: + - SetApiFiltering + - CalculateMetrics + - CalculateIoMeasurementInformation + +\*****************************************************************************/ + class IMetricSet_1_1 : public IMetricSet_1_0 + { + public: + virtual ~IMetricSet_1_1(); + + // To filter available metrics/information for the given API. Use TMetricApiType to build the mask. + virtual TCompletionCode SetApiFiltering( uint32_t apiMask ); + + // To calculate normalized metrics/information from the raw data. + virtual TCompletionCode CalculateMetrics( const unsigned char* rawData, uint32_t rawDataSize, TTypedValue_1_0* out, + uint32_t outSize, uint32_t* outReportCount, bool enableContextFiltering ); + + // To calculate additional information for stream measurements. + virtual TCompletionCode CalculateIoMeasurementInformation( TTypedValue_1_0* out, uint32_t outSize ); + }; + +/*****************************************************************************\ + +Class: + IMetricSet_1_4 + +Description: + Updated 1.1 version to use with 1.4 interface version. + Extends set params with gtType information. + + Updates: + - GetParams + +\*****************************************************************************/ + class IMetricSet_1_4 : public IMetricSet_1_1 + { + public: + virtual ~IMetricSet_1_4(); + + virtual TMetricSetParams_1_4* GetParams( void ); + }; + +/*****************************************************************************\ + +Class: + IMetricSet_1_5 + +Description: + Updated 1.4 version to use with 1.5 interface version. + Adds an ability to calculate MaxValueEquations (maximal value) for each metric. + Param 'enableContextFiltering' becomes deprecated. + + Updates: + - GetComplementaryMetricSet + - CalculateMetrics + +\*****************************************************************************/ + class IMetricSet_1_5 : public IMetricSet_1_4 + { + public: + // Update to 1.5 interface + virtual IMetricSet_1_5* GetComplementaryMetricSet( uint32_t index ); + + // CalculateMetrics extended with max values calculation. + // Optional param 'outMaxValues' should have a memory for at least 'MetricCount * RawReportCount' values, can be NULL. + virtual TCompletionCode CalculateMetrics( const unsigned char* rawData, uint32_t rawDataSize, TTypedValue_1_0* out, + uint32_t outSize, uint32_t* outReportCount, TTypedValue_1_0* outMaxValues, uint32_t outMaxValuesSize ); + }; + +/*****************************************************************************\ + +Class: + IConcurrentGroup_1_0 + +Description: + Abstract interface for the metrics groups that can be collected concurrently to another group. + +\*****************************************************************************/ + class IConcurrentGroup_1_0 + { + public: + virtual ~IConcurrentGroup_1_0(); + + virtual TConcurrentGroupParams_1_0* GetParams( void ); + virtual IMetricSet_1_0* GetMetricSet( uint32_t index ); + + virtual TCompletionCode OpenIoStream( IMetricSet_1_0* metricSet, uint32_t processId, uint32_t* nsTimerPeriod, uint32_t* oaBufferSize ); + virtual TCompletionCode ReadIoStream( uint32_t* reportsCount, char* reportData, uint32_t readFlags ); + virtual TCompletionCode CloseIoStream( void ); + virtual TCompletionCode WaitForReports( uint32_t milliseconds ); + virtual IInformation_1_0* GetIoMeasurementInformation( uint32_t index ); + virtual IInformation_1_0* GetIoGpuContextInformation( uint32_t index ); + }; + +/*****************************************************************************\ + +Class: + IConcurrentGroup_1_1 + +Description: + Updated 1.0 version to use with 1.1 interface version. + + Updates: + - GetMetricSet + +\*****************************************************************************/ + class IConcurrentGroup_1_1 : public IConcurrentGroup_1_0 + { + public: + // Update to 1.1 interface + virtual IMetricSet_1_1* GetMetricSet( uint32_t index ); + }; + +/*****************************************************************************\ + +Class: + IConcurrentGroup_1_3 + +Description: + Updated 1.1 version to use with 1.3 interface version. + Introduces setting Stream Sampling Type. + + New: + - SetIoStreamSamplingType + +\*****************************************************************************/ + class IConcurrentGroup_1_3 : public IConcurrentGroup_1_1 + { + public: + // To set sampling type during IoStream measurements + virtual TCompletionCode SetIoStreamSamplingType( TSamplingType type ); + }; + +/*****************************************************************************\ + +Class: + IConcurrentGroup_1_5 + +Description: + Updated 1.3 version to use with 1.5 interface version. + + Updates: + - GetMetricSet + +\*****************************************************************************/ + class IConcurrentGroup_1_5 : public IConcurrentGroup_1_3 + { + public: + // Update to 1.5 interface + virtual IMetricSet_1_5* GetMetricSet( uint32_t index ); + }; + +/*****************************************************************************\ + +Class: + IOverride_1_2 + +Description: + Abstract interface for Metrics Device overrides. + +\*****************************************************************************/ + class IOverride_1_2 + { + public: + virtual ~IOverride_1_2(); + + // To get this Override params + virtual TOverrideParams_1_2* GetParams( void ); + + // To enable/disable this Override + virtual TCompletionCode SetOverride( TSetOverrideParams_1_2* params, uint32_t paramsSize ); + }; + +/*****************************************************************************\ + +Class: + IMetricsDevice_1_0 + +Description: + Abstract interface for the GPU metrics root object. + +\*****************************************************************************/ + class IMetricsDevice_1_0 + { + public: + virtual ~IMetricsDevice_1_0(); + + // To get MetricsDevice params + virtual TMetricsDeviceParams_1_0* GetParams( void ); + + // Child objects are of IConcurrentGroup + virtual IConcurrentGroup_1_0* GetConcurrentGroup( uint32_t index ); + + // To get GlobalSymbol at the given index + virtual TGlobalSymbol_1_0* GetGlobalSymbol( uint32_t index ); + + // To get GlobalSymbol with the given name + virtual TTypedValue_1_0* GetGlobalSymbolValueByName( const char* name ); + + // To get last error from TCompletionCode enum + virtual TCompletionCode GetLastError( void ); + + // To get both GPU and CPU timestamp at the same time + virtual TCompletionCode GetGpuCpuTimestamps( uint64_t* gpuTimestampNs, uint64_t* cpuTimestampNs, + uint32_t* cpuId ); + }; + +/*****************************************************************************\ + +Class: + IMetricsDevice_1_1 + +Description: + Updated 1.0 version to use with 1.1 interface version. + + Updates: + - GetConcurrentGroup + +\*****************************************************************************/ + class IMetricsDevice_1_1 : public IMetricsDevice_1_0 + { + public: + // Update to 1.1 interface + virtual IConcurrentGroup_1_1* GetConcurrentGroup( uint32_t index ); + }; + +/*****************************************************************************\ + +Class: + IMetricsDevice_1_2 + +Description: + Updated 1.1 version to use with 1.2 interface version. + Introduces an interface for getting overrides. + + Updates: + - GetParams + New: + - GetOverride + - GetOverrideByName + +\*****************************************************************************/ + class IMetricsDevice_1_2 : public IMetricsDevice_1_1 + { + public: + // Update returned params + virtual TMetricsDeviceParams_1_2* GetParams( void ); + + // To get override at the given index + virtual IOverride_1_2* GetOverride( uint32_t index ); + + // To get override with the given name + virtual IOverride_1_2* GetOverrideByName( const char* symbolName ); + }; + +/*****************************************************************************\ + +Class: + IMetricsDevice_1_5 + +Description: + Updated 1.2 version to use with 1.5 interface version. + + Updates: + - GetConcurrentGroup + +\*****************************************************************************/ + class IMetricsDevice_1_5 : public IMetricsDevice_1_2 + { + public: + // Update to 1.5 interface + virtual IConcurrentGroup_1_5* GetConcurrentGroup( uint32_t index ); + }; + +#ifdef __cplusplus + extern "C" { +#endif + + // Factory functions + typedef TCompletionCode (MD_STDCALL *OpenMetricsDevice_fn)(IMetricsDevice_1_5** device); + typedef TCompletionCode (MD_STDCALL *OpenMetricsDeviceFromFile_fn)(const char* fileName, void* openParams, IMetricsDevice_1_5** device); + typedef TCompletionCode (MD_STDCALL *CloseMetricsDevice_fn)(IMetricsDevice_1_5* device); + typedef TCompletionCode (MD_STDCALL *SaveMetricsDeviceToFile_fn)(const char* fileName, void* saveParams, IMetricsDevice_1_5* device); + +#ifdef __cplusplus + } +#endif + +}; +#endif // __METRICS_DISCOVERY_H_ + diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index ede7962a9..e3727aae0 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -78,7 +78,7 @@ Windows - tdh.lib;ws2_32.lib;kernel32.lib;user32.lib;shlwapi.lib;%(AdditionalDependencies) + tdh.lib;ws2_32.lib;kernel32.lib;user32.lib;shlwapi.lib;setupapi.lib;%(AdditionalDependencies) $(ProjectDir)os\win32\comexport.def true tdh.dll @@ -585,6 +585,9 @@ {5de5a561-548a-4dd7-90f0-06a2b39eae9a} + + {7fcb5fc5-1dbd-4da6-83a0-6ba4e945bda5} + {40349ad9-5558-4df4-84e2-11934de90a11}