/* * Copyright (c) 2017, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include #include //For not redefining STATUS_* from ntstatus.h #define WIN32_NO_STATUS #include "runtime/os_interface/windows/wddm.h" #include "runtime/os_interface/windows/os_interface.h" #include "runtime/os_interface/windows/os_time.h" #undef WIN32_NO_STATUS namespace OCLRT { bool runEscape(Wddm *wddm, TimeStampDataHeader &escapeInfo) { if (wddm) { D3DKMT_ESCAPE escapeCommand = {0}; GTDIGetGpuCpuTimestampsIn in = {GTDI_FNC_GET_GPU_CPU_TIMESTAMPS}; GTDIGetGpuCpuTimestampsOut out = {GTDI_RET_FAILED, 0}; uint32_t inSize = sizeof(GTDIGetGpuCpuTimestampsIn); uint32_t outSize = sizeof(GTDIGetGpuCpuTimestampsOut); escapeInfo.m_Header.EscapeCode = GFX_ESCAPE_IGPA_INSTRUMENTATION_CONTROL; escapeInfo.m_Header.Size = outSize; escapeInfo.m_Data.m_In = in; escapeCommand.Flags.Value = 0; escapeCommand.hAdapter = (D3DKMT_HANDLE)0; escapeCommand.hContext = (D3DKMT_HANDLE)0; // escape is not context specific escapeCommand.hDevice = (D3DKMT_HANDLE)0; // escape not device specific escapeCommand.pPrivateDriverData = &escapeInfo; escapeCommand.PrivateDriverDataSize = sizeof(escapeInfo); escapeCommand.Type = D3DKMT_ESCAPE_DRIVERPRIVATE; auto status = wddm->escape(escapeCommand); if (status == STATUS_SUCCESS) { return true; } } return false; } bool OSTimeWin::getCpuGpuTime(TimeStampData *pGpuCpuTime) { bool retVal = false; pGpuCpuTime->CPUTimeinNS = 0; pGpuCpuTime->GPUTimeStamp = 0; TimeStampDataHeader escapeInfo = {0}; if (runEscape(wddm, escapeInfo)) { double cpuNanoseconds = escapeInfo.m_Data.m_Out.cpuPerfTicks * (1000000000.0 / escapeInfo.m_Data.m_Out.cpuPerfFreq); pGpuCpuTime->CPUTimeinNS = (unsigned long long)cpuNanoseconds; pGpuCpuTime->GPUTimeStamp = (unsigned long long)escapeInfo.m_Data.m_Out.gpuPerfTicks; retVal = true; } return retVal; } bool OSTimeWin::getCpuTime(uint64_t *timeStamp) { uint64_t time; uint64_t frequency; QueryPerformanceCounter((LARGE_INTEGER *)&time); QueryPerformanceFrequency((LARGE_INTEGER *)&frequency); *timeStamp = time * NSEC_PER_SEC / frequency; return true; }; std::unique_ptr OSTime::create(OSInterface *osInterface) { return std::unique_ptr(new OSTimeWin(osInterface)); } OSTimeWin::OSTimeWin(OSInterface *osInterface) : wddm(nullptr) { this->osInterface = osInterface; if (osInterface) { wddm = osInterface->get()->getWddm(); } QueryPerformanceFrequency(&frequency); } double OSTimeWin::getHostTimerResolution() const { double retValue = 0; if (frequency.QuadPart) { retValue = 1e9 / frequency.QuadPart; } return retValue; } double OSTimeWin::getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const { double retVal = 0; TimeStampDataHeader escapeInfo = {0}; if (runEscape(wddm, escapeInfo)) { retVal = 1000000000.0 / (double)escapeInfo.m_Data.m_Out.gpuPerfFreq; } return retVal; } uint64_t OSTimeWin::getCpuRawTimestamp() { LARGE_INTEGER cpuRawTimestamp = {}; QueryPerformanceCounter(&cpuRawTimestamp); return cpuRawTimestamp.QuadPart; } } // namespace OCLRT