1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604 |
- #pragma once
- // This is free and unencumbered software released into the public domain.
- // Anyone is free to copy, modify, publish, use, compile, sell, or
- // distribute this software, either in source code form or as a compiled
- // binary, for any purpose, commercial or non-commercial, and by any
- // means.
- // In jurisdictions that recognize copyright laws, the author or authors
- // of this software dedicate any and all copyright interest in the
- // software to the public domain. We make this dedication for the benefit
- // of the public at large and to the detriment of our heirs and
- // successors. We intend this dedication to be an overt act of
- // relinquishment in perpetuity of all present and future rights to this
- // software under copyright law.
- // 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 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.
- // For more information, please refer to <http://unlicense.org/>
- //
- // ***********************************************************************
- //
- //
- //
- //
- // Howto:
- // Call these functions from your code:
- // MicroProfileOnThreadCreate
- // MicroProfileMouseButton
- // MicroProfileMousePosition
- // MicroProfileModKey
- // MicroProfileFlip <-- Call this once per frame
- // MicroProfileDraw <-- Call this once per frame
- // MicroProfileToggleDisplayMode <-- Bind to a key to toggle profiling
- // MicroProfileTogglePause <-- Bind to a key to toggle pause
- //
- // Use these macros in your code in blocks you want to time:
- //
- // MICROPROFILE_DECLARE
- // MICROPROFILE_DEFINE
- // MICROPROFILE_DECLARE_GPU
- // MICROPROFILE_DEFINE_GPU
- // MICROPROFILE_SCOPE
- // MICROPROFILE_SCOPEI
- // MICROPROFILE_SCOPEGPU
- // MICROPROFILE_SCOPEGPUI
- // MICROPROFILE_META
- //
- //
- // Usage:
- //
- // {
- // MICROPROFILE_SCOPEI("GroupName", "TimerName", nColorRgb):
- // ..Code to be timed..
- // }
- //
- // MICROPROFILE_DECLARE / MICROPROFILE_DEFINE allows defining groups in a shared place, to ensure sorting of the timers
- //
- // (in global scope)
- // MICROPROFILE_DEFINE(g_ProfileFisk, "Fisk", "Skalle", nSomeColorRgb);
- //
- // (in some other file)
- // MICROPROFILE_DECLARE(g_ProfileFisk);
- //
- // void foo(){
- // MICROPROFILE_SCOPE(g_ProfileFisk);
- // }
- //
- // Once code is instrumented the gui is activeted by calling MicroProfileToggleDisplayMode or by clicking in the upper left corner of
- // the screen
- //
- // The following functions must be implemented before the profiler is usable
- // debug render:
- // void MicroProfileDrawText(int nX, int nY, uint32_t nColor, const char* pText, uint32_t nNumCharacters);
- // void MicroProfileDrawBox(int nX, int nY, int nX1, int nY1, uint32_t nColor, MicroProfileBoxType = MicroProfileBoxTypeFlat);
- // void MicroProfileDrawLine2D(uint32_t nVertices, float* pVertices, uint32_t nColor);
- // Gpu time stamps: (See below for d3d/opengl helper)
- // uint32_t MicroProfileGpuInsertTimeStamp();
- // uint64_t MicroProfileGpuGetTimeStamp(uint32_t nKey);
- // uint64_t MicroProfileTicksPerSecondGpu();
- // threading:
- // const char* MicroProfileGetThreadName(); Threadnames in detailed view
- //
- // Default implementations of Gpu timestamp functions:
- // Opengl:
- // in .c file where MICROPROFILE_IMPL is defined:
- // #define MICROPROFILE_GPU_TIMERS_GL
- // call MicroProfileGpuInitGL() on startup
- // D3D11:
- // in .c file where MICROPROFILE_IMPL is defined:
- // #define MICROPROFILE_GPU_TIMERS_D3D11
- // call MICROPROFILE_GPU_TIMERS_D3D11(). Pass Device & ImmediateContext
- //
- // Limitations:
- // GPU timestamps can only be inserted from one thread.
- #ifndef MICROPROFILE_ENABLED
- #define MICROPROFILE_ENABLED 1
- #endif
- #include <stdint.h>
- typedef uint64_t MicroProfileToken;
- typedef uint16_t MicroProfileGroupId;
- #if 0 == MICROPROFILE_ENABLED
- #define MICROPROFILE_DECLARE(var)
- #define MICROPROFILE_DEFINE(var, group, name, color)
- #define MICROPROFILE_REGISTER_GROUP(group, color, category)
- #define MICROPROFILE_DECLARE_GPU(var)
- #define MICROPROFILE_DEFINE_GPU(var, name, color)
- #define MICROPROFILE_SCOPE(var) do{}while(0)
- #define MICROPROFILE_SCOPEI(group, name, color) do{}while(0)
- #define MICROPROFILE_SCOPEGPU(var) do{}while(0)
- #define MICROPROFILE_SCOPEGPUI( name, color) do{}while(0)
- #define MICROPROFILE_META_CPU(name, count)
- #define MICROPROFILE_META_GPU(name, count)
- #define MICROPROFILE_FORCEENABLECPUGROUP(s) do{} while(0)
- #define MICROPROFILE_FORCEDISABLECPUGROUP(s) do{} while(0)
- #define MICROPROFILE_FORCEENABLEGPUGROUP(s) do{} while(0)
- #define MICROPROFILE_FORCEDISABLEGPUGROUP(s) do{} while(0)
- #define MICROPROFILE_SCOPE_TOKEN(token)
- #define MicroProfileGetTime(group, name) 0.f
- #define MicroProfileOnThreadCreate(foo) do{}while(0)
- #define MicroProfileFlip() do{}while(0)
- #define MicroProfileSetAggregateFrames(a) do{}while(0)
- #define MicroProfileGetAggregateFrames() 0
- #define MicroProfileGetCurrentAggregateFrames() 0
- #define MicroProfileTogglePause() do{}while(0)
- #define MicroProfileToggleAllGroups() do{} while(0)
- #define MicroProfileDumpTimers() do{}while(0)
- #define MicroProfileShutdown() do{}while(0)
- #define MicroProfileSetForceEnable(a) do{} while(0)
- #define MicroProfileGetForceEnable() false
- #define MicroProfileSetEnableAllGroups(a) do{} while(0)
- #define MicroProfileEnableCategory(a) do{} while(0)
- #define MicroProfileDisableCategory(a) do{} while(0)
- #define MicroProfileGetEnableAllGroups() false
- #define MicroProfileSetForceMetaCounters(a)
- #define MicroProfileGetForceMetaCounters() 0
- #define MicroProfileEnableMetaCounter(c) do{}while(0)
- #define MicroProfileDisableMetaCounter(c) do{}while(0)
- #define MicroProfileDumpFile(html,csv) do{} while(0)
- #define MicroProfileWebServerPort() ((uint32_t)-1)
- #else
- #include <stdint.h>
- #include <string.h>
- #include <algorithm>
- #include <array>
- #include <atomic>
- #include <mutex>
- #include <thread>
- #ifndef MICROPROFILE_API
- #define MICROPROFILE_API
- #endif
- MICROPROFILE_API int64_t MicroProfileTicksPerSecondCpu();
- #if defined(__APPLE__)
- #include <mach/mach.h>
- #include <mach/mach_time.h>
- #include <unistd.h>
- #include <libkern/OSAtomic.h>
- #include <TargetConditionals.h>
- #if TARGET_OS_IPHONE
- #define MICROPROFILE_IOS
- #endif
- #define MP_TICK() mach_absolute_time()
- inline int64_t MicroProfileTicksPerSecondCpu()
- {
- static int64_t nTicksPerSecond = 0;
- if(nTicksPerSecond == 0)
- {
- mach_timebase_info_data_t sTimebaseInfo;
- mach_timebase_info(&sTimebaseInfo);
- nTicksPerSecond = 1000000000ll * sTimebaseInfo.denom / sTimebaseInfo.numer;
- }
- return nTicksPerSecond;
- }
- inline uint64_t MicroProfileGetCurrentThreadId()
- {
- uint64_t tid;
- pthread_threadid_np(pthread_self(), &tid);
- return tid;
- }
- #define MP_BREAK() __builtin_trap()
- #define MP_THREAD_LOCAL __thread
- #define MP_STRCASECMP strcasecmp
- #define MP_GETCURRENTTHREADID() MicroProfileGetCurrentThreadId()
- typedef uint64_t ThreadIdType;
- #elif defined(_WIN32)
- int64_t MicroProfileGetTick();
- #define MP_TICK() MicroProfileGetTick()
- #define MP_BREAK() __debugbreak()
- #define MP_THREAD_LOCAL thread_local
- #define MP_STRCASECMP _stricmp
- #define MP_GETCURRENTTHREADID() GetCurrentThreadId()
- typedef uint32_t ThreadIdType;
- #elif !defined(_WIN32)
- #include <unistd.h>
- #include <time.h>
- inline int64_t MicroProfileTicksPerSecondCpu()
- {
- return 1000000000ll;
- }
- inline int64_t MicroProfileGetTick()
- {
- timespec ts;
- clock_gettime(CLOCK_REALTIME, &ts);
- return 1000000000ll * ts.tv_sec + ts.tv_nsec;
- }
- #define MP_TICK() MicroProfileGetTick()
- #define MP_BREAK() __builtin_trap()
- #define MP_THREAD_LOCAL __thread
- #define MP_STRCASECMP strcasecmp
- #define MP_GETCURRENTTHREADID() (uint64_t)pthread_self()
- typedef uint64_t ThreadIdType;
- #endif
- #ifndef MP_GETCURRENTTHREADID
- #define MP_GETCURRENTTHREADID() 0
- typedef uint32_t ThreadIdType;
- #endif
- #define MP_ASSERT(a) do{if(!(a)){MP_BREAK();} }while(0)
- #define MICROPROFILE_DECLARE(var) extern MicroProfileToken g_mp_##var
- #define MICROPROFILE_DEFINE(var, group, name, color) MicroProfileToken g_mp_##var = MicroProfileGetToken(group, name, color, MicroProfileTokenTypeCpu)
- #define MICROPROFILE_REGISTER_GROUP(group, category, color) MicroProfileRegisterGroup(group, category, color)
- #define MICROPROFILE_DECLARE_GPU(var) extern MicroProfileToken g_mp_##var
- #define MICROPROFILE_DEFINE_GPU(var, name, color) MicroProfileToken g_mp_##var = MicroProfileGetToken("GPU", name, color, MicroProfileTokenTypeGpu)
- #define MICROPROFILE_TOKEN_PASTE0(a, b) a ## b
- #define MICROPROFILE_TOKEN_PASTE(a, b) MICROPROFILE_TOKEN_PASTE0(a,b)
- #define MICROPROFILE_TOKEN(var) g_mp_##var
- #define MICROPROFILE_SCOPE(var) MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo, __LINE__)(g_mp_##var)
- #define MICROPROFILE_SCOPE_TOKEN(token) MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo, __LINE__)(token)
- #define MICROPROFILE_SCOPEI(group, name, color) static MicroProfileToken MICROPROFILE_TOKEN_PASTE(g_mp,__LINE__) = MicroProfileGetToken(group, name, color, MicroProfileTokenTypeCpu); MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo,__LINE__)( MICROPROFILE_TOKEN_PASTE(g_mp,__LINE__))
- #define MICROPROFILE_SCOPEGPU(var) MicroProfileScopeGpuHandler MICROPROFILE_TOKEN_PASTE(foo, __LINE__)(g_mp_##var)
- #define MICROPROFILE_SCOPEGPUI(name, color) static MicroProfileToken MICROPROFILE_TOKEN_PASTE(g_mp,__LINE__) = MicroProfileGetToken("GPU", name, color, MicroProfileTokenTypeGpu); MicroProfileScopeGpuHandler MICROPROFILE_TOKEN_PASTE(foo,__LINE__)( MICROPROFILE_TOKEN_PASTE(g_mp,__LINE__))
- #define MICROPROFILE_META_CPU(name, count) static MicroProfileToken MICROPROFILE_TOKEN_PASTE(g_mp_meta,__LINE__) = MicroProfileGetMetaToken(name); MicroProfileMetaUpdate(MICROPROFILE_TOKEN_PASTE(g_mp_meta,__LINE__), count, MicroProfileTokenTypeCpu)
- #define MICROPROFILE_META_GPU(name, count) static MicroProfileToken MICROPROFILE_TOKEN_PASTE(g_mp_meta,__LINE__) = MicroProfileGetMetaToken(name); MicroProfileMetaUpdate(MICROPROFILE_TOKEN_PASTE(g_mp_meta,__LINE__), count, MicroProfileTokenTypeGpu)
- #ifndef MICROPROFILE_USE_THREAD_NAME_CALLBACK
- #define MICROPROFILE_USE_THREAD_NAME_CALLBACK 0
- #endif
- #ifndef MICROPROFILE_PER_THREAD_BUFFER_SIZE
- #define MICROPROFILE_PER_THREAD_BUFFER_SIZE (2048<<10)
- #endif
- #ifndef MICROPROFILE_MAX_FRAME_HISTORY
- #define MICROPROFILE_MAX_FRAME_HISTORY 512
- #endif
- #ifndef MICROPROFILE_PRINTF
- #define MICROPROFILE_PRINTF printf
- #endif
- #ifndef MICROPROFILE_META_MAX
- #define MICROPROFILE_META_MAX 8
- #endif
- #ifndef MICROPROFILE_WEBSERVER_PORT
- #define MICROPROFILE_WEBSERVER_PORT 1338
- #endif
- #ifndef MICROPROFILE_WEBSERVER
- #define MICROPROFILE_WEBSERVER 1
- #endif
- #ifndef MICROPROFILE_WEBSERVER_MAXFRAMES
- #define MICROPROFILE_WEBSERVER_MAXFRAMES 30
- #endif
- #ifndef MICROPROFILE_WEBSERVER_SOCKET_BUFFER_SIZE
- #define MICROPROFILE_WEBSERVER_SOCKET_BUFFER_SIZE (16<<10)
- #endif
- #ifndef MICROPROFILE_GPU_TIMERS
- #define MICROPROFILE_GPU_TIMERS 1
- #endif
- #ifndef MICROPROFILE_GPU_FRAME_DELAY
- #define MICROPROFILE_GPU_FRAME_DELAY 3 //must be > 0
- #endif
- #ifndef MICROPROFILE_NAME_MAX_LEN
- #define MICROPROFILE_NAME_MAX_LEN 64
- #endif
- #define MICROPROFILE_FORCEENABLECPUGROUP(s) MicroProfileForceEnableGroup(s, MicroProfileTokenTypeCpu)
- #define MICROPROFILE_FORCEDISABLECPUGROUP(s) MicroProfileForceDisableGroup(s, MicroProfileTokenTypeCpu)
- #define MICROPROFILE_FORCEENABLEGPUGROUP(s) MicroProfileForceEnableGroup(s, MicroProfileTokenTypeGpu)
- #define MICROPROFILE_FORCEDISABLEGPUGROUP(s) MicroProfileForceDisableGroup(s, MicroProfileTokenTypeGpu)
- #define MICROPROFILE_INVALID_TICK ((uint64_t)-1)
- #define MICROPROFILE_GROUP_MASK_ALL 0xffffffffffff
- #define MICROPROFILE_INVALID_TOKEN (uint64_t)-1
- enum MicroProfileTokenType
- {
- MicroProfileTokenTypeCpu,
- MicroProfileTokenTypeGpu,
- };
- enum MicroProfileBoxType
- {
- MicroProfileBoxTypeBar,
- MicroProfileBoxTypeFlat,
- };
- struct MicroProfile;
- MICROPROFILE_API void MicroProfileInit();
- MICROPROFILE_API void MicroProfileShutdown();
- MICROPROFILE_API MicroProfileToken MicroProfileFindToken(const char* sGroup, const char* sName);
- MICROPROFILE_API MicroProfileToken MicroProfileGetToken(const char* sGroup, const char* sName, uint32_t nColor, MicroProfileTokenType Token = MicroProfileTokenTypeCpu);
- MICROPROFILE_API MicroProfileToken MicroProfileGetMetaToken(const char* pName);
- MICROPROFILE_API void MicroProfileMetaUpdate(MicroProfileToken, int nCount, MicroProfileTokenType eTokenType);
- MICROPROFILE_API uint64_t MicroProfileEnter(MicroProfileToken nToken);
- MICROPROFILE_API void MicroProfileLeave(MicroProfileToken nToken, uint64_t nTick);
- MICROPROFILE_API uint64_t MicroProfileGpuEnter(MicroProfileToken nToken);
- MICROPROFILE_API void MicroProfileGpuLeave(MicroProfileToken nToken, uint64_t nTick);
- inline uint16_t MicroProfileGetTimerIndex(MicroProfileToken t){ return (t&0xffff); }
- inline uint64_t MicroProfileGetGroupMask(MicroProfileToken t){ return ((t>>16)&MICROPROFILE_GROUP_MASK_ALL);}
- inline MicroProfileToken MicroProfileMakeToken(uint64_t nGroupMask, uint16_t nTimer){ return (nGroupMask<<16) | nTimer;}
- MICROPROFILE_API void MicroProfileFlip(); //! call once per frame.
- MICROPROFILE_API void MicroProfileTogglePause();
- MICROPROFILE_API void MicroProfileForceEnableGroup(const char* pGroup, MicroProfileTokenType Type);
- MICROPROFILE_API void MicroProfileForceDisableGroup(const char* pGroup, MicroProfileTokenType Type);
- MICROPROFILE_API float MicroProfileGetTime(const char* pGroup, const char* pName);
- MICROPROFILE_API void MicroProfileContextSwitchSearch(uint32_t* pContextSwitchStart, uint32_t* pContextSwitchEnd, uint64_t nBaseTicksCpu, uint64_t nBaseTicksEndCpu);
- MICROPROFILE_API void MicroProfileOnThreadCreate(const char* pThreadName); //should be called from newly created threads
- MICROPROFILE_API void MicroProfileOnThreadExit(); //call on exit to reuse log
- MICROPROFILE_API void MicroProfileInitThreadLog();
- MICROPROFILE_API void MicroProfileSetForceEnable(bool bForceEnable);
- MICROPROFILE_API bool MicroProfileGetForceEnable();
- MICROPROFILE_API void MicroProfileSetEnableAllGroups(bool bEnable);
- MICROPROFILE_API void MicroProfileEnableCategory(const char* pCategory);
- MICROPROFILE_API void MicroProfileDisableCategory(const char* pCategory);
- MICROPROFILE_API bool MicroProfileGetEnableAllGroups();
- MICROPROFILE_API void MicroProfileSetForceMetaCounters(bool bEnable);
- MICROPROFILE_API bool MicroProfileGetForceMetaCounters();
- MICROPROFILE_API void MicroProfileEnableMetaCounter(const char* pMet);
- MICROPROFILE_API void MicroProfileDisableMetaCounter(const char* pMet);
- MICROPROFILE_API void MicroProfileSetAggregateFrames(int frames);
- MICROPROFILE_API int MicroProfileGetAggregateFrames();
- MICROPROFILE_API int MicroProfileGetCurrentAggregateFrames();
- MICROPROFILE_API MicroProfile* MicroProfileGet();
- MICROPROFILE_API void MicroProfileGetRange(uint32_t nPut, uint32_t nGet, uint32_t nRange[2][2]);
- MICROPROFILE_API std::recursive_mutex& MicroProfileGetMutex();
- MICROPROFILE_API void MicroProfileStartContextSwitchTrace();
- MICROPROFILE_API void MicroProfileStopContextSwitchTrace();
- MICROPROFILE_API bool MicroProfileIsLocalThread(uint32_t nThreadId);
- #if MICROPROFILE_WEBSERVER
- MICROPROFILE_API void MicroProfileDumpFile(const char* pHtml, const char* pCsv);
- MICROPROFILE_API uint32_t MicroProfileWebServerPort();
- #else
- #define MicroProfileDumpFile(c) do{} while(0)
- #define MicroProfileWebServerPort() ((uint32_t)-1)
- #endif
- #if MICROPROFILE_GPU_TIMERS
- MICROPROFILE_API uint32_t MicroProfileGpuInsertTimeStamp();
- MICROPROFILE_API uint64_t MicroProfileGpuGetTimeStamp(uint32_t nKey);
- MICROPROFILE_API uint64_t MicroProfileTicksPerSecondGpu();
- MICROPROFILE_API int MicroProfileGetGpuTickReference(int64_t* pOutCPU, int64_t* pOutGpu);
- #else
- #define MicroProfileGpuInsertTimeStamp() 1
- #define MicroProfileGpuGetTimeStamp(a) 0
- #define MicroProfileTicksPerSecondGpu() 1
- #define MicroProfileGetGpuTickReference(a,b) 0
- #endif
- #if MICROPROFILE_GPU_TIMERS_D3D11
- #define MICROPROFILE_D3D_MAX_QUERIES (8<<10)
- MICROPROFILE_API void MicroProfileGpuInitD3D11(void* pDevice, void* pDeviceContext);
- #endif
- #if MICROPROFILE_GPU_TIMERS_GL
- #define MICROPROFILE_GL_MAX_QUERIES (8<<10)
- MICROPROFILE_API void MicroProfileGpuInitGL();
- #endif
- #if MICROPROFILE_USE_THREAD_NAME_CALLBACK
- MICROPROFILE_API const char* MicroProfileGetThreadName();
- #else
- #define MicroProfileGetThreadName() "<implement MicroProfileGetThreadName to get threadnames>"
- #endif
- #if !defined(MICROPROFILE_THREAD_NAME_FROM_ID)
- #define MICROPROFILE_THREAD_NAME_FROM_ID(a) ""
- #endif
- struct MicroProfileScopeHandler
- {
- MicroProfileToken nToken;
- uint64_t nTick;
- MicroProfileScopeHandler(MicroProfileToken Token):nToken(Token)
- {
- nTick = MicroProfileEnter(nToken);
- }
- ~MicroProfileScopeHandler()
- {
- MicroProfileLeave(nToken, nTick);
- }
- };
- struct MicroProfileScopeGpuHandler
- {
- MicroProfileToken nToken;
- uint64_t nTick;
- MicroProfileScopeGpuHandler(MicroProfileToken Token):nToken(Token)
- {
- nTick = MicroProfileGpuEnter(nToken);
- }
- ~MicroProfileScopeGpuHandler()
- {
- MicroProfileGpuLeave(nToken, nTick);
- }
- };
- #define MICROPROFILE_MAX_TIMERS 1024
- #define MICROPROFILE_MAX_GROUPS 48 //dont bump! no. of bits used it bitmask
- #define MICROPROFILE_MAX_CATEGORIES 16
- #define MICROPROFILE_MAX_GRAPHS 5
- #define MICROPROFILE_GRAPH_HISTORY 128
- #define MICROPROFILE_BUFFER_SIZE ((MICROPROFILE_PER_THREAD_BUFFER_SIZE)/sizeof(MicroProfileLogEntry))
- #define MICROPROFILE_MAX_CONTEXT_SWITCH_THREADS 256
- #define MICROPROFILE_STACK_MAX 32
- //#define MICROPROFILE_MAX_PRESETS 5
- #define MICROPROFILE_ANIM_DELAY_PRC 0.5f
- #define MICROPROFILE_GAP_TIME 50 //extra ms to fetch to close timers from earlier frames
- #ifndef MICROPROFILE_MAX_THREADS
- #define MICROPROFILE_MAX_THREADS 32
- #endif
- #ifndef MICROPROFILE_UNPACK_RED
- #define MICROPROFILE_UNPACK_RED(c) ((c)>>16)
- #endif
- #ifndef MICROPROFILE_UNPACK_GREEN
- #define MICROPROFILE_UNPACK_GREEN(c) ((c)>>8)
- #endif
- #ifndef MICROPROFILE_UNPACK_BLUE
- #define MICROPROFILE_UNPACK_BLUE(c) ((c))
- #endif
- #ifndef MICROPROFILE_DEFAULT_PRESET
- #define MICROPROFILE_DEFAULT_PRESET "Default"
- #endif
- #ifndef MICROPROFILE_CONTEXT_SWITCH_TRACE
- #if defined(_WIN32)
- #define MICROPROFILE_CONTEXT_SWITCH_TRACE 1
- #elif defined(__APPLE__)
- #define MICROPROFILE_CONTEXT_SWITCH_TRACE 0 //disabled until dtrace script is working.
- #else
- #define MICROPROFILE_CONTEXT_SWITCH_TRACE 0
- #endif
- #endif
- #if MICROPROFILE_CONTEXT_SWITCH_TRACE
- #define MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE (128*1024) //2mb with 16 byte entry size
- #else
- #define MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE (1)
- #endif
- #ifndef MICROPROFILE_MINIZ
- #define MICROPROFILE_MINIZ 0
- #endif
- #ifdef _WIN32
- #include <basetsd.h>
- typedef UINT_PTR MpSocket;
- #else
- typedef int MpSocket;
- #endif
- #ifndef _WIN32
- typedef pthread_t MicroProfileThread;
- #elif defined(_MSC_VER)
- typedef HANDLE MicroProfileThread;
- #else
- typedef std::thread* MicroProfileThread;
- #endif
- enum MicroProfileDrawMask
- {
- MP_DRAW_OFF = 0x0,
- MP_DRAW_BARS = 0x1,
- MP_DRAW_DETAILED = 0x2,
- MP_DRAW_HIDDEN = 0x3,
- };
- enum MicroProfileDrawBarsMask
- {
- MP_DRAW_TIMERS = 0x1,
- MP_DRAW_AVERAGE = 0x2,
- MP_DRAW_MAX = 0x4,
- MP_DRAW_CALL_COUNT = 0x8,
- MP_DRAW_TIMERS_EXCLUSIVE = 0x10,
- MP_DRAW_AVERAGE_EXCLUSIVE = 0x20,
- MP_DRAW_MAX_EXCLUSIVE = 0x40,
- MP_DRAW_META_FIRST = 0x80,
- MP_DRAW_ALL = 0xffffffff,
- };
- typedef uint64_t MicroProfileLogEntry;
- struct MicroProfileTimer
- {
- uint64_t nTicks;
- uint32_t nCount;
- };
- struct MicroProfileCategory
- {
- char pName[MICROPROFILE_NAME_MAX_LEN];
- uint64_t nGroupMask;
- };
- struct MicroProfileGroupInfo
- {
- char pName[MICROPROFILE_NAME_MAX_LEN];
- uint32_t nNameLen;
- uint32_t nGroupIndex;
- uint32_t nNumTimers;
- uint32_t nMaxTimerNameLen;
- uint32_t nColor;
- uint32_t nCategory;
- MicroProfileTokenType Type;
- };
- struct MicroProfileTimerInfo
- {
- MicroProfileToken nToken;
- uint32_t nTimerIndex;
- uint32_t nGroupIndex;
- char pName[MICROPROFILE_NAME_MAX_LEN];
- uint32_t nNameLen;
- uint32_t nColor;
- bool bGraph;
- };
- struct MicroProfileGraphState
- {
- int64_t nHistory[MICROPROFILE_GRAPH_HISTORY];
- MicroProfileToken nToken;
- int32_t nKey;
- };
- struct MicroProfileContextSwitch
- {
- ThreadIdType nThreadOut;
- ThreadIdType nThreadIn;
- int64_t nCpu : 8;
- int64_t nTicks : 56;
- };
- struct MicroProfileFrameState
- {
- int64_t nFrameStartCpu;
- int64_t nFrameStartGpu;
- uint32_t nLogStart[MICROPROFILE_MAX_THREADS];
- };
- struct MicroProfileThreadLog
- {
- std::array<MicroProfileLogEntry, MICROPROFILE_BUFFER_SIZE> Log{};
- std::atomic<uint32_t> nPut{0};
- std::atomic<uint32_t> nGet{0};
- uint32_t nActive = 0;
- uint32_t nGpu = 0;
- ThreadIdType nThreadId{};
- std::array<uint32_t, MICROPROFILE_STACK_MAX> nStack{};
- std::array<int64_t, MICROPROFILE_STACK_MAX> nChildTickStack{};
- uint32_t nStackPos = 0;
- std::array<uint8_t, MICROPROFILE_MAX_GROUPS> nGroupStackPos{};
- std::array<int64_t, MICROPROFILE_MAX_GROUPS> nGroupTicks{};
- std::array<int64_t, MICROPROFILE_MAX_GROUPS> nAggregateGroupTicks{};
- enum
- {
- THREAD_MAX_LEN = 64,
- };
- char ThreadName[64]{};
- int nFreeListNext = 0;
- void Reset() {
- Log.fill({});
- nPut = 0;
- nGet = 0;
- nActive = 0;
- nGpu = 0;
- nThreadId = {};
- nStack.fill(0);
- nChildTickStack.fill(0);
- nStackPos = 0;
- nGroupStackPos.fill(0);
- nGroupTicks.fill(0);
- nAggregateGroupTicks.fill(0);
- std::fill(std::begin(ThreadName), std::end(ThreadName), '\0');
- nFreeListNext = 0;
- }
- };
- #if MICROPROFILE_GPU_TIMERS_D3D11
- struct MicroProfileD3D11Frame
- {
- uint32_t m_nQueryStart;
- uint32_t m_nQueryCount;
- uint32_t m_nRateQueryStarted;
- void* m_pRateQuery;
- };
- struct MicroProfileGpuTimerState
- {
- uint32_t bInitialized;
- void* m_pDevice;
- void* m_pDeviceContext;
- void* m_pQueries[MICROPROFILE_D3D_MAX_QUERIES];
- int64_t m_nQueryResults[MICROPROFILE_D3D_MAX_QUERIES];
- uint32_t m_nQueryPut;
- uint32_t m_nQueryGet;
- uint32_t m_nQueryFrame;
- int64_t m_nQueryFrequency;
- MicroProfileD3D11Frame m_QueryFrames[MICROPROFILE_GPU_FRAME_DELAY];
- };
- #elif MICROPROFILE_GPU_TIMERS_GL
- struct MicroProfileGpuTimerState
- {
- uint32_t GLTimers[MICROPROFILE_GL_MAX_QUERIES];
- uint32_t GLTimerPos;
- };
- #else
- struct MicroProfileGpuTimerState{};
- #endif
- struct MicroProfile
- {
- uint32_t nTotalTimers;
- uint32_t nGroupCount;
- uint32_t nCategoryCount;
- uint32_t nAggregateClear;
- uint32_t nAggregateFlip;
- uint32_t nAggregateFlipCount;
- uint32_t nAggregateFrames;
- uint64_t nAggregateFlipTick;
- uint32_t nDisplay;
- uint32_t nBars;
- uint64_t nActiveGroup;
- uint32_t nActiveBars;
- uint64_t nForceGroup;
- uint32_t nForceEnable;
- uint32_t nForceMetaCounters;
- uint64_t nForceGroupUI;
- uint64_t nActiveGroupWanted;
- uint32_t nAllGroupsWanted;
- uint32_t nAllThreadsWanted;
- uint32_t nOverflow;
- uint64_t nGroupMask;
- uint32_t nRunning;
- uint32_t nToggleRunning;
- uint32_t nMaxGroupSize;
- uint32_t nDumpFileNextFrame;
- uint32_t nAutoClearFrames;
- char HtmlDumpPath[512];
- char CsvDumpPath[512];
- int64_t nPauseTicks;
- float fReferenceTime;
- float fRcpReferenceTime;
- MicroProfileCategory CategoryInfo[MICROPROFILE_MAX_CATEGORIES];
- MicroProfileGroupInfo GroupInfo[MICROPROFILE_MAX_GROUPS];
- MicroProfileTimerInfo TimerInfo[MICROPROFILE_MAX_TIMERS];
- uint8_t TimerToGroup[MICROPROFILE_MAX_TIMERS];
- MicroProfileTimer AccumTimers[MICROPROFILE_MAX_TIMERS];
- uint64_t AccumMaxTimers[MICROPROFILE_MAX_TIMERS];
- uint64_t AccumTimersExclusive[MICROPROFILE_MAX_TIMERS];
- uint64_t AccumMaxTimersExclusive[MICROPROFILE_MAX_TIMERS];
- MicroProfileTimer Frame[MICROPROFILE_MAX_TIMERS];
- uint64_t FrameExclusive[MICROPROFILE_MAX_TIMERS];
- MicroProfileTimer Aggregate[MICROPROFILE_MAX_TIMERS];
- uint64_t AggregateMax[MICROPROFILE_MAX_TIMERS];
- uint64_t AggregateExclusive[MICROPROFILE_MAX_TIMERS];
- uint64_t AggregateMaxExclusive[MICROPROFILE_MAX_TIMERS];
- uint64_t FrameGroup[MICROPROFILE_MAX_GROUPS];
- uint64_t AccumGroup[MICROPROFILE_MAX_GROUPS];
- uint64_t AccumGroupMax[MICROPROFILE_MAX_GROUPS];
- uint64_t AggregateGroup[MICROPROFILE_MAX_GROUPS];
- uint64_t AggregateGroupMax[MICROPROFILE_MAX_GROUPS];
- struct
- {
- uint64_t nCounters[MICROPROFILE_MAX_TIMERS];
- uint64_t nAccum[MICROPROFILE_MAX_TIMERS];
- uint64_t nAccumMax[MICROPROFILE_MAX_TIMERS];
- uint64_t nAggregate[MICROPROFILE_MAX_TIMERS];
- uint64_t nAggregateMax[MICROPROFILE_MAX_TIMERS];
- uint64_t nSum;
- uint64_t nSumAccum;
- uint64_t nSumAccumMax;
- uint64_t nSumAggregate;
- uint64_t nSumAggregateMax;
- const char* pName;
- } MetaCounters[MICROPROFILE_META_MAX];
- MicroProfileGraphState Graph[MICROPROFILE_MAX_GRAPHS];
- uint32_t nGraphPut;
- uint32_t nThreadActive[MICROPROFILE_MAX_THREADS];
- MicroProfileThreadLog* Pool[MICROPROFILE_MAX_THREADS];
- uint32_t nNumLogs;
- uint32_t nMemUsage;
- int nFreeListHead;
- uint32_t nFrameCurrent;
- uint32_t nFrameCurrentIndex;
- uint32_t nFramePut;
- uint64_t nFramePutIndex;
- MicroProfileFrameState Frames[MICROPROFILE_MAX_FRAME_HISTORY];
- uint64_t nFlipTicks;
- uint64_t nFlipAggregate;
- uint64_t nFlipMax;
- uint64_t nFlipAggregateDisplay;
- uint64_t nFlipMaxDisplay;
- MicroProfileThread ContextSwitchThread;
- bool bContextSwitchRunning;
- bool bContextSwitchStop;
- bool bContextSwitchAllThreads;
- bool bContextSwitchNoBars;
- uint32_t nContextSwitchUsage;
- uint32_t nContextSwitchLastPut;
- int64_t nContextSwitchHoverTickIn;
- int64_t nContextSwitchHoverTickOut;
- uint32_t nContextSwitchHoverThread;
- uint32_t nContextSwitchHoverThreadBefore;
- uint32_t nContextSwitchHoverThreadAfter;
- uint8_t nContextSwitchHoverCpu;
- uint8_t nContextSwitchHoverCpuNext;
- uint32_t nContextSwitchPut;
- MicroProfileContextSwitch ContextSwitch[MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE];
- MpSocket ListenerSocket;
- uint32_t nWebServerPort;
- char WebServerBuffer[MICROPROFILE_WEBSERVER_SOCKET_BUFFER_SIZE];
- uint32_t WebServerPut;
- uint64_t nWebServerDataSent;
- MicroProfileGpuTimerState GPU;
- };
- #define MP_LOG_TICK_MASK 0x0000ffffffffffff
- #define MP_LOG_INDEX_MASK 0x3fff000000000000
- #define MP_LOG_BEGIN_MASK 0xc000000000000000
- #define MP_LOG_GPU_EXTRA 0x3
- #define MP_LOG_META 0x2
- #define MP_LOG_ENTER 0x1
- #define MP_LOG_LEAVE 0x0
- inline int MicroProfileLogType(MicroProfileLogEntry Index)
- {
- return (int)(((MP_LOG_BEGIN_MASK & Index)>>62) & 0x3ULL);
- }
- inline uint64_t MicroProfileLogTimerIndex(MicroProfileLogEntry Index)
- {
- return (0x3fff&(Index>>48));
- }
- inline MicroProfileLogEntry MicroProfileMakeLogIndex(uint64_t nBegin, MicroProfileToken nToken, int64_t nTick)
- {
- MicroProfileLogEntry Entry = (nBegin<<62) | ((0x3fff&nToken)<<48) | (MP_LOG_TICK_MASK&nTick);
- int t = MicroProfileLogType(Entry);
- uint64_t nTimerIndex = MicroProfileLogTimerIndex(Entry);
- MP_ASSERT((uint64_t)t == nBegin);
- MP_ASSERT(nTimerIndex == (nToken&0x3fff));
- return Entry;
- }
- inline int64_t MicroProfileLogTickDifference(MicroProfileLogEntry Start, MicroProfileLogEntry End)
- {
- uint64_t nStart = Start;
- uint64_t nEnd = End;
- int64_t nDifference = ((nEnd<<16) - (nStart<<16));
- return nDifference >> 16;
- }
- inline int64_t MicroProfileLogGetTick(MicroProfileLogEntry e)
- {
- return MP_LOG_TICK_MASK & e;
- }
- inline int64_t MicroProfileLogSetTick(MicroProfileLogEntry e, int64_t nTick)
- {
- return (MP_LOG_TICK_MASK & nTick) | (e & ~MP_LOG_TICK_MASK);
- }
- template<typename T>
- T MicroProfileMin(T a, T b)
- { return a < b ? a : b; }
- template<typename T>
- T MicroProfileMax(T a, T b)
- { return a > b ? a : b; }
- inline int64_t MicroProfileMsToTick(float fMs, int64_t nTicksPerSecond)
- {
- return (int64_t)(fMs*0.001f*(float)nTicksPerSecond);
- }
- inline float MicroProfileTickToMsMultiplier(int64_t nTicksPerSecond)
- {
- return 1000.f / (float)nTicksPerSecond;
- }
- inline uint16_t MicroProfileGetGroupIndex(MicroProfileToken t)
- {
- return (uint16_t)MicroProfileGet()->TimerToGroup[MicroProfileGetTimerIndex(t)];
- }
- #ifdef MICROPROFILE_IMPL
- #ifdef _WIN32
- #include <windows.h>
- #define snprintf _snprintf
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable: 4244)
- #endif
- int64_t MicroProfileTicksPerSecondCpu()
- {
- static int64_t nTicksPerSecond = 0;
- if(nTicksPerSecond == 0)
- {
- QueryPerformanceFrequency((LARGE_INTEGER*)&nTicksPerSecond);
- }
- return nTicksPerSecond;
- }
- int64_t MicroProfileGetTick()
- {
- int64_t ticks;
- QueryPerformanceCounter((LARGE_INTEGER*)&ticks);
- return ticks;
- }
- #endif
- #if defined(MICROPROFILE_WEBSERVER) || defined(MICROPROFILE_CONTEXT_SWITCH_TRACE)
- typedef void* (*MicroProfileThreadFunc)(void*);
- #ifndef _WIN32
- typedef pthread_t MicroProfileThread;
- inline void MicroProfileThreadStart(MicroProfileThread* pThread, MicroProfileThreadFunc Func)
- {
- pthread_attr_t Attr;
- int r = pthread_attr_init(&Attr);
- MP_ASSERT(r == 0);
- pthread_create(pThread, &Attr, Func, 0);
- }
- inline void MicroProfileThreadJoin(MicroProfileThread* pThread)
- {
- int r = pthread_join(*pThread, 0);
- MP_ASSERT(r == 0);
- }
- #elif defined(_MSC_VER)
- typedef HANDLE MicroProfileThread;
- DWORD _stdcall ThreadTrampoline(void* pFunc)
- {
- MicroProfileThreadFunc F = (MicroProfileThreadFunc)pFunc;
- // The return value of F will always return a void*, however, this is for
- // compatibility with pthreads. The underlying "address" of the pointer
- // is always a 32-bit value, so this cast is safe to perform.
- return static_cast<DWORD>(reinterpret_cast<uint64_t>(F(0)));
- }
- inline void MicroProfileThreadStart(MicroProfileThread* pThread, MicroProfileThreadFunc Func)
- {
- *pThread = CreateThread(0, 0, ThreadTrampoline, Func, 0, 0);
- }
- inline void MicroProfileThreadJoin(MicroProfileThread* pThread)
- {
- WaitForSingleObject(*pThread, INFINITE);
- CloseHandle(*pThread);
- }
- #else
- #include <thread>
- typedef std::thread* MicroProfileThread;
- inline void MicroProfileThreadStart(MicroProfileThread* pThread, MicroProfileThreadFunc Func)
- {
- *pThread = new std::thread(Func, nullptr);
- }
- inline void MicroProfileThreadJoin(MicroProfileThread* pThread)
- {
- (*pThread)->join();
- delete *pThread;
- }
- #endif
- #endif
- #if MICROPROFILE_WEBSERVER
- #ifdef _WIN32
- #define MP_INVALID_SOCKET(f) (f == INVALID_SOCKET)
- #endif
- #ifndef _WIN32
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <fcntl.h>
- #define MP_INVALID_SOCKET(f) (f < 0)
- #endif
- void MicroProfileWebServerStart();
- void MicroProfileWebServerStop();
- bool MicroProfileWebServerUpdate();
- void MicroProfileDumpToFile();
- #else
- #define MicroProfileWebServerStart() do{}while(0)
- #define MicroProfileWebServerStop() do{}while(0)
- #define MicroProfileWebServerUpdate() false
- #define MicroProfileDumpToFile() do{} while(0)
- #endif
- #if MICROPROFILE_GPU_TIMERS_D3D11
- void MicroProfileGpuFlip();
- void MicroProfileGpuShutdown();
- #else
- #define MicroProfileGpuFlip() do{}while(0)
- #define MicroProfileGpuShutdown() do{}while(0)
- #endif
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <algorithm>
- #ifndef MICROPROFILE_DEBUG
- #define MICROPROFILE_DEBUG 0
- #endif
- #define S g_MicroProfile
- MicroProfile g_MicroProfile;
- MicroProfileThreadLog* g_MicroProfileGpuLog = 0;
- #ifdef MICROPROFILE_IOS
- // iOS doesn't support __thread
- static pthread_key_t g_MicroProfileThreadLogKey;
- static pthread_once_t g_MicroProfileThreadLogKeyOnce = PTHREAD_ONCE_INIT;
- static void MicroProfileCreateThreadLogKey()
- {
- pthread_key_create(&g_MicroProfileThreadLogKey, NULL);
- }
- #else
- MP_THREAD_LOCAL MicroProfileThreadLog* g_MicroProfileThreadLog = 0;
- #endif
- static std::atomic<bool> g_bUseLock{false}; /// This is used because windows does not support using mutexes under dll init(which is where global initialization is handled)
- MICROPROFILE_DEFINE(g_MicroProfileFlip, "MicroProfile", "MicroProfileFlip", 0x3355ee);
- MICROPROFILE_DEFINE(g_MicroProfileThreadLoop, "MicroProfile", "ThreadLoop", 0x3355ee);
- MICROPROFILE_DEFINE(g_MicroProfileClear, "MicroProfile", "Clear", 0x3355ee);
- MICROPROFILE_DEFINE(g_MicroProfileAccumulate, "MicroProfile", "Accumulate", 0x3355ee);
- MICROPROFILE_DEFINE(g_MicroProfileContextSwitchSearch,"MicroProfile", "ContextSwitchSearch", 0xDD7300);
- inline std::recursive_mutex& MicroProfileMutex()
- {
- static std::recursive_mutex Mutex;
- return Mutex;
- }
- std::recursive_mutex& MicroProfileGetMutex()
- {
- return MicroProfileMutex();
- }
- MICROPROFILE_API MicroProfile* MicroProfileGet()
- {
- return &g_MicroProfile;
- }
- MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName);
- void MicroProfileInit()
- {
- std::recursive_mutex& mutex = MicroProfileMutex();
- bool bUseLock = g_bUseLock;
- if(bUseLock)
- mutex.lock();
- static bool bOnce = true;
- if(bOnce)
- {
- S.nMemUsage += sizeof(S);
- bOnce = false;
- memset(&S, 0, sizeof(S));
- for(int i = 0; i < MICROPROFILE_MAX_GROUPS; ++i)
- {
- S.GroupInfo[i].pName[0] = '\0';
- }
- for(int i = 0; i < MICROPROFILE_MAX_CATEGORIES; ++i)
- {
- S.CategoryInfo[i].pName[0] = '\0';
- S.CategoryInfo[i].nGroupMask = 0;
- }
- strcpy(&S.CategoryInfo[0].pName[0], "default");
- S.nCategoryCount = 1;
- for(int i = 0; i < MICROPROFILE_MAX_TIMERS; ++i)
- {
- S.TimerInfo[i].pName[0] = '\0';
- }
- S.nGroupCount = 0;
- S.nAggregateFlipTick = MP_TICK();
- S.nActiveGroup = 0;
- S.nActiveBars = 0;
- S.nForceGroup = 0;
- S.nAllGroupsWanted = 0;
- S.nActiveGroupWanted = 0;
- S.nAllThreadsWanted = 1;
- S.nAggregateFlip = 0;
- S.nTotalTimers = 0;
- for(uint32_t i = 0; i < MICROPROFILE_MAX_GRAPHS; ++i)
- {
- S.Graph[i].nToken = MICROPROFILE_INVALID_TOKEN;
- }
- S.nRunning = 1;
- S.fReferenceTime = 33.33f;
- S.fRcpReferenceTime = 1.f / S.fReferenceTime;
- S.nFreeListHead = -1;
- int64_t nTick = MP_TICK();
- for(int i = 0; i < MICROPROFILE_MAX_FRAME_HISTORY; ++i)
- {
- S.Frames[i].nFrameStartCpu = nTick;
- S.Frames[i].nFrameStartGpu = -1;
- }
- MicroProfileThreadLog* pGpu = MicroProfileCreateThreadLog("GPU");
- g_MicroProfileGpuLog = pGpu;
- MP_ASSERT(S.Pool[0] == pGpu);
- pGpu->nGpu = 1;
- pGpu->nThreadId = 0;
- S.nWebServerDataSent = (uint64_t)-1;
- }
- if(bUseLock)
- mutex.unlock();
- }
- void MicroProfileShutdown()
- {
- std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
- MicroProfileWebServerStop();
- MicroProfileStopContextSwitchTrace();
- MicroProfileGpuShutdown();
- }
- #ifdef MICROPROFILE_IOS
- inline MicroProfileThreadLog* MicroProfileGetThreadLog()
- {
- pthread_once(&g_MicroProfileThreadLogKeyOnce, MicroProfileCreateThreadLogKey);
- return (MicroProfileThreadLog*)pthread_getspecific(g_MicroProfileThreadLogKey);
- }
- inline void MicroProfileSetThreadLog(MicroProfileThreadLog* pLog)
- {
- pthread_once(&g_MicroProfileThreadLogKeyOnce, MicroProfileCreateThreadLogKey);
- pthread_setspecific(g_MicroProfileThreadLogKey, pLog);
- }
- #else
- inline MicroProfileThreadLog* MicroProfileGetThreadLog()
- {
- return g_MicroProfileThreadLog;
- }
- inline void MicroProfileSetThreadLog(MicroProfileThreadLog* pLog)
- {
- g_MicroProfileThreadLog = pLog;
- }
- #endif
- MicroProfileThreadLog* MicroProfileCreateThreadLog(const char* pName)
- {
- MicroProfileThreadLog* pLog = 0;
- if(S.nFreeListHead != -1)
- {
- pLog = S.Pool[S.nFreeListHead];
- MP_ASSERT(pLog->nPut.load() == 0);
- MP_ASSERT(pLog->nGet.load() == 0);
- S.nFreeListHead = S.Pool[S.nFreeListHead]->nFreeListNext;
- pLog->Reset();
- }
- else
- {
- pLog = new MicroProfileThreadLog;
- S.nMemUsage += sizeof(MicroProfileThreadLog);
- S.Pool[S.nNumLogs++] = pLog;
- }
- int len = (int)strlen(pName);
- int maxlen = sizeof(pLog->ThreadName)-1;
- len = len < maxlen ? len : maxlen;
- memcpy(&pLog->ThreadName[0], pName, len);
- pLog->ThreadName[len] = '\0';
- pLog->nThreadId = MP_GETCURRENTTHREADID();
- pLog->nFreeListNext = -1;
- pLog->nActive = 1;
- return pLog;
- }
- void MicroProfileOnThreadCreate(const char* pThreadName)
- {
- g_bUseLock = true;
- MicroProfileInit();
- std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
- MP_ASSERT(MicroProfileGetThreadLog() == 0);
- MicroProfileThreadLog* pLog = MicroProfileCreateThreadLog(pThreadName ? pThreadName : MicroProfileGetThreadName());
- MP_ASSERT(pLog);
- MicroProfileSetThreadLog(pLog);
- }
- void MicroProfileOnThreadExit()
- {
- std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
- MicroProfileThreadLog* pLog = MicroProfileGetThreadLog();
- if(pLog)
- {
- int32_t nLogIndex = -1;
- for(int i = 0; i < MICROPROFILE_MAX_THREADS; ++i)
- {
- if(pLog == S.Pool[i])
- {
- nLogIndex = i;
- break;
- }
- }
- MP_ASSERT(nLogIndex < MICROPROFILE_MAX_THREADS && nLogIndex > 0);
- pLog->nFreeListNext = S.nFreeListHead;
- pLog->nActive = 0;
- pLog->nPut.store(0);
- pLog->nGet.store(0);
- S.nFreeListHead = nLogIndex;
- for(int i = 0; i < MICROPROFILE_MAX_FRAME_HISTORY; ++i)
- {
- S.Frames[i].nLogStart[nLogIndex] = 0;
- }
- pLog->nGroupStackPos.fill(0);
- pLog->nGroupTicks.fill(0);
- }
- }
- void MicroProfileInitThreadLog()
- {
- MicroProfileOnThreadCreate(nullptr);
- }
- struct MicroProfileScopeLock
- {
- bool bUseLock;
- std::recursive_mutex& m;
- MicroProfileScopeLock(std::recursive_mutex& m_) : bUseLock(g_bUseLock), m(m_)
- {
- if(bUseLock)
- m.lock();
- }
- ~MicroProfileScopeLock()
- {
- if(bUseLock)
- m.unlock();
- }
- };
- MicroProfileToken MicroProfileFindToken(const char* pGroup, const char* pName)
- {
- MicroProfileInit();
- MicroProfileScopeLock L(MicroProfileMutex());
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- if(!MP_STRCASECMP(pName, S.TimerInfo[i].pName) && !MP_STRCASECMP(pGroup, S.GroupInfo[S.TimerToGroup[i]].pName))
- {
- return S.TimerInfo[i].nToken;
- }
- }
- return MICROPROFILE_INVALID_TOKEN;
- }
- inline uint16_t MicroProfileGetGroup(const char* pGroup, MicroProfileTokenType Type)
- {
- for(uint32_t i = 0; i < S.nGroupCount; ++i)
- {
- if(!MP_STRCASECMP(pGroup, S.GroupInfo[i].pName))
- {
- return i;
- }
- }
- uint16_t nGroupIndex = 0xffff;
- uint32_t nLen = (uint32_t)strlen(pGroup);
- if(nLen > MICROPROFILE_NAME_MAX_LEN-1)
- nLen = MICROPROFILE_NAME_MAX_LEN-1;
- memcpy(&S.GroupInfo[S.nGroupCount].pName[0], pGroup, nLen);
- S.GroupInfo[S.nGroupCount].pName[nLen] = '\0';
- S.GroupInfo[S.nGroupCount].nNameLen = nLen;
- S.GroupInfo[S.nGroupCount].nNumTimers = 0;
- S.GroupInfo[S.nGroupCount].nGroupIndex = S.nGroupCount;
- S.GroupInfo[S.nGroupCount].Type = Type;
- S.GroupInfo[S.nGroupCount].nMaxTimerNameLen = 0;
- S.GroupInfo[S.nGroupCount].nColor = 0x88888888;
- S.GroupInfo[S.nGroupCount].nCategory = 0;
- S.CategoryInfo[0].nGroupMask |= (1ll << (uint64_t)S.nGroupCount);
- nGroupIndex = S.nGroupCount++;
- S.nGroupMask = (S.nGroupMask<<1)|1;
- MP_ASSERT(nGroupIndex < MICROPROFILE_MAX_GROUPS);
- return nGroupIndex;
- }
- inline void MicroProfileRegisterGroup(const char* pGroup, const char* pCategory, uint32_t nColor)
- {
- int nCategoryIndex = -1;
- for(uint32_t i = 0; i < S.nCategoryCount; ++i)
- {
- if(!MP_STRCASECMP(pCategory, S.CategoryInfo[i].pName))
- {
- nCategoryIndex = (int)i;
- break;
- }
- }
- if(-1 == nCategoryIndex && S.nCategoryCount < MICROPROFILE_MAX_CATEGORIES)
- {
- MP_ASSERT(S.CategoryInfo[S.nCategoryCount].pName[0] == '\0');
- nCategoryIndex = (int)S.nCategoryCount++;
- uint32_t nLen = (uint32_t)strlen(pCategory);
- if(nLen > MICROPROFILE_NAME_MAX_LEN-1)
- nLen = MICROPROFILE_NAME_MAX_LEN-1;
- memcpy(&S.CategoryInfo[nCategoryIndex].pName[0], pCategory, nLen);
- S.CategoryInfo[nCategoryIndex].pName[nLen] = '\0';
- }
- uint16_t nGroup = MicroProfileGetGroup(pGroup, 0 != MP_STRCASECMP(pGroup, "gpu")?MicroProfileTokenTypeCpu : MicroProfileTokenTypeGpu);
- S.GroupInfo[nGroup].nColor = nColor;
- if(nCategoryIndex >= 0)
- {
- uint64_t nBit = 1ll << nGroup;
- uint32_t nOldCategory = S.GroupInfo[nGroup].nCategory;
- S.CategoryInfo[nOldCategory].nGroupMask &= ~nBit;
- S.CategoryInfo[nCategoryIndex].nGroupMask |= nBit;
- S.GroupInfo[nGroup].nCategory = nCategoryIndex;
- }
- }
- MicroProfileToken MicroProfileGetToken(const char* pGroup, const char* pName, uint32_t nColor, MicroProfileTokenType Type)
- {
- MicroProfileInit();
- MicroProfileScopeLock L(MicroProfileMutex());
- MicroProfileToken ret = MicroProfileFindToken(pGroup, pName);
- if(ret != MICROPROFILE_INVALID_TOKEN)
- return ret;
- uint16_t nGroupIndex = MicroProfileGetGroup(pGroup, Type);
- uint16_t nTimerIndex = (uint16_t)(S.nTotalTimers++);
- uint64_t nGroupMask = 1ll << nGroupIndex;
- MicroProfileToken nToken = MicroProfileMakeToken(nGroupMask, nTimerIndex);
- S.GroupInfo[nGroupIndex].nNumTimers++;
- S.GroupInfo[nGroupIndex].nMaxTimerNameLen = MicroProfileMax(S.GroupInfo[nGroupIndex].nMaxTimerNameLen, (uint32_t)strlen(pName));
- MP_ASSERT(S.GroupInfo[nGroupIndex].Type == Type); //dont mix cpu & gpu timers in the same group
- S.nMaxGroupSize = MicroProfileMax(S.nMaxGroupSize, S.GroupInfo[nGroupIndex].nNumTimers);
- S.TimerInfo[nTimerIndex].nToken = nToken;
- uint32_t nLen = (uint32_t)strlen(pName);
- if(nLen > MICROPROFILE_NAME_MAX_LEN-1)
- nLen = MICROPROFILE_NAME_MAX_LEN-1;
- memcpy(&S.TimerInfo[nTimerIndex].pName, pName, nLen);
- S.TimerInfo[nTimerIndex].pName[nLen] = '\0';
- S.TimerInfo[nTimerIndex].nNameLen = nLen;
- S.TimerInfo[nTimerIndex].nColor = nColor&0xffffff;
- S.TimerInfo[nTimerIndex].nGroupIndex = nGroupIndex;
- S.TimerInfo[nTimerIndex].nTimerIndex = nTimerIndex;
- S.TimerToGroup[nTimerIndex] = nGroupIndex;
- return nToken;
- }
- MicroProfileToken MicroProfileGetMetaToken(const char* pName)
- {
- MicroProfileInit();
- MicroProfileScopeLock L(MicroProfileMutex());
- for(uint32_t i = 0; i < MICROPROFILE_META_MAX; ++i)
- {
- if(!S.MetaCounters[i].pName)
- {
- S.MetaCounters[i].pName = pName;
- return i;
- }
- else if(!MP_STRCASECMP(pName, S.MetaCounters[i].pName))
- {
- return i;
- }
- }
- MP_ASSERT(0);//out of slots, increase MICROPROFILE_META_MAX
- return (MicroProfileToken)-1;
- }
- inline void MicroProfileLogPut(MicroProfileToken nToken_, uint64_t nTick, uint64_t nBegin, MicroProfileThreadLog* pLog)
- {
- MP_ASSERT(pLog != 0); //this assert is hit if MicroProfileOnCreateThread is not called
- MP_ASSERT(pLog->nActive);
- uint32_t nPos = pLog->nPut.load(std::memory_order_relaxed);
- uint32_t nNextPos = (nPos+1) % MICROPROFILE_BUFFER_SIZE;
- if(nNextPos == pLog->nGet.load(std::memory_order_relaxed))
- {
- S.nOverflow = 100;
- }
- else
- {
- pLog->Log[nPos] = MicroProfileMakeLogIndex(nBegin, nToken_, nTick);
- pLog->nPut.store(nNextPos, std::memory_order_release);
- }
- }
- uint64_t MicroProfileEnter(MicroProfileToken nToken_)
- {
- if(MicroProfileGetGroupMask(nToken_) & S.nActiveGroup)
- {
- if(!MicroProfileGetThreadLog())
- {
- MicroProfileInitThreadLog();
- }
- uint64_t nTick = MP_TICK();
- MicroProfileLogPut(nToken_, nTick, MP_LOG_ENTER, MicroProfileGetThreadLog());
- return nTick;
- }
- return MICROPROFILE_INVALID_TICK;
- }
- void MicroProfileMetaUpdate(MicroProfileToken nToken, int nCount, MicroProfileTokenType eTokenType)
- {
- if((MP_DRAW_META_FIRST<<nToken) & S.nActiveBars)
- {
- MicroProfileThreadLog* pLog = MicroProfileTokenTypeCpu == eTokenType ? MicroProfileGetThreadLog() : g_MicroProfileGpuLog;
- if(pLog)
- {
- MP_ASSERT(nToken < MICROPROFILE_META_MAX);
- MicroProfileLogPut(nToken, nCount, MP_LOG_META, pLog);
- }
- }
- }
- void MicroProfileLeave(MicroProfileToken nToken_, uint64_t nTickStart)
- {
- if(MICROPROFILE_INVALID_TICK != nTickStart)
- {
- if(!MicroProfileGetThreadLog())
- {
- MicroProfileInitThreadLog();
- }
- uint64_t nTick = MP_TICK();
- MicroProfileThreadLog* pLog = MicroProfileGetThreadLog();
- MicroProfileLogPut(nToken_, nTick, MP_LOG_LEAVE, pLog);
- }
- }
- uint64_t MicroProfileGpuEnter(MicroProfileToken nToken_)
- {
- if(MicroProfileGetGroupMask(nToken_) & S.nActiveGroup)
- {
- uint64_t nTimer = MicroProfileGpuInsertTimeStamp();
- MicroProfileLogPut(nToken_, nTimer, MP_LOG_ENTER, g_MicroProfileGpuLog);
- MicroProfileLogPut(nToken_, MP_TICK(), MP_LOG_GPU_EXTRA, g_MicroProfileGpuLog);
- return 1;
- }
- return 0;
- }
- void MicroProfileGpuLeave(MicroProfileToken nToken_, uint64_t nTickStart)
- {
- if(nTickStart)
- {
- uint64_t nTimer = MicroProfileGpuInsertTimeStamp();
- MicroProfileLogPut(nToken_, nTimer, MP_LOG_LEAVE, g_MicroProfileGpuLog);
- MicroProfileLogPut(nToken_, MP_TICK(), MP_LOG_GPU_EXTRA, g_MicroProfileGpuLog);
- }
- }
- inline void MicroProfileContextSwitchPut(MicroProfileContextSwitch* pContextSwitch)
- {
- if(S.nRunning || pContextSwitch->nTicks <= S.nPauseTicks)
- {
- uint32_t nPut = S.nContextSwitchPut;
- S.ContextSwitch[nPut] = *pContextSwitch;
- S.nContextSwitchPut = (S.nContextSwitchPut+1) % MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE;
- }
- }
- void MicroProfileGetRange(uint32_t nPut, uint32_t nGet, uint32_t nRange[2][2])
- {
- if(nPut > nGet)
- {
- nRange[0][0] = nGet;
- nRange[0][1] = nPut;
- nRange[1][0] = nRange[1][1] = 0;
- }
- else if(nPut != nGet)
- {
- MP_ASSERT(nGet != MICROPROFILE_BUFFER_SIZE);
- uint32_t nCountEnd = MICROPROFILE_BUFFER_SIZE - nGet;
- nRange[0][0] = nGet;
- nRange[0][1] = nGet + nCountEnd;
- nRange[1][0] = 0;
- nRange[1][1] = nPut;
- }
- }
- void MicroProfileFlip()
- {
- #if 0
- //verify LogEntry wraps correctly
- MicroProfileLogEntry c = MP_LOG_TICK_MASK-5000;
- for(int i = 0; i < 10000; ++i, c += 1)
- {
- MicroProfileLogEntry l2 = (c+2500) & MP_LOG_TICK_MASK;
- MP_ASSERT(2500 == MicroProfileLogTickDifference(c, l2));
- }
- #endif
- MICROPROFILE_SCOPE(g_MicroProfileFlip);
- std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
- MicroProfileGpuFlip();
- if(S.nToggleRunning)
- {
- S.nRunning = !S.nRunning;
- if(!S.nRunning)
- S.nPauseTicks = MP_TICK();
- S.nToggleRunning = 0;
- for(uint32_t i = 0; i < MICROPROFILE_MAX_THREADS; ++i)
- {
- MicroProfileThreadLog* pLog = S.Pool[i];
- if(pLog)
- {
- pLog->nStackPos = 0;
- }
- }
- }
- uint32_t nAggregateClear = S.nAggregateClear || S.nAutoClearFrames, nAggregateFlip = 0;
- if(S.nDumpFileNextFrame)
- {
- MicroProfileDumpToFile();
- S.nDumpFileNextFrame = 0;
- S.nAutoClearFrames = MICROPROFILE_GPU_FRAME_DELAY + 3; //hide spike from dumping webpage
- }
- if(S.nWebServerDataSent == (uint64_t)-1)
- {
- MicroProfileWebServerStart();
- S.nWebServerDataSent = 0;
- }
- if(MicroProfileWebServerUpdate())
- {
- S.nAutoClearFrames = MICROPROFILE_GPU_FRAME_DELAY + 3; //hide spike from dumping webpage
- }
- if(S.nAutoClearFrames)
- {
- nAggregateClear = 1;
- nAggregateFlip = 1;
- S.nAutoClearFrames -= 1;
- }
- if(S.nRunning || S.nForceEnable)
- {
- S.nFramePutIndex++;
- S.nFramePut = (S.nFramePut+1) % MICROPROFILE_MAX_FRAME_HISTORY;
- MP_ASSERT((S.nFramePutIndex % MICROPROFILE_MAX_FRAME_HISTORY) == S.nFramePut);
- S.nFrameCurrent = (S.nFramePut + MICROPROFILE_MAX_FRAME_HISTORY - MICROPROFILE_GPU_FRAME_DELAY - 1) % MICROPROFILE_MAX_FRAME_HISTORY;
- S.nFrameCurrentIndex++;
- uint32_t nFrameNext = (S.nFrameCurrent+1) % MICROPROFILE_MAX_FRAME_HISTORY;
- uint32_t nContextSwitchPut = S.nContextSwitchPut;
- if(S.nContextSwitchLastPut < nContextSwitchPut)
- {
- S.nContextSwitchUsage = (nContextSwitchPut - S.nContextSwitchLastPut);
- }
- else
- {
- S.nContextSwitchUsage = MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE - S.nContextSwitchLastPut + nContextSwitchPut;
- }
- S.nContextSwitchLastPut = nContextSwitchPut;
- MicroProfileFrameState* pFramePut = &S.Frames[S.nFramePut];
- MicroProfileFrameState* pFrameCurrent = &S.Frames[S.nFrameCurrent];
- MicroProfileFrameState* pFrameNext = &S.Frames[nFrameNext];
- pFramePut->nFrameStartCpu = MP_TICK();
- pFramePut->nFrameStartGpu = (uint32_t)MicroProfileGpuInsertTimeStamp();
- if(pFrameNext->nFrameStartGpu != -1)
- pFrameNext->nFrameStartGpu = MicroProfileGpuGetTimeStamp((uint32_t)pFrameNext->nFrameStartGpu);
- if(pFrameCurrent->nFrameStartGpu == -1)
- pFrameCurrent->nFrameStartGpu = pFrameNext->nFrameStartGpu + 1;
- uint64_t nFrameStartCpu = pFrameCurrent->nFrameStartCpu;
- uint64_t nFrameEndCpu = pFrameNext->nFrameStartCpu;
- {
- uint64_t nTick = nFrameEndCpu - nFrameStartCpu;
- S.nFlipTicks = nTick;
- S.nFlipAggregate += nTick;
- S.nFlipMax = MicroProfileMax(S.nFlipMax, nTick);
- }
- uint8_t* pTimerToGroup = &S.TimerToGroup[0];
- for(uint32_t i = 0; i < MICROPROFILE_MAX_THREADS; ++i)
- {
- MicroProfileThreadLog* pLog = S.Pool[i];
- if(!pLog)
- {
- pFramePut->nLogStart[i] = 0;
- }
- else
- {
- uint32_t nPut = pLog->nPut.load(std::memory_order_acquire);
- pFramePut->nLogStart[i] = nPut;
- MP_ASSERT(nPut< MICROPROFILE_BUFFER_SIZE);
- //need to keep last frame around to close timers. timers more than 1 frame old is ditched.
- pLog->nGet.store(nPut, std::memory_order_relaxed);
- }
- }
- if(S.nRunning)
- {
- uint64_t* pFrameGroup = &S.FrameGroup[0];
- {
- MICROPROFILE_SCOPE(g_MicroProfileClear);
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- S.Frame[i].nTicks = 0;
- S.Frame[i].nCount = 0;
- S.FrameExclusive[i] = 0;
- }
- for(uint32_t i = 0; i < MICROPROFILE_MAX_GROUPS; ++i)
- {
- pFrameGroup[i] = 0;
- }
- for(uint32_t j = 0; j < MICROPROFILE_META_MAX; ++j)
- {
- if(S.MetaCounters[j].pName && 0 != (S.nActiveBars & (MP_DRAW_META_FIRST<<j)))
- {
- auto& Meta = S.MetaCounters[j];
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- Meta.nCounters[i] = 0;
- }
- }
- }
- }
- {
- MICROPROFILE_SCOPE(g_MicroProfileThreadLoop);
- for(uint32_t i = 0; i < MICROPROFILE_MAX_THREADS; ++i)
- {
- MicroProfileThreadLog* pLog = S.Pool[i];
- if(!pLog)
- continue;
- uint8_t* pGroupStackPos = &pLog->nGroupStackPos[0];
- int64_t nGroupTicks[MICROPROFILE_MAX_GROUPS] = {0};
- uint32_t nPut = pFrameNext->nLogStart[i];
- uint32_t nGet = pFrameCurrent->nLogStart[i];
- uint32_t nRange[2][2] = { {0, 0}, {0, 0}, };
- MicroProfileGetRange(nPut, nGet, nRange);
- //fetch gpu results.
- if(pLog->nGpu)
- {
- for(uint32_t j = 0; j < 2; ++j)
- {
- uint32_t nStart = nRange[j][0];
- uint32_t nEnd = nRange[j][1];
- for(uint32_t k = nStart; k < nEnd; ++k)
- {
- MicroProfileLogEntry L = pLog->Log[k];
- if(MicroProfileLogType(L) < MP_LOG_META)
- {
- pLog->Log[k] = MicroProfileLogSetTick(L, MicroProfileGpuGetTimeStamp((uint32_t)MicroProfileLogGetTick(L)));
- }
- }
- }
- }
- uint32_t* pStack = &pLog->nStack[0];
- int64_t* pChildTickStack = &pLog->nChildTickStack[0];
- uint32_t nStackPos = pLog->nStackPos;
- for(uint32_t j = 0; j < 2; ++j)
- {
- uint32_t nStart = nRange[j][0];
- uint32_t nEnd = nRange[j][1];
- for(uint32_t k = nStart; k < nEnd; ++k)
- {
- MicroProfileLogEntry LE = pLog->Log[k];
- int nType = MicroProfileLogType(LE);
- if(MP_LOG_ENTER == nType)
- {
- int nTimer = MicroProfileLogTimerIndex(LE);
- uint8_t nGroup = pTimerToGroup[nTimer];
- // To avoid crashing due to OOB memory accesses/asserts
- // simply skip this iteration
- // MP_ASSERT(nStackPos < MICROPROFILE_STACK_MAX);
- if (nStackPos >= MICROPROFILE_STACK_MAX) {
- break;
- }
- MP_ASSERT(nGroup < MICROPROFILE_MAX_GROUPS);
- pGroupStackPos[nGroup]++;
- pStack[nStackPos++] = k;
- pChildTickStack[nStackPos] = 0;
- }
- else if(MP_LOG_META == nType)
- {
- if(nStackPos)
- {
- int64_t nMetaIndex = MicroProfileLogTimerIndex(LE);
- int64_t nMetaCount = MicroProfileLogGetTick(LE);
- MP_ASSERT(nMetaIndex < MICROPROFILE_META_MAX);
- int64_t nCounter = MicroProfileLogTimerIndex(pLog->Log[pStack[nStackPos-1]]);
- S.MetaCounters[nMetaIndex].nCounters[nCounter] += nMetaCount;
- }
- }
- else if(MP_LOG_LEAVE == nType)
- {
- int nTimer = MicroProfileLogTimerIndex(LE);
- uint8_t nGroup = pTimerToGroup[nTimer];
- MP_ASSERT(nGroup < MICROPROFILE_MAX_GROUPS);
- if(nStackPos)
- {
- int64_t nTickStart = pLog->Log[pStack[nStackPos-1]];
- int64_t nTicks = MicroProfileLogTickDifference(nTickStart, LE);
- int64_t nChildTicks = pChildTickStack[nStackPos];
- nStackPos--;
- pChildTickStack[nStackPos] += nTicks;
- uint32_t nTimerIndex = MicroProfileLogTimerIndex(LE);
- S.Frame[nTimerIndex].nTicks += nTicks;
- S.FrameExclusive[nTimerIndex] += (nTicks-nChildTicks);
- S.Frame[nTimerIndex].nCount += 1;
- MP_ASSERT(nGroup < MICROPROFILE_MAX_GROUPS);
- uint8_t nGroupStackPos = pGroupStackPos[nGroup];
- if(nGroupStackPos)
- {
- nGroupStackPos--;
- if(0 == nGroupStackPos)
- {
- nGroupTicks[nGroup] += nTicks;
- }
- pGroupStackPos[nGroup] = nGroupStackPos;
- }
- }
- }
- }
- }
- for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
- {
- pLog->nGroupTicks[j] += nGroupTicks[j];
- pFrameGroup[j] += nGroupTicks[j];
- }
- pLog->nStackPos = nStackPos;
- }
- }
- {
- MICROPROFILE_SCOPE(g_MicroProfileAccumulate);
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- S.AccumTimers[i].nTicks += S.Frame[i].nTicks;
- S.AccumTimers[i].nCount += S.Frame[i].nCount;
- S.AccumMaxTimers[i] = MicroProfileMax(S.AccumMaxTimers[i], S.Frame[i].nTicks);
- S.AccumTimersExclusive[i] += S.FrameExclusive[i];
- S.AccumMaxTimersExclusive[i] = MicroProfileMax(S.AccumMaxTimersExclusive[i], S.FrameExclusive[i]);
- }
- for(uint32_t i = 0; i < MICROPROFILE_MAX_GROUPS; ++i)
- {
- S.AccumGroup[i] += pFrameGroup[i];
- S.AccumGroupMax[i] = MicroProfileMax(S.AccumGroupMax[i], pFrameGroup[i]);
- }
- for(uint32_t j = 0; j < MICROPROFILE_META_MAX; ++j)
- {
- if(S.MetaCounters[j].pName && 0 != (S.nActiveBars & (MP_DRAW_META_FIRST<<j)))
- {
- auto& Meta = S.MetaCounters[j];
- uint64_t nSum = 0;;
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- uint64_t nCounter = Meta.nCounters[i];
- Meta.nAccumMax[i] = MicroProfileMax(Meta.nAccumMax[i], nCounter);
- Meta.nAccum[i] += nCounter;
- nSum += nCounter;
- }
- Meta.nSumAccum += nSum;
- Meta.nSumAccumMax = MicroProfileMax(Meta.nSumAccumMax, nSum);
- }
- }
- }
- for(uint32_t i = 0; i < MICROPROFILE_MAX_GRAPHS; ++i)
- {
- if(S.Graph[i].nToken != MICROPROFILE_INVALID_TOKEN)
- {
- MicroProfileToken nToken = S.Graph[i].nToken;
- S.Graph[i].nHistory[S.nGraphPut] = S.Frame[MicroProfileGetTimerIndex(nToken)].nTicks;
- }
- }
- S.nGraphPut = (S.nGraphPut+1) % MICROPROFILE_GRAPH_HISTORY;
- }
- if(S.nRunning && S.nAggregateFlip <= ++S.nAggregateFlipCount)
- {
- nAggregateFlip = 1;
- if(S.nAggregateFlip) // if 0 accumulate indefinitely
- {
- nAggregateClear = 1;
- }
- }
- }
- if(nAggregateFlip)
- {
- memcpy(&S.Aggregate[0], &S.AccumTimers[0], sizeof(S.Aggregate[0]) * S.nTotalTimers);
- memcpy(&S.AggregateMax[0], &S.AccumMaxTimers[0], sizeof(S.AggregateMax[0]) * S.nTotalTimers);
- memcpy(&S.AggregateExclusive[0], &S.AccumTimersExclusive[0], sizeof(S.AggregateExclusive[0]) * S.nTotalTimers);
- memcpy(&S.AggregateMaxExclusive[0], &S.AccumMaxTimersExclusive[0], sizeof(S.AggregateMaxExclusive[0]) * S.nTotalTimers);
- memcpy(&S.AggregateGroup[0], &S.AccumGroup[0], sizeof(S.AggregateGroup));
- memcpy(&S.AggregateGroupMax[0], &S.AccumGroupMax[0], sizeof(S.AggregateGroup));
- for(uint32_t i = 0; i < MICROPROFILE_MAX_THREADS; ++i)
- {
- MicroProfileThreadLog* pLog = S.Pool[i];
- if(!pLog)
- continue;
- memcpy(&pLog->nAggregateGroupTicks[0], &pLog->nGroupTicks[0], sizeof(pLog->nAggregateGroupTicks));
- if(nAggregateClear)
- {
- memset(&pLog->nGroupTicks[0], 0, sizeof(pLog->nGroupTicks));
- }
- }
- for(uint32_t j = 0; j < MICROPROFILE_META_MAX; ++j)
- {
- if(S.MetaCounters[j].pName && 0 != (S.nActiveBars & (MP_DRAW_META_FIRST<<j)))
- {
- auto& Meta = S.MetaCounters[j];
- memcpy(&Meta.nAggregateMax[0], &Meta.nAccumMax[0], sizeof(Meta.nAggregateMax[0]) * S.nTotalTimers);
- memcpy(&Meta.nAggregate[0], &Meta.nAccum[0], sizeof(Meta.nAggregate[0]) * S.nTotalTimers);
- Meta.nSumAggregate = Meta.nSumAccum;
- Meta.nSumAggregateMax = Meta.nSumAccumMax;
- if(nAggregateClear)
- {
- memset(&Meta.nAccumMax[0], 0, sizeof(Meta.nAccumMax[0]) * S.nTotalTimers);
- memset(&Meta.nAccum[0], 0, sizeof(Meta.nAccum[0]) * S.nTotalTimers);
- Meta.nSumAccum = 0;
- Meta.nSumAccumMax = 0;
- }
- }
- }
- S.nAggregateFrames = S.nAggregateFlipCount;
- S.nFlipAggregateDisplay = S.nFlipAggregate;
- S.nFlipMaxDisplay = S.nFlipMax;
- if(nAggregateClear)
- {
- memset(&S.AccumTimers[0], 0, sizeof(S.Aggregate[0]) * S.nTotalTimers);
- memset(&S.AccumMaxTimers[0], 0, sizeof(S.AccumMaxTimers[0]) * S.nTotalTimers);
- memset(&S.AccumTimersExclusive[0], 0, sizeof(S.AggregateExclusive[0]) * S.nTotalTimers);
- memset(&S.AccumMaxTimersExclusive[0], 0, sizeof(S.AccumMaxTimersExclusive[0]) * S.nTotalTimers);
- memset(&S.AccumGroup[0], 0, sizeof(S.AggregateGroup));
- memset(&S.AccumGroupMax[0], 0, sizeof(S.AggregateGroup));
- S.nAggregateFlipCount = 0;
- S.nFlipAggregate = 0;
- S.nFlipMax = 0;
- S.nAggregateFlipTick = MP_TICK();
- }
- }
- S.nAggregateClear = 0;
- uint64_t nNewActiveGroup = 0;
- if(S.nForceEnable || (S.nDisplay && S.nRunning))
- nNewActiveGroup = S.nAllGroupsWanted ? S.nGroupMask : S.nActiveGroupWanted;
- nNewActiveGroup |= S.nForceGroup;
- nNewActiveGroup |= S.nForceGroupUI;
- if(S.nActiveGroup != nNewActiveGroup)
- S.nActiveGroup = nNewActiveGroup;
- uint32_t nNewActiveBars = 0;
- if(S.nDisplay && S.nRunning)
- nNewActiveBars = S.nBars;
- if(S.nForceMetaCounters)
- {
- for(int i = 0; i < MICROPROFILE_META_MAX; ++i)
- {
- if(S.MetaCounters[i].pName)
- {
- nNewActiveBars |= (MP_DRAW_META_FIRST<<i);
- }
- }
- }
- if(nNewActiveBars != S.nActiveBars)
- S.nActiveBars = nNewActiveBars;
- }
- void MicroProfileSetForceEnable(bool bEnable)
- {
- S.nForceEnable = bEnable ? 1 : 0;
- }
- bool MicroProfileGetForceEnable()
- {
- return S.nForceEnable != 0;
- }
- void MicroProfileSetEnableAllGroups(bool bEnableAllGroups)
- {
- S.nAllGroupsWanted = bEnableAllGroups ? 1 : 0;
- }
- inline void MicroProfileEnableCategory(const char* pCategory, bool bEnabled)
- {
- int nCategoryIndex = -1;
- for(uint32_t i = 0; i < S.nCategoryCount; ++i)
- {
- if(!MP_STRCASECMP(pCategory, S.CategoryInfo[i].pName))
- {
- nCategoryIndex = (int)i;
- break;
- }
- }
- if(nCategoryIndex >= 0)
- {
- if(bEnabled)
- {
- S.nActiveGroupWanted |= S.CategoryInfo[nCategoryIndex].nGroupMask;
- }
- else
- {
- S.nActiveGroupWanted &= ~S.CategoryInfo[nCategoryIndex].nGroupMask;
- }
- }
- }
- void MicroProfileEnableCategory(const char* pCategory)
- {
- MicroProfileEnableCategory(pCategory, true);
- }
- void MicroProfileDisableCategory(const char* pCategory)
- {
- MicroProfileEnableCategory(pCategory, false);
- }
- bool MicroProfileGetEnableAllGroups()
- {
- return 0 != S.nAllGroupsWanted;
- }
- void MicroProfileSetForceMetaCounters(bool bForce)
- {
- S.nForceMetaCounters = bForce ? 1 : 0;
- }
- bool MicroProfileGetForceMetaCounters()
- {
- return 0 != S.nForceMetaCounters;
- }
- void MicroProfileEnableMetaCounter(const char* pMeta)
- {
- for(uint32_t i = 0; i < MICROPROFILE_META_MAX; ++i)
- {
- if(S.MetaCounters[i].pName && 0 == MP_STRCASECMP(S.MetaCounters[i].pName, pMeta))
- {
- S.nBars |= (MP_DRAW_META_FIRST<<i);
- return;
- }
- }
- }
- void MicroProfileDisableMetaCounter(const char* pMeta)
- {
- for(uint32_t i = 0; i < MICROPROFILE_META_MAX; ++i)
- {
- if(S.MetaCounters[i].pName && 0 == MP_STRCASECMP(S.MetaCounters[i].pName, pMeta))
- {
- S.nBars &= ~(MP_DRAW_META_FIRST<<i);
- return;
- }
- }
- }
- void MicroProfileSetAggregateFrames(int nFrames)
- {
- S.nAggregateFlip = (uint32_t)nFrames;
- if(0 == nFrames)
- {
- S.nAggregateClear = 1;
- }
- }
- int MicroProfileGetAggregateFrames()
- {
- return S.nAggregateFlip;
- }
- int MicroProfileGetCurrentAggregateFrames()
- {
- return int(S.nAggregateFlip ? S.nAggregateFlip : S.nAggregateFlipCount);
- }
- void MicroProfileForceEnableGroup(const char* pGroup, MicroProfileTokenType Type)
- {
- MicroProfileInit();
- std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
- uint16_t nGroup = MicroProfileGetGroup(pGroup, Type);
- S.nForceGroup |= (1ll << nGroup);
- }
- void MicroProfileForceDisableGroup(const char* pGroup, MicroProfileTokenType Type)
- {
- MicroProfileInit();
- std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
- uint16_t nGroup = MicroProfileGetGroup(pGroup, Type);
- S.nForceGroup &= ~(1ll << nGroup);
- }
- inline void MicroProfileCalcAllTimers(float* pTimers, float* pAverage, float* pMax, float* pCallAverage, float* pExclusive, float* pAverageExclusive, float* pMaxExclusive, float* pTotal, uint32_t nSize)
- {
- for(uint32_t i = 0; i < S.nTotalTimers && i < nSize; ++i)
- {
- const uint32_t nGroupId = S.TimerInfo[i].nGroupIndex;
- const float fToMs = MicroProfileTickToMsMultiplier(S.GroupInfo[nGroupId].Type == MicroProfileTokenTypeGpu ? MicroProfileTicksPerSecondGpu() : MicroProfileTicksPerSecondCpu());
- uint32_t nTimer = i;
- uint32_t nIdx = i * 2;
- uint32_t nAggregateFrames = S.nAggregateFrames ? S.nAggregateFrames : 1;
- uint32_t nAggregateCount = S.Aggregate[nTimer].nCount ? S.Aggregate[nTimer].nCount : 1;
- float fToPrc = S.fRcpReferenceTime;
- float fMs = fToMs * (S.Frame[nTimer].nTicks);
- float fPrc = MicroProfileMin(fMs * fToPrc, 1.f);
- float fAverageMs = fToMs * (S.Aggregate[nTimer].nTicks / nAggregateFrames);
- float fAveragePrc = MicroProfileMin(fAverageMs * fToPrc, 1.f);
- float fMaxMs = fToMs * (S.AggregateMax[nTimer]);
- float fMaxPrc = MicroProfileMin(fMaxMs * fToPrc, 1.f);
- float fCallAverageMs = fToMs * (S.Aggregate[nTimer].nTicks / nAggregateCount);
- float fCallAveragePrc = MicroProfileMin(fCallAverageMs * fToPrc, 1.f);
- float fMsExclusive = fToMs * (S.FrameExclusive[nTimer]);
- float fPrcExclusive = MicroProfileMin(fMsExclusive * fToPrc, 1.f);
- float fAverageMsExclusive = fToMs * (S.AggregateExclusive[nTimer] / nAggregateFrames);
- float fAveragePrcExclusive = MicroProfileMin(fAverageMsExclusive * fToPrc, 1.f);
- float fMaxMsExclusive = fToMs * (S.AggregateMaxExclusive[nTimer]);
- float fMaxPrcExclusive = MicroProfileMin(fMaxMsExclusive * fToPrc, 1.f);
- float fTotalMs = fToMs * S.Aggregate[nTimer].nTicks;
- pTimers[nIdx] = fMs;
- pTimers[nIdx+1] = fPrc;
- pAverage[nIdx] = fAverageMs;
- pAverage[nIdx+1] = fAveragePrc;
- pMax[nIdx] = fMaxMs;
- pMax[nIdx+1] = fMaxPrc;
- pCallAverage[nIdx] = fCallAverageMs;
- pCallAverage[nIdx+1] = fCallAveragePrc;
- pExclusive[nIdx] = fMsExclusive;
- pExclusive[nIdx+1] = fPrcExclusive;
- pAverageExclusive[nIdx] = fAverageMsExclusive;
- pAverageExclusive[nIdx+1] = fAveragePrcExclusive;
- pMaxExclusive[nIdx] = fMaxMsExclusive;
- pMaxExclusive[nIdx+1] = fMaxPrcExclusive;
- pTotal[nIdx] = fTotalMs;
- pTotal[nIdx+1] = 0.f;
- }
- }
- void MicroProfileTogglePause()
- {
- S.nToggleRunning = 1;
- }
- float MicroProfileGetTime(const char* pGroup, const char* pName)
- {
- MicroProfileToken nToken = MicroProfileFindToken(pGroup, pName);
- if(nToken == MICROPROFILE_INVALID_TOKEN)
- {
- return 0.f;
- }
- uint32_t nTimerIndex = MicroProfileGetTimerIndex(nToken);
- uint32_t nGroupIndex = MicroProfileGetGroupIndex(nToken);
- float fToMs = MicroProfileTickToMsMultiplier(S.GroupInfo[nGroupIndex].Type == MicroProfileTokenTypeGpu ? MicroProfileTicksPerSecondGpu() : MicroProfileTicksPerSecondCpu());
- return S.Frame[nTimerIndex].nTicks * fToMs;
- }
- void MicroProfileContextSwitchSearch(uint32_t* pContextSwitchStart, uint32_t* pContextSwitchEnd, uint64_t nBaseTicksCpu, uint64_t nBaseTicksEndCpu)
- {
- MICROPROFILE_SCOPE(g_MicroProfileContextSwitchSearch);
- uint32_t nContextSwitchPut = S.nContextSwitchPut;
- uint64_t nContextSwitchStart, nContextSwitchEnd;
- nContextSwitchStart = nContextSwitchEnd = (nContextSwitchPut + MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE - 1) % MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE;
- int64_t nSearchEnd = nBaseTicksEndCpu + MicroProfileMsToTick(30.f, MicroProfileTicksPerSecondCpu());
- int64_t nSearchBegin = nBaseTicksCpu - MicroProfileMsToTick(30.f, MicroProfileTicksPerSecondCpu());
- for(uint32_t i = 0; i < MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE; ++i)
- {
- uint32_t nIndex = (nContextSwitchPut + MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE - (i+1)) % MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE;
- MicroProfileContextSwitch& CS = S.ContextSwitch[nIndex];
- if(CS.nTicks > nSearchEnd)
- {
- nContextSwitchEnd = nIndex;
- }
- if(CS.nTicks > nSearchBegin)
- {
- nContextSwitchStart = nIndex;
- }
- }
- *pContextSwitchStart = nContextSwitchStart;
- *pContextSwitchEnd = nContextSwitchEnd;
- }
- #if MICROPROFILE_WEBSERVER
- #define MICROPROFILE_EMBED_HTML
- extern const char* g_MicroProfileHtml_begin[];
- extern size_t g_MicroProfileHtml_begin_sizes[];
- extern size_t g_MicroProfileHtml_begin_count;
- extern const char* g_MicroProfileHtml_end[];
- extern size_t g_MicroProfileHtml_end_sizes[];
- extern size_t g_MicroProfileHtml_end_count;
- typedef void MicroProfileWriteCallback(void* Handle, size_t size, const char* pData);
- uint32_t MicroProfileWebServerPort()
- {
- return S.nWebServerPort;
- }
- void MicroProfileDumpFile(const char* pHtml, const char* pCsv)
- {
- S.nDumpFileNextFrame = 0;
- if(pHtml)
- {
- uint32_t nLen = strlen(pHtml);
- if(nLen > sizeof(S.HtmlDumpPath)-1)
- {
- return;
- }
- memcpy(S.HtmlDumpPath, pHtml, nLen+1);
- S.nDumpFileNextFrame |= 1;
- }
- if(pCsv)
- {
- uint32_t nLen = strlen(pCsv);
- if(nLen > sizeof(S.CsvDumpPath)-1)
- {
- return;
- }
- memcpy(S.CsvDumpPath, pCsv, nLen+1);
- S.nDumpFileNextFrame |= 2;
- }
- }
- void MicroProfilePrintf(MicroProfileWriteCallback CB, void* Handle, const char* pFmt, ...)
- {
- char buffer[32*1024];
- va_list args;
- va_start (args, pFmt);
- #ifdef _WIN32
- size_t size = vsprintf_s(buffer, pFmt, args);
- #else
- size_t size = vsnprintf(buffer, sizeof(buffer)-1, pFmt, args);
- #endif
- CB(Handle, size, &buffer[0]);
- va_end (args);
- }
- #define printf(...) MicroProfilePrintf(CB, Handle, __VA_ARGS__)
- void MicroProfileDumpCsv(MicroProfileWriteCallback CB, void* Handle, int nMaxFrames)
- {
- uint32_t nAggregateFrames = S.nAggregateFrames ? S.nAggregateFrames : 1;
- float fToMsCPU = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
- float fToMsGPU = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondGpu());
- printf("frames,%d\n", nAggregateFrames);
- printf("group,name,average,max,callaverage\n");
- uint32_t nNumTimers = S.nTotalTimers;
- uint32_t nBlockSize = 2 * nNumTimers;
- float* pTimers = (float*)alloca(nBlockSize * 8 * sizeof(float));
- float* pAverage = pTimers + nBlockSize;
- float* pMax = pTimers + 2 * nBlockSize;
- float* pCallAverage = pTimers + 3 * nBlockSize;
- float* pTimersExclusive = pTimers + 4 * nBlockSize;
- float* pAverageExclusive = pTimers + 5 * nBlockSize;
- float* pMaxExclusive = pTimers + 6 * nBlockSize;
- float* pTotal = pTimers + 7 * nBlockSize;
- MicroProfileCalcAllTimers(pTimers, pAverage, pMax, pCallAverage, pTimersExclusive, pAverageExclusive, pMaxExclusive, pTotal, nNumTimers);
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- uint32_t nIdx = i * 2;
- printf("\"%s\",\"%s\",%f,%f,%f\n", S.TimerInfo[i].pName, S.GroupInfo[S.TimerInfo[i].nGroupIndex].pName, pAverage[nIdx], pMax[nIdx], pCallAverage[nIdx]);
- }
- printf("\n\n");
- printf("group,average,max,total\n");
- for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
- {
- const char* pGroupName = S.GroupInfo[j].pName;
- float fToMs = S.GroupInfo[j].Type == MicroProfileTokenTypeGpu ? fToMsGPU : fToMsCPU;
- if(pGroupName[0] != '\0')
- {
- printf("\"%s\",%.3f,%.3f,%.3f\n", pGroupName, fToMs * S.AggregateGroup[j] / nAggregateFrames, fToMs * S.AggregateGroup[j] / nAggregateFrames, fToMs * S.AggregateGroup[j]);
- }
- }
- printf("\n\n");
- printf("group,thread,average,total\n");
- for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
- {
- for(uint32_t i = 0; i < S.nNumLogs; ++i)
- {
- if(S.Pool[i])
- {
- const char* pThreadName = &S.Pool[i]->ThreadName[0];
- // MicroProfilePrintf(CB, Handle, "var ThreadGroupTime%d = [", i);
- float fToMs = S.Pool[i]->nGpu ? fToMsGPU : fToMsCPU;
- {
- uint64_t nTicks = S.Pool[i]->nAggregateGroupTicks[j];
- float fTime = nTicks / nAggregateFrames * fToMs;
- float fTimeTotal = nTicks * fToMs;
- if(fTimeTotal > 0.01f)
- {
- const char* pGroupName = S.GroupInfo[j].pName;
- printf("\"%s\",\"%s\",%.3f,%.3f\n", pGroupName, pThreadName, fTime, fTimeTotal);
- }
- }
- }
- }
- }
- printf("\n\n");
- printf("frametimecpu\n");
- const uint32_t nCount = MICROPROFILE_MAX_FRAME_HISTORY - MICROPROFILE_GPU_FRAME_DELAY - 3;
- const uint32_t nStart = S.nFrameCurrent;
- for(uint32_t i = nCount; i > 0; i--)
- {
- uint32_t nFrame = (nStart + MICROPROFILE_MAX_FRAME_HISTORY - i) % MICROPROFILE_MAX_FRAME_HISTORY;
- uint32_t nFrameNext = (nStart + MICROPROFILE_MAX_FRAME_HISTORY - i + 1) % MICROPROFILE_MAX_FRAME_HISTORY;
- uint64_t nTicks = S.Frames[nFrameNext].nFrameStartCpu - S.Frames[nFrame].nFrameStartCpu;
- printf("%f,", nTicks * fToMsCPU);
- }
- printf("\n");
- printf("\n\n");
- printf("frametimegpu\n");
- for(uint32_t i = nCount; i > 0; i--)
- {
- uint32_t nFrame = (nStart + MICROPROFILE_MAX_FRAME_HISTORY - i) % MICROPROFILE_MAX_FRAME_HISTORY;
- uint32_t nFrameNext = (nStart + MICROPROFILE_MAX_FRAME_HISTORY - i + 1) % MICROPROFILE_MAX_FRAME_HISTORY;
- uint64_t nTicks = S.Frames[nFrameNext].nFrameStartGpu - S.Frames[nFrame].nFrameStartGpu;
- printf("%f,", nTicks * fToMsGPU);
- }
- printf("\n\n");
- printf("Meta\n");//only single frame snapshot
- printf("name,average,max,total\n");
- for(int j = 0; j < MICROPROFILE_META_MAX; ++j)
- {
- if(S.MetaCounters[j].pName)
- {
- printf("\"%s\",%f,%lld,%lld\n",S.MetaCounters[j].pName, S.MetaCounters[j].nSumAggregate / (float)nAggregateFrames, S.MetaCounters[j].nSumAggregateMax,S.MetaCounters[j].nSumAggregate);
- }
- }
- }
- #undef printf
- void MicroProfileDumpHtml(MicroProfileWriteCallback CB, void* Handle, int nMaxFrames, const char* pHost)
- {
- uint32_t nRunning = S.nRunning;
- S.nRunning = 0;
- //stall pushing of timers
- uint64_t nActiveGroup = S.nActiveGroup;
- S.nActiveGroup = 0;
- S.nPauseTicks = MP_TICK();
- for(size_t i = 0; i < g_MicroProfileHtml_begin_count; ++i)
- {
- CB(Handle, g_MicroProfileHtml_begin_sizes[i]-1, g_MicroProfileHtml_begin[i]);
- }
- //dump info
- uint64_t nTicks = MP_TICK();
- float fToMsCPU = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
- float fToMsGPU = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondGpu());
- float fAggregateMs = fToMsCPU * (nTicks - S.nAggregateFlipTick);
- MicroProfilePrintf(CB, Handle, "var DumpHost = '%s';\n", pHost ? pHost : "");
- time_t CaptureTime;
- time(&CaptureTime);
- MicroProfilePrintf(CB, Handle, "var DumpUtcCaptureTime = %ld;\n", CaptureTime);
- MicroProfilePrintf(CB, Handle, "var AggregateInfo = {'Frames':%d, 'Time':%f};\n", S.nAggregateFrames, fAggregateMs);
- //categories
- MicroProfilePrintf(CB, Handle, "var CategoryInfo = Array(%d);\n",S.nCategoryCount);
- for(uint32_t i = 0; i < S.nCategoryCount; ++i)
- {
- MicroProfilePrintf(CB, Handle, "CategoryInfo[%d] = \"%s\";\n", i, S.CategoryInfo[i].pName);
- }
- //groups
- MicroProfilePrintf(CB, Handle, "var GroupInfo = Array(%d);\n\n",S.nGroupCount);
- uint32_t nAggregateFrames = S.nAggregateFrames ? S.nAggregateFrames : 1;
- float fRcpAggregateFrames = 1.f / nAggregateFrames;
- for(uint32_t i = 0; i < S.nGroupCount; ++i)
- {
- MP_ASSERT(i == S.GroupInfo[i].nGroupIndex);
- float fToMs = S.GroupInfo[i].Type == MicroProfileTokenTypeCpu ? fToMsCPU : fToMsGPU;
- MicroProfilePrintf(CB, Handle, "GroupInfo[%d] = MakeGroup(%d, \"%s\", %d, %d, %d, %f, %f, %f, '#%02x%02x%02x');\n",
- S.GroupInfo[i].nGroupIndex,
- S.GroupInfo[i].nGroupIndex,
- S.GroupInfo[i].pName,
- S.GroupInfo[i].nCategory,
- S.GroupInfo[i].nNumTimers,
- S.GroupInfo[i].Type == MicroProfileTokenTypeGpu?1:0,
- fToMs * S.AggregateGroup[i],
- fToMs * S.AggregateGroup[i] / nAggregateFrames,
- fToMs * S.AggregateGroupMax[i],
- MICROPROFILE_UNPACK_RED(S.GroupInfo[i].nColor) & 0xff,
- MICROPROFILE_UNPACK_GREEN(S.GroupInfo[i].nColor) & 0xff,
- MICROPROFILE_UNPACK_BLUE(S.GroupInfo[i].nColor) & 0xff);
- }
- //timers
- uint32_t nNumTimers = S.nTotalTimers;
- uint32_t nBlockSize = 2 * nNumTimers;
- float* pTimers = (float*)alloca(nBlockSize * 8 * sizeof(float));
- float* pAverage = pTimers + nBlockSize;
- float* pMax = pTimers + 2 * nBlockSize;
- float* pCallAverage = pTimers + 3 * nBlockSize;
- float* pTimersExclusive = pTimers + 4 * nBlockSize;
- float* pAverageExclusive = pTimers + 5 * nBlockSize;
- float* pMaxExclusive = pTimers + 6 * nBlockSize;
- float* pTotal = pTimers + 7 * nBlockSize;
- MicroProfileCalcAllTimers(pTimers, pAverage, pMax, pCallAverage, pTimersExclusive, pAverageExclusive, pMaxExclusive, pTotal, nNumTimers);
- MicroProfilePrintf(CB, Handle, "\nvar TimerInfo = Array(%d);\n\n", S.nTotalTimers);
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- uint32_t nIdx = i * 2;
- MP_ASSERT(i == S.TimerInfo[i].nTimerIndex);
- MicroProfilePrintf(CB, Handle, "var Meta%d = [", i);
- bool bOnce = true;
- for(int j = 0; j < MICROPROFILE_META_MAX; ++j)
- {
- if(S.MetaCounters[j].pName)
- {
- uint32_t lala = S.MetaCounters[j].nCounters[i];
- MicroProfilePrintf(CB, Handle, bOnce ? "%d" : ",%d", lala);
- bOnce = false;
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- MicroProfilePrintf(CB, Handle, "var MetaAvg%d = [", i);
- bOnce = true;
- for(int j = 0; j < MICROPROFILE_META_MAX; ++j)
- {
- if(S.MetaCounters[j].pName)
- {
- MicroProfilePrintf(CB, Handle, bOnce ? "%f" : ",%f", fRcpAggregateFrames * S.MetaCounters[j].nAggregate[i]);
- bOnce = false;
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- MicroProfilePrintf(CB, Handle, "var MetaMax%d = [", i);
- bOnce = true;
- for(int j = 0; j < MICROPROFILE_META_MAX; ++j)
- {
- if(S.MetaCounters[j].pName)
- {
- MicroProfilePrintf(CB, Handle, bOnce ? "%d" : ",%d", S.MetaCounters[j].nAggregateMax[i]);
- bOnce = false;
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- uint32_t nColor = S.TimerInfo[i].nColor;
- uint32_t nColorDark = (nColor >> 1) & ~0x80808080;
- MicroProfilePrintf(CB, Handle, "TimerInfo[%d] = MakeTimer(%d, \"%s\", %d, '#%02x%02x%02x','#%02x%02x%02x', %f, %f, %f, %f, %f, %d, %f, Meta%d, MetaAvg%d, MetaMax%d);\n", S.TimerInfo[i].nTimerIndex, S.TimerInfo[i].nTimerIndex, S.TimerInfo[i].pName, S.TimerInfo[i].nGroupIndex,
- MICROPROFILE_UNPACK_RED(nColor) & 0xff,
- MICROPROFILE_UNPACK_GREEN(nColor) & 0xff,
- MICROPROFILE_UNPACK_BLUE(nColor) & 0xff,
- MICROPROFILE_UNPACK_RED(nColorDark) & 0xff,
- MICROPROFILE_UNPACK_GREEN(nColorDark) & 0xff,
- MICROPROFILE_UNPACK_BLUE(nColorDark) & 0xff,
- pAverage[nIdx],
- pMax[nIdx],
- pAverageExclusive[nIdx],
- pMaxExclusive[nIdx],
- pCallAverage[nIdx],
- S.Aggregate[i].nCount,
- pTotal[nIdx],
- i,i,i);
- }
- MicroProfilePrintf(CB, Handle, "\nvar ThreadNames = [");
- for(uint32_t i = 0; i < S.nNumLogs; ++i)
- {
- if(S.Pool[i])
- {
- MicroProfilePrintf(CB, Handle, "'%s',", S.Pool[i]->ThreadName);
- }
- else
- {
- MicroProfilePrintf(CB, Handle, "'Thread %d',", i);
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n\n");
- for(uint32_t i = 0; i < S.nNumLogs; ++i)
- {
- if(S.Pool[i])
- {
- MicroProfilePrintf(CB, Handle, "var ThreadGroupTime%d = [", i);
- float fToMs = S.Pool[i]->nGpu ? fToMsGPU : fToMsCPU;
- for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
- {
- MicroProfilePrintf(CB, Handle, "%f,", S.Pool[i]->nAggregateGroupTicks[j]/nAggregateFrames * fToMs);
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- }
- }
- MicroProfilePrintf(CB, Handle, "\nvar ThreadGroupTimeArray = [");
- for(uint32_t i = 0; i < S.nNumLogs; ++i)
- {
- if(S.Pool[i])
- {
- MicroProfilePrintf(CB, Handle, "ThreadGroupTime%d,", i);
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- for(uint32_t i = 0; i < S.nNumLogs; ++i)
- {
- if(S.Pool[i])
- {
- MicroProfilePrintf(CB, Handle, "var ThreadGroupTimeTotal%d = [", i);
- float fToMs = S.Pool[i]->nGpu ? fToMsGPU : fToMsCPU;
- for(uint32_t j = 0; j < MICROPROFILE_MAX_GROUPS; ++j)
- {
- MicroProfilePrintf(CB, Handle, "%f,", S.Pool[i]->nAggregateGroupTicks[j] * fToMs);
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- }
- }
- MicroProfilePrintf(CB, Handle, "\nvar ThreadGroupTimeTotalArray = [");
- for(uint32_t i = 0; i < S.nNumLogs; ++i)
- {
- if(S.Pool[i])
- {
- MicroProfilePrintf(CB, Handle, "ThreadGroupTimeTotal%d,", i);
- }
- }
- MicroProfilePrintf(CB, Handle, "];");
- MicroProfilePrintf(CB, Handle, "\nvar ThreadIds = [");
- for(uint32_t i = 0; i < S.nNumLogs; ++i)
- {
- if(S.Pool[i])
- {
- ThreadIdType ThreadId = S.Pool[i]->nThreadId;
- if(!ThreadId)
- {
- ThreadId = (ThreadIdType)-1;
- }
- MicroProfilePrintf(CB, Handle, "%d,", ThreadId);
- }
- else
- {
- MicroProfilePrintf(CB, Handle, "-1,", i);
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n\n");
- MicroProfilePrintf(CB, Handle, "\nvar MetaNames = [");
- for(int i = 0; i < MICROPROFILE_META_MAX; ++i)
- {
- if(S.MetaCounters[i].pName)
- {
- MicroProfilePrintf(CB, Handle, "'%s',", S.MetaCounters[i].pName);
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n\n");
- uint32_t nNumFrames = (MICROPROFILE_MAX_FRAME_HISTORY - MICROPROFILE_GPU_FRAME_DELAY - 3); //leave a few to not overwrite
- nNumFrames = MicroProfileMin(nNumFrames, (uint32_t)nMaxFrames);
- uint32_t nFirstFrame = (S.nFrameCurrent + MICROPROFILE_MAX_FRAME_HISTORY - nNumFrames) % MICROPROFILE_MAX_FRAME_HISTORY;
- uint32_t nLastFrame = (nFirstFrame + nNumFrames) % MICROPROFILE_MAX_FRAME_HISTORY;
- MP_ASSERT(nLastFrame == (S.nFrameCurrent % MICROPROFILE_MAX_FRAME_HISTORY));
- MP_ASSERT(nFirstFrame < MICROPROFILE_MAX_FRAME_HISTORY);
- MP_ASSERT(nLastFrame < MICROPROFILE_MAX_FRAME_HISTORY);
- const int64_t nTickStart = S.Frames[nFirstFrame].nFrameStartCpu;
- const int64_t nTickEnd = S.Frames[nLastFrame].nFrameStartCpu;
- int64_t nTickStartGpu = S.Frames[nFirstFrame].nFrameStartGpu;
- int64_t nTickReferenceCpu, nTickReferenceGpu;
- int64_t nTicksPerSecondCpu = MicroProfileTicksPerSecondCpu();
- int64_t nTicksPerSecondGpu = MicroProfileTicksPerSecondGpu();
- int nTickReference = 0;
- if(MicroProfileGetGpuTickReference(&nTickReferenceCpu, &nTickReferenceGpu))
- {
- nTickStartGpu = (nTickStart - nTickReferenceCpu) * nTicksPerSecondGpu / nTicksPerSecondCpu + nTickReferenceGpu;
- nTickReference = 1;
- }
- #if MICROPROFILE_DEBUG
- printf("dumping %d frames\n", nNumFrames);
- printf("dumping frame %d to %d\n", nFirstFrame, nLastFrame);
- #endif
- uint32_t* nTimerCounter = (uint32_t*)alloca(sizeof(uint32_t)* S.nTotalTimers);
- memset(nTimerCounter, 0, sizeof(uint32_t) * S.nTotalTimers);
- MicroProfilePrintf(CB, Handle, "var Frames = Array(%d);\n", nNumFrames);
- for(uint32_t i = 0; i < nNumFrames; ++i)
- {
- uint32_t nFrameIndex = (nFirstFrame + i) % MICROPROFILE_MAX_FRAME_HISTORY;
- uint32_t nFrameIndexNext = (nFrameIndex + 1) % MICROPROFILE_MAX_FRAME_HISTORY;
- for(uint32_t j = 0; j < S.nNumLogs; ++j)
- {
- MicroProfileThreadLog* pLog = S.Pool[j];
- int64_t nStartTickBase = pLog->nGpu ? nTickStartGpu : nTickStart;
- uint32_t nLogStart = S.Frames[nFrameIndex].nLogStart[j];
- uint32_t nLogEnd = S.Frames[nFrameIndexNext].nLogStart[j];
- float fToMsCpu = MicroProfileTickToMsMultiplier(nTicksPerSecondCpu);
- float fToMsBase = MicroProfileTickToMsMultiplier(pLog->nGpu ? nTicksPerSecondGpu : nTicksPerSecondCpu);
- MicroProfilePrintf(CB, Handle, "var ts_%d_%d = [", i, j);
- if(nLogStart != nLogEnd)
- {
- uint32_t k = nLogStart;
- uint32_t nLogType = MicroProfileLogType(pLog->Log[k]);
- float fToMs = nLogType == MP_LOG_GPU_EXTRA ? fToMsCpu : fToMsBase;
- int64_t nStartTick = nLogType == MP_LOG_GPU_EXTRA ? nTickStart : nStartTickBase;
- float fTime = nLogType == MP_LOG_META ? 0.f : MicroProfileLogTickDifference(nStartTick, pLog->Log[k]) * fToMs;
- MicroProfilePrintf(CB, Handle, "%f", fTime);
- for(k = (k+1) % MICROPROFILE_BUFFER_SIZE; k != nLogEnd; k = (k+1) % MICROPROFILE_BUFFER_SIZE)
- {
- uint32_t nLogType = MicroProfileLogType(pLog->Log[k]);
- float fToMs = nLogType == MP_LOG_GPU_EXTRA ? fToMsCpu : fToMsBase;
- nStartTick = nLogType == MP_LOG_GPU_EXTRA ? nTickStart : nStartTickBase;
- float fTime = nLogType == MP_LOG_META ? 0.f : MicroProfileLogTickDifference(nStartTick, pLog->Log[k]) * fToMs;
- MicroProfilePrintf(CB, Handle, ",%f", fTime);
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- MicroProfilePrintf(CB, Handle, "var tt_%d_%d = [", i, j);
- if(nLogStart != nLogEnd)
- {
- uint32_t k = nLogStart;
- MicroProfilePrintf(CB, Handle, "%d", MicroProfileLogType(pLog->Log[k]));
- for(k = (k+1) % MICROPROFILE_BUFFER_SIZE; k != nLogEnd; k = (k+1) % MICROPROFILE_BUFFER_SIZE)
- {
- uint32_t nLogType = MicroProfileLogType(pLog->Log[k]);
- if(nLogType == MP_LOG_META)
- {
- //for meta, store the count + 3, which is the tick part
- nLogType = 3 + MicroProfileLogGetTick(pLog->Log[k]);
- }
- MicroProfilePrintf(CB, Handle, ",%d", nLogType);
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- MicroProfilePrintf(CB, Handle, "var ti_%d_%d = [", i, j);
- if(nLogStart != nLogEnd)
- {
- uint32_t k = nLogStart;
- MicroProfilePrintf(CB, Handle, "%d", (uint32_t)MicroProfileLogTimerIndex(pLog->Log[k]));
- for(k = (k+1) % MICROPROFILE_BUFFER_SIZE; k != nLogEnd; k = (k+1) % MICROPROFILE_BUFFER_SIZE)
- {
- uint32_t nTimerIndex = (uint32_t)MicroProfileLogTimerIndex(pLog->Log[k]);
- MicroProfilePrintf(CB, Handle, ",%d", nTimerIndex);
- nTimerCounter[nTimerIndex]++;
- }
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- }
- MicroProfilePrintf(CB, Handle, "var ts%d = [", i);
- for(uint32_t j = 0; j < S.nNumLogs; ++j)
- {
- MicroProfilePrintf(CB, Handle, "ts_%d_%d,", i, j);
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- MicroProfilePrintf(CB, Handle, "var tt%d = [", i);
- for(uint32_t j = 0; j < S.nNumLogs; ++j)
- {
- MicroProfilePrintf(CB, Handle, "tt_%d_%d,", i, j);
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- MicroProfilePrintf(CB, Handle, "var ti%d = [", i);
- for(uint32_t j = 0; j < S.nNumLogs; ++j)
- {
- MicroProfilePrintf(CB, Handle, "ti_%d_%d,", i, j);
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- int64_t nFrameStart = S.Frames[nFrameIndex].nFrameStartCpu;
- int64_t nFrameEnd = S.Frames[nFrameIndexNext].nFrameStartCpu;
- float fToMs = MicroProfileTickToMsMultiplier(nTicksPerSecondCpu);
- float fFrameMs = MicroProfileLogTickDifference(nTickStart, nFrameStart) * fToMs;
- float fFrameEndMs = MicroProfileLogTickDifference(nTickStart, nFrameEnd) * fToMs;
- float fFrameGpuMs = 0;
- float fFrameGpuEndMs = 0;
- if(nTickReference)
- {
- fFrameGpuMs = MicroProfileLogTickDifference(nTickStartGpu, S.Frames[nFrameIndex].nFrameStartGpu) * fToMsGPU;
- fFrameGpuEndMs = MicroProfileLogTickDifference(nTickStartGpu, S.Frames[nFrameIndexNext].nFrameStartGpu) * fToMsGPU;
- }
- MicroProfilePrintf(CB, Handle, "Frames[%d] = MakeFrame(%d, %f, %f, %f, %f, ts%d, tt%d, ti%d);\n", i, 0, fFrameMs, fFrameEndMs, fFrameGpuMs, fFrameGpuEndMs, i, i, i);
- }
- uint32_t nContextSwitchStart = 0;
- uint32_t nContextSwitchEnd = 0;
- MicroProfileContextSwitchSearch(&nContextSwitchStart, &nContextSwitchEnd, nTickStart, nTickEnd);
- uint32_t nWrittenBefore = S.nWebServerDataSent;
- MicroProfilePrintf(CB, Handle, "var CSwitchThreadInOutCpu = [");
- for(uint32_t j = nContextSwitchStart; j != nContextSwitchEnd; j = (j+1) % MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE)
- {
- MicroProfileContextSwitch CS = S.ContextSwitch[j];
- int nCpu = CS.nCpu;
- MicroProfilePrintf(CB, Handle, "%d,%d,%d,", CS.nThreadIn, CS.nThreadOut, nCpu);
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- MicroProfilePrintf(CB, Handle, "var CSwitchTime = [");
- float fToMsCpu = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu());
- for(uint32_t j = nContextSwitchStart; j != nContextSwitchEnd; j = (j+1) % MICROPROFILE_CONTEXT_SWITCH_BUFFER_SIZE)
- {
- MicroProfileContextSwitch CS = S.ContextSwitch[j];
- float fTime = MicroProfileLogTickDifference(nTickStart, CS.nTicks) * fToMsCpu;
- MicroProfilePrintf(CB, Handle, "%f,", fTime);
- }
- MicroProfilePrintf(CB, Handle, "];\n");
- uint32_t nWrittenAfter = S.nWebServerDataSent;
- MicroProfilePrintf(CB, Handle, "//CSwitch Size %d\n", nWrittenAfter - nWrittenBefore);
- for(size_t i = 0; i < g_MicroProfileHtml_end_count; ++i)
- {
- CB(Handle, g_MicroProfileHtml_end_sizes[i]-1, g_MicroProfileHtml_end[i]);
- }
- uint32_t* nGroupCounter = (uint32_t*)alloca(sizeof(uint32_t)* S.nGroupCount);
- memset(nGroupCounter, 0, sizeof(uint32_t) * S.nGroupCount);
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- uint32_t nGroupIndex = S.TimerInfo[i].nGroupIndex;
- nGroupCounter[nGroupIndex] += nTimerCounter[i];
- }
- uint32_t* nGroupCounterSort = (uint32_t*)alloca(sizeof(uint32_t)* S.nGroupCount);
- uint32_t* nTimerCounterSort = (uint32_t*)alloca(sizeof(uint32_t)* S.nTotalTimers);
- for(uint32_t i = 0; i < S.nGroupCount; ++i)
- {
- nGroupCounterSort[i] = i;
- }
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- nTimerCounterSort[i] = i;
- }
- std::sort(nGroupCounterSort, nGroupCounterSort + S.nGroupCount,
- [nGroupCounter](const uint32_t l, const uint32_t r)
- {
- return nGroupCounter[l] > nGroupCounter[r];
- }
- );
- std::sort(nTimerCounterSort, nTimerCounterSort + S.nTotalTimers,
- [nTimerCounter](const uint32_t l, const uint32_t r)
- {
- return nTimerCounter[l] > nTimerCounter[r];
- }
- );
- MicroProfilePrintf(CB, Handle, "\n<!--\nMarker Per Group\n");
- for(uint32_t i = 0; i < S.nGroupCount; ++i)
- {
- uint32_t idx = nGroupCounterSort[i];
- MicroProfilePrintf(CB, Handle, "%8d:%s\n", nGroupCounter[idx], S.GroupInfo[idx].pName);
- }
- MicroProfilePrintf(CB, Handle, "Marker Per Timer\n");
- for(uint32_t i = 0; i < S.nTotalTimers; ++i)
- {
- uint32_t idx = nTimerCounterSort[i];
- MicroProfilePrintf(CB, Handle, "%8d:%s(%s)\n", nTimerCounter[idx], S.TimerInfo[idx].pName, S.GroupInfo[S.TimerInfo[idx].nGroupIndex].pName);
- }
- MicroProfilePrintf(CB, Handle, "\n-->\n");
- S.nActiveGroup = nActiveGroup;
- S.nRunning = nRunning;
- #if MICROPROFILE_DEBUG
- int64_t nTicksEnd = MP_TICK();
- float fMs = fToMsCpu * (nTicksEnd - S.nPauseTicks);
- printf("html dump took %6.2fms\n", fMs);
- #endif
- }
- void MicroProfileWriteFile(void* Handle, size_t nSize, const char* pData)
- {
- fwrite(pData, nSize, 1, (FILE*)Handle);
- }
- void MicroProfileDumpToFile()
- {
- std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
- if(S.nDumpFileNextFrame&1)
- {
- FILE* F = fopen(S.HtmlDumpPath, "w");
- if(F)
- {
- MicroProfileDumpHtml(MicroProfileWriteFile, F, MICROPROFILE_WEBSERVER_MAXFRAMES, S.HtmlDumpPath);
- fclose(F);
- }
- }
- if(S.nDumpFileNextFrame&2)
- {
- FILE* F = fopen(S.CsvDumpPath, "w");
- if(F)
- {
- MicroProfileDumpCsv(MicroProfileWriteFile, F, MICROPROFILE_WEBSERVER_MAXFRAMES);
- fclose(F);
- }
- }
- }
- void MicroProfileFlushSocket(MpSocket Socket)
- {
- send(Socket, &S.WebServerBuffer[0], S.WebServerPut, 0);
- S.WebServerPut = 0;
- }
- void MicroProfileWriteSocket(void* Handle, size_t nSize, const char* pData)
- {
- S.nWebServerDataSent += nSize;
- MpSocket Socket = *(MpSocket*)Handle;
- if(nSize > MICROPROFILE_WEBSERVER_SOCKET_BUFFER_SIZE / 2)
- {
- MicroProfileFlushSocket(Socket);
- send(Socket, pData, nSize, 0);
- }
- else
- {
- memcpy(&S.WebServerBuffer[S.WebServerPut], pData, nSize);
- S.WebServerPut += nSize;
- if(S.WebServerPut > MICROPROFILE_WEBSERVER_SOCKET_BUFFER_SIZE/2)
- {
- MicroProfileFlushSocket(Socket);
- }
- }
- }
- #if MICROPROFILE_MINIZ
- #ifndef MICROPROFILE_COMPRESS_BUFFER_SIZE
- #define MICROPROFILE_COMPRESS_BUFFER_SIZE (256<<10)
- #endif
- #define MICROPROFILE_COMPRESS_CHUNK (MICROPROFILE_COMPRESS_BUFFER_SIZE/2)
- struct MicroProfileCompressedSocketState
- {
- unsigned char DeflateOut[MICROPROFILE_COMPRESS_CHUNK];
- unsigned char DeflateIn[MICROPROFILE_COMPRESS_CHUNK];
- mz_stream Stream;
- MpSocket Socket;
- uint32_t nSize;
- uint32_t nCompressedSize;
- uint32_t nFlushes;
- uint32_t nMemmoveBytes;
- };
- void MicroProfileCompressedSocketFlush(MicroProfileCompressedSocketState* pState)
- {
- mz_stream& Stream = pState->Stream;
- unsigned char* pSendStart = &pState->DeflateOut[0];
- unsigned char* pSendEnd = &pState->DeflateOut[MICROPROFILE_COMPRESS_CHUNK - Stream.avail_out];
- if(pSendStart != pSendEnd)
- {
- send(pState->Socket, (const char*)pSendStart, pSendEnd - pSendStart, 0);
- pState->nCompressedSize += pSendEnd - pSendStart;
- }
- Stream.next_out = &pState->DeflateOut[0];
- Stream.avail_out = MICROPROFILE_COMPRESS_CHUNK;
- }
- void MicroProfileCompressedSocketStart(MicroProfileCompressedSocketState* pState, MpSocket Socket)
- {
- mz_stream& Stream = pState->Stream;
- memset(&Stream, 0, sizeof(Stream));
- Stream.next_out = &pState->DeflateOut[0];
- Stream.avail_out = MICROPROFILE_COMPRESS_CHUNK;
- Stream.next_in = &pState->DeflateIn[0];
- Stream.avail_in = 0;
- mz_deflateInit(&Stream, Z_DEFAULT_COMPRESSION);
- pState->Socket = Socket;
- pState->nSize = 0;
- pState->nCompressedSize = 0;
- pState->nFlushes = 0;
- pState->nMemmoveBytes = 0;
- }
- void MicroProfileCompressedSocketFinish(MicroProfileCompressedSocketState* pState)
- {
- mz_stream& Stream = pState->Stream;
- MicroProfileCompressedSocketFlush(pState);
- int r = mz_deflate(&Stream, MZ_FINISH);
- MP_ASSERT(r == MZ_STREAM_END);
- MicroProfileCompressedSocketFlush(pState);
- r = mz_deflateEnd(&Stream);
- MP_ASSERT(r == MZ_OK);
- }
- void MicroProfileCompressedWriteSocket(void* Handle, size_t nSize, const char* pData)
- {
- MicroProfileCompressedSocketState* pState = (MicroProfileCompressedSocketState*)Handle;
- mz_stream& Stream = pState->Stream;
- const unsigned char* pDeflateInEnd = Stream.next_in + Stream.avail_in;
- const unsigned char* pDeflateInStart = &pState->DeflateIn[0];
- const unsigned char* pDeflateInRealEnd = &pState->DeflateIn[MICROPROFILE_COMPRESS_CHUNK];
- pState->nSize += nSize;
- if(nSize <= pDeflateInRealEnd - pDeflateInEnd)
- {
- memcpy((void*)pDeflateInEnd, pData, nSize);
- Stream.avail_in += nSize;
- MP_ASSERT(Stream.next_in + Stream.avail_in <= pDeflateInRealEnd);
- return;
- }
- int Flush = 0;
- while(nSize)
- {
- pDeflateInEnd = Stream.next_in + Stream.avail_in;
- if(Flush)
- {
- pState->nFlushes++;
- MicroProfileCompressedSocketFlush(pState);
- pDeflateInRealEnd = &pState->DeflateIn[MICROPROFILE_COMPRESS_CHUNK];
- if(pDeflateInEnd == pDeflateInRealEnd)
- {
- if(Stream.avail_in)
- {
- MP_ASSERT(pDeflateInStart != Stream.next_in);
- memmove((void*)pDeflateInStart, Stream.next_in, Stream.avail_in);
- pState->nMemmoveBytes += Stream.avail_in;
- }
- Stream.next_in = pDeflateInStart;
- pDeflateInEnd = Stream.next_in + Stream.avail_in;
- }
- }
- size_t nSpace = pDeflateInRealEnd - pDeflateInEnd;
- size_t nBytes = MicroProfileMin(nSpace, nSize);
- MP_ASSERT(nBytes + pDeflateInEnd <= pDeflateInRealEnd);
- memcpy((void*)pDeflateInEnd, pData, nBytes);
- Stream.avail_in += nBytes;
- nSize -= nBytes;
- pData += nBytes;
- int r = mz_deflate(&Stream, MZ_NO_FLUSH);
- Flush = r == MZ_BUF_ERROR || nBytes == 0 || Stream.avail_out == 0 ? 1 : 0;
- MP_ASSERT(r == MZ_BUF_ERROR || r == MZ_OK);
- if(r == MZ_BUF_ERROR)
- {
- r = mz_deflate(&Stream, MZ_SYNC_FLUSH);
- }
- }
- }
- #endif
- #ifndef MicroProfileSetNonBlocking //fcntl doesnt work on a some unix like platforms..
- void MicroProfileSetNonBlocking(MpSocket Socket, int NonBlocking)
- {
- #ifdef _WIN32
- u_long nonBlocking = NonBlocking ? 1 : 0;
- ioctlsocket(Socket, FIONBIO, &nonBlocking);
- #else
- int Options = fcntl(Socket, F_GETFL);
- if(NonBlocking)
- {
- fcntl(Socket, F_SETFL, Options|O_NONBLOCK);
- }
- else
- {
- fcntl(Socket, F_SETFL, Options&(~O_NONBLOCK));
- }
- #endif
- }
- #endif
- void MicroProfileWebServerStart()
- {
- #ifdef _WIN32
- WSADATA wsa;
- if(WSAStartup(MAKEWORD(2, 2), &wsa))
- {
- S.ListenerSocket = -1;
- return;
- }
- #endif
- S.ListenerSocket = socket(PF_INET, SOCK_STREAM, 6);
- MP_ASSERT(!MP_INVALID_SOCKET(S.ListenerSocket));
- MicroProfileSetNonBlocking(S.ListenerSocket, 1);
- S.nWebServerPort = (uint32_t)-1;
- struct sockaddr_in Addr;
- Addr.sin_family = AF_INET;
- Addr.sin_addr.s_addr = INADDR_ANY;
- for(int i = 0; i < 20; ++i)
- {
- Addr.sin_port = htons(MICROPROFILE_WEBSERVER_PORT+i);
- if(0 == bind(S.ListenerSocket, (sockaddr*)&Addr, sizeof(Addr)))
- {
- S.nWebServerPort = MICROPROFILE_WEBSERVER_PORT+i;
- break;
- }
- }
- listen(S.ListenerSocket, 8);
- }
- void MicroProfileWebServerStop()
- {
- #ifdef _WIN32
- closesocket(S.ListenerSocket);
- WSACleanup();
- #else
- close(S.ListenerSocket);
- #endif
- }
- int MicroProfileParseGet(const char* pGet)
- {
- const char* pStart = pGet;
- while(*pGet != '\0')
- {
- if(*pGet < '0' || *pGet > '9')
- return 0;
- pGet++;
- }
- int nFrames = atoi(pStart);
- if(nFrames)
- {
- return nFrames;
- }
- else
- {
- return MICROPROFILE_WEBSERVER_MAXFRAMES;
- }
- }
- bool MicroProfileWebServerUpdate()
- {
- MICROPROFILE_SCOPEI("MicroProfile", "Webserver-update", -1);
- MpSocket Connection = accept(S.ListenerSocket, 0, 0);
- bool bServed = false;
- if(!MP_INVALID_SOCKET(Connection))
- {
- std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
- char Req[8192];
- MicroProfileSetNonBlocking(Connection, 0);
- int nReceived = recv(Connection, Req, sizeof(Req)-1, 0);
- if(nReceived > 0)
- {
- Req[nReceived] = '\0';
- #if MICROPROFILE_MINIZ
- #define MICROPROFILE_HTML_HEADER "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nContent-Encoding: deflate\r\nExpires: Tue, 01 Jan 2199 16:00:00 GMT\r\n\r\n"
- #else
- #define MICROPROFILE_HTML_HEADER "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nExpires: Tue, 01 Jan 2199 16:00:00 GMT\r\n\r\n"
- #endif
- char* pHttp = strstr(Req, "HTTP/");
- char* pGet = strstr(Req, "GET /");
- char* pHost = strstr(Req, "Host: ");
- auto Terminate = [](char* pString)
- {
- char* pEnd = pString;
- while(*pEnd != '\0')
- {
- if(*pEnd == '\r' || *pEnd == '\n' || *pEnd == ' ')
- {
- *pEnd = '\0';
- return;
- }
- pEnd++;
- }
- };
- if(pHost)
- {
- pHost += sizeof("Host: ")-1;
- Terminate(pHost);
- }
- if(pHttp && pGet)
- {
- *pHttp = '\0';
- pGet += sizeof("GET /")-1;
- Terminate(pGet);
- int nFrames = MicroProfileParseGet(pGet);
- if(nFrames)
- {
- uint64_t nTickStart = MP_TICK();
- send(Connection, MICROPROFILE_HTML_HEADER, sizeof(MICROPROFILE_HTML_HEADER)-1, 0);
- uint64_t nDataStart = S.nWebServerDataSent;
- S.WebServerPut = 0;
- #if 0 == MICROPROFILE_MINIZ
- MicroProfileDumpHtml(MicroProfileWriteSocket, &Connection, nFrames, pHost);
- uint64_t nDataEnd = S.nWebServerDataSent;
- uint64_t nTickEnd = MP_TICK();
- uint64_t nDiff = (nTickEnd - nTickStart);
- float fMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu()) * nDiff;
- int nKb = ((nDataEnd-nDataStart)>>10) + 1;
- int nCompressedKb = nKb;
- MicroProfilePrintf(MicroProfileWriteSocket, &Connection, "\n<!-- Sent %dkb in %.2fms-->\n\n",nKb, fMs);
- MicroProfileFlushSocket(Connection);
- #else
- MicroProfileCompressedSocketState CompressState;
- MicroProfileCompressedSocketStart(&CompressState, Connection);
- MicroProfileDumpHtml(MicroProfileCompressedWriteSocket, &CompressState, nFrames, pHost);
- S.nWebServerDataSent += CompressState.nSize;
- uint64_t nDataEnd = S.nWebServerDataSent;
- uint64_t nTickEnd = MP_TICK();
- uint64_t nDiff = (nTickEnd - nTickStart);
- float fMs = MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu()) * nDiff;
- int nKb = ((nDataEnd-nDataStart)>>10) + 1;
- int nCompressedKb = ((CompressState.nCompressedSize)>>10) + 1;
- MicroProfilePrintf(MicroProfileCompressedWriteSocket, &CompressState, "\n<!-- Sent %dkb(compressed %dkb) in %.2fms-->\n\n", nKb, nCompressedKb, fMs);
- MicroProfileCompressedSocketFinish(&CompressState);
- MicroProfileFlushSocket(Connection);
- #endif
- #if MICROPROFILE_DEBUG
- printf("\n<!-- Sent %dkb(compressed %dkb) in %.2fms-->\n\n", nKb, nCompressedKb, fMs);
- #endif
- }
- }
- }
- #ifdef _WIN32
- closesocket(Connection);
- #else
- close(Connection);
- #endif
- }
- return bServed;
- }
- #endif
- #if MICROPROFILE_CONTEXT_SWITCH_TRACE
- //functions that need to be implemented per platform.
- void* MicroProfileTraceThread(void* unused);
- bool MicroProfileIsLocalThread(uint32_t nThreadId);
- void MicroProfileStartContextSwitchTrace()
- {
- if(!S.bContextSwitchRunning)
- {
- S.bContextSwitchRunning = true;
- S.bContextSwitchStop = false;
- MicroProfileThreadStart(&S.ContextSwitchThread, MicroProfileTraceThread);
- }
- }
- void MicroProfileStopContextSwitchTrace()
- {
- if(S.bContextSwitchRunning)
- {
- S.bContextSwitchStop = true;
- MicroProfileThreadJoin(&S.ContextSwitchThread);
- }
- }
- #ifdef _WIN32
- #define INITGUID
- #include <evntrace.h>
- #include <evntcons.h>
- #include <strsafe.h>
- static GUID g_MicroProfileThreadClassGuid = { 0x3d6fa8d1, 0xfe05, 0x11d0, 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c };
- struct MicroProfileSCSwitch
- {
- uint32_t NewThreadId;
- uint32_t OldThreadId;
- int8_t NewThreadPriority;
- int8_t OldThreadPriority;
- uint8_t PreviousCState;
- int8_t SpareByte;
- int8_t OldThreadWaitReason;
- int8_t OldThreadWaitMode;
- int8_t OldThreadState;
- int8_t OldThreadWaitIdealProcessor;
- uint32_t NewThreadWaitTime;
- uint32_t Reserved;
- };
- VOID WINAPI MicroProfileContextSwitchCallback(PEVENT_TRACE pEvent)
- {
- if (pEvent->Header.Guid == g_MicroProfileThreadClassGuid)
- {
- if (pEvent->Header.Class.Type == 36)
- {
- MicroProfileSCSwitch* pCSwitch = (MicroProfileSCSwitch*) pEvent->MofData;
- if ((pCSwitch->NewThreadId != 0) || (pCSwitch->OldThreadId != 0))
- {
- MicroProfileContextSwitch Switch;
- Switch.nThreadOut = pCSwitch->OldThreadId;
- Switch.nThreadIn = pCSwitch->NewThreadId;
- Switch.nCpu = pEvent->BufferContext.ProcessorNumber;
- Switch.nTicks = pEvent->Header.TimeStamp.QuadPart;
- MicroProfileContextSwitchPut(&Switch);
- }
- }
- }
- }
- ULONG WINAPI MicroProfileBufferCallback(PEVENT_TRACE_LOGFILE Buffer)
- {
- return (S.bContextSwitchStop || !S.bContextSwitchRunning) ? FALSE : TRUE;
- }
- struct MicroProfileKernelTraceProperties : public EVENT_TRACE_PROPERTIES
- {
- char dummy[sizeof(KERNEL_LOGGER_NAME)];
- };
- void MicroProfileContextSwitchShutdownTrace()
- {
- TRACEHANDLE SessionHandle = 0;
- MicroProfileKernelTraceProperties sessionProperties;
- ZeroMemory(&sessionProperties, sizeof(sessionProperties));
- sessionProperties.Wnode.BufferSize = sizeof(sessionProperties);
- sessionProperties.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
- sessionProperties.Wnode.ClientContext = 1; //QPC clock resolution
- sessionProperties.Wnode.Guid = SystemTraceControlGuid;
- sessionProperties.BufferSize = 1;
- sessionProperties.NumberOfBuffers = 128;
- sessionProperties.EnableFlags = EVENT_TRACE_FLAG_CSWITCH;
- sessionProperties.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
- sessionProperties.MaximumFileSize = 0;
- sessionProperties.LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
- sessionProperties.LogFileNameOffset = 0;
- EVENT_TRACE_LOGFILE log;
- ZeroMemory(&log, sizeof(log));
- log.LoggerName = KERNEL_LOGGER_NAME;
- log.ProcessTraceMode = 0;
- TRACEHANDLE hLog = OpenTrace(&log);
- if (hLog)
- {
- ControlTrace(SessionHandle, KERNEL_LOGGER_NAME, &sessionProperties, EVENT_TRACE_CONTROL_STOP);
- }
- CloseTrace(hLog);
- }
- void* MicroProfileTraceThread(void* unused)
- {
- MicroProfileContextSwitchShutdownTrace();
- ULONG status = ERROR_SUCCESS;
- TRACEHANDLE SessionHandle = 0;
- MicroProfileKernelTraceProperties sessionProperties;
- ZeroMemory(&sessionProperties, sizeof(sessionProperties));
- sessionProperties.Wnode.BufferSize = sizeof(sessionProperties);
- sessionProperties.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
- sessionProperties.Wnode.ClientContext = 1; //QPC clock resolution
- sessionProperties.Wnode.Guid = SystemTraceControlGuid;
- sessionProperties.BufferSize = 1;
- sessionProperties.NumberOfBuffers = 128;
- sessionProperties.EnableFlags = EVENT_TRACE_FLAG_CSWITCH|EVENT_TRACE_FLAG_PROCESS;
- sessionProperties.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
- sessionProperties.MaximumFileSize = 0;
- sessionProperties.LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
- sessionProperties.LogFileNameOffset = 0;
- status = StartTrace((PTRACEHANDLE) &SessionHandle, KERNEL_LOGGER_NAME, &sessionProperties);
- if (ERROR_SUCCESS != status)
- {
- S.bContextSwitchRunning = false;
- return 0;
- }
- EVENT_TRACE_LOGFILE log;
- ZeroMemory(&log, sizeof(log));
- log.LoggerName = KERNEL_LOGGER_NAME;
- log.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_RAW_TIMESTAMP;
- log.EventCallback = MicroProfileContextSwitchCallback;
- log.BufferCallback = MicroProfileBufferCallback;
- TRACEHANDLE hLog = OpenTrace(&log);
- ProcessTrace(&hLog, 1, 0, 0);
- CloseTrace(hLog);
- MicroProfileContextSwitchShutdownTrace();
- S.bContextSwitchRunning = false;
- return 0;
- }
- bool MicroProfileIsLocalThread(uint32_t nThreadId)
- {
- HANDLE h = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, nThreadId);
- if(h == NULL)
- return false;
- DWORD hProcess = GetProcessIdOfThread(h);
- CloseHandle(h);
- return GetCurrentProcessId() == hProcess;
- }
- #elif defined(__APPLE__)
- #include <sys/time.h>
- void* MicroProfileTraceThread(void* unused)
- {
- FILE* pFile = fopen("mypipe", "r");
- if(!pFile)
- {
- printf("CONTEXT SWITCH FAILED TO OPEN FILE: make sure to run dtrace script\n");
- S.bContextSwitchRunning = false;
- return 0;
- }
- printf("STARTING TRACE THREAD\n");
- char* pLine = 0;
- size_t cap = 0;
- size_t len = 0;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- uint64_t nsSinceEpoch = ((uint64_t)(tv.tv_sec) * 1000000 + (uint64_t)(tv.tv_usec)) * 1000;
- uint64_t nTickEpoch = MP_TICK();
- uint32_t nLastThread[MICROPROFILE_MAX_CONTEXT_SWITCH_THREADS] = {0};
- mach_timebase_info_data_t sTimebaseInfo;
- mach_timebase_info(&sTimebaseInfo);
- S.bContextSwitchRunning = true;
- uint64_t nProcessed = 0;
- uint64_t nProcessedLast = 0;
- while((len = getline(&pLine, &cap, pFile))>0 && !S.bContextSwitchStop)
- {
- nProcessed += len;
- if(nProcessed - nProcessedLast > 10<<10)
- {
- nProcessedLast = nProcessed;
- printf("processed %llukb %llukb\n", (nProcessed-nProcessedLast)>>10,nProcessed >>10);
- }
- char* pX = strchr(pLine, 'X');
- if(pX)
- {
- int cpu = atoi(pX+1);
- char* pX2 = strchr(pX + 1, 'X');
- char* pX3 = strchr(pX2 + 1, 'X');
- int thread = atoi(pX2+1);
- char* lala;
- int64_t timestamp = strtoll(pX3 + 1, &lala, 10);
- MicroProfileContextSwitch Switch;
- //convert to ticks.
- uint64_t nDeltaNsSinceEpoch = timestamp - nsSinceEpoch;
- uint64_t nDeltaTickSinceEpoch = sTimebaseInfo.numer * nDeltaNsSinceEpoch / sTimebaseInfo.denom;
- uint64_t nTicks = nDeltaTickSinceEpoch + nTickEpoch;
- if(cpu < MICROPROFILE_MAX_CONTEXT_SWITCH_THREADS)
- {
- Switch.nThreadOut = nLastThread[cpu];
- Switch.nThreadIn = thread;
- nLastThread[cpu] = thread;
- Switch.nCpu = cpu;
- Switch.nTicks = nTicks;
- MicroProfileContextSwitchPut(&Switch);
- }
- }
- }
- printf("EXITING TRACE THREAD\n");
- S.bContextSwitchRunning = false;
- return 0;
- }
- bool MicroProfileIsLocalThread(uint32_t nThreadId)
- {
- return false;
- }
- #endif
- #else
- bool MicroProfileIsLocalThread([[maybe_unused]] uint32_t nThreadId) { return false; }
- void MicroProfileStopContextSwitchTrace(){}
- void MicroProfileStartContextSwitchTrace(){}
- #endif
- #if MICROPROFILE_GPU_TIMERS_D3D11
- uint32_t MicroProfileGpuInsertTimeStamp()
- {
- MicroProfileD3D11Frame& Frame = S.GPU.m_QueryFrames[S.GPU.m_nQueryFrame];
- if(Frame.m_nRateQueryStarted)
- {
- uint32_t nCurrent = (Frame.m_nQueryStart + Frame.m_nQueryCount) % MICROPROFILE_D3D_MAX_QUERIES;
- uint32_t nNext = (nCurrent + 1) % MICROPROFILE_D3D_MAX_QUERIES;
- if(nNext != S.GPU.m_nQueryGet)
- {
- Frame.m_nQueryCount++;
- ID3D11Query* pQuery = (ID3D11Query*)S.GPU.m_pQueries[nCurrent];
- ID3D11DeviceContext* pContext = (ID3D11DeviceContext*)S.GPU.m_pDeviceContext;
- pContext->End(pQuery);
- S.GPU.m_nQueryPut = nNext;
- return nCurrent;
- }
- }
- return (uint32_t)-1;
- }
- uint64_t MicroProfileGpuGetTimeStamp(uint32_t nIndex)
- {
- if(nIndex == (uint32_t)-1)
- {
- return (uint64_t)-1;
- }
- int64_t nResult = S.GPU.m_nQueryResults[nIndex];
- MP_ASSERT(nResult != -1);
- return nResult;
- }
- bool MicroProfileGpuGetData(void* pQuery, void* pData, uint32_t nDataSize)
- {
- HRESULT hr;
- do
- {
- hr = ((ID3D11DeviceContext*)S.GPU.m_pDeviceContext)->GetData((ID3D11Query*)pQuery, pData, nDataSize, 0);
- }while(hr == S_FALSE);
- switch(hr)
- {
- case DXGI_ERROR_DEVICE_REMOVED:
- case DXGI_ERROR_INVALID_CALL:
- case E_INVALIDARG:
- MP_BREAK();
- return false;
- }
- return true;
- }
- uint64_t MicroProfileTicksPerSecondGpu()
- {
- return S.GPU.m_nQueryFrequency;
- }
- void MicroProfileGpuFlip()
- {
- MicroProfileD3D11Frame& CurrentFrame = S.GPU.m_QueryFrames[S.GPU.m_nQueryFrame];
- ID3D11DeviceContext* pContext = (ID3D11DeviceContext*)S.GPU.m_pDeviceContext;
- if(CurrentFrame.m_nRateQueryStarted)
- {
- pContext->End((ID3D11Query*)CurrentFrame.m_pRateQuery);
- }
- uint32_t nNextFrame = (S.GPU.m_nQueryFrame + 1) % MICROPROFILE_GPU_FRAME_DELAY;
- MicroProfileD3D11Frame& OldFrame = S.GPU.m_QueryFrames[nNextFrame];
- if(OldFrame.m_nRateQueryStarted)
- {
- struct RateQueryResult
- {
- uint64_t nFrequency;
- BOOL bDisjoint;
- };
- RateQueryResult Result;
- if(MicroProfileGpuGetData(OldFrame.m_pRateQuery, &Result, sizeof(Result)))
- {
- if(S.GPU.m_nQueryFrequency != (int64_t)Result.nFrequency)
- {
- if(S.GPU.m_nQueryFrequency)
- {
- OutputDebugString("Query freq changing");
- }
- S.GPU.m_nQueryFrequency = Result.nFrequency;
- }
- uint32_t nStart = OldFrame.m_nQueryStart;
- uint32_t nCount = OldFrame.m_nQueryCount;
- for(uint32_t i = 0; i < nCount; ++i)
- {
- uint32_t nIndex = (i + nStart) % MICROPROFILE_D3D_MAX_QUERIES;
- if(!MicroProfileGpuGetData(S.GPU.m_pQueries[nIndex], &S.GPU.m_nQueryResults[nIndex], sizeof(uint64_t)))
- {
- S.GPU.m_nQueryResults[nIndex] = -1;
- }
- }
- }
- else
- {
- uint32_t nStart = OldFrame.m_nQueryStart;
- uint32_t nCount = OldFrame.m_nQueryCount;
- for(uint32_t i = 0; i < nCount; ++i)
- {
- uint32_t nIndex = (i + nStart) % MICROPROFILE_D3D_MAX_QUERIES;
- S.GPU.m_nQueryResults[nIndex] = -1;
- }
- }
- S.GPU.m_nQueryGet = (OldFrame.m_nQueryStart + OldFrame.m_nQueryCount) % MICROPROFILE_D3D_MAX_QUERIES;
- }
- S.GPU.m_nQueryFrame = nNextFrame;
- MicroProfileD3D11Frame& NextFrame = S.GPU.m_QueryFrames[nNextFrame];
- pContext->Begin((ID3D11Query*)NextFrame.m_pRateQuery);
- NextFrame.m_nQueryStart = S.GPU.m_nQueryPut;
- NextFrame.m_nQueryCount = 0;
- NextFrame.m_nRateQueryStarted = 1;
- }
- void MicroProfileGpuInitD3D11(void* pDevice_, void* pDeviceContext_)
- {
- ID3D11Device* pDevice = (ID3D11Device*)pDevice_;
- ID3D11DeviceContext* pDeviceContext = (ID3D11DeviceContext*)pDeviceContext_;
- S.GPU.m_pDeviceContext = pDeviceContext_;
- D3D11_QUERY_DESC Desc;
- Desc.MiscFlags = 0;
- Desc.Query = D3D11_QUERY_TIMESTAMP;
- for(uint32_t i = 0; i < MICROPROFILE_D3D_MAX_QUERIES; ++i)
- {
- HRESULT hr = pDevice->CreateQuery(&Desc, (ID3D11Query**)&S.GPU.m_pQueries[i]);
- MP_ASSERT(hr == S_OK);
- S.GPU.m_nQueryResults[i] = -1;
- }
- S.GPU.m_nQueryPut = 0;
- S.GPU.m_nQueryGet = 0;
- S.GPU.m_nQueryFrame = 0;
- S.GPU.m_nQueryFrequency = 0;
- Desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
- for(uint32_t i = 0; i < MICROPROFILE_GPU_FRAME_DELAY; ++i)
- {
- S.GPU.m_QueryFrames[i].m_nQueryStart = 0;
- S.GPU.m_QueryFrames[i].m_nQueryCount = 0;
- S.GPU.m_QueryFrames[i].m_nRateQueryStarted = 0;
- HRESULT hr = pDevice->CreateQuery(&Desc, (ID3D11Query**)&S.GPU.m_QueryFrames[i].m_pRateQuery);
- MP_ASSERT(hr == S_OK);
- }
- }
- void MicroProfileGpuShutdown()
- {
- for(uint32_t i = 0; i < MICROPROFILE_D3D_MAX_QUERIES; ++i)
- {
- ((ID3D11Query*)&S.GPU.m_pQueries[i])->Release();
- S.GPU.m_pQueries[i] = 0;
- }
- for(uint32_t i = 0; i < MICROPROFILE_GPU_FRAME_DELAY; ++i)
- {
- ((ID3D11Query*)S.GPU.m_QueryFrames[i].m_pRateQuery)->Release();
- S.GPU.m_QueryFrames[i].m_pRateQuery = 0;
- }
- }
- int MicroProfileGetGpuTickReference(int64_t* pOutCPU, int64_t* pOutGpu)
- {
- return 0;
- }
- #elif MICROPROFILE_GPU_TIMERS_GL
- void MicroProfileGpuInitGL()
- {
- S.GPU.GLTimerPos = 0;
- glGenQueries(MICROPROFILE_GL_MAX_QUERIES, &S.GPU.GLTimers[0]);
- }
- uint32_t MicroProfileGpuInsertTimeStamp()
- {
- uint32_t nIndex = (S.GPU.GLTimerPos+1)%MICROPROFILE_GL_MAX_QUERIES;
- glQueryCounter(S.GPU.GLTimers[nIndex], GL_TIMESTAMP);
- S.GPU.GLTimerPos = nIndex;
- return nIndex;
- }
- uint64_t MicroProfileGpuGetTimeStamp(uint32_t nKey)
- {
- uint64_t result;
- glGetQueryObjectui64v(S.GPU.GLTimers[nKey], GL_QUERY_RESULT, &result);
- return result;
- }
- uint64_t MicroProfileTicksPerSecondGpu()
- {
- return 1000000000ll;
- }
- int MicroProfileGetGpuTickReference(int64_t* pOutCpu, int64_t* pOutGpu)
- {
- int64_t nGpuTimeStamp;
- glGetInteger64v(GL_TIMESTAMP, &nGpuTimeStamp);
- if(nGpuTimeStamp)
- {
- *pOutCpu = MP_TICK();
- *pOutGpu = nGpuTimeStamp;
- #if 0 //debug test if timestamp diverges
- static int64_t nTicksPerSecondCpu = MicroProfileTicksPerSecondCpu();
- static int64_t nTicksPerSecondGpu = MicroProfileTicksPerSecondGpu();
- static int64_t nGpuStart = 0;
- static int64_t nCpuStart = 0;
- if(!nCpuStart)
- {
- nCpuStart = *pOutCpu;
- nGpuStart = *pOutGpu;
- }
- static int nCountDown = 100;
- if(0 == nCountDown--)
- {
- int64_t nCurCpu = *pOutCpu;
- int64_t nCurGpu = *pOutGpu;
- double fDistanceCpu = (nCurCpu - nCpuStart) / (double)nTicksPerSecondCpu;
- double fDistanceGpu = (nCurGpu - nGpuStart) / (double)nTicksPerSecondGpu;
- char buf[254];
- snprintf(buf, sizeof(buf)-1,"Distance %f %f diff %f\n", fDistanceCpu, fDistanceGpu, fDistanceCpu-fDistanceGpu);
- OutputDebugString(buf);
- nCountDown = 100;
- }
- #endif
- return 1;
- }
- return 0;
- }
- #endif
- #undef S
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- #endif
- #endif
- #ifdef MICROPROFILE_EMBED_HTML
- #include "microprofile_html.h"
- #endif
|