From f1bd727dff0bcf86898e3447e4060a8a1fa9980f Mon Sep 17 00:00:00 2001 From: "tabi.katalin" Date: Mon, 2 Mar 2020 19:17:20 +0100 Subject: [PATCH] Add support for ARM counters Adding support for ARM counters via a third-party lib. The main target platform is Android. --- .../Dialogs/PerformanceCounterSelection.cpp | 6 + .../Windows/PerformanceCounterViewer.cpp | 4 + renderdoc.sln | 11 + renderdoc/CMakeLists.txt | 6 + renderdoc/android/android.cpp | 11 + renderdoc/api/replay/replay_enums.h | 19 +- renderdoc/driver/gl/gl_counters.cpp | 99 + renderdoc/driver/gl/gl_replay.cpp | 18 + renderdoc/driver/gl/gl_replay.h | 9 + renderdoc/driver/ihv/arm/ARM.vcxproj | 220 ++ renderdoc/driver/ihv/arm/ARM.vcxproj.filters | 150 + renderdoc/driver/ihv/arm/CMakeLists.txt | 62 + renderdoc/driver/ihv/arm/arm_counters.cpp | 227 ++ renderdoc/driver/ihv/arm/arm_counters.h | 73 + .../driver/ihv/arm/arm_counters_stub.cpp | 83 + .../driver/ihv/arm/official/lizard/LICENSE | 19 + .../driver/ihv/arm/official/lizard/README.md | 21 + .../ihv/arm/official/lizard/gator_api.cpp | 461 +++ .../ihv/arm/official/lizard/gator_api.hpp | 90 + .../arm/official/lizard/gator_constants.hpp | 88 + .../ihv/arm/official/lizard/gator_message.cpp | 91 + .../ihv/arm/official/lizard/gator_message.hpp | 57 + .../arm/official/lizard/gatord_xml_reader.cpp | 266 ++ .../arm/official/lizard/gatord_xml_reader.hpp | 79 + .../ihv/arm/official/lizard/hwcpipe_api.cpp | 172 + .../ihv/arm/official/lizard/hwcpipe_api.hpp | 51 + .../official/lizard/hwcpipe_communication.cpp | 63 + .../official/lizard/hwcpipe_communication.hpp | 54 + .../official/lizard/include/lizard/lizard.hpp | 176 + .../lizard/include/lizard/lizard_api.h | 234 ++ .../lizard/include/lizard/lizard_counter.hpp | 136 + .../driver/ihv/arm/official/lizard/lizard.cpp | 341 ++ .../ihv/arm/official/lizard/lizard_api.cpp | 280 ++ .../official/lizard/lizard_communication.cpp | 69 + .../official/lizard/lizard_communication.hpp | 57 + .../arm/official/lizard/lizard_counter.cpp | 92 + .../ihv/arm/official/lizard/message_util.cpp | 77 + .../ihv/arm/official/lizard/message_util.hpp | 40 + .../driver/ihv/arm/official/lizard/socket.cpp | 156 + .../driver/ihv/arm/official/lizard/socket.hpp | 64 + .../lizard/thirdparty/hwcpipe/LICENSE | 21 + .../lizard/thirdparty/hwcpipe/README.md | 156 + .../lizard/thirdparty/hwcpipe/cpu_profiler.h | 115 + .../lizard/thirdparty/hwcpipe/gpu_profiler.h | 192 + .../lizard/thirdparty/hwcpipe/hwcpipe.cpp | 197 + .../lizard/thirdparty/hwcpipe/hwcpipe.h | 93 + .../lizard/thirdparty/hwcpipe/hwcpipe_log.h | 40 + .../lizard/thirdparty/hwcpipe/value.h | 69 + .../hwcpipe/vendor/arm/mali/hwc.hpp | 413 ++ .../hwcpipe/vendor/arm/mali/hwc_names.hpp | 3346 +++++++++++++++++ .../hwcpipe/vendor/arm/mali/mali_profiler.cpp | 614 +++ .../hwcpipe/vendor/arm/mali/mali_profiler.h | 124 + .../hwcpipe/vendor/arm/pmu/pmu_counter.cpp | 175 + .../hwcpipe/vendor/arm/pmu/pmu_counter.h | 103 + .../hwcpipe/vendor/arm/pmu/pmu_profiler.cpp | 117 + .../hwcpipe/vendor/arm/pmu/pmu_profiler.h | 77 + renderdoc/renderdoc.vcxproj | 3 + 57 files changed, 10086 insertions(+), 1 deletion(-) create mode 100644 renderdoc/driver/ihv/arm/ARM.vcxproj create mode 100644 renderdoc/driver/ihv/arm/ARM.vcxproj.filters create mode 100644 renderdoc/driver/ihv/arm/CMakeLists.txt create mode 100644 renderdoc/driver/ihv/arm/arm_counters.cpp create mode 100644 renderdoc/driver/ihv/arm/arm_counters.h create mode 100644 renderdoc/driver/ihv/arm/arm_counters_stub.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/LICENSE create mode 100644 renderdoc/driver/ihv/arm/official/lizard/README.md create mode 100644 renderdoc/driver/ihv/arm/official/lizard/gator_api.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/gator_api.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/gator_constants.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/gator_message.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/gator_message.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/gatord_xml_reader.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/gatord_xml_reader.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/hwcpipe_api.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/hwcpipe_api.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/hwcpipe_communication.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/hwcpipe_communication.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard_api.h create mode 100644 renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard_counter.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/lizard.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/lizard_api.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/lizard_communication.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/lizard_communication.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/lizard_counter.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/message_util.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/message_util.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/socket.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/socket.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/LICENSE create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/README.md create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/cpu_profiler.h create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/gpu_profiler.h create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe.h create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe_log.h create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/value.h create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc_names.hpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.h create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.h create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.cpp create mode 100644 renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.h diff --git a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp index 735862231e..298b7415f4 100644 --- a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp +++ b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp @@ -51,6 +51,7 @@ enum class CounterFamily Intel, NVIDIA, VulkanExtended, + ARM, }; CounterFamily GetCounterFamily(GPUCounter counter) @@ -71,6 +72,10 @@ CounterFamily GetCounterFamily(GPUCounter counter) { return CounterFamily::VulkanExtended; } + else if(IsARMCounter(counter)) + { + return CounterFamily::ARM; + } return CounterFamily::Generic; } @@ -84,6 +89,7 @@ QString ToString(CounterFamily family) case CounterFamily::Intel: return lit("Intel"); case CounterFamily::NVIDIA: return lit("NVIDIA"); case CounterFamily::VulkanExtended: return lit("Vulkan Extended"); + case CounterFamily::ARM: return lit("ARM"); case CounterFamily::Unknown: return lit("Unknown"); } diff --git a/qrenderdoc/Windows/PerformanceCounterViewer.cpp b/qrenderdoc/Windows/PerformanceCounterViewer.cpp index 9c8c248a15..bc0ca71c62 100644 --- a/qrenderdoc/Windows/PerformanceCounterViewer.cpp +++ b/qrenderdoc/Windows/PerformanceCounterViewer.cpp @@ -177,6 +177,10 @@ QTableWidgetItem *PerformanceCounterViewer::MakeCounterResultItem(const CounterR case CounterUnit::Absolute: case CounterUnit::Ratio: break; + + case CounterUnit::Hertz: returnValue += lit(" Hz"); break; + case CounterUnit::Volt: returnValue += lit(" V"); break; + case CounterUnit::Celsius: returnValue += lit(" °C"); break; } return new CustomSortedTableItem(returnValue, SortValue(result, description)); diff --git a/renderdoc.sln b/renderdoc.sln index b2a44e2448..a643f9f6c7 100644 --- a/renderdoc.sln +++ b/renderdoc.sln @@ -83,6 +83,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NV", "renderdoc\driver\ihv\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Intel", "renderdoc\driver\ihv\intel\Intel.vcxproj", "{7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ARM", "renderdoc\driver\ihv\arm\ARM.vcxproj", "{F9CCE6CA-0CA3-4A22-9C7B-881369955E62}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Development|x64 = Development|x64 @@ -283,6 +285,14 @@ Global {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Release|x64.Build.0 = Release|x64 {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Release|x86.ActiveCfg = Release|Win32 {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5}.Release|x86.Build.0 = Release|Win32 + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62}.Development|x64.ActiveCfg = Development|x64 + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62}.Development|x64.Build.0 = Development|x64 + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62}.Development|x86.ActiveCfg = Development|Win32 + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62}.Development|x86.Build.0 = Development|Win32 + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62}.Release|x64.ActiveCfg = Release|x64 + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62}.Release|x64.Build.0 = Release|x64 + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62}.Release|x86.ActiveCfg = Release|Win32 + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -318,5 +328,6 @@ Global {37955C79-D91D-423F-8C6C-8F5BCF4F28D4} = {B5A783D9-AEB9-420D-8E77-D4D930F8D88C} {40349AD9-5558-4DF4-84E2-11934DE90A11} = {4DA2F3E3-9A65-45DD-A69B-82C7757D4904} {7FCB5FC5-1DBD-4DA6-83A0-6BA4E945BDA5} = {4DA2F3E3-9A65-45DD-A69B-82C7757D4904} + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62} = {4DA2F3E3-9A65-45DD-A69B-82C7757D4904} EndGlobalSection EndGlobal diff --git a/renderdoc/CMakeLists.txt b/renderdoc/CMakeLists.txt index 83706cbd1f..cee6b3b024 100644 --- a/renderdoc/CMakeLists.txt +++ b/renderdoc/CMakeLists.txt @@ -502,6 +502,12 @@ if(ENABLE_GL OR ENABLE_GLES) list(APPEND renderdoc_objects $) endif() +# pull in the ARM folder for perf query +if(ENABLE_GL OR ENABLE_GLES) + add_subdirectory(driver/ihv/arm) + list(APPEND renderdoc_objects $) +endif() + add_library(rdoc OBJECT ${sources}) target_compile_definitions(rdoc ${RDOC_DEFINITIONS}) target_include_directories(rdoc ${RDOC_INCLUDES}) diff --git a/renderdoc/android/android.cpp b/renderdoc/android/android.cpp index 0f435c92c6..9b9b0cd0ee 100644 --- a/renderdoc/android/android.cpp +++ b/renderdoc/android/android.cpp @@ -558,11 +558,22 @@ struct AndroidRemoteServer : public RemoteServer { ResetAndroidSettings(); + // enable profiling to measure hardware counters + Android::adbExecCommand(m_deviceID, "shell setprop security.perf_harden 0"); + LazilyStartLogcatThread(); return RemoteServer::OpenCapture(proxyid, filename, opts, progress); } + virtual void CloseCapture(IReplayController *rend) override + { + // disable profiling + Android::adbExecCommand(m_deviceID, "shell setprop security.perf_harden 1"); + + RemoteServer::CloseCapture(rend); + } + virtual rdcstr GetHomeFolder() override { return ""; } virtual rdcarray ListFolder(const char *path) override { diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 9e2de20428..1cd41ecf9a 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -3229,7 +3229,10 @@ enum class GPUCounter : uint32_t FirstVulkanExtended = 4000000, LastNvidia = FirstVulkanExtended - 1, - LastVulkanExtended = 5000000, + FirstARM = 5000000, + LastVulkanExtended = FirstARM - 1, + + LastARM = 6000000, }; ITERABLE_OPERATORS(GPUCounter); @@ -3290,6 +3293,17 @@ inline constexpr bool IsVulkanExtendedCounter(GPUCounter c) return c >= GPUCounter::FirstVulkanExtended && c <= GPUCounter::LastVulkanExtended; } +DOCUMENT(R"(Check whether or not this is an ARM private counter. + +:param GPUCounter c: The counter. +:return: ``True`` if it is an ARM private counter, ``False`` if it's not. +:rtype: ``bool`` +)"); +inline constexpr bool IsARMCounter(GPUCounter c) +{ + return c >= GPUCounter::FirstARM && c <= GPUCounter::LastARM; +} + DOCUMENT(R"(The unit that GPU counter data is returned in. .. data:: Absolute @@ -3324,6 +3338,9 @@ enum class CounterUnit : uint32_t Ratio, Bytes, Cycles, + Hertz, + Volt, + Celsius }; DECLARE_REFLECTION_ENUM(CounterUnit); diff --git a/renderdoc/driver/gl/gl_counters.cpp b/renderdoc/driver/gl/gl_counters.cpp index 8c4253ef5e..f6a3decdd7 100644 --- a/renderdoc/driver/gl/gl_counters.cpp +++ b/renderdoc/driver/gl/gl_counters.cpp @@ -25,6 +25,7 @@ #include #include #include "driver/ihv/amd/amd_counters.h" +#include "driver/ihv/arm/arm_counters.h" #include "driver/ihv/intel/intel_gl_counters.h" #include "gl_driver.h" #include "gl_replay.h" @@ -65,6 +66,11 @@ rdcarray GLReplay::EnumerateCounters() ret.append(m_pIntelCounters->GetPublicCounterIds()); } + if(m_pARMCounters) + { + ret.append(m_pARMCounters->GetPublicCounterIds()); + } + return ret; } @@ -96,6 +102,11 @@ CounterDescription GLReplay::DescribeCounter(GPUCounter counterID) } } + if(IsARMCounter(counterID) && m_pARMCounters) + { + return m_pARMCounters->GetCounterDescription(counterID); + } + // FFBA5548-FBF8-405D-BA18-F0329DA370A0 desc.uuid.words[0] = 0xFFBA5548; desc.uuid.words[1] = 0xFBF8405D; @@ -461,6 +472,84 @@ rdcarray GLReplay::FetchCountersIntel(const rdcarray return ret; } +void GLReplay::FillTimersARM(uint32_t *eventStartID, uint32_t *sampleIndex, + rdcarray *eventIDs, const DrawcallDescription &drawnode) +{ + if(drawnode.children.empty()) + return; + + for(size_t i = 0; i < drawnode.children.size(); i++) + { + const DrawcallDescription &d = drawnode.children[i]; + + FillTimersARM(eventStartID, sampleIndex, eventIDs, drawnode.children[i]); + + if(d.events.empty()) + continue; + + eventIDs->push_back(d.eventId); + + m_pDriver->ReplayLog(*eventStartID, d.eventId, eReplay_WithoutDraw); + + m_pARMCounters->BeginSample(d.eventId); + + m_pDriver->ReplayLog(*eventStartID, d.eventId, eReplay_OnlyDraw); + + // wait for the GPU to process all commands + GLsync sync = GL.glFenceSync(eGL_SYNC_GPU_COMMANDS_COMPLETE, 0); + GL.glClientWaitSync(sync, eGL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); + + m_pARMCounters->EndSample(); + + GL.glDeleteSync(sync); + + *eventStartID = d.eventId + 1; + ++*sampleIndex; + } +} + +rdcarray GLReplay::FetchCountersARM(const rdcarray &counters) +{ + m_pARMCounters->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(IsARMCounter(counters[i])); + m_pARMCounters->EnableCounter(counters[i]); + } + + uint32_t passCount = m_pARMCounters->GetPassCount(); + + uint32_t sampleIndex = 0; + + rdcarray eventIDs; + + m_pDriver->ReplayMarkers(false); + + for(uint32_t p = 0; p < passCount; p++) + { + m_pARMCounters->BeginPass(p); + + uint32_t eventStartID = 0; + + sampleIndex = 0; + + eventIDs.clear(); + + FillTimersARM(&eventStartID, &sampleIndex, &eventIDs, m_pDriver->GetRootDraw()); + + m_pARMCounters->EndPass(); + } + m_pDriver->ReplayMarkers(true); + + rdcarray ret = m_pARMCounters->GetCounterData(eventIDs, counters); + + return ret; +} + rdcarray GLReplay::FetchCounters(const rdcarray &allCounters) { rdcarray ret; @@ -503,6 +592,16 @@ rdcarray GLReplay::FetchCounters(const rdcarray &allC } } + if(m_pARMCounters) + { + rdcarray armCounters; + std::copy_if(allCounters.begin(), allCounters.end(), std::back_inserter(armCounters), + [](const GPUCounter &c) { return IsARMCounter(c); }); + + if(!armCounters.empty()) + ret = FetchCountersARM(armCounters); + } + if(counters.empty()) { return ret; diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index c040abcd54..21164ce6a3 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -26,6 +26,7 @@ #include "gl_replay.h" #include "core/settings.h" #include "driver/ihv/amd/amd_counters.h" +#include "driver/ihv/arm/arm_counters.h" #include "driver/ihv/intel/intel_gl_counters.h" #include "maths/matrix.h" #include "serialise/rdcfile.h" @@ -67,6 +68,7 @@ void GLReplay::Shutdown() { SAFE_DELETE(m_pAMDCounters); SAFE_DELETE(m_pIntelCounters); + SAFE_DELETE(m_pARMCounters); DeleteDebugData(); @@ -235,6 +237,7 @@ void GLReplay::SetReplayData(GLWindowingData data) { AMDCounters *countersAMD = NULL; IntelGlCounters *countersIntel = NULL; + ARMCounters *countersARM = NULL; bool isMesa = false; @@ -283,6 +286,11 @@ void GLReplay::SetReplayData(GLWindowingData data) RDCLOG("AMD GPU detected - trying to initialise AMD counters"); countersAMD = new AMDCounters(); } + else if(m_DriverInfo.vendor == GPUVendor::ARM) + { + RDCLOG("ARM Mali GPU detected - trying to initialise ARM counters"); + countersARM = new ARMCounters(); + } else { RDCLOG("%s GPU detected - no counters available", ToStr(m_DriverInfo.vendor).c_str()); @@ -308,6 +316,16 @@ void GLReplay::SetReplayData(GLWindowingData data) delete countersIntel; m_pIntelCounters = NULL; } + + if(countersARM && countersARM->Init()) + { + m_pARMCounters = countersARM; + } + else + { + delete countersARM; + m_pARMCounters = NULL; + } } } diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 8d1edd8d55..c5338a91af 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -31,6 +31,7 @@ #include "gl_common.h" class AMDCounters; +class ARMCounters; class IntelGlCounters; class WrappedOpenGL; struct GLCounterContext; @@ -465,4 +466,12 @@ class GLReplay : public IReplayDriver const DrawcallDescription &drawnode); rdcarray FetchCountersIntel(const rdcarray &counters); + + // ARM counter instance + ARMCounters *m_pARMCounters = NULL; + + void FillTimersARM(uint32_t *eventStartID, uint32_t *sampleIndex, rdcarray *eventIDs, + const DrawcallDescription &drawnode); + + rdcarray FetchCountersARM(const rdcarray &counters); }; diff --git a/renderdoc/driver/ihv/arm/ARM.vcxproj b/renderdoc/driver/ihv/arm/ARM.vcxproj new file mode 100644 index 0000000000..7de9125f63 --- /dev/null +++ b/renderdoc/driver/ihv/arm/ARM.vcxproj @@ -0,0 +1,220 @@ + + + + + Development + Win32 + + + Development + x64 + + + Release + Win32 + + + Release + x64 + + + + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62} + 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 + /w44062 %(AdditionalOptions) + + + Windows + true + + + + + Disabled + + + + + MaxSpeed + Default + true + true + false + + + true + true + + + + + true + + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + + + + \ No newline at end of file diff --git a/renderdoc/driver/ihv/arm/ARM.vcxproj.filters b/renderdoc/driver/ihv/arm/ARM.vcxproj.filters new file mode 100644 index 0000000000..6b098c84bc --- /dev/null +++ b/renderdoc/driver/ihv/arm/ARM.vcxproj.filters @@ -0,0 +1,150 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + + + {7e5aff88-5de6-4985-ad92-c69fd47fb6ce} + + + {b1fd2e34-8140-4eed-a65c-db2c592e00e9} + + + {45866afa-f87c-4bfd-8f1b-720bebf4e82e} + + + {d25e3ccb-84a3-4a4a-8bf6-24795ba1bf47} + + + {7f040482-c5df-453f-869b-a1d6cf2c537e} + + + + + Counters + + + Counters + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard\thirdparty\hwcpipe + + + official\lizard\thirdparty\hwcpipe\mali + + + official\lizard\thirdparty\hwcpipe\pmu + + + official\lizard\thirdparty\hwcpipe\pmu + + + + + Counters + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard + + + official\lizard\thirdparty\hwcpipe + + + official\lizard\thirdparty\hwcpipe + + + official\lizard\thirdparty\hwcpipe + + + official\lizard\thirdparty\hwcpipe + + + official\lizard\thirdparty\hwcpipe + + + official\lizard\thirdparty\hwcpipe\mali + + + official\lizard\thirdparty\hwcpipe\mali + + + official\lizard\thirdparty\hwcpipe\mali + + + official\lizard\thirdparty\hwcpipe\pmu + + + official\lizard\thirdparty\hwcpipe\pmu + + + \ No newline at end of file diff --git a/renderdoc/driver/ihv/arm/CMakeLists.txt b/renderdoc/driver/ihv/arm/CMakeLists.txt new file mode 100644 index 0000000000..cd2ece2491 --- /dev/null +++ b/renderdoc/driver/ihv/arm/CMakeLists.txt @@ -0,0 +1,62 @@ +set(sources + arm_counters.h +) + +if(ANDROID) + list(APPEND sources + arm_counters.cpp + + official/lizard/include/lizard/lizard_api.h + official/lizard/lizard_api.cpp + + official/lizard/include/lizard/lizard.hpp + official/lizard/lizard.cpp + official/lizard/lizard_counter.cpp + official/lizard/lizard_communication.hpp + official/lizard/lizard_communication.cpp + official/lizard/hwcpipe_communication.hpp + official/lizard/hwcpipe_communication.cpp + official/lizard/hwcpipe_api.hpp + official/lizard/hwcpipe_api.cpp + official/lizard/gatord_xml_reader.cpp + + official/lizard/gator_api.cpp + official/lizard/gator_constants.hpp + official/lizard/gator_message.cpp + official/lizard/gator_message.hpp + official/lizard/message_util.cpp + official/lizard/message_util.hpp + official/lizard/socket.cpp + + official/lizard/thirdparty/hwcpipe/hwcpipe.h + official/lizard/thirdparty/hwcpipe/hwcpipe.cpp + official/lizard/thirdparty/hwcpipe/cpu_profiler.h + official/lizard/thirdparty/hwcpipe/gpu_profiler.h + official/lizard/thirdparty/hwcpipe/value.h + + official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc.hpp + official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc_names.hpp + official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.h + official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.cpp + + official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.h + official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.cpp + official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.h + official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.cpp + ) +else() + list(APPEND sources + arm_counters_stub.cpp + ) +endif() + +add_library(rdoc_arm OBJECT ${sources}) + +set(include_dirs + ${RDOC_INCLUDES} + official/lizard/ + official/lizard/include/lizard + official/lizard/thirdparty/hwcpipe/ +) +target_include_directories(rdoc_arm ${include_dirs}) +target_compile_definitions(rdoc_arm ${RDOC_DEFINITIONS}) diff --git a/renderdoc/driver/ihv/arm/arm_counters.cpp b/renderdoc/driver/ihv/arm/arm_counters.cpp new file mode 100644 index 0000000000..1301446f4d --- /dev/null +++ b/renderdoc/driver/ihv/arm/arm_counters.cpp @@ -0,0 +1,227 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 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 "arm_counters.h" + +#include "android/android.h" +#include "common/common.h" +#include "common/formatting.h" +#include "core/plugins.h" +#include "os/os_specific.h" + +#include + +#include "official/lizard/include/lizard/lizard_api.h" + +static CounterDescription ARMCreateCounterDescription(GPUCounter index, + LizardCounterDescription &lzdDesc) +{ + CounterDescription desc; + desc.name = StringFormat::Fmt("%s %s", lzdDesc.title, lzdDesc.name); + desc.counter = GPUCounter(index); + desc.category = lzdDesc.category; + + if(strlen(lzdDesc.short_name) > 0) + desc.description = StringFormat::Fmt("%s (%s)", lzdDesc.description, lzdDesc.short_name); + else + desc.description = lzdDesc.description; + + switch(lzdDesc.result_type) + { + case LZD_TYPE_INT: desc.resultType = CompType::UInt; break; + case LZD_TYPE_DOUBLE: desc.resultType = CompType::Double; break; + default: desc.resultType = CompType::UInt; break; + } + + switch(lzdDesc.units) + { + case LZD_UNITS_BYTE: desc.unit = CounterUnit::Bytes; break; + case LZD_UNITS_CELSIUS: desc.unit = CounterUnit::Celsius; break; + case LZD_UNITS_HZ: desc.unit = CounterUnit::Hertz; break; + case LZD_UNITS_S: desc.unit = CounterUnit::Seconds; break; + case LZD_UNITS_V: desc.unit = CounterUnit::Volt; break; + default: desc.unit = CounterUnit::Absolute; break; + } + + return desc; +} + +ARMCounters::ARMCounters() : m_Api(NULL), m_Ctx(0), m_EventId(0), m_passIndex(0) +{ +} + +ARMCounters::~ARMCounters() +{ + if(m_Ctx) + m_Api->Destroy(m_Ctx); +} + +bool ARMCounters::Init() +{ + if(LoadApi(&m_Api) != LZD_OK) + { + RDCLOG("Failed to load Lizard api."); + return false; + } + + if(m_Api->version != LIZARD_VERSION_0_1) + { + RDCLOG("Lizard version is not supported."); + return false; + } + + m_Ctx = m_Api->Init("127.0.0.1", 8080); + if(!m_Ctx) + { + RDCLOG("Failed to initialize Lizard."); + return false; + } + + uint32_t count = m_Api->GetAvailableCountersCount(m_Ctx); + + if(count == 0) + { + RDCLOG("Couldn't find available ARM counters."); + m_Api->Destroy(m_Ctx); + return false; + } + + for(LizardCounterId idx = 1; idx <= count; idx++) + { + struct LizardCounterDescription lzdDesc; + + LZD_Result result = m_Api->GetCounterDescription(m_Ctx, idx, &lzdDesc); + + if(result == LZD_OK) + { + CounterDescription desc = + ARMCreateCounterDescription(GPUCounter((int)GPUCounter::FirstARM + idx), lzdDesc); + m_CounterDescriptions.push_back(desc); + m_CounterIds.push_back(desc.counter); + } + else + { + RDCLOG("Failed to get ARM counter information."); + m_Api->Destroy(m_Ctx); + return false; + } + } + return true; +} + +rdcarray ARMCounters::GetPublicCounterIds() +{ + return m_CounterIds; +} + +CounterDescription ARMCounters::GetCounterDescription(GPUCounter index) +{ + return m_CounterDescriptions[(int)index - (int)GPUCounter::FirstARM - 1]; +} + +void ARMCounters::EnableCounter(GPUCounter counter) +{ + uint32_t id = (uint32_t)counter - (uint32_t)GPUCounter::FirstARM; + m_EnabledCounters.push_back(id); +} + +void ARMCounters::DisableAllCounters() +{ + m_EnabledCounters.clear(); +} + +uint32_t ARMCounters::GetPassCount() +{ + return 1; +} + +void ARMCounters::BeginPass(uint32_t passID) +{ + m_passIndex = passID; + for(size_t i = 0; i < m_EnabledCounters.size(); i++) + { + m_Api->EnableCounter(m_Ctx, m_EnabledCounters[i]); + } +} + +void ARMCounters::EndPass() +{ + for(size_t i = 0; i < m_EnabledCounters.size(); i++) + { + m_Api->DisableCounter(m_Ctx, m_EnabledCounters[i]); + } +} + +void ARMCounters::BeginSample(uint32_t eventId) +{ + m_EventId = eventId; + m_Api->StartCapture(m_Ctx); +} + +void ARMCounters::EndSample() +{ + m_Api->StopCapture(m_Ctx); + + for(uint32_t counterId : m_EnabledCounters) + { + const CounterDescription &desc = m_CounterDescriptions[counterId - 1]; + CounterValue data; + data.u64 = 0; + if(desc.resultType == CompType::UInt) + { + data.u64 = m_Api->ReadCounterInt(m_Ctx, counterId); + } + else if(desc.resultType == CompType::Double) + { + data.d = m_Api->ReadCounterDouble(m_Ctx, counterId); + } + m_CounterData[m_EventId][counterId] = data; + } +} + +rdcarray ARMCounters::GetCounterData(const rdcarray &eventIDs, + const rdcarray &counters) +{ + rdcarray result; + for(size_t i = 0; i < eventIDs.size(); i++) + { + uint32_t eventId = eventIDs[i]; + for(size_t j = 0; j < counters.size(); j++) + { + GPUCounter counter = counters[j]; + uint32_t counterId = (uint32_t)counter - (uint32_t)GPUCounter::FirstARM; + const CounterDescription &desc = GetCounterDescription(counter); + const CounterValue &data = m_CounterData[eventId][counterId]; + if(desc.resultType == CompType::UInt) + { + result.push_back(CounterResult(eventId, counter, data.u64)); + } + else if(desc.resultType == CompType::Double) + { + result.push_back(CounterResult(eventId, counter, data.d)); + } + } + } + return result; +} diff --git a/renderdoc/driver/ihv/arm/arm_counters.h b/renderdoc/driver/ihv/arm/arm_counters.h new file mode 100644 index 0000000000..4ea8d9f637 --- /dev/null +++ b/renderdoc/driver/ihv/arm/arm_counters.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 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/data_types.h" +#include "api/replay/renderdoc_replay.h" +#include "api/replay/replay_enums.h" +#include "common/common.h" + +struct LizardApi; +typedef void *LizardInstance; + +class ARMCounters +{ +public: + ARMCounters(); + ~ARMCounters(); + + bool Init(); + rdcarray GetPublicCounterIds(); + CounterDescription GetCounterDescription(GPUCounter index); + + void EnableCounter(GPUCounter counter); + void DisableAllCounters(); + + uint32_t GetPassCount(); + + void BeginPass(uint32_t passID); + void EndPass(); + + void BeginSample(uint32_t eventId); + void EndSample(); + + rdcarray GetCounterData(const rdcarray &eventIDs, + const rdcarray &counters); + +private: +#if ENABLED(RDOC_ANDROID) + struct LizardApi *m_Api; + LizardInstance m_Ctx; + + uint32_t m_EventId; + uint32_t m_passIndex; + + rdcarray m_EnabledCounters; + rdcarray m_CounterDescriptions; + rdcarray m_CounterIds; + std::map> m_CounterData; +#endif +}; diff --git a/renderdoc/driver/ihv/arm/arm_counters_stub.cpp b/renderdoc/driver/ihv/arm/arm_counters_stub.cpp new file mode 100644 index 0000000000..845f3adfb8 --- /dev/null +++ b/renderdoc/driver/ihv/arm/arm_counters_stub.cpp @@ -0,0 +1,83 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 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 "arm_counters.h" + +ARMCounters::ARMCounters() +{ +} + +ARMCounters::~ARMCounters() +{ +} + +bool ARMCounters::Init() +{ + return false; +} + +rdcarray ARMCounters::GetPublicCounterIds() +{ + return {}; +} + +CounterDescription ARMCounters::GetCounterDescription(GPUCounter index) +{ + return {}; +} + +void ARMCounters::EnableCounter(GPUCounter counter) +{ +} + +void ARMCounters::DisableAllCounters() +{ +} + +uint32_t ARMCounters::GetPassCount() +{ + return 0; +} + +void ARMCounters::BeginPass(uint32_t passID) +{ +} + +void ARMCounters::EndPass() +{ +} + +void ARMCounters::BeginSample(uint32_t eventId) +{ +} + +void ARMCounters::EndSample() +{ +} + +rdcarray ARMCounters::GetCounterData(const rdcarray &eventIDs, + const rdcarray &counters) +{ + return {}; +} diff --git a/renderdoc/driver/ihv/arm/official/lizard/LICENSE b/renderdoc/driver/ihv/arm/official/lizard/LICENSE new file mode 100644 index 0000000000..83587eda8b --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 Samsung Electronics (UK) Limited + +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/arm/official/lizard/README.md b/renderdoc/driver/ihv/arm/official/lizard/README.md new file mode 100644 index 0000000000..43042571aa --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/README.md @@ -0,0 +1,21 @@ +## Lizard + +Lizard is a library to capture ARM hardware counters on Android devices. + +### Using the library with gatord + +This step is optional, the library can query a few hardware counters directly. + +1. Build `gatord` for Android. + +2. Copy `gatord` to a directory which is publicly readable, writeable and executable on the Android device (e.g. /data/local/tmp) + +```sh +$ adb push gatord /data/local/tmp/gatord +``` + +3. Start gatord on the Android device ( -M: Mali device type e.g. G71, G76, etc.) + +```sh +$ adb shell ./data/local/tmp/gatord -M G71 +``` diff --git a/renderdoc/driver/ihv/arm/official/lizard/gator_api.cpp b/renderdoc/driver/ihv/arm/official/lizard/gator_api.cpp new file mode 100644 index 0000000000..bc4d0bd34b --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/gator_api.cpp @@ -0,0 +1,461 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 "gator_api.hpp" + +#include +#include +#include +#include +#include + +#include "gator_constants.hpp" +#include "gator_message.hpp" +#include "gatord_xml_reader.hpp" +#include "message_util.hpp" + +namespace lizard +{ +static const std::string ATTR_TYPE = "type"; + +static const std::string TAG_REQUEST = "request"; + +static const std::string VALUE_CAPTURED = "captured"; +static const std::string VALUE_CONFIGURATION = "configuration"; +static const std::string VALUE_COUNTERS = "counters"; +static const std::string VALUE_DEFAULTS = "defaults"; +static const std::string VALUE_EVENTS = "events"; + +GatorApi::GatorApi(char *hostname, const uint32_t port, + std::vector &availableCounters, LizardCounterDataStore &dataStore) + : m_host(hostname), + m_port(port), + m_connection(NULL), + m_availableCounters(availableCounters), + m_data(dataStore) +{ +} + +GatorApi::~GatorApi() +{ + if(m_host) + { + free(m_host); + } + + if(m_connection) + { + delete m_connection; + m_connection = NULL; + } +} + +bool GatorApi::createConnection() +{ + m_connection = lizard::Socket::createConnection(m_host, m_port); + if(m_connection == NULL) + { + return false; + } + return true; +} + +void GatorApi::destroyConnection() +{ + Socket::destroyConnection(m_connection); + m_connection = NULL; +} + +bool GatorApi::init(uint32_t &counterId) +{ + std::string eventsXml = requestEvents(); + std::string countersXml = requestCounters(); + + // Store all events supported by gatord + std::vector gatordEvents = + GatordXML::parseEvents(eventsXml.c_str(), eventsXml.size()); + // Store available counters provided by gatord + std::vector gatordAvailableCounters = + GatordXML::parseCounters(countersXml.c_str(), countersXml.size()); + + std::vector::const_iterator countersStart = gatordAvailableCounters.begin(); + std::vector::const_iterator countersEnd = gatordAvailableCounters.end(); + + uint32_t counterNum = counterId; + + for(GatordXML::EventCategory &category : gatordEvents) + { + for(GatordXML::Event &event : category.events) + { + if(std::find(countersStart, countersEnd, event.counter) != countersEnd) + { + // found the counter + LizardCounter::ClassType classType = event.eventClass == CLASS_ABSOLUTE + ? LizardCounter::CLASS_ABSOLUTE + : LizardCounter::CLASS_DELTA; + m_availableCounters.emplace_back(++counterId, event.counter.c_str(), event.name.c_str(), + event.title.c_str(), event.description.c_str(), + category.name.c_str(), event.multiplier, event.units, + classType, LizardCounter::SOURCE_GATORD); + } + } + } + + return counterId > counterNum; +} + +bool GatorApi::setupCapturedCounters() +{ + std::string capturedXml = requestCaptured(); + std::vector capturedCounters = + GatordXML::parseCapturedCounters(capturedXml.c_str(), capturedXml.size()); + + if(capturedCounters.empty()) + { + return false; + } + + for(GatordXML::CapturedCounter captured : capturedCounters) + { + for(LizardCounter &counter : m_availableCounters) + { + if(captured.type == counter.key()) + { + counter.setInternalKey(captured.key); + break; + } + } + } + + return true; +} + +bool GatorApi::sendConfiguration(const std::vector &enabledCounters) +{ + std::string xml = std::string("\n"); + xml += "\n"; + for(uint32_t idx = 0; idx < enabledCounters.size(); idx++) + { + const lizard::LizardCounter &cnt = enabledCounters[idx]; + xml += "\n"; + } + xml += ""; + sendXml(xml); + uint8_t response = getResponse(); + if(response != RESPONSE_ACK) + { + return false; + } + return true; +} + +bool GatorApi::sendSession() +{ + std::string xml = std::string( + "\n\n\n\n\n"); + sendXml(xml); + uint8_t response = getResponse(); + if(response != RESPONSE_ACK) + { + return false; + } + return true; +} + +void GatorApi::sendDisconnect() +{ + sendCommand(COMMAND_DISCONNECT); + getResponse(); +} + +std::string GatorApi::requestCounters() +{ + requestXml(VALUE_COUNTERS); + return getXmlResponse(); +} + +std::string GatorApi::requestEvents() +{ + requestXml(VALUE_EVENTS); + return getXmlResponse(); +} + +std::string GatorApi::requestConfiguration() +{ + requestXml(VALUE_CONFIGURATION); + return getXmlResponse(); +} + +std::string GatorApi::requestDefaults() +{ + requestXml(VALUE_DEFAULTS); + return getXmlResponse(); +} + +std::string GatorApi::requestCaptured() +{ + requestXml(VALUE_CAPTURED); + return getXmlResponse(); +} + +void GatorApi::requestXml(const std::string &attributeValue) +{ + std::string xml = std::string(""); + xml += "<" + TAG_REQUEST + " " + ATTR_TYPE + "=" + attributeValue + "/>"; + + uint8_t header[5]; + header[0] = COMMAND_REQUEST_XML; + writeLEInt(header + 1, xml.size()); + + size_t byteSent; + m_connection->send(header, sizeof(header), &byteSent); + m_connection->send(xml.c_str(), xml.size(), &byteSent); +} + +void GatorApi::sendXml(const std::string &xml) +{ + uint8_t header[5]; + header[0] = COMMAND_DELIVER_XML; + writeLEInt(header + 1, xml.size()); + + size_t byteSent; + m_connection->send(header, sizeof(header), &byteSent); + m_connection->send(xml.c_str(), xml.size(), &byteSent); +} + +uint8_t GatorApi::getResponse() +{ + uint8_t responseType; + uint32_t responseSize; + getResponseHeader(&responseType, &responseSize); + return responseType; +} + +std::string GatorApi::getXmlResponse() +{ + uint8_t responseType; + uint32_t responseSize; + getResponseHeader(&responseType, &responseSize); + + if(responseType != RESPONSE_XML) + return ""; + + std::vector responseXml(responseSize); + + size_t bytesRecv; + m_connection->receiveAll(responseXml.data(), responseSize, &bytesRecv); + + std::string xml(responseXml.begin(), responseXml.end()); + + return xml; +} + +void GatorApi::sendCommand(uint8_t command) +{ + uint8_t message[5]; + message[0] = command; + writeLEInt(message + 1, 0); + size_t byteSent; + m_connection->send(message, sizeof(message), &byteSent); +} + +Socket::Result GatorApi::getResponseHeader(uint8_t *responseType, uint32_t *responseSize) +{ + uint8_t responseHeader[5]; + size_t bytesRecv; + Socket::Result result = m_connection->receive(responseHeader, sizeof(responseHeader), &bytesRecv); + if(result == Socket::Result::SUCCESS) + { + *responseType = responseHeader[0]; + *responseSize = readLEInt(responseHeader + 1); + } + return result; +} + +bool GatorApi::sendVersion() +{ + char *msg_version = (char *)GATOR_PROTOCOL_VERSION; + char *msg_streamline = (char *)STREAMLINE; + + size_t bytesSent; + m_connection->send(msg_version, strlen(msg_version), &bytesSent); + m_connection->send(msg_streamline, strlen(msg_streamline), &bytesSent); + + // "GATOR 670\n" + size_t bytesRecv = 0; + size_t size = 10; + char buffer[size]; + m_connection->receiveAll(buffer, sizeof(buffer), &bytesRecv); + + std::string gator_pattern = "GATOR "; + if(bytesRecv != size || std::strncmp(buffer, gator_pattern.c_str(), gator_pattern.length()) != 0) + { + return false; + } + + sendCommand(COMMAND_PING); + uint8_t response = getResponse(); + if(response != RESPONSE_ACK) + { + return false; + } + + return true; +} + +bool GatorApi::resendConfiguration(const std::vector &enabledGatorCounters) +{ + if(enabledGatorCounters.empty()) + { + return false; + } + + if(!createConnection()) + { + return false; + } + + if(!sendVersion()) + { + destroyConnection(); + return false; + } + + if(!sendConfiguration(enabledGatorCounters)) + { + sendDisconnect(); + destroyConnection(); + return false; + } + + sendDisconnect(); + destroyConnection(); + + return true; +} + +bool GatorApi::startSession() +{ + if(!createConnection()) + { + return false; + } + if(!sendVersion()) + { + destroyConnection(); + return false; + } + if(!sendSession()) + { + sendDisconnect(); + destroyConnection(); + return false; + } + + if(!setupCapturedCounters()) + { + sendDisconnect(); + destroyConnection(); + } + + return true; +} + +void GatorApi::startCapture() +{ + sendCommand(COMMAND_APC_START); +} + +void GatorApi::stopCapture() +{ + sendCommand(COMMAND_APC_STOP); +} + +GatorApi::MessageResult GatorApi::readMessage(GatorMessage &message) +{ + uint8_t responseType; + uint32_t responseSize; + + Socket::Result result = getResponseHeader(&responseType, &responseSize); + if(result == Socket::Result::SUCCESS) + { + message.setType(responseType); + if(responseSize > 0) + { + std::vector response(responseSize); + size_t bytesRecv; + result = m_connection->receiveAll(response.data(), responseSize, &bytesRecv); + if(result == Socket::Result::SUCCESS) + { + message.setData(response); + return GatorApi::MessageResult::SUCCESS; + } + } + } + return GatorApi::MessageResult::ERROR; +} + +void GatorApi::processMessage(GatorMessage &message) +{ + if(!message.getData().empty() && message.getType() == RESPONSE_APC_DATA && + message.getPackedInt() == FRAME_BLOCK_COUNTER) + { + processBlockCounter(message); + } +} + +void GatorApi::processBlockCounter(GatorMessage &message) +{ + (void) message.getPackedInt(); // skip first item in message + + while(message.hasRemaining()) + { + int64_t key = message.getPackedInt(); + int64_t value = message.getPackedInt(); + + if(isValidKey(key)) + { + Value v; + v.as_int = value; + for(LizardCounter counter : m_availableCounters) + { + if(counter.internalKey() == (uint64_t)key) + { + m_data.addValue(counter.id(), v); + } + } + } + } +} + +bool GatorApi::isValidKey(int64_t key) +{ + return key > 2; +} + +} /* namespace lizard */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/gator_api.hpp b/renderdoc/driver/ihv/arm/official/lizard/gator_api.hpp new file mode 100644 index 0000000000..62cc10fd92 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/gator_api.hpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef GATOR_API_H +#define GATOR_API_H + +#include + +#include "../../gator_message.hpp" +#include "lizard_counter.hpp" +#include "socket.hpp" + +namespace lizard +{ +#define GATOR_PROTOCOL_VERSION "VERSION 671\n"; +#define STREAMLINE "STREAMLINE\n"; + +class GatorApi +{ +public: + enum MessageResult + { + SUCCESS, + ERROR, + }; + + GatorApi(char *host, const uint32_t port, std::vector &availableCounters, + LizardCounterDataStore &dataStore); + ~GatorApi(); + bool createConnection(); + void destroyConnection(); + bool init(uint32_t &counterId); + bool sendVersion(); + void startCapture(); + void stopCapture(); + void sendDisconnect(); + MessageResult readMessage(GatorMessage &message); + void processMessage(GatorMessage &message); + bool resendConfiguration(const std::vector &enabledGatorCounters); + bool startSession(); + +private: + bool setupCapturedCounters(); + bool sendConfiguration(const std::vector &enabledCounters); + bool sendSession(); + void requestXml(const std::string &attributeValue); + void sendXml(const std::string &xml); + uint8_t getResponse(); + std::string getXmlResponse(); + Socket::Result getResponseHeader(uint8_t *responseType, uint32_t *responseSize); + void sendCommand(uint8_t command); + std::string requestCounters(); + std::string requestEvents(); + std::string requestConfiguration(); + std::string requestDefaults(); + std::string requestCaptured(); + void processBlockCounter(GatorMessage &message); + bool isValidKey(int64_t key); + + char *m_host; + const uint32_t m_port; + Socket *m_connection; + std::vector &m_availableCounters; + LizardCounterDataStore &m_data; +}; + +} /* namespace lizard */ + +#endif // GATOR_API_H diff --git a/renderdoc/driver/ihv/arm/official/lizard/gator_constants.hpp b/renderdoc/driver/ihv/arm/official/lizard/gator_constants.hpp new file mode 100644 index 0000000000..83f91523f3 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/gator_constants.hpp @@ -0,0 +1,88 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef GATOR_CONSTANTS_H +#define GATOR_CONSTANTS_H + +namespace lizard +{ +enum +{ + FRAME_UNKNOWN = 0, + FRAME_SUMMARY = 1, + FRAME_BACKTRACE = 2, + FRAME_NAME = 3, + FRAME_COUNTER = 4, + FRAME_BLOCK_COUNTER = 5, + FRAME_ANNOTATE = 6, + FRAME_SCHED_TRACE = 7, + FRAME_IDLE = 9, + FRAME_EXTERNAL = 10, + FRAME_PERF_ATTRS = 11, + FRAME_PROC = 11, + FRAME_PERF = 12, + FRAME_ACTIVITY_TRACE = 13, +}; + +enum +{ + RESPONSE_XML = 1, + RESPONSE_APC_DATA = 3, + RESPONSE_ACK = 4, + RESPONSE_NAK = 5, + RESPONSE_ERROR = 0xFF +}; + +enum +{ + COMMAND_REQUEST_XML = 0, + COMMAND_DELIVER_XML = 1, + COMMAND_APC_START = 2, + COMMAND_APC_STOP = 3, + COMMAND_DISCONNECT = 4, + COMMAND_PING = 5 +}; + +enum +{ + CLASS_UNKNOWN, + CLASS_ABSOLUTE, + CLASS_ACTIVITY, + CLASS_DELTA, + CLASS_INCIDENT +}; + +enum +{ + DISPLAY_UNKNOWN, + DISPLAY_ACCUMULATE, + DISPLAY_AVERAGE, + DISPLAY_MAXIMUM, + DISPLAY_MINIMUM, + DISPLAY_HERTZ +}; + +} /* namespace lizard */ + +#endif // GATOR_CONSTANTS_H diff --git a/renderdoc/driver/ihv/arm/official/lizard/gator_message.cpp b/renderdoc/driver/ihv/arm/official/lizard/gator_message.cpp new file mode 100644 index 0000000000..c50b92d973 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/gator_message.cpp @@ -0,0 +1,91 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 "gator_message.hpp" +#include "message_util.hpp" + +namespace lizard +{ +GatorMessage::GatorMessage() : m_type(0), m_pos(0) +{ +} + +GatorMessage::GatorMessage(const std::vector &in, uint8_t type) + : m_in(in), m_type(type), m_pos(0) +{ +} + +GatorMessage::~GatorMessage() +{ +} + +void GatorMessage::setType(uint8_t type) +{ + m_type = type; +} + +uint8_t GatorMessage::getType() +{ + return m_type; +} + +void GatorMessage::setData(const std::vector &data) +{ + m_in = data; +} + +const std::vector &GatorMessage::getData() +{ + return m_in; +} + +bool GatorMessage::hasData() +{ + return !m_in.empty(); +} + +bool GatorMessage::hasRemaining() +{ + return m_pos < (m_in.size() - 1); +} + +int64_t GatorMessage::getPackedInt() +{ + unsigned int sizeRead; + int64_t value = decodeSLEB128(&m_in[m_pos], &sizeRead); + m_pos += sizeRead; + return value; +} + +std::string GatorMessage::getGatorString() +{ + unsigned int sizeRead; + int64_t stringLength = decodeSLEB128(&m_in[m_pos], &sizeRead); + m_pos += sizeRead; + std::string result(m_in.begin() + m_pos, m_in.begin() + m_pos + stringLength); + m_pos += stringLength; + return result; +} + +} /* namespace lizard */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/gator_message.hpp b/renderdoc/driver/ihv/arm/official/lizard/gator_message.hpp new file mode 100644 index 0000000000..9ad4283452 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/gator_message.hpp @@ -0,0 +1,57 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef GATOR_MESSAGE_H +#define GATOR_MESSAGE_H + +#include +#include +#include "stdint.h" + +namespace lizard +{ +class GatorMessage +{ +public: + GatorMessage(); + GatorMessage(const std::vector &in, uint8_t type); + ~GatorMessage(); + int64_t getPackedInt(); + std::string getGatorString(); + bool hasRemaining(); + bool hasData(); + void setType(uint8_t type); + uint8_t getType(); + void setData(const std::vector &data); + const std::vector &getData(); + +private: + std::vector m_in; + uint8_t m_type; + unsigned int m_pos; +}; + +} /* namespace lizard */ + +#endif // GATOR_MESSAGE_H diff --git a/renderdoc/driver/ihv/arm/official/lizard/gatord_xml_reader.cpp b/renderdoc/driver/ihv/arm/official/lizard/gatord_xml_reader.cpp new file mode 100644 index 0000000000..456573b0fe --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/gatord_xml_reader.cpp @@ -0,0 +1,266 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 "gatord_xml_reader.hpp" + +#include +#include +#include + +#include "gator_constants.hpp" + +#include + +namespace lizard +{ +static void reportXmlError(pugi::xml_parse_result result, const void *xmlData, size_t xmlSize) +{ + std::cout << "XML [] parsed with errors: "; + std::cout << "Error description: " << result.description() << "\n"; + std::cout << "Error offset: " << result.offset << " (error at [..." + << (static_cast(xmlData) + result.offset) << "]\n\n"; +} + +static uint8_t strToEventClass(const std::string &eventClass) +{ + if(eventClass == "absolute") + { + return CLASS_ABSOLUTE; + } + else if(eventClass == "activity") + { + return CLASS_ACTIVITY; + } + else if(eventClass == "delta") + { + return CLASS_DELTA; + } + else if(eventClass == "incident") + { + return CLASS_INCIDENT; + } + else + { + return CLASS_UNKNOWN; + } +} + +static uint8_t strToEventDisplay(const std::string &eventDisplay) +{ + if(eventDisplay == "accumulate") + { + return DISPLAY_ACCUMULATE; + } + else if(eventDisplay == "average") + { + return DISPLAY_AVERAGE; + } + else if(eventDisplay == "maximum") + { + return DISPLAY_MAXIMUM; + } + else if(eventDisplay == "minimum") + { + return DISPLAY_MINIMUM; + } + else if(eventDisplay == "hertz") + { + return DISPLAY_HERTZ; + } + else + { + return DISPLAY_UNKNOWN; + } +} + +static LizardCounter::UnitType strToEventUnits(const std::string &eventUnits) +{ + if(eventUnits == "B") + { + return LizardCounter::UNITS_BYTE; + } + else if(eventUnits == "Hz") + { + return LizardCounter::UNITS_HZ; + } + else if(eventUnits == "MHz") + { + return LizardCounter::UNITS_MHZ; + } + else if(eventUnits == "pages") + { + return LizardCounter::UNITS_PAGES; + } + else if(eventUnits == "s") + { + return LizardCounter::UNITS_S; + } + else if(eventUnits == "V") + { + return LizardCounter::UNITS_V; + } + else if(eventUnits == "mV") + { + return LizardCounter::UNITS_MV; + } + else if(eventUnits == "°C") + { + return LizardCounter::UNITS_CELSIUS; + } + else if(eventUnits == "RPM") + { + return LizardCounter::UNITS_RPM; + } + else + { + return LizardCounter::UNITS_UNKNOWN; + } +} + +std::vector GatordXML::parseConfiguration(const void *xmlData, + size_t xmlSize) +{ + std::vector configurations; + + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_buffer(xmlData, xmlSize); + + if(result) + { + for(pugi::xml_node &cfg : doc.child("configurations").children("configuration")) + { + std::string name = cfg.attribute("counter").as_string(); + uint32_t event = cfg.attribute("event").as_uint(); + uint32_t cores = cfg.attribute("cores").as_uint(); + + assert(name.size() > 0); + + configurations.push_back({name, event, cores}); + } + } + else + { + reportXmlError(result, xmlData, xmlSize); + } + + return configurations; +} + +std::vector GatordXML::parseCounters(const void *xmlData, size_t xmlSize) +{ + std::vector counters; + + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_buffer(xmlData, xmlSize); + + if(result) + { + for(pugi::xml_node &cfg : doc.child("counters").children("counter")) + { + std::string name = cfg.attribute("name").as_string(); + assert(name.size() > 0); + counters.push_back(name); + } + } + else + { + reportXmlError(result, xmlData, xmlSize); + } + + return counters; +} + +std::vector GatordXML::parseEvents(const void *xmlData, size_t xmlSize) +{ + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_buffer(xmlData, xmlSize); + + if(!result) + { + reportXmlError(result, xmlData, xmlSize); + return {}; + } + + std::vector eventCategories; + + for(pugi::xml_node &categoryNode : doc.child("events").children("category")) + { + GatordXML::EventCategory category; + category.name = categoryNode.attribute("name").as_string(); + assert(category.name.size() > 0); + + for(pugi::xml_node &eventNode : categoryNode.children("event")) + { + GatordXML::Event event; + event.name = eventNode.attribute("name").as_string(); + event.title = eventNode.attribute("title").as_string(); + event.counter = eventNode.attribute("counter").as_string(); + event.description = eventNode.attribute("description").as_string(); + event.event = eventNode.attribute("event").as_uint(); + event.eventClass = strToEventClass(eventNode.attribute("class").as_string()); + event.display = strToEventDisplay(eventNode.attribute("display").as_string()); + event.units = strToEventUnits(eventNode.attribute("units").as_string()); + event.multiplier = eventNode.attribute("multiplier").as_double(); + if(event.multiplier == 0) + { + event.multiplier = 1; + } + assert(event.name.size() > 0); + + category.events.push_back(event); + } + + eventCategories.push_back(category); + } + + return eventCategories; +} + +std::vector GatordXML::parseCapturedCounters(const void *xmlData, + size_t xmlSize) +{ + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_buffer(xmlData, xmlSize); + + if(!result) + { + reportXmlError(result, xmlData, xmlSize); + return {}; + } + + std::vector capturedCounters; + + for(pugi::xml_node &counterNode : doc.child("captured").child("counters")) + { + GatordXML::CapturedCounter counter; + counter.key = counterNode.attribute("key").as_int(); + counter.type = counterNode.attribute("type").as_string(); + counter.event = counterNode.attribute("event").as_int(); + capturedCounters.push_back(counter); + } + + return capturedCounters; +} + +} /* namespace lizard */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/gatord_xml_reader.hpp b/renderdoc/driver/ihv/arm/official/lizard/gatord_xml_reader.hpp new file mode 100644 index 0000000000..da2ce4fe84 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/gatord_xml_reader.hpp @@ -0,0 +1,79 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef LIB_GATORD_XML_READER_HPP +#define LIB_GATORD_XML_READER_HPP + +#include +#include + +#include "lizard_counter.hpp" + +namespace lizard +{ +namespace GatordXML +{ +struct Configuration +{ + std::string name; + uint32_t event; + uint32_t cores; +}; + +std::vector parseConfiguration(const void *xmlData, size_t xmlSize); +std::vector parseCounters(const void *xmlData, size_t xmlSize); + +struct Event +{ + std::string title; + std::string name; + std::string description; + uint32_t event; + std::string counter; + uint8_t eventClass; + uint8_t display; + LizardCounter::UnitType units; + double multiplier; +}; +struct EventCategory +{ + std::string name; + std::vector events; +}; + +std::vector parseEvents(const void *xmlData, size_t xmlSize); + +struct CapturedCounter +{ + uint32_t key; + std::string type; + uint32_t event; +}; + +std::vector parseCapturedCounters(const void *xmlData, size_t xmlSize); +} + +} /* namespace lizard */ + +#endif /* LIB_GATORD_XML_READER_HPP */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_api.cpp b/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_api.cpp new file mode 100644 index 0000000000..643b03fa3b --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_api.cpp @@ -0,0 +1,172 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 "hwcpipe_api.hpp" + +namespace lizard +{ +HwcPipeApi::HwcPipeApi(std::vector &availableCounters, + LizardCounterDataStore &dataStore) + : m_availableCounters(availableCounters), m_data(dataStore), m_HwcPipe(NULL) +{ +} + +HwcPipeApi::~HwcPipeApi() +{ + if(m_HwcPipe) + { + delete m_HwcPipe; + } +} + +template +LizardCounter createCounter(uint64_t counterId, TID hwcpipeId, + const std::unordered_map &names, + const std::unordered_map &info, + const std::string &category, const LizardCounter::SourceType sourceType) +{ + std::string title; + for(auto &i : names) + { + if(i.second == hwcpipeId) + { + title = i.first; + break; + } + } + std::string desc = (info.at(hwcpipeId)).desc; + std::string unit = (info.at(hwcpipeId)).unit; + std::string key = ""; + std::string name = ""; + LizardCounter cnt = LizardCounter( + ++counterId, key.c_str(), name.c_str(), title.c_str(), desc.c_str(), category.c_str(), 1, + unit.compare("B") == 0 ? LizardCounter::UNITS_BYTE : LizardCounter::UNITS_UNKNOWN, + LizardCounter::CLASS_ABSOLUTE, sourceType); + cnt.setInternalKey((uint64_t)hwcpipeId); + return cnt; +} + +bool HwcPipeApi::init(uint32_t &counterId) +{ + m_HwcPipe = new hwcpipe::HWCPipe(); + + uint64_t counterNum = counterId; + + if(m_HwcPipe->cpu_profiler()) + { + for(hwcpipe::CpuCounter hwcpipeId : m_HwcPipe->cpu_profiler()->supported_counters()) + { + m_availableCounters.push_back(createCounter(++counterId, hwcpipeId, hwcpipe::cpu_counter_names, + hwcpipe::cpu_counter_info, "HWCPipe CPU Counter", + LizardCounter::SOURCE_HWCPIPE_CPU)); + } + } + + if(m_HwcPipe->gpu_profiler()) + { + for(hwcpipe::GpuCounter hwcpipeId : m_HwcPipe->gpu_profiler()->supported_counters()) + { + m_availableCounters.push_back(createCounter(++counterId, hwcpipeId, hwcpipe::gpu_counter_names, + hwcpipe::gpu_counter_info, "HWCPipe GPU Counter", + LizardCounter::SOURCE_HWCPIPE_GPU)); + } + } + + return counterId > counterNum; +} + +void HwcPipeApi::enableCounters(const std::vector &counters) +{ + hwcpipe::CpuCounterSet cpuCounterSet; + hwcpipe::GpuCounterSet gpuCounterSet; + + for(LizardCounter counter : counters) + { + switch(counter.sourceType()) + { + case LizardCounter::SourceType::SOURCE_HWCPIPE_CPU: + cpuCounterSet.insert((hwcpipe::CpuCounter)counter.internalKey()); + break; + case LizardCounter::SourceType::SOURCE_HWCPIPE_GPU: + gpuCounterSet.insert((hwcpipe::GpuCounter)counter.internalKey()); + break; + default: break; + } + } + + m_HwcPipe->set_enabled_cpu_counters(cpuCounterSet); + m_HwcPipe->set_enabled_gpu_counters(gpuCounterSet); +} + +void HwcPipeApi::startCapture() +{ + m_HwcPipe->run(); + m_HwcPipe->sample(); +} + +void HwcPipeApi::stopCapture() +{ + m_HwcPipe->stop(); +} + +void HwcPipeApi::readMessage() +{ + hwcpipe::Measurements measurements = m_HwcPipe->sample(); + if(measurements.cpu) + { + for(const std::pair &data : *measurements.cpu) + { + for(LizardCounter &counter : m_availableCounters) + { + if(counter.sourceType() == LizardCounter::SourceType::SOURCE_HWCPIPE_CPU && + counter.internalKey() == (uint64_t)data.first) + { + Value value; + value.as_double = data.second.get(); + m_data.addValue(counter.id(), value); + break; + } + } + } + } + + if(measurements.gpu) + { + for(const std::pair &data : *measurements.gpu) + { + for(LizardCounter &counter : m_availableCounters) + { + if(counter.sourceType() == LizardCounter::SourceType::SOURCE_HWCPIPE_GPU && + counter.internalKey() == (uint64_t)data.first) + { + Value value; + value.as_double = data.second.get(); + m_data.addValue(counter.id(), value); + break; + } + } + } + } +} +} diff --git a/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_api.hpp b/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_api.hpp new file mode 100644 index 0000000000..37f649fdd3 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_api.hpp @@ -0,0 +1,51 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef LIB_HWCPIPE_API_H +#define LIB_HWCPIPE_API_H + +#include "thirdparty/hwcpipe/hwcpipe.h" +#include "lizard_counter.hpp" + +namespace lizard +{ +class HwcPipeApi +{ +public: + HwcPipeApi(std::vector &availableCounters, LizardCounterDataStore &dataStore); + ~HwcPipeApi(); + bool init(uint32_t &counterNum); + void enableCounters(const std::vector &counters); + void startCapture(); + void stopCapture(); + void readMessage(); + +private: + std::vector &m_availableCounters; + LizardCounterDataStore &m_data; + hwcpipe::HWCPipe *m_HwcPipe; +}; +} + +#endif /* LIB_HWCPIPE_API_H */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_communication.cpp b/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_communication.cpp new file mode 100644 index 0000000000..9605dc4283 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_communication.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 + +#include + +namespace lizard +{ +HwcPipeThread::HwcPipeThread(HwcPipeApi &hwcPipeApi) + : m_HwcPipeApi(hwcPipeApi), m_thread() +{ +} + +HwcPipeThread::~HwcPipeThread() +{ +} + +void HwcPipeThread::start(void) +{ + m_shouldWork = true; + m_HwcPipeApi.startCapture(); + m_thread = std::thread(&HwcPipeThread::worker, this); +} + +void HwcPipeThread::stop(void) +{ + m_shouldWork = false; + m_thread.join(); + m_HwcPipeApi.stopCapture(); +} + +void HwcPipeThread::worker(void) +{ + while(m_shouldWork != false) + { + m_HwcPipeApi.readMessage(); + } + m_HwcPipeApi.readMessage(); +} + +} diff --git a/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_communication.hpp b/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_communication.hpp new file mode 100644 index 0000000000..c159a0271e --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/hwcpipe_communication.hpp @@ -0,0 +1,54 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef LIB_HWCPIPE_COMMUNICATION_HPP +#define LIB_HWCPIPE_COMMUNICATION_HPP + +#include +#include + +#include "hwcpipe_api.hpp" + +namespace lizard +{ +class HwcPipeThread +{ +public: + HwcPipeThread(HwcPipeApi &hwcPipeApi); + ~HwcPipeThread(void); + + void start(void); + void stop(void); + +private: + void worker(void); + + std::atomic m_shouldWork; + HwcPipeApi& m_HwcPipeApi; + std::thread m_thread; +}; + +} /* namespace lizard */ + +#endif /* LIB_HWCPIPE_COMMUNICATION_HPP */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard.hpp b/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard.hpp new file mode 100644 index 0000000000..ddbed7f44b --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard.hpp @@ -0,0 +1,176 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef LIB_LIZARD_HPP +#define LIB_LIZARD_HPP + +#include +#include + +#include + +namespace lizard +{ +class GatorApi; +class CommunicationThread; +class HwcPipeApi; +class HwcPipeThread; + +class Lizard +{ +public: + Lizard(void); + + ~Lizard(void); + + /** + * Set the gatord hostname and port number to connect to. + * + * :param hostname: should be an ipv4 compatible address or hostname. + * :param port: port number. + */ + bool configure(const char *hostname, uint32_t port); + + /** + * Query the list of available counters into an array. + * + * Usage: + * { + * Lizard lzd; // lzd should be configured after initialization! + * + * int count = lzd.availableCountersCount(); + * std::vector counters; + * counters.reserve(count); + * + * int copied = lzd.availableCounters(&counters[0], count)); + * } + * + * :param outCounter: output array of available counters. + * :param arraySize: size (element count) of the `outCounter` array. + * :returns: the number of `LizardCounter` elements copied into the `outCounter` array. + */ + uint32_t availableCounters(LizardCounter *outCounters, uint32_t arraySize); + + /** + * Query the list of available counters (non-copy). + * + * Usage: + * { + * Lizard lzd; // lzd should be configured after initialization! + * + * int count = lzd.availableCountersCount(); + * LizardCounter *counterslzd.availableCounters(); + * } + * + * :returns: a pointer to a `LizardCounter` array containing maximum `availableCountersCount()` + * elements. + */ + const LizardCounter *availableCounters(void) const { return &m_availableCounters[0]; } + + /** + * Query the number of available counters; + * + * Usage: + * See `availableCounters`. + * + * :returns: number of `LizardCounter` elements available. + */ + uint32_t availableCountersCount(void) const; + + /** + * Enable a set of counters based on Id values. + * + * Usage: + * { + * Lizard lzd; // lzd should be configured after initialization! + * + * std::vector counters; + * // fill counters with required counters. + * // ... + * // Enable the first three counters. + * std::vector ids; + * ids.reserve(3); + * lizard::countersToIds(&counters[0], &ids[0], 3); + * + * lzd.enableCounters(&ids[0], 3); + * } + * + * :param counterIds: array of `LizardCounterId` values to enable. + * :param arraySize: size (element count) of the `counterIds` array. + */ + void enableCounters(const LizardCounterId *counterIds, uint32_t arraySize); + + void disableCounters(const LizardCounterId *counterIds, uint32_t arraySize); + + /** + * Start the capture of the enabled counters. + * + * This operation does not block. Underlying communication is done in a different thread. + * + * :returns: true if the capture was started correctly, otherwise false. + */ + bool startCapture(void); + + /** + * Stops the capture. + * + * Captured data can be accessed via another method. + */ + void endCapture(void); + + LizardCounterData *readCounter(const LizardCounterId counterId) const; + + size_t readCounterInt(const LizardCounterId counterId, int64_t *values) const; + size_t readCounterDouble(const LizardCounterId counterId, double *values) const; + + const LizardCounter *getCounterInfo(const LizardCounterId counterId) const; + +private: + bool configureGatord(const char *hostname, uint32_t port); + bool configureHwcPipe(void); + bool startGatord(void); + void stopGatord(void); + bool startHwcPipe(void); + void stopHwcPipe(void); + + uint32_t m_idCounter; + + std::vector m_availableCounters; + std::vector m_enabledCounters; + + GatorApi *m_gatorApi; + CommunicationThread *m_comm; + + HwcPipeApi *m_HwcPipeApi; + HwcPipeThread *m_HwcPipe_comm; + + bool m_configuredGatord; + bool m_configuredHwcPipe; + + LizardCounterDataStore m_dataStore; +}; + +} /* namepsace lizard */ + +#endif /* LIB_LIZARD_HPP */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard_api.h b/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard_api.h new file mode 100644 index 0000000000..4f1d44494f --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard_api.h @@ -0,0 +1,234 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef LIB_LIZARD_API_H +#define LIB_LIZARD_API_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif // End of __cplusplus + +struct LizardApi; +typedef void *LizardInstance; +typedef uint32_t LizardCounterId; + +enum LizardVersion +{ + LIZARD_VERSION_0_1 = 1, +}; + +typedef enum { + LZD_OK = 0, + LZD_FAILURE, +} LZD_Result; + +/** + * LizardInstance* LZD_Init(const char* host, int port); + * + * Initializes a Lizard Instance with the given host:port arguments. + * The Lizard Instance must be destroyed with the LZD_Destroy method. + * + * :param host: IP address of the target gatord. + * :param port: Port number of the target gatord. + */ +typedef LizardInstance (*LZD_Init_PFN)(const char *host, int port); + +/** + * void LZD_Destroy(LizardInstance** ctx); + * + * Destroy the Lizard Instance and sets the `ctx` pointer's value to NULL. + */ +typedef void (*LZD_Destroy_PFN)(LizardInstance ctx); + +/** + * Get the number of the available counters. + * + * The LizardIds are in the range of [1, MAX_UINT]. + * + * :param ctx: LizardInstance created via LZD_Init. + * :returns: Number of available counters. + */ +typedef uint32_t (*LZD_GetAvailableCountersCount_PFN)(LizardInstance ctx); + + +struct LizardCounterDescription +{ + LizardCounterId id; + const char *short_name; + const char *name; + const char *title; + const char *description; + const char *category; + double multiplier; + uint32_t units; + uint32_t class_type; + uint32_t result_type; +}; + +/** + * Get information about the counter + * + * :param ctx: LizardInstance created via LZD_Init. + * :param id: id of the counter, must be 1 or above. + * :param lzdDesc: LizardCounterDescription to be populated. + * :returns: LZD_OK if succeeded + */ +typedef LZD_Result (*LZD_GetCounterDescription_PFN)(LizardInstance ctx, LizardCounterId id, + LizardCounterDescription *lzdDesc); + +/** + * Enable the counter for capture. + * + * :param ctx: Lizard Instance created via LZD_Init. + * :param id: Id of the counter to enable. + */ +typedef void (*LZD_EnableCounter_PFN)(LizardInstance ctx, LizardCounterId id); + +/** + * Disable the counter for capture. + * + * :param ctx: Lizard Instance created via LZD_Init + * :param id: Id of the counter to disable. + */ +typedef void (*LZD_DisableCounter_PFN)(LizardInstance ctx, LizardCounterId id); + +/** + * Disable all counters for capture. + * + * By default all counters are disabled. + * + * :param ctx: Lizard Instance created via LZD_Init + */ +typedef void (*LZD_DisableAllCounters_PFN)(LizardInstance ctx); + +/** + * Start capture. + * + * The actual capture is performed in a different thread. + * + * :param ctx: Lizard Instance created via LZD_Init + * :returns: LZD_OK if succeeded + */ +typedef LZD_Result (*LZD_StartCapture_PFN)(LizardInstance ctx); + +/** + * Stop capture. + * + * :param ctx: Lizard Instance created via LZD_Init + * :returns: LZD_OK if succeeded + */ +typedef LZD_Result (*LZD_StopCapture_PFN)(LizardInstance ctx); + +typedef enum { + LZD_ABSOLUTE = 1, + LZD_DELTA = 2, +} LZD_CounterClassType; + +/** + * Get the measured counter value as an integer. + * + * :param ctx: Lizard Instance created via LZD_Init + * :param id: The id of the counter which value is measured. + * :returns: The measured value. + */ +typedef int64_t (*LZD_ReadCounterInt_PFN)(LizardInstance ctx, LizardCounterId id); + +/** + * Get the measured counter value as a double. + * + * :param ctx: Lizard Instance created via LZD_Init + * :param id: The id of the counter which value is measured. + * :returns: The measured value. + */ +typedef double (*LZD_ReadCounterDouble_PFN)(LizardInstance ctx, LizardCounterId id); + +typedef enum { + LZD_UNITS_UNKNOWN, + LZD_UNITS_BYTE, + LZD_UNITS_CELSIUS, + LZD_UNITS_HZ, + LZD_UNITS_PAGES, + LZD_UNITS_RPM, + LZD_UNITS_S, + LZD_UNITS_V, + + LZD_TYPE_INT, + LZD_TYPE_DOUBLE, +} LZD_CounterAttribute; + +struct LizardApi +{ + int struct_size; + int version; + LZD_Init_PFN Init; + LZD_Destroy_PFN Destroy; + LZD_GetAvailableCountersCount_PFN GetAvailableCountersCount; + LZD_GetCounterDescription_PFN GetCounterDescription; + LZD_EnableCounter_PFN EnableCounter; + LZD_DisableCounter_PFN DisableCounter; + LZD_DisableAllCounters_PFN DisableAllCounters; + + LZD_StartCapture_PFN StartCapture; + LZD_StopCapture_PFN StopCapture; + + LZD_ReadCounterInt_PFN ReadCounterInt; + LZD_ReadCounterDouble_PFN ReadCounterDouble; +}; + +/** + * Entry point of the API. + * + * To load the api search for the "LoadApi" function symbol and + * invoke the method with a `LizardApi` pointer to get access to all + * API functions. + * + * Example usage: + * + * void* lib = dlopen("liblizard.so", RTLD_LAZY); + * LZD_LoadApi_PFN loadApi = (LZD_LoadApi_PFN)dlsym(lib, "LoadApi"); + * + * struct LizardApi* api; + * + * if (loadApi(&api) != LZD_OK) { + * // report failure and return + * } + * if (api->version != LIZARD_VERSION_0_1) { + * // report version mismatch and return + * } + * + * LizardInstance* ctx = api->Init("127.0.0.1", 8080); + * + * :param api: LizardApi struct pointer to initialize the API pointers. + * :returns: LZD_OK if the counter initialization was ok. + */ +typedef LZD_Result (*LZD_LoadApi_PFN)(struct LizardApi **api); +LZD_Result LoadApi(struct LizardApi **api); + +#ifdef __cplusplus +} +#endif // End of __cplusplus + +#endif /* LIB_LIZARD_API_H */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard_counter.hpp b/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard_counter.hpp new file mode 100644 index 0000000000..79f535a58c --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/include/lizard/lizard_counter.hpp @@ -0,0 +1,136 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef LIB_LIZARD_COUNTER_HPP +#define LIB_LIZARD_COUNTER_HPP + +#include +#include +#include + +namespace lizard +{ +typedef uint32_t LizardCounterId; + +typedef union +{ + int64_t as_int; + double as_double; +} Value; + +class LizardCounterData +{ +public: + LizardCounterData(LizardCounterId id, const int64_t *values, size_t length); + LizardCounterData(LizardCounterId id, const double *values, size_t length); + ~LizardCounterData(void); + const int64_t *getIntValues() const { return reinterpret_cast(m_values); } + const double *getDoubleValues() const { return reinterpret_cast(m_values); } + const Value *getValues() const { return m_values; } + LizardCounterId getId() const { return m_id; } + size_t getLength() const { return m_length; } + bool isInt() const { return m_is_int; } +private: + LizardCounterId m_id; + Value *m_values; + size_t m_length; + bool m_is_int; +}; + +class LizardCounter +{ +public: + enum ClassType + { + CLASS_ABSOLUTE, + CLASS_DELTA, + }; + + enum SourceType + { + SOURCE_GATORD, + SOURCE_HWCPIPE_CPU, + SOURCE_HWCPIPE_GPU, + }; + + enum UnitType + { + UNITS_UNKNOWN, + UNITS_BYTE, + UNITS_CELSIUS, + UNITS_HZ, + UNITS_MHZ, + UNITS_PAGES, + UNITS_RPM, + UNITS_S, + UNITS_V, + UNITS_MV + }; + + LizardCounter() : m_id(0), m_multiplier(1) {} + LizardCounter(LizardCounterId id, const char *key, const char *name, const char *title, + const char *description, const char *category, const double multiplier, + UnitType units, ClassType classType, SourceType sourceType); + ~LizardCounter(void) {} + LizardCounterId id(void) const { return m_id; } + const char *key(void) const { return m_key.c_str(); } + const char *name(void) const { return m_name.c_str(); } + const char *title(void) const { return m_title.c_str(); } + const char *description(void) const { return m_description.c_str(); } + const char *category(void) const { return m_category.c_str(); } + double multiplier(void) const { return m_multiplier; } + UnitType units(void) const { return m_units; } + ClassType classType(void) const { return m_classType; } + SourceType sourceType(void) const { return m_sourceType; } + uint64_t internalKey(void) const { return m_internalKey; } + void setInternalKey(uint64_t key); + +private: + const LizardCounterId m_id; + std::string m_key; + std::string m_name; + std::string m_title; + std::string m_description; + std::string m_category; + double m_multiplier; + UnitType m_units; + ClassType m_classType; + SourceType m_sourceType; + uint64_t m_internalKey; +}; + +class LizardCounterDataStore +{ +public: + void addValue(int64_t key, Value value); + const std::vector &getValues(int64_t key) const; + void clear(); + +private: + std::map> m_values; +}; + +}; /* namespace lizard */ + +#endif /* LIB_LIZARD_COUNTER_HPP */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/lizard.cpp b/renderdoc/driver/ihv/arm/official/lizard/lizard.cpp new file mode 100644 index 0000000000..ba9041752e --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/lizard.cpp @@ -0,0 +1,341 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 "lizard.hpp" + +#include +#include +#include +#include +#include +#include + +#include "gator_api.hpp" +#include "hwcpipe_communication.hpp" +#include "lizard_communication.hpp" +#include "lizard_counter.hpp" + +namespace lizard +{ +enum +{ + MAX_HOSTNAME_SIZE = 64, +}; + +Lizard::Lizard(void) + : m_idCounter(0), + m_availableCounters(), + m_enabledCounters(), + m_gatorApi(NULL), + m_comm(NULL), + m_HwcPipeApi(NULL), + m_HwcPipe_comm(NULL) +{ +} + +Lizard::~Lizard() +{ + if(m_gatorApi) + { + delete m_gatorApi; + } + if(m_HwcPipeApi) + { + delete m_HwcPipeApi; + } +} + +bool Lizard::configure(const char *hostname, uint32_t port) +{ + m_availableCounters.clear(); + + m_configuredGatord = configureGatord(hostname, port); + m_configuredHwcPipe = configureHwcPipe(); + if(m_configuredGatord || m_configuredHwcPipe) + { + m_availableCounters.shrink_to_fit(); + m_enabledCounters.clear(); + m_enabledCounters.resize(m_availableCounters.size() + 1); // +1 as 0 ID is invalid + return true; + } + return false; +} + +bool Lizard::configureGatord(const char *hostname, uint32_t port) +{ + m_gatorApi = new lizard::GatorApi(strndup(hostname, MAX_HOSTNAME_SIZE), port, m_availableCounters, + m_dataStore); + + if(!m_gatorApi->createConnection()) + { + return false; + } + + if(!m_gatorApi->sendVersion()) + { + m_gatorApi->destroyConnection(); + return false; + } + + bool success = m_gatorApi->init(m_idCounter); + + m_gatorApi->sendDisconnect(); + m_gatorApi->destroyConnection(); + + return success; +} + +uint32_t Lizard::availableCountersCount(void) const +{ + return m_availableCounters.size(); +} + +void Lizard::enableCounters(const LizardCounterId *counterIds, uint32_t arraySize) +{ + for(uint32_t idx = 0; idx < arraySize; idx++) + { + m_enabledCounters[counterIds[idx]] = true; + } +} + +void Lizard::disableCounters(const LizardCounterId *counterIds, uint32_t arraySize) +{ + for(uint32_t idx = 0; idx < arraySize; idx++) + { + m_enabledCounters[counterIds[idx]] = false; + } +} + +bool Lizard::startCapture(void) +{ + m_dataStore.clear(); + + bool started = false; + + if(m_configuredGatord) + { + started = startGatord() || started; + } + + if(m_configuredHwcPipe) + { + started = startHwcPipe() || started; + } + + return started; +} + +bool Lizard::startGatord() +{ + if(m_comm != NULL) + { + return false; + } + + std::vector enabledGatorCounters; + + for(size_t i = 0; i < m_availableCounters.size(); i++) + { + if(m_enabledCounters[m_availableCounters[i].id()] && + m_availableCounters[i].sourceType() == LizardCounter::SOURCE_GATORD) + { + enabledGatorCounters.push_back(m_availableCounters[i]); + } + } + + if(!m_gatorApi->resendConfiguration(enabledGatorCounters)) + { + return false; + } + + if(!m_gatorApi->startSession()) + { + return false; + } + + m_comm = new CommunicationThread(*m_gatorApi); + m_comm->start(); + + // Give gatord a bit of time to start up + usleep(1); + + return true; +} + +bool Lizard::startHwcPipe() +{ + if(m_HwcPipe_comm != NULL) + { + return false; + } + + std::vector enabledHwcPipeCounters; + + for(size_t i = 0; i < m_availableCounters.size(); i++) + { + if(m_enabledCounters[m_availableCounters[i].id()] && + (m_availableCounters[i].sourceType() == LizardCounter::SOURCE_HWCPIPE_CPU || + m_availableCounters[i].sourceType() == LizardCounter::SOURCE_HWCPIPE_GPU)) + { + enabledHwcPipeCounters.push_back(m_availableCounters[i]); + } + } + + if(enabledHwcPipeCounters.empty()) + { + return false; + } + + m_HwcPipeApi->enableCounters(enabledHwcPipeCounters); + + m_HwcPipe_comm = new HwcPipeThread(*m_HwcPipeApi); + m_HwcPipe_comm->start(); + + return true; +} + +void Lizard::endCapture(void) +{ + stopGatord(); + stopHwcPipe(); +} + +void Lizard::stopGatord(void) +{ + if(m_comm != NULL) + { + usleep(1); + m_comm->stop(); + + delete m_comm; + m_comm = NULL; + } +} + +void Lizard::stopHwcPipe(void) +{ + if(m_HwcPipe_comm != NULL) + { + m_HwcPipe_comm->stop(); + + delete m_HwcPipe_comm; + m_HwcPipe_comm = NULL; + } +} + +LizardCounterData *Lizard::readCounter(const LizardCounterId counterId) const +{ + if(counterId < 1 || counterId > m_availableCounters.size()) + { + return NULL; + } + + const std::vector &values = m_dataStore.getValues(counterId); + + switch(getCounterInfo(counterId)->sourceType()) + { + case LizardCounter::SOURCE_GATORD: + { + std::vector vec(values.size()); + for(size_t i = 0; i < values.size(); i++) + { + vec[i] = values[i].as_int; + } + return new LizardCounterData(counterId, (int64_t *)&vec[0], vec.size()); + } + case LizardCounter::SOURCE_HWCPIPE_CPU: + case LizardCounter::SOURCE_HWCPIPE_GPU: + { + std::vector vec(values.size()); + for(size_t i = 0; i < values.size(); i++) + { + vec[i] = values[i].as_double; + } + return new LizardCounterData(counterId, vec.data(), vec.size()); + } + } + + return NULL; +} + +size_t Lizard::readCounterInt(const LizardCounterId counterId, int64_t *values) const +{ + if(counterId < 1 || counterId > m_availableCounters.size()) + { + return 0; + } + + const std::vector &vals = m_dataStore.getValues(counterId); + std::vector vec(vals.size()); + + for(size_t i = 0; i < vals.size(); i++) + { + vec[i] = vals[i].as_int; + } + if(values) + { + memcpy(values, vec.data(), vec.size() * sizeof(int64_t)); + } + + return vec.size(); +} + +size_t Lizard::readCounterDouble(const LizardCounterId counterId, double *values) const +{ + if(counterId < 1 || counterId > m_availableCounters.size()) + { + return 0; + } + + const std::vector &vals = m_dataStore.getValues(counterId); + std::vector vec(vals.size()); + + for(size_t i = 0; i < vals.size(); i++) + { + vec[i] = vals[i].as_double; + } + if(values) + { + memcpy(values, vec.data(), vec.size() * sizeof(double)); + } + + return vec.size(); +} + +const LizardCounter *Lizard::getCounterInfo(const LizardCounterId counterId) const +{ + if(counterId < 1 || counterId > m_availableCounters.size()) + { + return NULL; + } + return &m_availableCounters[counterId - 1]; +} + +bool Lizard::configureHwcPipe() +{ + m_HwcPipeApi = new HwcPipeApi(m_availableCounters, m_dataStore); + return m_HwcPipeApi->init(m_idCounter); +} + +} /* namespace lizard */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/lizard_api.cpp b/renderdoc/driver/ihv/arm/official/lizard/lizard_api.cpp new file mode 100644 index 0000000000..efcd3d6247 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/lizard_api.cpp @@ -0,0 +1,280 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 + +#include +#include + +#include +#include + +static LizardInstance LZD_Init(const char *host, int port) +{ + lizard::Lizard *lzd = new lizard::Lizard(); + + bool configured = lzd->configure(host, port); + + if(!configured) + { + delete lzd; + return NULL; + } + + return static_cast(lzd); +} + +static void LZD_Destroy(LizardInstance ctx) +{ + delete static_cast(ctx); +} + +static uint32_t LZD_GetAvailableCountersCount(LizardInstance ctx) +{ + lizard::Lizard *lzd = static_cast(ctx); + + if(lzd == NULL) + { + return 0; + } + + return lzd->availableCountersCount(); +} + +static LZD_Result LZD_GetCounterDescription(LizardInstance ctx, LizardCounterId id, + LizardCounterDescription *desc) +{ + lizard::Lizard *lzd = static_cast(ctx); + + if(lzd == NULL || desc == NULL) + { + return LZD_FAILURE; + } + + uint32_t count = lzd->availableCountersCount(); + + if(id == 0 || id > count) + { + return LZD_FAILURE; + } + + const lizard::LizardCounter *lzdCounter = lzd->availableCounters() + (id - 1); + + desc->id = lzdCounter->id(); + desc->short_name = lzdCounter->key(); + desc->title = lzdCounter->title(); + desc->name = lzdCounter->name(); + desc->category = lzdCounter->category(); + desc->description = lzdCounter->description(); + desc->multiplier = lzdCounter->multiplier(); + + switch(lzdCounter->classType()) + { + case lizard::LizardCounter::CLASS_ABSOLUTE: desc->class_type = LZD_ABSOLUTE; break; + case lizard::LizardCounter::CLASS_DELTA: desc->class_type = LZD_DELTA; break; + default: break; + } + + switch(lzdCounter->units()) + { + case lizard::LizardCounter::UNITS_BYTE: desc->units = LZD_UNITS_BYTE; break; + case lizard::LizardCounter::UNITS_CELSIUS: desc->units = LZD_UNITS_CELSIUS; break; + case lizard::LizardCounter::UNITS_MHZ: + case lizard::LizardCounter::UNITS_HZ: desc->units = LZD_UNITS_HZ; break; + case lizard::LizardCounter::UNITS_PAGES: desc->units = LZD_UNITS_PAGES; break; + case lizard::LizardCounter::UNITS_RPM: desc->units = LZD_UNITS_RPM; break; + case lizard::LizardCounter::UNITS_S: desc->units = LZD_UNITS_S; break; + case lizard::LizardCounter::UNITS_V: desc->units = LZD_UNITS_V; break; + default: desc->units = LZD_UNITS_UNKNOWN; break; + } + + if(lzdCounter->multiplier() == 1 && lzdCounter->sourceType() == lizard::LizardCounter::SOURCE_GATORD) + { + desc->result_type = LZD_TYPE_INT; + } + else + { + desc->result_type = LZD_TYPE_DOUBLE; + } + + return LZD_OK; +} + +static void LZD_EnableCounter(LizardInstance ctx, LizardCounterId id) +{ + lizard::Lizard *lzd = static_cast(ctx); + if(lzd != NULL) + { + lzd->enableCounters(&id, 1); + } +} + +static void LZD_DisableCounter(LizardInstance ctx, LizardCounterId id) +{ + lizard::Lizard *lzd = static_cast(ctx); + if(lzd != NULL) + { + lzd->disableCounters(&id, 1); + } +} + +static void LZD_DisableAllCounters(LizardInstance ctx) +{ + lizard::Lizard *lzd = static_cast(ctx); + if(lzd != NULL) + { + uint32_t count = lzd->availableCountersCount(); + const lizard::LizardCounter *counters = lzd->availableCounters(); + + for(uint32_t idx = 0; idx < count; idx++) + { + lizard::LizardCounterId id = counters[idx].id(); + lzd->disableCounters(&id, 1); + } + } +} + +static LZD_Result LZD_StartCapture(LizardInstance ctx) +{ + lizard::Lizard *lzd = static_cast(ctx); + if(lzd == NULL) + { + return LZD_FAILURE; + } + bool result = lzd->startCapture(); + return result ? LZD_OK : LZD_FAILURE; +} + +static LZD_Result LZD_StopCapture(LizardInstance ctx) +{ + lizard::Lizard *lzd = static_cast(ctx); + if(lzd == NULL) + { + return LZD_FAILURE; + } + lzd->endCapture(); + return LZD_OK; +} + +static int64_t LZD_ReadCounterInt(LizardInstance ctx, LizardCounterId id) +{ + lizard::Lizard *lzd = static_cast(ctx); + + if(lzd == NULL) + { + return 0; + } + + size_t size = lzd->readCounterInt(id, nullptr); + + std::vector values(size); + + size = lzd->readCounterInt(id, values.data()); + + int64_t result = 0; + + for(size_t idx = 0; idx < size; idx++) + { + result += values[idx]; + } + + if(lzd->getCounterInfo(id)->classType() == lizard::LizardCounter::CLASS_ABSOLUTE && size != 0) + { + result /= size; + } + + if(lzd->getCounterInfo(id)->units() == lizard::LizardCounter::UNITS_MHZ) + { + result *= 1000000; + } + + return result * lzd->getCounterInfo(id)->multiplier(); +} + +static double LZD_ReadCounterDouble(LizardInstance ctx, LizardCounterId id) +{ + lizard::Lizard *lzd = static_cast(ctx); + + if(lzd == NULL) + { + return 0; + } + + size_t size = lzd->readCounterDouble(id, nullptr); + + std::vector values(size); + + size = lzd->readCounterDouble(id, values.data()); + + double result = 0; + + for(size_t idx = 0; idx < size; idx++) + { + result += values[idx]; + } + + if(lzd->getCounterInfo(id)->classType() == lizard::LizardCounter::CLASS_ABSOLUTE && size != 0) + { + result /= size; + } + + return result * lzd->getCounterInfo(id)->multiplier(); +} + +static struct LizardApi s_ApiInstance; + +static void InitApi(void) +{ + s_ApiInstance.struct_size = sizeof(struct LizardApi); + s_ApiInstance.version = LIZARD_VERSION_0_1; + s_ApiInstance.Init = &LZD_Init; + s_ApiInstance.Destroy = &LZD_Destroy; + s_ApiInstance.GetAvailableCountersCount = &LZD_GetAvailableCountersCount; + s_ApiInstance.GetCounterDescription = &LZD_GetCounterDescription; + s_ApiInstance.EnableCounter = &LZD_EnableCounter; + s_ApiInstance.DisableCounter = &LZD_DisableCounter; + s_ApiInstance.DisableAllCounters = &LZD_DisableAllCounters; + s_ApiInstance.StartCapture = &LZD_StartCapture; + s_ApiInstance.StopCapture = &LZD_StopCapture; + s_ApiInstance.ReadCounterInt = &LZD_ReadCounterInt; + s_ApiInstance.ReadCounterDouble = &LZD_ReadCounterDouble; +} + +extern "C" LZD_Result LoadApi(struct LizardApi **api) +{ + static bool initialized = false; + if(!initialized) + { + InitApi(); + initialized = true; + } + + if(api == NULL) + { + return LZD_FAILURE; + } + + *api = &s_ApiInstance; + return LZD_OK; +} diff --git a/renderdoc/driver/ihv/arm/official/lizard/lizard_communication.cpp b/renderdoc/driver/ihv/arm/official/lizard/lizard_communication.cpp new file mode 100644 index 0000000000..1fa81972fc --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/lizard_communication.cpp @@ -0,0 +1,69 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 "lizard_communication.hpp" + +#include "gator_api.hpp" +#include "gator_message.hpp" + +namespace lizard +{ +CommunicationThread::CommunicationThread(GatorApi &gatorApi) : m_gatorApi(gatorApi), m_thread() +{ +} + +CommunicationThread::~CommunicationThread() +{ +} + +void CommunicationThread::start(void) +{ + m_shouldWork = true; + m_gatorApi.startCapture(); + m_thread = std::thread(&CommunicationThread::worker, this); +} + +void CommunicationThread::stop(void) +{ + m_shouldWork = false; + m_gatorApi.stopCapture(); + m_thread.join(); +} + +void CommunicationThread::worker(void) +{ + bool hasData = false; + + while(m_shouldWork != false || hasData) + { + GatorMessage message; + GatorApi::MessageResult result = m_gatorApi.readMessage(message); + hasData = result == GatorApi::MessageResult::SUCCESS; + if(hasData) + { + m_gatorApi.processMessage(message); + } + } +} +} diff --git a/renderdoc/driver/ihv/arm/official/lizard/lizard_communication.hpp b/renderdoc/driver/ihv/arm/official/lizard/lizard_communication.hpp new file mode 100644 index 0000000000..8619fe95c9 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/lizard_communication.hpp @@ -0,0 +1,57 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef LIB_LIZARD_COMMUNICATION_HPP +#define LIB_LIZARD_COMMUNICATION_HPP + +#include +#include +#include +#include +#include + +#include "gator_api.hpp" + +namespace lizard +{ +class CommunicationThread +{ +public: + CommunicationThread(GatorApi &gatorApi); + ~CommunicationThread(void); + + void start(void); + void stop(void); + +private: + void worker(void); + + std::atomic m_shouldWork; + GatorApi &m_gatorApi; + std::thread m_thread; +}; + +} /* namespace lizard */ + +#endif /* LIB_LIZARD_COMMUNICATION_HPP */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/lizard_counter.cpp b/renderdoc/driver/ihv/arm/official/lizard/lizard_counter.cpp new file mode 100644 index 0000000000..6b55e022a6 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/lizard_counter.cpp @@ -0,0 +1,92 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 "lizard_counter.hpp" + +#include + +namespace lizard +{ +static std::vector s_empty; + +LizardCounterData::LizardCounterData(LizardCounterId id, const int64_t *values, size_t length) + : m_id(id), m_length(length), m_is_int(true) +{ + m_values = new Value[length]; + memcpy(m_values, (const void *)values, sizeof(int64_t) * length); +} + +LizardCounterData::LizardCounterData(LizardCounterId id, const double *values, size_t length) + : m_id(id), m_length(length), m_is_int(false) +{ + m_values = new Value[length]; + memcpy(m_values, (const void *)values, sizeof(double) * length); +} + +LizardCounterData::~LizardCounterData() +{ + delete[] m_values; +} + +LizardCounter::LizardCounter(LizardCounterId id, const char *key, const char *name, const char *title, + const char *description, const char *category, const double multiplier, + UnitType units, ClassType classType, SourceType sourceType) + : m_id(id), + m_key(key), + m_name(name), + m_title(title), + m_description(description), + m_category(category), + m_multiplier(multiplier), + m_units(units), + m_classType(classType), + m_sourceType(sourceType) +{ +} + +void LizardCounter::setInternalKey(uint64_t key) +{ + m_internalKey = key; +} + +void LizardCounterDataStore::addValue(int64_t key, Value value) +{ + m_values[key].push_back(value); +} + +const std::vector &LizardCounterDataStore::getValues(int64_t key) const +{ + const std::map >::const_iterator it = m_values.find(key); + if(it != m_values.end()) + return it->second; + else + return s_empty; +} + +void LizardCounterDataStore::clear() +{ + m_values.clear(); +} + +} /* namespace lizard */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/message_util.cpp b/renderdoc/driver/ihv/arm/official/lizard/message_util.cpp new file mode 100644 index 0000000000..2cba0be818 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/message_util.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 + +namespace lizard +{ +void writeLEInt(uint8_t *buf, uint32_t v) +{ + buf[0] = (v >> 0) & 0xFF; + buf[1] = (v >> 8) & 0xFF; + buf[2] = (v >> 16) & 0xFF; + buf[3] = (v >> 24) & 0xFF; +} + +uint32_t readLEInt(uint8_t *buffer) +{ + return (buffer[0] << 0) | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24); +} + +/** + * Utility function to decode a SLEB128 value. + * Source: https://llvm.org/doxygen/LEB128_8h_source.html + */ +int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr, + const char **error = nullptr) +{ + const uint8_t *orig_p = p; + int64_t Value = 0; + unsigned Shift = 0; + uint8_t Byte; + if(error) + *error = nullptr; + do + { + if(end && p == end) + { + if(error) + *error = "malformed sleb128, extends past end"; + if(n) + *n = (unsigned)(p - orig_p); + return 0; + } + Byte = *p++; + Value |= (uint64_t(Byte & 0x7f) << Shift); + Shift += 7; + } while(Byte >= 128); + // Sign extend negative numbers if needed. + if(Shift < 64 && (Byte & 0x40)) + Value |= (-1ULL) << Shift; + if(n) + *n = (unsigned)(p - orig_p); + return Value; +} + +} /* namespace lizard */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/message_util.hpp b/renderdoc/driver/ihv/arm/official/lizard/message_util.hpp new file mode 100644 index 0000000000..59f2db0fa7 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/message_util.hpp @@ -0,0 +1,40 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef GATOR_MESSAGE_UTIL_H +#define GATOR_MESSAGE_UTIL_H + +namespace lizard +{ +void writeLEInt(uint8_t *buf, uint32_t v); + +uint32_t readLEInt(uint8_t *buffer); + +/// Utility function to decode a SLEB128 value. +int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr, const uint8_t *end = nullptr, + const char **error = nullptr); + +} /* namespace lizard */ + +#endif // GATOR_MESSAGE_UTIL_H diff --git a/renderdoc/driver/ihv/arm/official/lizard/socket.cpp b/renderdoc/driver/ihv/arm/official/lizard/socket.cpp new file mode 100644 index 0000000000..edebff38e8 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/socket.cpp @@ -0,0 +1,156 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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 "socket.hpp" + +#include +#include +#include + +#include +#include + +namespace lizard +{ +using namespace std; + +Socket *Socket::createConnection(const char *host, uint32_t port) +{ + struct sockaddr_in serv_addr; + int sock; + if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + return NULL; + } + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(port); + + if(inet_pton(AF_INET, host, &serv_addr.sin_addr) <= 0) + { + return NULL; + } + int connectResult = connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); + if(connectResult < 0) + { + return NULL; + } + return new lizard::Socket(sock); +} + +void Socket::destroyConnection(Socket *connection) +{ + delete connection; +} + +static Socket::Result toSocketResult(ssize_t value, int lastErrno) +{ + if(value > 0) + return Socket::SUCCESS; + if(value == 0) + return Socket::CONNECTION_CLOSED; + + switch(lastErrno) + { + case EAGAIN: return Socket::WOULD_BLOCK; + case ECONNABORTED: + case ECONNRESET: return Socket::CONNECTION_TERMINATED; + default: return Socket::ERROR; + } +} + +Socket::Socket(int fd) : m_fd(fd) +{ +} + +Socket::~Socket() +{ + close(); +} + +Socket::Result Socket::send(const void *buffer, size_t bufferSize, size_t *bytesSent) +{ + ssize_t bytesWritten = ::send(m_fd, (const char *)buffer, bufferSize, 0); + Socket::Result result = toSocketResult(bytesWritten, errno); + + if(bytesSent != NULL) + *bytesSent = bytesWritten > 0 ? (size_t)bytesWritten : 0; + + return result; +} + +Socket::Result Socket::receive(void *buffer, size_t bufferSize, size_t *bytesRecv) +{ + ssize_t bytesRead = ::recv(m_fd, (char *)buffer, bufferSize, 0); + Result result = toSocketResult(bytesRead, errno); + + if(bytesRecv != NULL) + *bytesRecv = bytesRead > 0 ? (size_t)bytesRead : 0; + + return result; +} + +Socket::Result Socket::receiveAll(void *buffer, size_t bufferSize, size_t *bytesRecv) +{ + size_t bytesRead = 0; + Result result; + while(bytesRead < bufferSize) + { + bytesRead += ::recv(m_fd, (char *)buffer + bytesRead, bufferSize - bytesRead, 0); + result = toSocketResult(bytesRead, errno); + if(result != SUCCESS) + { + return result; + } + } + if(bytesRecv != NULL) + *bytesRecv = bytesRead > 0 ? (size_t)bytesRead : 0; + return result; +} + +Socket::Result Socket::shutdown() +{ + int shutdownResult = ::shutdown(m_fd, SHUT_RDWR); + return shutdownResult == 0 ? SUCCESS : ERROR; +} + +Socket::Result Socket::close() +{ + int closeResult = ::close(m_fd); + return closeResult == 0 ? SUCCESS : ERROR; +} + +string Socket::resultstr(Socket::Result result) +{ + switch(result) + { + case SUCCESS: return "SUCCESS"; + case WOULD_BLOCK: return "WOULD_BLOCK"; + case CONNECTION_TERMINATED: return "CONNECTION_TERMINATED"; + case CONNECTION_CLOSED: return "CONNECTION_CLOSED"; + case ERROR: return "ERROR"; + default: return "UNSPECIFIED RESULT"; + } +} + +} /* namespace lizard */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/socket.hpp b/renderdoc/driver/ihv/arm/official/lizard/socket.hpp new file mode 100644 index 0000000000..443d09079e --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/socket.hpp @@ -0,0 +1,64 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Samsung Electronics (UK) Limited + * + * 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. + ******************************************************************************/ + +#ifndef SOCKET_HPP +#define SOCKET_HPP + +#include +#include + +namespace lizard +{ +class Socket +{ + int m_fd; + +public: + enum Result + { + SUCCESS, + WOULD_BLOCK, + CONNECTION_TERMINATED, + CONNECTION_CLOSED, + ERROR, + }; // enum Result + + Socket(int fd); + ~Socket(); + + Result send(const void *buffer, size_t bufferSize, size_t *bytesSent); + Result receive(void *buffer, size_t bufferSize, size_t *bytesRead); + Result receiveAll(void *buffer, size_t bufferSize, size_t *bytesRead); + Result close(); + Result shutdown(); + + static Socket *createConnection(const char *host, uint32_t port); + static void destroyConnection(Socket *connection); + + static std::string resultstr(Result result); +}; // class Socket + +} /* namespace lizard */ + +#endif // SOCKET_HPP diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/LICENSE b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/LICENSE new file mode 100644 index 0000000000..9c3c722f07 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Arm Software + +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/arm/official/lizard/thirdparty/hwcpipe/README.md b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/README.md new file mode 100644 index 0000000000..b600d78adb --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/README.md @@ -0,0 +1,156 @@ + + +# HWCPipe + +## Introduction + +HWCPipe is a simple and extensible interface for reading CPU and GPU hardware counters. + +## License + +The software is provided under an MIT license. + +This project has a third-party dependency, which may have independent licensing: + +- [nlohmann/json](https://github.com/nlohmann/json): A JSON library for modern C++ + +## Contributions + +All contributions are accepted under the same [LICENSE](LICENSE). + +## Building + +To use HWCPipe, build it as a shared library in your project. + +If your project uses CMake, you can add the following to your `CMakeLists.txt`: + +``` +add_subdirectory(hwcpipe) +``` + +## Usage + +### Using HWCPipe + +Basic usage for HWCPipe is simple: + +``` +// HWCPipe performs automated platform detection for CPU/GPU counters +hwcpipe::HWCPipe h; + +// Start HWCPipe once at the beginning of the profiling session +h.run(); + +while (main_loop) { + // Call sample() to sample counters with the frequency you need + auto measurements = h.sample(); + + [...] +} + +// At the end of the profiling session, stop HWCPipe +h.stop(); +``` + +The `sample` function returns a `Measurements` struct, which can be accessed like this: + +``` +// Check if CPU measurements are available +if (measurements.cpu) +{ + // Look for a counter in the map + const auto &counter = measurements.cpu->find(CpuCounter::Cycles); + if (counter != measurements.cpu->end()) + { + // Get the data stored in the counter, casted to the type you need + auto value = counter->second.get(); + } +} +``` + +### Enabling counters + +The available counters are specified in the `CpuCounter` and `GpuCounter` enums (`cpu_profiler.h` and `gpu_profiler.h` respectively). + +Platforms will support a subset of these counters, which can be queried via: + +``` +auto cpu_counters = h.cpu_profiler()->supported_counters(); +auto gpu_counters = h.gpu_profiler()->supported_counters() +``` + +You can specify the counters to be enabled in the following ways: + +``` +// Enable a default set of counters +auto h = hwcpipe::HWCPipe(); + +// Pass sets of CPU and GPU counters to be enabled +auto h = hwcpipe::HWCPipe({CpuCounter::Cycles, CpuCounter::Instructions}, {GpuCounter::GpuCycles}); + +// Pass a JSON string +auto h = hwcpipe::HWCPipe(json); +``` + +The JSON string should be formatted like this: + +``` +{ + "cpu": ["Cycles", "Instructions"], + "gpu": ["GpuCycles"] +} +``` + +Available counter names can be found in `cpu_counter_names` (`cpu_profiler.h`) and `gpu_counter_names` (`gpu_profiler.h`). + +For more information regarding Mali counters, see [Mali Performance Counters](https://community.arm.com/graphics/b/blog/posts/mali-bifrost-family-performance-counters). + +### Enabling profiling on Android + +In order for performance data to be displayed, profiling needs to be enabled on the device. +Some devices may disable it by default. + +Profiling can be enabled via `adb`: + +``` +adb shell setprop security.perf_harden 0 +``` + +## Adding support for a new platform + +If the counters provided in `CpuCounter` and `GpuCounter` are enough for the new platform, +the process is simple: + +* Add an implementation of either `CpuProfiler` of `GpuProfiler` (you can use `PmuProfiler` and `MaliProfiler` as references). +* Add your platform to the automated platform detection in `hwcpipe.cpp`. For consistency in platform detection, the constructor for your platform should throw if the platform is not available. +* Add your platform to the build system. + +### Adding new counters + +If you need to add new counters to the existing ones, you should update the following variables: + +* Add the counter to the `CpuCounter`/`GpuCounter` enum. +* Add the counter name to the `cpu_counter_names`/`gpu_counter_names` map (necessary for JSON initialization). +* Add a description and the unit for your counter to the `cpu_counter_info`/`gpu_counter_info` map. + +The `CpuCounter` and `GpuCounter` enums are meant to be expanded. Platforms must not break if new counters are added. diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/cpu_profiler.h b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/cpu_profiler.h new file mode 100644 index 0000000000..b64b8964e1 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/cpu_profiler.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 "value.h" + +#include +#include +#include + +namespace hwcpipe +{ +// The available CPU counters. Profiler implementations will support a subset of them. +enum class CpuCounter +{ + Cycles, + Instructions, + CacheReferences, + CacheMisses, + BranchInstructions, + BranchMisses, + + MaxValue +}; + +// Mapping from CPU counter names to enum values. Used for JSON initialization. +const std::unordered_map cpu_counter_names{ + {"Cycles", CpuCounter::Cycles}, + {"Instructions", CpuCounter::Instructions}, + {"CacheReferences", CpuCounter::CacheReferences}, + {"CacheMisses", CpuCounter::CacheMisses}, + {"BranchInstructions", CpuCounter::BranchInstructions}, + {"BranchMisses", CpuCounter::BranchMisses}, +}; + +// A hash function for CpuCounter values +struct CpuCounterHash +{ + template + std::size_t operator()(T t) const + { + return static_cast(t); + } +}; + +struct CpuCounterInfo +{ + std::string desc; + std::string unit; +}; + +// Mapping from each counter to its corresponding information (description and unit) +const std::unordered_map cpu_counter_info{ + {CpuCounter::Cycles, {"Number of CPU cycles", "cycles"}}, + {CpuCounter::Instructions, {"Number of CPU instructions", "instructions"}}, + {CpuCounter::CacheReferences, {"Number of cache references", "references"}}, + {CpuCounter::CacheMisses, {"Number of cache misses", "misses"}}, + {CpuCounter::BranchInstructions, {"Number of branch instructions", "instructions"}}, + {CpuCounter::BranchMisses, {"Number of branch misses", "misses"}}, +}; + +typedef std::unordered_set CpuCounterSet; +typedef std::unordered_map + CpuMeasurements; + +/** An interface for classes that collect CPU performance data. */ +class CpuProfiler +{ + public: + virtual ~CpuProfiler() = default; + + // Returns the enabled counters + virtual const CpuCounterSet &enabled_counters() const = 0; + + // Returns the counters that the platform supports + virtual const CpuCounterSet &supported_counters() const = 0; + + // Sets the enabled counters after initialization + virtual void set_enabled_counters(CpuCounterSet counters) = 0; + + // Starts a profiling session + virtual void run() = 0; + + // Sample the counters. Returns a map of measurements for the counters + // that are both available and enabled. + // A profiling session must be running when sampling the counters. + virtual const CpuMeasurements &sample() = 0; + + // Stops the active profiling session + virtual void stop() = 0; +}; + +} // namespace hwcpipe diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/gpu_profiler.h b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/gpu_profiler.h new file mode 100644 index 0000000000..228c5f5943 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/gpu_profiler.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 "value.h" + +#include +#include +#include + +namespace hwcpipe +{ +// The available GPU counters. Profiler implementations will support a subset of them. +enum class GpuCounter +{ + GpuCycles, + VertexComputeCycles, + FragmentCycles, + TilerCycles, + + VertexComputeJobs, + FragmentJobs, + Pixels, + + Tiles, + TransactionEliminations, + EarlyZTests, + EarlyZKilled, + LateZTests, + LateZKilled, + + Instructions, + DivergedInstructions, + + ShaderCycles, + ShaderArithmeticCycles, + ShaderLoadStoreCycles, + ShaderTextureCycles, + + CacheReadLookups, + CacheWriteLookups, + ExternalMemoryReadAccesses, + ExternalMemoryWriteAccesses, + ExternalMemoryReadStalls, + ExternalMemoryWriteStalls, + ExternalMemoryReadBytes, + ExternalMemoryWriteBytes, + + MaxValue +}; + +// Mapping from GPU counter names to enum values. Used for JSON initialization. +const std::unordered_map gpu_counter_names{ + {"GpuCycles", GpuCounter::GpuCycles}, + {"VertexComputeCycles", GpuCounter::VertexComputeCycles}, + {"FragmentCycles", GpuCounter::FragmentCycles}, + {"TilerCycles", GpuCounter::TilerCycles}, + + {"VertexComputeJobs", GpuCounter::VertexComputeJobs}, + {"Tiles", GpuCounter::Tiles}, + {"TransactionEliminations", GpuCounter::TransactionEliminations}, + {"FragmentJobs", GpuCounter::FragmentJobs}, + {"Pixels", GpuCounter::Pixels}, + + {"EarlyZTests", GpuCounter::EarlyZTests}, + {"EarlyZKilled", GpuCounter::EarlyZKilled}, + {"LateZTests", GpuCounter::LateZTests}, + {"LateZKilled", GpuCounter::LateZKilled}, + + {"Instructions", GpuCounter::Instructions}, + {"DivergedInstructions", GpuCounter::DivergedInstructions}, + + {"ShaderCycles", GpuCounter::ShaderCycles}, + {"ShaderArithmeticCycles", GpuCounter::ShaderArithmeticCycles}, + {"ShaderLoadStoreCycles", GpuCounter::ShaderLoadStoreCycles}, + {"ShaderTextureCycles", GpuCounter::ShaderTextureCycles}, + + {"CacheReadLookups", GpuCounter::CacheReadLookups}, + {"CacheWriteLookups", GpuCounter::CacheWriteLookups}, + {"ExternalMemoryReadAccesses", GpuCounter::ExternalMemoryReadAccesses}, + {"ExternalMemoryWriteAccesses", GpuCounter::ExternalMemoryWriteAccesses}, + {"ExternalMemoryReadStalls", GpuCounter::ExternalMemoryReadStalls}, + {"ExternalMemoryWriteStalls", GpuCounter::ExternalMemoryWriteStalls}, + {"ExternalMemoryReadBytes", GpuCounter::ExternalMemoryReadBytes}, + {"ExternalMemoryWriteBytes", GpuCounter::ExternalMemoryWriteBytes}, +}; + +// A hash function for GpuCounter values +struct GpuCounterHash +{ + template + std::size_t operator()(T t) const + { + return static_cast(t); + } +}; + +struct GpuCounterInfo +{ + std::string desc; + std::string unit; +}; + +// Mapping from each counter to its corresponding information (description and unit) +const std::unordered_map gpu_counter_info{ + {GpuCounter::GpuCycles, {"Number of GPU cycles", "cycles"}}, + {GpuCounter::VertexComputeCycles, {"Number of vertex/compute cycles", "cycles"}}, + {GpuCounter::FragmentCycles, {"Number of fragment cycles", "cycles"}}, + {GpuCounter::TilerCycles, {"Number of tiler cycles", "cycles"}}, + + {GpuCounter::VertexComputeJobs, {"Number of vertex/compute jobs", "jobs"}}, + {GpuCounter::Tiles, {"Number of physical tiles written", "tiles"}}, + {GpuCounter::TransactionEliminations, {"Number of transaction eliminations", "tiles"}}, + {GpuCounter::FragmentJobs, {"Number of fragment jobs", "jobs"}}, + {GpuCounter::Pixels, {"Number of pixels shaded", "cycles"}}, + + {GpuCounter::EarlyZTests, {"Early-Z tests performed", "tests"}}, + {GpuCounter::EarlyZKilled, {"Early-Z tests resulting in a kill", "tests"}}, + {GpuCounter::LateZTests, {"Late-Z tests performed", "tests"}}, + {GpuCounter::LateZKilled, {"Late-Z tests resulting in a kill", "tests"}}, + + {GpuCounter::Instructions, {"Number of shader instructions", "instructions"}}, + {GpuCounter::DivergedInstructions, {"Number of diverged shader instructions", "instructions"}}, + + {GpuCounter::ShaderCycles, {"Shader total cycles", "cycles"}}, + {GpuCounter::ShaderArithmeticCycles, {"Shader arithmetic cycles", "cycles"}}, + {GpuCounter::ShaderLoadStoreCycles, {"Shader load/store cycles", "cycles"}}, + {GpuCounter::ShaderTextureCycles, {"Shader texture cycles", "cycles"}}, + + {GpuCounter::CacheReadLookups, {"Cache read lookups", "lookups"}}, + {GpuCounter::CacheWriteLookups, {"Cache write lookups", "lookups"}}, + {GpuCounter::ExternalMemoryReadAccesses, {"Reads from external memory", "accesses"}}, + {GpuCounter::ExternalMemoryWriteAccesses, {"Writes to external memory", "accesses"}}, + {GpuCounter::ExternalMemoryReadStalls, {"Stalls when reading from external memory", "stalls"}}, + {GpuCounter::ExternalMemoryWriteStalls, {"Stalls when writing to external memory", "stalls"}}, + {GpuCounter::ExternalMemoryReadBytes, {"Bytes read to external memory", "B"}}, + {GpuCounter::ExternalMemoryWriteBytes, {"Bytes written to external memory", "B"}}, +}; + +typedef std::unordered_set GpuCounterSet; +typedef std::unordered_map GpuMeasurements; + +/** An interface for classes that collect GPU performance data. */ +class GpuProfiler +{ + public: + virtual ~GpuProfiler() = default; + + // Returns the enabled counters + virtual const GpuCounterSet &enabled_counters() const = 0; + + // Returns the counters that the platform supports + virtual const GpuCounterSet &supported_counters() const = 0; + + // Sets the enabled counters after initialization + virtual void set_enabled_counters(GpuCounterSet counters) = 0; + + // Starts a profiling session + virtual void run() = 0; + + // Sample the counters. Returns a map of measurements for the counters + // that are both available and enabled. + // A profiling session must be running when sampling the counters. + virtual const GpuMeasurements &sample() = 0; + + // Stops the active profiling session + virtual void stop() = 0; +}; + +} // namespace hwcpipe diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe.cpp b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe.cpp new file mode 100644 index 0000000000..2d3ba19ae3 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 "hwcpipe.h" +#include "hwcpipe_log.h" + +#ifdef __linux__ +# include "vendor/arm/pmu/pmu_profiler.h" +# include "vendor/arm/mali/mali_profiler.h" +#endif + +#ifndef HWCPIPE_NO_JSON +#include +using json = nlohmann::json; +#endif + +#include + +namespace hwcpipe +{ +#ifndef HWCPIPE_NO_JSON +HWCPipe::HWCPipe(const char *json_string) +{ + auto json = json::parse(json_string); + + CpuCounterSet enabled_cpu_counters{}; + auto cpu = json.find("cpu"); + if (cpu != json.end()) + { + for (auto &counter_name : cpu->items()) + { + auto counter = cpu_counter_names.find(counter_name.value().get()); + if (counter != cpu_counter_names.end()) + { + enabled_cpu_counters.insert(counter->second); + } + else + { + HWCPIPE_LOG("CPU counter \"%s\" not found.", counter_name.value().get().c_str()); + } + } + } + + GpuCounterSet enabled_gpu_counters{}; + auto gpu = json.find("gpu"); + if (gpu != json.end()) + { + for (auto &counter_name : gpu->items()) + { + auto counter = gpu_counter_names.find(counter_name.value().get()); + if (counter != gpu_counter_names.end()) + { + enabled_gpu_counters.insert(counter->second); + } + else + { + HWCPIPE_LOG("GPU counter \"%s\" not found.", counter_name.value().get().c_str()); + } + } + } + + create_profilers(std::move(enabled_cpu_counters), std::move(enabled_gpu_counters)); +} +#endif + +HWCPipe::HWCPipe(CpuCounterSet enabled_cpu_counters, GpuCounterSet enabled_gpu_counters) +{ + create_profilers(std::move(enabled_cpu_counters), std::move(enabled_gpu_counters)); +} + +HWCPipe::HWCPipe() +{ + CpuCounterSet enabled_cpu_counters{CpuCounter::Cycles, + CpuCounter::Instructions, + CpuCounter::CacheReferences, + CpuCounter::CacheMisses, + CpuCounter::BranchInstructions, + CpuCounter::BranchMisses}; + + GpuCounterSet enabled_gpu_counters{GpuCounter::GpuCycles, + GpuCounter::VertexComputeCycles, + GpuCounter::FragmentCycles, + GpuCounter::TilerCycles, + GpuCounter::CacheReadLookups, + GpuCounter::CacheWriteLookups, + GpuCounter::ExternalMemoryReadAccesses, + GpuCounter::ExternalMemoryWriteAccesses, + GpuCounter::ExternalMemoryReadStalls, + GpuCounter::ExternalMemoryWriteStalls, + GpuCounter::ExternalMemoryReadBytes, + GpuCounter::ExternalMemoryWriteBytes}; + + create_profilers(std::move(enabled_cpu_counters), std::move(enabled_gpu_counters)); +} + +void HWCPipe::set_enabled_cpu_counters(CpuCounterSet counters) +{ + if (cpu_profiler_) + { + cpu_profiler_->set_enabled_counters(std::move(counters)); + } +} + +void HWCPipe::set_enabled_gpu_counters(GpuCounterSet counters) +{ + if (gpu_profiler_) + { + gpu_profiler_->set_enabled_counters(std::move(counters)); + } +} + +void HWCPipe::run() +{ + if (cpu_profiler_) + { + cpu_profiler_->run(); + } + if (gpu_profiler_) + { + gpu_profiler_->run(); + } +} + +Measurements HWCPipe::sample() +{ + Measurements m; + if (cpu_profiler_) + { + m.cpu = &cpu_profiler_->sample(); + } + if (gpu_profiler_) + { + m.gpu = &gpu_profiler_->sample(); + } + return m; +} + +void HWCPipe::stop() +{ + if (cpu_profiler_) + { + cpu_profiler_->stop(); + } + if (gpu_profiler_) + { + gpu_profiler_->stop(); + } +} + +void HWCPipe::create_profilers(CpuCounterSet enabled_cpu_counters, GpuCounterSet enabled_gpu_counters) +{ + // Automated platform detection +#ifdef __linux__ + try + { + cpu_profiler_ = std::unique_ptr(new PmuProfiler(enabled_cpu_counters)); + } + catch (const std::runtime_error &e) + { + HWCPIPE_LOG("PMU profiler initialization failed: %s", e.what()); + } + + try + { + gpu_profiler_ = std::unique_ptr(new MaliProfiler(enabled_gpu_counters)); + } + catch (const std::runtime_error &e) + { + HWCPIPE_LOG("Mali profiler initialization failed: %s", e.what()); + } +#else + HWCPIPE_LOG("No counters available for this platform."); +#endif +} + +} // namespace hwcpipe diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe.h b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe.h new file mode 100644 index 0000000000..a2744872e1 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 + +/* Force disable JSON in HWCPIPE */ +#define HWCPIPE_NO_JSON + +#include "cpu_profiler.h" +#include "gpu_profiler.h" + +#include +#include + +namespace hwcpipe +{ +struct Measurements +{ + const CpuMeasurements *cpu{nullptr}; + const GpuMeasurements *gpu{nullptr}; +}; + +/** A class that collects CPU/GPU performance data. */ +class HWCPipe +{ + public: +#ifndef HWCPIPE_NO_JSON + // Initializes HWCPipe via a JSON configuration string + explicit HWCPipe(const char *json_string); +#endif + + // Initializes HWCPipe with the specified counters + HWCPipe(CpuCounterSet enabled_cpu_counters, GpuCounterSet enabled_gpu_counters); + + // Initializes HWCPipe with a default set of counters + HWCPipe(); + + // Sets the enabled counters for the CPU profiler + void set_enabled_cpu_counters(CpuCounterSet counters); + + // Sets the enabled counters for the GPU profiler + void set_enabled_gpu_counters(GpuCounterSet counters); + + // Starts a profiling session + void run(); + + // Sample the counters. The function returns pointers to the CPU and GPU + // measurements maps, if the corresponding profiler is enabled. + // The entries in the maps are the counters that are both available and enabled. + // A profiling session must be running when sampling the counters. + Measurements sample(); + + // Stops the active profiling session + void stop(); + + const CpuProfiler *cpu_profiler() + { + return cpu_profiler_.get(); + } + const GpuProfiler *gpu_profiler() + { + return gpu_profiler_.get(); + } + + private: + std::unique_ptr cpu_profiler_{}; + std::unique_ptr gpu_profiler_{}; + + void create_profilers(CpuCounterSet enabled_cpu_counters, GpuCounterSet enabled_gpu_counters); +}; + +} // namespace hwcpipe diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe_log.h b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe_log.h new file mode 100644 index 0000000000..ec5591d29e --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/hwcpipe_log.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 + +#define HWCPIPE_TAG "HWCPipe" + +#if defined(__ANDROID__) +# include + +# define HWCPIPE_LOG(...) //__android_log_print(ANDROID_LOG_VERBOSE, HWCPIPE_TAG, __VA_ARGS__) +#else +# define HWCPIPE_LOG(...) \ + { \ + fprintf(stdout, "%s [INFO] : ", HWCPIPE_TAG); \ + fprintf(stdout, __VA_ARGS__); \ + fprintf(stdout, "\n"); \ + } +#endif diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/value.h b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/value.h new file mode 100644 index 0000000000..bf64d9d72b --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/value.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 + +namespace hwcpipe +{ +class Value +{ + public: + Value() : + is_int_(true), + int_(0), + double_(0.0f) + {} + Value(long long value) : + is_int_(true), + int_(value) + {} + Value(double value) : + is_int_(false), + double_(value) + {} + + template + T get() const + { + return is_int_ ? static_cast(int_) : static_cast(double_); + } + + void set(long long value) + { + int_ = value; + is_int_ = true; + } + + void set(double value) + { + double_ = value; + is_int_ = false; + } + + private: + bool is_int_; + long long int_{0}; + double double_{0.0}; +}; +} // namespace hwcpipe diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc.hpp b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc.hpp new file mode 100644 index 0000000000..d982f9b23a --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc.hpp @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2017-2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hwc_names.hpp" + +#ifndef DOXYGEN_SKIP_THIS + +# if defined(ANDROID) || defined(__ANDROID__) +/* We use _IOR_BAD/_IOW_BAD rather than _IOR/_IOW otherwise fails to compile with NDK-BUILD because of _IOC_TYPECHECK is defined, not because the paramter is invalid */ +# define MALI_IOR(a, b, c) _IOR_BAD(a, b, c) +# define MALI_IOW(a, b, c) _IOW_BAD(a, b, c) +# else +# define MALI_IOR(a, b, c) _IOR(a, b, c) +# define MALI_IOW(a, b, c) _IOW(a, b, c) +# endif + +namespace mali_userspace +{ +union uk_header +{ + uint32_t id; + uint32_t ret; + uint64_t sizer; +}; + +# define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 3 +# define BASE_MAX_COHERENT_GROUPS 16 + +struct mali_base_gpu_core_props +{ + uint32_t product_id; + uint16_t version_status; + uint16_t minor_revision; + uint16_t major_revision; + uint16_t padding; + uint32_t gpu_speed_mhz; + uint32_t gpu_freq_khz_max; + uint32_t gpu_freq_khz_min; + uint32_t log2_program_counter_size; + uint32_t texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + uint64_t gpu_available_memory_size; +}; + +struct mali_base_gpu_l2_cache_props +{ + uint8_t log2_line_size; + uint8_t log2_cache_size; + uint8_t num_l2_slices; + uint8_t padding[5]; +}; + +struct mali_base_gpu_tiler_props +{ + uint32_t bin_size_bytes; + uint32_t max_active_levels; +}; + +struct mali_base_gpu_thread_props +{ + uint32_t max_threads; + uint32_t max_workgroup_size; + uint32_t max_barrier_size; + uint16_t max_registers; + uint8_t max_task_queue; + uint8_t max_thread_group_split; + uint8_t impl_tech; + uint8_t padding[7]; +}; + +struct mali_base_gpu_coherent_group +{ + uint64_t core_mask; + uint16_t num_cores; + uint16_t padding[3]; +}; + +struct mali_base_gpu_coherent_group_info +{ + uint32_t num_groups; + uint32_t num_core_groups; + uint32_t coherency; + uint32_t padding; + mali_base_gpu_coherent_group group[BASE_MAX_COHERENT_GROUPS]; +}; + +# define GPU_MAX_JOB_SLOTS 16 +struct gpu_raw_gpu_props +{ + uint64_t shader_present; + uint64_t tiler_present; + uint64_t l2_present; + uint64_t unused_1; + + uint32_t l2_features; + uint32_t suspend_size; + uint32_t mem_features; + uint32_t mmu_features; + + uint32_t as_present; + + uint32_t js_present; + uint32_t js_features[GPU_MAX_JOB_SLOTS]; + uint32_t tiler_features; + uint32_t texture_features[3]; + + uint32_t gpu_id; + + uint32_t thread_max_threads; + uint32_t thread_max_workgroup_size; + uint32_t thread_max_barrier_size; + uint32_t thread_features; + + uint32_t coherency_mode; +}; + +struct mali_base_gpu_props +{ + mali_base_gpu_core_props core_props; + mali_base_gpu_l2_cache_props l2_props; + uint64_t unused; + mali_base_gpu_tiler_props tiler_props; + mali_base_gpu_thread_props thread_props; + gpu_raw_gpu_props raw_props; + mali_base_gpu_coherent_group_info coherency_info; +}; + +struct kbase_uk_gpuprops +{ + uk_header header; + mali_base_gpu_props props; +}; + +# define KBASE_GPUPROP_VALUE_SIZE_U8 (0x0) +# define KBASE_GPUPROP_VALUE_SIZE_U16 (0x1) +# define KBASE_GPUPROP_VALUE_SIZE_U32 (0x2) +# define KBASE_GPUPROP_VALUE_SIZE_U64 (0x3) + +# define KBASE_GPUPROP_PRODUCT_ID 1 +# define KBASE_GPUPROP_MINOR_REVISION 3 +# define KBASE_GPUPROP_MAJOR_REVISION 4 + +# define KBASE_GPUPROP_COHERENCY_NUM_GROUPS 61 +# define KBASE_GPUPROP_COHERENCY_NUM_CORE_GROUPS 62 +# define KBASE_GPUPROP_COHERENCY_GROUP_0 64 +# define KBASE_GPUPROP_COHERENCY_GROUP_1 65 +# define KBASE_GPUPROP_COHERENCY_GROUP_2 66 +# define KBASE_GPUPROP_COHERENCY_GROUP_3 67 +# define KBASE_GPUPROP_COHERENCY_GROUP_4 68 +# define KBASE_GPUPROP_COHERENCY_GROUP_5 69 +# define KBASE_GPUPROP_COHERENCY_GROUP_6 70 +# define KBASE_GPUPROP_COHERENCY_GROUP_7 71 +# define KBASE_GPUPROP_COHERENCY_GROUP_8 72 +# define KBASE_GPUPROP_COHERENCY_GROUP_9 73 +# define KBASE_GPUPROP_COHERENCY_GROUP_10 74 +# define KBASE_GPUPROP_COHERENCY_GROUP_11 75 +# define KBASE_GPUPROP_COHERENCY_GROUP_12 76 +# define KBASE_GPUPROP_COHERENCY_GROUP_13 77 +# define KBASE_GPUPROP_COHERENCY_GROUP_14 78 +# define KBASE_GPUPROP_COHERENCY_GROUP_15 79 + +# define KBASE_GPUPROP_L2_NUM_L2_SLICES 15 + +struct gpu_props +{ + uint32_t product_id; + uint16_t minor_revision; + uint16_t major_revision; + uint32_t num_groups; + uint32_t num_core_groups; + uint64_t core_mask[16]; + + uint32_t l2_slices; +}; + +static const struct +{ + uint32_t type; + size_t offset; + int size; +} gpu_property_mapping[] = { +# define PROP(name, member) \ + { \ + KBASE_GPUPROP_##name, offsetof(struct gpu_props, member), \ + sizeof(((struct gpu_props *) 0)->member) \ + } + PROP(PRODUCT_ID, product_id), + PROP(MINOR_REVISION, minor_revision), + PROP(MAJOR_REVISION, major_revision), + PROP(COHERENCY_NUM_GROUPS, num_groups), + PROP(COHERENCY_NUM_CORE_GROUPS, num_core_groups), + PROP(COHERENCY_GROUP_0, core_mask[0]), + PROP(COHERENCY_GROUP_1, core_mask[1]), + PROP(COHERENCY_GROUP_2, core_mask[2]), + PROP(COHERENCY_GROUP_3, core_mask[3]), + PROP(COHERENCY_GROUP_4, core_mask[4]), + PROP(COHERENCY_GROUP_5, core_mask[5]), + PROP(COHERENCY_GROUP_6, core_mask[6]), + PROP(COHERENCY_GROUP_7, core_mask[7]), + PROP(COHERENCY_GROUP_8, core_mask[8]), + PROP(COHERENCY_GROUP_9, core_mask[9]), + PROP(COHERENCY_GROUP_10, core_mask[10]), + PROP(COHERENCY_GROUP_11, core_mask[11]), + PROP(COHERENCY_GROUP_12, core_mask[12]), + PROP(COHERENCY_GROUP_13, core_mask[13]), + PROP(COHERENCY_GROUP_14, core_mask[14]), + PROP(COHERENCY_GROUP_15, core_mask[15]), + + PROP(L2_NUM_L2_SLICES, l2_slices), +# undef PROP + {0, 0, 0}}; + +struct kbase_hwcnt_reader_metadata +{ + uint64_t timestamp = 0; + uint32_t event_id = 0; + uint32_t buffer_idx = 0; +}; + +namespace +{ +/** Message header */ +union kbase_uk_hwcnt_header +{ + /* 32-bit number identifying the UK function to be called. */ + uint32_t id; + /* The int return code returned by the called UK function. */ + uint32_t ret; + /* Used to ensure 64-bit alignment of this union. Do not remove. */ + uint64_t sizer; +}; + +/** IOCTL parameters to check version */ +struct kbase_uk_hwcnt_reader_version_check_args +{ + union kbase_uk_hwcnt_header header; + + uint16_t major; + uint16_t minor; + uint8_t padding[4]; +}; + +union kbase_pointer +{ + void * value; + uint32_t compat_value; + uint64_t sizer; +}; + +struct kbase_ioctl_get_gpuprops +{ + kbase_pointer buffer; + uint32_t size; + uint32_t flags; +}; + +struct kbase_ioctl_version_check +{ + uint16_t major; + uint16_t minor; +}; + +struct kbase_ioctl_set_flags +{ + uint32_t create_flags; +}; + +struct kbase_ioctl_hwcnt_reader_setup +{ + uint32_t buffer_count; + uint32_t jm_bm; + uint32_t shader_bm; + uint32_t tiler_bm; + uint32_t mmu_l2_bm; +}; + +# define KBASE_IOCTL_TYPE 0x80 +# define KBASE_IOCTL_GET_GPUPROPS MALI_IOW(KBASE_IOCTL_TYPE, 3, struct mali_userspace::kbase_ioctl_get_gpuprops) +# define KBASE_IOCTL_VERSION_CHECK _IOWR(KBASE_IOCTL_TYPE, 0, struct mali_userspace::kbase_ioctl_version_check) +# define KBASE_IOCTL_SET_FLAGS _IOW(KBASE_IOCTL_TYPE, 1, struct mali_userspace::kbase_ioctl_set_flags) +# define KBASE_IOCTL_HWCNT_READER_SETUP _IOW(KBASE_IOCTL_TYPE, 8, struct mali_userspace::kbase_ioctl_hwcnt_reader_setup) + +/** IOCTL parameters to set flags */ +struct kbase_uk_hwcnt_reader_set_flags +{ + union kbase_uk_hwcnt_header header; + + uint32_t create_flags; + uint32_t padding; +}; + +/** IOCTL parameters to configure reader */ +struct kbase_uk_hwcnt_reader_setup +{ + union kbase_uk_hwcnt_header header; + + /* IN */ + uint32_t buffer_count; + uint32_t jm_bm; + uint32_t shader_bm; + uint32_t tiler_bm; + uint32_t mmu_l2_bm; + + /* OUT */ + int32_t fd; +}; + +static const uint32_t HWCNT_READER_API = 1; + +struct uku_version_check_args +{ + uk_header header; + uint16_t major; + uint16_t minor; + uint8_t padding[4]; +}; + +enum +{ + UKP_FUNC_ID_CHECK_VERSION = 0, + /* Related to mali0 ioctl interface */ + LINUX_UK_BASE_MAGIC = 0x80, + BASE_CONTEXT_CREATE_KERNEL_FLAGS = 0x2, + KBASE_FUNC_HWCNT_UK_FUNC_ID = 512, + KBASE_FUNC_GPU_PROPS_REG_DUMP = KBASE_FUNC_HWCNT_UK_FUNC_ID + 14, + KBASE_FUNC_HWCNT_READER_SETUP = KBASE_FUNC_HWCNT_UK_FUNC_ID + 36, + KBASE_FUNC_HWCNT_DUMP = KBASE_FUNC_HWCNT_UK_FUNC_ID + 11, + KBASE_FUNC_HWCNT_CLEAR = KBASE_FUNC_HWCNT_UK_FUNC_ID + 12, + KBASE_FUNC_SET_FLAGS = KBASE_FUNC_HWCNT_UK_FUNC_ID + 18, + + /* The ids of ioctl commands for the reader interface */ + KBASE_HWCNT_READER = 0xBE, + KBASE_HWCNT_READER_GET_HWVER = MALI_IOR(KBASE_HWCNT_READER, 0x00, uint32_t), + KBASE_HWCNT_READER_GET_BUFFER_SIZE = MALI_IOR(KBASE_HWCNT_READER, 0x01, uint32_t), + KBASE_HWCNT_READER_DUMP = MALI_IOW(KBASE_HWCNT_READER, 0x10, uint32_t), + KBASE_HWCNT_READER_CLEAR = MALI_IOW(KBASE_HWCNT_READER, 0x11, uint32_t), + KBASE_HWCNT_READER_GET_BUFFER = MALI_IOR(KBASE_HWCNT_READER, 0x20, struct kbase_hwcnt_reader_metadata), + KBASE_HWCNT_READER_PUT_BUFFER = MALI_IOW(KBASE_HWCNT_READER, 0x21, struct kbase_hwcnt_reader_metadata), + KBASE_HWCNT_READER_SET_INTERVAL = MALI_IOW(KBASE_HWCNT_READER, 0x30, uint32_t), + KBASE_HWCNT_READER_ENABLE_EVENT = MALI_IOW(KBASE_HWCNT_READER, 0x40, uint32_t), + KBASE_HWCNT_READER_DISABLE_EVENT = MALI_IOW(KBASE_HWCNT_READER, 0x41, uint32_t), + KBASE_HWCNT_READER_GET_API_VERSION = MALI_IOW(KBASE_HWCNT_READER, 0xFF, uint32_t) +}; + +enum +{ + PIPE_DESCRIPTOR_IN, /**< The index of a pipe's input descriptor. */ + PIPE_DESCRIPTOR_OUT, /**< The index of a pipe's output descriptor. */ + + PIPE_DESCRIPTOR_COUNT /**< The number of descriptors forming a pipe. */ +}; + +enum +{ + POLL_DESCRIPTOR_SIGNAL, /**< The index of the signal descriptor in poll fds array. */ + POLL_DESCRIPTOR_HWCNT_READER, /**< The index of the hwcnt reader descriptor in poll fds array. */ + + POLL_DESCRIPTOR_COUNT /**< The number of descriptors poll is waiting for. */ +}; + +/** Write a single byte into the pipe to interrupt the reader thread */ +typedef char poll_data_t; +} // namespace + +template +static inline int mali_ioctl(int fd, T &arg) +{ + auto * hdr = &arg.header; + const int cmd = _IOC(_IOC_READ | _IOC_WRITE, LINUX_UK_BASE_MAGIC, hdr->id, sizeof(T)); + + if (ioctl(fd, cmd, &arg)) + return -1; + if (hdr->ret) + return -1; + + return 0; +} +} // namespace mali_userspace + +#endif /* DOXYGEN_SKIP_THIS */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc_names.hpp b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc_names.hpp new file mode 100644 index 0000000000..65c4774b47 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/hwc_names.hpp @@ -0,0 +1,3346 @@ +/* + * Copyright (c) 2017-2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 + +#ifndef DOXYGEN_SKIP_THIS + +namespace mali_userspace +{ +enum MaliCounterBlockName +{ + MALI_NAME_BLOCK_JM = 0, + MALI_NAME_BLOCK_TILER = 1, + MALI_NAME_BLOCK_SHADER = 2, + MALI_NAME_BLOCK_MMU = 3 +}; + +enum +{ + MALI_NAME_BLOCK_SIZE = 64 +}; + +/* + * "Short names" for hardware counters used by Streamline. Counters names are + * stored in accordance with their memory layout in the binary counter block + * emitted by the Mali GPU. Each "master" in the GPU emits a fixed-size block + * of 64 counters, and each GPU implements the same set of "masters" although + * the counters each master exposes within its block of 64 may vary. + * + * Counters which are an empty string are simply "holes" in the counter memory + * where no counter exists. + */ + +static const char *const hardware_counters_mali_t60x[] = + { + /* Job Manager */ + "", + "", + "", + "", + "T60x_MESSAGES_SENT", + "T60x_MESSAGES_RECEIVED", + "T60x_GPU_ACTIVE", + "T60x_IRQ_ACTIVE", + "T60x_JS0_JOBS", + "T60x_JS0_TASKS", + "T60x_JS0_ACTIVE", + "", + "T60x_JS0_WAIT_READ", + "T60x_JS0_WAIT_ISSUE", + "T60x_JS0_WAIT_DEPEND", + "T60x_JS0_WAIT_FINISH", + "T60x_JS1_JOBS", + "T60x_JS1_TASKS", + "T60x_JS1_ACTIVE", + "", + "T60x_JS1_WAIT_READ", + "T60x_JS1_WAIT_ISSUE", + "T60x_JS1_WAIT_DEPEND", + "T60x_JS1_WAIT_FINISH", + "T60x_JS2_JOBS", + "T60x_JS2_TASKS", + "T60x_JS2_ACTIVE", + "", + "T60x_JS2_WAIT_READ", + "T60x_JS2_WAIT_ISSUE", + "T60x_JS2_WAIT_DEPEND", + "T60x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T60x_TI_JOBS_PROCESSED", + "T60x_TI_TRIANGLES", + "T60x_TI_QUADS", + "T60x_TI_POLYGONS", + "T60x_TI_POINTS", + "T60x_TI_LINES", + "T60x_TI_VCACHE_HIT", + "T60x_TI_VCACHE_MISS", + "T60x_TI_FRONT_FACING", + "T60x_TI_BACK_FACING", + "T60x_TI_PRIM_VISIBLE", + "T60x_TI_PRIM_CULLED", + "T60x_TI_PRIM_CLIPPED", + "T60x_TI_LEVEL0", + "T60x_TI_LEVEL1", + "T60x_TI_LEVEL2", + "T60x_TI_LEVEL3", + "T60x_TI_LEVEL4", + "T60x_TI_LEVEL5", + "T60x_TI_LEVEL6", + "T60x_TI_LEVEL7", + "T60x_TI_COMMAND_1", + "T60x_TI_COMMAND_2", + "T60x_TI_COMMAND_3", + "T60x_TI_COMMAND_4", + "T60x_TI_COMMAND_4_7", + "T60x_TI_COMMAND_8_15", + "T60x_TI_COMMAND_16_63", + "T60x_TI_COMMAND_64", + "T60x_TI_COMPRESS_IN", + "T60x_TI_COMPRESS_OUT", + "T60x_TI_COMPRESS_FLUSH", + "T60x_TI_TIMESTAMPS", + "T60x_TI_PCACHE_HIT", + "T60x_TI_PCACHE_MISS", + "T60x_TI_PCACHE_LINE", + "T60x_TI_PCACHE_STALL", + "T60x_TI_WRBUF_HIT", + "T60x_TI_WRBUF_MISS", + "T60x_TI_WRBUF_LINE", + "T60x_TI_WRBUF_PARTIAL", + "T60x_TI_WRBUF_STALL", + "T60x_TI_ACTIVE", + "T60x_TI_LOADING_DESC", + "T60x_TI_INDEX_WAIT", + "T60x_TI_INDEX_RANGE_WAIT", + "T60x_TI_VERTEX_WAIT", + "T60x_TI_PCACHE_WAIT", + "T60x_TI_WRBUF_WAIT", + "T60x_TI_BUS_READ", + "T60x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T60x_TI_UTLB_STALL", + "T60x_TI_UTLB_REPLAY_MISS", + "T60x_TI_UTLB_REPLAY_FULL", + "T60x_TI_UTLB_NEW_MISS", + "T60x_TI_UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "", + "T60x_FRAG_ACTIVE", + "T60x_FRAG_PRIMITIVES", + "T60x_FRAG_PRIMITIVES_DROPPED", + "T60x_FRAG_CYCLES_DESC", + "T60x_FRAG_CYCLES_PLR", + "T60x_FRAG_CYCLES_VERT", + "T60x_FRAG_CYCLES_TRISETUP", + "T60x_FRAG_CYCLES_RAST", + "T60x_FRAG_THREADS", + "T60x_FRAG_DUMMY_THREADS", + "T60x_FRAG_QUADS_RAST", + "T60x_FRAG_QUADS_EZS_TEST", + "T60x_FRAG_QUADS_EZS_KILLED", + "T60x_FRAG_THREADS_LZS_TEST", + "T60x_FRAG_THREADS_LZS_KILLED", + "T60x_FRAG_CYCLES_NO_TILE", + "T60x_FRAG_NUM_TILES", + "T60x_FRAG_TRANS_ELIM", + "T60x_COMPUTE_ACTIVE", + "T60x_COMPUTE_TASKS", + "T60x_COMPUTE_THREADS", + "T60x_COMPUTE_CYCLES_DESC", + "T60x_TRIPIPE_ACTIVE", + "T60x_ARITH_WORDS", + "T60x_ARITH_CYCLES_REG", + "T60x_ARITH_CYCLES_L0", + "T60x_ARITH_FRAG_DEPEND", + "T60x_LS_WORDS", + "T60x_LS_ISSUES", + "T60x_LS_RESTARTS", + "T60x_LS_REISSUES_MISS", + "T60x_LS_REISSUES_VD", + "T60x_LS_REISSUE_ATTRIB_MISS", + "T60x_LS_NO_WB", + "T60x_TEX_WORDS", + "T60x_TEX_BUBBLES", + "T60x_TEX_WORDS_L0", + "T60x_TEX_WORDS_DESC", + "T60x_TEX_ISSUES", + "T60x_TEX_RECIRC_FMISS", + "T60x_TEX_RECIRC_DESC", + "T60x_TEX_RECIRC_MULTI", + "T60x_TEX_RECIRC_PMISS", + "T60x_TEX_RECIRC_CONF", + "T60x_LSC_READ_HITS", + "T60x_LSC_READ_MISSES", + "T60x_LSC_WRITE_HITS", + "T60x_LSC_WRITE_MISSES", + "T60x_LSC_ATOMIC_HITS", + "T60x_LSC_ATOMIC_MISSES", + "T60x_LSC_LINE_FETCHES", + "T60x_LSC_DIRTY_LINE", + "T60x_LSC_SNOOPS", + "T60x_AXI_TLB_STALL", + "T60x_AXI_TLB_MISS", + "T60x_AXI_TLB_TRANSACTION", + "T60x_LS_TLB_MISS", + "T60x_LS_TLB_HIT", + "T60x_AXI_BEATS_READ", + "T60x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T60x_MMU_HIT", + "T60x_MMU_NEW_MISS", + "T60x_MMU_REPLAY_FULL", + "T60x_MMU_REPLAY_MISS", + "T60x_MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "T60x_UTLB_HIT", + "T60x_UTLB_NEW_MISS", + "T60x_UTLB_REPLAY_FULL", + "T60x_UTLB_REPLAY_MISS", + "T60x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T60x_L2_EXT_WRITE_BEATS", + "T60x_L2_EXT_READ_BEATS", + "T60x_L2_ANY_LOOKUP", + "T60x_L2_READ_LOOKUP", + "T60x_L2_SREAD_LOOKUP", + "T60x_L2_READ_REPLAY", + "T60x_L2_READ_SNOOP", + "T60x_L2_READ_HIT", + "T60x_L2_CLEAN_MISS", + "T60x_L2_WRITE_LOOKUP", + "T60x_L2_SWRITE_LOOKUP", + "T60x_L2_WRITE_REPLAY", + "T60x_L2_WRITE_SNOOP", + "T60x_L2_WRITE_HIT", + "T60x_L2_EXT_READ_FULL", + "T60x_L2_EXT_READ_HALF", + "T60x_L2_EXT_WRITE_FULL", + "T60x_L2_EXT_WRITE_HALF", + "T60x_L2_EXT_READ", + "T60x_L2_EXT_READ_LINE", + "T60x_L2_EXT_WRITE", + "T60x_L2_EXT_WRITE_LINE", + "T60x_L2_EXT_WRITE_SMALL", + "T60x_L2_EXT_BARRIER", + "T60x_L2_EXT_AR_STALL", + "T60x_L2_EXT_R_BUF_FULL", + "T60x_L2_EXT_RD_BUF_FULL", + "T60x_L2_EXT_R_RAW", + "T60x_L2_EXT_W_STALL", + "T60x_L2_EXT_W_BUF_FULL", + "T60x_L2_EXT_R_W_HAZARD", + "T60x_L2_TAG_HAZARD", + "T60x_L2_SNOOP_FULL", + "T60x_L2_REPLAY_FULL"}; + +static const char *const hardware_counters_mali_t62x[] = + { + /* Job Manager */ + "", + "", + "", + "", + "T62x_MESSAGES_SENT", + "T62x_MESSAGES_RECEIVED", + "T62x_GPU_ACTIVE", + "T62x_IRQ_ACTIVE", + "T62x_JS0_JOBS", + "T62x_JS0_TASKS", + "T62x_JS0_ACTIVE", + "", + "T62x_JS0_WAIT_READ", + "T62x_JS0_WAIT_ISSUE", + "T62x_JS0_WAIT_DEPEND", + "T62x_JS0_WAIT_FINISH", + "T62x_JS1_JOBS", + "T62x_JS1_TASKS", + "T62x_JS1_ACTIVE", + "", + "T62x_JS1_WAIT_READ", + "T62x_JS1_WAIT_ISSUE", + "T62x_JS1_WAIT_DEPEND", + "T62x_JS1_WAIT_FINISH", + "T62x_JS2_JOBS", + "T62x_JS2_TASKS", + "T62x_JS2_ACTIVE", + "", + "T62x_JS2_WAIT_READ", + "T62x_JS2_WAIT_ISSUE", + "T62x_JS2_WAIT_DEPEND", + "T62x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T62x_TI_JOBS_PROCESSED", + "T62x_TI_TRIANGLES", + "T62x_TI_QUADS", + "T62x_TI_POLYGONS", + "T62x_TI_POINTS", + "T62x_TI_LINES", + "T62x_TI_VCACHE_HIT", + "T62x_TI_VCACHE_MISS", + "T62x_TI_FRONT_FACING", + "T62x_TI_BACK_FACING", + "T62x_TI_PRIM_VISIBLE", + "T62x_TI_PRIM_CULLED", + "T62x_TI_PRIM_CLIPPED", + "T62x_TI_LEVEL0", + "T62x_TI_LEVEL1", + "T62x_TI_LEVEL2", + "T62x_TI_LEVEL3", + "T62x_TI_LEVEL4", + "T62x_TI_LEVEL5", + "T62x_TI_LEVEL6", + "T62x_TI_LEVEL7", + "T62x_TI_COMMAND_1", + "T62x_TI_COMMAND_2", + "T62x_TI_COMMAND_3", + "T62x_TI_COMMAND_4", + "T62x_TI_COMMAND_5_7", + "T62x_TI_COMMAND_8_15", + "T62x_TI_COMMAND_16_63", + "T62x_TI_COMMAND_64", + "T62x_TI_COMPRESS_IN", + "T62x_TI_COMPRESS_OUT", + "T62x_TI_COMPRESS_FLUSH", + "T62x_TI_TIMESTAMPS", + "T62x_TI_PCACHE_HIT", + "T62x_TI_PCACHE_MISS", + "T62x_TI_PCACHE_LINE", + "T62x_TI_PCACHE_STALL", + "T62x_TI_WRBUF_HIT", + "T62x_TI_WRBUF_MISS", + "T62x_TI_WRBUF_LINE", + "T62x_TI_WRBUF_PARTIAL", + "T62x_TI_WRBUF_STALL", + "T62x_TI_ACTIVE", + "T62x_TI_LOADING_DESC", + "T62x_TI_INDEX_WAIT", + "T62x_TI_INDEX_RANGE_WAIT", + "T62x_TI_VERTEX_WAIT", + "T62x_TI_PCACHE_WAIT", + "T62x_TI_WRBUF_WAIT", + "T62x_TI_BUS_READ", + "T62x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T62x_TI_UTLB_STALL", + "T62x_TI_UTLB_REPLAY_MISS", + "T62x_TI_UTLB_REPLAY_FULL", + "T62x_TI_UTLB_NEW_MISS", + "T62x_TI_UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "T62x_SHADER_CORE_ACTIVE", + "T62x_FRAG_ACTIVE", + "T62x_FRAG_PRIMITIVES", + "T62x_FRAG_PRIMITIVES_DROPPED", + "T62x_FRAG_CYCLES_DESC", + "T62x_FRAG_CYCLES_FPKQ_ACTIVE", + "T62x_FRAG_CYCLES_VERT", + "T62x_FRAG_CYCLES_TRISETUP", + "T62x_FRAG_CYCLES_EZS_ACTIVE", + "T62x_FRAG_THREADS", + "T62x_FRAG_DUMMY_THREADS", + "T62x_FRAG_QUADS_RAST", + "T62x_FRAG_QUADS_EZS_TEST", + "T62x_FRAG_QUADS_EZS_KILLED", + "T62x_FRAG_THREADS_LZS_TEST", + "T62x_FRAG_THREADS_LZS_KILLED", + "T62x_FRAG_CYCLES_NO_TILE", + "T62x_FRAG_NUM_TILES", + "T62x_FRAG_TRANS_ELIM", + "T62x_COMPUTE_ACTIVE", + "T62x_COMPUTE_TASKS", + "T62x_COMPUTE_THREADS", + "T62x_COMPUTE_CYCLES_DESC", + "T62x_TRIPIPE_ACTIVE", + "T62x_ARITH_WORDS", + "T62x_ARITH_CYCLES_REG", + "T62x_ARITH_CYCLES_L0", + "T62x_ARITH_FRAG_DEPEND", + "T62x_LS_WORDS", + "T62x_LS_ISSUES", + "T62x_LS_RESTARTS", + "T62x_LS_REISSUES_MISS", + "T62x_LS_REISSUES_VD", + "T62x_LS_REISSUE_ATTRIB_MISS", + "T62x_LS_NO_WB", + "T62x_TEX_WORDS", + "T62x_TEX_BUBBLES", + "T62x_TEX_WORDS_L0", + "T62x_TEX_WORDS_DESC", + "T62x_TEX_ISSUES", + "T62x_TEX_RECIRC_FMISS", + "T62x_TEX_RECIRC_DESC", + "T62x_TEX_RECIRC_MULTI", + "T62x_TEX_RECIRC_PMISS", + "T62x_TEX_RECIRC_CONF", + "T62x_LSC_READ_HITS", + "T62x_LSC_READ_MISSES", + "T62x_LSC_WRITE_HITS", + "T62x_LSC_WRITE_MISSES", + "T62x_LSC_ATOMIC_HITS", + "T62x_LSC_ATOMIC_MISSES", + "T62x_LSC_LINE_FETCHES", + "T62x_LSC_DIRTY_LINE", + "T62x_LSC_SNOOPS", + "T62x_AXI_TLB_STALL", + "T62x_AXI_TLB_MISS", + "T62x_AXI_TLB_TRANSACTION", + "T62x_LS_TLB_MISS", + "T62x_LS_TLB_HIT", + "T62x_AXI_BEATS_READ", + "T62x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T62x_MMU_HIT", + "T62x_MMU_NEW_MISS", + "T62x_MMU_REPLAY_FULL", + "T62x_MMU_REPLAY_MISS", + "T62x_MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "T62x_UTLB_HIT", + "T62x_UTLB_NEW_MISS", + "T62x_UTLB_REPLAY_FULL", + "T62x_UTLB_REPLAY_MISS", + "T62x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T62x_L2_EXT_WRITE_BEATS", + "T62x_L2_EXT_READ_BEATS", + "T62x_L2_ANY_LOOKUP", + "T62x_L2_READ_LOOKUP", + "T62x_L2_SREAD_LOOKUP", + "T62x_L2_READ_REPLAY", + "T62x_L2_READ_SNOOP", + "T62x_L2_READ_HIT", + "T62x_L2_CLEAN_MISS", + "T62x_L2_WRITE_LOOKUP", + "T62x_L2_SWRITE_LOOKUP", + "T62x_L2_WRITE_REPLAY", + "T62x_L2_WRITE_SNOOP", + "T62x_L2_WRITE_HIT", + "T62x_L2_EXT_READ_FULL", + "T62x_L2_EXT_READ_HALF", + "T62x_L2_EXT_WRITE_FULL", + "T62x_L2_EXT_WRITE_HALF", + "T62x_L2_EXT_READ", + "T62x_L2_EXT_READ_LINE", + "T62x_L2_EXT_WRITE", + "T62x_L2_EXT_WRITE_LINE", + "T62x_L2_EXT_WRITE_SMALL", + "T62x_L2_EXT_BARRIER", + "T62x_L2_EXT_AR_STALL", + "T62x_L2_EXT_R_BUF_FULL", + "T62x_L2_EXT_RD_BUF_FULL", + "T62x_L2_EXT_R_RAW", + "T62x_L2_EXT_W_STALL", + "T62x_L2_EXT_W_BUF_FULL", + "T62x_L2_EXT_R_W_HAZARD", + "T62x_L2_TAG_HAZARD", + "T62x_L2_SNOOP_FULL", + "T62x_L2_REPLAY_FULL"}; + +static const char *const hardware_counters_mali_t72x[] = + { + /* Job Manager */ + "", + "", + "", + "", + "T72x_GPU_ACTIVE", + "T72x_IRQ_ACTIVE", + "T72x_JS0_JOBS", + "T72x_JS0_TASKS", + "T72x_JS0_ACTIVE", + "T72x_JS1_JOBS", + "T72x_JS1_TASKS", + "T72x_JS1_ACTIVE", + "T72x_JS2_JOBS", + "T72x_JS2_TASKS", + "T72x_JS2_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T72x_TI_JOBS_PROCESSED", + "T72x_TI_TRIANGLES", + "T72x_TI_QUADS", + "T72x_TI_POLYGONS", + "T72x_TI_POINTS", + "T72x_TI_LINES", + "T72x_TI_FRONT_FACING", + "T72x_TI_BACK_FACING", + "T72x_TI_PRIM_VISIBLE", + "T72x_TI_PRIM_CULLED", + "T72x_TI_PRIM_CLIPPED", + "", + "", + "", + "", + "", + "", + "", + "", + "T72x_TI_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Shader Core */ + "", + "", + "", + "", + "T72x_FRAG_ACTIVE", + "T72x_FRAG_PRIMITIVES", + "T72x_FRAG_PRIMITIVES_DROPPED", + "T72x_FRAG_THREADS", + "T72x_FRAG_DUMMY_THREADS", + "T72x_FRAG_QUADS_RAST", + "T72x_FRAG_QUADS_EZS_TEST", + "T72x_FRAG_QUADS_EZS_KILLED", + "T72x_FRAG_THREADS_LZS_TEST", + "T72x_FRAG_THREADS_LZS_KILLED", + "T72x_FRAG_CYCLES_NO_TILE", + "T72x_FRAG_NUM_TILES", + "T72x_FRAG_TRANS_ELIM", + "T72x_COMPUTE_ACTIVE", + "T72x_COMPUTE_TASKS", + "T72x_COMPUTE_THREADS", + "T72x_TRIPIPE_ACTIVE", + "T72x_ARITH_WORDS", + "T72x_ARITH_CYCLES_REG", + "T72x_LS_WORDS", + "T72x_LS_ISSUES", + "T72x_LS_RESTARTS", + "T72x_LS_REISSUES_MISS", + "T72x_TEX_WORDS", + "T72x_TEX_BUBBLES", + "T72x_TEX_ISSUES", + "T72x_LSC_READ_HITS", + "T72x_LSC_READ_MISSES", + "T72x_LSC_WRITE_HITS", + "T72x_LSC_WRITE_MISSES", + "T72x_LSC_ATOMIC_HITS", + "T72x_LSC_ATOMIC_MISSES", + "T72x_LSC_LINE_FETCHES", + "T72x_LSC_DIRTY_LINE", + "T72x_LSC_SNOOPS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*L2 and MMU */ + "", + "", + "", + "", + "T72x_L2_EXT_WRITE_BEAT", + "T72x_L2_EXT_READ_BEAT", + "T72x_L2_READ_SNOOP", + "T72x_L2_READ_HIT", + "T72x_L2_WRITE_SNOOP", + "T72x_L2_WRITE_HIT", + "T72x_L2_EXT_WRITE_SMALL", + "T72x_L2_EXT_BARRIER", + "T72x_L2_EXT_AR_STALL", + "T72x_L2_EXT_W_STALL", + "T72x_L2_SNOOP_FULL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + ""}; + +static const char *const hardware_counters_mali_t76x[] = + { + /* Job Manager */ + "", + "", + "", + "", + "T76x_MESSAGES_SENT", + "T76x_MESSAGES_RECEIVED", + "T76x_GPU_ACTIVE", + "T76x_IRQ_ACTIVE", + "T76x_JS0_JOBS", + "T76x_JS0_TASKS", + "T76x_JS0_ACTIVE", + "", + "T76x_JS0_WAIT_READ", + "T76x_JS0_WAIT_ISSUE", + "T76x_JS0_WAIT_DEPEND", + "T76x_JS0_WAIT_FINISH", + "T76x_JS1_JOBS", + "T76x_JS1_TASKS", + "T76x_JS1_ACTIVE", + "", + "T76x_JS1_WAIT_READ", + "T76x_JS1_WAIT_ISSUE", + "T76x_JS1_WAIT_DEPEND", + "T76x_JS1_WAIT_FINISH", + "T76x_JS2_JOBS", + "T76x_JS2_TASKS", + "T76x_JS2_ACTIVE", + "", + "T76x_JS2_WAIT_READ", + "T76x_JS2_WAIT_ISSUE", + "T76x_JS2_WAIT_DEPEND", + "T76x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T76x_TI_JOBS_PROCESSED", + "T76x_TI_TRIANGLES", + "T76x_TI_QUADS", + "T76x_TI_POLYGONS", + "T76x_TI_POINTS", + "T76x_TI_LINES", + "T76x_TI_VCACHE_HIT", + "T76x_TI_VCACHE_MISS", + "T76x_TI_FRONT_FACING", + "T76x_TI_BACK_FACING", + "T76x_TI_PRIM_VISIBLE", + "T76x_TI_PRIM_CULLED", + "T76x_TI_PRIM_CLIPPED", + "T76x_TI_LEVEL0", + "T76x_TI_LEVEL1", + "T76x_TI_LEVEL2", + "T76x_TI_LEVEL3", + "T76x_TI_LEVEL4", + "T76x_TI_LEVEL5", + "T76x_TI_LEVEL6", + "T76x_TI_LEVEL7", + "T76x_TI_COMMAND_1", + "T76x_TI_COMMAND_2", + "T76x_TI_COMMAND_3", + "T76x_TI_COMMAND_4", + "T76x_TI_COMMAND_5_7", + "T76x_TI_COMMAND_8_15", + "T76x_TI_COMMAND_16_63", + "T76x_TI_COMMAND_64", + "T76x_TI_COMPRESS_IN", + "T76x_TI_COMPRESS_OUT", + "T76x_TI_COMPRESS_FLUSH", + "T76x_TI_TIMESTAMPS", + "T76x_TI_PCACHE_HIT", + "T76x_TI_PCACHE_MISS", + "T76x_TI_PCACHE_LINE", + "T76x_TI_PCACHE_STALL", + "T76x_TI_WRBUF_HIT", + "T76x_TI_WRBUF_MISS", + "T76x_TI_WRBUF_LINE", + "T76x_TI_WRBUF_PARTIAL", + "T76x_TI_WRBUF_STALL", + "T76x_TI_ACTIVE", + "T76x_TI_LOADING_DESC", + "T76x_TI_INDEX_WAIT", + "T76x_TI_INDEX_RANGE_WAIT", + "T76x_TI_VERTEX_WAIT", + "T76x_TI_PCACHE_WAIT", + "T76x_TI_WRBUF_WAIT", + "T76x_TI_BUS_READ", + "T76x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T76x_TI_UTLB_HIT", + "T76x_TI_UTLB_NEW_MISS", + "T76x_TI_UTLB_REPLAY_FULL", + "T76x_TI_UTLB_REPLAY_MISS", + "T76x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T76x_FRAG_ACTIVE", + "T76x_FRAG_PRIMITIVES", + "T76x_FRAG_PRIMITIVES_DROPPED", + "T76x_FRAG_CYCLES_DESC", + "T76x_FRAG_CYCLES_FPKQ_ACTIVE", + "T76x_FRAG_CYCLES_VERT", + "T76x_FRAG_CYCLES_TRISETUP", + "T76x_FRAG_CYCLES_EZS_ACTIVE", + "T76x_FRAG_THREADS", + "T76x_FRAG_DUMMY_THREADS", + "T76x_FRAG_QUADS_RAST", + "T76x_FRAG_QUADS_EZS_TEST", + "T76x_FRAG_QUADS_EZS_KILLED", + "T76x_FRAG_THREADS_LZS_TEST", + "T76x_FRAG_THREADS_LZS_KILLED", + "T76x_FRAG_CYCLES_NO_TILE", + "T76x_FRAG_NUM_TILES", + "T76x_FRAG_TRANS_ELIM", + "T76x_COMPUTE_ACTIVE", + "T76x_COMPUTE_TASKS", + "T76x_COMPUTE_THREADS", + "T76x_COMPUTE_CYCLES_DESC", + "T76x_TRIPIPE_ACTIVE", + "T76x_ARITH_WORDS", + "T76x_ARITH_CYCLES_REG", + "T76x_ARITH_CYCLES_L0", + "T76x_ARITH_FRAG_DEPEND", + "T76x_LS_WORDS", + "T76x_LS_ISSUES", + "T76x_LS_REISSUE_ATTR", + "T76x_LS_REISSUES_VARY", + "T76x_LS_VARY_RV_MISS", + "T76x_LS_VARY_RV_HIT", + "T76x_LS_NO_UNPARK", + "T76x_TEX_WORDS", + "T76x_TEX_BUBBLES", + "T76x_TEX_WORDS_L0", + "T76x_TEX_WORDS_DESC", + "T76x_TEX_ISSUES", + "T76x_TEX_RECIRC_FMISS", + "T76x_TEX_RECIRC_DESC", + "T76x_TEX_RECIRC_MULTI", + "T76x_TEX_RECIRC_PMISS", + "T76x_TEX_RECIRC_CONF", + "T76x_LSC_READ_HITS", + "T76x_LSC_READ_OP", + "T76x_LSC_WRITE_HITS", + "T76x_LSC_WRITE_OP", + "T76x_LSC_ATOMIC_HITS", + "T76x_LSC_ATOMIC_OP", + "T76x_LSC_LINE_FETCHES", + "T76x_LSC_DIRTY_LINE", + "T76x_LSC_SNOOPS", + "T76x_AXI_TLB_STALL", + "T76x_AXI_TLB_MISS", + "T76x_AXI_TLB_TRANSACTION", + "T76x_LS_TLB_MISS", + "T76x_LS_TLB_HIT", + "T76x_AXI_BEATS_READ", + "T76x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T76x_MMU_HIT", + "T76x_MMU_NEW_MISS", + "T76x_MMU_REPLAY_FULL", + "T76x_MMU_REPLAY_MISS", + "T76x_MMU_TABLE_WALK", + "T76x_MMU_REQUESTS", + "", + "", + "T76x_UTLB_HIT", + "T76x_UTLB_NEW_MISS", + "T76x_UTLB_REPLAY_FULL", + "T76x_UTLB_REPLAY_MISS", + "T76x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T76x_L2_EXT_WRITE_BEATS", + "T76x_L2_EXT_READ_BEATS", + "T76x_L2_ANY_LOOKUP", + "T76x_L2_READ_LOOKUP", + "T76x_L2_SREAD_LOOKUP", + "T76x_L2_READ_REPLAY", + "T76x_L2_READ_SNOOP", + "T76x_L2_READ_HIT", + "T76x_L2_CLEAN_MISS", + "T76x_L2_WRITE_LOOKUP", + "T76x_L2_SWRITE_LOOKUP", + "T76x_L2_WRITE_REPLAY", + "T76x_L2_WRITE_SNOOP", + "T76x_L2_WRITE_HIT", + "T76x_L2_EXT_READ_FULL", + "", + "T76x_L2_EXT_WRITE_FULL", + "T76x_L2_EXT_R_W_HAZARD", + "T76x_L2_EXT_READ", + "T76x_L2_EXT_READ_LINE", + "T76x_L2_EXT_WRITE", + "T76x_L2_EXT_WRITE_LINE", + "T76x_L2_EXT_WRITE_SMALL", + "T76x_L2_EXT_BARRIER", + "T76x_L2_EXT_AR_STALL", + "T76x_L2_EXT_R_BUF_FULL", + "T76x_L2_EXT_RD_BUF_FULL", + "T76x_L2_EXT_R_RAW", + "T76x_L2_EXT_W_STALL", + "T76x_L2_EXT_W_BUF_FULL", + "T76x_L2_EXT_R_BUF_FULL", + "T76x_L2_TAG_HAZARD", + "T76x_L2_SNOOP_FULL", + "T76x_L2_REPLAY_FULL"}; + +static const char *const hardware_counters_mali_t82x[] = + { + /* Job Manager */ + "", + "", + "", + "", + "T82x_MESSAGES_SENT", + "T82x_MESSAGES_RECEIVED", + "T82x_GPU_ACTIVE", + "T82x_IRQ_ACTIVE", + "T82x_JS0_JOBS", + "T82x_JS0_TASKS", + "T82x_JS0_ACTIVE", + "", + "T82x_JS0_WAIT_READ", + "T82x_JS0_WAIT_ISSUE", + "T82x_JS0_WAIT_DEPEND", + "T82x_JS0_WAIT_FINISH", + "T82x_JS1_JOBS", + "T82x_JS1_TASKS", + "T82x_JS1_ACTIVE", + "", + "T82x_JS1_WAIT_READ", + "T82x_JS1_WAIT_ISSUE", + "T82x_JS1_WAIT_DEPEND", + "T82x_JS1_WAIT_FINISH", + "T82x_JS2_JOBS", + "T82x_JS2_TASKS", + "T82x_JS2_ACTIVE", + "", + "T82x_JS2_WAIT_READ", + "T82x_JS2_WAIT_ISSUE", + "T82x_JS2_WAIT_DEPEND", + "T82x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T82x_TI_JOBS_PROCESSED", + "T82x_TI_TRIANGLES", + "T82x_TI_QUADS", + "T82x_TI_POLYGONS", + "T82x_TI_POINTS", + "T82x_TI_LINES", + "T82x_TI_FRONT_FACING", + "T82x_TI_BACK_FACING", + "T82x_TI_PRIM_VISIBLE", + "T82x_TI_PRIM_CULLED", + "T82x_TI_PRIM_CLIPPED", + "", + "", + "", + "", + "", + "", + "", + "", + "T82x_TI_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Shader Core */ + "", + "", + "", + "", + "T82x_FRAG_ACTIVE", + "T82x_FRAG_PRIMITIVES", + "T82x_FRAG_PRIMITIVES_DROPPED", + "T82x_FRAG_CYCLES_DESC", + "T82x_FRAG_CYCLES_FPKQ_ACTIVE", + "T82x_FRAG_CYCLES_VERT", + "T82x_FRAG_CYCLES_TRISETUP", + "T82x_FRAG_CYCLES_EZS_ACTIVE", + "T82x_FRAG_THREADS", + "T82x_FRAG_DUMMY_THREADS", + "T82x_FRAG_QUADS_RAST", + "T82x_FRAG_QUADS_EZS_TEST", + "T82x_FRAG_QUADS_EZS_KILLED", + "T82x_FRAG_THREADS_LZS_TEST", + "T82x_FRAG_THREADS_LZS_KILLED", + "T82x_FRAG_CYCLES_NO_TILE", + "T82x_FRAG_NUM_TILES", + "T82x_FRAG_TRANS_ELIM", + "T82x_COMPUTE_ACTIVE", + "T82x_COMPUTE_TASKS", + "T82x_COMPUTE_THREADS", + "T82x_COMPUTE_CYCLES_DESC", + "T82x_TRIPIPE_ACTIVE", + "T82x_ARITH_WORDS", + "T82x_ARITH_CYCLES_REG", + "T82x_ARITH_CYCLES_L0", + "T82x_ARITH_FRAG_DEPEND", + "T82x_LS_WORDS", + "T82x_LS_ISSUES", + "T82x_LS_REISSUE_ATTR", + "T82x_LS_REISSUES_VARY", + "T82x_LS_VARY_RV_MISS", + "T82x_LS_VARY_RV_HIT", + "T82x_LS_NO_UNPARK", + "T82x_TEX_WORDS", + "T82x_TEX_BUBBLES", + "T82x_TEX_WORDS_L0", + "T82x_TEX_WORDS_DESC", + "T82x_TEX_ISSUES", + "T82x_TEX_RECIRC_FMISS", + "T82x_TEX_RECIRC_DESC", + "T82x_TEX_RECIRC_MULTI", + "T82x_TEX_RECIRC_PMISS", + "T82x_TEX_RECIRC_CONF", + "T82x_LSC_READ_HITS", + "T82x_LSC_READ_OP", + "T82x_LSC_WRITE_HITS", + "T82x_LSC_WRITE_OP", + "T82x_LSC_ATOMIC_HITS", + "T82x_LSC_ATOMIC_OP", + "T82x_LSC_LINE_FETCHES", + "T82x_LSC_DIRTY_LINE", + "T82x_LSC_SNOOPS", + "T82x_AXI_TLB_STALL", + "T82x_AXI_TLB_MISS", + "T82x_AXI_TLB_TRANSACTION", + "T82x_LS_TLB_MISS", + "T82x_LS_TLB_HIT", + "T82x_AXI_BEATS_READ", + "T82x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T82x_MMU_HIT", + "T82x_MMU_NEW_MISS", + "T82x_MMU_REPLAY_FULL", + "T82x_MMU_REPLAY_MISS", + "T82x_MMU_TABLE_WALK", + "T82x_MMU_REQUESTS", + "", + "", + "T82x_UTLB_HIT", + "T82x_UTLB_NEW_MISS", + "T82x_UTLB_REPLAY_FULL", + "T82x_UTLB_REPLAY_MISS", + "T82x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T82x_L2_EXT_WRITE_BEATS", + "T82x_L2_EXT_READ_BEATS", + "T82x_L2_ANY_LOOKUP", + "T82x_L2_READ_LOOKUP", + "T82x_L2_SREAD_LOOKUP", + "T82x_L2_READ_REPLAY", + "T82x_L2_READ_SNOOP", + "T82x_L2_READ_HIT", + "T82x_L2_CLEAN_MISS", + "T82x_L2_WRITE_LOOKUP", + "T82x_L2_SWRITE_LOOKUP", + "T82x_L2_WRITE_REPLAY", + "T82x_L2_WRITE_SNOOP", + "T82x_L2_WRITE_HIT", + "T82x_L2_EXT_READ_FULL", + "", + "T82x_L2_EXT_WRITE_FULL", + "T82x_L2_EXT_R_W_HAZARD", + "T82x_L2_EXT_READ", + "T82x_L2_EXT_READ_LINE", + "T82x_L2_EXT_WRITE", + "T82x_L2_EXT_WRITE_LINE", + "T82x_L2_EXT_WRITE_SMALL", + "T82x_L2_EXT_BARRIER", + "T82x_L2_EXT_AR_STALL", + "T82x_L2_EXT_R_BUF_FULL", + "T82x_L2_EXT_RD_BUF_FULL", + "T82x_L2_EXT_R_RAW", + "T82x_L2_EXT_W_STALL", + "T82x_L2_EXT_W_BUF_FULL", + "T82x_L2_EXT_R_BUF_FULL", + "T82x_L2_TAG_HAZARD", + "T82x_L2_SNOOP_FULL", + "T82x_L2_REPLAY_FULL"}; + +static const char *const hardware_counters_mali_t83x[] = + { + /* Job Manager */ + "", + "", + "", + "", + "T83x_MESSAGES_SENT", + "T83x_MESSAGES_RECEIVED", + "T83x_GPU_ACTIVE", + "T83x_IRQ_ACTIVE", + "T83x_JS0_JOBS", + "T83x_JS0_TASKS", + "T83x_JS0_ACTIVE", + "", + "T83x_JS0_WAIT_READ", + "T83x_JS0_WAIT_ISSUE", + "T83x_JS0_WAIT_DEPEND", + "T83x_JS0_WAIT_FINISH", + "T83x_JS1_JOBS", + "T83x_JS1_TASKS", + "T83x_JS1_ACTIVE", + "", + "T83x_JS1_WAIT_READ", + "T83x_JS1_WAIT_ISSUE", + "T83x_JS1_WAIT_DEPEND", + "T83x_JS1_WAIT_FINISH", + "T83x_JS2_JOBS", + "T83x_JS2_TASKS", + "T83x_JS2_ACTIVE", + "", + "T83x_JS2_WAIT_READ", + "T83x_JS2_WAIT_ISSUE", + "T83x_JS2_WAIT_DEPEND", + "T83x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T83x_TI_JOBS_PROCESSED", + "T83x_TI_TRIANGLES", + "T83x_TI_QUADS", + "T83x_TI_POLYGONS", + "T83x_TI_POINTS", + "T83x_TI_LINES", + "T83x_TI_FRONT_FACING", + "T83x_TI_BACK_FACING", + "T83x_TI_PRIM_VISIBLE", + "T83x_TI_PRIM_CULLED", + "T83x_TI_PRIM_CLIPPED", + "", + "", + "", + "", + "", + "", + "", + "", + "T83x_TI_ACTIVE", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Shader Core */ + "", + "", + "", + "", + "T83x_FRAG_ACTIVE", + "T83x_FRAG_PRIMITIVES", + "T83x_FRAG_PRIMITIVES_DROPPED", + "T83x_FRAG_CYCLES_DESC", + "T83x_FRAG_CYCLES_FPKQ_ACTIVE", + "T83x_FRAG_CYCLES_VERT", + "T83x_FRAG_CYCLES_TRISETUP", + "T83x_FRAG_CYCLES_EZS_ACTIVE", + "T83x_FRAG_THREADS", + "T83x_FRAG_DUMMY_THREADS", + "T83x_FRAG_QUADS_RAST", + "T83x_FRAG_QUADS_EZS_TEST", + "T83x_FRAG_QUADS_EZS_KILLED", + "T83x_FRAG_THREADS_LZS_TEST", + "T83x_FRAG_THREADS_LZS_KILLED", + "T83x_FRAG_CYCLES_NO_TILE", + "T83x_FRAG_NUM_TILES", + "T83x_FRAG_TRANS_ELIM", + "T83x_COMPUTE_ACTIVE", + "T83x_COMPUTE_TASKS", + "T83x_COMPUTE_THREADS", + "T83x_COMPUTE_CYCLES_DESC", + "T83x_TRIPIPE_ACTIVE", + "T83x_ARITH_WORDS", + "T83x_ARITH_CYCLES_REG", + "T83x_ARITH_CYCLES_L0", + "T83x_ARITH_FRAG_DEPEND", + "T83x_LS_WORDS", + "T83x_LS_ISSUES", + "T83x_LS_REISSUE_ATTR", + "T83x_LS_REISSUES_VARY", + "T83x_LS_VARY_RV_MISS", + "T83x_LS_VARY_RV_HIT", + "T83x_LS_NO_UNPARK", + "T83x_TEX_WORDS", + "T83x_TEX_BUBBLES", + "T83x_TEX_WORDS_L0", + "T83x_TEX_WORDS_DESC", + "T83x_TEX_ISSUES", + "T83x_TEX_RECIRC_FMISS", + "T83x_TEX_RECIRC_DESC", + "T83x_TEX_RECIRC_MULTI", + "T83x_TEX_RECIRC_PMISS", + "T83x_TEX_RECIRC_CONF", + "T83x_LSC_READ_HITS", + "T83x_LSC_READ_OP", + "T83x_LSC_WRITE_HITS", + "T83x_LSC_WRITE_OP", + "T83x_LSC_ATOMIC_HITS", + "T83x_LSC_ATOMIC_OP", + "T83x_LSC_LINE_FETCHES", + "T83x_LSC_DIRTY_LINE", + "T83x_LSC_SNOOPS", + "T83x_AXI_TLB_STALL", + "T83x_AXI_TLB_MISS", + "T83x_AXI_TLB_TRANSACTION", + "T83x_LS_TLB_MISS", + "T83x_LS_TLB_HIT", + "T83x_AXI_BEATS_READ", + "T83x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T83x_MMU_HIT", + "T83x_MMU_NEW_MISS", + "T83x_MMU_REPLAY_FULL", + "T83x_MMU_REPLAY_MISS", + "T83x_MMU_TABLE_WALK", + "T83x_MMU_REQUESTS", + "", + "", + "T83x_UTLB_HIT", + "T83x_UTLB_NEW_MISS", + "T83x_UTLB_REPLAY_FULL", + "T83x_UTLB_REPLAY_MISS", + "T83x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T83x_L2_EXT_WRITE_BEATS", + "T83x_L2_EXT_READ_BEATS", + "T83x_L2_ANY_LOOKUP", + "T83x_L2_READ_LOOKUP", + "T83x_L2_SREAD_LOOKUP", + "T83x_L2_READ_REPLAY", + "T83x_L2_READ_SNOOP", + "T83x_L2_READ_HIT", + "T83x_L2_CLEAN_MISS", + "T83x_L2_WRITE_LOOKUP", + "T83x_L2_SWRITE_LOOKUP", + "T83x_L2_WRITE_REPLAY", + "T83x_L2_WRITE_SNOOP", + "T83x_L2_WRITE_HIT", + "T83x_L2_EXT_READ_FULL", + "", + "T83x_L2_EXT_WRITE_FULL", + "T83x_L2_EXT_R_W_HAZARD", + "T83x_L2_EXT_READ", + "T83x_L2_EXT_READ_LINE", + "T83x_L2_EXT_WRITE", + "T83x_L2_EXT_WRITE_LINE", + "T83x_L2_EXT_WRITE_SMALL", + "T83x_L2_EXT_BARRIER", + "T83x_L2_EXT_AR_STALL", + "T83x_L2_EXT_R_BUF_FULL", + "T83x_L2_EXT_RD_BUF_FULL", + "T83x_L2_EXT_R_RAW", + "T83x_L2_EXT_W_STALL", + "T83x_L2_EXT_W_BUF_FULL", + "T83x_L2_EXT_R_BUF_FULL", + "T83x_L2_TAG_HAZARD", + "T83x_L2_SNOOP_FULL", + "T83x_L2_REPLAY_FULL"}; + +static const char *const hardware_counters_mali_t86x[] = + { + /* Job Manager */ + "", + "", + "", + "", + "T86x_MESSAGES_SENT", + "T86x_MESSAGES_RECEIVED", + "T86x_GPU_ACTIVE", + "T86x_IRQ_ACTIVE", + "T86x_JS0_JOBS", + "T86x_JS0_TASKS", + "T86x_JS0_ACTIVE", + "", + "T86x_JS0_WAIT_READ", + "T86x_JS0_WAIT_ISSUE", + "T86x_JS0_WAIT_DEPEND", + "T86x_JS0_WAIT_FINISH", + "T86x_JS1_JOBS", + "T86x_JS1_TASKS", + "T86x_JS1_ACTIVE", + "", + "T86x_JS1_WAIT_READ", + "T86x_JS1_WAIT_ISSUE", + "T86x_JS1_WAIT_DEPEND", + "T86x_JS1_WAIT_FINISH", + "T86x_JS2_JOBS", + "T86x_JS2_TASKS", + "T86x_JS2_ACTIVE", + "", + "T86x_JS2_WAIT_READ", + "T86x_JS2_WAIT_ISSUE", + "T86x_JS2_WAIT_DEPEND", + "T86x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T86x_TI_JOBS_PROCESSED", + "T86x_TI_TRIANGLES", + "T86x_TI_QUADS", + "T86x_TI_POLYGONS", + "T86x_TI_POINTS", + "T86x_TI_LINES", + "T86x_TI_VCACHE_HIT", + "T86x_TI_VCACHE_MISS", + "T86x_TI_FRONT_FACING", + "T86x_TI_BACK_FACING", + "T86x_TI_PRIM_VISIBLE", + "T86x_TI_PRIM_CULLED", + "T86x_TI_PRIM_CLIPPED", + "T86x_TI_LEVEL0", + "T86x_TI_LEVEL1", + "T86x_TI_LEVEL2", + "T86x_TI_LEVEL3", + "T86x_TI_LEVEL4", + "T86x_TI_LEVEL5", + "T86x_TI_LEVEL6", + "T86x_TI_LEVEL7", + "T86x_TI_COMMAND_1", + "T86x_TI_COMMAND_2", + "T86x_TI_COMMAND_3", + "T86x_TI_COMMAND_4", + "T86x_TI_COMMAND_5_7", + "T86x_TI_COMMAND_8_15", + "T86x_TI_COMMAND_16_63", + "T86x_TI_COMMAND_64", + "T86x_TI_COMPRESS_IN", + "T86x_TI_COMPRESS_OUT", + "T86x_TI_COMPRESS_FLUSH", + "T86x_TI_TIMESTAMPS", + "T86x_TI_PCACHE_HIT", + "T86x_TI_PCACHE_MISS", + "T86x_TI_PCACHE_LINE", + "T86x_TI_PCACHE_STALL", + "T86x_TI_WRBUF_HIT", + "T86x_TI_WRBUF_MISS", + "T86x_TI_WRBUF_LINE", + "T86x_TI_WRBUF_PARTIAL", + "T86x_TI_WRBUF_STALL", + "T86x_TI_ACTIVE", + "T86x_TI_LOADING_DESC", + "T86x_TI_INDEX_WAIT", + "T86x_TI_INDEX_RANGE_WAIT", + "T86x_TI_VERTEX_WAIT", + "T86x_TI_PCACHE_WAIT", + "T86x_TI_WRBUF_WAIT", + "T86x_TI_BUS_READ", + "T86x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T86x_TI_UTLB_HIT", + "T86x_TI_UTLB_NEW_MISS", + "T86x_TI_UTLB_REPLAY_FULL", + "T86x_TI_UTLB_REPLAY_MISS", + "T86x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T86x_FRAG_ACTIVE", + "T86x_FRAG_PRIMITIVES", + "T86x_FRAG_PRIMITIVES_DROPPED", + "T86x_FRAG_CYCLES_DESC", + "T86x_FRAG_CYCLES_FPKQ_ACTIVE", + "T86x_FRAG_CYCLES_VERT", + "T86x_FRAG_CYCLES_TRISETUP", + "T86x_FRAG_CYCLES_EZS_ACTIVE", + "T86x_FRAG_THREADS", + "T86x_FRAG_DUMMY_THREADS", + "T86x_FRAG_QUADS_RAST", + "T86x_FRAG_QUADS_EZS_TEST", + "T86x_FRAG_QUADS_EZS_KILLED", + "T86x_FRAG_THREADS_LZS_TEST", + "T86x_FRAG_THREADS_LZS_KILLED", + "T86x_FRAG_CYCLES_NO_TILE", + "T86x_FRAG_NUM_TILES", + "T86x_FRAG_TRANS_ELIM", + "T86x_COMPUTE_ACTIVE", + "T86x_COMPUTE_TASKS", + "T86x_COMPUTE_THREADS", + "T86x_COMPUTE_CYCLES_DESC", + "T86x_TRIPIPE_ACTIVE", + "T86x_ARITH_WORDS", + "T86x_ARITH_CYCLES_REG", + "T86x_ARITH_CYCLES_L0", + "T86x_ARITH_FRAG_DEPEND", + "T86x_LS_WORDS", + "T86x_LS_ISSUES", + "T86x_LS_REISSUE_ATTR", + "T86x_LS_REISSUES_VARY", + "T86x_LS_VARY_RV_MISS", + "T86x_LS_VARY_RV_HIT", + "T86x_LS_NO_UNPARK", + "T86x_TEX_WORDS", + "T86x_TEX_BUBBLES", + "T86x_TEX_WORDS_L0", + "T86x_TEX_WORDS_DESC", + "T86x_TEX_ISSUES", + "T86x_TEX_RECIRC_FMISS", + "T86x_TEX_RECIRC_DESC", + "T86x_TEX_RECIRC_MULTI", + "T86x_TEX_RECIRC_PMISS", + "T86x_TEX_RECIRC_CONF", + "T86x_LSC_READ_HITS", + "T86x_LSC_READ_OP", + "T86x_LSC_WRITE_HITS", + "T86x_LSC_WRITE_OP", + "T86x_LSC_ATOMIC_HITS", + "T86x_LSC_ATOMIC_OP", + "T86x_LSC_LINE_FETCHES", + "T86x_LSC_DIRTY_LINE", + "T86x_LSC_SNOOPS", + "T86x_AXI_TLB_STALL", + "T86x_AXI_TLB_MISS", + "T86x_AXI_TLB_TRANSACTION", + "T86x_LS_TLB_MISS", + "T86x_LS_TLB_HIT", + "T86x_AXI_BEATS_READ", + "T86x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T86x_MMU_HIT", + "T86x_MMU_NEW_MISS", + "T86x_MMU_REPLAY_FULL", + "T86x_MMU_REPLAY_MISS", + "T86x_MMU_TABLE_WALK", + "T86x_MMU_REQUESTS", + "", + "", + "T86x_UTLB_HIT", + "T86x_UTLB_NEW_MISS", + "T86x_UTLB_REPLAY_FULL", + "T86x_UTLB_REPLAY_MISS", + "T86x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T86x_L2_EXT_WRITE_BEATS", + "T86x_L2_EXT_READ_BEATS", + "T86x_L2_ANY_LOOKUP", + "T86x_L2_READ_LOOKUP", + "T86x_L2_SREAD_LOOKUP", + "T86x_L2_READ_REPLAY", + "T86x_L2_READ_SNOOP", + "T86x_L2_READ_HIT", + "T86x_L2_CLEAN_MISS", + "T86x_L2_WRITE_LOOKUP", + "T86x_L2_SWRITE_LOOKUP", + "T86x_L2_WRITE_REPLAY", + "T86x_L2_WRITE_SNOOP", + "T86x_L2_WRITE_HIT", + "T86x_L2_EXT_READ_FULL", + "", + "T86x_L2_EXT_WRITE_FULL", + "T86x_L2_EXT_R_W_HAZARD", + "T86x_L2_EXT_READ", + "T86x_L2_EXT_READ_LINE", + "T86x_L2_EXT_WRITE", + "T86x_L2_EXT_WRITE_LINE", + "T86x_L2_EXT_WRITE_SMALL", + "T86x_L2_EXT_BARRIER", + "T86x_L2_EXT_AR_STALL", + "T86x_L2_EXT_R_BUF_FULL", + "T86x_L2_EXT_RD_BUF_FULL", + "T86x_L2_EXT_R_RAW", + "T86x_L2_EXT_W_STALL", + "T86x_L2_EXT_W_BUF_FULL", + "T86x_L2_EXT_R_BUF_FULL", + "T86x_L2_TAG_HAZARD", + "T86x_L2_SNOOP_FULL", + "T86x_L2_REPLAY_FULL"}; + +static const char *const hardware_counters_mali_t88x[] = + { + /* Job Manager */ + "", + "", + "", + "", + "T88x_MESSAGES_SENT", + "T88x_MESSAGES_RECEIVED", + "T88x_GPU_ACTIVE", + "T88x_IRQ_ACTIVE", + "T88x_JS0_JOBS", + "T88x_JS0_TASKS", + "T88x_JS0_ACTIVE", + "", + "T88x_JS0_WAIT_READ", + "T88x_JS0_WAIT_ISSUE", + "T88x_JS0_WAIT_DEPEND", + "T88x_JS0_WAIT_FINISH", + "T88x_JS1_JOBS", + "T88x_JS1_TASKS", + "T88x_JS1_ACTIVE", + "", + "T88x_JS1_WAIT_READ", + "T88x_JS1_WAIT_ISSUE", + "T88x_JS1_WAIT_DEPEND", + "T88x_JS1_WAIT_FINISH", + "T88x_JS2_JOBS", + "T88x_JS2_TASKS", + "T88x_JS2_ACTIVE", + "", + "T88x_JS2_WAIT_READ", + "T88x_JS2_WAIT_ISSUE", + "T88x_JS2_WAIT_DEPEND", + "T88x_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /*Tiler */ + "", + "", + "", + "T88x_TI_JOBS_PROCESSED", + "T88x_TI_TRIANGLES", + "T88x_TI_QUADS", + "T88x_TI_POLYGONS", + "T88x_TI_POINTS", + "T88x_TI_LINES", + "T88x_TI_VCACHE_HIT", + "T88x_TI_VCACHE_MISS", + "T88x_TI_FRONT_FACING", + "T88x_TI_BACK_FACING", + "T88x_TI_PRIM_VISIBLE", + "T88x_TI_PRIM_CULLED", + "T88x_TI_PRIM_CLIPPED", + "T88x_TI_LEVEL0", + "T88x_TI_LEVEL1", + "T88x_TI_LEVEL2", + "T88x_TI_LEVEL3", + "T88x_TI_LEVEL4", + "T88x_TI_LEVEL5", + "T88x_TI_LEVEL6", + "T88x_TI_LEVEL7", + "T88x_TI_COMMAND_1", + "T88x_TI_COMMAND_2", + "T88x_TI_COMMAND_3", + "T88x_TI_COMMAND_4", + "T88x_TI_COMMAND_5_7", + "T88x_TI_COMMAND_8_15", + "T88x_TI_COMMAND_16_63", + "T88x_TI_COMMAND_64", + "T88x_TI_COMPRESS_IN", + "T88x_TI_COMPRESS_OUT", + "T88x_TI_COMPRESS_FLUSH", + "T88x_TI_TIMESTAMPS", + "T88x_TI_PCACHE_HIT", + "T88x_TI_PCACHE_MISS", + "T88x_TI_PCACHE_LINE", + "T88x_TI_PCACHE_STALL", + "T88x_TI_WRBUF_HIT", + "T88x_TI_WRBUF_MISS", + "T88x_TI_WRBUF_LINE", + "T88x_TI_WRBUF_PARTIAL", + "T88x_TI_WRBUF_STALL", + "T88x_TI_ACTIVE", + "T88x_TI_LOADING_DESC", + "T88x_TI_INDEX_WAIT", + "T88x_TI_INDEX_RANGE_WAIT", + "T88x_TI_VERTEX_WAIT", + "T88x_TI_PCACHE_WAIT", + "T88x_TI_WRBUF_WAIT", + "T88x_TI_BUS_READ", + "T88x_TI_BUS_WRITE", + "", + "", + "", + "", + "", + "T88x_TI_UTLB_HIT", + "T88x_TI_UTLB_NEW_MISS", + "T88x_TI_UTLB_REPLAY_FULL", + "T88x_TI_UTLB_REPLAY_MISS", + "T88x_TI_UTLB_STALL", + + /* Shader Core */ + "", + "", + "", + "", + "T88x_FRAG_ACTIVE", + "T88x_FRAG_PRIMITIVES", + "T88x_FRAG_PRIMITIVES_DROPPED", + "T88x_FRAG_CYCLES_DESC", + "T88x_FRAG_CYCLES_FPKQ_ACTIVE", + "T88x_FRAG_CYCLES_VERT", + "T88x_FRAG_CYCLES_TRISETUP", + "T88x_FRAG_CYCLES_EZS_ACTIVE", + "T88x_FRAG_THREADS", + "T88x_FRAG_DUMMY_THREADS", + "T88x_FRAG_QUADS_RAST", + "T88x_FRAG_QUADS_EZS_TEST", + "T88x_FRAG_QUADS_EZS_KILLED", + "T88x_FRAG_THREADS_LZS_TEST", + "T88x_FRAG_THREADS_LZS_KILLED", + "T88x_FRAG_CYCLES_NO_TILE", + "T88x_FRAG_NUM_TILES", + "T88x_FRAG_TRANS_ELIM", + "T88x_COMPUTE_ACTIVE", + "T88x_COMPUTE_TASKS", + "T88x_COMPUTE_THREADS", + "T88x_COMPUTE_CYCLES_DESC", + "T88x_TRIPIPE_ACTIVE", + "T88x_ARITH_WORDS", + "T88x_ARITH_CYCLES_REG", + "T88x_ARITH_CYCLES_L0", + "T88x_ARITH_FRAG_DEPEND", + "T88x_LS_WORDS", + "T88x_LS_ISSUES", + "T88x_LS_REISSUE_ATTR", + "T88x_LS_REISSUES_VARY", + "T88x_LS_VARY_RV_MISS", + "T88x_LS_VARY_RV_HIT", + "T88x_LS_NO_UNPARK", + "T88x_TEX_WORDS", + "T88x_TEX_BUBBLES", + "T88x_TEX_WORDS_L0", + "T88x_TEX_WORDS_DESC", + "T88x_TEX_ISSUES", + "T88x_TEX_RECIRC_FMISS", + "T88x_TEX_RECIRC_DESC", + "T88x_TEX_RECIRC_MULTI", + "T88x_TEX_RECIRC_PMISS", + "T88x_TEX_RECIRC_CONF", + "T88x_LSC_READ_HITS", + "T88x_LSC_READ_OP", + "T88x_LSC_WRITE_HITS", + "T88x_LSC_WRITE_OP", + "T88x_LSC_ATOMIC_HITS", + "T88x_LSC_ATOMIC_OP", + "T88x_LSC_LINE_FETCHES", + "T88x_LSC_DIRTY_LINE", + "T88x_LSC_SNOOPS", + "T88x_AXI_TLB_STALL", + "T88x_AXI_TLB_MISS", + "T88x_AXI_TLB_TRANSACTION", + "T88x_LS_TLB_MISS", + "T88x_LS_TLB_HIT", + "T88x_AXI_BEATS_READ", + "T88x_AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "T88x_MMU_HIT", + "T88x_MMU_NEW_MISS", + "T88x_MMU_REPLAY_FULL", + "T88x_MMU_REPLAY_MISS", + "T88x_MMU_TABLE_WALK", + "T88x_MMU_REQUESTS", + "", + "", + "T88x_UTLB_HIT", + "T88x_UTLB_NEW_MISS", + "T88x_UTLB_REPLAY_FULL", + "T88x_UTLB_REPLAY_MISS", + "T88x_UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "T88x_L2_EXT_WRITE_BEATS", + "T88x_L2_EXT_READ_BEATS", + "T88x_L2_ANY_LOOKUP", + "T88x_L2_READ_LOOKUP", + "T88x_L2_SREAD_LOOKUP", + "T88x_L2_READ_REPLAY", + "T88x_L2_READ_SNOOP", + "T88x_L2_READ_HIT", + "T88x_L2_CLEAN_MISS", + "T88x_L2_WRITE_LOOKUP", + "T88x_L2_SWRITE_LOOKUP", + "T88x_L2_WRITE_REPLAY", + "T88x_L2_WRITE_SNOOP", + "T88x_L2_WRITE_HIT", + "T88x_L2_EXT_READ_FULL", + "", + "T88x_L2_EXT_WRITE_FULL", + "T88x_L2_EXT_R_W_HAZARD", + "T88x_L2_EXT_READ", + "T88x_L2_EXT_READ_LINE", + "T88x_L2_EXT_WRITE", + "T88x_L2_EXT_WRITE_LINE", + "T88x_L2_EXT_WRITE_SMALL", + "T88x_L2_EXT_BARRIER", + "T88x_L2_EXT_AR_STALL", + "T88x_L2_EXT_R_BUF_FULL", + "T88x_L2_EXT_RD_BUF_FULL", + "T88x_L2_EXT_R_RAW", + "T88x_L2_EXT_W_STALL", + "T88x_L2_EXT_W_BUF_FULL", + "T88x_L2_EXT_R_BUF_FULL", + "T88x_L2_TAG_HAZARD", + "T88x_L2_SNOOP_FULL", + "T88x_L2_REPLAY_FULL"}; + +static const char *const hardware_counters_mali_tHEx[] = + { + /* Performance counters for the Job Manager */ + "", + "", + "", + "", + "THEx_MESSAGES_SENT", + "THEx_MESSAGES_RECEIVED", + "THEx_GPU_ACTIVE", + "THEx_IRQ_ACTIVE", + "THEx_JS0_JOBS", + "THEx_JS0_TASKS", + "THEx_JS0_ACTIVE", + "", + "THEx_JS0_WAIT_READ", + "THEx_JS0_WAIT_ISSUE", + "THEx_JS0_WAIT_DEPEND", + "THEx_JS0_WAIT_FINISH", + "THEx_JS1_JOBS", + "THEx_JS1_TASKS", + "THEx_JS1_ACTIVE", + "", + "THEx_JS1_WAIT_READ", + "THEx_JS1_WAIT_ISSUE", + "THEx_JS1_WAIT_DEPEND", + "THEx_JS1_WAIT_FINISH", + "THEx_JS2_JOBS", + "THEx_JS2_TASKS", + "THEx_JS2_ACTIVE", + "", + "THEx_JS2_WAIT_READ", + "THEx_JS2_WAIT_ISSUE", + "THEx_JS2_WAIT_DEPEND", + "THEx_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Performance counters for the Tiler */ + "", + "", + "", + "", + "THEx_TILER_ACTIVE", + "THEx_JOBS_PROCESSED", + "THEx_TRIANGLES", + "THEx_LINES", + "THEx_POINTS", + "THEx_FRONT_FACING", + "THEx_BACK_FACING", + "THEx_PRIM_VISIBLE", + "THEx_PRIM_CULLED", + "THEx_PRIM_CLIPPED", + "THEx_PRIM_SAT_CULLED", + "", + "", + "THEx_BUS_READ", + "", + "THEx_BUS_WRITE", + "THEx_LOADING_DESC", + "THEx_IDVS_POS_SHAD_REQ", + "THEx_IDVS_POS_SHAD_WAIT", + "THEx_IDVS_POS_SHAD_STALL", + "THEx_IDVS_POS_FIFO_FULL", + "THEx_PREFETCH_STALL", + "THEx_VCACHE_HIT", + "THEx_VCACHE_MISS", + "THEx_VCACHE_LINE_WAIT", + "THEx_VFETCH_POS_READ_WAIT", + "THEx_VFETCH_VERTEX_WAIT", + "THEx_VFETCH_STALL", + "THEx_PRIMASSY_STALL", + "THEx_BBOX_GEN_STALL", + "THEx_IDVS_VBU_HIT", + "THEx_IDVS_VBU_MISS", + "THEx_IDVS_VBU_LINE_DEALLOCATE", + "THEx_IDVS_VAR_SHAD_REQ", + "THEx_IDVS_VAR_SHAD_STALL", + "THEx_BINNER_STALL", + "THEx_ITER_STALL", + "THEx_COMPRESS_MISS", + "THEx_COMPRESS_STALL", + "THEx_PCACHE_HIT", + "THEx_PCACHE_MISS", + "THEx_PCACHE_MISS_STALL", + "THEx_PCACHE_EVICT_STALL", + "THEx_PMGR_PTR_WR_STALL", + "THEx_PMGR_PTR_RD_STALL", + "THEx_PMGR_CMD_WR_STALL", + "THEx_WRBUF_ACTIVE", + "THEx_WRBUF_HIT", + "THEx_WRBUF_MISS", + "THEx_WRBUF_NO_FREE_LINE_STALL", + "THEx_WRBUF_NO_AXI_ID_STALL", + "THEx_WRBUF_AXI_STALL", + "", + "", + "", + "THEx_UTLB_TRANS", + "THEx_UTLB_TRANS_HIT", + "THEx_UTLB_TRANS_STALL", + "THEx_UTLB_TRANS_MISS_DELAY", + "THEx_UTLB_MMU_REQ", + + /* Performance counters for the Shader Core */ + "", + "", + "", + "", + "THEx_FRAG_ACTIVE", + "THEx_FRAG_PRIMITIVES", + "THEx_FRAG_PRIM_RAST", + "THEx_FRAG_FPK_ACTIVE", + "THEx_FRAG_STARVING", + "THEx_FRAG_WARPS", + "THEx_FRAG_PARTIAL_WARPS", + "THEx_FRAG_QUADS_RAST", + "THEx_FRAG_QUADS_EZS_TEST", + "THEx_FRAG_QUADS_EZS_UPDATE", + "THEx_FRAG_QUADS_EZS_KILL", + "THEx_FRAG_LZS_TEST", + "THEx_FRAG_LZS_KILL", + "", + "THEx_FRAG_PTILES", + "THEx_FRAG_TRANS_ELIM", + "THEx_QUAD_FPK_KILLER", + "", + "THEx_COMPUTE_ACTIVE", + "THEx_COMPUTE_TASKS", + "THEx_COMPUTE_WARPS", + "THEx_COMPUTE_STARVING", + "THEx_EXEC_CORE_ACTIVE", + "THEx_EXEC_ACTIVE", + "THEx_EXEC_INSTR_COUNT", + "THEx_EXEC_INSTR_DIVERGED", + "THEx_EXEC_INSTR_STARVING", + "THEx_ARITH_INSTR_SINGLE_FMA", + "THEx_ARITH_INSTR_DOUBLE", + "THEx_ARITH_INSTR_MSG", + "THEx_ARITH_INSTR_MSG_ONLY", + "THEx_TEX_INSTR", + "THEx_TEX_INSTR_MIPMAP", + "THEx_TEX_INSTR_COMPRESSED", + "THEx_TEX_INSTR_3D", + "THEx_TEX_INSTR_TRILINEAR", + "THEx_TEX_COORD_ISSUE", + "THEx_TEX_COORD_STALL", + "THEx_TEX_STARVE_CACHE", + "THEx_TEX_STARVE_FILTER", + "THEx_LS_MEM_READ_FULL", + "THEx_LS_MEM_READ_SHORT", + "THEx_LS_MEM_WRITE_FULL", + "THEx_LS_MEM_WRITE_SHORT", + "THEx_LS_MEM_ATOMIC", + "THEx_VARY_INSTR", + "THEx_VARY_SLOT_32", + "THEx_VARY_SLOT_16", + "THEx_ATTR_INSTR", + "THEx_ARITH_INSTR_FP_MUL", + "THEx_BEATS_RD_FTC", + "THEx_BEATS_RD_FTC_EXT", + "THEx_BEATS_RD_LSC", + "THEx_BEATS_RD_LSC_EXT", + "THEx_BEATS_RD_TEX", + "THEx_BEATS_RD_TEX_EXT", + "THEx_BEATS_RD_OTHER", + "THEx_BEATS_WR_LSC", + "THEx_BEATS_WR_TIB", + "", + + /* Performance counters for the Memory System */ + "", + "", + "", + "", + "THEx_MMU_REQUESTS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "THEx_L2_RD_MSG_IN", + "THEx_L2_RD_MSG_IN_STALL", + "THEx_L2_WR_MSG_IN", + "THEx_L2_WR_MSG_IN_STALL", + "THEx_L2_SNP_MSG_IN", + "THEx_L2_SNP_MSG_IN_STALL", + "THEx_L2_RD_MSG_OUT", + "THEx_L2_RD_MSG_OUT_STALL", + "THEx_L2_WR_MSG_OUT", + "THEx_L2_ANY_LOOKUP", + "THEx_L2_READ_LOOKUP", + "THEx_L2_WRITE_LOOKUP", + "THEx_L2_EXT_SNOOP_LOOKUP", + "THEx_L2_EXT_READ", + "THEx_L2_EXT_READ_NOSNP", + "THEx_L2_EXT_READ_UNIQUE", + "THEx_L2_EXT_READ_BEATS", + "THEx_L2_EXT_AR_STALL", + "THEx_L2_EXT_AR_CNT_Q1", + "THEx_L2_EXT_AR_CNT_Q2", + "THEx_L2_EXT_AR_CNT_Q3", + "THEx_L2_EXT_RRESP_0_127", + "THEx_L2_EXT_RRESP_128_191", + "THEx_L2_EXT_RRESP_192_255", + "THEx_L2_EXT_RRESP_256_319", + "THEx_L2_EXT_RRESP_320_383", + "THEx_L2_EXT_WRITE", + "THEx_L2_EXT_WRITE_NOSNP_FULL", + "THEx_L2_EXT_WRITE_NOSNP_PTL", + "THEx_L2_EXT_WRITE_SNP_FULL", + "THEx_L2_EXT_WRITE_SNP_PTL", + "THEx_L2_EXT_WRITE_BEATS", + "THEx_L2_EXT_W_STALL", + "THEx_L2_EXT_AW_CNT_Q1", + "THEx_L2_EXT_AW_CNT_Q2", + "THEx_L2_EXT_AW_CNT_Q3", + "THEx_L2_EXT_SNOOP", + "THEx_L2_EXT_SNOOP_STALL", + "THEx_L2_EXT_SNOOP_RESP_CLEAN", + "THEx_L2_EXT_SNOOP_RESP_DATA", + "THEx_L2_EXT_SNOOP_INTERNAL", + "", + "", + "", + "", + "", + "", + ""}; + +static const char *const hardware_counters_mali_tMIx[] = + { + /* Performance counters for the Job Manager */ + "", + "", + "", + "", + "TMIx_MESSAGES_SENT", + "TMIx_MESSAGES_RECEIVED", + "TMIx_GPU_ACTIVE", + "TMIx_IRQ_ACTIVE", + "TMIx_JS0_JOBS", + "TMIx_JS0_TASKS", + "TMIx_JS0_ACTIVE", + "", + "TMIx_JS0_WAIT_READ", + "TMIx_JS0_WAIT_ISSUE", + "TMIx_JS0_WAIT_DEPEND", + "TMIx_JS0_WAIT_FINISH", + "TMIx_JS1_JOBS", + "TMIx_JS1_TASKS", + "TMIx_JS1_ACTIVE", + "", + "TMIx_JS1_WAIT_READ", + "TMIx_JS1_WAIT_ISSUE", + "TMIx_JS1_WAIT_DEPEND", + "TMIx_JS1_WAIT_FINISH", + "TMIx_JS2_JOBS", + "TMIx_JS2_TASKS", + "TMIx_JS2_ACTIVE", + "", + "TMIx_JS2_WAIT_READ", + "TMIx_JS2_WAIT_ISSUE", + "TMIx_JS2_WAIT_DEPEND", + "TMIx_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Performance counters for the Tiler */ + "", + "", + "", + "", + "TMIx_TILER_ACTIVE", + "TMIx_JOBS_PROCESSED", + "TMIx_TRIANGLES", + "TMIx_LINES", + "TMIx_POINTS", + "TMIx_FRONT_FACING", + "TMIx_BACK_FACING", + "TMIx_PRIM_VISIBLE", + "TMIx_PRIM_CULLED", + "TMIx_PRIM_CLIPPED", + "TMIx_PRIM_SAT_CULLED", + "", + "", + "TMIx_BUS_READ", + "", + "TMIx_BUS_WRITE", + "TMIx_LOADING_DESC", + "TMIx_IDVS_POS_SHAD_REQ", + "TMIx_IDVS_POS_SHAD_WAIT", + "TMIx_IDVS_POS_SHAD_STALL", + "TMIx_IDVS_POS_FIFO_FULL", + "TMIx_PREFETCH_STALL", + "TMIx_VCACHE_HIT", + "TMIx_VCACHE_MISS", + "TMIx_VCACHE_LINE_WAIT", + "TMIx_VFETCH_POS_READ_WAIT", + "TMIx_VFETCH_VERTEX_WAIT", + "TMIx_VFETCH_STALL", + "TMIx_PRIMASSY_STALL", + "TMIx_BBOX_GEN_STALL", + "TMIx_IDVS_VBU_HIT", + "TMIx_IDVS_VBU_MISS", + "TMIx_IDVS_VBU_LINE_DEALLOCATE", + "TMIx_IDVS_VAR_SHAD_REQ", + "TMIx_IDVS_VAR_SHAD_STALL", + "TMIx_BINNER_STALL", + "TMIx_ITER_STALL", + "TMIx_COMPRESS_MISS", + "TMIx_COMPRESS_STALL", + "TMIx_PCACHE_HIT", + "TMIx_PCACHE_MISS", + "TMIx_PCACHE_MISS_STALL", + "TMIx_PCACHE_EVICT_STALL", + "TMIx_PMGR_PTR_WR_STALL", + "TMIx_PMGR_PTR_RD_STALL", + "TMIx_PMGR_CMD_WR_STALL", + "TMIx_WRBUF_ACTIVE", + "TMIx_WRBUF_HIT", + "TMIx_WRBUF_MISS", + "TMIx_WRBUF_NO_FREE_LINE_STALL", + "TMIx_WRBUF_NO_AXI_ID_STALL", + "TMIx_WRBUF_AXI_STALL", + "", + "", + "", + "TMIx_UTLB_TRANS", + "TMIx_UTLB_TRANS_HIT", + "TMIx_UTLB_TRANS_STALL", + "TMIx_UTLB_TRANS_MISS_DELAY", + "TMIx_UTLB_MMU_REQ", + + /* Performance counters for the Shader Core */ + "", + "", + "", + "", + "TMIx_FRAG_ACTIVE", + "TMIx_FRAG_PRIMITIVES", + "TMIx_FRAG_PRIM_RAST", + "TMIx_FRAG_FPK_ACTIVE", + "TMIx_FRAG_STARVING", + "TMIx_FRAG_WARPS", + "TMIx_FRAG_PARTIAL_WARPS", + "TMIx_FRAG_QUADS_RAST", + "TMIx_FRAG_QUADS_EZS_TEST", + "TMIx_FRAG_QUADS_EZS_UPDATE", + "TMIx_FRAG_QUADS_EZS_KILL", + "TMIx_FRAG_LZS_TEST", + "TMIx_FRAG_LZS_KILL", + "", + "TMIx_FRAG_PTILES", + "TMIx_FRAG_TRANS_ELIM", + "TMIx_QUAD_FPK_KILLER", + "", + "TMIx_COMPUTE_ACTIVE", + "TMIx_COMPUTE_TASKS", + "TMIx_COMPUTE_WARPS", + "TMIx_COMPUTE_STARVING", + "TMIx_EXEC_CORE_ACTIVE", + "TMIx_EXEC_ACTIVE", + "TMIx_EXEC_INSTR_COUNT", + "TMIx_EXEC_INSTR_DIVERGED", + "TMIx_EXEC_INSTR_STARVING", + "TMIx_ARITH_INSTR_SINGLE_FMA", + "TMIx_ARITH_INSTR_DOUBLE", + "TMIx_ARITH_INSTR_MSG", + "TMIx_ARITH_INSTR_MSG_ONLY", + "TMIx_TEX_INSTR", + "TMIx_TEX_INSTR_MIPMAP", + "TMIx_TEX_INSTR_COMPRESSED", + "TMIx_TEX_INSTR_3D", + "TMIx_TEX_INSTR_TRILINEAR", + "TMIx_TEX_COORD_ISSUE", + "TMIx_TEX_COORD_STALL", + "TMIx_TEX_STARVE_CACHE", + "TMIx_TEX_STARVE_FILTER", + "TMIx_LS_MEM_READ_FULL", + "TMIx_LS_MEM_READ_SHORT", + "TMIx_LS_MEM_WRITE_FULL", + "TMIx_LS_MEM_WRITE_SHORT", + "TMIx_LS_MEM_ATOMIC", + "TMIx_VARY_INSTR", + "TMIx_VARY_SLOT_32", + "TMIx_VARY_SLOT_16", + "TMIx_ATTR_INSTR", + "TMIx_ARITH_INSTR_FP_MUL", + "TMIx_BEATS_RD_FTC", + "TMIx_BEATS_RD_FTC_EXT", + "TMIx_BEATS_RD_LSC", + "TMIx_BEATS_RD_LSC_EXT", + "TMIx_BEATS_RD_TEX", + "TMIx_BEATS_RD_TEX_EXT", + "TMIx_BEATS_RD_OTHER", + "TMIx_BEATS_WR_LSC", + "TMIx_BEATS_WR_TIB", + "", + + /* Performance counters for the Memory System */ + "", + "", + "", + "", + "TMIx_MMU_REQUESTS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "TMIx_L2_RD_MSG_IN", + "TMIx_L2_RD_MSG_IN_STALL", + "TMIx_L2_WR_MSG_IN", + "TMIx_L2_WR_MSG_IN_STALL", + "TMIx_L2_SNP_MSG_IN", + "TMIx_L2_SNP_MSG_IN_STALL", + "TMIx_L2_RD_MSG_OUT", + "TMIx_L2_RD_MSG_OUT_STALL", + "TMIx_L2_WR_MSG_OUT", + "TMIx_L2_ANY_LOOKUP", + "TMIx_L2_READ_LOOKUP", + "TMIx_L2_WRITE_LOOKUP", + "TMIx_L2_EXT_SNOOP_LOOKUP", + "TMIx_L2_EXT_READ", + "TMIx_L2_EXT_READ_NOSNP", + "TMIx_L2_EXT_READ_UNIQUE", + "TMIx_L2_EXT_READ_BEATS", + "TMIx_L2_EXT_AR_STALL", + "TMIx_L2_EXT_AR_CNT_Q1", + "TMIx_L2_EXT_AR_CNT_Q2", + "TMIx_L2_EXT_AR_CNT_Q3", + "TMIx_L2_EXT_RRESP_0_127", + "TMIx_L2_EXT_RRESP_128_191", + "TMIx_L2_EXT_RRESP_192_255", + "TMIx_L2_EXT_RRESP_256_319", + "TMIx_L2_EXT_RRESP_320_383", + "TMIx_L2_EXT_WRITE", + "TMIx_L2_EXT_WRITE_NOSNP_FULL", + "TMIx_L2_EXT_WRITE_NOSNP_PTL", + "TMIx_L2_EXT_WRITE_SNP_FULL", + "TMIx_L2_EXT_WRITE_SNP_PTL", + "TMIx_L2_EXT_WRITE_BEATS", + "TMIx_L2_EXT_W_STALL", + "TMIx_L2_EXT_AW_CNT_Q1", + "TMIx_L2_EXT_AW_CNT_Q2", + "TMIx_L2_EXT_AW_CNT_Q3", + "TMIx_L2_EXT_SNOOP", + "TMIx_L2_EXT_SNOOP_STALL", + "TMIx_L2_EXT_SNOOP_RESP_CLEAN", + "TMIx_L2_EXT_SNOOP_RESP_DATA", + "TMIx_L2_EXT_SNOOP_INTERNAL", + "", + "", + "", + "", + "", + "", + ""}; + +static const char *const hardware_counters_mali_tSIx[] = + { + /* Performance counters for the Job Manager */ + "", + "", + "", + "", + "TSIx_MESSAGES_SENT", + "TSIx_MESSAGES_RECEIVED", + "TSIx_GPU_ACTIVE", + "TSIx_IRQ_ACTIVE", + "TSIx_JS0_JOBS", + "TSIx_JS0_TASKS", + "TSIx_JS0_ACTIVE", + "", + "TSIx_JS0_WAIT_READ", + "TSIx_JS0_WAIT_ISSUE", + "TSIx_JS0_WAIT_DEPEND", + "TSIx_JS0_WAIT_FINISH", + "TSIx_JS1_JOBS", + "TSIx_JS1_TASKS", + "TSIx_JS1_ACTIVE", + "", + "TSIx_JS1_WAIT_READ", + "TSIx_JS1_WAIT_ISSUE", + "TSIx_JS1_WAIT_DEPEND", + "TSIx_JS1_WAIT_FINISH", + "TSIx_JS2_JOBS", + "TSIx_JS2_TASKS", + "TSIx_JS2_ACTIVE", + "", + "TSIx_JS2_WAIT_READ", + "TSIx_JS2_WAIT_ISSUE", + "TSIx_JS2_WAIT_DEPEND", + "TSIx_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Performance counters for the Tiler */ + "", + "", + "", + "", + "TSIx_TILER_ACTIVE", + "TSIx_JOBS_PROCESSED", + "TSIx_TRIANGLES", + "TSIx_LINES", + "TSIx_POINTS", + "TSIx_FRONT_FACING", + "TSIx_BACK_FACING", + "TSIx_PRIM_VISIBLE", + "TSIx_PRIM_CULLED", + "TSIx_PRIM_CLIPPED", + "TSIx_PRIM_SAT_CULLED", + "", + "", + "TSIx_BUS_READ", + "", + "TSIx_BUS_WRITE", + "TSIx_LOADING_DESC", + "", + "", + "", + "", + "TSIx_PREFETCH_STALL", + "TSIx_VCACHE_HIT", + "TSIx_VCACHE_MISS", + "TSIx_VCACHE_LINE_WAIT", + "TSIx_VFETCH_POS_READ_WAIT", + "TSIx_VFETCH_VERTEX_WAIT", + "TSIx_VFETCH_STALL", + "TSIx_PRIMASSY_STALL", + "TSIx_BBOX_GEN_STALL", + "", + "", + "", + "", + "", + "TSIx_BINNER_STALL", + "TSIx_ITER_STALL", + "TSIx_COMPRESS_MISS", + "TSIx_COMPRESS_STALL", + "TSIx_PCACHE_HIT", + "TSIx_PCACHE_MISS", + "TSIx_PCACHE_MISS_STALL", + "TSIx_PCACHE_EVICT_STALL", + "TSIx_PMGR_PTR_WR_STALL", + "TSIx_PMGR_PTR_RD_STALL", + "TSIx_PMGR_CMD_WR_STALL", + "TSIx_WRBUF_ACTIVE", + "TSIx_WRBUF_HIT", + "TSIx_WRBUF_MISS", + "TSIx_WRBUF_NO_FREE_LINE_STALL", + "TSIx_WRBUF_NO_AXI_ID_STALL", + "TSIx_WRBUF_AXI_STALL", + "", + "", + "", + "TSIx_UTLB_TRANS", + "TSIx_UTLB_TRANS_HIT", + "TSIx_UTLB_TRANS_STALL", + "TSIx_UTLB_TRANS_MISS_DELAY", + "TSIx_UTLB_MMU_REQ", + + /* Performance counters for the Shader Core */ + "", + "", + "", + "", + "TSIx_FRAG_ACTIVE", + "TSIx_FRAG_PRIMITIVES", + "TSIx_FRAG_PRIM_RAST", + "TSIx_FRAG_FPK_ACTIVE", + "TSIx_FRAG_STARVING", + "TSIx_FRAG_WARPS", + "TSIx_FRAG_PARTIAL_WARPS", + "TSIx_FRAG_QUADS_RAST", + "TSIx_FRAG_QUADS_EZS_TEST", + "TSIx_FRAG_QUADS_EZS_UPDATE", + "TSIx_FRAG_QUADS_EZS_KILL", + "TSIx_FRAG_LZS_TEST", + "TSIx_FRAG_LZS_KILL", + "", + "TSIx_FRAG_PTILES", + "TSIx_FRAG_TRANS_ELIM", + "TSIx_QUAD_FPK_KILLER", + "", + "TSIx_COMPUTE_ACTIVE", + "TSIx_COMPUTE_TASKS", + "TSIx_COMPUTE_WARPS", + "TSIx_COMPUTE_STARVING", + "TSIx_EXEC_CORE_ACTIVE", + "TSIx_EXEC_ACTIVE", + "TSIx_EXEC_INSTR_COUNT", + "TSIx_EXEC_INSTR_DIVERGED", + "TSIx_EXEC_INSTR_STARVING", + "TSIx_ARITH_INSTR_SINGLE_FMA", + "TSIx_ARITH_INSTR_DOUBLE", + "TSIx_ARITH_INSTR_MSG", + "TSIx_ARITH_INSTR_MSG_ONLY", + "TSIx_TEX_INSTR", + "TSIx_TEX_INSTR_MIPMAP", + "TSIx_TEX_INSTR_COMPRESSED", + "TSIx_TEX_INSTR_3D", + "TSIx_TEX_INSTR_TRILINEAR", + "TSIx_TEX_COORD_ISSUE", + "TSIx_TEX_COORD_STALL", + "TSIx_TEX_STARVE_CACHE", + "TSIx_TEX_STARVE_FILTER", + "TSIx_LS_MEM_READ_FULL", + "TSIx_LS_MEM_READ_SHORT", + "TSIx_LS_MEM_WRITE_FULL", + "TSIx_LS_MEM_WRITE_SHORT", + "TSIx_LS_MEM_ATOMIC", + "TSIx_VARY_INSTR", + "TSIx_VARY_SLOT_32", + "TSIx_VARY_SLOT_16", + "TSIx_ATTR_INSTR", + "TSIx_ARITH_INSTR_FP_MUL", + "TSIx_BEATS_RD_FTC", + "TSIx_BEATS_RD_FTC_EXT", + "TSIx_BEATS_RD_LSC", + "TSIx_BEATS_RD_LSC_EXT", + "TSIx_BEATS_RD_TEX", + "TSIx_BEATS_RD_TEX_EXT", + "TSIx_BEATS_RD_OTHER", + "TSIx_BEATS_WR_LSC", + "TSIx_BEATS_WR_TIB", + "", + + /* Performance counters for the Memory System */ + "", + "", + "", + "", + "TSIx_MMU_REQUESTS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "TSIx_L2_RD_MSG_IN", + "TSIx_L2_RD_MSG_IN_STALL", + "TSIx_L2_WR_MSG_IN", + "TSIx_L2_WR_MSG_IN_STALL", + "TSIx_L2_SNP_MSG_IN", + "TSIx_L2_SNP_MSG_IN_STALL", + "TSIx_L2_RD_MSG_OUT", + "TSIx_L2_RD_MSG_OUT_STALL", + "TSIx_L2_WR_MSG_OUT", + "TSIx_L2_ANY_LOOKUP", + "TSIx_L2_READ_LOOKUP", + "TSIx_L2_WRITE_LOOKUP", + "TSIx_L2_EXT_SNOOP_LOOKUP", + "TSIx_L2_EXT_READ", + "TSIx_L2_EXT_READ_NOSNP", + "TSIx_L2_EXT_READ_UNIQUE", + "TSIx_L2_EXT_READ_BEATS", + "TSIx_L2_EXT_AR_STALL", + "TSIx_L2_EXT_AR_CNT_Q1", + "TSIx_L2_EXT_AR_CNT_Q2", + "TSIx_L2_EXT_AR_CNT_Q3", + "TSIx_L2_EXT_RRESP_0_127", + "TSIx_L2_EXT_RRESP_128_191", + "TSIx_L2_EXT_RRESP_192_255", + "TSIx_L2_EXT_RRESP_256_319", + "TSIx_L2_EXT_RRESP_320_383", + "TSIx_L2_EXT_WRITE", + "TSIx_L2_EXT_WRITE_NOSNP_FULL", + "TSIx_L2_EXT_WRITE_NOSNP_PTL", + "TSIx_L2_EXT_WRITE_SNP_FULL", + "TSIx_L2_EXT_WRITE_SNP_PTL", + "TSIx_L2_EXT_WRITE_BEATS", + "TSIx_L2_EXT_W_STALL", + "TSIx_L2_EXT_AW_CNT_Q1", + "TSIx_L2_EXT_AW_CNT_Q2", + "TSIx_L2_EXT_AW_CNT_Q3", + "TSIx_L2_EXT_SNOOP", + "TSIx_L2_EXT_SNOOP_STALL", + "TSIx_L2_EXT_SNOOP_RESP_CLEAN", + "TSIx_L2_EXT_SNOOP_RESP_DATA", + "TSIx_L2_EXT_SNOOP_INTERNAL", + "", + "", + "", + "", + "", + "", + ""}; + +static const char *const hardware_counters_mali_tNOx[] = + { + /* Performance counters for the Job Manager */ + "", + "", + "", + "", + "TNOx_MESSAGES_SENT", + "TNOx_MESSAGES_RECEIVED", + "TNOx_GPU_ACTIVE", + "TNOx_IRQ_ACTIVE", + "TNOx_JS0_JOBS", + "TNOx_JS0_TASKS", + "TNOx_JS0_ACTIVE", + "", + "TNOx_JS0_WAIT_READ", + "TNOx_JS0_WAIT_ISSUE", + "TNOx_JS0_WAIT_DEPEND", + "TNOx_JS0_WAIT_FINISH", + "TNOx_JS1_JOBS", + "TNOx_JS1_TASKS", + "TNOx_JS1_ACTIVE", + "", + "TNOx_JS1_WAIT_READ", + "TNOx_JS1_WAIT_ISSUE", + "TNOx_JS1_WAIT_DEPEND", + "TNOx_JS1_WAIT_FINISH", + "TNOx_JS2_JOBS", + "TNOx_JS2_TASKS", + "TNOx_JS2_ACTIVE", + "", + "TNOx_JS2_WAIT_READ", + "TNOx_JS2_WAIT_ISSUE", + "TNOx_JS2_WAIT_DEPEND", + "TNOx_JS2_WAIT_FINISH", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + + /* Performance counters for the Tiler */ + "", + "", + "", + "", + "TNOx_TILER_ACTIVE", + "TNOx_JOBS_PROCESSED", + "TNOx_TRIANGLES", + "TNOx_LINES", + "TNOx_POINTS", + "TNOx_FRONT_FACING", + "TNOx_BACK_FACING", + "TNOx_PRIM_VISIBLE", + "TNOx_PRIM_CULLED", + "TNOx_PRIM_CLIPPED", + "TNOx_PRIM_SAT_CULLED", + "TNOx_BIN_ALLOC_INIT", + "TNOx_BIN_ALLOC_OVERFLOW", + "TNOx_BUS_READ", + "", + "TNOx_BUS_WRITE", + "TNOx_LOADING_DESC", + "TNOx_IDVS_POS_SHAD_REQ", + "TNOx_IDVS_POS_SHAD_WAIT", + "TNOx_IDVS_POS_SHAD_STALL", + "TNOx_IDVS_POS_FIFO_FULL", + "TNOx_PREFETCH_STALL", + "TNOx_VCACHE_HIT", + "TNOx_VCACHE_MISS", + "TNOx_VCACHE_LINE_WAIT", + "TNOx_VFETCH_POS_READ_WAIT", + "TNOx_VFETCH_VERTEX_WAIT", + "TNOx_VFETCH_STALL", + "TNOx_PRIMASSY_STALL", + "TNOx_BBOX_GEN_STALL", + "TNOx_IDVS_VBU_HIT", + "TNOx_IDVS_VBU_MISS", + "TNOx_IDVS_VBU_LINE_DEALLOCATE", + "TNOx_IDVS_VAR_SHAD_REQ", + "TNOx_IDVS_VAR_SHAD_STALL", + "TNOx_BINNER_STALL", + "TNOx_ITER_STALL", + "TNOx_COMPRESS_MISS", + "TNOx_COMPRESS_STALL", + "TNOx_PCACHE_HIT", + "TNOx_PCACHE_MISS", + "TNOx_PCACHE_MISS_STALL", + "TNOx_PCACHE_EVICT_STALL", + "TNOx_PMGR_PTR_WR_STALL", + "TNOx_PMGR_PTR_RD_STALL", + "TNOx_PMGR_CMD_WR_STALL", + "TNOx_WRBUF_ACTIVE", + "TNOx_WRBUF_HIT", + "TNOx_WRBUF_MISS", + "TNOx_WRBUF_NO_FREE_LINE_STALL", + "TNOx_WRBUF_NO_AXI_ID_STALL", + "TNOx_WRBUF_AXI_STALL", + "", + "", + "", + "TNOx_UTLB_TRANS", + "TNOx_UTLB_TRANS_HIT", + "TNOx_UTLB_TRANS_STALL", + "TNOx_UTLB_TRANS_MISS_DELAY", + "TNOx_UTLB_MMU_REQ", + + /* Performance counters for the Shader Core */ + "", + "", + "", + "", + "TNOx_FRAG_ACTIVE", + "TNOx_FRAG_PRIMITIVES", + "TNOx_FRAG_PRIM_RAST", + "TNOx_FRAG_FPK_ACTIVE", + "TNOx_FRAG_STARVING", + "TNOx_FRAG_WARPS", + "TNOx_FRAG_PARTIAL_WARPS", + "TNOx_FRAG_QUADS_RAST", + "TNOx_FRAG_QUADS_EZS_TEST", + "TNOx_FRAG_QUADS_EZS_UPDATE", + "TNOx_FRAG_QUADS_EZS_KILL", + "TNOx_FRAG_LZS_TEST", + "TNOx_FRAG_LZS_KILL", + "TNOx_WARP_REG_SIZE_64", + "TNOx_FRAG_PTILES", + "TNOx_FRAG_TRANS_ELIM", + "TNOx_QUAD_FPK_KILLER", + "TNOx_FULL_QUAD_WARPS", + "TNOx_COMPUTE_ACTIVE", + "TNOx_COMPUTE_TASKS", + "TNOx_COMPUTE_WARPS", + "TNOx_COMPUTE_STARVING", + "TNOx_EXEC_CORE_ACTIVE", + "TNOx_EXEC_ACTIVE", + "TNOx_EXEC_INSTR_COUNT", + "TNOx_EXEC_INSTR_DIVERGED", + "TNOx_EXEC_INSTR_STARVING", + "TNOx_ARITH_INSTR_SINGLE_FMA", + "TNOx_ARITH_INSTR_DOUBLE", + "TNOx_ARITH_INSTR_MSG", + "TNOx_ARITH_INSTR_MSG_ONLY", + "TNOx_TEX_MSGI_NUM_QUADS", + "TNOx_TEX_DFCH_NUM_PASSES", + "TNOx_TEX_DFCH_NUM_PASSES_MISS", + "TNOx_TEX_DFCH_NUM_PASSES_MIP_MAP", + "TNOx_TEX_TIDX_NUM_SPLIT_MIP_MAP", + "TNOx_TEX_TFCH_NUM_LINES_FETCHED", + "TNOx_TEX_TFCH_NUM_LINES_FETCHED_BLOCK", + "TNOx_TEX_TFCH_NUM_OPERATIONS", + "TNOx_TEX_FILT_NUM_OPERATIONS", + "TNOx_LS_MEM_READ_FULL", + "TNOx_LS_MEM_READ_SHORT", + "TNOx_LS_MEM_WRITE_FULL", + "TNOx_LS_MEM_WRITE_SHORT", + "TNOx_LS_MEM_ATOMIC", + "TNOx_VARY_INSTR", + "TNOx_VARY_SLOT_32", + "TNOx_VARY_SLOT_16", + "TNOx_ATTR_INSTR", + "TNOx_ARITH_INSTR_FP_MUL", + "TNOx_BEATS_RD_FTC", + "TNOx_BEATS_RD_FTC_EXT", + "TNOx_BEATS_RD_LSC", + "TNOx_BEATS_RD_LSC_EXT", + "TNOx_BEATS_RD_TEX", + "TNOx_BEATS_RD_TEX_EXT", + "TNOx_BEATS_RD_OTHER", + "TNOx_BEATS_WR_LSC_OTHER", + "TNOx_BEATS_WR_TIB", + "TNOx_BEATS_WR_LSC_WB", + + /* Performance counters for the Memory System */ + "", + "", + "", + "", + "TNOx_MMU_REQUESTS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "TNOx_L2_RD_MSG_IN", + "TNOx_L2_RD_MSG_IN_STALL", + "TNOx_L2_WR_MSG_IN", + "TNOx_L2_WR_MSG_IN_STALL", + "TNOx_L2_SNP_MSG_IN", + "TNOx_L2_SNP_MSG_IN_STALL", + "TNOx_L2_RD_MSG_OUT", + "TNOx_L2_RD_MSG_OUT_STALL", + "TNOx_L2_WR_MSG_OUT", + "TNOx_L2_ANY_LOOKUP", + "TNOx_L2_READ_LOOKUP", + "TNOx_L2_WRITE_LOOKUP", + "TNOx_L2_EXT_SNOOP_LOOKUP", + "TNOx_L2_EXT_READ", + "TNOx_L2_EXT_READ_NOSNP", + "TNOx_L2_EXT_READ_UNIQUE", + "TNOx_L2_EXT_READ_BEATS", + "TNOx_L2_EXT_AR_STALL", + "TNOx_L2_EXT_AR_CNT_Q1", + "TNOx_L2_EXT_AR_CNT_Q2", + "TNOx_L2_EXT_AR_CNT_Q3", + "TNOx_L2_EXT_RRESP_0_127", + "TNOx_L2_EXT_RRESP_128_191", + "TNOx_L2_EXT_RRESP_192_255", + "TNOx_L2_EXT_RRESP_256_319", + "TNOx_L2_EXT_RRESP_320_383", + "TNOx_L2_EXT_WRITE", + "TNOx_L2_EXT_WRITE_NOSNP_FULL", + "TNOx_L2_EXT_WRITE_NOSNP_PTL", + "TNOx_L2_EXT_WRITE_SNP_FULL", + "TNOx_L2_EXT_WRITE_SNP_PTL", + "TNOx_L2_EXT_WRITE_BEATS", + "TNOx_L2_EXT_W_STALL", + "TNOx_L2_EXT_AW_CNT_Q1", + "TNOx_L2_EXT_AW_CNT_Q2", + "TNOx_L2_EXT_AW_CNT_Q3", + "TNOx_L2_EXT_SNOOP", + "TNOx_L2_EXT_SNOOP_STALL", + "TNOx_L2_EXT_SNOOP_RESP_CLEAN", + "TNOx_L2_EXT_SNOOP_RESP_DATA", + "TNOx_L2_EXT_SNOOP_INTERNAL", + "", + "", + "", + "", + "", + "", + ""}; + +enum +{ + /* Product id masks for old and new versions of the id field. NB: the T60x must be tested before anything else as it could exceptionally be + * treated as a new style of id with product code 0x6006 */ + PRODUCT_ID_MASK_OLD = 0xffff, + PRODUCT_ID_MASK_NEW = 0xf00f, + /* Old style product ids */ + PRODUCT_ID_T60X = 0x6956, + PRODUCT_ID_T62X = 0x0620, + PRODUCT_ID_T72X = 0x0720, + PRODUCT_ID_T76X = 0x0750, + PRODUCT_ID_T82X = 0x0820, + PRODUCT_ID_T83X = 0x0830, + PRODUCT_ID_T86X = 0x0860, + PRODUCT_ID_TFRX = 0x0880, + /* New style product ids */ + PRODUCT_ID_TMIX = 0x6000, + PRODUCT_ID_THEX = 0x6001, + PRODUCT_ID_TSIX = 0x7000, + PRODUCT_ID_TNOX = 0x7001 +}; + +struct CounterMapping +{ + uint32_t product_mask; + uint32_t product_id; + const char *const *names_lut; +}; + +static const CounterMapping products[] = + { + { + PRODUCT_ID_MASK_OLD, + PRODUCT_ID_T60X, + hardware_counters_mali_t60x, + }, + { + PRODUCT_ID_MASK_OLD, + PRODUCT_ID_T62X, + hardware_counters_mali_t62x, + }, + { + PRODUCT_ID_MASK_OLD, + PRODUCT_ID_T72X, + hardware_counters_mali_t72x, + }, + { + PRODUCT_ID_MASK_OLD, + PRODUCT_ID_T76X, + hardware_counters_mali_t76x, + }, + { + PRODUCT_ID_MASK_OLD, + PRODUCT_ID_T82X, + hardware_counters_mali_t82x, + }, + { + PRODUCT_ID_MASK_OLD, + PRODUCT_ID_T83X, + hardware_counters_mali_t83x, + }, + { + PRODUCT_ID_MASK_OLD, + PRODUCT_ID_T86X, + hardware_counters_mali_t86x, + }, + { + PRODUCT_ID_MASK_OLD, + PRODUCT_ID_TFRX, + hardware_counters_mali_t88x, + }, + { + PRODUCT_ID_MASK_NEW, + PRODUCT_ID_TMIX, + hardware_counters_mali_tMIx, + }, + { + PRODUCT_ID_MASK_NEW, + PRODUCT_ID_THEX, + hardware_counters_mali_tHEx, + }, + { + PRODUCT_ID_MASK_NEW, + PRODUCT_ID_TSIX, + hardware_counters_mali_tSIx, + }, + { + PRODUCT_ID_MASK_NEW, + PRODUCT_ID_TNOX, + hardware_counters_mali_tNOx, + }, +}; + +enum +{ + NUM_PRODUCTS = sizeof(products) / sizeof(products[0]) +}; +} // namespace mali_userspace + +#endif /* DOXYGEN_SKIP_THIS */ diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.cpp b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.cpp new file mode 100644 index 0000000000..42b19ae711 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.cpp @@ -0,0 +1,614 @@ +/* + * Copyright (c) 2017-2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 "mali_profiler.h" + +#include "hwcpipe_log.h" + +#include + +using mali_userspace::MALI_NAME_BLOCK_JM; +using mali_userspace::MALI_NAME_BLOCK_MMU; +using mali_userspace::MALI_NAME_BLOCK_SHADER; +using mali_userspace::MALI_NAME_BLOCK_TILER; + +namespace hwcpipe +{ +namespace +{ +struct MaliHWInfo +{ + unsigned mp_count; + unsigned gpu_id; + unsigned r_value; + unsigned p_value; + unsigned core_mask; + unsigned l2_slices; +}; + +MaliHWInfo get_mali_hw_info(const char *path) +{ + int fd = open(path, O_RDWR); // NOLINT + + if (fd < 0) + { + throw std::runtime_error("Failed to get HW info."); + } + + { + mali_userspace::kbase_uk_hwcnt_reader_version_check_args version_check_args; + version_check_args.header.id = mali_userspace::UKP_FUNC_ID_CHECK_VERSION; // NOLINT + version_check_args.major = 10; + version_check_args.minor = 2; + + if (mali_userspace::mali_ioctl(fd, version_check_args) != 0) + { + mali_userspace::kbase_ioctl_version_check _version_check_args = {0, 0}; + if (ioctl(fd, KBASE_IOCTL_VERSION_CHECK, &_version_check_args) < 0) + { + close(fd); + throw std::runtime_error("Failed to check version."); + } + } + } + + { + mali_userspace::kbase_uk_hwcnt_reader_set_flags flags; // NOLINT + memset(&flags, 0, sizeof(flags)); + flags.header.id = mali_userspace::KBASE_FUNC_SET_FLAGS; // NOLINT + flags.create_flags = mali_userspace::BASE_CONTEXT_CREATE_KERNEL_FLAGS; + + if (mali_userspace::mali_ioctl(fd, flags) != 0) + { + mali_userspace::kbase_ioctl_set_flags _flags = {1u << 1}; + if (ioctl(fd, KBASE_IOCTL_SET_FLAGS, &_flags) < 0) + { + close(fd); + throw std::runtime_error("Failed settings flags ioctl."); + } + } + } + + { + MaliHWInfo hw_info; // NOLINT + memset(&hw_info, 0, sizeof(hw_info)); + mali_userspace::kbase_uk_gpuprops props = {}; + props.header.id = mali_userspace::KBASE_FUNC_GPU_PROPS_REG_DUMP; + if (mali_ioctl(fd, props) == 0) + { + hw_info.gpu_id = props.props.core_props.product_id; + hw_info.r_value = props.props.core_props.major_revision; + hw_info.p_value = props.props.core_props.minor_revision; + for (uint32_t i = 0; i < props.props.coherency_info.num_core_groups; i++) + hw_info.core_mask |= props.props.coherency_info.group[i].core_mask; + hw_info.mp_count = __builtin_popcountll(hw_info.core_mask); + hw_info.l2_slices = props.props.l2_props.num_l2_slices; + + close(fd); + } + else + { + mali_userspace::kbase_ioctl_get_gpuprops get_props = {}; + int ret; + if ((ret = ioctl(fd, KBASE_IOCTL_GET_GPUPROPS, &get_props)) < 0) + { + throw std::runtime_error("Failed getting GPU properties."); + close(fd); + } + + get_props.size = ret; + std::vector buffer(ret); + get_props.buffer.value = buffer.data(); + ret = ioctl(fd, KBASE_IOCTL_GET_GPUPROPS, &get_props); + if (ret < 0) + { + throw std::runtime_error("Failed getting GPU properties."); + close(fd); + } + +#define READ_U8(p) ((p)[0]) +#define READ_U16(p) (READ_U8((p)) | (uint16_t(READ_U8((p) + 1)) << 8)) +#define READ_U32(p) (READ_U16((p)) | (uint32_t(READ_U16((p) + 2)) << 16)) +#define READ_U64(p) (READ_U32((p)) | (uint64_t(READ_U32((p) + 4)) << 32)) + + mali_userspace::gpu_props props = {}; + + const auto *ptr = buffer.data(); + int size = ret; + while (size > 0) + { + uint32_t type = READ_U32(ptr); + uint32_t value_type = type & 3; + uint64_t value; + + ptr += 4; + size -= 4; + + switch (value_type) + { + case KBASE_GPUPROP_VALUE_SIZE_U8: + value = READ_U8(ptr); + ptr++; + size--; + break; + case KBASE_GPUPROP_VALUE_SIZE_U16: + value = READ_U16(ptr); + ptr += 2; + size -= 2; + break; + case KBASE_GPUPROP_VALUE_SIZE_U32: + value = READ_U32(ptr); + ptr += 4; + size -= 4; + break; + case KBASE_GPUPROP_VALUE_SIZE_U64: + value = READ_U64(ptr); + ptr += 8; + size -= 8; + break; + } + + for (unsigned i = 0; mali_userspace::gpu_property_mapping[i].type; i++) + { + if (mali_userspace::gpu_property_mapping[i].type == (type >> 2)) + { + auto offset = mali_userspace::gpu_property_mapping[i].offset; + void *p = reinterpret_cast(&props) + offset; + switch (mali_userspace::gpu_property_mapping[i].size) + { + case 1: + *reinterpret_cast(p) = value; + break; + case 2: + *reinterpret_cast(p) = value; + break; + case 4: + *reinterpret_cast(p) = value; + break; + case 8: + *reinterpret_cast(p) = value; + break; + default: + throw std::runtime_error("Invalid property size."); + close(fd); + } + break; + } + } + } + + hw_info.gpu_id = props.product_id; + hw_info.r_value = props.major_revision; + hw_info.p_value = props.minor_revision; + for (uint32_t i = 0; i < props.num_core_groups; i++) + hw_info.core_mask |= props.core_mask[i]; + hw_info.mp_count = __builtin_popcountll(hw_info.core_mask); + hw_info.l2_slices = props.l2_slices; + + close(fd); + } + + return hw_info; + } +} +} // namespace + +typedef std::function MaliValueGetter; + +MaliProfiler::MaliProfiler(const GpuCounterSet &enabled_counters) : + enabled_counters_(enabled_counters) +{ + // Throws if setup fails + init(); + + const std::unordered_map bifrost_mappings = { + {GpuCounter::GpuCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "GPU_ACTIVE"); }}, + {GpuCounter::VertexComputeCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS1_ACTIVE"); }}, + {GpuCounter::FragmentCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS0_ACTIVE"); }}, + {GpuCounter::TilerCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_TILER, "TILER_ACTIVE"); }}, + + {GpuCounter::VertexComputeJobs, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS1_JOBS"); }}, + {GpuCounter::FragmentJobs, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS0_JOBS"); }}, + {GpuCounter::Pixels, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS0_TASKS") * 1024; }}, + + {GpuCounter::Tiles, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_PTILES"); }}, + {GpuCounter::TransactionEliminations, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_TRANS_ELIM"); }}, + {GpuCounter::EarlyZTests, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_QUADS_EZS_TEST"); }}, + {GpuCounter::EarlyZKilled, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_QUADS_EZS_KILL"); }}, + {GpuCounter::LateZTests, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_LZS_TEST"); }}, + {GpuCounter::LateZKilled, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_LZS_KILL"); }}, + + {GpuCounter::Instructions, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "EXEC_INSTR_COUNT"); }}, + {GpuCounter::DivergedInstructions, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "EXEC_INSTR_DIVERGED"); }}, + + {GpuCounter::ShaderCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "EXEC_CORE_ACTIVE"); }}, + {GpuCounter::ShaderArithmeticCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "EXEC_INSTR_COUNT"); }}, + {GpuCounter::ShaderLoadStoreCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "LS_MEM_READ_FULL") + get_counter_value(MALI_NAME_BLOCK_SHADER, "LS_MEM_WRITE_FULL") + get_counter_value(MALI_NAME_BLOCK_SHADER, "LS_MEM_READ_SHORT") + get_counter_value(MALI_NAME_BLOCK_SHADER, "LS_MEM_WRITE_SHORT") + get_counter_value(MALI_NAME_BLOCK_SHADER, "LS_MEM_ATOMIC"); }}, + {GpuCounter::ShaderTextureCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "TEX_FILT_NUM_OPERATIONS"); }}, + + {GpuCounter::CacheReadLookups, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_READ_LOOKUP"); }}, + {GpuCounter::CacheWriteLookups, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_WRITE_LOOKUP"); }}, + {GpuCounter::ExternalMemoryReadAccesses, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_READ"); }}, + {GpuCounter::ExternalMemoryWriteAccesses, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_WRITE"); }}, + {GpuCounter::ExternalMemoryReadStalls, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_AR_STALL"); }}, + {GpuCounter::ExternalMemoryWriteStalls, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_W_STALL"); }}, + {GpuCounter::ExternalMemoryReadBytes, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_READ_BEATS") * 16; }}, + {GpuCounter::ExternalMemoryWriteBytes, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_WRITE_BEATS") * 16; }}, + }; + + const std::unordered_map midgard_mappings = { + {GpuCounter::GpuCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "GPU_ACTIVE"); }}, + {GpuCounter::VertexComputeCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS1_ACTIVE"); }}, + {GpuCounter::FragmentCycles, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS0_ACTIVE"); }}, + + {GpuCounter::VertexComputeJobs, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS1_JOBS"); }}, + {GpuCounter::FragmentJobs, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS0_JOBS"); }}, + {GpuCounter::Pixels, [this] { return get_counter_value(MALI_NAME_BLOCK_JM, "JS0_TASKS") * 1024; }}, + + {GpuCounter::Tiles, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_PTILES"); }}, + {GpuCounter::TransactionEliminations, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_TRANS_ELIM"); }}, + {GpuCounter::EarlyZTests, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_QUADS_EZS_TEST"); }}, + {GpuCounter::EarlyZKilled, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_QUADS_EZS_KILLED"); }}, + {GpuCounter::LateZTests, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_THREADS_LZS_TEST"); }}, + {GpuCounter::LateZKilled, [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "FRAG_THREADS_LZS_KILLED"); }}, + + {GpuCounter::CacheReadLookups, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_READ_LOOKUP"); }}, + {GpuCounter::CacheWriteLookups, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_WRITE_LOOKUP"); }}, + {GpuCounter::ExternalMemoryReadAccesses, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_READ"); }}, + {GpuCounter::ExternalMemoryWriteAccesses, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_WRITE"); }}, + {GpuCounter::ExternalMemoryReadStalls, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_AR_STALL"); }}, + {GpuCounter::ExternalMemoryWriteStalls, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_W_STALL"); }}, + {GpuCounter::ExternalMemoryReadBytes, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_READ_BEATS") * 16; }}, + {GpuCounter::ExternalMemoryWriteBytes, [this] { return get_counter_value(MALI_NAME_BLOCK_MMU, "L2_EXT_WRITE_BEATS") * 16; }}, + }; + + auto product = std::find_if(std::begin(mali_userspace::products), std::end(mali_userspace::products), [&](const mali_userspace::CounterMapping &cm) { + return (cm.product_mask & gpu_id_) == cm.product_id; + }); + + if (product != std::end(mali_userspace::products)) + { + switch (product->product_id) + { + case mali_userspace::PRODUCT_ID_T60X: + case mali_userspace::PRODUCT_ID_T62X: + case mali_userspace::PRODUCT_ID_T72X: + mappings_ = midgard_mappings; + mappings_[GpuCounter::Pixels] = [this]() { return get_counter_value(MALI_NAME_BLOCK_JM, "JS0_TASKS") * 256; }; + break; + case mali_userspace::PRODUCT_ID_T76X: + case mali_userspace::PRODUCT_ID_T82X: + case mali_userspace::PRODUCT_ID_T83X: + case mali_userspace::PRODUCT_ID_T86X: + case mali_userspace::PRODUCT_ID_TFRX: + mappings_ = midgard_mappings; + break; + case mali_userspace::PRODUCT_ID_TMIX: + case mali_userspace::PRODUCT_ID_THEX: + mappings_ = bifrost_mappings; + mappings_[GpuCounter::ShaderTextureCycles] = [this] { return get_counter_value(MALI_NAME_BLOCK_SHADER, "TEX_COORD_ISSUE"); }; + break; + case mali_userspace::PRODUCT_ID_TSIX: + case mali_userspace::PRODUCT_ID_TNOX: + default: + mappings_ = bifrost_mappings; + break; + } + } + else + { + HWCPIPE_LOG("Mali counters initialization failed: Failed to identify GPU"); + } +} + +void MaliProfiler::init() +{ + MaliHWInfo hw_info = get_mali_hw_info(device_); + + num_cores_ = hw_info.mp_count; + num_l2_slices_ = hw_info.l2_slices; + gpu_id_ = hw_info.gpu_id; + + fd_ = open(device_, O_RDWR | O_CLOEXEC | O_NONBLOCK); // NOLINT + + if (fd_ < 0) + { + throw std::runtime_error("Failed to open /dev/mali0."); + } + + { + mali_userspace::kbase_uk_hwcnt_reader_version_check_args check; // NOLINT + memset(&check, 0, sizeof(check)); + + if (mali_userspace::mali_ioctl(fd_, check) != 0) + { + mali_userspace::kbase_ioctl_version_check _check = {0, 0}; + if (ioctl(fd_, KBASE_IOCTL_VERSION_CHECK, &_check) < 0) + { + throw std::runtime_error("Failed to get ABI version."); + } + } + else if (check.major < 10) + { + throw std::runtime_error("Unsupported ABI version 10."); + } + } + + { + mali_userspace::kbase_uk_hwcnt_reader_set_flags flags; // NOLINT + memset(&flags, 0, sizeof(flags)); + flags.header.id = mali_userspace::KBASE_FUNC_SET_FLAGS; // NOLINT + flags.create_flags = mali_userspace::BASE_CONTEXT_CREATE_KERNEL_FLAGS; + + if (mali_userspace::mali_ioctl(fd_, flags) != 0) + { + mali_userspace::kbase_ioctl_set_flags _flags = {1u << 1}; + if (ioctl(fd_, KBASE_IOCTL_SET_FLAGS, &_flags) < 0) + { + throw std::runtime_error("Failed settings flags ioctl."); + } + } + } + + { + mali_userspace::kbase_uk_hwcnt_reader_setup setup; // NOLINT + memset(&setup, 0, sizeof(setup)); + setup.header.id = mali_userspace::KBASE_FUNC_HWCNT_READER_SETUP; // NOLINT + setup.buffer_count = buffer_count_; + setup.jm_bm = -1; + setup.shader_bm = -1; + setup.tiler_bm = -1; + setup.mmu_l2_bm = -1; + setup.fd = -1; + + if (mali_userspace::mali_ioctl(fd_, setup) != 0) + { + mali_userspace::kbase_ioctl_hwcnt_reader_setup _setup = {}; + _setup.buffer_count = buffer_count_; + _setup.jm_bm = -1; + _setup.shader_bm = -1; + _setup.tiler_bm = -1; + _setup.mmu_l2_bm = -1; + + int ret; + if ((ret = ioctl(fd_, KBASE_IOCTL_HWCNT_READER_SETUP, &_setup)) < 0) + { + throw std::runtime_error("Failed setting hwcnt reader ioctl."); + } + hwc_fd_ = ret; + } + else + { + hwc_fd_ = setup.fd; + } + } + + { + uint32_t api_version = ~mali_userspace::HWCNT_READER_API; + + if (ioctl(hwc_fd_, mali_userspace::KBASE_HWCNT_READER_GET_API_VERSION, &api_version) != 0) // NOLINT + { + throw std::runtime_error("Could not determine hwcnt reader API."); + } + else if (api_version != mali_userspace::HWCNT_READER_API) + { + throw std::runtime_error("Invalid API version."); + } + } + + if (ioctl(hwc_fd_, static_cast(mali_userspace::KBASE_HWCNT_READER_GET_BUFFER_SIZE), &buffer_size_) != 0) // NOLINT + { + throw std::runtime_error("Failed to get buffer size."); + } + + if (ioctl(hwc_fd_, static_cast(mali_userspace::KBASE_HWCNT_READER_GET_HWVER), &hw_ver_) != 0) // NOLINT + { + throw std::runtime_error("Could not determine HW version."); + } + + if (hw_ver_ < 5) + { + throw std::runtime_error("Unsupported HW version."); + } + + sample_data_ = static_cast(mmap(nullptr, buffer_count_ * buffer_size_, PROT_READ, MAP_PRIVATE, hwc_fd_, 0)); + + if (sample_data_ == MAP_FAILED) // NOLINT + { + throw std::runtime_error("Failed to map sample data."); + } + + auto product = std::find_if(std::begin(mali_userspace::products), std::end(mali_userspace::products), [&](const mali_userspace::CounterMapping &cm) { + return (cm.product_mask & hw_info.gpu_id) == cm.product_id; + }); + + if (product != std::end(mali_userspace::products)) + { + names_lut_ = product->names_lut; + } + else + { + throw std::runtime_error("Could not identify GPU."); + } + + raw_counter_buffer_.resize(buffer_size_ / sizeof(uint32_t)); + + // Build core remap table. + core_index_remap_.clear(); + core_index_remap_.reserve(hw_info.mp_count); + + unsigned int mask = hw_info.core_mask; + + while (mask != 0) + { + unsigned int bit = __builtin_ctz(mask); + core_index_remap_.push_back(bit); + mask &= ~(1u << bit); + } +} + +void MaliProfiler::run() +{ + sample_counters(); + wait_next_event(); +} + +void MaliProfiler::stop() +{ + // We don't need to do anything on stop() +} + +const GpuMeasurements &MaliProfiler::sample() +{ + sample_counters(); + wait_next_event(); + + for (const auto &counter : enabled_counters_) + { + auto mapping = mappings_.find(counter); + if (mapping == mappings_.end()) + { + continue; + } + + measurements_[mapping->first] = mapping->second(); + } + + return measurements_; +} + +void MaliProfiler::sample_counters() +{ + if (ioctl(hwc_fd_, mali_userspace::KBASE_HWCNT_READER_DUMP, 0) != 0) + { + throw std::runtime_error("Could not sample hardware counters."); + } +} + +void MaliProfiler::wait_next_event() +{ + pollfd poll_fd; // NOLINT + poll_fd.fd = hwc_fd_; + poll_fd.events = POLLIN; + + const int count = poll(&poll_fd, 1, -1); + + if (count < 0) + { + throw std::runtime_error("poll() failed."); + } + + if ((poll_fd.revents & POLLIN) != 0) + { + mali_userspace::kbase_hwcnt_reader_metadata meta; // NOLINT + + if (ioctl(hwc_fd_, static_cast(mali_userspace::KBASE_HWCNT_READER_GET_BUFFER), &meta) != 0) // NOLINT + { + throw std::runtime_error("Failed READER_GET_BUFFER."); + } + + memcpy(raw_counter_buffer_.data(), sample_data_ + buffer_size_ * meta.buffer_idx, buffer_size_); + timestamp_ = meta.timestamp; + + if (ioctl(hwc_fd_, mali_userspace::KBASE_HWCNT_READER_PUT_BUFFER, &meta) != 0) // NOLINT + { + throw std::runtime_error("Failed READER_PUT_BUFFER."); + } + } + else if ((poll_fd.revents & POLLHUP) != 0) + { + throw std::runtime_error("HWC hung up."); + } +} + +uint64_t MaliProfiler::get_counter_value(mali_userspace::MaliCounterBlockName block, const char *name) const +{ + uint64_t sum = 0; + switch (block) + { + case mali_userspace::MALI_NAME_BLOCK_MMU: + // If an MMU counter is selected, sum the values over MMU slices + for (int i = 0; i < num_l2_slices_; i++) + { + sum += get_counters(block, i)[find_counter_index_by_name(block, name)]; + } + return sum; + + case mali_userspace::MALI_NAME_BLOCK_SHADER: + // If a shader core counter is selected, sum the values over shader cores + for (int i = 0; i < num_cores_; i++) + { + sum += get_counters(block, i)[find_counter_index_by_name(block, name)]; + } + return sum; + + case mali_userspace::MALI_NAME_BLOCK_JM: + case mali_userspace::MALI_NAME_BLOCK_TILER: + default: + return static_cast(get_counters(block)[find_counter_index_by_name(block, name)]); + } +} + +const uint32_t *MaliProfiler::get_counters(mali_userspace::MaliCounterBlockName block, int index) const +{ + switch (block) + { + case mali_userspace::MALI_NAME_BLOCK_JM: + return raw_counter_buffer_.data() + mali_userspace::MALI_NAME_BLOCK_SIZE * 0; + case mali_userspace::MALI_NAME_BLOCK_MMU: + if (index < 0 || index >= num_l2_slices_) + { + throw std::runtime_error("Invalid slice number."); + } + + // If an MMU counter is selected, index refers to the MMU slice + return raw_counter_buffer_.data() + mali_userspace::MALI_NAME_BLOCK_SIZE * (2 + index); + case mali_userspace::MALI_NAME_BLOCK_TILER: + return raw_counter_buffer_.data() + mali_userspace::MALI_NAME_BLOCK_SIZE * 1; + default: + if (index < 0 || index >= num_cores_) + { + throw std::runtime_error("Invalid core number."); + } + + // If a shader core counter is selected, index refers to the core index + return raw_counter_buffer_.data() + mali_userspace::MALI_NAME_BLOCK_SIZE * (2 + num_l2_slices_ + core_index_remap_[index]); + } +} + +int MaliProfiler::find_counter_index_by_name(mali_userspace::MaliCounterBlockName block, const char *name) const +{ + const char *const *names = &names_lut_[mali_userspace::MALI_NAME_BLOCK_SIZE * block]; + + for (int i = 0; i < mali_userspace::MALI_NAME_BLOCK_SIZE; ++i) + { + if (strstr(names[i], name) != nullptr) + { + return i; + } + } + + return -1; +} + +} // namespace hwcpipe diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.h b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.h new file mode 100644 index 0000000000..49c48a3ec2 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/mali/mali_profiler.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 "gpu_profiler.h" + +#include "hwc.hpp" + +#include +#include + +namespace hwcpipe +{ +/** A Gpu profiler that uses Mali counter data. */ +class MaliProfiler : public GpuProfiler +{ + public: + explicit MaliProfiler(const GpuCounterSet &enabled_counters); + virtual ~MaliProfiler() = default; + + virtual const GpuCounterSet &enabled_counters() const override + { + return enabled_counters_; + } + + virtual const GpuCounterSet &supported_counters() const override + { + return supported_counters_; + }; + + virtual void set_enabled_counters(GpuCounterSet counters) override + { + enabled_counters_ = std::move(counters); + }; + + virtual void run() override; + virtual const GpuMeasurements &sample() override; + virtual void stop() override; + + private: + GpuCounterSet enabled_counters_{}; + + const GpuCounterSet supported_counters_{ + GpuCounter::GpuCycles, + GpuCounter::VertexComputeCycles, + GpuCounter::FragmentCycles, + GpuCounter::TilerCycles, + GpuCounter::VertexComputeJobs, + GpuCounter::Tiles, + GpuCounter::TransactionEliminations, + GpuCounter::FragmentJobs, + GpuCounter::Pixels, + GpuCounter::EarlyZTests, + GpuCounter::EarlyZKilled, + GpuCounter::LateZTests, + GpuCounter::LateZKilled, + GpuCounter::Instructions, + GpuCounter::DivergedInstructions, + GpuCounter::ShaderCycles, + GpuCounter::ShaderArithmeticCycles, + GpuCounter::ShaderLoadStoreCycles, + GpuCounter::ShaderTextureCycles, + GpuCounter::CacheReadLookups, + GpuCounter::CacheWriteLookups, + GpuCounter::ExternalMemoryReadAccesses, + GpuCounter::ExternalMemoryWriteAccesses, + GpuCounter::ExternalMemoryReadStalls, + GpuCounter::ExternalMemoryWriteStalls, + GpuCounter::ExternalMemoryReadBytes, + GpuCounter::ExternalMemoryWriteBytes, + }; + + typedef std::function MaliValueGetter; + std::unordered_map mappings_{}; + + const char *const device_{"/dev/mali0"}; + int num_cores_{0}; + int num_l2_slices_{0}; + int gpu_id_{0}; + uint32_t hw_ver_{0}; + int buffer_count_{16}; + size_t buffer_size_{0}; + uint8_t * sample_data_{nullptr}; + uint64_t timestamp_{0}; + const char *const *names_lut_{ + nullptr}; + std::vector raw_counter_buffer_{}; + std::vector core_index_remap_{}; + int fd_{-1}; + int hwc_fd_{-1}; + + GpuMeasurements measurements_{}; + + void init(); + void sample_counters(); + void wait_next_event(); + const uint32_t *get_counters(mali_userspace::MaliCounterBlockName block, int index = 0) const; + uint64_t get_counter_value(mali_userspace::MaliCounterBlockName block, const char *name) const; + int find_counter_index_by_name(mali_userspace::MaliCounterBlockName block, const char *name) const; +}; + +} // namespace hwcpipe diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.cpp b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.cpp new file mode 100644 index 0000000000..f32a3ddff1 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017-2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 "pmu_counter.h" + +#include +#include +#include +#include + +/* Add std_to_string implementation as it is possible that Android does not provide it */ +#include +#include + +template +std::string std_to_string(T value) +{ + std::ostringstream os ; + os << value ; + return os.str() ; +} + + +PmuCounter::PmuCounter() : + _perf_config() +{ + _perf_config.type = PERF_TYPE_HARDWARE; + _perf_config.size = sizeof(perf_event_attr); + + // Start disabled + _perf_config.disabled = 1; + // The inherit bit specifies that this counter should count events of child + // tasks as well as the task specified + _perf_config.inherit = 1; + // Enables saving of event counts on context switch for inherited tasks + _perf_config.inherit_stat = 1; +} + +PmuCounter::PmuCounter(uint64_t config) : + PmuCounter() +{ + open(config); +} + +PmuCounter::~PmuCounter() +{ + close(); +} + +void PmuCounter::open(uint64_t config) +{ + _perf_config.config = config; + open(_perf_config); +} + +void PmuCounter::open(const perf_event_attr &perf_config) +{ + // Measure this process/thread (+ children) on any CPU + _fd = syscall(__NR_perf_event_open, &perf_config, 0, -1, -1, 0); + + if (_fd < 0) + { + throw std::runtime_error("perf_event_open failed. Counter ID: " + config_to_str(_perf_config)); + } + + const int result = ioctl(_fd, PERF_EVENT_IOC_ENABLE, 0); + if (result == -1) + { + throw std::runtime_error("Failed to enable PMU counter: " + std::string(strerror(errno))); + } +} + +void PmuCounter::close() +{ + if (_fd != -1) + { + ::close(_fd); + _fd = -1; + } +} + +bool PmuCounter::reset() +{ + const int result = ioctl(_fd, PERF_EVENT_IOC_RESET, 0); + + if (result == -1) + { + throw std::runtime_error("Failed to reset PMU counter: " + std::string(std::strerror(errno))); + } + + return result != -1; +} + +std::string PmuCounter::config_to_str(const perf_event_attr &perf_config) +{ + switch (perf_config.type) + { + case PERF_TYPE_HARDWARE: + switch (perf_config.config) + { + case PERF_COUNT_HW_CPU_CYCLES: + return "PERF_COUNT_HW_CPU_CYCLES"; + case PERF_COUNT_HW_INSTRUCTIONS: + return "PERF_COUNT_HW_INSTRUCTIONS"; + case PERF_COUNT_HW_CACHE_REFERENCES: + return "PERF_COUNT_HW_CACHE_REFERENCES"; + case PERF_COUNT_HW_CACHE_MISSES: + return "PERF_COUNT_HW_CACHE_MISSES"; + case PERF_COUNT_HW_BRANCH_INSTRUCTIONS: + return "PERF_COUNT_HW_BRANCH_INSTRUCTIONS"; + case PERF_COUNT_HW_BRANCH_MISSES: + return "PERF_COUNT_HW_BRANCH_MISSES"; + case PERF_COUNT_HW_BUS_CYCLES: + return "PERF_COUNT_HW_BUS_CYCLES"; + case PERF_COUNT_HW_STALLED_CYCLES_FRONTEND: + return "PERF_COUNT_HW_STALLED_CYCLES_FRONTEND"; + case PERF_COUNT_HW_STALLED_CYCLES_BACKEND: + return "PERF_COUNT_HW_STALLED_CYCLES_BACKEND"; + case PERF_COUNT_HW_REF_CPU_CYCLES: + return "PERF_COUNT_HW_REF_CPU_CYCLES"; + default: + return "UNKNOWN HARDWARE COUNTER"; + } + + case PERF_TYPE_SOFTWARE: + switch (perf_config.config) + { + case PERF_COUNT_SW_CPU_CLOCK: + return "PERF_COUNT_SW_CPU_CLOCK"; + case PERF_COUNT_SW_TASK_CLOCK: + return "PERF_COUNT_SW_TASK_CLOCK"; + case PERF_COUNT_SW_PAGE_FAULTS: + return "PERF_COUNT_SW_PAGE_FAULTS"; + case PERF_COUNT_SW_CONTEXT_SWITCHES: + return "PERF_COUNT_SW_CONTEXT_SWITCHES"; + case PERF_COUNT_SW_CPU_MIGRATIONS: + return "PERF_COUNT_SW_CPU_MIGRATIONS"; + case PERF_COUNT_SW_PAGE_FAULTS_MIN: + return "PERF_COUNT_SW_PAGE_FAULTS_MIN"; + case PERF_COUNT_SW_PAGE_FAULTS_MAJ: + return "PERF_COUNT_SW_PAGE_FAULTS_MAJ"; + case PERF_COUNT_SW_ALIGNMENT_FAULTS: + return "PERF_COUNT_SW_ALIGNMENT_FAULTS"; + case PERF_COUNT_SW_EMULATION_FAULTS: + return "PERF_COUNT_SW_EMULATION_FAULTS"; + case PERF_COUNT_SW_DUMMY: + return "PERF_COUNT_SW_DUMMY"; + default: + return "UNKNOWN SOFTWARE COUNTER"; + } + default: + return std_to_string(perf_config.config); + } +} diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.h b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.h new file mode 100644 index 0000000000..183dcda3c6 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_counter.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017-2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hwcpipe_log.h" + +/** Class provides access to CPU hardware counters. */ +class PmuCounter +{ + public: + /** Default constructor. */ + PmuCounter(); + + /** Create PMU counter with specified config. + * + * This constructor automatically calls @ref open with the default + * configuration. + * + * @param[in] config Counter identifier. + */ + PmuCounter(uint64_t config); + + /** Default destructor. */ + ~PmuCounter(); + + /** Get the counter value. + * + * @return Counter value casted to the specified type. */ + template + T get_value() const; + + /** Open the specified counter based on the default configuration. + * + * @param[in] config The default configuration. + */ + void open(uint64_t config); + + /** Open the specified configuration. + * + * @param[in] perf_config The specified configuration. + */ + void open(const perf_event_attr &perf_config); + + /** Close the currently open counter. */ + void close(); + + /** Reset counter. + * + * @return false if reset fails. */ + bool reset(); + + /** Print counter config ID. */ + std::string config_to_str(const perf_event_attr &perf_config); + + private: + perf_event_attr _perf_config; + long _fd{-1}; +}; + +template +T PmuCounter::get_value() const +{ + long long value{}; + const ssize_t result = read(_fd, &value, sizeof(long long)); + + if (result == -1) + { + throw std::runtime_error("Can't get PMU counter value: " + std::string(std::strerror(errno))); + } + + return static_cast(value); +} diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.cpp b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.cpp new file mode 100644 index 0000000000..d6af31b1e4 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017-2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 "pmu_profiler.h" + +#include "hwcpipe_log.h" + +namespace hwcpipe +{ +const std::unordered_map pmu_mappings{ + {CpuCounter::Cycles, PERF_COUNT_HW_CPU_CYCLES}, + {CpuCounter::Instructions, PERF_COUNT_HW_INSTRUCTIONS}, + {CpuCounter::CacheReferences, PERF_COUNT_HW_CACHE_REFERENCES}, + {CpuCounter::CacheMisses, PERF_COUNT_HW_CACHE_MISSES}, + {CpuCounter::BranchInstructions, PERF_COUNT_HW_BRANCH_INSTRUCTIONS}, + {CpuCounter::BranchMisses, PERF_COUNT_HW_BRANCH_MISSES}, +}; + +PmuProfiler::PmuProfiler(const CpuCounterSet &enabled_counters) : + enabled_counters_(enabled_counters) +{ + // Set up PMU counters + for (const auto &counter : enabled_counters) + { + const auto &pmu_config = pmu_mappings.find(counter); + if (pmu_config != pmu_mappings.end()) + { + try + { + // Create a PMU counter with the specified configuration + auto pmu_counter_res = pmu_counters_.emplace(counter, pmu_config->second); + + // Try reading a value from the counter to check that it opened correctly + auto &pmu_counter = pmu_counter_res.first->second; + pmu_counter.get_value(); + + // PMU counter is created and can retrieve values + available_counters_.insert(counter); + } + catch (const std::runtime_error &e) + { + // PMU counter initialization failed + HWCPIPE_LOG("%s", e.what()); + } + } + } + + if (available_counters_.size() == 0) + { + throw std::runtime_error("PMU counters not available."); + } +} + +void PmuProfiler::run() +{ + for (auto &pmu_counter : pmu_counters_) + { + pmu_counter.second.reset(); + prev_measurements_[pmu_counter.first] = Value{}; + } +} + +const CpuMeasurements &PmuProfiler::sample() +{ + for (const auto &counter : enabled_counters_) + { + const auto &pmu_counter = pmu_counters_.find(counter); + if (pmu_counter == pmu_counters_.end()) + { + continue; + } + + try + { + auto value = pmu_counter->second.get_value(); + + // Resetting the PMU counter every frame seems to alter the data, + // so we make a differential reading. + measurements_[pmu_counter->first] = value - prev_measurements_[pmu_counter->first].get(); + prev_measurements_[pmu_counter->first] = value; + } + catch (const std::runtime_error &e) + { + HWCPIPE_LOG("Failed to get value from PMU: %s.", e.what()); + } + } + + return measurements_; +} + +void PmuProfiler::stop() +{ + // We don't need to do anything on stop() +} + +} // namespace hwcpipe diff --git a/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.h b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.h new file mode 100644 index 0000000000..7cfe8b37b1 --- /dev/null +++ b/renderdoc/driver/ihv/arm/official/lizard/thirdparty/hwcpipe/vendor/arm/pmu/pmu_profiler.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * 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 "cpu_profiler.h" + +#include "pmu_counter.h" + +namespace hwcpipe +{ +/** A CPU profiler that uses PMU counter data. */ +class PmuProfiler : public CpuProfiler +{ + public: + explicit PmuProfiler(const CpuCounterSet &enabled_counters); + virtual ~PmuProfiler() = default; + + virtual const CpuCounterSet &enabled_counters() const override + { + return enabled_counters_; + } + + virtual const CpuCounterSet &supported_counters() const override + { + return supported_counters_; + }; + + virtual void set_enabled_counters(CpuCounterSet counters) override + { + enabled_counters_ = std::move(counters); + }; + + virtual void run() override; + virtual const CpuMeasurements &sample() override; + virtual void stop() override; + + private: + CpuCounterSet enabled_counters_{}; + CpuCounterSet available_counters_{}; + + const CpuCounterSet supported_counters_{ + CpuCounter::Cycles, + CpuCounter::Instructions, + CpuCounter::CacheReferences, + CpuCounter::CacheMisses, + CpuCounter::BranchInstructions, + CpuCounter::BranchMisses}; + + CpuMeasurements measurements_{}; + CpuMeasurements prev_measurements_{}; + + std::unordered_map pmu_counters_{}; +}; + +} // namespace hwcpipe diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index 8382b81fd4..2158628123 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -677,6 +677,9 @@ {5de5a561-548a-4dd7-90f0-06a2b39eae9a} + + {F9CCE6CA-0CA3-4A22-9C7B-881369955E62} + {7fcb5fc5-1dbd-4da6-83a0-6ba4e945bda5}