void GPA_CounterGeneratorDX11Base::ComputeSWCounterValue(gpa_uint32 softwareCounterIndex, gpa_uint64 value, void* pResult, const GPA_HWInfo* pHwInfo) const { gpa_uint32 numAMDCounters = GetNumAMDCounters(); if (softwareCounterIndex >= numAMDCounters) { softwareCounterIndex -= numAMDCounters; //adjust index for AMD counters } const SwCounterDescVec* pSwCounters = SwCounterManager::Instance()->GetSwCounters(); if (softwareCounterIndex < static_cast<gpa_uint32>(pSwCounters->size())) { const std::string nvGPUTime = "GPUTime"; const std::string d3dGPUTime = "D3DGPUTime"; const std::string counterName = pSwCounters->at(softwareCounterIndex).m_name; if (counterName == d3dGPUTime || counterName == nvGPUTime) { gpa_uint64 freq = 1u; GPA_ASSERT(pHwInfo->GetTimeStampFrequency(freq)); gpa_float64* pBuf = static_cast<gpa_float64*>(pResult); *pBuf = static_cast<gpa_float64>(value) / static_cast<gpa_float64>(freq) * 1000.0; } else // other SW DX counters { GPA_Data_Type type = (*pSwCounters)[softwareCounterIndex].m_type; if (GPA_DATA_TYPE_UINT64 == type) { gpa_uint64* pBuf = static_cast<gpa_uint64*>(pResult); *pBuf = static_cast<gpa_uint64>(value); } else if (GPA_DATA_TYPE_FLOAT64 == type) { memcpy(pResult, &value, sizeof(gpa_float64)); } else { GPA_LogError("Unexpected software counter type."); } } } }
bool VkUtils::GetTimestampFrequency(VkPhysicalDevice vkPhysicalDevice, gpa_uint64& timestampFrequency) { bool success = false; if (s_isEntryPointsInitialized) { VkPhysicalDeviceProperties properties; _vkGetPhysicalDeviceProperties(vkPhysicalDevice, &properties); // Vulkan's timestampPeriod is expressed in nanoseconds per clock tick, convert to frequency in seconds float timestampPeriod = properties.limits.timestampPeriod; timestampFrequency = static_cast<gpa_uint64>(1000000000.0f / (timestampPeriod)); success = true; } else { GPA_LogError("Vulkan entrypoints are not initialized."); } return success; }
GPA_SessionId CLGPAContext::CreateSession(GPA_Session_Sample_Type sampleType) { GPA_SessionId pRetSessionId = nullptr; CLGPASession* pNewGpaCLGpaSession = new(std::nothrow) CLGPASession(this, sampleType); if (nullptr == pNewGpaCLGpaSession) { GPA_LogError("Unable to allocate memory for the session."); } else { AddGpaSession(pNewGpaCLGpaSession); if (nullptr != pNewGpaCLGpaSession) { pRetSessionId = reinterpret_cast<GPA_SessionId>(GPAUniqueObjectManager::Instance()->CreateObject(pNewGpaCLGpaSession)); } } return pRetSessionId; }
GPA_Status GPAImplementor::OpenContext(void* pContext, GPA_OpenContextFlags flags, GPA_ContextId* pContextId) { // validate that only a single clock mode is specified unsigned int numClockModes = 0; if (GPA_OPENCONTEXT_CLOCK_MODE_NONE_BIT & flags) { numClockModes++; } if (GPA_OPENCONTEXT_CLOCK_MODE_PEAK_BIT & flags) { numClockModes++; } if (GPA_OPENCONTEXT_CLOCK_MODE_MIN_MEMORY_BIT & flags) { numClockModes++; } if (GPA_OPENCONTEXT_CLOCK_MODE_MIN_ENGINE_BIT & flags) { numClockModes++; } if (1 < numClockModes) { GPA_LogError("More than one clock mode specified."); return GPA_STATUS_ERROR_INVALID_PARAMETER; } GPA_Status gpaStatus = GPA_STATUS_OK; std::lock_guard<std::mutex> lock(m_deviceGpaContextMapMutex); if (!DoesContextInfoExist(pContext)) { GPA_HWInfo hwInfo; if (GPA_STATUS_OK == IsDeviceSupported(pContext, &hwInfo)) { IGPAContext* pNewGPAContext = nullptr; pNewGPAContext = OpenAPIContext(pContext, hwInfo, flags); if (nullptr != pNewGPAContext) { *pContextId = reinterpret_cast<GPA_ContextId>(GPAUniqueObjectManager::Instance()->CreateObject(pNewGPAContext)); m_appContextInfoGpaContextMap.insert(GPADeviceIdentifierGPAContextPair(GetDeviceIdentifierFromContextInfo(pContext), pNewGPAContext)); } else { GPA_LogError("Failed to open API-specific GPA Context."); gpaStatus = GPA_STATUS_ERROR_FAILED; } } else { GPA_LogError("Device not supported."); gpaStatus = GPA_STATUS_ERROR_HARDWARE_NOT_SUPPORTED; } } else { GPA_LogError("Context is already open."); gpaStatus = GPA_STATUS_ERROR_CONTEXT_ALREADY_OPEN; } return gpaStatus; }
GPA_Status GPAImplementor::IsDeviceSupported(GPAContextInfoPtr pContextInfo, GPA_HWInfo* pHwInfo) const { bool foundMatchingHWInfo = false; AsicInfoList asicInfoList; GPA_HWInfo apiHwInfo; if (!GetHwInfoFromAPI(pContextInfo, apiHwInfo)) { GPA_LogError("Unable to get hardware information from the API."); return GPA_STATUS_ERROR_FAILED; } if (apiHwInfo.IsAMD()) { AMDTADLUtils::Instance()->GetAsicInfoList(asicInfoList); GPA_HWInfo asicHwInfo; // make sure there are available asics for AMD card. // In case there is no AMD driver, we output a message. if (asicInfoList.empty()) { GPA_LogMessage("Cannot get asicInfoList from ADL."); } for (auto asicInfo : asicInfoList) { asicHwInfo.SetVendorID(asicInfo.vendorID); asicHwInfo.SetDeviceName(asicInfo.adapterName.c_str()); asicHwInfo.SetDeviceID(asicInfo.deviceID); asicHwInfo.SetRevisionID(asicInfo.revID); asicHwInfo.SetGpuIndex(asicInfo.gpuIndex); asicHwInfo.UpdateDeviceInfoBasedOnDeviceID(); if (CompareHwInfo(apiHwInfo, asicHwInfo)) { gpa_uint32 apiRevId = 0; // make sure revision id is set correctly based on the actual hardware if (apiHwInfo.GetRevisionID(apiRevId) && REVISION_ID_ANY == apiRevId) { apiHwInfo.SetRevisionID(asicInfo.revID); } apiHwInfo.UpdateDeviceInfoBasedOnDeviceID(); // this device matches what the application is running on, so break from the loop. foundMatchingHWInfo = true; break; } } } #if defined(WIN32) if (!foundMatchingHWInfo) // ADL will not be available on a clean system that has never had the AMD driver installed { Adapter adapter; asicInfoList.clear(); if (adapter.getAsicInfoList(asicInfoList)) { for (auto asicInfo : asicInfoList) { GPA_HWInfo asicHwInfo; asicHwInfo.SetVendorID(asicInfo.vendorID); asicHwInfo.SetDeviceName(asicInfo.adapterName.c_str()); asicHwInfo.SetDeviceID(asicInfo.deviceID); asicHwInfo.SetRevisionID(asicInfo.revID); if (NVIDIA_VENDOR_ID == asicInfo.vendorID) { asicHwInfo.SetHWGeneration(GDT_HW_GENERATION_NVIDIA); } else if (INTEL_VENDOR_ID == asicInfo.vendorID) { asicHwInfo.SetHWGeneration(GDT_HW_GENERATION_INTEL); } else { // this call makes sure the hw generation is set correctly asicHwInfo.UpdateDeviceInfoBasedOnDeviceID(); } if (CompareHwInfo(apiHwInfo, asicHwInfo)) { gpa_uint32 apiRevId = 0; // make sure revision id is set correctly based on the actual hardware if (apiHwInfo.GetRevisionID(apiRevId) && REVISION_ID_ANY == apiRevId) { apiHwInfo.SetRevisionID(asicInfo.revID); } apiHwInfo.UpdateDeviceInfoBasedOnDeviceID(); // this device matches what the application is running on, so break from the loop. foundMatchingHWInfo = true; break; } } } else { GPA_LogMessage("Unable to get asic info from the Adapter."); } } #endif // WIN32 if (!foundMatchingHWInfo) { // This code path is for systems where ADL is not available. ADL is not available on ROCm systems as well as on amdgpu systems. // API specific hardware information mostly gets basic information (namely just needs to get VendorID and DeviceID), so we need to update // the device info with additional information that we store per-deviceID. bool deviceInfoOk = apiHwInfo.UpdateDeviceInfoBasedOnDeviceID(); if (!deviceInfoOk) { // If this fails, then the hardware must not be supported because we don't know enough about it GPA_LogError("Cannot update device information."); return GPA_STATUS_ERROR_HARDWARE_NOT_SUPPORTED; } } // Give the API-specific implementation a chance to verify that the hardware is supported. GPA_Status status = VerifyAPIHwSupport(pContextInfo, apiHwInfo) ? GPA_STATUS_OK : GPA_STATUS_ERROR_FAILED; if (GPA_STATUS_OK == status) { *pHwInfo = apiHwInfo; } return status; }
GPASampleResult* DX12GPASample::PopulateSampleResult() { size_t sampleDataBytes = 0u; // Validate result space sampleDataBytes = GetSampleResultLocation()->GetBufferBytes(); if (0 != sampleDataBytes) { if (nullptr != GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()) { gpa_uint64* pResultBuffer = nullptr; gpa_uint64 timingData[2] = {}; if (GetPass()->IsTimingPass()) { pResultBuffer = timingData; sampleDataBytes = sizeof(timingData); } else { pResultBuffer = GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer(); } if (CopyResult(sampleDataBytes, pResultBuffer)) { if (GetPass()->IsTimingPass()) { const GPA_HardwareCounters* pHardwareCounters = GetPass()->GetSessionContextCounterAccessor()->GetHardwareCounters(); for (CounterCount i = 0; i < GetPass()->GetEnabledCounterCount(); ++i) { CounterIndex counterIndex; GetPass()->GetCounterByIndexInPass(i, &counterIndex); if (counterIndex == pHardwareCounters->m_gpuTimeBottomToBottomDurationCounterIndex) { GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()[i] = timingData[1] - timingData[0]; } else if (counterIndex == pHardwareCounters->m_gpuTimeBottomToBottomStartCounterIndex) { GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()[i] = timingData[0]; } else if (counterIndex == pHardwareCounters->m_gpuTimeBottomToBottomEndCounterIndex) { GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()[i] = timingData[1]; } else if (counterIndex == pHardwareCounters->m_gpuTimeTopToBottomDurationCounterIndex) { GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()[i] = timingData[1] - timingData[0]; } else if (counterIndex == pHardwareCounters->m_gpuTimeTopToBottomStartCounterIndex) { GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()[i] = timingData[0]; } else if (counterIndex == pHardwareCounters->m_gpuTimeTopToBottomEndCounterIndex) { GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()[i] = timingData[1]; } else { GPA_LogError("Unknown timing counter."); GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()[i] = 0; } } } if (IsSampleContinuing()) { GPASampleResult* pSampleResult = reinterpret_cast<DX12GPASample*>(GetContinuingSample())->PopulateSampleResult(); for (size_t counterIter = 0; counterIter < GetPass()->GetEnabledCounterCount(); counterIter++) { GetSampleResultLocation()->GetAsCounterSampleResult()->GetResultBuffer()[counterIter] += pSampleResult->GetAsCounterSampleResult()->GetResultBuffer()[counterIter]; } } MarkAsCompleted(); } else { GPA_LogError("Unable to get the result from the driver."); } } else { GPA_LogError("Incorrect space allocated for sample result."); } } return GetSampleResultLocation(); }
bool DX12GPASample::CopyResult(size_t sampleDataSize, void* pResultBuffer) const { bool isDataReady = false; bool isAnyHardwareCounterEnabled = GetPass()->GetEnabledCounterCount() > 0; if (nullptr != pResultBuffer) { if (isAnyHardwareCounterEnabled) { DX12GPACommandList* pDX12GpaCmdList = reinterpret_cast<DX12GPACommandList*>(GetCmdList()); IAmdExtGpaSession* pResultSession = nullptr; if (IsCopied()) { pResultSession = pDX12GpaCmdList->GetBundleResultAmdExtSession(GetClientSampleId()); } else { pResultSession = pDX12GpaCmdList->GetAmdExtSession(); } if (nullptr == pResultSession) { GPA_LogError("Invalid profiling session encountered while copying results."); } else { if (pResultSession->IsReady()) { size_t sampleDataSizeInDriver = 0u; HRESULT driverResult = pResultSession->GetResults(GetDriverSampleId(), &sampleDataSizeInDriver, nullptr); assert(SUCCEEDED(driverResult)); assert(sampleDataSize == sampleDataSizeInDriver); if (SUCCEEDED(driverResult) && sampleDataSize == sampleDataSizeInDriver) { driverResult = pResultSession->GetResults(GetDriverSampleId(), &sampleDataSizeInDriver, pResultBuffer); assert(SUCCEEDED(driverResult)); if (SUCCEEDED(driverResult)) { isDataReady = true; } else { GPA_LogError("Error occurred while getting sample results from driver."); } } else { GPA_LogError("Error occurred while getting sample result size from driver."); } } } } else { // there is no hardware counter enabled in the driver, put zeros in all result location memcpy(pResultBuffer, 0, sampleDataSize); isDataReady = true; } } return isDataReady; }
//========================================================================================================= bool GetASICInfo(ASICInfo& rASICInfo) { if (nullptr == oglUtils::_oglGetPerfMonitorCountersAMD || nullptr == oglUtils::_oglGetPerfMonitorGroupStringAMD || nullptr == oglUtils::_oglGetPerfMonitorCounterInfoAMD || nullptr == oglUtils::_oglGetPerfMonitorCounterStringAMD || nullptr == oglUtils::_oglGenPerfMonitorsAMD || nullptr == oglUtils::_oglDeletePerfMonitorsAMD || nullptr == oglUtils::_oglSelectPerfMonitorCountersAMD || nullptr == oglUtils::_oglBeginPerfMonitorAMD || nullptr == oglUtils::_oglEndPerfMonitorAMD || nullptr == oglUtils::_oglGetPerfMonitorCounterDataAMD) { // No AMD_peformance_monitor support, means no ASIC info GPA_LogError("One or more of the GL_AMD_performance_monitor functions were not found."); return false; } // Find the ASIC info group (GPIN = GPu INformation) GLint nASICGroupId = GetGroupID(ASIC_GROUP); if (nASICGroupId == -1) { GPA_LogError("Unable to find the GPIN group."); return false; } // Get the ASIC ID GLuint nAsicType = 0; if (!GetCounterValue(nASICGroupId, ASIC_TYPE, nAsicType)) { GPA_LogError("Unable to get the asic id."); return false; } // query the driver version so that we can correct the asic ID after a driver // change that happened for 10.2, where support for pre-R6xx hardware was removed //(legacy driver will support that) #ifndef GLES // Since GL ES didn't exist before version 9551, there's no need to check the // version number. For now, it is assumed the version number will be >9551 const GLubyte* pVersion = oglUtils::_oglGetString(GL_VERSION); int nVersion = extractVersionNumber(pVersion); std::stringstream message; message << "ASIC ID returned from driver is: " << nAsicType << " and GL_VERSION is: " << reinterpret_cast<const char*>(pVersion) << "."; GPA_LogMessage(message.str().c_str()); #else int nVersion = INT_MAX; #endif if (nVersion < 13452) { // pre-GCN devices were removed from the driver starting with version 13452. // if the driver version is earlier than that we will return an error. GPA_LogError("OpenGL driver version is too old. Please update your driver."); return false; } // store the Asic Revision ID rASICInfo.eAsicRev = (ATIAsicID) nAsicType; // Decode the ASIC Type if (nAsicType == ATIASIC_ID_TAHITI_P || nAsicType == ATIASIC_ID_PITCAIRN_PM || nAsicType == ATIASIC_ID_CAPEVERDE_M || nAsicType == ATIASIC_ID_OLAND_M || nAsicType == ATIASIC_ID_HAINAN_M) { GPA_LogMessage("Recognized a GFX6 card."); rASICInfo.eAsicType = ASIC_Gfx6; } else if (nAsicType == ATIASIC_ID_BONAIRE_M || nAsicType == ATIASIC_ID_HAWAII_P) { GPA_LogMessage("Recognized a GFX7 card."); rASICInfo.eAsicType = ASIC_Gfx7; } else if (nAsicType == ATIASIC_ID_KALINDI || nAsicType == ATIASIC_ID_GODAVARI || nAsicType == ATIASIC_ID_SPECTRE || nAsicType == ATIASIC_ID_SPOOKY) { GPA_LogMessage("Recognized an APU with GFX7 graphics."); rASICInfo.eAsicType = ASIC_Gfx7; } else if (nAsicType == ATIASIC_ID_ICELAND_M || nAsicType == ATIASIC_ID_TONGA_P || nAsicType == ATIASIC_ID_FIJI_P || nAsicType == ATIASIC_ID_ELLESMERE || nAsicType == ATIASIC_ID_BAFFIN || nAsicType == ATIASIC_ID_LEXA || nAsicType == ATIASIC_ID_VEGAM) { GPA_LogMessage("Recognized a GFX8 card."); rASICInfo.eAsicType = ASIC_Gfx8; } else if (nAsicType == ATIASIC_ID_CARRIZO || nAsicType == ATIASIC_ID_STONEY) { GPA_LogMessage("Recognized an APU with GFX8 graphics."); rASICInfo.eAsicType = ASIC_Gfx8; } else if (nAsicType == ATIASIC_ID_GFX900 || nAsicType == ATIASIC_ID_PLACEHOLDER1 || nAsicType == ATIASIC_ID_GFX906) { GPA_LogMessage("Recognized a GFX9 card."); rASICInfo.eAsicType = ASIC_Gfx9; } else if (nAsicType == ATIASIC_ID_GFX902 || nAsicType == ATIASIC_ID_PLACEHOLDER) { GPA_LogMessage("Recognized an APU with GFX9 graphics."); rASICInfo.eAsicType = ASIC_Gfx9; } else { std::stringstream errorMessage; errorMessage << "Unrecognized asic type: " << nAsicType << "."; GPA_LogError(errorMessage.str().c_str()); assert(0); // Unknown ASIC Type, need to update enums list from UGL driver rASICInfo.eAsicType = ASIC_UNKNOWN; return false; } // Now, fill in the rest of the ASIC structure switch (rASICInfo.eAsicType) { case ASIC_Gfx6: case ASIC_Gfx7: case ASIC_Gfx8: case ASIC_Gfx9: if (!GetCounterValue(nASICGroupId, "GPIN_001", rASICInfo.nNumSIMD)) { GPA_LogError("Unable to query GPIN_001."); return false; } if (!GetCounterValue(nASICGroupId, "GPIN_002", rASICInfo.nNumQuadPipe)) { GPA_LogError("Unable to query GPIN_002."); return false; } if (!GetCounterValue(nASICGroupId, "GPIN_003", rASICInfo.nNumRB)) { GPA_LogError("Unable to query GPIN_003."); return false; } if (!GetCounterValue(nASICGroupId, "GPIN_004", rASICInfo.nNumSPI)) { GPA_LogError("Unable to query GPIN_004."); return false; } break; default: break; } return true; }
GPA_Status GPA_CounterGeneratorDX12::GenerateHardwareCounters( GDT_HW_GENERATION desiredGeneration, GDT_HW_ASIC_TYPE asicType, gpa_uint8 generateAsicSpecificCounters, GPA_HardwareCounters* pHardwareCounters) { UNREFERENCED_PARAMETER(asicType); UNREFERENCED_PARAMETER(generateAsicSpecificCounters); GPA_Status status = GPA_STATUS_OK; if (nullptr == pHardwareCounters) { status = GPA_STATUS_ERROR_NULL_POINTER; } else { pHardwareCounters->Clear(); if (true == pHardwareCounters->m_countersGenerated) //only generate counters once to improve performance { return GPA_STATUS_OK; } pHardwareCounters->Clear(); if (desiredGeneration == GDT_HW_GENERATION_SEAISLAND) { pHardwareCounters->m_ppCounterGroupArray = DX12CounterGroupArrayGfx7; pHardwareCounters->m_pGroups = HWDX12GroupsGfx7; pHardwareCounters->m_groupCount = HWDX12GroupCountGfx7; pHardwareCounters->m_pSQCounterGroups = HWDX12SQGroupsGfx7; pHardwareCounters->m_sqGroupCount = HWDX12SQGroupCountGfx7; pHardwareCounters->m_timestampBlockIds = HWDX12TimestampBlockIdsGfx7; pHardwareCounters->m_timeCounterIndices = HWDX12TimeCounterIndicesGfx7; pHardwareCounters->m_gpuTimeBottomToBottomDurationCounterIndex = HWDX12GputimeBottomToBottomDurationIndexGfx7; pHardwareCounters->m_gpuTimeBottomToBottomStartCounterIndex = HWDX12GputimeBottomToBottomStartIndexGfx7; pHardwareCounters->m_gpuTimeBottomToBottomEndCounterIndex = HWDX12GputimeBottomToBottomEndIndexGfx7; pHardwareCounters->m_gpuTimeTopToBottomDurationCounterIndex = HWDX12GputimeTopToBottomDurationIndexGfx7; pHardwareCounters->m_gpuTimeTopToBottomStartCounterIndex = HWDX12GputimeTopToBottomStartIndexGfx7; pHardwareCounters->m_gpuTimeTopToBottomEndCounterIndex = HWDX12GputimeTopToBottomEndIndexGfx7; pHardwareCounters->m_pIsolatedGroups = HWDX12SQIsolatedGroupsGfx7; pHardwareCounters->m_isolatedGroupCount = HWDX12SQIsolatedGroupCountGfx7; } else if (desiredGeneration == GDT_HW_GENERATION_VOLCANICISLAND) { pHardwareCounters->m_ppCounterGroupArray = DX12CounterGroupArrayGfx8; pHardwareCounters->m_pGroups = HWDX12GroupsGfx8; pHardwareCounters->m_groupCount = HWDX12GroupCountGfx8; pHardwareCounters->m_pSQCounterGroups = HWDX12SQGroupsGfx8; pHardwareCounters->m_sqGroupCount = HWDX12SQGroupCountGfx8; pHardwareCounters->m_timestampBlockIds = HWDX12TimestampBlockIdsGfx8; pHardwareCounters->m_timeCounterIndices = HWDX12TimeCounterIndicesGfx8; pHardwareCounters->m_gpuTimeBottomToBottomDurationCounterIndex = HWDX12GputimeBottomToBottomDurationIndexGfx8; pHardwareCounters->m_gpuTimeBottomToBottomStartCounterIndex = HWDX12GputimeBottomToBottomStartIndexGfx8; pHardwareCounters->m_gpuTimeBottomToBottomEndCounterIndex = HWDX12GputimeBottomToBottomEndIndexGfx8; pHardwareCounters->m_gpuTimeTopToBottomDurationCounterIndex = HWDX12GputimeTopToBottomDurationIndexGfx8; pHardwareCounters->m_gpuTimeTopToBottomStartCounterIndex = HWDX12GputimeTopToBottomStartIndexGfx8; pHardwareCounters->m_gpuTimeTopToBottomEndCounterIndex = HWDX12GputimeTopToBottomEndIndexGfx8; pHardwareCounters->m_pIsolatedGroups = HWDX12SQIsolatedGroupsGfx8; pHardwareCounters->m_isolatedGroupCount = HWDX12SQIsolatedGroupCountGfx8; } else if (desiredGeneration == GDT_HW_GENERATION_GFX9) { pHardwareCounters->m_ppCounterGroupArray = DX12CounterGroupArrayGfx9; pHardwareCounters->m_pGroups = HWDX12GroupsGfx9; pHardwareCounters->m_groupCount = HWDX12GroupCountGfx9; pHardwareCounters->m_pSQCounterGroups = HWDX12SQGroupsGfx9; pHardwareCounters->m_sqGroupCount = HWDX12SQGroupCountGfx9; pHardwareCounters->m_timestampBlockIds = HWDX12TimestampBlockIdsGfx9; pHardwareCounters->m_timeCounterIndices = HWDX12TimeCounterIndicesGfx9; pHardwareCounters->m_gpuTimeBottomToBottomDurationCounterIndex = HWDX12GputimeBottomToBottomDurationIndexGfx9; pHardwareCounters->m_gpuTimeBottomToBottomStartCounterIndex = HWDX12GputimeBottomToBottomStartIndexGfx9; pHardwareCounters->m_gpuTimeBottomToBottomEndCounterIndex = HWDX12GputimeBottomToBottomEndIndexGfx9; pHardwareCounters->m_gpuTimeTopToBottomDurationCounterIndex = HWDX12GputimeTopToBottomDurationIndexGfx9; pHardwareCounters->m_gpuTimeTopToBottomStartCounterIndex = HWDX12GputimeTopToBottomStartIndexGfx9; pHardwareCounters->m_gpuTimeTopToBottomEndCounterIndex = HWDX12GputimeTopToBottomEndIndexGfx9; pHardwareCounters->m_pIsolatedGroups = HWDX12SQIsolatedGroupsGfx9; pHardwareCounters->m_isolatedGroupCount = HWDX12SQIsolatedGroupCountGfx9; } else { GPA_LogError("Unrecognized or unhandled hardware generation."); return GPA_STATUS_ERROR_HARDWARE_NOT_SUPPORTED; } } // need to count total number of internal counters, since split into groups if (!pHardwareCounters->m_countersGenerated) { if (!GenerateInternalCounters(pHardwareCounters, desiredGeneration)) { GPA_LogError("Unable to generate internal counters."); pHardwareCounters->m_currentGroupUsedCounts.resize(0); return GPA_STATUS_ERROR_CONTEXT_NOT_OPEN; } } unsigned int uGroupCount = pHardwareCounters->m_groupCount; pHardwareCounters->m_currentGroupUsedCounts.resize(uGroupCount); return status; }
GPA_Status GPA_IMP_OpenContext(void* pContext) { GPA_Status result = GPA_STATUS_OK; if (nullptr == pContext) { GPA_LogError("Unable to open context. Parameter 'pContext' is NULL."); result = GPA_STATUS_ERROR_NULL_POINTER; } else { IUnknown* pUnknown = static_cast<IUnknown*>(pContext); ID3D12GraphicsCommandList* pCommandList = nullptr; HRESULT hr = pUnknown->QueryInterface(__uuidof(ID3D12GraphicsCommandList), reinterpret_cast<void**>(&pCommandList)); if (S_OK != hr) { GPA_LogError("Failed to get command list from context"); result = GPA_STATUS_ERROR_FAILED; } else { bool setCommandList = GetCurrentContext()->SetCommandList(pCommandList); if (!setCommandList) { result = GPA_STATUS_ERROR_FAILED; } if (GPA_STATUS_OK == result) { gpa_uint32 vendorId = 0; gpa_uint32 deviceId = 0; gpa_uint32 revisionId = 0; if (false == (g_pCurrentContext->m_hwInfo.GetVendorID(vendorId))) { result = GPA_STATUS_ERROR_FAILED; } else if (false == (g_pCurrentContext->m_hwInfo.GetDeviceID(deviceId))) { result = GPA_STATUS_ERROR_FAILED; } else if (false == (g_pCurrentContext->m_hwInfo.GetRevisionID(revisionId))) { result = GPA_STATUS_ERROR_FAILED; } if (GPA_STATUS_OK == result) { GPA_ICounterAccessor* pCounterAccessor = nullptr; GPA_ICounterScheduler* pCounterScheduler = nullptr; result = GenerateCounters( GPA_API_DIRECTX_12, vendorId, deviceId, revisionId, &pCounterAccessor, &pCounterScheduler); if (GPA_STATUS_OK == result) { g_pCurrentContext->m_pCounterAccessor = static_cast<GPA_CounterGeneratorBase*>(pCounterAccessor); g_pCurrentContext->m_pCounterScheduler = pCounterScheduler; } } } pCommandList->Release(); } } return result; } // end of GPA_IMP_OpenContext
GPA_Status GPA_IMP_GetHWInfo(void* pContext, GPA_HWInfo* pHwInfo) { GPA_Status result = GPA_STATUS_OK; if (nullptr == pContext) { GPA_LogError("Parameter 'pContext' is NULL."); result = GPA_STATUS_ERROR_NULL_POINTER; } else if (nullptr == pHwInfo) { GPA_LogError("Parameter 'pHwInfo' is NULL."); result = GPA_STATUS_ERROR_NULL_POINTER; } else { IUnknown* pUnknown = static_cast<IUnknown*>(pContext); ID3D12GraphicsCommandList* pCommandList = nullptr; HRESULT hr = pUnknown->QueryInterface(__uuidof(ID3D12GraphicsCommandList), reinterpret_cast<void**>(&pCommandList)); if (S_OK != hr) { GPA_LogError("Failed to get command list from context"); result = GPA_STATUS_ERROR_FAILED; } else { ID3D12Device* pDevice; hr = pCommandList->GetDevice(__uuidof(ID3D12Device), reinterpret_cast<void**>(&pDevice)); if (S_OK != hr) { GPA_LogError("Failed to get device from command list"); result = GPA_STATUS_ERROR_FAILED; } else { DXGI_ADAPTER_DESC adapterDesc; result = DX12GetAdapterDesc(pDevice, adapterDesc); if (GPA_STATUS_OK != result) { GPA_LogError("Could not get adapter description, hardware cannot be supported."); result = GPA_STATUS_ERROR_FAILED; } else { //get Time stamp frequency gpa_uint64 freq = 0ull; if (nullptr == g_pCurrentContext) { GPA_LogError("g_pCurrentContext is NULL."); result = GPA_STATUS_ERROR_NULL_POINTER; return result; } GetCurrentContext()->SetCommandList(pCommandList); result = GetCurrentContext()->GetTimestampFrequency(freq); if (GPA_STATUS_OK != result) { GPA_LogError("GetTimestampFrequency() failed."); } else { // For now it is assumed that DX12 MGPU support is exposed to the app // and the app always opens the device on the correct GPU. // In case where MGPU support hides the GPU from the app, then // we will need to use DX12 MGPU extension (and possibly ADL util) // to get the correct HW info pHwInfo->SetVendorID(adapterDesc.VendorId); // TODO: To enable running on WARP driver, fake a Bonaire HW ID if the device is the WARP device if (0x8c == adapterDesc.DeviceId && AMD_VENDOR_ID == adapterDesc.VendorId) { pHwInfo->SetDeviceID(0x665C); pHwInfo->SetRevisionID(0); } else { pHwInfo->SetVendorID(adapterDesc.VendorId); pHwInfo->SetDeviceID(adapterDesc.DeviceId); pHwInfo->SetRevisionID(adapterDesc.Revision); } std::wstring adapterNameW(adapterDesc.Description); std::string adapterName(adapterNameW.begin(), adapterNameW.end()); pHwInfo->SetDeviceName(adapterName.c_str()); GDT_HW_GENERATION hwGen = GDT_HW_GENERATION_NONE; if (NVIDIA_VENDOR_ID == adapterDesc.VendorId) { hwGen = GDT_HW_GENERATION_NVIDIA; } else if (INTEL_VENDOR_ID == adapterDesc.VendorId) { hwGen = GDT_HW_GENERATION_INTEL; } else if (AMD_VENDOR_ID == adapterDesc.VendorId) { AMDTDeviceInfoUtils::Instance()->GetHardwareGeneration(adapterDesc.DeviceId, hwGen); } pHwInfo->SetHWGeneration(hwGen); pHwInfo->SetTimeStampFrequency(freq); } } pDevice->Release(); } pCommandList->Release(); } } return result; }
GPA_Status GPA_IMP_VerifyHWSupport(void* pContext, GPA_HWInfo* pHwInfo) { GPA_Status result = GPA_STATUS_OK; if ((nullptr == pContext) || (nullptr == pHwInfo)) { result = GPA_STATUS_ERROR_FAILED; } else { IUnknown* pUnknown = static_cast<IUnknown*>(pContext); ID3D12GraphicsCommandList* pCommandList = nullptr; HRESULT hr = pUnknown->QueryInterface(__uuidof(ID3D12GraphicsCommandList), reinterpret_cast<void**>(&pCommandList)); if (S_OK != hr) { GPA_LogError("Failed to get command list from context"); result = GPA_STATUS_ERROR_FAILED; } else { ID3D12Device* pDevice; hr = pCommandList->GetDevice(__uuidof(ID3D12Device), reinterpret_cast<void**>(&pDevice)); if (S_OK != hr) { GPA_LogError("Failed to get D3D12 device"); result = GPA_STATUS_ERROR_FAILED; } else { D3D12_FEATURE_DATA_FEATURE_LEVELS featureLevels; static const D3D_FEATURE_LEVEL requestedFeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, }; featureLevels.NumFeatureLevels = (sizeof(requestedFeatureLevels) / sizeof(D3D_FEATURE_LEVEL)); featureLevels.pFeatureLevelsRequested = requestedFeatureLevels; featureLevels.MaxSupportedFeatureLevel = D3D_FEATURE_LEVEL_11_1; hr = pDevice->CheckFeatureSupport( D3D12_FEATURE_FEATURE_LEVELS, &featureLevels, sizeof(featureLevels)); if (S_OK != hr) { GPA_LogError("Failed to get D3D12 device feature levels"); result = GPA_STATUS_ERROR_FAILED; } else { if (D3D_FEATURE_LEVEL_11_0 > featureLevels.MaxSupportedFeatureLevel) { result = GPA_STATUS_ERROR_HARDWARE_NOT_SUPPORTED; } else { // TODO Once DX12 performance extension is available, check // it's possible to create a HW counter } } pDevice->Release(); } pCommandList->Release(); } } return result; } // end of GPA_IMP_VerifyHwSupport
bool DX12GPAImplementor::GetHwInfoFromAPI(const GPAContextInfoPtr pContextInfo, GPA_HWInfo& hwInfo) const { bool success = false; IUnknown* pUnknownPtr = static_cast<IUnknown*>(pContextInfo); ID3D12Device* pD3D12Device; if (DX12Utils::GetD3D12Device(pUnknownPtr, &pD3D12Device) && DX12Utils::IsFeatureLevelSupported(pD3D12Device)) { DXGI_ADAPTER_DESC adapterDesc; GPA_Status result = DX12Utils::DX12GetAdapterDesc(pD3D12Device, adapterDesc); if (GPA_STATUS_OK == result) { // For now it is assumed that DX12 MGPU support is exposed to the app // and the app always opens the device on the correct GPU. // In case where MGPU support hides the GPU from the app, then // we will need to use DX12 MGPU extension (and possibly ADL util) // to get the correct HW info hwInfo.SetVendorID(adapterDesc.VendorId); hwInfo.SetDeviceID(adapterDesc.DeviceId); hwInfo.SetRevisionID(adapterDesc.Revision); std::wstring adapterNameW(adapterDesc.Description); std::string adapterName(adapterNameW.begin(), adapterNameW.end()); hwInfo.SetDeviceName(adapterName.c_str()); GDT_HW_GENERATION hwGen = GDT_HW_GENERATION_NONE; if (NVIDIA_VENDOR_ID == adapterDesc.VendorId) { hwGen = GDT_HW_GENERATION_NVIDIA; } else if (INTEL_VENDOR_ID == adapterDesc.VendorId) { hwGen = GDT_HW_GENERATION_INTEL; } else if (AMD_VENDOR_ID == adapterDesc.VendorId) { GDT_GfxCardInfo cardInfo; if (AMDTDeviceInfoUtils::Instance()->GetDeviceInfo(adapterDesc.DeviceId, adapterDesc.Revision, cardInfo)) { hwGen = cardInfo.m_generation; // GPA DX12 requires GFX8 or above (but also works on Hawaii) if (GDT_HW_GENERATION_VOLCANICISLAND > hwGen && GDT_HAWAII != cardInfo.m_asicType) { GPA_LogError("Hardware not supported."); } else { UINT64 deviceFrequency = 0ull; GPA_ASSERT(DX12Utils::GetTimestampFrequency(pD3D12Device, deviceFrequency)); hwInfo.SetTimeStampFrequency(deviceFrequency); success = true; } } } hwInfo.SetHWGeneration(hwGen); } } return success; }