#include "sistem_metrik.hpp" #include #include // clang-format off #include #include // PROCESS_MEMORY_COUNTERS (K32GetProcessMemoryInfo — kernel32, ekstra lib yok) #include // GPU kullanımı (yerel-bağımsız İngilizce sayaç) #include // PDH_MORE_DATA vb. durum kodları #include // VRAM (IDXGIAdapter3::QueryVideoMemoryInfo) // clang-format on namespace fiko { namespace { constexpr float MB = 1.0f / (1024.0f * 1024.0f); // FILETIME (100ns) → uint64. uint64_t ft64(const FILETIME& f) { return (uint64_t(f.dwHighDateTime) << 32) | f.dwLowDateTime; } // Sola-kaydırmalı halka: en yeni değeri sona koy. void gecmiseKoy(float* dizi, int n, float deger) { std::memmove(dizi, dizi + 1, (size_t)(n - 1) * sizeof(float)); dizi[n - 1] = deger; } } // namespace SistemMetrikToplayici::SistemMetrikToplayici() { SYSTEM_INFO si{}; GetSystemInfo(&si); cekirdekSayi_ = (int)(si.dwNumberOfProcessors ? si.dwNumberOfProcessors : 1); // CPU delta başlangıç referansı. FILETIME olus, cikis, cekirdek, kullanici, simdi; if (GetProcessTimes(GetCurrentProcess(), &olus, &cikis, &cekirdek, &kullanici)) { oncekiCpu100ns_ = ft64(cekirdek) + ft64(kullanici); GetSystemTimeAsFileTime(&simdi); oncekiDuvar100ns_ = ft64(simdi); } // ---- PDH: GPU 3D motor kullanımı (yerelden bağımsız İngilizce sayaç yolu) ---- PDH_HQUERY sorgu = nullptr; if (PdhOpenQueryW(nullptr, 0, &sorgu) == ERROR_SUCCESS) { PDH_HCOUNTER sayac = nullptr; if (PdhAddEnglishCounterW(sorgu, L"\\GPU Engine(*engtype_3D)\\Utilization Percentage", 0, &sayac) == ERROR_SUCCESS) { PdhCollectQueryData(sorgu); // oran sayacı için ilk örnek (değer sonraki turda) pdhSorgu_ = sorgu; pdhGpuSayac_ = sayac; pdhHazir_ = true; } else { PdhCloseQuery(sorgu); } } // ---- DXGI: birincil adaptör (VRAM sorgusu için) ---- IDXGIFactory4* fabrika = nullptr; if (SUCCEEDED(CreateDXGIFactory1(__uuidof(IDXGIFactory4), (void**)&fabrika))) { IDXGIAdapter1* ad1 = nullptr; if (fabrika->EnumAdapters1(0, &ad1) != DXGI_ERROR_NOT_FOUND && ad1) { IDXGIAdapter3* ad3 = nullptr; if (SUCCEEDED(ad1->QueryInterface(__uuidof(IDXGIAdapter3), (void**)&ad3))) { dxgiAdaptor_ = ad3; DXGI_ADAPTER_DESC1 tanim{}; if (SUCCEEDED(ad1->GetDesc1(&tanim))) m_.vramToplamMB = (float)tanim.DedicatedVideoMemory * MB; } ad1->Release(); } fabrika->Release(); } } SistemMetrikToplayici::~SistemMetrikToplayici() { if (pdhSorgu_) PdhCloseQuery((PDH_HQUERY)pdhSorgu_); if (dxgiAdaptor_) ((IDXGIAdapter3*)dxgiAdaptor_)->Release(); } void SistemMetrikToplayici::agirOrnekle() { // ---- Süreç CPU % (kernel+user delta / duvar-saat delta / çekirdek sayısı) ---- FILETIME olus, cikis, cek, kul, simdi; if (GetProcessTimes(GetCurrentProcess(), &olus, &cikis, &cek, &kul)) { GetSystemTimeAsFileTime(&simdi); const uint64_t cpu = ft64(cek) + ft64(kul); const uint64_t duvar = ft64(simdi); const uint64_t dCpu = cpu - oncekiCpu100ns_; const uint64_t dDuvar = duvar - oncekiDuvar100ns_; if (dDuvar > 0) m_.cpuYuzde = (float)((double)dCpu / (double)dDuvar / cekirdekSayi_ * 100.0); oncekiCpu100ns_ = cpu; oncekiDuvar100ns_ = duvar; if (m_.cpuYuzde < 0) m_.cpuYuzde = 0; if (m_.cpuYuzde > 100) m_.cpuYuzde = 100; } // ---- Süreç RAM (çalışma kümesi) + sistem RAM ---- PROCESS_MEMORY_COUNTERS pmc{}; pmc.cb = sizeof(pmc); if (K32GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) m_.ramMB = (float)pmc.WorkingSetSize * MB; MEMORYSTATUSEX ms{}; ms.dwLength = sizeof(ms); if (GlobalMemoryStatusEx(&ms)) { m_.ramSistemToplamMB = (float)ms.ullTotalPhys * MB; m_.ramSistemKullanilanMB = (float)(ms.ullTotalPhys - ms.ullAvailPhys) * MB; m_.ramSistemYuzde = (float)ms.dwMemoryLoad; } // ---- GPU kullanımı (PDH; en yoğun 3D motor örneği) ---- if (pdhHazir_ && PdhCollectQueryData((PDH_HQUERY)pdhSorgu_) == ERROR_SUCCESS) { DWORD bayt = 0, adet = 0; PDH_STATUS st = PdhGetFormattedCounterArrayW((PDH_HCOUNTER)pdhGpuSayac_, PDH_FMT_DOUBLE, &bayt, &adet, nullptr); if (st == PDH_MORE_DATA && bayt > 0) { auto* tampon = (PDH_FMT_COUNTERVALUE_ITEM_W*)std::malloc(bayt); if (tampon && PdhGetFormattedCounterArrayW((PDH_HCOUNTER)pdhGpuSayac_, PDH_FMT_DOUBLE, &bayt, &adet, tampon) == ERROR_SUCCESS) { double enYuksek = 0.0; for (DWORD i = 0; i < adet; ++i) if (tampon[i].FmtValue.CStatus == ERROR_SUCCESS && tampon[i].FmtValue.doubleValue > enYuksek) enYuksek = tampon[i].FmtValue.doubleValue; m_.gpuYuzde = (float)(enYuksek > 100.0 ? 100.0 : enYuksek); } std::free(tampon); } } // ---- VRAM (DXGI; süreç yerel bellek kullanımı) ---- if (dxgiAdaptor_) { DXGI_QUERY_VIDEO_MEMORY_INFO vbilgi{}; if (SUCCEEDED(((IDXGIAdapter3*)dxgiAdaptor_) ->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &vbilgi))) { m_.vramKullanilanMB = (float)vbilgi.CurrentUsage * MB; if (m_.vramToplamMB <= 0.0f && vbilgi.Budget > 0) m_.vramToplamMB = (float)vbilgi.Budget * MB; } } // ---- Geçmişe yaz ---- gecmiseKoy(m_.fpsGecmis, SistemMetrik::GECMIS, m_.fps); gecmiseKoy(m_.cpuGecmis, SistemMetrik::GECMIS, m_.cpuYuzde); gecmiseKoy(m_.gpuGecmis, SistemMetrik::GECMIS, m_.gpuYuzde); gecmiseKoy(m_.kareGecmis, SistemMetrik::GECMIS, m_.kareSuresiMs); if (m_.gecmisSayi < SistemMetrik::GECMIS) ++m_.gecmisSayi; } void SistemMetrikToplayici::guncelle(float dt, float kareSuresiMs) { m_.kareSuresiMs = kareSuresiMs; m_.fps = kareSuresiMs > 0.001f ? 1000.0f / kareSuresiMs : 0.0f; birikim_ += dt; if (birikim_ >= 0.5f) { // ağır metrikler ~2 Hz birikim_ = 0.0f; agirOrnekle(); } } } // namespace fiko