UNPKG

leva-r3f-stats

Version:

A small plugin to display React Three Fiber stats in Leva

2 lines (1 loc) 27.8 kB
function t(t,e=A){const i=t.stats||{},n=W.getPeaks(),r=F(t);return Object.entries(r).filter(([e])=>{var n;return!("compute"===e&&!t.trackCompute||"vsync"===e&&!1===t.vsync||!1===(null===(n=i[e])||void 0===n?void 0:n.show))}).map(([s,l])=>{var a,o;const u=s,c=null!==(o=null===(a=i[u])||void 0===a?void 0:a.order)&&void 0!==o?o:Object.keys(r).indexOf(u);let h,d,p=100;switch(u){case"fps":h=t=>P(t,e.fpsCritical,e.fpsWarning,!0),p=1.2*e.targetFPS,d="MAX: "+e.targetFPS;break;case"ms":h=t=>P(t,e.msWarning,e.msCritical),p=2*e.targetMS,d=`MAX: ${e.targetMS.toFixed(1)}ms`;break;case"gpu":t.gpuPercentage?(h=t=>t>90?"#ff6b6b":t>70?"#ffd93d":"#51cf66",p=100,d=""):(h=t=>P(t,e.msWarning,e.msCritical),p=2*e.targetMS);break;case"cpu":h=t=>P(t,e.msWarning,e.msCritical),p=2*e.targetMS;break;case"triangles":h=t=>P(t,e.trianglesWarning,e.trianglesCritical),p=Math.max(1.5*e.trianglesBudget,1.2*n.triangles),d=n.triangles>0?"MAX: "+I.triangles(n.triangles):"MAX: "+I.triangles(e.trianglesBudget);break;case"drawCalls":h=t=>P(t,e.drawCallsWarning,e.drawCallsCritical),p=Math.max(1.5*e.drawCallsBudget,1.2*n.drawCalls),d=n.drawCalls>0?"MAX: "+n.drawCalls:"MAX: "+e.drawCallsBudget}return{key:u,label:l,labelSuffix:d,shortLabel:l,unit:"memory"===u?"MB":"vsync"===u?"Hz":"",format:I[u],color:h,show:!0,order:c,showInCompact:"cpu"!==u&&"vsync"!==u,graphMin:0,graphMax(){return p}}}).sort((t,e)=>t.order-e.order)}function e(t,e,i=!1){return t.filter(t=>!(i&&!t.showInCompact||!("compute"!==t.key||e.isWebGPU&&0!==e.compute)||"cpu"===t.key&&!e.gpuAccurate))}function i(){var t,e,i;if(null!==$)return $;if(!T){T=!0;try{if("undefined"!=typeof window&&(null===(t=window.screen)||void 0===t?void 0:t.refreshRate)){const t=window.screen.refreshRate;if(t&&t>0)return $=t,t}if("undefined"!=typeof window){const t=[165,144,120,90,75,72];for(const e of t)if(window.matchMedia(`(min-resolution: ${e-5}dpi) and (max-resolution: ${e+5}dpi)`).matches)return $=e,e;if(window.matchMedia("(prefers-reduced-motion: no-preference) and (update: fast)").matches)return window.devicePixelRatio>2?($=90,90):($=120,120)}"undefined"!=typeof window&&"getScreenDetails"in window&&(null===(i=(e=window).getScreenDetails)||void 0===i?void 0:i.call(e).then(t=>{var e;(null===(e=null==t?void 0:t.currentScreen)||void 0===e?void 0:e.refreshRate)&&($=t.currentScreen.refreshRate)}).catch(()=>{}))}catch(n){}}return null}function n(t,e,i){const n=1e3/t,r=e||1e6,s=i||500;return{fpsWarning:.8*t,fpsCritical:.5*t,msWarning:1.2*n,msCritical:1.5*n,gpuWarning:1.2*n,gpuCritical:1.5*n,targetFPS:t,targetMS:n,trianglesBudget:r,drawCallsBudget:s,trianglesWarning:.8*r,trianglesCritical:1.2*r,drawCallsWarning:.8*s,drawCallsCritical:1.2*s}}function r({data:t,color:e,min:i,max:n,height:r,label:s,fullLabel:l,unit:a,currentValue:o,backgroundColor:u="#181c20",gridColor:c="#ffffff25",fontSize:h=9,showFullLabel:d=!1}){const p=m(null),f=m(),v=Math.max(8,h-1),w=`${o.toFixed(1)}${a}`,y=b(()=>{var t;if(d&&l){const e=l.match(/^(.+?)(\s+MAX:.+)?$/);if(e)return{main:e[1].trim(),suffix:(null===(t=e[2])||void 0===t?void 0:t.trim())||""}}return{main:s,suffix:""}},[d,l,s]),x=b(()=>`url("data:image/svg+xml,%3Csvg width='6' height='${r}' xmlns='http://www.w3.org/2000/svg'%3E%3Cline x1='0' y1='${r/2}' x2='3' y2='${r/2}' stroke='${encodeURIComponent(c)}' stroke-width='1'/%3E%3C/svg%3E")`,[c,r]),C=b(()=>({container:{position:"relative",height:r+"px",backgroundColor:u,overflow:"hidden",backgroundImage:x,backgroundRepeat:"repeat-x",backgroundPosition:"left center",backgroundSize:`8px ${r}px`},canvas:{display:"block",width:"100%",height:r+"px",position:"relative",zIndex:1},gradient:{position:"absolute",top:0,left:0,width:"80px",height:"100%",background:`linear-gradient(90deg, ${u}ee 0%, ${u}b3 70%, ${u}00 100%)`,pointerEvents:"none",zIndex:2},overlay:{position:"absolute",top:"3px",left:"3px",fontFamily:"monospace",pointerEvents:"none",zIndex:3,maxWidth:"95%"},label:{fontSize:v+"px",color:"#999",lineHeight:v+1+"px",display:"flex",alignItems:"baseline",gap:"4px"},labelMain:{flexShrink:0},labelSuffix:{fontSize:Math.max(7,v-1)+"px",opacity:.7,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flexShrink:1},value:{fontSize:h+"px",fontWeight:"bold",color:e,lineHeight:h+2+"px"}}),[r,u,c,v,h,e,x]);return g(()=>{const r=p.current;if(!r)return;const s=r.getContext("2d",{alpha:!0});if(!s)return;let l=!0;const a=()=>{if(!l||!r)return;const o=r.getBoundingClientRect();if(0===o.width||0===o.height)return f.current=requestAnimationFrame(a),void 0;const u=window.devicePixelRatio||1,c=o.width,h=o.height;if(r.width===c*u&&r.height===h*u||(r.width=c*u,r.height=h*u,s.scale(u,u)),s.clearRect(0,0,c,h),t.getCount()>1){s.strokeStyle=e,s.lineWidth=1.5,s.lineCap="round",s.lineJoin="round",s.beginPath();const r=c/(t.size-1),l=n-i||1;let a=!0;t.forEachValue((t,e)=>{const n=e*r,o=h-Math.max(0,Math.min(1,(t-i)/l))*h;a?(s.moveTo(n,o),a=!1):s.lineTo(n,o)}),s.stroke()}l&&(f.current=requestAnimationFrame(a))};return a(),()=>{l=!1,f.current&&cancelAnimationFrame(f.current)}},[t,e,i,n]),j("div",{style:C.container,children:[O("canvas",{ref:p,style:C.canvas}),O("div",{style:C.gradient}),j("div",{style:C.overlay,children:[j("div",{style:C.label,children:[O("span",{style:C.labelMain,children:y.main}),y.suffix&&O("span",{style:C.labelSuffix,children:y.suffix})]}),O("div",{style:C.value,children:w})]})]})}function s({stats:t,options:e,configs:i}){var n,s;const l=null!==(n=e.columns)&&void 0!==n?n:2,a=Math.max(1,Math.min(l,8)),o=null!==(s=e.showFullLabels)&&void 0!==s&&s,u=i.filter(i=>"vsync"!==i.key&&(!("compute"===i.key&&!e.trackCompute)&&null!=t[i.key]));return O("div",{style:U.graphGridContainer(a),children:u.map(i=>{const n=W.buffers[i.key];if(!n)return null;const s="gpu"===i.key&&e.gpuPercentage?t.gpuPercent||0:t[i.key],l=!1!==e.showColors&&i.color?i.color(s,null):e.defaultColor||"#999";return O("div",{style:U.graphItemContainer,children:O(r,{data:n,color:l,min:i.graphMin||0,max:i.graphMax?i.graphMax(null):100,height:e.graphHeight||48,label:i.shortLabel||i.label,fullLabel:o&&i.labelSuffix?`${i.label} ${i.labelSuffix}`:i.label,unit:i.unit||"",currentValue:s,backgroundColor:e.graphBackgroundColor,gridColor:e.graphGridColor,fontSize:e.fontSize,showFullLabel:o})},i.key)})})}function l({stats:t,options:e,configs:i}){var n,r;const s=null!==(r=null!==(n=e.columnsCompact)&&void 0!==n?n:e.columns)&&void 0!==r?r:4;return O("div",{style:U.statsCompactWrapper(Math.max(1,Math.min(s,8)),e.fontSize||11),children:i.map(i=>{const n="gpu"===i.key&&e.gpuPercentage?t.gpuPercent||0:t[i.key];if(null==n||Number.isNaN(n))return null;const r=!1!==e.showColors&&i.color?i.color(n,null):e.defaultColor||"#999999",s=i.format(n);return"vsync"===i.key&&n?O("div",{style:U.statItemCompact,children:j("span",{style:{fontSize:"9px",opacity:.5},children:[n,"Hz"]})},i.key):j("div",{style:U.statItemCompact,children:[j("span",{style:U.statLabelCompact,children:[i.shortLabel,":"]}),O("span",{style:Object.assign(Object.assign({},U.statValueCompact),{color:r,minWidth:"28px",fontFamily:"monospace"}),children:s})]},i.key)})})}function a({stats:t,options:e,configs:i}){var n;const r=null!==(n=e.columns)&&void 0!==n?n:2,s=!1!==e.showMinMax;return O("div",{style:U.statsContainer(Math.max(1,Math.min(r,8)),e.fontSize||12),children:i.map(i=>{const n="gpu"===i.key&&e.gpuPercentage?t.gpuPercent||0:t[i.key],r=W.buffers[i.key];if(null==n)return null;const l=!1!==e.showColors&&i.color?i.color(n,null):e.defaultColor;return j("div",{style:U.statItem,children:[j("div",{style:U.statLabel,children:[i.label,i.labelSuffix&&O("span",{style:U.labelSuffix,children:i.labelSuffix})]}),j("div",{style:Object.assign(Object.assign({},U.statValue),{color:l}),children:[i.format(n),s&&r&&j("span",{style:U.minMaxValue,children:[i.format(r.getMin()),"-",i.format(r.getMax())]})]})]},i.key)})})}function o({stats:r,options:o}){const u=b(()=>{return o.targetFramerate||((t=r.vsync)&&t>0?t:i()||("undefined"!=typeof window&&window.devicePixelRatio>2?90:60));var t},[o.targetFramerate,r.vsync]),c=b(()=>n(u,o.trianglesBudget,o.drawCallsBudget),[u,o.trianglesBudget,o.drawCallsBudget]),h=b(()=>t(o,c),[o,c]),d=b(()=>o.graphHeight&&o.graphHeight>0?o.compact?Object.assign(Object.assign({},o),{fontSize:o.fontSize||9,graphHeight:o.graphHeight||40,columns:o.columns||3}):o:null,[o.graphHeight,o.compact,o.fontSize,o.columns,o.graphBackgroundColor,o.graphGridColor,o.showColors,o.defaultColor,o.trianglesBudget,o.drawCallsBudget]);if(d){const t=b(()=>e(h,r,!1),[h,r]);return O(s,{stats:r,options:d,configs:t,thresholds:c})}const p=b(()=>e(h,r,o.compact),[h,r,o.compact]);return O(o.compact?l:a,{stats:r,options:o,configs:p})}function u(t={}){return E(Object.assign({updateInterval:100,targetFramerate:null,compact:!1,showColors:!0,defaultColor:"#999999",smoothing:!0,showMinMax:!0,trackCompute:!1,vsync:!0,order:-1,graphHeight:0,graphHistory:100,columns:void 0,columnsCompact:void 0,fontSize:void 0,aggressiveCount:!1,stats:{fps:{show:!0,order:0},ms:{show:!0,order:1},memory:{show:!0,order:2},gpu:{show:!0,order:3},cpu:{show:!0,order:4},compute:{show:!0,order:5},triangles:{show:!0,order:6},drawCalls:{show:!0,order:7},vsync:{show:!1,order:8}}},t))}function c(t,e){const i=M(t=>t.gl),n=m(0),r=m(0),s=m(new G(.05)),l=m(new R),a=m(new L(!1!==e.vsync)),o=m(new q),u=m(new q),c=m(null),h=m({frameTriangles:0,frameDrawCalls:0,originalRender:null}),d=!(!i||!i.isWebGPURenderer);t.webGPUState.current.isWebGPU=d,t.stats.current.isWebGPU=d,g(()=>{let t;"object"==typeof e.smoothing?t=e.smoothing:!0===e.smoothing?t={enabled:!0}:!1===e.smoothing&&(t={enabled:!1}),!1!==(null==t?void 0:t.enabled)&&(l.current=new R(t))},[e.smoothing]),S(()=>{var i;const l=performance.now(),o=t.stats.current;if(r.current>0){const t=s.current.update(l-r.current);o.ms=t,o.fps=1e3/t}if(r.current=l,n.current++,!1!==e.vsync&&n.current%30==0){const t=a.current.update(o.fps);null!==t&&(o.vsync=t)}(null===(i=window.performance)||void 0===i?void 0:i.memory)&&(o.memory=Math.round(window.performance.memory.usedJSHeapSize/1048576))}),g(()=>{if(!i)return;let n=null,r=!1,a=!0,p=null,f=null;const m=()=>{if(s.current.reset(),l.current.reset(),!d&&i.info){const t=i.info;if(c.current||(c.current=t.update),e.aggressiveCount){const e=o.current;t.update=function(t,i,n){c.current.call(this,t,i,n),e.triangles+=t/3,e.drawCalls+=1}}else{const e=u.current;e.reset(),t.update=function(t,n,r){c.current.call(this,t,n,r);const s=i.info.render;s.triangles>e.triangles&&(e.triangles=s.triangles),s.calls>e.drawCalls&&(e.drawCalls=s.calls)}}}d&&i.render&&!h.current.originalRender&&(h.current.originalRender=i.render.bind(i),i.render=function(...t){var e,n;const r=i.info,s=(null===(e=null==r?void 0:r.render)||void 0===e?void 0:e.triangles)||0,l=(null===(n=null==r?void 0:r.render)||void 0===n?void 0:n.calls)||0,a=h.current.originalRender.apply(this,t);if(null==r?void 0:r.render){const t=r.render.calls||0;h.current.frameTriangles=(r.render.triangles||0)-s,h.current.frameDrawCalls=t-l}return a})};if(!d){const e=i.domElement;p=()=>{r=!1,n&&(n=null),t.stats.current.gpuAccurate=!1,t.stats.current.gpu=0},f=()=>{m()},e.addEventListener("webglcontextlost",p),e.addEventListener("webglcontextrestored",f)}m();const b=z(()=>{if(r&&n&&!d)try{const t=i.getContext(),e=null==t?void 0:t.getExtension("EXT_disjoint_timer_query_webgl2");e&&t.endQuery(e.TIME_ELAPSED_EXT)}catch(s){}if(!d&&i.info)if(e.aggressiveCount){const e=o.current;t.stats.current.triangles=e.triangles,t.stats.current.drawCalls=e.drawCalls,e.reset()}else{const e=u.current;t.stats.current.triangles=e.triangles,t.stats.current.drawCalls=e.drawCalls,e.reset()}}),g=setInterval(()=>{var s,l,o;if(a){if(!d){const e=i.getContext();if(!e||(null===(s=e.isContextLost)||void 0===s?void 0:s.call(e)))return t.stats.current.gpuAccurate=!1,void 0}if(d){const n=i.info;(null===(l=null==n?void 0:n.render)||void 0===l?void 0:l.timestamp)?(t.stats.current.gpu=n.render.timestamp,t.stats.current.gpuAccurate=!0):t.stats.current.gpuAccurate=!1,e.trackCompute&&(null===(o=null==n?void 0:n.compute)||void 0===o?void 0:o.timestamp)&&(t.stats.current.compute=n.compute.timestamp),t.stats.current.triangles=h.current.frameTriangles,t.stats.current.drawCalls=h.current.frameDrawCalls}else{const e=i.getContext();if(!e)return;const s=e.getExtension("EXT_disjoint_timer_query_webgl2");if(s&&!r)try{e.getParameter(s.GPU_DISJOINT_EXT)||(n=e.createQuery(),n&&(e.beginQuery(s.TIME_ELAPSED_EXT,n),r=!0))}catch(u){t.stats.current.gpuAccurate=!1}if(n&&r)try{if(e.getQueryParameter(n,e.QUERY_RESULT_AVAILABLE)){const i=e.getQueryParameter(n,e.QUERY_RESULT)/1e6;t.stats.current.gpu=i,t.stats.current.gpuAccurate=!0,e.deleteQuery(n),n=null,r=!1}}catch(u){if(t.stats.current.gpuAccurate=!1,n){try{e.deleteQuery(n)}catch(c){}n=null,r=!1}}}}},16);return()=>{if(a=!1,clearInterval(g),b(),!d&&i.domElement&&(p&&i.domElement.removeEventListener("webglcontextlost",p),f&&i.domElement.removeEventListener("webglcontextrestored",f)),!d&&c.current&&i.info&&(i.info.update=c.current,c.current=null),d&&h.current.originalRender&&(i.render=h.current.originalRender,h.current.originalRender=null),o.current.reset(),u.current.reset(),n)try{const t=i.getContext();null==t?void 0:t.deleteQuery(n)}catch(t){}}},[i,d,e.trackCompute,e.aggressiveCount]),g(()=>{let i=!0;const n=e.updateInterval||100;let r=0;const s=()=>{if(!i)return;const a=performance.now();if(n>a-r)return requestAnimationFrame(s),void 0;r=a;const o=t.stats.current;let u=!1;!0===e.smoothing?u=!0:!1===e.smoothing?u=!1:"object"==typeof e.smoothing&&(u=!1!==e.smoothing.enabled);const c={fps:o.fps,ms:o.ms,memory:u?l.current.smooth("memory",o.memory):o.memory,gpu:u&&o.gpu>0?l.current.smooth("gpu",o.gpu):o.gpu,compute:u&&o.compute>0?l.current.smooth("compute",o.compute):o.compute,triangles:u?l.current.smooth("triangles",o.triangles):o.triangles,drawCalls:u?l.current.smooth("drawCalls",o.drawCalls):o.drawCalls,vsync:o.vsync,isWebGPU:o.isWebGPU,gpuAccurate:o.gpuAccurate},h=c.ms>0?c.gpu/c.ms*100:0,d=c.gpuAccurate&&c.gpu>0?Math.max(0,c.ms-c.gpu):0;W.update(Object.assign(Object.assign({},c),{gpuPercent:u?l.current.smooth("gpuPercent",h):h,cpu:u&&d>0?l.current.smooth("cpu",d):d})),i&&requestAnimationFrame(s)};return requestAnimationFrame(s),()=>{i=!1}},[t,e.updateInterval,e.smoothing])}function h(t={}){const e=m(null),i=m(null),n={stats:m({fps:0,ms:0,memory:0,gpu:0,cpu:0,compute:0,triangles:0,drawCalls:0,vsync:null,isWebGPU:!1,gpuAccurate:!1,frameTimestamps:[],prevTime:performance.now(),frameStartTime:0}),webGPUState:m({isWebGPU:!1,hasTimestampQuery:!1}),gpuTimingState:m({available:!1,ext:null,query:null,queryInProgress:!1,lastGPUTime:0}),vsyncDetector:m(null),createdQueries:m([])};return g(()=>(e.current=Object.assign(Object.assign({},W.buffers),{destroy(){}}),()=>{var t;null===(t=e.current)||void 0===t?void 0:t.destroy(),e.current=null}),[t.graphHistory]),g(()=>(i.current=W.registerInstance(),()=>{var t;null===(t=i.current)||void 0===t?void 0:t.call(i)}),[]),d(t),g(()=>(W.getInstanceCount(),()=>{}),[]),c(n,{vsync:t.vsync,trackCompute:t.trackCompute,updateInterval:t.updateInterval,aggressiveCount:t.aggressiveCount,smoothing:t.smoothing}),g(()=>()=>{W.reset()},[]),null}function d(t){var e;const i=m("Performance_"+Math.random().toString(36).substr(2,9));try{const n=u(t);if(!n)return void 0,void 0;y({[i.current]:n},{order:null!==(e=t.order)&&void 0!==e?e:-1},[])}catch(n){void 0}}function p(t,e){return i=this,n=arguments,s=function*(t,e,i={}){const{name:n="compute",autoReport:r=!0}=i,s=performance.now();try{const i=yield e(),l=performance.now()-s;return r&&(null==t?void 0:t.info)&&(t.info[n]||(t.info[n]={}),t.info[n].timestamp=l),{result:i,elapsed:l}}catch(l){const e=performance.now()-s;throw r&&(null==t?void 0:t.info)&&(t.info[n]||(t.info[n]={}),t.info[n].timestamp=e,t.info[n].error=!0),l}},new((r=void 0)||(r=Promise))((t,e)=>{function l(t){try{o(s.next(t))}catch(i){e(i)}}function a(t){try{o(s.throw(t))}catch(i){e(i)}}function o(e){var i;e.done?t(e.value):(i=e.value,i instanceof r?i:new r(t=>{t(i)})).then(l,a)}o((s=s.apply(i,n||[])).next())});var i,n,r,s}function f(t,e={}){return w(i=>p(t,i,e),[t,e])}import{useRef as m,useMemo as b,useEffect as g,useState as v,useCallback as w}from"react";import{useControls as y}from"leva";import{useInputContext as x,createPlugin as C}from"leva/plugin";import{jsxs as j,jsx as O}from"react/jsx-runtime";import{useThree as M,useFrame as S,addAfterEffect as z}from"@react-three/fiber";class k{constructor(t){Object.defineProperty(this,"buffer",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"pointer",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"filled",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"size",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"min",{enumerable:!0,configurable:!0,writable:!0,value:1/0}),Object.defineProperty(this,"max",{enumerable:!0,configurable:!0,writable:!0,value:-1/0}),Object.defineProperty(this,"sum",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"count",{enumerable:!0,configurable:!0,writable:!0,value:0}),this.size=t,this.buffer=new Float32Array(t)}push(t){if(this.filled){const t=this.buffer[this.pointer];this.sum-=t,t!==this.min&&t!==this.max||this.recalculateStats()}this.buffer[this.pointer]=t,this.sum+=t,this.min=Math.min(this.min,t),this.max=Math.max(this.max,t),this.pointer=(this.pointer+1)%this.size,0===this.pointer&&(this.filled=!0),this.count=this.filled?this.size:this.pointer}recalculateStats(){this.min=1/0,this.max=-1/0,this.sum=0,this.forEachValue(t=>{this.min=Math.min(this.min,t),this.max=Math.max(this.max,t),this.sum+=t})}resize(t){if(t===this.size)return;const e=this.getData();this.size=t,this.buffer=new Float32Array(t),this.pointer=0,this.filled=!1,this.min=1/0,this.max=-1/0,this.sum=0;const i=Math.min(e.length,t),n=Math.max(0,e.length-i);for(let r=0;i>r;r++)this.push(e[n+r])}getLatest(){return 0===this.count?0:this.buffer[(this.pointer-1+this.size)%this.size]}getData(){if(0===this.count)return new Float32Array(0);if(!this.filled)return this.buffer.slice(0,this.pointer);const t=new Float32Array(this.size);for(let e=0;this.size>e;e++)t[e]=this.buffer[(this.pointer+e)%this.size];return t}forEachValue(t){if(0!==this.count)if(this.filled)for(let e=0;this.size>e;e++)t(this.buffer[(this.pointer+e)%this.size],e);else for(let e=0;this.pointer>e;e++)t(this.buffer[e],e)}getMin(){return this.count>0&&isFinite(this.min)?this.min:0}getMax(){return this.count>0&&isFinite(this.max)?this.max:0}getAverage(){return this.count>0?this.sum/this.count:0}getCount(){return this.count}clear(){this.pointer=0,this.filled=!1,this.min=1/0,this.max=-1/0,this.sum=0,this.count=0}destroy(){this.clear()}}const W=new class{constructor(){Object.defineProperty(this,"listeners",{enumerable:!0,configurable:!0,writable:!0,value:new Set}),Object.defineProperty(this,"data",{enumerable:!0,configurable:!0,writable:!0,value:{fps:0,ms:0,memory:0,gpu:0,cpu:0,compute:0,triangles:0,drawCalls:0,vsync:null,isWebGPU:!1,gpuAccurate:!1}}),Object.defineProperty(this,"buffers",{enumerable:!0,configurable:!0,writable:!0,value:{fps:new k(100),ms:new k(100),memory:new k(100),gpuPercent:new k(100),gpu:new k(100),cpu:new k(100),compute:new k(100),triangles:new k(100),drawCalls:new k(100)}}),Object.defineProperty(this,"peaks",{enumerable:!0,configurable:!0,writable:!0,value:{triangles:0,drawCalls:0,lastReset:Date.now()}}),Object.defineProperty(this,"instanceCount",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"updateScheduled",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"pendingUpdates",{enumerable:!0,configurable:!0,writable:!0,value:{}})}subscribe(t){return this.listeners.add(t),t(this.data),()=>this.listeners.delete(t)}update(t){Object.assign(this.pendingUpdates,t),this.updateScheduled||(this.updateScheduled=!0,queueMicrotask(()=>this.flushUpdates()))}flushUpdates(){void 0!==this.pendingUpdates.triangles&&this.pendingUpdates.triangles>this.peaks.triangles&&(this.peaks.triangles=this.pendingUpdates.triangles),void 0!==this.pendingUpdates.drawCalls&&this.pendingUpdates.drawCalls>this.peaks.drawCalls&&(this.peaks.drawCalls=this.pendingUpdates.drawCalls),this.data=Object.assign(Object.assign({},this.data),this.pendingUpdates),Object.entries(this.pendingUpdates).forEach(([t,e])=>{t in this.buffers&&"number"==typeof e&&this.buffers[t].push(e)}),this.listeners.forEach(t=>{try{t(this.data)}catch(e){void 0}}),this.pendingUpdates={},this.updateScheduled=!1}get(){return this.data}getPeaks(){return Object.assign({},this.peaks)}resetPeaks(){this.peaks={triangles:this.data.triangles,drawCalls:this.data.drawCalls,lastReset:Date.now()}}resizeBuffers(t){Object.values(this.buffers).forEach(e=>e.resize(t))}reset(){this.update({fps:0,ms:0,memory:0,gpu:0,cpu:0,compute:0,triangles:0,drawCalls:0,vsync:null,isWebGPU:!1,gpuAccurate:!1}),Object.values(this.buffers).forEach(t=>t.clear()),this.peaks={triangles:0,drawCalls:0,lastReset:Date.now()}}registerInstance(){return this.instanceCount++,()=>{this.instanceCount--,0===this.instanceCount&&(this.reset(),this.listeners.clear())}}getInstanceCount(){return this.instanceCount}},F=t=>({fps:"FPS",ms:"MS",memory:"MEM",gpu:t.gpuPercentage?"GPU%":"GPU",cpu:"CPU",compute:"COMP",triangles:"TRI",drawCalls:"DRW",vsync:"VSYNC"}),I={fps(t){return t.toFixed(0)},ms(t){return t.toFixed(1)},memory(t){return t.toFixed(0)},gpu(t,e){return(null==e?void 0:e.gpuPercentage)?t.toFixed(0)+"%":t.toFixed(1)},cpu(t){return t.toFixed(1)},compute(t){return t.toFixed(1)},triangles(t){return 1e9>t?1e6>t?1e3>t?""+t:(t/1e3).toFixed(1)+"K":(t/1e6).toFixed(1)+"M":(t/1e9).toFixed(1)+"B"},drawCalls(t){return t.toFixed(0)},vsync(t){return t?t+"Hz":"Detecting..."}},P=(t,e,i,n=!1)=>{const r=n?(i-t)/(i-e):(t-e)/(i-e);return r>0?1>r?"#ffd93d":"#ff6b6b":"#51cf66"},A={fpsWarning:48,fpsCritical:30,msWarning:20,msCritical:33,gpuWarning:20,gpuCritical:33,targetFPS:60,targetMS:16.67,trianglesBudget:1e6,drawCallsBudget:1e3,trianglesWarning:8e5,trianglesCritical:12e5,drawCallsWarning:800,drawCallsCritical:1200};let $=null,T=!1;const D={fontFamily:"monospace",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"4px"},U={statsContainer(t,e){return{display:"grid",gridTemplateColumns:`repeat(${t}, 1fr)`,gap:"8px",padding:"8px",width:"100%",fontFamily:"monospace",fontSize:e+"px",boxSizing:"border-box",overflow:"hidden"}},statsCompactWrapper(t,e){return{display:"grid",gridTemplateColumns:`repeat(${t}, 1fr)`,gap:"8px",padding:"4px 8px",width:"100%",fontFamily:"monospace",fontSize:e+"px"}},graphGridContainer(t){return{display:"grid",gridTemplateColumns:`repeat(${t}, 1fr)`,gap:"8px",padding:"4px",width:"100%",boxSizing:"border-box",overflow:"hidden"}},statItem:Object.assign(Object.assign({display:"flex",flexDirection:"column",padding:"6px"},D),{minWidth:0}),statItemCompact:{display:"flex",alignItems:"center",gap:"2px",overflow:"hidden"},graphItemContainer:Object.assign(Object.assign({},D),{padding:"4px",overflow:"hidden"}),statLabel:{fontSize:"0.85em",opacity:.7,color:"#aaa",marginBottom:"2px",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},statLabelCompact:{opacity:.6,color:"#999999",fontWeight:"normal",whiteSpace:"nowrap",fontSize:"inherit"},statValue:{fontSize:"1em",fontWeight:"bold",fontFamily:"monospace",display:"flex",alignItems:"baseline",gap:"4px"},statValueCompact:{fontWeight:"bold",fontFamily:"monospace",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",maxWidth:"50px",fontSize:"inherit"},labelSuffix:{fontSize:"0.8em",opacity:.85,marginLeft:"10px",letterSpacing:"-0.02em",fontWeight:"normal",whiteSpace:"nowrap"},minMaxValue:{fontSize:"0.75em",letterSpacing:"-0.02em",marginLeft:"6px",opacity:.85,fontWeight:"normal",whiteSpace:"nowrap"},canvas:{display:"block",width:"100%"}},E=C({component(){const t=x(),[e,i]=v(W.get()),n=m(null),r=m(e),s=m(null),l=m(Date.now()),a=b(()=>({updateInterval:50,smoothing:!0,targetFramerate:null,compact:!1,showColors:!0,defaultColor:"#999999",showMinMax:!0,trackCompute:!1,vsync:!0,graphHeight:0,graphHistory:100,fontSize:void 0,stats:{fps:{show:!0,order:0},ms:{show:!0,order:1},memory:{show:!0,order:2},gpu:{show:!0,order:3},cpu:{show:!0,order:4},compute:{show:!0,order:5},triangles:{show:!0,order:6},drawCalls:{show:!0,order:7},vsync:{show:!1,order:8}}}),[]),u=b(()=>t&&t.value?Object.assign(Object.assign({},a),"object"==typeof t.value&&"value"in t.value?t.value.value:t.value):a,[t,a]);return g(()=>{let t=null;const e=()=>{t=W.subscribe(t=>{r.current=t,l.current=Date.now(),n.current||(n.current=setTimeout(()=>{i(r.current),n.current=null},16))})};e();const a=setInterval(()=>{Date.now()-l.current>1e3&&(t&&t(),e())},1e3);return()=>{clearInterval(a),t&&t(),n.current&&(clearTimeout(n.current),n.current=null),s.current&&(clearTimeout(s.current),s.current=null)}},[]),O(o,{stats:e,options:u})}});class L{constructor(t=!0){Object.defineProperty(this,"enabled",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"samples",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"SAMPLE_SIZE",{enumerable:!0,configurable:!0,writable:!0,value:30}),this.enabled=t}update(t){if(!this.enabled||!t||0>=t)return null;if(this.samples.push(t),this.samples.length>this.SAMPLE_SIZE&&this.samples.shift(),this.SAMPLE_SIZE>this.samples.length)return null;const e=this.samples.reduce((t,e)=>t+e)/this.samples.length,i=[30,60,72,75,90,120,144,165,240];for(const n of i)if(2>Math.abs(e-n))return n;return null}reset(){this.samples=[]}}class q{constructor(){Object.defineProperty(this,"triangles",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"drawCalls",{enumerable:!0,configurable:!0,writable:!0,value:0})}reset(){this.triangles=0,this.drawCalls=0}hasData(){return this.drawCalls>0}}class G{constructor(t=.1){Object.defineProperty(this,"alpha",{enumerable:!0,configurable:!0,writable:!0,value:t}),Object.defineProperty(this,"value",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"initialized",{enumerable:!0,configurable:!0,writable:!0,value:!1})}update(t){return this.initialized?(this.value=this.alpha*t+(1-this.alpha)*this.value,this.value):(this.value=t,this.initialized=!0,t)}reset(){this.initialized=!1,this.value=0}}class H{constructor(t=.01){Object.defineProperty(this,"lastValue",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"threshold",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.threshold=t}filter(t){return Math.abs(t-this.lastValue)>this.threshold&&(this.lastValue=t),this.lastValue}reset(){this.lastValue=0}}class R{constructor(t){Object.defineProperty(this,"smoothers",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"filters",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"alphas",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.alphas=(null==t?void 0:t.aggressive)?{fps:.03,ms:.03,memory:.01,gpu:.05,cpu:.05,compute:.05,triangles:.1,drawCalls:.1}:{fps:.05,ms:.05,memory:.02,gpu:.08,cpu:.08,compute:.08,triangles:.15,drawCalls:.15},(null==t?void 0:t.custom)&&Object.assign(this.alphas,t.custom)}smooth(t,e){if(!this.smoothers.has(t)){this.smoothers.set(t,new G(this.alphas[t]||.1));let e=.01;"memory"===t?e=.5:"triangles"!==t&&"drawCalls"!==t||(e=1),this.filters.set(t,new H(e))}const i=this.smoothers.get(t).update(e);return this.filters.get(t).filter(i)}reset(){this.smoothers.forEach(t=>t.reset()),this.filters.forEach(t=>t.reset())}}export{u as stats,E as statsPlugin,p as trackComputeTime,f as useComputeTracker,h as useStatsPanel};//# sourceMappingURL=index.esm.js.map