void DCGPAProfiler::MapCounterNames(CounterList& selectedCounters) { for (CounterList::iterator it = selectedCounters.begin(); it != selectedCounters.end(); ++it) { string str = *it; if (str.compare("FetchUnitBusy") == 0) { *it = "TexUnitBusy"; } else if (str.compare("FetchUnitStalled") == 0) { *it = "TexUnitStalled"; } else if (str.compare("WriteUnitStalled") == 0) { *it = "PSExportStalls"; } else if (str.compare("FetchSize") == 0) { *it = "TexMemBytesRead"; } else { *it = CS_COUNTER_NAME_PREFIX + *it; } } }
virtual void on_reload() { if (hQuery_ != NULL) return; PDH::PDHError status = PDH::PDHFactory::get_impl()->PdhOpenQuery( NULL, 0, &hQuery_ ); if (status.is_error()) throw pdh_exception("PdhOpenQuery failed", status); for (CounterList::iterator it = counters_.begin(); it != counters_.end(); it++) { (*it)->addToQuery(getQueryHandle()); } }
virtual void on_unload() { if (hQuery_ == NULL) return; for (CounterList::iterator it = counters_.begin(); it != counters_.end(); it++) { (*it)->remove(); } PDH::PDHError status = PDH::PDHFactory::get_impl()->PdhCloseQuery(hQuery_); if (status.is_error()) throw pdh_exception("PdhCloseQuery failed", status); hQuery_ = NULL; }
void close() { if (hQuery_ == NULL) throw pdh_exception("query is null!"); PDH::PDHFactory::get_impl()->remove_listener(this); on_unload(); counters_.clear(); }
void gatherData() { collect(); for (CounterList::iterator it = counters_.begin(); it != counters_.end(); it++) { PDH::PDHError status = (*it)->collect(); if (status.is_negative_denominator()) { Sleep(500); collect(); status = (*it)->collect(); } if (status.is_negative_denominator()) { if (!hasDisplayedInvalidCOunter_) { hasDisplayedInvalidCOunter_ = true; throw pdh_exception((*it)->getName(), "Negative denominator issue (check FAQ for ways to solve this): ", status); } } else if (status.is_error()) { throw pdh_exception((*it)->getName(), "Failed to poll counter", status); } } }
// helper function void PrintCounters(CounterList& counterList, const string& strGenerationName, const std::string& outputFile) { const unsigned int nLineBreak = 5; unsigned int curItem = 0; bool shouldWriteToFile = !outputFile.empty(); std::ofstream fout; if (shouldWriteToFile) { fout.open(outputFile.c_str()); if (!fout.is_open()) { cout << "Unable to open " << outputFile << std::endl; return; } } else { cout << "The list of valid counters for " << strGenerationName << " based graphics cards:\n"; } for (CounterList::iterator it = counterList.begin(); it != counterList.end(); ++it) { if (shouldWriteToFile) { fout << *it << std::endl; } else { cout << *it; if (*it != counterList.back()) { cout << ", "; } // line break if (curItem && (curItem + 1) % nLineBreak == 0) { cout << endl; curItem = 0; } else { curItem++; } } } if (shouldWriteToFile) { fout.close(); cout << "Counters written to " << outputFile << std::endl; } else { cout << endl << endl; } }
bool DCGPAProfiler::GetAllComputeCounters(CounterList& counterList) { bool retVal = true; // Loading dxgi.dll has a side effect of initializing Real_CreateDXGIFactory1 LIB_HANDLE hDxgiDll = OSUtils::Instance()->GenericLoadLibrary("dxgi.dll"); if (NULL == hDxgiDll) { retVal = false; } else { if (NULL == Real_CreateDXGIFactory1) { retVal = false; } else { // Make sure this isn't called from DllMain (or a detoured LoadLibrary call) // See this note on MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/bb205075%28v=vs.85%29.aspx#DXGI_Responses_From_DLLMain // DXGI Responses from DLLMain // Because a DllMain function can't guarantee the order in which it loads and unloads DLLs, we recommend that your app's DllMain function not call // Direct3D or DXGI functions or methods, including functions or methods that create or release objects.If your app's DllMain function calls into a // particular component, that component might call another DLL that isn't present on the operating system, which causes the operating system to crash. // Direct3D and DXGI might load a set of DLLs, typically a set of drivers, that differs from computer to computer. Therefore, even if your app doesn’t // crash on your development and test computers when its DllMain function calls Direct3D or DXGI functions or methods, it might crash when it runs on // another computer. // // To prevent you from creating an app that might cause the operating system to crash, DXGI provides the following responses in the specified situations : // If your app's DllMain function releases its last reference to a DXGI factory, DXGI raises an exception. // If your app's DllMain function creates a DXGI factory, DXGI returns an error code. IDXGIFactory* pDxgiFactory = NULL; HRESULT hr = Real_CreateDXGIFactory1(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pDxgiFactory)); if (S_OK != hr) { retVal = false; } else { typedef std::unordered_set<CounterList::value_type> CounterNames; CounterNames counterNames; CounterList adapterCounters; UINT adapterIndex = 0; while (retVal && (S_OK == hr)) { IDXGIAdapter* pDxgiAdapter = NULL; hr = pDxgiFactory->EnumAdapters(adapterIndex, &pDxgiAdapter); if (S_OK == hr) { DXGI_ADAPTER_DESC adapterDesc; hr = pDxgiAdapter->GetDesc(&adapterDesc); if (S_OK == hr) { GDT_HW_GENERATION hwGen; bool hwGenFound = AMDTDeviceInfoUtils::Instance()->GetHardwareGeneration(adapterDesc.DeviceId, hwGen); if (hwGenFound) { adapterCounters.clear(); m_GPAUtils.GetAvailableCountersGdt(hwGen, adapterCounters); m_GPAUtils.FilterNonComputeCountersGdt(hwGen, adapterCounters); for (CounterList::iterator aci = adapterCounters.begin() ; adapterCounters.end() != aci; ++aci) { if (counterNames.end() == counterNames.find(*aci)) { counterNames.insert(*aci); } } } } pDxgiAdapter->Release(); } ++adapterIndex; } // DXGI_ERROR_NOT_FOUND marks that EnumAdapters reached the last adapter in the system if (DXGI_ERROR_NOT_FOUND != hr) { retVal = false; } else { for (CounterNames::iterator cni = counterNames.begin() ; counterNames.end() != cni ; ++cni) { counterList.push_back(*cni); } } pDxgiFactory->Release(); } } } return retVal; }
void DCGPAProfiler::DumpHeader() { // Header should only be dumped once if (m_bDoneHeadings) { return; } KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("ProfileFileVersion=%d.%d", GPUPROFILER_BACKEND_MAJOR_VERSION, GPUPROFILER_BACKEND_MINOR_VERSION)); KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("ProfilerVersion=%d.%d.%d", GPUPROFILER_BACKEND_MAJOR_VERSION, GPUPROFILER_BACKEND_MINOR_VERSION, GPUPROFILER_BACKEND_BUILD_NUMBER)); KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("API=DirectCompute")); KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("Application=%s", FileUtils::GetExeFullPath().c_str())); KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("ApplicationArgs=%s", m_profilerParams.m_strCmdArgs.asUTF8CharArray())); KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("WorkingDirectory=%s", m_profilerParams.m_strWorkingDir.asUTF8CharArray())); EnvVarMap envVarMap = GlobalSettings::GetInstance()->m_params.m_mapEnvVars; if (!envVarMap.empty()) { KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("FullEnvironment=%d", GlobalSettings::GetInstance()->m_params.m_bFullEnvBlock)); for (EnvVarMap::const_iterator it = envVarMap.begin(); it != envVarMap.end(); ++it) { KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("EnvVar=%s=%s", it->first.asUTF8CharArray(), it->second.asUTF8CharArray())); } } KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("OS Version=%s", OSUtils::Instance()->GetOSInfo().c_str())); KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("DisplayName=%s", GlobalSettings::GetInstance()->m_params.m_strSessionName.c_str())); KernelProfileResultManager::Instance()->AddHeader(StringUtils::FormatString("ListSeparator=%c", m_profilerParams.m_cOutputSeparator)); SP_TODO("Currently, DumpHeader only works if counters are enabled in GPA, consider switching to offline mode like CL/HSA Profiler"); CounterList selectedCounters; m_GPAUtils.GetEnabledCounterNames(selectedCounters); KernelProfileResultManager::Instance()->AddProfileResultItem("Identifier"); KernelProfileResultManager::Instance()->AddProfileResultItem("ExecutionOrder"); KernelProfileResultManager::Instance()->AddProfileResultItem("ThreadGroup"); KernelProfileResultManager::Instance()->AddProfileResultItem("WorkGroupSize"); // 2014/06/18 // Comment out data transfer size column to make DirectCokmpute output compatible with OpenCL output. // Leaving commented out to make it easy to revert this change. //KernelProfileResultManager::Instance()->AddProfileResultItem("DataTransferSize"); // lazy initialization of the enabled counter list std::string counterName; if (IsGpuTimeEnabled()) // Always add the GPU time unless it's disabled { m_enabledCounters.push_back(GPU_TIME_COUNTER_NAME); counterName = GPU_TIME_COUNTER_NAME; UnmapCounterName(CS_COUNTER_NAME_PREFIX, counterName); KernelProfileResultManager::Instance()->AddProfileResultItem(counterName); } for (CounterList::iterator counterIter = selectedCounters.begin(); counterIter != selectedCounters.end(); ++counterIter) { counterName = *counterIter; if (GPU_TIME_COUNTER_NAME != counterName) // time is handled seperately above { m_enabledCounters.push_back(counterName); UnmapCounterName(CS_COUNTER_NAME_PREFIX, counterName); KernelProfileResultManager::Instance()->AddProfileResultItem(counterName); } } m_GPAUtils.SetEnabledCounters(m_enabledCounters); m_bDoneHeadings = true; }
void removeAllCounters() { if (hQuery_) close(); counters_.clear(); }
counter_ptr addCounter(std::wstring name) { counter_ptr counter = counter_ptr(new PDHCounter(name)); counters_.push_back(counter); return counter; }