From b7f893b559de378cb99e53f84e55b0fbb24eb25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matth=C3=A4us=20G=2E=20Chajdas?= Date: Mon, 12 Jun 2017 16:06:10 +0200 Subject: [PATCH] Add backend support for AMD performance counters. --- docs/credits_acknowledgements.rst | 2 + renderdoc.sln | 14 + renderdoc/api/replay/replay_enums.h | 15 + renderdoc/driver/d3d11/d3d11_counters.cpp | 199 ++++++++- renderdoc/driver/d3d11/d3d11_debug.cpp | 14 + renderdoc/driver/d3d11/d3d11_debug.h | 8 + renderdoc/driver/d3d11/d3d11_hooks.cpp | 2 +- .../driver/d3d11/renderdoc_d3d11.vcxproj | 5 +- renderdoc/driver/ihv/amd/AMD.vcxproj | 104 +++++ renderdoc/driver/ihv/amd/AMD.vcxproj.filters | 27 ++ renderdoc/driver/ihv/amd/amd_counters.cpp | 419 ++++++++++++++++++ renderdoc/driver/ihv/amd/amd_counters.h | 85 ++++ .../amd => ihv/amd/official/DXExt}/AmdDxExt.h | 0 .../amd/official/DXExt}/AmdDxExtApi.h | 0 .../amd/official/DXExt}/AmdDxExtIface.h | 0 .../GPUPerfAPI/Include/GPACounterGenerator.h | 32 ++ .../GPUPerfAPI/Include/GPAFunctions.h | 81 ++++ .../GPUPerfAPI/Include/GPAICounterAccessor.h | 106 +++++ .../GPUPerfAPI/Include/GPAICounterScheduler.h | 102 +++++ .../GPUPerfAPI/Include/GPUPerfAPI-HSA.h | 46 ++ .../GPUPerfAPI/Include/GPUPerfAPI-Private.h | 49 ++ .../official/GPUPerfAPI/Include/GPUPerfAPI.h | 389 ++++++++++++++++ .../GPUPerfAPI/Include/GPUPerfAPICounters.h | 45 ++ .../Include/GPUPerfAPIFunctionTypes-Private.h | 33 ++ .../Include/GPUPerfAPIFunctionTypes.h | 76 ++++ .../Include/GPUPerfAPITypes-Private.h | 61 +++ .../GPUPerfAPI/Include/GPUPerfAPITypes.h | 177 ++++++++ .../ihv/amd/official/GPUPerfAPI/LICENSE | 19 + .../GPUPerfAPI/thirdpartylicenses.txt | 42 ++ .../ihv/amd/official/GPUPerfAPI/version.txt | 1 + 30 files changed, 2146 insertions(+), 7 deletions(-) create mode 100644 renderdoc/driver/ihv/amd/AMD.vcxproj create mode 100644 renderdoc/driver/ihv/amd/AMD.vcxproj.filters create mode 100644 renderdoc/driver/ihv/amd/amd_counters.cpp create mode 100644 renderdoc/driver/ihv/amd/amd_counters.h rename renderdoc/driver/{dx/official/amd => ihv/amd/official/DXExt}/AmdDxExt.h (100%) rename renderdoc/driver/{dx/official/amd => ihv/amd/official/DXExt}/AmdDxExtApi.h (100%) rename renderdoc/driver/{dx/official/amd => ihv/amd/official/DXExt}/AmdDxExtIface.h (100%) create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPACounterGenerator.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAFunctions.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAICounterAccessor.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAICounterScheduler.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-HSA.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-Private.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPICounters.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes-Private.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPITypes-Private.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPITypes.h create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/LICENSE create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/thirdpartylicenses.txt create mode 100644 renderdoc/driver/ihv/amd/official/GPUPerfAPI/version.txt diff --git a/docs/credits_acknowledgements.rst b/docs/credits_acknowledgements.rst index 7a35c36e1..7726665eb 100644 --- a/docs/credits_acknowledgements.rst +++ b/docs/credits_acknowledgements.rst @@ -84,6 +84,8 @@ The following libraries and components are incorporated into RenderDoc, listed h Used to display message boxes cross-platform from the non-UI core code. +* `AMD GPUPerfAPI `_ - Copyright (c) 2016 Advanced Micro Devices, Inc., distributed under the MIT license. + Thanks ------ diff --git a/renderdoc.sln b/renderdoc.sln index e00b0c8f7..c3792e463 100644 --- a/renderdoc.sln +++ b/renderdoc.sln @@ -17,6 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderdoc", "renderdoc\rend {F1E59A05-60D4-4927-9E57-DD191EAE90EF} = {F1E59A05-60D4-4927-9E57-DD191EAE90EF} {EC847717-119A-2391-0477-212E1140082C} = {EC847717-119A-2391-0477-212E1140082C} {B7399F39-300F-450E-F471-9490F959D2A7} = {B7399F39-300F-450E-F471-9490F959D2A7} + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A} = {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A} {2A793574-BD3C-46D4-9788-C339D9550CE1} = {2A793574-BD3C-46D4-9788-C339D9550CE1} {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7} = {EA1242CF-BB42-B1AC-9B6A-A508D96D1CB7} EndProjectSection @@ -52,6 +53,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "drivers", "drivers", "{864A EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d11", "renderdoc\driver\d3d11\renderdoc_d3d11.vcxproj", "{F1E59A05-60D4-4927-9E57-DD191EAE90EF}" ProjectSection(ProjectDependencies) = postProject + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A} = {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A} {2A793574-BD3C-46D4-9788-C339D9550CE1} = {2A793574-BD3C-46D4-9788-C339D9550CE1} EndProjectSection EndProject @@ -71,6 +73,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d12", "renderdoc\driver\d EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d9", "renderdoc\driver\d3d9\renderdoc_d3d9.vcxproj", "{44044776-9469-4079-B587-ABFFF6574AA4}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AMD", "renderdoc\driver\ihv\amd\AMD.vcxproj", "{5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Development|x64 = Development|x64 @@ -207,6 +211,15 @@ Global {44044776-9469-4079-B587-ABFFF6574AA4}.Release|x64.Build.0 = Release|x64 {44044776-9469-4079-B587-ABFFF6574AA4}.Release|x86.ActiveCfg = Release|Win32 {44044776-9469-4079-B587-ABFFF6574AA4}.Release|x86.Build.0 = Release|Win32 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Development|x64.ActiveCfg = Development|x64 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Development|x64.Build.0 = Development|x64 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Development|x86.ActiveCfg = Development|Win32 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Development|x86.Build.0 = Development|Win32 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Development|x86.Deploy.0 = Development|Win32 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Release|x64.ActiveCfg = Release|x64 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Release|x64.Build.0 = Release|x64 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Release|x86.ActiveCfg = Release|Win32 + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -232,5 +245,6 @@ Global {88C5DAC6-30A0-4CFD-AF51-540A977D1F3F} = {864A44B0-5612-451A-857F-41E3EF785EF6} {9E6B10A2-84B4-434D-ABDB-43BE4EA650F4} = {864A44B0-5612-451A-857F-41E3EF785EF6} {44044776-9469-4079-B587-ABFFF6574AA4} = {864A44B0-5612-451A-857F-41E3EF785EF6} + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A} = {864A44B0-5612-451A-857F-41E3EF785EF6} EndGlobalSection EndGlobal diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 7bcea742e..0912d5706 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -2918,12 +2918,27 @@ DOCUMENT(R"(The unit that GPU counter data is returned in. .. data:: Percentage The value is a floating point percentage value between 0.0 and 1.0. + +.. data:: Ratio + + The value describes a ratio between two separate GPU units or counters. + +.. data:: Bytes + + The value is in bytes. + +.. data:: Cycles + + The value is a duration in clock cycles. )"); enum class CounterUnit : uint32_t { Absolute, Seconds, Percentage, + Ratio, + Bytes, + Cycles, }; DOCUMENT(R"(How supported a given API is on a particular replay instance. diff --git a/renderdoc/driver/d3d11/d3d11_counters.cpp b/renderdoc/driver/d3d11/d3d11_counters.cpp index 76ca056c2..6b91b7b22 100644 --- a/renderdoc/driver/d3d11/d3d11_counters.cpp +++ b/renderdoc/driver/d3d11/d3d11_counters.cpp @@ -22,7 +22,10 @@ * THE SOFTWARE. ******************************************************************************/ +#include +#include #include "common/common.h" +#include "driver/ihv/amd/amd_counters.h" #include "d3d11_context.h" #include "d3d11_debug.h" #include "d3d11_device.h" @@ -61,6 +64,14 @@ vector D3D11DebugManager::EnumerateCounters() ret.push_back(GPUCounter::PSInvocations); ret.push_back(GPUCounter::CSInvocations); + if(m_pAMDCounters) + { + for(uint32_t i = 0; i < m_pAMDCounters->GetNumCounters(); i++) + { + ret.push_back(static_cast(static_cast(GPUCounter::FirstAMD) + i)); + } + } + return ret; } @@ -68,6 +79,17 @@ void D3D11DebugManager::DescribeCounter(GPUCounter counterID, CounterDescription { desc.counterID = counterID; + /////AMD////// + if(counterID >= GPUCounter::FirstAMD && counterID < GPUCounter::FirstIntel) + { + if(m_pAMDCounters) + { + desc = m_pAMDCounters->GetCounterDescription(counterID); + + return; + } + } + switch(counterID) { case GPUCounter::EventGPUDuration: @@ -257,6 +279,157 @@ void D3D11DebugManager::FillTimers(D3D11CounterContext &ctx, const DrawcallTreeN } } +void D3D11DebugManager::FillTimersAMD(uint32_t &eventStartID, uint32_t &sampleIndex, + vector &eventIDs, const DrawcallTreeNode &drawnode) +{ + if(drawnode.children.empty()) + return; + + for(size_t i = 0; i < drawnode.children.size(); i++) + { + const DrawcallDescription &d = drawnode.children[i].draw; + + FillTimersAMD(eventStartID, sampleIndex, eventIDs, drawnode.children[i]); + + if(d.events.count == 0) + continue; + + eventIDs.push_back(d.eventID); + + m_WrappedDevice->ReplayLog(eventStartID, d.eventID, eReplay_WithoutDraw); + + m_pImmediateContext->Flush(); + + m_pAMDCounters->BeginSample(sampleIndex); + + m_WrappedDevice->ReplayLog(eventStartID, d.eventID, eReplay_OnlyDraw); + + m_pAMDCounters->EndSample(); + + eventStartID = d.eventID + 1; + sampleIndex++; + } +} + +vector D3D11DebugManager::FetchCountersAMD(const vector &counters) +{ + vector ret; + + m_pAMDCounters->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((counters[i] >= (GPUCounter::FirstAMD)) && (counters[i] < (GPUCounter::FirstIntel))); + m_pAMDCounters->EnableCounter(counters[i]); + } + + uint32_t sessionID = m_pAMDCounters->BeginSession(); + + uint32_t passCount = m_pAMDCounters->GetPassCount(); + + uint32_t sampleIndex = 0; + + vector eventIDs; + + for(uint32_t p = 0; p < passCount; p++) + { + m_pAMDCounters->BeginPass(); + + uint32_t eventStartID = 0; + + sampleIndex = 0; + + eventIDs.clear(); + + FillTimersAMD(eventStartID, sampleIndex, eventIDs, m_WrappedContext->GetRootDraw()); + + m_pAMDCounters->EndPass(); + } + + m_pAMDCounters->EndSesssion(); + + bool isReady = false; + + do + { + isReady = m_pAMDCounters->IsSessionReady(sessionID); + } while(!isReady); + + for(uint32_t s = 0; s < sampleIndex; s++) + { + for(size_t c = 0; c < counters.size(); c++) + { + const CounterDescription desc = m_pAMDCounters->GetCounterDescription(counters[c]); + + switch(desc.resultType) + { + case CompType::UInt: + { + if(desc.resultByteWidth == sizeof(uint32_t)) + { + uint32_t value = m_pAMDCounters->GetSampleUint32(sessionID, s, counters[c]); + + if(desc.unit == CounterUnit::Percentage) + { + value = RDCCLAMP(value, 0U, 100U); + } + + ret.push_back(CounterResult(eventIDs[s], counters[c], value)); + } + else if(desc.resultByteWidth == sizeof(uint64_t)) + { + uint64_t value = m_pAMDCounters->GetSampleUint64(sessionID, s, counters[c]); + + if(desc.unit == CounterUnit::Percentage) + { + value = RDCCLAMP(value, 0ULL, 100ULL); + } + + ret.push_back( + + CounterResult(eventIDs[s], counters[c], value)); + } + else + { + RDCERR("Unexpected byte width %u", desc.resultByteWidth); + } + } + break; + case CompType::Float: + { + float value = m_pAMDCounters->GetSampleFloat32(sessionID, s, counters[c]); + + if(desc.unit == CounterUnit::Percentage) + { + value = RDCCLAMP(value, 0.0f, 100.0f); + } + + ret.push_back(CounterResult(eventIDs[s], counters[c], value)); + } + break; + case CompType::Double: + { + double value = m_pAMDCounters->GetSampleFloat64(sessionID, s, counters[c]); + + if(desc.unit == CounterUnit::Percentage) + { + value = RDCCLAMP(value, 0.0, 100.0); + } + + ret.push_back(CounterResult(eventIDs[s], counters[c], value)); + } + break; + default: RDCASSERT(0); break; + }; + } + } + + return ret; +} + vector D3D11DebugManager::FetchCounters(const vector &counters) { vector ret; @@ -269,6 +442,21 @@ vector D3D11DebugManager::FetchCounters(const vector SCOPED_TIMER("Fetch Counters, counters to fetch %u", counters.size()); + vector d3dCounters; + std::copy_if(counters.begin(), counters.end(), std::back_inserter(d3dCounters), + [](const GPUCounter &c) { return c <= GPUCounter::FirstAMD; }); + + if(m_pAMDCounters) + { + // Filter out the AMD counters + vector amdCounters; + std::copy_if( + counters.begin(), counters.end(), std::back_inserter(amdCounters), + [](const GPUCounter &c) { return c >= GPUCounter::FirstAMD && c < GPUCounter::FirstIntel; }); + + ret = FetchCountersAMD(amdCounters); + } + D3D11_QUERY_DESC disjointdesc = {D3D11_QUERY_TIMESTAMP_DISJOINT, 0}; ID3D11Query *disjoint = NULL; @@ -349,9 +537,9 @@ vector D3D11DebugManager::FetchCounters(const vector hr = m_pImmediateContext->GetData(ctx.timers[i].occlusion, &occlusion, sizeof(UINT64), 0); RDCASSERTEQUAL(hr, S_OK); - for(size_t c = 0; c < counters.size(); c++) + for(size_t c = 0; c < d3dCounters.size(); c++) { - switch(counters[c]) + switch(d3dCounters[c]) { case GPUCounter::EventGPUDuration: ret.push_back( @@ -410,9 +598,9 @@ vector D3D11DebugManager::FetchCounters(const vector } else { - for(size_t c = 0; c < counters.size(); c++) + for(size_t c = 0; c < d3dCounters.size(); c++) { - switch(counters[c]) + switch(d3dCounters[c]) { case GPUCounter::EventGPUDuration: ret.push_back( @@ -430,7 +618,8 @@ vector D3D11DebugManager::FetchCounters(const vector case GPUCounter::PSInvocations: case GPUCounter::CSInvocations: case GPUCounter::SamplesWritten: - ret.push_back(CounterResult(ctx.timers[i].eventID, counters[c], 0xFFFFFFFFFFFFFFFF)); + ret.push_back( + CounterResult(ctx.timers[i].eventID, d3dCounters[c], 0xFFFFFFFFFFFFFFFF)); break; } } diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index 404f31d3b..c22dd8444 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -28,6 +28,7 @@ #include "data/resource.h" #include "driver/d3d11/d3d11_resources.h" #include "driver/dx/official/d3dcompiler.h" +#include "driver/ihv/amd/amd_counters.h" #include "driver/shaders/dxbc/dxbc_debug.h" #include "maths/camera.h" #include "maths/formatpacking.h" @@ -156,10 +157,23 @@ D3D11DebugManager::D3D11DebugManager(WrappedID3D11Device *wrapper) PostDeviceInitCounters(); RenderDoc::Inst().SetProgress(DebugManagerInit, 1.0f); + + AMDCounters *counters = new AMDCounters(); + if(counters->Init((void *)m_pDevice)) + { + m_pAMDCounters = counters; + } + else + { + delete counters; + m_pAMDCounters = NULL; + } } D3D11DebugManager::~D3D11DebugManager() { + SAFE_DELETE(m_pAMDCounters); + PreDeviceShutdownCounters(); if(m_ShaderCacheDirty) diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index ee30975da..084ed3f3b 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -43,6 +43,8 @@ class Vec3f; class WrappedID3D11Device; class WrappedID3D11DeviceContext; +class AMDCounters; + struct DrawcallTreeNode; struct D3D11CounterContext; @@ -158,6 +160,7 @@ public: vector EnumerateCounters(); void DescribeCounter(GPUCounter counterID, CounterDescription &desc); vector FetchCounters(const vector &counters); + vector FetchCountersAMD(const vector &counters); void RenderText(float x, float y, const char *textfmt, ...); void RenderMesh(uint32_t eventID, const vector &secondaryDraws, const MeshDisplay &cfg); @@ -260,6 +263,8 @@ public: TextureShaderDetails GetShaderDetails(ResourceId id, CompType typeHint, bool rawOutput); + AMDCounters *m_pAMDCounters; + private: struct CacheElem { @@ -581,5 +586,8 @@ private: void FillTimers(D3D11CounterContext &ctx, const DrawcallTreeNode &drawnode); + void FillTimersAMD(uint32_t &eventStartID, uint32_t &sampleIndex, vector &eventIDs, + const DrawcallTreeNode &drawnode); + void FillCBuffer(ID3D11Buffer *buf, const void *data, size_t size); }; diff --git a/renderdoc/driver/d3d11/d3d11_hooks.cpp b/renderdoc/driver/d3d11/d3d11_hooks.cpp index 2d2b123d7..628af0d66 100644 --- a/renderdoc/driver/d3d11/d3d11_hooks.cpp +++ b/renderdoc/driver/d3d11/d3d11_hooks.cpp @@ -24,8 +24,8 @@ ******************************************************************************/ #include "driver/d3d11/d3d11_device.h" -#include "driver/dx/official/amd/AmdDxExtApi.h" #include "driver/dxgi/dxgi_wrapped.h" +#include "driver/ihv/amd/official/DXExt/AmdDxExtApi.h" #include "hooks/hooks.h" #define DLL_NAME "d3d11.dll" diff --git a/renderdoc/driver/d3d11/renderdoc_d3d11.vcxproj b/renderdoc/driver/d3d11/renderdoc_d3d11.vcxproj index 797ff3e9c..2bf2751df 100644 --- a/renderdoc/driver/d3d11/renderdoc_d3d11.vcxproj +++ b/renderdoc/driver/d3d11/renderdoc_d3d11.vcxproj @@ -59,7 +59,7 @@ RELEASE;%(PreprocessorDefinitions) - + $(SolutionDir)renderdoc\;$(SolutionDir)renderdoc\3rdparty\ RENDERDOC_EXPORTS;RENDERDOC_PLATFORM_WIN32;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) @@ -144,6 +144,9 @@ + + {5de5a561-548a-4dd7-90f0-06a2b39eae9a} + {c43ff27e-a155-4852-88ec-5ce9334c07a8} false diff --git a/renderdoc/driver/ihv/amd/AMD.vcxproj b/renderdoc/driver/ihv/amd/AMD.vcxproj new file mode 100644 index 000000000..b4252272d --- /dev/null +++ b/renderdoc/driver/ihv/amd/AMD.vcxproj @@ -0,0 +1,104 @@ + + + + + Development + Win32 + + + Development + x64 + + + Release + Win32 + + + Release + x64 + + + + {5DE5A561-548A-4DD7-90F0-06A2B39EAE9A} + AMD + + + + 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/amd/AMD.vcxproj.filters b/renderdoc/driver/ihv/amd/AMD.vcxproj.filters new file mode 100644 index 000000000..9dedfb9dd --- /dev/null +++ b/renderdoc/driver/ihv/amd/AMD.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/renderdoc/driver/ihv/amd/amd_counters.cpp b/renderdoc/driver/ihv/amd/amd_counters.cpp new file mode 100644 index 000000000..7d4a89aa5 --- /dev/null +++ b/renderdoc/driver/ihv/amd/amd_counters.cpp @@ -0,0 +1,419 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2015-2017 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 "amd_counters.h" +#include +#include "common/common.h" +#include "official/GPUPerfAPI/Include/GPUPerfAPI.h" +#include "official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes.h" + +typedef GPA_Status(__stdcall *PFN_GPA_INITIALIZE)(); +typedef GPA_Status(__stdcall *PFN_GPA_OPENCONTEXT)(void *pContext); +typedef GPA_Status(__stdcall *PFN_GPA_GET_NUM_COUNTERS)(gpa_uint32 *pCount); +typedef GPA_Status(__stdcall *PFN_GPA_GET_COUNTER_NAME)(gpa_uint32 index, const char **ppName); +typedef GPA_Status(__stdcall *PFN_GPA_GET_COUNTER_INDEX)(const char *pCounter, gpa_uint32 *pIndex); +typedef GPA_Status(__stdcall *PFN_GPA_GET_COUNTER_DESCRIPTION)(gpa_uint32 index, + const char **ppDescription); +typedef GPA_Status(__stdcall *PFN_GPA_GET_COUNTER_DATA_TYPE)(gpa_uint32 index, GPA_Type *pDataType); +typedef GPA_Status(__stdcall *PFN_GPA_GET_COUNTER_USAGE_TYPE)(gpa_uint32 index, + GPA_Usage_Type *usageType); +typedef GPA_Status(__stdcall *PFN_GPA_ENABLE_COUNTER)(gpa_uint32 index); +typedef GPA_Status(__stdcall *PFN_GPA_ENABLE_COUNTER_STR)(const char *pCounter); +typedef GPA_Status(__stdcall *PFN_GPA_ENABLE_ALL_COUNTERS)(); +typedef GPA_Status(__stdcall *PFN_GPA_DISABLE_COUNTER)(gpa_uint32 index); +typedef GPA_Status(__stdcall *PFN_GPA_DISABLE_COUNTER_STR)(const char *pCounter); +typedef GPA_Status(__stdcall *PFN_GPA_DISABLE_ALL_COUNTERS)(); +typedef GPA_Status(__stdcall *PFN_GPA_GET_PASS_COUNT)(gpa_uint32 *pNumPasses); +typedef GPA_Status(__stdcall *PFN_GPA_BEGIN_SESSION)(gpa_uint32 *pSessionID); +typedef GPA_Status(__stdcall *PFN_GPA_END_SESSION)(); +typedef GPA_Status(__stdcall *PFN_GPA_BEGIN_PASS)(); +typedef GPA_Status(__stdcall *PFN_GPA_END_PASS)(); +typedef GPA_Status(__stdcall *PFN_GPA_BEGIN_SAMPLE)(gpa_uint32 sampleID); +typedef GPA_Status(__stdcall *PFN_GPA_END_SAMPLE)(); +typedef GPA_Status(__stdcall *PFN_GPA_IS_SESSION_READY)(bool *pReadyResult, gpa_uint32 sessionID); +typedef GPA_Status(__stdcall *PFN_GPA_IS_SAMPLE_READY)(bool *pReadyResult, gpa_uint32 sessionID, + gpa_uint32 sampleID); +typedef GPA_Status(__stdcall *PFN_GPA_GET_SAMPLE_UINT32)(gpa_uint32 sessionID, gpa_uint32 sampleID, + gpa_uint32 counterID, gpa_uint32 *pResult); +typedef GPA_Status(__stdcall *PFN_GPA_GET_SAMPLE_UINT64)(gpa_uint32 sessionID, gpa_uint32 sampleID, + gpa_uint32 counterID, gpa_uint64 *pResult); +typedef GPA_Status(__stdcall *PFN_GPA_GET_SAMPLE_FLOAT32)(gpa_uint32 sessionID, gpa_uint32 sampleID, + gpa_uint32 counterID, gpa_float32 *pResult); +typedef GPA_Status(__stdcall *PFN_GPA_GET_SAMPLE_FLOAT64)(gpa_uint32 sessionID, gpa_uint32 sampleID, + gpa_uint32 counterID, gpa_float64 *pResult); +typedef GPA_Status(__stdcall *PFN_GPA_CLOSE_CONTEXT)(); +typedef GPA_Status(__stdcall *PFN_GPA_DESTROY)(); + +class GPUPerfAPI +{ +public: + PFN_GPA_INITIALIZE init; + PFN_GPA_OPENCONTEXT openContext; + PFN_GPA_GET_NUM_COUNTERS getNumCounters; + PFN_GPA_GET_COUNTER_NAME getCounterName; + PFN_GPA_GET_COUNTER_INDEX getCounterIndex; + PFN_GPA_GET_COUNTER_DESCRIPTION getCounterDescription; + PFN_GPA_GET_COUNTER_DATA_TYPE getCounterDataType; + PFN_GPA_GET_COUNTER_USAGE_TYPE getCounterUsageType; + PFN_GPA_ENABLE_COUNTER enableCounter; + PFN_GPA_ENABLE_COUNTER_STR enableCounterStr; + PFN_GPA_ENABLE_ALL_COUNTERS enableAllCounters; + PFN_GPA_DISABLE_COUNTER disableCounter; + PFN_GPA_DISABLE_COUNTER_STR disableCounterStr; + PFN_GPA_DISABLE_ALL_COUNTERS disableAllCounters; + PFN_GPA_GET_PASS_COUNT getPassCount; + PFN_GPA_BEGIN_SESSION beginSession; + PFN_GPA_END_SESSION endSession; + PFN_GPA_BEGIN_PASS beginPass; + PFN_GPA_END_PASS endPass; + PFN_GPA_BEGIN_SAMPLE beginSample; + PFN_GPA_END_SAMPLE endSample; + PFN_GPA_IS_SESSION_READY isSessionReady; + PFN_GPA_IS_SAMPLE_READY isSampleReady; + PFN_GPA_GET_SAMPLE_UINT32 getSampleUInt32; + PFN_GPA_GET_SAMPLE_UINT64 getSampleUInt64; + PFN_GPA_GET_SAMPLE_FLOAT32 getSampleFloat32; + PFN_GPA_GET_SAMPLE_FLOAT64 getSampleFloat64; + PFN_GPA_CLOSE_CONTEXT closeContext; + PFN_GPA_DESTROY destroy; +}; + +AMDCounters::AMDCounters() : m_pGPUPerfAPI(NULL) +{ +} + +bool AMDCounters::Init(void *pContext) +{ + HMODULE module = LoadLibraryA("GPUPerfAPIDX11-x64.dll"); + + if(module == 0) + { + RDCERR( + "AMD GPU performance counters could not be initialized successfully. " + "Are you missing the DLLs?"); + + return false; + } + + m_pGPUPerfAPI = new GPUPerfAPI(); + m_pGPUPerfAPI->init = (PFN_GPA_INITIALIZE)GetProcAddress(module, "GPA_Initialize"); + m_pGPUPerfAPI->openContext = (PFN_GPA_OPENCONTEXT)GetProcAddress(module, "GPA_OpenContext"); + m_pGPUPerfAPI->getNumCounters = + (PFN_GPA_GET_NUM_COUNTERS)GetProcAddress(module, "GPA_GetNumCounters"); + m_pGPUPerfAPI->getCounterName = + (PFN_GPA_GET_COUNTER_NAME)GetProcAddress(module, "GPA_GetCounterName"); + m_pGPUPerfAPI->getCounterIndex = + (PFN_GPA_GET_COUNTER_INDEX)GetProcAddress(module, "GPA_GetCounterIndex"); + m_pGPUPerfAPI->getCounterDescription = + (PFN_GPA_GET_COUNTER_DESCRIPTION)GetProcAddress(module, "GPA_GetCounterDescription"); + m_pGPUPerfAPI->getCounterDataType = + (PFN_GPA_GET_COUNTER_DATA_TYPE)GetProcAddress(module, "GPA_GetCounterDataType"); + m_pGPUPerfAPI->getCounterUsageType = + (PFN_GPA_GET_COUNTER_USAGE_TYPE)GetProcAddress(module, "GPA_GetCounterUsageType"); + m_pGPUPerfAPI->enableCounter = + (PFN_GPA_ENABLE_COUNTER)GetProcAddress(module, "GPA_EnableCounter"); + m_pGPUPerfAPI->enableCounterStr = + (PFN_GPA_ENABLE_COUNTER_STR)GetProcAddress(module, "GPA_EnableCounterStr"); + m_pGPUPerfAPI->enableAllCounters = + (PFN_GPA_ENABLE_ALL_COUNTERS)GetProcAddress(module, "GPA_EnableAllCounters"); + m_pGPUPerfAPI->disableCounter = + (PFN_GPA_DISABLE_COUNTER)GetProcAddress(module, "GPA_DisableCounter"); + m_pGPUPerfAPI->disableCounterStr = + (PFN_GPA_DISABLE_COUNTER_STR)GetProcAddress(module, "GPA_DisableCounterStr"); + m_pGPUPerfAPI->disableAllCounters = + (PFN_GPA_DISABLE_ALL_COUNTERS)GetProcAddress(module, "GPA_DisableAllCounters"); + m_pGPUPerfAPI->getPassCount = (PFN_GPA_GET_PASS_COUNT)GetProcAddress(module, "GPA_GetPassCount"); + m_pGPUPerfAPI->beginSession = (PFN_GPA_BEGIN_SESSION)GetProcAddress(module, "GPA_BeginSession"); + m_pGPUPerfAPI->endSession = (PFN_GPA_END_SESSION)GetProcAddress(module, "GPA_EndSession"); + m_pGPUPerfAPI->beginPass = (PFN_GPA_BEGIN_PASS)GetProcAddress(module, "GPA_BeginPass"); + m_pGPUPerfAPI->endPass = (PFN_GPA_END_PASS)GetProcAddress(module, "GPA_EndPass"); + m_pGPUPerfAPI->beginSample = (PFN_GPA_BEGIN_SAMPLE)GetProcAddress(module, "GPA_BeginSample"); + m_pGPUPerfAPI->endSample = (PFN_GPA_END_SAMPLE)GetProcAddress(module, "GPA_EndSample"); + m_pGPUPerfAPI->isSessionReady = + (PFN_GPA_IS_SESSION_READY)GetProcAddress(module, "GPA_IsSessionReady"); + m_pGPUPerfAPI->isSampleReady = + (PFN_GPA_IS_SAMPLE_READY)GetProcAddress(module, "GPA_IsSampleReady"); + m_pGPUPerfAPI->getSampleUInt32 = + (PFN_GPA_GET_SAMPLE_UINT32)GetProcAddress(module, "GPA_GetSampleUInt32"); + m_pGPUPerfAPI->getSampleUInt64 = + (PFN_GPA_GET_SAMPLE_UINT64)GetProcAddress(module, "GPA_GetSampleUInt64"); + m_pGPUPerfAPI->getSampleFloat32 = + (PFN_GPA_GET_SAMPLE_FLOAT32)GetProcAddress(module, "GPA_GetSampleFloat32"); + m_pGPUPerfAPI->getSampleFloat64 = + (PFN_GPA_GET_SAMPLE_FLOAT64)GetProcAddress(module, "GPA_GetSampleFloat64"); + m_pGPUPerfAPI->closeContext = (PFN_GPA_CLOSE_CONTEXT)GetProcAddress(module, "GPA_CloseContext"); + m_pGPUPerfAPI->destroy = (PFN_GPA_DESTROY)GetProcAddress(module, "GPA_Destroy"); + + if(m_pGPUPerfAPI->init() != GPA_STATUS_OK) + { + delete m_pGPUPerfAPI; + m_pGPUPerfAPI = NULL; + return false; + } + + if(m_pGPUPerfAPI->openContext(pContext) != GPA_STATUS_OK) + { + m_pGPUPerfAPI->destroy(); + delete m_pGPUPerfAPI; + m_pGPUPerfAPI = NULL; + return false; + } + + m_Counters = EnumerateCounters(); + + return true; +} + +AMDCounters::~AMDCounters() +{ + if(m_pGPUPerfAPI) + { + GPA_Status status = GPA_STATUS_OK; + + status = m_pGPUPerfAPI->closeContext(); + status = m_pGPUPerfAPI->destroy(); + + delete m_pGPUPerfAPI; + } +} + +vector AMDCounters::EnumerateCounters() +{ + gpa_uint32 num; + + m_pGPUPerfAPI->getNumCounters(&num); + + vector counters; + + for(uint32_t i = 0; i < num; ++i) + { + InternalCounterDescription internalDesc; + internalDesc.desc = InternalGetCounterDescription(i); + + // We ignore any D3D11 counters, as those are handled elsewhere + if(strncmp(internalDesc.desc.description, "#D3D11#", 7) == 0) + { + continue; + } + + internalDesc.internalIndex = i; + counters.push_back(internalDesc); + } + + return counters; +} + +uint32_t AMDCounters::GetNumCounters() +{ + return (uint32_t)m_Counters.size(); +} + +CounterDescription AMDCounters::GetCounterDescription(GPUCounter counter) +{ + return m_Counters[GPUCounterToCounterIndex(counter)].desc; +} + +CounterDescription AMDCounters::InternalGetCounterDescription(uint32_t internalIndex) +{ + CounterDescription desc = {}; + const char *tmp = NULL; + m_pGPUPerfAPI->getCounterName(internalIndex, &tmp); + desc.name = tmp; + m_pGPUPerfAPI->getCounterDescription(internalIndex, &tmp); + desc.description = tmp; + + GPA_Usage_Type usageType; + + m_pGPUPerfAPI->getCounterUsageType(internalIndex, &usageType); + + switch(usageType) + { + case GPA_USAGE_TYPE_RATIO: ///< Result is a ratio of two different values or types + desc.unit = CounterUnit::Ratio; + break; + case GPA_USAGE_TYPE_PERCENTAGE: ///< Result is a percentage, typically within [0,100] range, + /// but may be higher for certain counters + desc.unit = CounterUnit::Percentage; + break; + case GPA_USAGE_TYPE_CYCLES: ///< Result is in clock cycles + desc.unit = CounterUnit::Cycles; + break; + case GPA_USAGE_TYPE_MILLISECONDS: ///< Result is in milliseconds + desc.unit = CounterUnit::Seconds; + break; + case GPA_USAGE_TYPE_KILOBYTES: ///< Result is in kilobytes + case GPA_USAGE_TYPE_BYTES: ///< Result is in bytes + desc.unit = CounterUnit::Bytes; + break; + case GPA_USAGE_TYPE_ITEMS: ///< Result is a count of items or objects (ie, vertices, + /// triangles, threads, pixels, texels, etc) + desc.unit = CounterUnit::Absolute; + break; + default: desc.unit = CounterUnit::Absolute; + } + + GPA_Type type; + + m_pGPUPerfAPI->getCounterDataType(internalIndex, &type); + + // results should either be float32/64 or uint32/64 as the GetSample functions only support those + switch(type) + { + case GPA_TYPE_FLOAT32: ///< Result will be a 32-bit float + desc.resultType = CompType::Float; + desc.resultByteWidth = sizeof(float); + break; + case GPA_TYPE_FLOAT64: ///< Result will be a 64-bit float + desc.resultType = CompType::Double; + desc.resultByteWidth = sizeof(double); + break; + case GPA_TYPE_UINT32: ///< Result will be a 32-bit unsigned int + desc.resultType = CompType::UInt; + desc.resultByteWidth = sizeof(uint32_t); + break; + case GPA_TYPE_UINT64: ///< Result will be a 64-bit unsigned int + desc.resultType = CompType::UInt; + desc.resultByteWidth = sizeof(uint64_t); + break; + case GPA_TYPE_INT32: ///< Result will be a 32-bit int + desc.resultType = CompType::SInt; + desc.resultByteWidth = sizeof(int32_t); + break; + case GPA_TYPE_INT64: ///< Result will be a 64-bit int + desc.resultType = CompType::SInt; + desc.resultByteWidth = sizeof(int64_t); + break; + default: desc.resultType = CompType::UInt; desc.resultByteWidth = sizeof(uint32_t); + } + + return desc; +} + +void AMDCounters::EnableCounter(GPUCounter counter) +{ + const uint32_t internalIndex = m_Counters[GPUCounterToCounterIndex(counter)].internalIndex; + + m_pGPUPerfAPI->enableCounter(internalIndex); +} + +void AMDCounters::EnableAllCounters() +{ + m_pGPUPerfAPI->enableAllCounters(); +} + +void AMDCounters::DisableAllCounters() +{ + m_pGPUPerfAPI->disableAllCounters(); +} + +uint32_t AMDCounters::GetPassCount() +{ + gpa_uint32 numRequiredPasses; + m_pGPUPerfAPI->getPassCount(&numRequiredPasses); + + return (uint32_t)numRequiredPasses; +} + +uint32_t AMDCounters::BeginSession() +{ + gpa_uint32 sessionID; + + m_pGPUPerfAPI->beginSession(&sessionID); + + return (uint32_t)sessionID; +} + +void AMDCounters::EndSesssion() +{ + m_pGPUPerfAPI->endSession(); +} + +bool AMDCounters::IsSessionReady(uint32_t sessionIndex) +{ + bool readyResult = false; + + GPA_Status status = m_pGPUPerfAPI->isSessionReady(&readyResult, sessionIndex); + + return readyResult && status == GPA_STATUS_OK; +} + +void AMDCounters::BeginPass() +{ + m_pGPUPerfAPI->beginPass(); +} + +void AMDCounters::EndPass() +{ + m_pGPUPerfAPI->endPass(); +} + +void AMDCounters::BeginSample(uint32_t index) +{ + m_pGPUPerfAPI->beginSample(index); +} + +void AMDCounters::EndSample() +{ + m_pGPUPerfAPI->endSample(); +} + +uint32_t AMDCounters::GetSampleUint32(uint32_t session, uint32_t sample, GPUCounter counter) +{ + const uint32_t internalIndex = m_Counters[GPUCounterToCounterIndex(counter)].internalIndex; + uint32_t value; + + m_pGPUPerfAPI->getSampleUInt32(session, sample, internalIndex, &value); + + return value; +} + +uint64_t AMDCounters::GetSampleUint64(uint32_t session, uint32_t sample, GPUCounter counter) +{ + const uint32_t internalIndex = m_Counters[GPUCounterToCounterIndex(counter)].internalIndex; + gpa_uint64 value; + + m_pGPUPerfAPI->getSampleUInt64(session, sample, internalIndex, &value); + + return value; +} + +float AMDCounters::GetSampleFloat32(uint32_t session, uint32_t sample, GPUCounter counter) +{ + const uint32_t internalIndex = m_Counters[GPUCounterToCounterIndex(counter)].internalIndex; + float value; + + m_pGPUPerfAPI->getSampleFloat32(session, sample, internalIndex, &value); + + return value; +} + +double AMDCounters::GetSampleFloat64(uint32_t session, uint32_t sample, GPUCounter counter) +{ + const uint32_t internalIndex = m_Counters[GPUCounterToCounterIndex(counter)].internalIndex; + double value; + + m_pGPUPerfAPI->getSampleFloat64(session, sample, internalIndex, &value); + + return value; +} \ No newline at end of file diff --git a/renderdoc/driver/ihv/amd/amd_counters.h b/renderdoc/driver/ihv/amd/amd_counters.h new file mode 100644 index 000000000..4ce5b343e --- /dev/null +++ b/renderdoc/driver/ihv/amd/amd_counters.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2015-2017 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 "api/replay/renderdoc_replay.h" + +class GPUPerfAPI; + +class AMDCounters +{ +public: + AMDCounters(); + bool Init(void *pContext); + ~AMDCounters(); + + uint32_t GetNumCounters(); + + CounterDescription GetCounterDescription(GPUCounter index); + + void EnableCounter(GPUCounter index); + void EnableAllCounters(); + void DisableAllCounters(); + + uint32_t GetPassCount(); + + uint32_t BeginSession(); + void EndSesssion(); + + void BeginPass(); + void EndPass(); + + void BeginSample(uint32_t index); + void EndSample(); + + bool IsSessionReady(uint32_t sessionIndex); + + uint32_t GetSampleUint32(uint32_t session, uint32_t sample, GPUCounter counter); + + uint64_t GetSampleUint64(uint32_t session, uint32_t sample, GPUCounter counter); + + float GetSampleFloat32(uint32_t session, uint32_t sample, GPUCounter counter); + + double GetSampleFloat64(uint32_t session, uint32_t sample, GPUCounter counter); + +private: + GPUPerfAPI *m_pGPUPerfAPI; + static uint32_t GPUCounterToCounterIndex(GPUCounter counter) + { + return (uint32_t)(counter) - (uint32_t)(GPUCounter::FirstAMD); + } + + CounterDescription InternalGetCounterDescription(uint32_t index); + + struct InternalCounterDescription + { + CounterDescription desc; + uint32_t internalIndex; + }; + + std::vector EnumerateCounters(); + std::vector m_Counters; +}; \ No newline at end of file diff --git a/renderdoc/driver/dx/official/amd/AmdDxExt.h b/renderdoc/driver/ihv/amd/official/DXExt/AmdDxExt.h similarity index 100% rename from renderdoc/driver/dx/official/amd/AmdDxExt.h rename to renderdoc/driver/ihv/amd/official/DXExt/AmdDxExt.h diff --git a/renderdoc/driver/dx/official/amd/AmdDxExtApi.h b/renderdoc/driver/ihv/amd/official/DXExt/AmdDxExtApi.h similarity index 100% rename from renderdoc/driver/dx/official/amd/AmdDxExtApi.h rename to renderdoc/driver/ihv/amd/official/DXExt/AmdDxExtApi.h diff --git a/renderdoc/driver/dx/official/amd/AmdDxExtIface.h b/renderdoc/driver/ihv/amd/official/DXExt/AmdDxExtIface.h similarity index 100% rename from renderdoc/driver/dx/official/amd/AmdDxExtIface.h rename to renderdoc/driver/ihv/amd/official/DXExt/AmdDxExtIface.h diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPACounterGenerator.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPACounterGenerator.h new file mode 100644 index 000000000..b587289ec --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPACounterGenerator.h @@ -0,0 +1,32 @@ +//============================================================================== +// Copyright (c) 2012-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief GPUPerfAPI Counter Generator function +//============================================================================== + + +#ifndef _GPA_COUNTER_GENERATOR_H_ +#define _GPA_COUNTER_GENERATOR_H_ + +#include "GPAICounterAccessor.h" +#include "GPAICounterScheduler.h" +#include "GPUPerfAPITypes.h" +#include "GPUPerfAPITypes-Private.h" + +// Internal function. We don't want this exposed by the internal DLLs though, so it doesn't use GPALIB_DECL +/// Generates a counter accessor object that can be used to obtain the counters to expose +/// \param[in] desiredAPI The API to generate counters for +/// \param[in] vendorId The vendor id to generate counters for +/// \param[in] deviceId The device id to generate counters for +/// \param[in] revisionId The revision id to generate counters for +/// \param[inout] ppCounterAccessorOut Address of a GPA_ICounterAccessor pointer which will be set to the necessary counter accessor +/// \param[inout] ppCounterSchedulerOut Address of a GPA_ICounterScheduler pointer which will be set to the necessary counter scheduler +/// \return GPA_STATUS_ERROR_NULL_POINTER if ppCounterAccessorOut or ppCounterSchedulerOut is nullptr +/// \return GPA_STATUS_ERROR_NOT_FOUND if the desired API is not supported +/// \return GPA_STATUS_ERROR_NOT_ENABLED if the desired API is not allowing any counters to be exposed +/// \return GPA_STATUS_ERROR_HARDWARE_NOT_SUPPORTED if the desired generation is not supported +/// \return GPA_STATUS_OK if the desired API and generation are supported +GPA_Status GenerateCounters(GPA_API_Type desiredAPI, gpa_uint32 vendorId, gpa_uint32 deviceId, gpa_uint32 revisionId, GPA_ICounterAccessor** ppCounterAccessorOut, GPA_ICounterScheduler** ppCounterSchedulerOut); + +#endif // _GPA_COUNTER_GENERATOR_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAFunctions.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAFunctions.h new file mode 100644 index 000000000..3207033ac --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAFunctions.h @@ -0,0 +1,81 @@ +//============================================================================== +// Copyright (c) 2014-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief GPA required public function declarations wrapped in a macro +//============================================================================== + +#ifndef GPA_FUNCTION_PREFIX + #define GPA_FUNCTION_PREFIX( f ) ///< placeholder macro in case it's not defined before including this file + #define NEED_TO_UNDEFINE_GPA_FUNCTION_PREFIX ///< used a a flag to indicate whether or not the macro needs to be undefined later +#endif + +GPA_FUNCTION_PREFIX(GPA_RegisterLoggingCallback) + +#ifdef AMDT_INTERNAL + GPA_FUNCTION_PREFIX(GPA_RegisterLoggingDebugCallback) +#endif // AMDT_INTERNAL + +GPA_FUNCTION_PREFIX(GPA_Initialize) +GPA_FUNCTION_PREFIX(GPA_Destroy) + +// Context +GPA_FUNCTION_PREFIX(GPA_OpenContext) +GPA_FUNCTION_PREFIX(GPA_CloseContext) +GPA_FUNCTION_PREFIX(GPA_SelectContext) + +// Counter Interrogation +GPA_FUNCTION_PREFIX(GPA_GetNumCounters) +GPA_FUNCTION_PREFIX(GPA_GetCounterName) +GPA_FUNCTION_PREFIX(GPA_GetCounterDescription) +GPA_FUNCTION_PREFIX(GPA_GetCounterDataType) +GPA_FUNCTION_PREFIX(GPA_GetCounterUsageType) +GPA_FUNCTION_PREFIX(GPA_GetDataTypeAsStr) +GPA_FUNCTION_PREFIX(GPA_GetUsageTypeAsStr) +GPA_FUNCTION_PREFIX(GPA_GetStatusAsStr) + +GPA_FUNCTION_PREFIX(GPA_EnableCounter) +GPA_FUNCTION_PREFIX(GPA_DisableCounter) +GPA_FUNCTION_PREFIX(GPA_GetEnabledCount) +GPA_FUNCTION_PREFIX(GPA_GetEnabledIndex) + +GPA_FUNCTION_PREFIX(GPA_IsCounterEnabled) + +GPA_FUNCTION_PREFIX(GPA_EnableCounterStr) +GPA_FUNCTION_PREFIX(GPA_DisableCounterStr) + +GPA_FUNCTION_PREFIX(GPA_EnableAllCounters) +GPA_FUNCTION_PREFIX(GPA_DisableAllCounters) +GPA_FUNCTION_PREFIX(GPA_GetCounterIndex) + +GPA_FUNCTION_PREFIX(GPA_GetPassCount) + +GPA_FUNCTION_PREFIX(GPA_BeginSession) +GPA_FUNCTION_PREFIX(GPA_EndSession) + +GPA_FUNCTION_PREFIX(GPA_BeginPass) +GPA_FUNCTION_PREFIX(GPA_EndPass) + +GPA_FUNCTION_PREFIX(GPA_BeginSample) +GPA_FUNCTION_PREFIX(GPA_EndSample) + +GPA_FUNCTION_PREFIX(GPA_GetSampleCount) + +GPA_FUNCTION_PREFIX(GPA_IsSampleReady) +GPA_FUNCTION_PREFIX(GPA_IsSessionReady) +GPA_FUNCTION_PREFIX(GPA_GetSampleUInt64) +GPA_FUNCTION_PREFIX(GPA_GetSampleUInt32) +GPA_FUNCTION_PREFIX(GPA_GetSampleFloat64) +GPA_FUNCTION_PREFIX(GPA_GetSampleFloat32) + +GPA_FUNCTION_PREFIX(GPA_GetDeviceID) +GPA_FUNCTION_PREFIX(GPA_GetDeviceDesc) + +#ifdef AMDT_INTERNAL + GPA_FUNCTION_PREFIX(GPA_InternalSetDrawCallCounts) +#endif + +#ifdef NEED_TO_UNDEFINE_GPA_FUNCTION_PREFIX + #undef GPA_FUNCTION_PREFIX + #undef NEED_TO_UNDEFINE_GPA_FUNCTION_PREFIX +#endif diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAICounterAccessor.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAICounterAccessor.h new file mode 100644 index 000000000..b3717bd31 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAICounterAccessor.h @@ -0,0 +1,106 @@ +//============================================================================== +// Copyright (c) 2012-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief An accessor interface for the GPA_CounterGeneratorBase class +//============================================================================== + + +#ifndef _GPA_I_COUNTER_ACCESSOR_H_ +#define _GPA_I_COUNTER_ACCESSOR_H_ + +#include +#include "GPUPerfAPITypes.h" + +struct GPA_HardwareCounterDescExt; +class GPA_HWInfo; +class GPA_PublicCounter; +class GPA_CounterResultLocation; + +/// Types of counter +enum GPACounterType { PUBLIC_COUNTER, HARDWARE_COUNTER, SOFTWARE_COUNTER, UNKNOWN_COUNTER }; + +/// Stores the type of counter and its local index into that family of counters +struct GPACounterTypeInfo +{ + gpa_uint32 m_localIndex; ///< the local index of the counter + GPACounterType m_counterType; ///< the type of the counter + + /// Sets the data for + /// \param localIndex the local index to set + /// \param type the type to set + void Set(gpa_uint32 localIndex, GPACounterType type) + { + m_localIndex = localIndex; + m_counterType = type; + } +}; + +/// An accessor interface for the GPA_CounterGeneratorBase class +class GPA_ICounterAccessor +{ +public: + /// Get the number of available counters + /// \return the number of available counters + virtual gpa_uint32 GetNumCounters() = 0; + + /// Gets a counter's name + /// \param index The index of a counter, must be between 0 and the value returned from GetNumPublicCounters() + /// \return The counter name + virtual const char* GetCounterName(gpa_uint32 index) = 0; + + /// Gets a counter's description + /// \param index The index of a counter, must be between 0 and the value returned from GetNumPublicCounters() + /// \return The counter description + virtual const char* GetCounterDescription(gpa_uint32 index) = 0; + + /// Gets the data type of a public counter + /// \param index The index of a counter + /// \return The data type of the the desired counter + virtual GPA_Type GetCounterDataType(gpa_uint32 index) = 0; + + /// Gets the usage type of a public counter + /// \param index The index of a counter + /// \return The usage of the the desired counter + virtual GPA_Usage_Type GetCounterUsageType(gpa_uint32 index) = 0; + + /// Gets a public counter + /// \param index The index of the public counter to return + /// \return A public counter + virtual const GPA_PublicCounter* GetPublicCounter(gpa_uint32 index) = 0; + + /// Gets a hardware counter + /// \param index The index of a hardware counter to return + /// \return A hardware counter + virtual GPA_HardwareCounterDescExt* GetHardwareCounterExt(gpa_uint32 index) = 0; + + /// Gets the number of public counters available + /// \return The number of public counters + virtual gpa_uint32 GetNumPublicCounters() = 0; + + /// Gets the internal counters required for the specified public counter index + /// \param index The index of a public counter + /// \return A vector of internal counter indices + virtual std::vector GetInternalCountersRequired(gpa_uint32 index) = 0; + + /// Computes a public counter value pased on supplied results and hardware info + /// \param[in] counterIndex The public counter index to calculate + /// \param[in] results A vector of hardware counter results + /// \param[in] internalCounterTypes A vector of counter types + /// \param[inout] pResult The computed counter result + /// \param[in] pHwInfo Information about the hardware on which the result was generated + virtual void ComputePublicCounterValue(gpa_uint32 counterIndex, std::vector& results, std::vector& internalCounterTypes, void* pResult, GPA_HWInfo* pHwInfo) = 0; + + /// Gets the counter type information based on the global counter index + /// \param globalIndex The index into the main list of counters + /// \return The info about the counter + virtual GPACounterTypeInfo GetCounterTypeInfo(gpa_uint32 globalIndex) = 0; + + /// Gets a counter's index + /// \param pName The name of a counter + /// \param[out] pIndex The index of the counter + /// \return true if the counter is found, false otherwise + virtual bool GetCounterIndex(const char* pName, gpa_uint32* pIndex) = 0; +}; + +#endif //_GPA_I_COUNTER_ACCESSOR_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAICounterScheduler.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAICounterScheduler.h new file mode 100644 index 000000000..0d617e4d4 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPAICounterScheduler.h @@ -0,0 +1,102 @@ +//============================================================================== +// Copyright (c) 2012-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief An interface for scheduling counters in terms of enabling, disabling, and +/// obtaining the number of necessary passes. +//============================================================================== + +#ifndef _GPA_I_COUNTER_SCHEDULER_H_ +#define _GPA_I_COUNTER_SCHEDULER_H_ + +#include "GPAICounterAccessor.h" +#include "GPUPerfAPITypes.h" +#include +#include + + +typedef std::map CounterResultLocationMap; ///< typedef for map of Counter Result Locations + +/// An interface for enabling and disabling counters and getting the resulting number of necessary passes +class GPA_ICounterScheduler +{ +public: + + /// Reset the counter scheduler + virtual void Reset() = 0; + + /// Set the counter accessor that should be used when scheduling counters + /// \param pCounterAccessor The counter accessor + /// \param vendorId the vendor id of the GPU hardware + /// \param deviceId the device id of the GPU hardware + /// \param revisionId the revision id of the GPU hardware + /// \return GPA_STATUS_ERROR_NULL_POINTER If pCounterAccessor is nullptr + /// \return GPA_STATUS_OK + virtual GPA_Status SetCounterAccessor(GPA_ICounterAccessor* pCounterAccessor, gpa_uint32 vendorId, gpa_uint32 deviceId, gpa_uint32 revisionId) = 0; + + /// Enables a counter + /// \param index The index of a counter to enable + /// \return GPA_STATUS_OK on success + virtual GPA_Status EnableCounter(gpa_uint32 index) = 0; + + /// Disables a counter + /// \param index The index of a counter to disable + /// \return GPA_STATUS_OK on success + virtual GPA_Status DisableCounter(gpa_uint32 index) = 0; + + /// Disables all counters + virtual void DisableAllCounters() = 0; + + /// Get the number of enabled counters + virtual gpa_uint32 GetNumEnabledCounters() = 0; + + /// Gets the counter index of the specified enabled counter + /// \param enabledIndex the enabled counter whose counter index is needed + /// \param[out] pCounterAtIndex the counter index of the specified enabled counter + /// \return GPA_STATUS_OK on success + virtual GPA_Status GetEnabledIndex(gpa_uint32 enabledIndex, gpa_uint32* pCounterAtIndex) = 0; + + /// Checks if the specified counter is enabled + /// \param counterIndex the index of the counter to check + /// \return GPA_STATUS_OK if the counter is enabled + virtual GPA_Status IsCounterEnabled(gpa_uint32 counterIndex) = 0; + + /// Obtains the number of passes required to collect the enabled counters + /// \param[inout] pNumRequiredPassesOut Will contain the number of passes needed to collect the set of enabled counters + /// \return GPA_STATUS_OK on success + virtual GPA_Status GetNumRequiredPasses(gpa_uint32* pNumRequiredPassesOut) = 0; + + /// Get a flag indicating if the counter selection has changed + /// \return true if the counter selection has changed, false otherwise + virtual bool GetCounterSelectionChanged() = 0; + + /// Begin profiling -- sets pass index to zero + /// \return GPA_STATUS_OK on success + virtual GPA_Status BeginProfile() = 0; + + /// Begin a pass -- increments the pass index + virtual void BeginPass() = 0; + + /// Gets the counters for the specified pass + /// \param passIndex the pass whose counters are needed + /// \return a list of counters for the specified pass + virtual std::vector* GetCountersForPass(gpa_uint32 passIndex) = 0; + + /// End a pass + virtual void EndPass() = 0; + + /// End profiling + /// \return GPA_STATUS_OK on success + virtual GPA_Status EndProfile() = 0; + + /// Gets the counter result locations for the specified public counter + /// \param publicCounterIndex the counter index whose result locations are needed + /// \return a map of counter result locations + virtual CounterResultLocationMap* GetCounterResultLocations(unsigned int publicCounterIndex) = 0; + + /// Set draw call counts (internal support) + /// \param iCounts the count of draw calls + virtual void SetDrawCallCounts(const int iCounts) = 0; +}; + +#endif //_GPA_I_COUNTER_SCHEDULER_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-HSA.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-HSA.h new file mode 100644 index 000000000..f10dd1cf4 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-HSA.h @@ -0,0 +1,46 @@ +//============================================================================== +// Copyright (c) 2015-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief This file can be included by an application that wishes to use the HSA +/// version of GPUPerfAPI. It defines a structure that can be passed to the +/// GPA_OpenContext call when using GPUPerfAPI with HSA. +//============================================================================== + + +#ifndef _GPUPERFAPI_HSA_H_ +#define _GPUPERFAPI_HSA_H_ + +#include "GPUPerfAPITypes.h" +#include "GPUPerfAPI.h" + +#include "hsa.h" + +// NOTE: When using the HSA version of GPUPerfAPI, you can initialize and call +// GPUPerfAPI in one of two ways: +// 1) You must call GPA_Initialize prior to the application initializing +// the HSA runtime with a call to hsa_init. You can then simply pass +// in a hsa_queue_t* instance when calling GPA_OpenContext. When doing +// this, GPUPerfAPI will set up the HSA runtime correctly to use the +// AQL-emulation mode and the pre/post-dispatch callbacks. +// 2) You can perform all initialization yourself to ensure that AQL-emulation +// mode is used and the pre/post-dispatch callbacks are used. In that case, +// you can then call GPA_OpenContext with an instance of the below structure +// (whose members you would initialize with data provided by the pre-dispatch +// callback). Note: this second method is currently used by the CodeXL GPU +// Profiler, though in the future, it may be modified to use the first method. +// +// It is recommended to use the first method above when using GPUPerfAPI directly +// from an HSA application. + +/// an instance of this structure can be passed to GPA_OpenContext for the HSA +/// version of GPUPerfAPI. +typedef struct +{ + const hsa_agent_t* m_pAgent; ///< the agent + const hsa_queue_t* m_pQueue; ///< the queue + void* m_pAqlTranslationHandle; ///< the AQL translation handle (an opaque pointer) supplied by the pre-dispatch callback +} GPA_HSA_Context; + + +#endif // _GPUPERFAPI_HSA_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-Private.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-Private.h new file mode 100644 index 000000000..ab4809c64 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI-Private.h @@ -0,0 +1,49 @@ +//============================================================================== +// Copyright (c) 2009-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief Include this file rather than GPUPerfAPI.h for our internal usage. +//============================================================================== + +#ifndef _GPUPERFAPI_PRIVATE_H_ +#define _GPUPERFAPI_PRIVATE_H_ +#include "GPUPerfAPIOS.h" +#include "GPUPerfAPI.h" +#include "GPUPerfAPITypes-Private.h" +#include "GPUPerfAPIFunctionTypes-Private.h" + +// For internal use only + +// *INDENT-OFF* +#ifdef AMDT_INTERNAL +/// \brief Register a debug callback function to receive debug log messages. +/// +/// Only one debug callback function can be registered, so the implementation should be able +/// to handle the different types of messages. A parameter to the callback function will +/// indicate the message type being received. +/// \param loggingType Identifies the type of messages to receive callbacks for. +/// \param callbackFuncPtr Pointer to the callback function +/// \return GPA_STATUS_OK, unless the callbackFuncPtr is nullptr and the loggingType is not +/// GPA_LOGGING_NONE, in which case GPA_STATUS_ERROR_NULL_POINTER is returned. +GPALIB_DECL GPA_Status GPA_RegisterLoggingDebugCallback(GPA_Log_Debug_Type loggingType, GPA_LoggingDebugCallbackPtrType callbackFuncPtr); + +/// \brief Internal function. Pass draw call counts to GPA for internal purposes. +/// \param iCounts[in] the draw counts for the current frame +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_InternalSetDrawCallCounts(const int iCounts); + +#endif // AMDT_INTERNAL +// *INDENT-ON* + +/// \brief Internal function. Unsupported and may be removed from the API at any time. +/// +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_InternalProfileStart(); + +/// \brief Internal function. Unsupported and may be removed from the API at any time. +/// +/// \param pFilename the name of the file to write profile results +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_InternalProfileStop(const char* pFilename); + +#endif // _GPUPERFAPI_PRIVATE_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI.h new file mode 100644 index 000000000..09ec34dfb --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPI.h @@ -0,0 +1,389 @@ +//============================================================================== +// Copyright (c) 2010-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief This file is the only header that must be included by an application that +/// wishes to use GPUPerfAPI. It defines all the available entrypoints. +//============================================================================== + +#ifndef _GPUPERFAPI_H_ +#define _GPUPERFAPI_H_ + +#ifndef GPALIB_DECL + /// macro for exporting an API function + #ifdef _WIN32 + #ifdef __cplusplus + #define GPALIB_DECL extern "C" __declspec( dllimport ) + #else + #define GPALIB_DECL __declspec( dllimport ) + #endif + #else //__linux__ + #ifdef __cplusplus + #define GPALIB_DECL extern "C" + #else + #define GPALIB_DECL extern + #endif + #endif +#endif + +#include +#include "GPUPerfAPITypes.h" +#include "GPUPerfAPIFunctionTypes.h" + +/// \brief Register a callback function to receive log messages. +/// +/// Only one callback function can be registered, so the implementation should be able +/// to handle the different types of messages. A parameter to the callback function will +/// indicate the message type being received. Messages will not contain a newline character +/// at the end of the message. +/// \param loggingType Identifies the type of messages to receive callbacks for. +/// \param pCallbackFuncPtr Pointer to the callback function +/// \return GPA_STATUS_OK, unless the callbackFuncPtr is nullptr and the loggingType is not +/// GPA_LOGGING_NONE, in which case GPA_STATUS_ERROR_NULL_POINTER is returned. +GPALIB_DECL GPA_Status GPA_RegisterLoggingCallback(GPA_Logging_Type loggingType, GPA_LoggingCallbackPtrType pCallbackFuncPtr); + +// Init / destroy GPA + +/// \brief Initializes the driver so that counters are exposed. +/// +/// This function must be called before the rendering context or device is created. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_Initialize(); + +/// \brief Undo any initialization to ensure proper behavior in applications that are not being profiled. +/// +/// This function must be called after the rendering context or device is released / destroyed. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_Destroy(); + +// Context Startup / Finish + +/// \brief Opens the counters in the specified context for reading. +/// +/// This function must be called before any other GPA functions. +/// \param pContext The context to open counters for. Typically a device pointer. Refer to GPA API specific documentation for further details. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_OpenContext(void* pContext); + +/// \brief Closes the counters in the currently active context. +/// +/// GPA functions should not be called again until the counters are reopened with GPA_OpenContext. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_CloseContext(); + +/// \brief Select another context to be the currently active context. +/// +/// The selected context must have previously been opened with a call to GPA_OpenContext. +/// If the call is successful, all GPA functions will act on the currently selected context. +/// \param pContext The context to select. The same value that was passed to GPA_OpenContext. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_SelectContext(void* pContext); + + +// Counter Interrogation + +/// \brief Get the number of counters available. +/// +/// \param pCount The value which will hold the count upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetNumCounters(gpa_uint32* pCount); + +/// \brief Get the name of a specific counter. +/// +/// \param index The index of the counter name to query. Must lie between 0 and (GPA_GetNumCounters result - 1). +/// \param ppName The value which will hold the name upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetCounterName(gpa_uint32 index, const char** ppName); + +/// \brief Get description of the specified counter. +/// +/// \param index The index of the counter to query. Must lie between 0 and (GPA_GetNumCounters result - 1). +/// \param ppDescription The value which will hold the description upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetCounterDescription(gpa_uint32 index, const char** ppDescription); + +/// \brief Get the counter data type of the specified counter. +/// +/// \param index The index of the counter. Must lie between 0 and (GPA_GetNumCounters result - 1). +/// \param pCounterDataType The value which will hold the description upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetCounterDataType(gpa_uint32 index, GPA_Type* pCounterDataType); + +/// \brief Get the counter usage type of the specified counter. +/// +/// \param index The index of the counter. Must lie between 0 and (GPA_GetNumCounters result - 1). +/// \param pCounterUsageType The value which will hold the description upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetCounterUsageType(gpa_uint32 index, GPA_Usage_Type* pCounterUsageType); + +/// \brief Get a string with the name of the specified counter data type. +/// +/// Typically used to display counter types along with their name. +/// E.g. counterDataType of GPA_TYPE_UINT64 would return "gpa_uint64". +/// \param counterDataType The type to get the string for. +/// \param ppTypeStr The value that will be set to contain a reference to the name of the counter data type. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetDataTypeAsStr(GPA_Type counterDataType, const char** ppTypeStr); + +/// \brief Get a string with the name of the specified counter usage type. +/// +/// Converts the counter usage type to a string representation. +/// E.g. counterUsageType of GPA_USAGE_TYPE_PERCENTAGE would return "percentage". +/// \param counterUsageType The type to get the string for. +/// \param ppUsageTypeStr The value that will be set to contain a reference to the name of the counter usage type. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetUsageTypeAsStr(GPA_Usage_Type counterUsageType, const char** ppUsageTypeStr); + +/// \brief Enable a specified counter. +/// +/// Subsequent sampling sessions will provide values for any enabled counters. +/// Initially all counters are disabled, and must explicitly be enabled by calling this function. +/// \param index The index of the counter to enable. Must lie between 0 and (GPA_GetNumCounters result - 1). +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_EnableCounter(gpa_uint32 index); + + +/// \brief Disable a specified counter. +/// +/// Subsequent sampling sessions will not provide values for any disabled counters. +/// Initially all counters are disabled, and must explicitly be enabled. +/// \param index The index of the counter to enable. Must lie between 0 and (GPA_GetNumCounters result - 1). +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_DisableCounter(gpa_uint32 index); + + +/// \brief Get the number of enabled counters. +/// +/// \param pCount The value that will be set to the number of counters that are currently enabled. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetEnabledCount(gpa_uint32* pCount); + + +/// \brief Get the counter index for an enabled counter. +/// +/// For example, if GPA_GetEnabledIndex returns 3, and I wanted the counter index of the first enabled counter, +/// I would call this function with enabledNumber equal to 0. +/// \param enabledNumber The number of the enabled counter to get the counter index for. Must lie between 0 and (GPA_GetEnabledIndex result - 1). +/// \param pEnabledCounterIndex The value that will contain the index of the counter. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetEnabledIndex(gpa_uint32 enabledNumber, gpa_uint32* pEnabledCounterIndex); + + +/// \brief Check that a counter is enabled. +/// +/// \param counterIndex The index of the counter. Must lie between 0 and (GPA_GetNumCounters result - 1). +/// \return GPA_STATUS_OK is returned if the counter is enabled, GPA_STATUS_ERROR_NOT_FOUND otherwise. +GPALIB_DECL GPA_Status GPA_IsCounterEnabled(gpa_uint32 counterIndex); + + +/// \brief Enable a specified counter using the counter name (case insensitive). +/// +/// Subsequent sampling sessions will provide values for any enabled counters. +/// Initially all counters are disabled, and must explicitly be enabled by calling this function. +/// \param pCounter The name of the counter to enable. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_EnableCounterStr(const char* pCounter); + + +/// \brief Disable a specified counter using the counter name (case insensitive). +/// +/// Subsequent sampling sessions will not provide values for any disabled counters. +/// Initially all counters are disabled, and must explicitly be enabled. +/// \param pCounter The name of the counter to disable. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_DisableCounterStr(const char* pCounter); + + +/// \brief Enable all counters. +/// +/// Subsequent sampling sessions will provide values for all counters. +/// Initially all counters are disabled, and must explicitly be enabled by calling a function which enables them. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_EnableAllCounters(); + + +/// \brief Disable all counters. +/// +/// Subsequent sampling sessions will not provide values for any disabled counters. +/// Initially all counters are disabled, and must explicitly be enabled. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_DisableAllCounters(); + + +/// \brief Get index of a counter given its name (case insensitive). +/// +/// \param pCounter The name of the counter to get the index for. +/// \param pIndex The index of the requested counter. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetCounterIndex(const char* pCounter, gpa_uint32* pIndex); + + +/// \brief Get the number of passes required for the currently enabled set of counters. +/// +/// This represents the number of times the same sequence must be repeated to capture the counter data. +/// On each pass a different (compatible) set of counters will be measured. +/// \param pNumPasses The value of the number of passes. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetPassCount(gpa_uint32* pNumPasses); + + +/// \brief Begin sampling with the currently enabled set of counters. +/// +/// This must be called to begin the counter sampling process. +/// A unique sessionID will be returned which is later used to retrieve the counter values. +/// Session Identifiers are integers and always start from 1 on a newly opened context, upwards in sequence. +/// The set of enabled counters cannot be changed inside a BeginSession/EndSession sequence. +/// \param pSessionID The value that will be set to the session identifier. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_BeginSession(gpa_uint32* pSessionID); + + +/// \brief End sampling with the currently enabled set of counters. +/// +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_EndSession(); + + +/// \brief Begin sampling pass. +/// +/// Between BeginPass and EndPass calls it is expected that a sequence of repeatable operations exist. +/// If this is not the case only counters which execute in a single pass should be activated. +/// The number of required passes can be determined by enabling a set of counters and then calling GPA_GetPassCount. +/// The operations inside the BeginPass/EndPass calls should be looped over GPA_GetPassCount result number of times. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_BeginPass(); + + +/// \brief End sampling pass. +/// +/// Between BeginPass and EndPass calls it is expected that a sequence of repeatable operations exist. +/// If this is not the case only counters which execute in a single pass should be activated. +/// The number of required passes can be determined by enabling a set of counters and then calling GPA_GetPassCount. +/// The operations inside the BeginPass/EndPass calls should be looped over GPA_GetPassCount result number of times. +/// This is necessary to capture all counter values, since sometimes counter combinations cannot be captured simultaneously. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_EndPass(); + + +/// \brief Begin a sample using the enabled counters. +/// +/// Multiple samples can be performed inside a BeginSession/EndSession sequence. +/// Each sample computes the values of the counters between BeginSample and EndSample. +/// To identify each sample the user must provide a unique sampleID as a parameter to this function. +/// The number need only be unique within the same BeginSession/EndSession sequence. +/// BeginSample must be followed by a call to EndSample before BeginSample is called again. +/// \param sampleID Any integer, unique within the BeginSession/EndSession sequence, used to retrieve the sample results. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_BeginSample(gpa_uint32 sampleID); + + +/// \brief End sampling using the enabled counters. +/// +/// BeginSample must be followed by a call to EndSample before BeginSample is called again. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_EndSample(); + + +/// \brief Get the number of samples a specified session contains. +/// +/// This is useful if samples are conditionally created and a count is not kept. +/// \param sessionID The session to get the number of samples for. +/// \param pSamples The value that will be set to the number of samples contained within the session. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetSampleCount(gpa_uint32 sessionID, gpa_uint32* pSamples); + + +/// \brief Determine if an individual sample result is available. +/// +/// After a sampling session results may be available immediately or take a certain amount of time to become available. +/// This function allows you to determine when a sample can be read. +/// The function does not block, permitting periodic polling. +/// To block until a sample is ready use a GetSample* function instead of this. +/// It can be more efficient to determine if a whole session's worth of data is available using GPA_IsSessionReady. +/// \param pReadyResult The value that will contain the result of the sample being ready. True if ready. +/// \param sessionID The session containing the sample to determine availability. +/// \param sampleID The sample identifier of the sample to query availability for. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_IsSampleReady(bool* pReadyResult, gpa_uint32 sessionID, gpa_uint32 sampleID); + + +/// \brief Determine if all samples within a session are available. +/// +/// After a sampling session results may be available immediately or take a certain amount of time to become available. +/// This function allows you to determine when the results of a session can be read. +/// The function does not block, permitting periodic polling. +/// To block until a sample is ready use a GetSample* function instead of this. +/// \param pReadyResult The value that will contain the result of the session being ready. True if ready. +/// \param sessionID The session to determine availability for. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_IsSessionReady(bool* pReadyResult, gpa_uint32 sessionID); + + +/// \brief Get a sample of type 64-bit unsigned integer. +/// +/// This function will block until the value is available. +/// Use GPA_IsSampleReady if you do not wish to block. +/// \param sessionID The session identifier with the sample you wish to retrieve the result of. +/// \param sampleID The identifier of the sample to get the result for. +/// \param counterID The counter index to get the result for. +/// \param pResult The value which will contain the counter result upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetSampleUInt64(gpa_uint32 sessionID, gpa_uint32 sampleID, gpa_uint32 counterID, gpa_uint64* pResult); + + +/// \brief Get a sample of type 32-bit unsigned integer. +/// +/// This function will block until the value is available. +/// Use GPA_IsSampleReady if you do not wish to block. +/// \param sessionID The session identifier with the sample you wish to retrieve the result of. +/// \param sampleID The identifier of the sample to get the result for. +/// \param counterIndex The counter index to get the result for. +/// \param pResult The value which will contain the counter result upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetSampleUInt32(gpa_uint32 sessionID, gpa_uint32 sampleID, gpa_uint32 counterIndex, gpa_uint32* pResult); + + +/// \brief Get a sample of type 64-bit float. +/// +/// This function will block until the value is available. +/// Use GPA_IsSampleReady if you do not wish to block. +/// \param sessionID The session identifier with the sample you wish to retrieve the result of. +/// \param sampleID The identifier of the sample to get the result for. +/// \param counterIndex The counter index to get the result for. +/// \param pResult The value which will contain the counter result upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetSampleFloat64(gpa_uint32 sessionID, gpa_uint32 sampleID, gpa_uint32 counterIndex, gpa_float64* pResult); + + +/// \brief Get a sample of type 32-bit float. +/// +/// This function will block until the value is available. +/// Use GPA_IsSampleReady if you do not wish to block. +/// \param sessionID The session identifier with the sample you wish to retrieve the result of. +/// \param sampleID The identifier of the sample to get the result for. +/// \param counterIndex The counter index to get the result for. +/// \param pResult The value which will contain the counter result upon successful execution. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetSampleFloat32(gpa_uint32 sessionID, gpa_uint32 sampleID, gpa_uint32 counterIndex, gpa_float32* pResult); + + +/// \brief Get a string translation of a GPA status value. +/// +/// Provides a simple method to convert a status enum value into a string which can be used to display log messages. +/// \param status The status to convert into a string. +/// \return A string which describes the supplied status. +GPALIB_DECL const char* GPA_GetStatusAsStr(GPA_Status status); + +/// \brief Get the GPU device id associated with the current context +/// +/// \param deviceID The value that will be set to the device id. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetDeviceID(gpa_uint32* deviceID); + +/// \brief Get the GPU device description associated with the current context +/// +/// \param ppDesc The value that will be set to the device description. +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPALIB_DECL GPA_Status GPA_GetDeviceDesc(const char** ppDesc); + +#endif // _GPUPERFAPI_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPICounters.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPICounters.h new file mode 100644 index 000000000..f7cf45a22 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPICounters.h @@ -0,0 +1,45 @@ +//============================================================================== +// Copyright (c) 2012-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief Implements a library that allows access to the available counters in GPUPerfAPI. +//============================================================================== + +#ifndef _GPUPERFAPI_COUNTERS_H_ +#define _GPUPERFAPI_COUNTERS_H_ + +#include "GPUPerfAPITypes-Private.h" +#include "GPAICounterAccessor.h" +#include "GPAICounterScheduler.h" + +/// macro to export public API functions +#ifndef GPUPERFAPI_COUNTERS_DECL + #ifdef _WIN32 + #ifdef __cplusplus + #define GPUPERFAPI_COUNTERS_DECL extern "C" __declspec( dllimport ) + #else + #define GPUPERFAPI_COUNTERS_DECL __declspec( dllimport ) + #endif + #else //_LINUX + #define GPUPERFAPI_COUNTERS_DECL extern + #endif +#endif + +/// Entrypoint to get the available counters +/// \param api the api whose available counters are requested +/// \param vendorId the vendor id of the device whose available counters are requested +/// \param deviceId the device id of the device whose available counters are requested +/// \param revisionId the revision id of the device whose available counters are requested +/// \param[out] ppCounterAccessorOut the accessor that will provide the counters +/// \param[out] ppCounterSchedulerOut the scheduler that will provide the counters +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPUPERFAPI_COUNTERS_DECL GPA_Status GPA_GetAvailableCounters(GPA_API_Type api, gpa_uint32 vendorId, gpa_uint32 deviceId, gpa_uint32 revisionId, GPA_ICounterAccessor** ppCounterAccessorOut, GPA_ICounterScheduler** ppCounterSchedulerOut); + +/// Entrypoint to get the available counters by hardware generation +/// \param api the api whose available counters are requested +/// \param generation the hardware generation whose available counters are requested +/// \param[out] ppCounterAccessorOut the accessor that will provide the counters +/// \return The GPA result status of the operation. GPA_STATUS_OK is returned if the operation is successful. +GPUPERFAPI_COUNTERS_DECL GPA_Status GPA_GetAvailableCountersByGeneration(GPA_API_Type api, GPA_HW_GENERATION generation, GPA_ICounterAccessor** ppCounterAccessorOut); + +#endif // _GPUPERFAPI_COUNTERS_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes-Private.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes-Private.h new file mode 100644 index 000000000..8af1338a5 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes-Private.h @@ -0,0 +1,33 @@ +//============================================================================== +// Copyright (c) 2010-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief This file is for internal use to define the function types. +//============================================================================== + +#ifndef _GPUPERFAPI_FUNCTION_TYPES_INTERNAL_H_ +#define _GPUPERFAPI_FUNCTION_TYPES_INTERNAL_H_ + +#include "GPUPerfAPIFunctionTypes.h" + +/// Typedef for a function pointer for a function to enable counters from a file +typedef GPA_Status(*GPA_EnableCountersFromFilePtrType)(const char* pFile, gpa_uint32* pCountersRead); + +/// Typedef for a function pointer for a debug logging callback +typedef void(*GPA_LoggingDebugCallbackPtrType)(GPA_Log_Debug_Type messageType, const char* pMessage); + +/// Typedef for a function pointer for a function to register a debug logging callback +typedef GPA_Status(*GPA_RegisterLoggingDebugCallbackPtrType)(GPA_Log_Debug_Type loggingType, GPA_LoggingDebugCallbackPtrType pCallbackFuncPtr); + + +/// Typedef for a function pointer for a function to start profiling a GPA function +typedef GPA_Status(*GPA_InternalProfileStartPtrType)(); + +/// Typedef for a function pointer for a function to stop profiling a GPA function +typedef GPA_Status(*GPA_InternalProfileStopPtrType)(const char* pFilename); + +/// Typedef for a function pointer for a function to set the number of draw calls in a frame +/// For internal purposes only -- not needed for normal operation of GPUPerfAPI +typedef GPA_Status(*GPA_InternalSetDrawCallCountsPtrType)(const int iCounts); + +#endif // _GPUPERFAPI_FUNCTION_TYPES_INTERNAL_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes.h new file mode 100644 index 000000000..101418845 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPIFunctionTypes.h @@ -0,0 +1,76 @@ +//============================================================================== +// Copyright (c) 2010-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief This file defines function types to make it easier to dynamically load +/// different GPUPerfAPI DLLs into an application that supports multiple APIs. +/// Applications which statically link to GPUPerfAPI do not need to include +/// this file. +//============================================================================== + +#ifndef _GPUPERFAPI_FUNCTION_TYPES_H_ +#define _GPUPERFAPI_FUNCTION_TYPES_H_ + +#include "GPUPerfAPITypes.h" + +typedef void(*GPA_LoggingCallbackPtrType)(GPA_Logging_Type messageType, const char* pMessage); ///< Typedef for a function pointer for a logging callback function + +typedef GPA_Status(*GPA_RegisterLoggingCallbackPtrType)(GPA_Logging_Type loggingType, GPA_LoggingCallbackPtrType pCallbackFuncPtr); ///< Typedef for a function pointer for GPA_RegisterLoggingCallback + +// Startup / exit +typedef GPA_Status(*GPA_InitializePtrType)(); ///< Typedef for a function pointer for GPA_Initialize +typedef GPA_Status(*GPA_DestroyPtrType)(); ///< Typedef for a function pointer for GPA_Destroy + +// Context +typedef GPA_Status(*GPA_OpenContextPtrType)(void* pContext); ///< Typedef for a function pointer for GPA_OpenContext +typedef GPA_Status(*GPA_CloseContextPtrType)(); ///< Typedef for a function pointer for GPA_CloseContext +typedef GPA_Status(*GPA_SelectContextPtrType)(void* pCcontext); ///< Typedef for a function pointer for GPA_SelectContext + +// Counter Interrogation +typedef GPA_Status(*GPA_GetNumCountersPtrType)(gpa_uint32* pCount); ///< Typedef for a function pointer for GPA_GetNumCounters +typedef GPA_Status(*GPA_GetCounterNamePtrType)(gpa_uint32 index, const char** ppName); ///< Typedef for a function pointer for GPA_GetCounterName +typedef GPA_Status(*GPA_GetCounterDescriptionPtrType)(gpa_uint32 index, const char** ppDescription); ///< Typedef for a function pointer for GPA_GetCounterDescription +typedef GPA_Status(*GPA_GetCounterDataTypePtrType)(gpa_uint32 index, GPA_Type* pCounterDataType); ///< Typedef for a function pointer for GPA_GetCounterDataType +typedef GPA_Status(*GPA_GetCounterUsageTypePtrType)(gpa_uint32 index, GPA_Usage_Type* pCounterUsageType); ///< Typedef for a function pointer for GPA_GetCounterUsageType +typedef GPA_Status(*GPA_GetDataTypeAsStrPtrType)(GPA_Type counterDataType, const char** ppTypeStr); ///< Typedef for a function pointer for GPA_GetDataTypeAsStr +typedef GPA_Status(*GPA_GetUsageTypeAsStrPtrType)(GPA_Usage_Type counterUsageType, const char** ppTypeStr); ///< Typedef for a function pointer for GPA_GetUsageTypeAsStr +typedef const char* (*GPA_GetStatusAsStrPtrType)(GPA_Status status); ///< Typedef for a function pointer for GPA_GetStatusAsStr + +typedef GPA_Status(*GPA_EnableCounterPtrType)(gpa_uint32 index); ///< Typedef for a function pointer for GPA_EnableCounter +typedef GPA_Status(*GPA_DisableCounterPtrType)(gpa_uint32 index); ///< Typedef for a function pointer for GPA_DisableCounter +typedef GPA_Status(*GPA_GetEnabledCountPtrType)(gpa_uint32* pCount); ///< Typedef for a function pointer for GPA_GetEnabledCount +typedef GPA_Status(*GPA_GetEnabledIndexPtrType)(gpa_uint32 enabledNumber, gpa_uint32* pEnabledCounterIndex); ///< Typedef for a function pointer for GPA_GetEnabledIndex + +typedef GPA_Status(*GPA_IsCounterEnabledPtrType)(gpa_uint32 counterIndex); ///< Typedef for a function pointer for GPA_IsCounterEnabled + +typedef GPA_Status(*GPA_EnableCounterStrPtrType)(const char* pCounter); ///< Typedef for a function pointer for GPA_EnableCounterStr +typedef GPA_Status(*GPA_DisableCounterStrPtrType)(const char* pCounter); ///< Typedef for a function pointer for GPA_DisableCounterStr + +typedef GPA_Status(*GPA_EnableAllCountersPtrType)(); ///< Typedef for a function pointer for GPA_EnableAllCounters +typedef GPA_Status(*GPA_DisableAllCountersPtrType)(); ///< Typedef for a function pointer for GPA_DisableAllCounters +typedef GPA_Status(*GPA_GetCounterIndexPtrType)(const char* pCounter, gpa_uint32* pIndex); ///< Typedef for a function pointer for GPA_GetCounterIndex + +typedef GPA_Status(*GPA_GetPassCountPtrType)(gpa_uint32* pNumPasses); ///< Typedef for a function pointer for GPA_GetPassCount + +typedef GPA_Status(*GPA_BeginSessionPtrType)(gpa_uint32* pSessionID); ///< Typedef for a function pointer for GPA_BeginSession +typedef GPA_Status(*GPA_EndSessionPtrType)(); ///< Typedef for a function pointer for GPA_EndSession + +typedef GPA_Status(*GPA_BeginPassPtrType)(); ///< Typedef for a function pointer for GPA_BeginPass +typedef GPA_Status(*GPA_EndPassPtrType)(); ///< Typedef for a function pointer for GPA_EndPass + +typedef GPA_Status(*GPA_BeginSamplePtrType)(gpa_uint32 sampleID); ///< Typedef for a function pointer for GPA_BeginSample +typedef GPA_Status(*GPA_EndSamplePtrType)(); ///< Typedef for a function pointer for GPA_EndSample + +typedef GPA_Status(*GPA_GetSampleCountPtrType)(gpa_uint32 sessionID, gpa_uint32* pSamples); ///< Typedef for a function pointer for GPA_GetSampleCount + +typedef GPA_Status(*GPA_IsSampleReadyPtrType)(bool* pReadyResult, gpa_uint32 sessionID, gpa_uint32 sampleID); ///< Typedef for a function pointer for GPA_IsSampleReady +typedef GPA_Status(*GPA_IsSessionReadyPtrType)(bool* pReadyResult, gpa_uint32 sessionID); ///< Typedef for a function pointer for GPA_IsSessionReady +typedef GPA_Status(*GPA_GetSampleUInt64PtrType)(gpa_uint32 sessionID, gpa_uint32 sampleID, gpa_uint32 counterID, gpa_uint64* pResult); ///< Typedef for a function pointer for GPA_GetSampleUInt64 +typedef GPA_Status(*GPA_GetSampleUInt32PtrType)(gpa_uint32 sessionID, gpa_uint32 sampleID, gpa_uint32 counterIndex, gpa_uint32* pResult); ///< Typedef for a function pointer for GPA_GetSampleUInt32 +typedef GPA_Status(*GPA_GetSampleFloat32PtrType)(gpa_uint32 sessionID, gpa_uint32 sampleID, gpa_uint32 counterIndex, gpa_float32* pResult); ///< Typedef for a function pointer for GPA_GetSampleFloat32 +typedef GPA_Status(*GPA_GetSampleFloat64PtrType)(gpa_uint32 sessionID, gpa_uint32 sampleID, gpa_uint32 counterIndex, gpa_float64* pResult); ///< Typedef for a function pointer for GPA_GetSampleFloat64 + +typedef GPA_Status(*GPA_GetDeviceIDPtrType)(gpa_uint32* pDeviceID); ///< Typedef for a function pointer for GPA_GetDeviceID +typedef GPA_Status(*GPA_GetDeviceDescPtrType)(const char** ppDesc); ///< Typedef for a function pointer for GPA_GetDeviceDesc + +#endif // _GPUPERFAPI_FUNCTION_TYPES_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPITypes-Private.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPITypes-Private.h new file mode 100644 index 000000000..29fd625f3 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPITypes-Private.h @@ -0,0 +1,61 @@ +//============================================================================== +// Copyright (c) 2010-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief This file is for internal use to define the function types. +//============================================================================== + +#ifndef _GPUPERFAPI_TYPES_INTERNAL_H_ +#define _GPUPERFAPI_TYPES_INTERNAL_H_ + +#include "GPUPerfAPITypes.h" + +// For internal use only + +/// Counter type definitions +typedef enum +{ + GPA_COUNTER_TYPE_DYNAMIC, ///< hardware per sample counter type + GPA_COUNTER_TYPE_SESSION, ///< hardware per session counter type + GPA_COUNTER_TYPE_API_DYNAMIC, ///< api per sample counter type + GPA_COUNTER_TYPE_API_SESSION, ///< api per session counter + GPA_COUNTER_TYPE__LAST ///< Marker indicating last element +} GPA_CounterType; + +/// Private Logging types that adds messages defined in Debug Builds only +enum GPA_Log_Debug_Type +{ + // these must match the public GPA_Logging_type enum (but note we change LOGGING to LOG) + GPA_LOG_NONE = 0, + GPA_LOG_ERROR = 1, + GPA_LOG_MESSAGE = 2, + GPA_LOG_ERROR_AND_MESSAGE = 3, + GPA_LOG_TRACE = 4, + GPA_LOG_ERROR_AND_TRACE = 5, + GPA_LOG_MESSAGE_AND_TRACE = 6, + GPA_LOG_ERROR_MESSAGE_AND_TRACE = 7, + GPA_LOG_ALL = 0xFF, + +#ifdef AMDT_INTERNAL + // these are private types that are only defined in internal builds + GPA_LOG_DEBUG_ERROR = 0x0100, + GPA_LOG_DEBUG_MESSAGE = 0x0200, + GPA_LOG_DEBUG_TRACE = 0x0400, + GPA_LOG_DEBUG_COUNTERDEFS = 0x0800, + GPA_LOG_DEBUG_ALL = 0xFF00 +#endif // AMDT_INTERNAL +}; + +/// this enum needs to be kept up to date with GDT_HW_GENERATION in DeviceInfo.h +enum GPA_HW_GENERATION +{ + GPA_HW_GENERATION_NONE, ///< undefined hw generation + GPA_HW_GENERATION_NVIDIA, ///< Used for nvidia cards by GPA + GPA_HW_GENERATION_INTEL, ///< Used for Intel cards by GPA + GPA_HW_GENERATION_SOUTHERNISLAND, ///< GFX IP 6 + GPA_HW_GENERATION_SEAISLAND, ///< GFX IP 7 + GPA_HW_GENERATION_VOLCANICISLAND, ///< GFX IP 8 + GPA_HW_GENERATION_LAST +}; + +#endif // _GPUPERFAPI_TYPES_INTERNAL_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPITypes.h b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPITypes.h new file mode 100644 index 000000000..8faef9dac --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/Include/GPUPerfAPITypes.h @@ -0,0 +1,177 @@ +//============================================================================== +// Copyright (c) 2010-2016 Advanced Micro Devices, Inc. All rights reserved. +/// \author AMD Developer Tools Team +/// \file +/// \brief Defines the data types and enumerations used by GPUPerfAPI. +/// This file does not need to be directly included by an application +/// that uses GPUPerfAPI. +//============================================================================== + +#ifndef _GPUPERFAPI_TYPES_H_ +#define _GPUPERFAPI_TYPES_H_ + +#include + +// Type definitions +#ifdef _WIN32 + typedef char gpa_int8; + typedef short gpa_int16; + typedef int gpa_int32; + typedef __int64 gpa_int64; + typedef float gpa_float32; + typedef double gpa_float64; + typedef unsigned char gpa_uint8; + typedef unsigned short gpa_uint16; + typedef unsigned int gpa_uint32; + typedef unsigned __int64 gpa_uint64; + #ifndef __cplusplus + typedef gpa_uint8 bool; + #endif +#endif // _WIN32 + +#ifdef __linux__ + + #ifdef GPALIB_DECL + #else + #ifdef __cplusplus + #define GPALIB_DECL extern "C" + #else + #define GPALIB_DECL + #endif // _cplusplus + #endif + + typedef char gpa_int8; + typedef short gpa_int16; + typedef int gpa_int32; + typedef long long gpa_int64; + typedef unsigned int UINT; + typedef float gpa_float32; + typedef double gpa_float64; + typedef unsigned char gpa_uint8; + typedef unsigned short gpa_uint16; + typedef unsigned int gpa_uint32; + typedef unsigned long long gpa_uint64; + #ifndef __cplusplus + typedef gpa_uint8 bool; + #endif + + #define UNREFERENCED_PARAMETER(x) + #define UNREFERECED_VAR(x) + + #define _strcmpi(a, b) strcasecmp(a, b) + + // for now, just use non secure version for Linux + #define strcpy_s(dst, ndst, src) strcpy(dst, src) + #define strtok_s(a, b, c) strtok(a, b) + +#endif // __linux__ + +// Limit definitions +/// macro for max int8 +#define GPA_INT8_MAX SCHAR_MAX +/// macro for max int16 +#define GPA_INT16_MAX SHRT_MAX +/// macro for max int32 +#define GPA_INT32_MAX INT_MAX +/// macro for max int64 +#define GPA_INT64_MAX LLONG_MAX + +/// macro for max uint8 +#define GPA_UINT8_MAX UCHAR_MAX +/// macro for max uint16 +#define GPA_UINT16_MAX USHRT_MAX +/// macro for max uint32 +#define GPA_UINT32_MAX UINT_MAX +/// macro for max uint64 +#define GPA_UINT64_MAX ULLONG_MAX + +/// Status enumerations +typedef enum +{ + GPA_STATUS_OK = 0, + GPA_STATUS_ERROR_NULL_POINTER, + GPA_STATUS_ERROR_COUNTERS_NOT_OPEN, + GPA_STATUS_ERROR_COUNTERS_ALREADY_OPEN, + GPA_STATUS_ERROR_INDEX_OUT_OF_RANGE, + GPA_STATUS_ERROR_NOT_FOUND, + GPA_STATUS_ERROR_ALREADY_ENABLED, + GPA_STATUS_ERROR_NO_COUNTERS_ENABLED, + GPA_STATUS_ERROR_NOT_ENABLED, + GPA_STATUS_ERROR_SAMPLING_NOT_STARTED, + GPA_STATUS_ERROR_SAMPLING_ALREADY_STARTED, + GPA_STATUS_ERROR_SAMPLING_NOT_ENDED, + GPA_STATUS_ERROR_NOT_ENOUGH_PASSES, + GPA_STATUS_ERROR_PASS_NOT_ENDED, + GPA_STATUS_ERROR_PASS_NOT_STARTED, + GPA_STATUS_ERROR_PASS_ALREADY_STARTED, + GPA_STATUS_ERROR_SAMPLE_NOT_STARTED, + GPA_STATUS_ERROR_SAMPLE_ALREADY_STARTED, + GPA_STATUS_ERROR_SAMPLE_NOT_ENDED, + GPA_STATUS_ERROR_CANNOT_CHANGE_COUNTERS_WHEN_SAMPLING, + GPA_STATUS_ERROR_SESSION_NOT_FOUND, + GPA_STATUS_ERROR_SAMPLE_NOT_FOUND, + GPA_STATUS_ERROR_SAMPLE_NOT_FOUND_IN_ALL_PASSES, + GPA_STATUS_ERROR_COUNTER_NOT_OF_SPECIFIED_TYPE, + GPA_STATUS_ERROR_READING_COUNTER_RESULT, + GPA_STATUS_ERROR_VARIABLE_NUMBER_OF_SAMPLES_IN_PASSES, + GPA_STATUS_ERROR_FAILED, + GPA_STATUS_ERROR_HARDWARE_NOT_SUPPORTED, + GPA_STATUS_ERROR_DRIVER_NOT_SUPPORTED, + + // following are status codes used internally within GPUPerfAPI + GPA_STATUS_INTERNAL = 256, + GPA_STATUS_OK_HANDLED = GPA_STATUS_INTERNAL, +} GPA_Status; + +/// Value type definitions +typedef enum +{ + GPA_TYPE_FLOAT32, ///< Result will be a 32-bit float + GPA_TYPE_FLOAT64, ///< Result will be a 64-bit float + GPA_TYPE_UINT32, ///< Result will be a 32-bit unsigned int + GPA_TYPE_UINT64, ///< Result will be a 64-bit unsigned int + GPA_TYPE_INT32, ///< Result will be a 32-bit int + GPA_TYPE_INT64, ///< Result will be a 64-bit int + GPA_TYPE__LAST ///< Marker indicating last element +} GPA_Type; + +/// Result usage type definitions +typedef enum +{ + GPA_USAGE_TYPE_RATIO, ///< Result is a ratio of two different values or types + GPA_USAGE_TYPE_PERCENTAGE, ///< Result is a percentage, typically within [0,100] range, but may be higher for certain counters + GPA_USAGE_TYPE_CYCLES, ///< Result is in clock cycles + GPA_USAGE_TYPE_MILLISECONDS, ///< Result is in milliseconds + GPA_USAGE_TYPE_BYTES, ///< Result is in bytes + GPA_USAGE_TYPE_ITEMS, ///< Result is a count of items or objects (ie, vertices, triangles, threads, pixels, texels, etc) + GPA_USAGE_TYPE_KILOBYTES, ///< Result is in kilobytes + GPA_USAGE_TYPE__LAST ///< Marker indicating last element +} GPA_Usage_Type; + +/// Logging type definitions +typedef enum +{ + GPA_LOGGING_NONE = 0, + GPA_LOGGING_ERROR = 1, + GPA_LOGGING_MESSAGE = 2, + GPA_LOGGING_ERROR_AND_MESSAGE = 3, + GPA_LOGGING_TRACE = 4, + GPA_LOGGING_ERROR_AND_TRACE = 5, + GPA_LOGGING_MESSAGE_AND_TRACE = 6, + GPA_LOGGING_ERROR_MESSAGE_AND_TRACE = 7, + GPA_LOGGING_ALL = 0xFF +} GPA_Logging_Type; + +/// APIs Supported (either publicly or internally) by GPUPerfAPI +typedef enum +{ + GPA_API_DIRECTX_11, + GPA_API_DIRECTX_12, + GPA_API_OPENGL, + GPA_API_OPENGLES, + GPA_API_OPENCL, + GPA_API_HSA, + GPA_API__LAST +} GPA_API_Type; + +#endif // _GPUPERFAPI_TYPES_H_ diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/LICENSE b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/LICENSE new file mode 100644 index 000000000..80c45f1ec --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved. + +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. diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/thirdpartylicenses.txt b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/thirdpartylicenses.txt new file mode 100644 index 000000000..7419e2db2 --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/thirdpartylicenses.txt @@ -0,0 +1,42 @@ +Third-party licenses, acknowledgements +====================================== + +GPUPerfAPI uses the following third-party software: + +OpenCL +------ + +Copyright (c) 2008-2012 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and/or associated documentation files (the "Materials"), to deal in the Materials without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Materials, and to permit persons to whom the Materials are 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 Materials. + +THE MATERIALS ARE 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 MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +OpenGLES (3 entries from 3 different header files) +-------- + +Copyright (c) 2013-2014 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and/or associated documentation files (the "Materials"), to deal in the Materials without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Materials, and to permit persons to whom the Materials are furnished to do so, subject tothe following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Materials. + +THE MATERIALS ARE 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 MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +-------- + +This document is licensed under the SGI Free Software B License Version 2.0. For details, see http://oss.sgi.com/projects/FreeB/ + +-------- + +License Applicability. Except to the extent portions of this file are made subject to an alternative license as permitted in the SGI Free Software License B, Version 1.0 (the "License"), the contents of this file are subject only to the provisions of the License. You may not use this file except in compliance with the License. You may obtain a copy of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + +http://oss.sgi.com/projects/FreeB + +Note that, as provided in the License, the Software is distributed on an "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + +Original Code. The Original Code is: OpenGL Sample Implementation, Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. Copyright in any portions created by third parties is as indicated elsewhere herein. All Rights Reserved. + +Additional Notice Provisions: The application programming interfaces established by SGI in conjunction with the Original Code are The OpenGL(R) Graphics System: A Specification (Version 1.2.1), released April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version1.3), released November 4, 1998; and OpenGL(R) Graphics with the XWindow System(R) (Version 1.3), released October 19, 1998. This software was created using the OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has not been independently verified as being compliant with the OpenGL(R) version 1.2.1 Specification. \ No newline at end of file diff --git a/renderdoc/driver/ihv/amd/official/GPUPerfAPI/version.txt b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/version.txt new file mode 100644 index 000000000..4a663086b --- /dev/null +++ b/renderdoc/driver/ihv/amd/official/GPUPerfAPI/version.txt @@ -0,0 +1 @@ +Release: GPUPerfAPI 2.22.1 \ No newline at end of file