llfasttimerview.cpp 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637
  1. /**
  2. * @file llfasttimerview.cpp
  3. * @brief LLFastTimerView class implementation
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewergpl$
  6. *
  7. * Copyright (c) 2004-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llfasttimerview.h"
  34. #if TRACY_ENABLE
  35. # include "lldir.h"
  36. # include "llprocesslauncher.h"
  37. #endif
  38. #if LL_FAST_TIMERS_ENABLED
  39. #include "llgl.h"
  40. #include "llrender.h"
  41. #include "llappviewer.h"
  42. #include "llviewercontrol.h"
  43. #include "llviewertexturelist.h"
  44. #include "llviewerwindow.h"
  45. LLFastTimerView* gFastTimerViewp = NULL;
  46. constexpr S32 MAX_VISIBLE_HISTORY = 10;
  47. constexpr S32 LINE_GRAPH_HEIGHT = 240;
  48. constexpr S32 FASTTIMERVIEW_LEFT = 50;
  49. constexpr S32 FASTTIMERVIEW_TOP_DELTA = 50;
  50. struct ft_display_info
  51. {
  52. S32 timer;
  53. const char* desc;
  54. const LLColor4* color; // Auto-initialized
  55. S32 disabled; // Auto-initialized
  56. S32 level; // Calculated based on leading spaces in desc
  57. S32 parent; // Calculated
  58. };
  59. static struct ft_display_info ft_display_table[] =
  60. {
  61. { LLFastTimer::FTM_FRAME, "Frame" },
  62. { LLFastTimer::FTM_MEMORY_CHECK, " Memory check" },
  63. { LLFastTimer::FTM_MESSAGES, " System Messages" },
  64. #if LL_WINDOWS // Not used for Linux and Darwin
  65. { LLFastTimer::FTM_MOUSEHANDLER, " Mouse" },
  66. { LLFastTimer::FTM_KEYHANDLER, " Keyboard" },
  67. #endif
  68. { LLFastTimer::FTM_POST_DISPLAY, " Post-display" },
  69. { LLFastTimer::FTM_FETCH, " Texture Fetch" },
  70. { LLFastTimer::FTM_TEXTURE_CACHE, " Texture Cache" },
  71. { LLFastTimer::FTM_DECODE, " Texture Decode" },
  72. { LLFastTimer::FTM_FPS_LIMITING, " FPS limiting" },
  73. { LLFastTimer::FTM_SLEEP, " Sleep" },
  74. { LLFastTimer::FTM_IDLE, " Idle" },
  75. { LLFastTimer::FTM_RLV, " Restrained Love" },
  76. { LLFastTimer::FTM_IDLE_LUA_THREAD, " Lua threads" },
  77. { LLFastTimer::FTM_INVENTORY, " Inventory Update" },
  78. { LLFastTimer::FTM_AUTO_SELECT, " Open and Select" },
  79. { LLFastTimer::FTM_FILTER, " Filter" },
  80. { LLFastTimer::FTM_ARRANGE, " Arrange" },
  81. { LLFastTimer::FTM_REFRESH, " Refresh" },
  82. { LLFastTimer::FTM_SORT, " Sort" },
  83. { LLFastTimer::FTM_RESET_DRAWORDER, " ResetDrawOrder" },
  84. { LLFastTimer::FTM_WORLD_UPDATE, " World Update" },
  85. { LLFastTimer::FTM_UPDATE_MOVE, " Move Objects" },
  86. { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance" },
  87. { LLFastTimer::FTM_SIMULATE_PARTICLES, " Particle Sim" },
  88. { LLFastTimer::FTM_SIM_PART_SORT, " Particle Sim Sort" },
  89. { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object List Update" },
  90. { LLFastTimer::FTM_OBJECTLIST_COPY, " Object List Copy" },
  91. { LLFastTimer::FTM_AVATAR_UPDATE, " Avatars" },
  92. { LLFastTimer::FTM_AV_CHECK_TEX_LOADING, " Check Loading Tex." },
  93. { LLFastTimer::FTM_AV_RELEASE_OLD_TEX, " Release Old Tex." },
  94. { LLFastTimer::FTM_AV_UPDATE_TEXTURES, " Update Textures" },
  95. { LLFastTimer::FTM_JOINT_UPDATE, " Joints" },
  96. { LLFastTimer::FTM_PHYSICS_UPDATE, " Physics" },
  97. { LLFastTimer::FTM_ATTACHMENT_UPDATE, " Attachments" },
  98. { LLFastTimer::FTM_UPDATE_ANIMATION, " Animation" },
  99. { LLFastTimer::FTM_UPDATE_MOTIONS, " Motions" },
  100. { LLFastTimer::FTM_MOTION_ON_UPDATE, " On Update" },
  101. { LLFastTimer::FTM_APPLY_MORPH_TARGET, " Apply Morph" },
  102. { LLFastTimer::FTM_POLYSKELETAL_DISTORTION_APPLY, " Skel Distortion" },
  103. { LLFastTimer::FTM_UPDATE_HIDDEN_ANIMATION, " Hidden Anim" },
  104. { LLFastTimer::FTM_FLEXIBLE_UPDATE, " Flex Update" },
  105. { LLFastTimer::FTM_LOD_UPDATE, " LOD Update" },
  106. { LLFastTimer::FTM_CULL_AVATARS, " Cull Avatars" },
  107. { LLFastTimer::FTM_UPDATE_RIGGED_VOLUME, " Update Rigged" },
  108. { LLFastTimer::FTM_RIGGED_OCTREE, " Octree" },
  109. { LLFastTimer::FTM_CLEANUP, " Cleanup" },
  110. { LLFastTimer::FTM_CLEANUP_DRAWABLE, " Cleanup Drawable" },
  111. { LLFastTimer::FTM_UNLINK, " Unlink" },
  112. { LLFastTimer::FTM_REMOVE_FROM_LIGHT_SET, " Light Set" },
  113. { LLFastTimer::FTM_REMOVE_FROM_MOVE_LIST, " MoveList" },
  114. { LLFastTimer::FTM_REMOVE_FROM_SPATIAL_PARTITION, " Spatial Part." },
  115. { LLFastTimer::FTM_AREASEARCH_UPDATE, " Area Search Update" },
  116. { LLFastTimer::FTM_REGION_UPDATE, " Region Update" },
  117. { LLFastTimer::FTM_UPD_LANDPATCHES, " Land Patches" },
  118. { LLFastTimer::FTM_UPD_PARCELOVERLAY, " Parcel Overlays" },
  119. { LLFastTimer::FTM_UPD_CACHEDOBJECTS, " Cached Objects" },
  120. { LLFastTimer::FTM_NETWORK, " Network" },
  121. { LLFastTimer::FTM_IDLE_NETWORK, " Decode Msgs" },
  122. { LLFastTimer::FTM_PROCESS_MESSAGES, " Process Msgs" },
  123. { LLFastTimer::FTM_PROCESS_OBJECTS, " Process Objects" },
  124. { LLFastTimer::FTM_CREATE_OBJECT, " Create Obj" },
  125. // { LLFastTimer::FTM_LOAD_AVATAR, " Load Avatar" },
  126. { LLFastTimer::FTM_PROCESS_IMAGES, " Image Updates" },
  127. { LLFastTimer::FTM_SHIFT_OBJECTS, " Shift Objects" },
  128. { LLFastTimer::FTM_PIPELINE_SHIFT, " Pipeline Shift" },
  129. { LLFastTimer::FTM_SHIFT_DRAWABLE, " Shift Drawable" },
  130. { LLFastTimer::FTM_SHIFT_OCTREE, " Shift Octree" },
  131. { LLFastTimer::FTM_SHIFT_HUD, " Shift HUD" },
  132. { LLFastTimer::FTM_REGION_SHIFT, " Region Shift" },
  133. { LLFastTimer::FTM_PUMP, " Pump" },
  134. { LLFastTimer::FTM_PUMP_EVENT, " Events" },
  135. { LLFastTimer::FTM_PUMP_SERVICE, " Service" },
  136. { LLFastTimer::FTM_PUMP_IO, " Pump IO" },
  137. { LLFastTimer::FTM_PROCESS_SOCKET_READER, " Socket Reader" },
  138. { LLFastTimer::FTM_PROCESS_SOCKET_WRITER, " Socket Writer" },
  139. { LLFastTimer::FTM_PROCESS_SERVER_SOCKET, " Server Socket" },
  140. { LLFastTimer::FTM_PUMP_CALLBACK_CHAIN, " Chain" },
  141. { LLFastTimer::FTM_AUDIO_UPDATE, " Audio Update" },
  142. { LLFastTimer::FTM_VFILE_WAIT, " VFile Wait" },
  143. { LLFastTimer::FTM_IDLE_CB, " Callbacks" },
  144. { LLFastTimer::FTM_MEDIA_UPDATE, " Media Updates" },
  145. { LLFastTimer::FTM_MEDIA_UPDATE_INTEREST, " Update Interest" },
  146. { LLFastTimer::FTM_MEDIA_DO_UPDATE, " Impl. Update" },
  147. { LLFastTimer::FTM_MEDIA_GET_DATA, " Get Data" },
  148. { LLFastTimer::FTM_MEDIA_SET_SUBIMAGE, " Set Sub-image" },
  149. { LLFastTimer::FTM_MEDIA_CALCULATE_INTEREST, " Compute Interest" },
  150. { LLFastTimer::FTM_MEDIA_SORT, " Priority Sorting" },
  151. { LLFastTimer::FTM_MEDIA_MISC, " Miscellaneous" },
  152. { LLFastTimer::FTM_MEDIA_SORT2, " Distance Sorting" },
  153. { LLFastTimer::FTM_MATERIALS_IDLE, " Materials Updates" },
  154. { LLFastTimer::FTM_IDLE_CB_RADAR, " Radar Updates" },
  155. { LLFastTimer::FTM_RENDER, " Render" },
  156. { LLFastTimer::FTM_PICK, " Pick" },
  157. { LLFastTimer::FTM_HUD_UPDATE, " HUD Update" },
  158. { LLFastTimer::FTM_HUD_EFFECTS, " HUD Effects" },
  159. { LLFastTimer::FTM_HUD_OBJECTS, " HUD Objects" },
  160. { LLFastTimer::FTM_IMPOSTORS_UPDATE, " Impostors Update" },
  161. { LLFastTimer::FTM_IMPOSTOR_MARK_VISIBLE, " Imp. Mark Visible" },
  162. { LLFastTimer::FTM_IMPOSTOR_SETUP, " Impostor Setup" },
  163. { LLFastTimer::FTM_IMPOSTOR_ALLOCATE, " Impostor Allocate" },
  164. { LLFastTimer::FTM_IMPOSTOR_RESIZE, " Impostor Resize" },
  165. { LLFastTimer::FTM_IMPOSTOR_BACKGROUND, " Impostor Background" },
  166. { LLFastTimer::FTM_UPDATE_SKY, " Sky Update" },
  167. { LLFastTimer::FTM_UPDATE_TEXTURES, " Textures" },
  168. { LLFastTimer::FTM_DISPLAY_UPDATE_GEOM, " Update Geometry" },
  169. { LLFastTimer::FTM_GEO_UPDATE, " Geo Update" },
  170. { LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes" },
  171. { LLFastTimer::FTM_GEN_VOLUME, " Gen Volume" },
  172. { LLFastTimer::FTM_GEN_FLEX, " Flexible" },
  173. { LLFastTimer::FTM_DO_FLEXIBLE_UPDATE, " Update" },
  174. { LLFastTimer::FTM_FLEXIBLE_REBUILD, " Rebuild" },
  175. { LLFastTimer::FTM_GEN_TRIANGLES, " Triangles" },
  176. { LLFastTimer::FTM_UPDATE_TREE, " Tree" },
  177. { LLFastTimer::FTM_UPDATE_TERRAIN, " Terrain" },
  178. { LLFastTimer::FTM_UPDATE_CLOUDS, " Clouds" },
  179. { LLFastTimer::FTM_UPDATE_GRASS, " Grass" },
  180. { LLFastTimer::FTM_UPDATE_WATER, " Water" },
  181. { LLFastTimer::FTM_UPDATE_PARTICLES, " Particles" },
  182. { LLFastTimer::FTM_GEO_SKY, " Sky" },
  183. { LLFastTimer::FTM_PROCESS_PARTITIONQ, " PartitionQ" },
  184. { LLFastTimer::FTM_PIPELINE_CREATE, " Pipeline Create" },
  185. { LLFastTimer::FTM_UPDATE_WLPARAM, " Windlight Param" },
  186. { LLFastTimer::FTM_CULL, " Object Cull" },
  187. { LLFastTimer::FTM_CULL_VOCACHE, " Cull VO Cache" },
  188. { LLFastTimer::FTM_CULL_REBOUND, " Rebound" },
  189. { LLFastTimer::FTM_FRUSTUM_CULL, " Frustum Cull" },
  190. { LLFastTimer::FTM_OCCLUSION_EARLY_FAIL, " Occl. Early Fail" },
  191. { LLFastTimer::FTM_OCCLUSION_WAIT, " Occlusion Wait" },
  192. { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read" },
  193. { LLFastTimer::FTM_SET_OCCLUSION_STATE, " Occlusion State" },
  194. { LLFastTimer::FTM_IMAGE_UPDATE, " Image Update" },
  195. { LLFastTimer::FTM_IMAGE_UPDATE_CLASS, " Image Class" },
  196. { LLFastTimer::FTM_IMAGE_UPDATE_BUMP, " Image Bump" },
  197. { LLFastTimer::FTM_IMAGE_UPDATE_LIST, " Image List" },
  198. { LLFastTimer::FTM_IMAGE_CALLBACKS, " Image Callbacks" },
  199. { LLFastTimer::FTM_BUMP_SOURCE_STANDARD_LOADED, " Bump Std Loaded" },
  200. { LLFastTimer::FTM_BUMP_GEN_NORMAL, " Gen. Normal Map" },
  201. { LLFastTimer::FTM_BUMP_CREATE_TEXTURE, " Create GL N. Map" },
  202. { LLFastTimer::FTM_BUMP_SOURCE_LOADED, " Bump Src Loaded" },
  203. { LLFastTimer::FTM_BUMP_SOURCE_ENTRIES_UPDATE, " Entries Update" },
  204. { LLFastTimer::FTM_BUMP_SOURCE_MIN_MAX, " Min/Max" },
  205. { LLFastTimer::FTM_BUMP_SOURCE_RGB2LUM, " RGB to Luminance" },
  206. { LLFastTimer::FTM_BUMP_SOURCE_RESCALE, " Rescale" },
  207. { LLFastTimer::FTM_BUMP_SOURCE_CREATE, " Create" },
  208. { LLFastTimer::FTM_BUMP_SOURCE_GEN_NORMAL, " Generate Normal" },
  209. { LLFastTimer::FTM_IMAGE_CREATE, " Image CreateGL" },
  210. { LLFastTimer::FTM_IMAGE_UPDATE_PRIO, " Prioritize Images" },
  211. { LLFastTimer::FTM_IMAGE_FETCH, " Fetch Images" },
  212. { LLFastTimer::FTM_IMAGE_MARK_DIRTY, " Dirty Images" },
  213. { LLFastTimer::FTM_IMAGE_STATS, " Image Stats" },
  214. { LLFastTimer::FTM_TEXTURE_UNBIND, " Texture Unbind" },
  215. { LLFastTimer::FTM_STATESORT, " State Sort" },
  216. { LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable" },
  217. { LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort" },
  218. { LLFastTimer::FTM_REBUILD_PRIORITY_GROUPS, " Rebuild Prio. Grps" },
  219. { LLFastTimer::FTM_REBUILD_MESH, " Rebuild Mesh Obj." },
  220. { LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild" },
  221. { LLFastTimer::FTM_ADD_GEOMETRY_COUNT, " Add Geometry" },
  222. { LLFastTimer::FTM_CREATE_VB, " Create VB" },
  223. { LLFastTimer::FTM_GET_GEOMETRY, " Get Geometry" },
  224. { LLFastTimer::FTM_REBUILD_VOLUME_FACE_LIST, " Build Face List" },
  225. { LLFastTimer::FTM_VOLUME_TEXTURES, " Volume Textures" },
  226. { LLFastTimer::FTM_REBUILD_VOLUME_GEN_DRAW_INFO, " Gen Draw Info" },
  227. { LLFastTimer::FTM_GEN_DRAW_INFO_SORT, " Face Sort" },
  228. { LLFastTimer::FTM_GEN_DRAW_INFO_FACE_SIZE, " Face Sizing" },
  229. { LLFastTimer::FTM_REGISTER_FACE, " Register Face" },
  230. { LLFastTimer::FTM_REBUILD_TERRAIN_VB, " Terrain" },
  231. { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass" },
  232. { LLFastTimer::FTM_REBUILD_PARTICLE_VBO, " Particle VB0" },
  233. { LLFastTimer::FTM_REBUILD_PARTICLE_GEOM, " Get Geometry" },
  234. { LLFastTimer::FTM_GEN_SUN_SHADOW, " Gen Sun Shadow" },
  235. { LLFastTimer::FTM_BIND_DEFERRED, " Bind Deferred" },
  236. { LLFastTimer::FTM_RENDER_DEFERRED, " Deferred Shading" },
  237. { LLFastTimer::FTM_ATMOSPHERICS, " Atmospherics" },
  238. { LLFastTimer::FTM_SUN_SHADOW, " Shadow Map" },
  239. { LLFastTimer::FTM_SOFTEN_SHADOW, " Shadow Soften" },
  240. { LLFastTimer::FTM_LOCAL_LIGHTS, " Local Lights" },
  241. { LLFastTimer::FTM_PROJECTORS, " Projectors" },
  242. { LLFastTimer::FTM_FULLSCREEN_LIGHTS, " Full Screen Lights" },
  243. { LLFastTimer::FTM_SHADOW_RENDER, " Shadow" },
  244. { LLFastTimer::FTM_SHADOW_SIMPLE, " Simple" },
  245. { LLFastTimer::FTM_SHADOW_ALPHA, " Alpha" },
  246. { LLFastTimer::FTM_SHADOW_TERRAIN, " Terrain" },
  247. { LLFastTimer::FTM_SHADOW_AVATAR, " Avatar" },
  248. { LLFastTimer::FTM_SHADOW_TREE, " Tree" },
  249. { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry" },
  250. { LLFastTimer::FTM_POOLS, " Pools" },
  251. { LLFastTimer::FTM_POOLRENDER, " RenderPool" },
  252. { LLFastTimer::FTM_VOLUME_GEOM, " Volume Geometry" },
  253. { LLFastTimer::FTM_FACE_GET_GEOM, " Face Geom" },
  254. { LLFastTimer::FTM_FACE_GEOM_INDEX, " Index" },
  255. { LLFastTimer::FTM_FACE_GEOM_POSITION, " Position" },
  256. { LLFastTimer::FTM_FACE_GEOM_COLOR, " Color" },
  257. { LLFastTimer::FTM_FACE_GEOM_EMISSIVE, " Emissive" },
  258. { LLFastTimer::FTM_FACE_GEOM_NORMAL, " Normal" },
  259. { LLFastTimer::FTM_FACE_GEOM_TANGENT, " Tangent" },
  260. { LLFastTimer::FTM_FACE_GEOM_WEIGHTS, " Weights" },
  261. { LLFastTimer::FTM_FACE_GEOM_TEXTURE, " Texture" },
  262. { LLFastTimer::FTM_RENDER_OCCLUSION, " Occlusion" },
  263. { LLFastTimer::FTM_OCCLUSION_ALLOCATE, " Allocate" },
  264. { LLFastTimer::FTM_PUSH_OCCLUSION_VERTS, " Push Occlusion" },
  265. { LLFastTimer::FTM_OCCLUSION_BEGIN_QUERY, " Begin Query" },
  266. { LLFastTimer::FTM_OCCLUSION_DRAW_WATER, " Draw Water" },
  267. { LLFastTimer::FTM_OCCLUSION_DRAW, " Draw" },
  268. { LLFastTimer::FTM_OCCLUSION_END_QUERY, " End Query" },
  269. { LLFastTimer::FTM_AVATAR_FACE, " Avatar Face" },
  270. { LLFastTimer::FTM_RENDER_CHARACTERS, " Avatars" },
  271. { LLFastTimer::FTM_RENDER_AVATARS, " renderAvatars" },
  272. { LLFastTimer::FTM_RIGGED_VBO, " Rigged VBO" },
  273. { LLFastTimer::FTM_RENDER_SIMPLE, " Simple" },
  274. { LLFastTimer::FTM_RENDER_TERRAIN, " Terrain" },
  275. { LLFastTimer::FTM_RENDER_GRASS, " Grass" },
  276. { LLFastTimer::FTM_RENDER_WATER, " Water" },
  277. { LLFastTimer::FTM_RENDER_TREES, " Trees" },
  278. { LLFastTimer::FTM_RENDER_CLOUDS, " Clouds" },
  279. { LLFastTimer::FTM_RENDER_WL_SKY, " WL Sky" },
  280. { LLFastTimer::FTM_VISIBLE_CLOUD, " Visible Cloud" },
  281. { LLFastTimer::FTM_RENDER_INVISIBLE, " Invisible" },
  282. { LLFastTimer::FTM_RENDER_FULLBRIGHT, " Fullbright" },
  283. { LLFastTimer::FTM_RENDER_GLOW, " Glow" },
  284. { LLFastTimer::FTM_RENDER_SHINY, " Shiny" },
  285. { LLFastTimer::FTM_RENDER_BUMP, " Bump" },
  286. { LLFastTimer::FTM_RENDER_MATERIALS, " Materials" },
  287. { LLFastTimer::FTM_RENDER_ALPHA, " Alpha" },
  288. { LLFastTimer::FTM_RENDER_BLOOM, " Bloom" },
  289. { LLFastTimer::FTM_UPDATE_GL, " Update GL" },
  290. { LLFastTimer::FTM_REBUILD_GROUPS, " Rebuild Groups" },
  291. { LLFastTimer::FTM_RESET_VB, " Reset VB" },
  292. { LLFastTimer::FTM_RENDER_UI, " UI" },
  293. { LLFastTimer::FTM_RENDER_TIMER, " Fast Timers View" },
  294. { LLFastTimer::FTM_RENDER_FONTS_BATCHED, " Batched font glyphs" },
  295. { LLFastTimer::FTM_RENDER_FONTS_SERIALIZED, " Serialized font glyphs" },
  296. { LLFastTimer::FTM_RENDER_SPELLCHECK, " Mispell. Highlight" },
  297. { LLFastTimer::FTM_RESIZE_SCREEN_TEXTURE, " Resize Screen Tex." },
  298. { LLFastTimer::FTM_SWAP, " Swap" },
  299. { LLFastTimer::FTM_OTHER, " Other" }
  300. };
  301. constexpr S32 FTV_DISPLAY_NUM = LL_ARRAY_SIZE(ft_display_table);
  302. // line of table entry for display purposes (for collapse)
  303. S32 ft_display_idx[FTV_DISPLAY_NUM];
  304. static const LLColor4* level1_colors[] = { &LLColor4::cyan1,
  305. &LLColor4::grey1,
  306. &LLColor4::yellow1,
  307. &LLColor4::blue0,
  308. &LLColor4::green0,
  309. &LLColor4::red0,
  310. &LLColor4::black
  311. };
  312. constexpr S32 FTV_LEVEL1_COLORS = LL_ARRAY_SIZE(level1_colors);
  313. static const LLColor4* level2_colors[] = { &LLColor4::red1,
  314. &LLColor4::blue1,
  315. &LLColor4::green1,
  316. &LLColor4::orange1,
  317. &LLColor4::purple1,
  318. &LLColor4::cyan2,
  319. &LLColor4::magenta1,
  320. &LLColor4::yellow2,
  321. &LLColor4::grey2,
  322. &LLColor4::pink1,
  323. &LLColor4::red2,
  324. &LLColor4::blue2,
  325. &LLColor4::green2,
  326. &LLColor4::orange2,
  327. &LLColor4::purple2,
  328. &LLColor4::cyan3,
  329. &LLColor4::magenta2,
  330. &LLColor4::yellow3,
  331. &LLColor4::grey3,
  332. &LLColor4::pink2,
  333. &LLColor4::cyan4,
  334. &LLColor4::purple3,
  335. &LLColor4::yellow4,
  336. &LLColor4::green3,
  337. &LLColor4::orange3
  338. };
  339. constexpr S32 FTV_LEVEL2_COLORS = LL_ARRAY_SIZE(level2_colors);
  340. static const LLColor4* levelN_colors[] = { &LLColor4::red4,
  341. &LLColor4::blue3,
  342. &LLColor4::green4,
  343. &LLColor4::orange4,
  344. &LLColor4::purple4,
  345. &LLColor4::cyan5,
  346. &LLColor4::magenta3,
  347. &LLColor4::yellow5,
  348. &LLColor4::grey4,
  349. &LLColor4::red5,
  350. &LLColor4::blue4,
  351. &LLColor4::green5,
  352. &LLColor4::orange5,
  353. &LLColor4::purple4,
  354. &LLColor4::cyan6,
  355. &LLColor4::magenta4,
  356. &LLColor4::yellow6,
  357. &LLColor4::purple5,
  358. &LLColor4::green6,
  359. &LLColor4::yellow7,
  360. &LLColor4::blue6,
  361. &LLColor4::orange6,
  362. &LLColor4::green8,
  363. &LLColor4::blue7,
  364. &LLColor4::yellow8,
  365. &LLColor4::green7,
  366. &LLColor4::yellow9,
  367. &LLColor4::green9
  368. };
  369. constexpr S32 FTV_LEVELN_COLORS = LL_ARRAY_SIZE(levelN_colors);
  370. LLFastTimerView::LLFastTimerView(const std::string& name)
  371. : LLFloater(name, LLRect(0, 100, 100, 0), std::string(),
  372. false, 1, 1, false, false, true),
  373. mDisplayMode(0),
  374. mAvgCountTotal(0),
  375. mMaxCountTotal(0),
  376. mDisplayCenter(0),
  377. mDisplayCalls(0),
  378. mDisplayHz(0),
  379. mScrollIndex(0),
  380. mHoverIndex(-1),
  381. mHoverBarIndex(-1),
  382. mSubtractHidden(0),
  383. mPrintStats(-1),
  384. mWindowHeight(0),
  385. mWindowWidth(0),
  386. mFirstDrawLoop(true)
  387. {
  388. llassert_always(!gFastTimerViewp);
  389. gFastTimerViewp = this;
  390. mFont = LLFontGL::getFontMonospace();
  391. if (!mFont)
  392. {
  393. llerrs << "No monospace font !" << llendl;
  394. }
  395. setVisible(false);
  396. setFollowsTop();
  397. setFollowsLeft();
  398. resize();
  399. S32 count = (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM;
  400. mBarStart = new S32[count];
  401. memset(mBarStart, 0, count * sizeof(S32));
  402. mBarEnd = new S32[count];
  403. memset(mBarEnd, 0, count * sizeof(S32));
  404. setDisplayModeText();
  405. setCenterModeText();
  406. // One-time setup
  407. static bool ft_display_didcalc = false;
  408. if (!ft_display_didcalc)
  409. {
  410. S32 pidx[FTV_DISPLAY_NUM];
  411. S32 level;
  412. S32 color_idx1 = 0, color_idx2 = 0, color_idxN = 0;
  413. for (S32 i = 0; i < FTV_DISPLAY_NUM; ++i)
  414. {
  415. level = 0;
  416. const char* text = ft_display_table[i].desc;
  417. while (text[0] == ' ')
  418. {
  419. ++text;
  420. ++level;
  421. }
  422. llassert(level < FTV_DISPLAY_NUM);
  423. ft_display_table[i].desc = text;
  424. ft_display_table[i].level = level;
  425. ft_display_table[i].disabled = 0;
  426. if (level > 0)
  427. {
  428. ft_display_table[i].parent = pidx[level - 1];
  429. ft_display_table[i].disabled = level == 1 ? 1 : 3;
  430. if (level == 1)
  431. {
  432. ft_display_table[i].color = level1_colors[color_idx1];
  433. if (++color_idx1 >= FTV_LEVEL1_COLORS)
  434. {
  435. color_idx1 = 0;
  436. }
  437. }
  438. else if (level == 2)
  439. {
  440. ft_display_table[i].color = level2_colors[color_idx2];
  441. if (++color_idx2 >= FTV_LEVEL2_COLORS)
  442. {
  443. color_idx2 = 0;
  444. }
  445. }
  446. else
  447. {
  448. ft_display_table[i].color = levelN_colors[color_idxN];
  449. if (++color_idxN >= FTV_LEVELN_COLORS)
  450. {
  451. color_idxN = 0;
  452. }
  453. }
  454. }
  455. else
  456. {
  457. ft_display_table[i].parent = -1;
  458. ft_display_table[i].disabled = 0;
  459. ft_display_table[i].color = &LLColor4::white;
  460. }
  461. ft_display_idx[i] = i;
  462. pidx[level] = i;
  463. }
  464. ft_display_didcalc = true;
  465. }
  466. }
  467. LLFastTimerView::~LLFastTimerView()
  468. {
  469. delete[] mBarStart;
  470. delete[] mBarEnd;
  471. gFastTimerViewp = NULL;
  472. }
  473. void LLFastTimerView::setDisplayModeText()
  474. {
  475. static const char modedesc[][16] =
  476. {
  477. "2 x average ",
  478. "Max ",
  479. "Recent max ",
  480. "100 ms "
  481. };
  482. static const char* fullbar =
  483. "Full bar = %s [Click to pause/reset] [SHIFT-click to toggle]";
  484. mDisplayModeText =
  485. utf8str_to_wstring(llformat(fullbar, modedesc[mDisplayMode]));
  486. mDisplayModeTextWidth = mFont->getWidth(mDisplayModeText.c_str());
  487. }
  488. void LLFastTimerView::setCenterModeText()
  489. {
  490. static const char centerdesc[][16] =
  491. {
  492. "Left ",
  493. "Centered ",
  494. "Ordered "
  495. };
  496. static const char* justify = "Justification = %s [CTRL-click to toggle]";
  497. mCenterModeText =
  498. utf8str_to_wstring(llformat(justify, centerdesc[mDisplayCenter]));
  499. }
  500. void LLFastTimerView::resize()
  501. {
  502. S32 height = gViewerWindowp->getVirtualWindowRect().getHeight();
  503. S32 width = gViewerWindowp->getVirtualWindowRect().getWidth();
  504. mWindowHeight = 3 * height / 4;
  505. mWindowWidth = 3 * width / 4;
  506. reshape(mWindowWidth, mWindowHeight); // Necessary for the close button !
  507. LLRect rect;
  508. rect.setLeftTopAndSize(FASTTIMERVIEW_LEFT,
  509. height - FASTTIMERVIEW_TOP_DELTA,
  510. mWindowWidth, mWindowHeight);
  511. setRect(rect);
  512. }
  513. bool LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
  514. {
  515. if (mBarRect.pointInRect(x, y))
  516. {
  517. S32 bar_idx = MAX_VISIBLE_HISTORY -
  518. (y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) /
  519. mBarRect.getHeight();
  520. bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY);
  521. mPrintStats = bar_idx;
  522. return true;
  523. }
  524. return false;
  525. }
  526. S32 LLFastTimerView::getLegendIndex(S32 y)
  527. {
  528. static const S32 line_height =
  529. LLFontGL::getFontMonospace()->getLineHeight() + 2;
  530. S32 idx = (getRect().getHeight() - y) / line_height - 5;
  531. return idx >= 0 && idx < FTV_DISPLAY_NUM ? ft_display_idx[idx] : -1;
  532. }
  533. bool LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
  534. {
  535. {
  536. S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft;
  537. S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom;
  538. if (mButtons[BUTTON_CLOSE]->getVisible() &&
  539. mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y))
  540. {
  541. return LLFloater::handleMouseDown(x, y, mask);
  542. }
  543. }
  544. if (x < mBarRect.mLeft)
  545. {
  546. S32 legend_index = getLegendIndex(y);
  547. if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM)
  548. {
  549. S32 disabled = ft_display_table[legend_index].disabled;
  550. disabled = (disabled + 1) % 3;
  551. ft_display_table[legend_index].disabled = disabled;
  552. S32 level = ft_display_table[legend_index].level;
  553. // Propagate enable/disable to all children
  554. disabled = disabled ? 3 : 0;
  555. ++legend_index;
  556. while (legend_index < FTV_DISPLAY_NUM &&
  557. ft_display_table[legend_index].level > level)
  558. {
  559. ft_display_table[legend_index++].disabled = disabled;
  560. }
  561. }
  562. }
  563. else if (mask & MASK_ALT)
  564. {
  565. if (mask & MASK_SHIFT)
  566. {
  567. mSubtractHidden = !mSubtractHidden;
  568. }
  569. else if (mask & MASK_CONTROL)
  570. {
  571. mDisplayHz = !mDisplayHz;
  572. }
  573. else
  574. {
  575. mDisplayCalls = !mDisplayCalls;
  576. }
  577. }
  578. else if (mask & MASK_SHIFT)
  579. {
  580. if (++mDisplayMode > 3)
  581. {
  582. mDisplayMode = 0;
  583. }
  584. setDisplayModeText();
  585. }
  586. else if (mask & MASK_CONTROL)
  587. {
  588. if (++mDisplayCenter > 2)
  589. {
  590. mDisplayCenter = 0;
  591. }
  592. setCenterModeText();
  593. }
  594. else
  595. {
  596. // Pause/unpause
  597. LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
  598. // Reset scroll to bottom when unpausing
  599. if (!LLFastTimer::sPauseHistory)
  600. {
  601. mScrollIndex = 0;
  602. }
  603. }
  604. // SJB: Don't pass mouse clicks through the display
  605. return true;
  606. }
  607. bool LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask)
  608. {
  609. S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft;
  610. S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom;
  611. if (mButtons[BUTTON_CLOSE]->getVisible() &&
  612. mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y))
  613. {
  614. return LLFloater::handleMouseUp(x, y, mask);
  615. }
  616. return false;
  617. }
  618. bool LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
  619. {
  620. if (LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y))
  621. {
  622. mHoverIndex = -1;
  623. mHoverBarIndex = MAX_VISIBLE_HISTORY -
  624. (y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) /
  625. mBarRect.getHeight();
  626. if (mHoverBarIndex == 0)
  627. {
  628. return true;
  629. }
  630. else if (mHoverBarIndex < 0)
  631. {
  632. mHoverBarIndex = 0;
  633. }
  634. for (S32 i = 0; i < FTV_DISPLAY_NUM; ++i)
  635. {
  636. if (x > mBarStart[mHoverBarIndex * FTV_DISPLAY_NUM + i] &&
  637. x < mBarEnd[mHoverBarIndex * FTV_DISPLAY_NUM + i] &&
  638. ft_display_table[i].disabled <= 1)
  639. {
  640. mHoverIndex = i;
  641. }
  642. }
  643. }
  644. else if (x < mBarRect.mLeft)
  645. {
  646. S32 legend_index = getLegendIndex(y);
  647. if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM)
  648. {
  649. mHoverIndex = legend_index;
  650. }
  651. }
  652. return false;
  653. }
  654. bool LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
  655. {
  656. LLFastTimer::sPauseHistory = true;
  657. mScrollIndex = llclamp(mScrollIndex - clicks, 0,
  658. llmin(LLFastTimer::sLastFrameIndex,
  659. FTM_HISTORY_NUM - MAX_VISIBLE_HISTORY));
  660. return true;
  661. }
  662. //virtual
  663. void LLFastTimerView::setVisible(bool visible)
  664. {
  665. LLFloater::setVisible(visible);
  666. if (!visible)
  667. {
  668. mFirstDrawLoop = true; // Reset this for next opening.
  669. if (!gSavedSettings.getBool("FastTimersAlwaysEnabled"))
  670. {
  671. gEnableFastTimers = false;
  672. llinfos << "Fast timers disabled." << llendl;
  673. }
  674. }
  675. }
  676. //virtual
  677. void LLFastTimerView::onClose(bool app_quitting)
  678. {
  679. if (app_quitting)
  680. {
  681. LLFloater::close(app_quitting);
  682. }
  683. else
  684. {
  685. setVisible(false);
  686. }
  687. }
  688. void LLFastTimerView::draw()
  689. {
  690. LL_FAST_TIMER(FTM_RENDER_TIMER);
  691. if (!gEnableFastTimers)
  692. {
  693. gEnableFastTimers = true;
  694. llinfos << "Fast timers enabled." << llendl;
  695. }
  696. else if (mFirstDrawLoop)
  697. {
  698. // When the floater just got opened while FastTimersAlwaysEnabled was
  699. // TRUE, pause immediately after we draw the first loop. This way, the
  700. // user may see the timer stats before the fast timer floater drawing
  701. // time would start and pollute it...
  702. LLFastTimer::sPauseHistory = true;
  703. }
  704. S32 height = 3 * gViewerWindowp->getVirtualWindowRect().getHeight() / 4;
  705. S32 width = 3 * gViewerWindowp->getVirtualWindowRect().getWidth() / 4;
  706. if (mWindowHeight != height || mWindowWidth != width)
  707. {
  708. resize();
  709. }
  710. F64 clock_freq = (F64)LLFastTimer::countsPerSecond();
  711. F64 iclock_freq = 1000.0 / clock_freq;
  712. // Make sure all timers are accounted for: set 'FTM_OTHER' to unaccounted
  713. // ticks last frame.
  714. static S32 display_timer[LLFastTimer::FTM_NUM_TYPES];
  715. memset((void*)display_timer, 0, LLFastTimer::FTM_NUM_TYPES * sizeof(S32));
  716. for (S32 i = 0; i < FTV_DISPLAY_NUM; ++i)
  717. {
  718. S32 tidx = ft_display_table[i].timer;
  719. display_timer[tidx] = 1;
  720. }
  721. S32 hidx = LLFastTimer::sLastFrameIndex % FTM_HISTORY_NUM;
  722. LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] = 0;
  723. LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] = 0;
  724. for (S32 tidx = 0; tidx < LLFastTimer::FTM_NUM_TYPES; ++tidx)
  725. {
  726. U64 counts = LLFastTimer::sCountHistory[hidx][tidx];
  727. if (counts > 0 && display_timer[tidx] == 0)
  728. {
  729. LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] += counts;
  730. LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] += 1;
  731. }
  732. }
  733. LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] = 0;
  734. LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] = 0;
  735. for (S32 h = 0; h < FTM_HISTORY_NUM; ++h)
  736. {
  737. LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] +=
  738. LLFastTimer::sCountHistory[h][LLFastTimer::FTM_OTHER];
  739. LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] +=
  740. LLFastTimer::sCallHistory[h][LLFastTimer::FTM_OTHER];
  741. }
  742. LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] /= FTM_HISTORY_NUM;
  743. LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] /= FTM_HISTORY_NUM;
  744. LLTexUnit* unit0 = gGL.getTexUnit(0);
  745. // Draw the window background
  746. unit0->unbind(LLTexUnit::TT_TEXTURE);
  747. gl_rect_2d(0, height, width, 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
  748. constexpr S32 margin = 10;
  749. S32 xleft = margin;
  750. S32 ytop = margin;
  751. // Draw some help
  752. S32 x = xleft;
  753. S32 y = height - ytop;
  754. mFont->render(mDisplayModeText, 0, x, y, LLColor4::white, LLFontGL::LEFT,
  755. LLFontGL::TOP);
  756. S32 textw = mDisplayModeTextWidth;
  757. x = xleft;
  758. static const S32 texth = (S32)mFont->getLineHeight();
  759. y -= texth + 2;
  760. mFont->render(mCenterModeText, 0, x, y, LLColor4::white, LLFontGL::LEFT,
  761. LLFontGL::TOP);
  762. y -= texth + 2;
  763. static const LLWString cmds =
  764. utf8str_to_wstring(std::string("[Right-click log selected] [ALT-click toggle counts] [ALT-SHIFT-click sub hidden]"));
  765. mFont->render(cmds, 0, x, y, LLColor4::white, LLFontGL::LEFT,
  766. LLFontGL::TOP);
  767. y -= texth + 2;
  768. // Calc the total ticks
  769. S32 histmax = llmin(LLFastTimer::sLastFrameIndex + 1, MAX_VISIBLE_HISTORY);
  770. U64 ticks_sum[FTM_HISTORY_NUM + 1][FTV_DISPLAY_NUM];
  771. for (S32 j = -1; j < FTM_HISTORY_NUM; ++j)
  772. {
  773. S32 hidx;
  774. if (j >= 0)
  775. {
  776. hidx = (LLFastTimer::sLastFrameIndex + j) % FTM_HISTORY_NUM;
  777. }
  778. else
  779. {
  780. hidx = -1;
  781. }
  782. // Calculate tick info by adding child ticks to parents
  783. for (S32 i = 0; i < FTV_DISPLAY_NUM; ++i)
  784. {
  785. if (mSubtractHidden && ft_display_table[i].disabled > 1)
  786. {
  787. continue;
  788. }
  789. // Get ticks
  790. S32 tidx = ft_display_table[i].timer;
  791. if (hidx >= 0)
  792. {
  793. ticks_sum[j + 1][i] = LLFastTimer::sCountHistory[hidx][tidx];
  794. }
  795. else
  796. {
  797. ticks_sum[j + 1][i] = LLFastTimer::sCountAverage[tidx];
  798. }
  799. S32 pidx = ft_display_table[i].parent;
  800. // Add ticks to parents
  801. while (pidx >= 0)
  802. {
  803. ticks_sum[j + 1][pidx] += ticks_sum[j + 1][i];
  804. pidx = ft_display_table[pidx].parent;
  805. }
  806. }
  807. }
  808. // Draw the legend
  809. S32 legendwidth = 0;
  810. xleft = margin;
  811. ytop = y;
  812. y -= texth + 2;
  813. S32 cur_line = 0;
  814. S32 display_line[FTV_DISPLAY_NUM];
  815. std::string line;
  816. for (S32 i = 0; i < FTV_DISPLAY_NUM; ++i)
  817. {
  818. S32 disabled = ft_display_table[i].disabled;
  819. if (disabled == 3)
  820. {
  821. continue; // skip row
  822. }
  823. display_line[i] = cur_line;
  824. ft_display_idx[cur_line++] = i;
  825. S32 level = ft_display_table[i].level;
  826. S32 parent = ft_display_table[i].parent;
  827. x = xleft;
  828. S32 left = x;
  829. S32 right = x + texth;
  830. S32 top = y;
  831. S32 bottom = y - texth;
  832. S32 scale_offset = 0;
  833. if (y > 3 * texth)
  834. {
  835. if (i == mHoverIndex)
  836. {
  837. scale_offset =
  838. llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) *
  839. 2.f);
  840. }
  841. gl_rect_2d(left - scale_offset, top + scale_offset,
  842. right + scale_offset, bottom - scale_offset,
  843. *ft_display_table[i].color);
  844. }
  845. S32 tidx = ft_display_table[i].timer;
  846. F32 ms = 0;
  847. S32 calls = 0;
  848. if (mHoverBarIndex > 0 && mHoverIndex >= 0)
  849. {
  850. S32 hidx = (LLFastTimer::sLastFrameIndex + mHoverBarIndex - 1 -
  851. mScrollIndex) % FTM_HISTORY_NUM;
  852. S32 bidx = FTM_HISTORY_NUM - mScrollIndex - mHoverBarIndex;
  853. U64 ticks = ticks_sum[bidx + 1][i];
  854. ms = (F32)((F64)ticks * iclock_freq);
  855. calls = (S32)LLFastTimer::sCallHistory[hidx][tidx];
  856. }
  857. else
  858. {
  859. U64 ticks = ticks_sum[0][i];
  860. ms = (F32)((F64)ticks * iclock_freq);
  861. calls = (S32)LLFastTimer::sCallAverage[tidx];
  862. }
  863. if (mDisplayCalls)
  864. {
  865. line = llformat("%s (%d)", ft_display_table[i].desc, calls);
  866. }
  867. else
  868. {
  869. line = llformat("%s [%.1f]", ft_display_table[i].desc, ms);
  870. }
  871. S32 dx = texth + 4 + level * 8;
  872. LLColor4 color = disabled > 1 ? LLColor4::grey : LLColor4::white;
  873. if (level > 0 && y > 3 * texth)
  874. {
  875. S32 line_start_y = (top + bottom) / 2;
  876. S32 line_end_y = line_start_y + (texth + 2) *
  877. (display_line[i] - display_line[parent]) -
  878. texth / 2;
  879. gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color);
  880. S32 line_x = x + (texth + 4) + ((level - 1) * 8);
  881. gl_line_2d(line_x, line_start_y, line_x, line_end_y, color);
  882. if (disabled == 1)
  883. {
  884. gl_line_2d(line_x + 4, line_start_y - 3, line_x + 4,
  885. line_start_y + 4, color);
  886. }
  887. }
  888. x += dx;
  889. bool is_child_of_hover_item = (i == mHoverIndex);
  890. S32 next_parent = ft_display_table[i].parent;
  891. while (!is_child_of_hover_item && next_parent >= 0)
  892. {
  893. is_child_of_hover_item = (mHoverIndex == next_parent);
  894. next_parent = ft_display_table[next_parent].parent;
  895. }
  896. if (y > 3 * texth)
  897. {
  898. if (is_child_of_hover_item)
  899. {
  900. mFont->renderUTF8(line, 0, x, y, color, LLFontGL::LEFT,
  901. LLFontGL::TOP, LLFontGL::BOLD);
  902. }
  903. else
  904. {
  905. mFont->renderUTF8(line, 0, x, y, color, LLFontGL::LEFT,
  906. LLFontGL::TOP);
  907. }
  908. }
  909. y -= texth + 2;
  910. textw = dx + 40 +
  911. mFont->getWidth(std::string(ft_display_table[i].desc));
  912. if (textw > legendwidth)
  913. {
  914. legendwidth = textw;
  915. }
  916. }
  917. if (y <= 3 * texth)
  918. {
  919. static const LLWString truncated =
  920. utf8str_to_wstring(std::string("<list truncated>"));
  921. mFont->render(truncated, 0, 3 * texth, 2 * texth, LLColor4::white,
  922. LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD);
  923. }
  924. for (S32 i = cur_line; i < FTV_DISPLAY_NUM; ++i)
  925. {
  926. ft_display_idx[i] = -1;
  927. }
  928. xleft += legendwidth + 8;
  929. // Update rectangle that includes timer bars
  930. mBarRect.mLeft = xleft;
  931. mBarRect.mRight = getRect().mRight - xleft;
  932. mBarRect.mTop = ytop - (texth + 4);
  933. mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT;
  934. y = ytop;
  935. S32 barh = (ytop - margin - LINE_GRAPH_HEIGHT) / (MAX_VISIBLE_HISTORY + 2);
  936. S32 dy = barh >> 2; // Spacing between bars
  937. if (dy < 1) dy = 1;
  938. barh -= dy;
  939. S32 barw = width - xleft - margin;
  940. // Draw the history bars
  941. if (LLFastTimer::sLastFrameIndex >= 0)
  942. {
  943. U64 totalticks;
  944. if (mFirstDrawLoop || !LLFastTimer::sPauseHistory)
  945. {
  946. U64 ticks = 0;
  947. S32 hidx = (LLFastTimer::sLastFrameIndex - mScrollIndex) %
  948. FTM_HISTORY_NUM;
  949. for (S32 i = 0; i < FTV_DISPLAY_NUM; ++i)
  950. {
  951. if (mSubtractHidden && ft_display_table[i].disabled > 1)
  952. {
  953. continue;
  954. }
  955. S32 tidx = ft_display_table[i].timer;
  956. ticks += LLFastTimer::sCountHistory[hidx][tidx];
  957. }
  958. if (LLFastTimer::sCurFrameIndex >= 10)
  959. {
  960. U64 framec = LLFastTimer::sCurFrameIndex;
  961. U64 avg = (U64)mAvgCountTotal;
  962. mAvgCountTotal = (avg * framec + ticks) / (framec + 1);
  963. if (ticks > mMaxCountTotal)
  964. {
  965. mMaxCountTotal = ticks;
  966. }
  967. }
  968. #if 1
  969. if (ticks < mAvgCountTotal / 100 || ticks > mAvgCountTotal * 100)
  970. {
  971. LLFastTimer::sResetHistory = true;
  972. }
  973. #endif
  974. if (LLFastTimer::sCurFrameIndex < 10 || LLFastTimer::sResetHistory)
  975. {
  976. mAvgCountTotal = ticks;
  977. mMaxCountTotal = ticks;
  978. }
  979. }
  980. if (mDisplayMode == 0)
  981. {
  982. totalticks = mAvgCountTotal * 2;
  983. }
  984. else if (mDisplayMode == 1)
  985. {
  986. totalticks = mMaxCountTotal;
  987. }
  988. else if (mDisplayMode == 2)
  989. {
  990. // Calculate the max total ticks for the current history
  991. totalticks = 0;
  992. for (S32 j = 0; j < histmax; ++j)
  993. {
  994. U64 ticks = 0;
  995. for (S32 i = 0; i < FTV_DISPLAY_NUM; ++i)
  996. {
  997. if (mSubtractHidden && ft_display_table[i].disabled > 1)
  998. {
  999. continue;
  1000. }
  1001. S32 tidx = ft_display_table[i].timer;
  1002. ticks += LLFastTimer::sCountHistory[j][tidx];
  1003. }
  1004. if (ticks > totalticks)
  1005. {
  1006. totalticks = ticks;
  1007. }
  1008. }
  1009. }
  1010. else
  1011. {
  1012. totalticks = (U64)(clock_freq * .1); // 100 ms
  1013. }
  1014. // Draw MS ticks
  1015. {
  1016. U32 ms = (U32)((F64)totalticks * iclock_freq);
  1017. line = llformat("%.1f ms |", (F32)ms * .25f);
  1018. x = xleft + barw / 4 - mFont->getWidth(line);
  1019. mFont->renderUTF8(line, 0, x, y, LLColor4::white, LLFontGL::LEFT,
  1020. LLFontGL::TOP);
  1021. line = llformat("%.1f ms |", (F32)ms * .50f);
  1022. x = xleft + barw / 2 - mFont->getWidth(line);
  1023. mFont->renderUTF8(line, 0, x, y, LLColor4::white, LLFontGL::LEFT,
  1024. LLFontGL::TOP);
  1025. line = llformat("%.1f ms |", (F32)ms * .75f);
  1026. x = xleft + 3 * barw / 4 - mFont->getWidth(line);
  1027. mFont->renderUTF8(line, 0, x, y, LLColor4::white, LLFontGL::LEFT,
  1028. LLFontGL::TOP);
  1029. line = llformat("%d ms |", ms);
  1030. x = xleft + barw - mFont->getWidth(line);
  1031. mFont->renderUTF8(line, 0, x, y, LLColor4::white, LLFontGL::LEFT,
  1032. LLFontGL::TOP);
  1033. }
  1034. LLRect graph_rect;
  1035. // Draw borders
  1036. {
  1037. unit0->unbind(LLTexUnit::TT_TEXTURE);
  1038. gGL.color4f(0.5f, 0.5f, 0.5f, 0.5f);
  1039. S32 width = getRect().getWidth() - 5;
  1040. S32 by = y + 2;
  1041. y -= (texth + 4);
  1042. // Heading
  1043. gl_rect_2d(xleft - 5, by, width, y + 5, false);
  1044. // Tree view
  1045. gl_rect_2d(5, by, xleft - 10, 5, false);
  1046. by = y + 5;
  1047. // Average bar
  1048. gl_rect_2d(xleft - 5, by, width, by - barh - dy - 5, false);
  1049. by -= barh * 2 + dy;
  1050. // Current frame bar
  1051. gl_rect_2d(xleft - 5, by, width, by - barh - dy - 2, false);
  1052. by -= barh + dy + 1;
  1053. // History bars
  1054. gl_rect_2d(xleft - 5, by, width, LINE_GRAPH_HEIGHT - barh - dy - 2, false);
  1055. by = LINE_GRAPH_HEIGHT - barh - dy - 7;
  1056. // Line graph
  1057. graph_rect = LLRect(xleft - 5, by, width, 5);
  1058. gl_rect_2d(graph_rect, false);
  1059. }
  1060. // Draw bars for each history entry. Special: -1 = show running average
  1061. static const S32 tex_width = LLUIImage::sRoundedSquareWidth;
  1062. static const S32 tex_height = LLUIImage::sRoundedSquareHeight;
  1063. unit0->bind(LLUIImage::sRoundedSquare->getImage());
  1064. for (S32 j = -1; j < histmax && y > LINE_GRAPH_HEIGHT; ++j)
  1065. {
  1066. S32 sublevel_dx[FTV_DISPLAY_NUM + 1];
  1067. S32 sublevel_left[FTV_DISPLAY_NUM + 1];
  1068. S32 sublevel_right[FTV_DISPLAY_NUM + 1];
  1069. S32 tidx;
  1070. if (j >= 0)
  1071. {
  1072. tidx = FTM_HISTORY_NUM - j - 1 - mScrollIndex;
  1073. }
  1074. else
  1075. {
  1076. tidx = -1;
  1077. }
  1078. x = xleft;
  1079. // Draw the bars for each stat
  1080. S32 xpos[FTV_DISPLAY_NUM + 1];
  1081. S32 deltax[FTV_DISPLAY_NUM + 1];
  1082. xpos[0] = xleft;
  1083. for (S32 i = 0; i < FTV_DISPLAY_NUM; ++i)
  1084. {
  1085. if (ft_display_table[i].disabled > 1)
  1086. {
  1087. continue;
  1088. }
  1089. F32 frac = (F32)ticks_sum[tidx + 1][i] / (F32)totalticks;
  1090. S32 dx = ll_round(frac * (F32)barw);
  1091. deltax[i] = dx;
  1092. S32 level = ft_display_table[i].level;
  1093. S32 parent = ft_display_table[i].parent;
  1094. llassert(level < FTV_DISPLAY_NUM);
  1095. llassert(parent < FTV_DISPLAY_NUM);
  1096. S32 left = xpos[level];
  1097. S32 prev_idx = i - 1;
  1098. while (prev_idx > 0 &&
  1099. ft_display_table[prev_idx].disabled > 1)
  1100. {
  1101. --prev_idx;
  1102. }
  1103. S32 next_idx = i + 1;
  1104. while (next_idx < FTV_DISPLAY_NUM &&
  1105. ft_display_table[next_idx].disabled > 1)
  1106. {
  1107. ++next_idx;
  1108. }
  1109. if (level == 0)
  1110. {
  1111. sublevel_left[level] = xleft;
  1112. sublevel_dx[level] = dx;
  1113. sublevel_right[level] = sublevel_left[level] +
  1114. sublevel_dx[level];
  1115. }
  1116. else if (i == 0 || ft_display_table[prev_idx].level < level)
  1117. {
  1118. // If we are the first entry at a new sublevel block, calc
  1119. // the total width of this sublevel and modify left to
  1120. // align block.
  1121. U64 sublevelticks = ticks_sum[tidx + 1][i];
  1122. for (S32 k = i + 1; k < FTV_DISPLAY_NUM; ++k)
  1123. {
  1124. if (ft_display_table[k].level < level)
  1125. {
  1126. break;
  1127. }
  1128. if (ft_display_table[k].disabled <= 1 &&
  1129. ft_display_table[k].level == level)
  1130. {
  1131. sublevelticks += ticks_sum[tidx + 1][k];
  1132. }
  1133. }
  1134. F32 subfrac = (F32)sublevelticks / (F32)totalticks;
  1135. sublevel_dx[level] = (S32)(subfrac * (F32)barw + .5f);
  1136. if (mDisplayCenter == 1) // Center aligned
  1137. {
  1138. left += (deltax[parent] - sublevel_dx[level]) / 2;
  1139. }
  1140. else if (mDisplayCenter == 2) // Right aligned
  1141. {
  1142. left += deltax[parent] - sublevel_dx[level];
  1143. }
  1144. sublevel_left[level] = left;
  1145. sublevel_right[level] = sublevel_left[level] +
  1146. sublevel_dx[level];
  1147. }
  1148. S32 right = left + dx;
  1149. xpos[level] = right;
  1150. xpos[level + 1] = left;
  1151. mBarStart[(j + 1) * FTV_DISPLAY_NUM + i] = left;
  1152. mBarEnd[(j + 1) * FTV_DISPLAY_NUM + i] = right;
  1153. S32 top = y;
  1154. S32 bottom = y - barh;
  1155. if (right > left)
  1156. {
  1157. LLColor4 color = *ft_display_table[i].color;
  1158. S32 scale_offset = 0;
  1159. bool is_child_of_hover_item = (i == mHoverIndex);
  1160. S32 next_parent = ft_display_table[i].parent;
  1161. while (!is_child_of_hover_item && next_parent >= 0)
  1162. {
  1163. is_child_of_hover_item = (mHoverIndex == next_parent);
  1164. next_parent = ft_display_table[next_parent].parent;
  1165. }
  1166. if (i == mHoverIndex)
  1167. {
  1168. scale_offset =
  1169. llfloor(sinf(mHighlightTimer.getElapsedTimeF32() *
  1170. 6.f) * 3.f);
  1171. }
  1172. else if (mHoverIndex >= 0 && !is_child_of_hover_item)
  1173. {
  1174. color = lerp(color, LLColor4::grey, 0.8f);
  1175. }
  1176. gGL.color4fv(color.mV);
  1177. F32 start_fragment =
  1178. llclamp((F32)(left - sublevel_left[level]) /
  1179. (F32)sublevel_dx[level], 0.f, 1.f);
  1180. F32 end_fragment =
  1181. llclamp((F32)(right - sublevel_left[level]) /
  1182. (F32)sublevel_dx[level], 0.f, 1.f);
  1183. gl_segmented_rect_2d_fragment_tex(sublevel_left[level],
  1184. top - level + scale_offset,
  1185. sublevel_right[level],
  1186. bottom + level - scale_offset,
  1187. tex_width, tex_height,
  1188. 16, start_fragment,
  1189. end_fragment);
  1190. }
  1191. }
  1192. y -= barh + dy;
  1193. if (j < 0)
  1194. {
  1195. y -= barh;
  1196. }
  1197. }
  1198. // Draw line graph history
  1199. {
  1200. unit0->unbind(LLTexUnit::TT_TEXTURE);
  1201. LLLocalClipRect clip(graph_rect);
  1202. // Normalize based on last frame's maximum
  1203. static U64 last_max = 0;
  1204. static F32 alpha_interp = 0.f;
  1205. U64 max_ticks = llmax(last_max, (U64)1);
  1206. F32 ms = (F32)((F64)max_ticks * iclock_freq);
  1207. // Display y-axis range
  1208. std::string line;
  1209. if (mDisplayCalls)
  1210. {
  1211. line = llformat("%d calls", (S32)max_ticks);
  1212. }
  1213. else if (mDisplayHz)
  1214. {
  1215. line = llformat("%d Hz", (S32)max_ticks);
  1216. }
  1217. else
  1218. {
  1219. line = llformat("%4.2f ms", ms);
  1220. }
  1221. x = graph_rect.mRight - mFont->getWidth(line) - 5;
  1222. y = graph_rect.mTop - texth;
  1223. mFont->renderUTF8(line, 0, x, y, LLColor4::white, LLFontGL::LEFT,
  1224. LLFontGL::TOP);
  1225. // Highlight visible range
  1226. {
  1227. S32 first_frame = FTM_HISTORY_NUM - mScrollIndex;
  1228. S32 last_frame = first_frame - MAX_VISIBLE_HISTORY;
  1229. F32 frame_delta = (F32)graph_rect.getWidth() /
  1230. F32(FTM_HISTORY_NUM - 1);
  1231. F32 right = (F32)graph_rect.mLeft + frame_delta * first_frame;
  1232. F32 left = (F32)graph_rect.mLeft + frame_delta * last_frame;
  1233. gGL.color4f(0.5f, 0.5f, 0.5f, 0.3f);
  1234. gl_rect_2d((S32)left, graph_rect.mTop, (S32)right,
  1235. graph_rect.mBottom);
  1236. if (mHoverBarIndex >= 0)
  1237. {
  1238. S32 bar_frame = first_frame - mHoverBarIndex;
  1239. F32 bar = (F32)graph_rect.mLeft + frame_delta * bar_frame;
  1240. gGL.color4f(0.5f, 0.5f, 0.5f, 1.f);
  1241. gGL.begin(LLRender::LINES);
  1242. gGL.vertex2i((S32)bar, graph_rect.mBottom);
  1243. gGL.vertex2i((S32)bar, graph_rect.mTop);
  1244. gGL.end();
  1245. }
  1246. }
  1247. U64 cur_max = 0;
  1248. for (S32 idx = 0; idx < FTV_DISPLAY_NUM; ++idx)
  1249. {
  1250. if (ft_display_table[idx].disabled > 1)
  1251. {
  1252. // Skip disabled timers
  1253. continue;
  1254. }
  1255. // Fatten highlighted timer
  1256. if (mHoverIndex == idx)
  1257. {
  1258. gGL.flush();
  1259. gGL.lineWidth(3.f);
  1260. }
  1261. const F32* col = ft_display_table[idx].color->mV;
  1262. F32 alpha = 1.f;
  1263. if (mHoverIndex >= 0 && idx != mHoverIndex)
  1264. {
  1265. // Fade out non-hihglighted timers
  1266. if (ft_display_table[idx].parent != mHoverIndex)
  1267. {
  1268. alpha = alpha_interp;
  1269. }
  1270. }
  1271. gGL.color4f(col[0], col[1], col[2], alpha);
  1272. gGL.begin(LLRender::LINE_STRIP);
  1273. for (U32 j = 0; j < FTM_HISTORY_NUM; ++j)
  1274. {
  1275. U64 ticks = ticks_sum[j + 1][idx];
  1276. if (mDisplayHz)
  1277. {
  1278. F64 tc = (F64)(ticks + 1) * iclock_freq;
  1279. tc = 1000.f / tc;
  1280. ticks = llmin((U64)tc, (U64)1024);
  1281. }
  1282. else if (mDisplayCalls)
  1283. {
  1284. S32 tidx = ft_display_table[idx].timer;
  1285. S32 hidx = (LLFastTimer::sLastFrameIndex + j) %
  1286. FTM_HISTORY_NUM;
  1287. ticks = (S32)LLFastTimer::sCallHistory[hidx][tidx];
  1288. }
  1289. if (alpha == 1.f)
  1290. {
  1291. // Normalize to highlighted timer
  1292. cur_max = llmax(cur_max, ticks);
  1293. }
  1294. F32 x = graph_rect.mLeft +
  1295. F32(graph_rect.getWidth()) /
  1296. F32(FTM_HISTORY_NUM - 1) * j;
  1297. F32 y = graph_rect.mBottom +
  1298. F32(graph_rect.getHeight()) / max_ticks * ticks;
  1299. gGL.vertex2f(x, y);
  1300. }
  1301. gGL.end();
  1302. if (mHoverIndex == idx)
  1303. {
  1304. gGL.flush();
  1305. gGL.lineWidth(1.f);
  1306. }
  1307. }
  1308. // Interpolate towards new maximum
  1309. F32 dt = gFrameIntervalSeconds * 3.f;
  1310. last_max = (U64)((F32)last_max +
  1311. ((F32)cur_max - (F32)last_max) * dt);
  1312. F32 alpha_target = last_max > cur_max ?
  1313. llmin((F32)last_max / (F32)cur_max - 1.f, 1.f) :
  1314. llmin((F32)cur_max / (F32)last_max - 1.f, 1.f);
  1315. alpha_interp = alpha_interp + (alpha_target - alpha_interp) * dt;
  1316. if (mHoverIndex >= 0)
  1317. {
  1318. x = (graph_rect.mRight + graph_rect.mLeft) / 2;
  1319. y = graph_rect.mBottom + 8;
  1320. mFont->renderUTF8(std::string(ft_display_table[mHoverIndex].desc),
  1321. 0, x, y, LLColor4::white, LLFontGL::LEFT,
  1322. LLFontGL::BOTTOM);
  1323. }
  1324. }
  1325. }
  1326. // Output stats for clicked bar to log
  1327. if (mPrintStats >= 0)
  1328. {
  1329. std::string legend_stat;
  1330. S32 stat_num;
  1331. S32 first = 1;
  1332. for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; ++stat_num)
  1333. {
  1334. if (ft_display_table[stat_num].disabled > 1)
  1335. {
  1336. continue;
  1337. }
  1338. if (!first)
  1339. {
  1340. legend_stat += ", ";
  1341. }
  1342. first = 0;
  1343. legend_stat += ft_display_table[stat_num].desc;
  1344. }
  1345. llinfos << legend_stat << llendl;
  1346. std::string timer_stat;
  1347. first = 1;
  1348. for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; ++stat_num)
  1349. {
  1350. S32 disabled = ft_display_table[stat_num].disabled;
  1351. if (disabled > 1)
  1352. {
  1353. continue;
  1354. }
  1355. if (!first)
  1356. {
  1357. timer_stat += ", ";
  1358. }
  1359. first = 0;
  1360. U64 ticks;
  1361. S32 tidx = ft_display_table[stat_num].timer;
  1362. if (mPrintStats > 0)
  1363. {
  1364. S32 hidx = (LLFastTimer::sLastFrameIndex + mPrintStats - 1 -
  1365. mScrollIndex) % FTM_HISTORY_NUM;
  1366. ticks = disabled >= 1 ? ticks_sum[mPrintStats][stat_num]
  1367. : LLFastTimer::sCountHistory[hidx][tidx];
  1368. }
  1369. else
  1370. {
  1371. ticks = disabled >= 1 ? ticks_sum[0][stat_num]
  1372. : LLFastTimer::sCountAverage[tidx];
  1373. }
  1374. F32 ms = (F32)((F64)ticks * iclock_freq);
  1375. timer_stat += llformat("%.1f", ms);
  1376. }
  1377. llinfos << timer_stat << llendl;
  1378. mPrintStats = -1;
  1379. }
  1380. mHoverIndex = -1;
  1381. mHoverBarIndex = -1;
  1382. mFirstDrawLoop = false;
  1383. LLView::draw();
  1384. }
  1385. F64 LLFastTimerView::getTime(LLFastTimer::EFastTimerType tidx)
  1386. {
  1387. // Find table index
  1388. S32 i;
  1389. for (i = 0; i < FTV_DISPLAY_NUM; ++i)
  1390. {
  1391. if (tidx == ft_display_table[i].timer)
  1392. {
  1393. break;
  1394. }
  1395. }
  1396. if (i == FTV_DISPLAY_NUM)
  1397. {
  1398. // Walked off the end of ft_display_table without finding the desired
  1399. // timer type
  1400. llwarns << "Timer type " << tidx << " not known." << llendl;
  1401. return 0.0;
  1402. }
  1403. S32 table_idx = i;
  1404. // Add child ticks to parent
  1405. U64 ticks = LLFastTimer::sCountAverage[tidx];
  1406. S32 level = ft_display_table[table_idx].level;
  1407. for (i = table_idx + 1; i < FTV_DISPLAY_NUM; ++i)
  1408. {
  1409. if (ft_display_table[i].level <= level)
  1410. {
  1411. break;
  1412. }
  1413. ticks += LLFastTimer::sCountAverage[ft_display_table[i].timer];
  1414. }
  1415. return (F64)ticks / (F64)LLFastTimer::countsPerSecond();
  1416. }
  1417. #endif // LL_FAST_TIMERS_ENABLED
  1418. #if TRACY_ENABLE
  1419. //static
  1420. LLProcessLauncher* HBTracyProfiler::sProcess = NULL;
  1421. //static
  1422. bool HBTracyProfiler::running()
  1423. {
  1424. return sProcess && sProcess->isRunning();
  1425. }
  1426. //static
  1427. void HBTracyProfiler::launch()
  1428. {
  1429. if (running())
  1430. {
  1431. return;
  1432. }
  1433. std::string exe_path = gDirUtil.getExecutableDir();
  1434. #if LL_DARWIN
  1435. exe_path += "/../Resources/tracy";
  1436. #elif LL_WINDOWS
  1437. exe_path += "\\Tracy.exe";
  1438. #else // LL_LINUX
  1439. exe_path += "/tracy";
  1440. #endif
  1441. if (!LLFile::isfile(exe_path))
  1442. {
  1443. llwarns << "Tracy profiler executable not found. Cannot launch it."
  1444. << llendl;
  1445. return;
  1446. }
  1447. if (sProcess)
  1448. {
  1449. sProcess->kill();
  1450. sProcess->clearArguments();
  1451. }
  1452. else
  1453. {
  1454. sProcess = new LLProcessLauncher();
  1455. }
  1456. sProcess->setWorkingDirectory(gDirUtil.getOSUserDir());
  1457. sProcess->setExecutable(exe_path);
  1458. sProcess->addArgument("-a");
  1459. sProcess->addArgument("127.0.0.1");
  1460. if (sProcess->launch() != 0)
  1461. {
  1462. llwarns << "Failed to launch the Tracy profiler executable." << llendl;
  1463. }
  1464. }
  1465. //static
  1466. void HBTracyProfiler::detach()
  1467. {
  1468. if (sProcess)
  1469. {
  1470. sProcess->orphan();
  1471. delete sProcess;
  1472. sProcess = NULL;
  1473. }
  1474. }
  1475. //static
  1476. void HBTracyProfiler::kill()
  1477. {
  1478. if (sProcess)
  1479. {
  1480. delete sProcess;
  1481. sProcess = NULL;
  1482. }
  1483. }
  1484. #endif // TRACY_ENABLE