leva-r3f-stats
Version:
A small plugin to display React Three Fiber stats in Leva
2 lines (1 loc) • 28.1 kB
JavaScript
function e(e,t=j){const i=e.stats||{},n=w.getPeaks(),r=y(e);return Object.entries(r).filter(([t])=>{var n;return!("compute"===t&&!e.trackCompute||"vsync"===t&&!1===e.vsync||!1===(null===(n=i[t])||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=e=>C(e,t.fpsCritical,t.fpsWarning,!0),p=1.2*t.targetFPS,d="MAX: "+t.targetFPS;break;case"ms":h=e=>C(e,t.msWarning,t.msCritical),p=2*t.targetMS,d=`MAX: ${t.targetMS.toFixed(1)}ms`;break;case"gpu":e.gpuPercentage?(h=e=>e>90?"#ff6b6b":e>70?"#ffd93d":"#51cf66",p=100,d=""):(h=e=>C(e,t.msWarning,t.msCritical),p=2*t.targetMS);break;case"cpu":h=e=>C(e,t.msWarning,t.msCritical),p=2*t.targetMS;break;case"triangles":h=e=>C(e,t.trianglesWarning,t.trianglesCritical),p=Math.max(1.5*t.trianglesBudget,1.2*n.triangles),d=n.triangles>0?"MAX: "+x.triangles(n.triangles):"MAX: "+x.triangles(t.trianglesBudget);break;case"drawCalls":h=e=>C(e,t.drawCallsWarning,t.drawCallsCritical),p=Math.max(1.5*t.drawCallsBudget,1.2*n.drawCalls),d=n.drawCalls>0?"MAX: "+n.drawCalls:"MAX: "+t.drawCallsBudget}return{key:u,label:l,labelSuffix:d,shortLabel:l,unit:"memory"===u?"MB":"vsync"===u?"Hz":"",format:x[u],color:h,show:!0,order:c,showInCompact:"cpu"!==u&&"vsync"!==u,graphMin:0,graphMax(){return p}}}).sort((e,t)=>e.order-t.order)}function t(e,t,i=!1){return e.filter(e=>!(i&&!e.showInCompact||!("compute"!==e.key||t.isWebGPU&&0!==t.compute)||"cpu"===e.key&&!t.gpuAccurate))}function i(){var e,t,i;if(null!==O)return O;if(!M){M=!0;try{if("undefined"!=typeof window&&(null===(e=window.screen)||void 0===e?void 0:e.refreshRate)){const e=window.screen.refreshRate;if(e&&e>0)return O=e,e}if("undefined"!=typeof window){const e=[165,144,120,90,75,72];for(const t of e)if(window.matchMedia(`(min-resolution: ${t-5}dpi) and (max-resolution: ${t+5}dpi)`).matches)return O=t,t;if(window.matchMedia("(prefers-reduced-motion: no-preference) and (update: fast)").matches)return window.devicePixelRatio>2?(O=90,90):(O=120,120)}"undefined"!=typeof window&&"getScreenDetails"in window&&(null===(i=(t=window).getScreenDetails)||void 0===i?void 0:i.call(t).then(e=>{var t;(null===(t=null==e?void 0:e.currentScreen)||void 0===t?void 0:t.refreshRate)&&(O=e.currentScreen.refreshRate)}).catch(()=>{}))}catch(n){}}return null}function n(e,t,i){const n=1e3/e,r=t||1e6,s=i||500;return{fpsWarning:.8*e,fpsCritical:.5*e,msWarning:1.2*n,msCritical:1.5*n,gpuWarning:1.2*n,gpuCritical:1.5*n,targetFPS:e,targetMS:n,trianglesBudget:r,drawCallsBudget:s,trianglesWarning:.8*r,trianglesCritical:1.2*r,drawCallsWarning:.8*s,drawCallsCritical:1.2*s}}function r({data:e,color:t,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 f=p.useRef(null),b=p.useRef(),g=Math.max(8,h-1),v=`${o.toFixed(1)}${a}`,w=p.useMemo(()=>{var e;if(d&&l){const t=l.match(/^(.+?)(\s+MAX:.+)?$/);if(t)return{main:t[1].trim(),suffix:(null===(e=t[2])||void 0===e?void 0:e.trim())||""}}return{main:s,suffix:""}},[d,l,s]),y=p.useMemo(()=>`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]),x=p.useMemo(()=>({container:{position:"relative",height:r+"px",backgroundColor:u,overflow:"hidden",backgroundImage:y,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:g+"px",color:"#999",lineHeight:g+1+"px",display:"flex",alignItems:"baseline",gap:"4px"},labelMain:{flexShrink:0},labelSuffix:{fontSize:Math.max(7,g-1)+"px",opacity:.7,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flexShrink:1},value:{fontSize:h+"px",fontWeight:"bold",color:t,lineHeight:h+2+"px"}}),[r,u,c,g,h,t,y]);return p.useEffect(()=>{const r=f.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 b.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),e.getCount()>1){s.strokeStyle=t,s.lineWidth=1.5,s.lineCap="round",s.lineJoin="round",s.beginPath();const r=c/(e.size-1),l=n-i||1;let a=!0;e.forEachValue((e,t)=>{const n=t*r,o=h-Math.max(0,Math.min(1,(e-i)/l))*h;a?(s.moveTo(n,o),a=!1):s.lineTo(n,o)}),s.stroke()}l&&(b.current=requestAnimationFrame(a))};return a(),()=>{l=!1,b.current&&cancelAnimationFrame(b.current)}},[e,t,i,n]),m.jsxs("div",{style:x.container,children:[m.jsx("canvas",{ref:f,style:x.canvas}),m.jsx("div",{style:x.gradient}),m.jsxs("div",{style:x.overlay,children:[m.jsxs("div",{style:x.label,children:[m.jsx("span",{style:x.labelMain,children:w.main}),w.suffix&&m.jsx("span",{style:x.labelSuffix,children:w.suffix})]}),m.jsx("div",{style:x.value,children:v})]})]})}function s({stats:e,options:t,configs:i}){var n,s;const l=null!==(n=t.columns)&&void 0!==n?n:2,a=Math.max(1,Math.min(l,8)),o=null!==(s=t.showFullLabels)&&void 0!==s&&s,u=i.filter(i=>"vsync"!==i.key&&(!("compute"===i.key&&!t.trackCompute)&&null!=e[i.key]));return m.jsx("div",{style:z.graphGridContainer(a),children:u.map(i=>{const n=w.buffers[i.key];if(!n)return null;const s="gpu"===i.key&&t.gpuPercentage?e.gpuPercent||0:e[i.key],l=!1!==t.showColors&&i.color?i.color(s,null):t.defaultColor||"#999";return m.jsx("div",{style:z.graphItemContainer,children:m.jsx(r,{data:n,color:l,min:i.graphMin||0,max:i.graphMax?i.graphMax(null):100,height:t.graphHeight||48,label:i.shortLabel||i.label,fullLabel:o&&i.labelSuffix?`${i.label} ${i.labelSuffix}`:i.label,unit:i.unit||"",currentValue:s,backgroundColor:t.graphBackgroundColor,gridColor:t.graphGridColor,fontSize:t.fontSize,showFullLabel:o})},i.key)})})}function l({stats:e,options:t,configs:i}){var n,r;const s=null!==(r=null!==(n=t.columnsCompact)&&void 0!==n?n:t.columns)&&void 0!==r?r:4;return m.jsx("div",{style:z.statsCompactWrapper(Math.max(1,Math.min(s,8)),t.fontSize||11),children:i.map(i=>{const n="gpu"===i.key&&t.gpuPercentage?e.gpuPercent||0:e[i.key];if(null==n||Number.isNaN(n))return null;const r=!1!==t.showColors&&i.color?i.color(n,null):t.defaultColor||"#999999",s=i.format(n);return"vsync"===i.key&&n?m.jsx("div",{style:z.statItemCompact,children:m.jsxs("span",{style:{fontSize:"9px",opacity:.5},children:[n,"Hz"]})},i.key):m.jsxs("div",{style:z.statItemCompact,children:[m.jsxs("span",{style:z.statLabelCompact,children:[i.shortLabel,":"]}),m.jsx("span",{style:Object.assign(Object.assign({},z.statValueCompact),{color:r,minWidth:"28px",fontFamily:"monospace"}),children:s})]},i.key)})})}function a({stats:e,options:t,configs:i}){var n;const r=null!==(n=t.columns)&&void 0!==n?n:2,s=!1!==t.showMinMax;return m.jsx("div",{style:z.statsContainer(Math.max(1,Math.min(r,8)),t.fontSize||12),children:i.map(i=>{const n="gpu"===i.key&&t.gpuPercentage?e.gpuPercent||0:e[i.key],r=w.buffers[i.key];if(null==n)return null;const l=!1!==t.showColors&&i.color?i.color(n,null):t.defaultColor;return m.jsxs("div",{style:z.statItem,children:[m.jsxs("div",{style:z.statLabel,children:[i.label,i.labelSuffix&&m.jsx("span",{style:z.labelSuffix,children:i.labelSuffix})]}),m.jsxs("div",{style:Object.assign(Object.assign({},z.statValue),{color:l}),children:[i.format(n),s&&r&&m.jsxs("span",{style:z.minMaxValue,children:[i.format(r.getMin()),"-",i.format(r.getMax())]})]})]},i.key)})})}function o({stats:r,options:o}){const u=p.useMemo(()=>{return o.targetFramerate||((e=r.vsync)&&e>0?e:i()||("undefined"!=typeof window&&window.devicePixelRatio>2?90:60));var e},[o.targetFramerate,r.vsync]),c=p.useMemo(()=>n(u,o.trianglesBudget,o.drawCallsBudget),[u,o.trianglesBudget,o.drawCallsBudget]),h=p.useMemo(()=>e(o,c),[o,c]),d=p.useMemo(()=>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 e=p.useMemo(()=>t(h,r,!1),[h,r]);return m.jsx(s,{stats:r,options:d,configs:e,thresholds:c})}const f=p.useMemo(()=>t(h,r,o.compact),[h,r,o.compact]);return m.jsx(o.compact?l:a,{stats:r,options:o,configs:f})}function u(e={}){return k(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}}},e))}function c(e,t){const i=g.useThree(e=>e.gl),n=p.useRef(0),r=p.useRef(0),s=p.useRef(new I(.05)),l=p.useRef(new A),a=p.useRef(new W(!1!==t.vsync)),o=p.useRef(new F),u=p.useRef(new F),c=p.useRef(null),h=p.useRef({frameTriangles:0,frameDrawCalls:0,originalRender:null}),d=!(!i||!i.isWebGPURenderer);e.webGPUState.current.isWebGPU=d,e.stats.current.isWebGPU=d,p.useEffect(()=>{let e;"object"==typeof t.smoothing?e=t.smoothing:!0===t.smoothing?e={enabled:!0}:!1===t.smoothing&&(e={enabled:!1}),!1!==(null==e?void 0:e.enabled)&&(l.current=new A(e))},[t.smoothing]),g.useFrame(()=>{var i;const l=performance.now(),o=e.stats.current;if(r.current>0){const e=s.current.update(l-r.current);o.ms=e,o.fps=1e3/e}if(r.current=l,n.current++,!1!==t.vsync&&n.current%30==0){const e=a.current.update(o.fps);null!==e&&(o.vsync=e)}(null===(i=window.performance)||void 0===i?void 0:i.memory)&&(o.memory=Math.round(window.performance.memory.usedJSHeapSize/1048576))}),p.useEffect(()=>{if(!i)return;let n=null,r=!1,a=!0,p=null,f=null;const b=()=>{if(s.current.reset(),l.current.reset(),!d&&i.info){const e=i.info;if(c.current||(c.current=e.update),t.aggressiveCount){const t=o.current;e.update=function(e,i,n){c.current.call(this,e,i,n),t.triangles+=e/3,t.drawCalls+=1}}else{const t=u.current;t.reset(),e.update=function(e,n,r){c.current.call(this,e,n,r);const s=i.info.render;s.triangles>t.triangles&&(t.triangles=s.triangles),s.calls>t.drawCalls&&(t.drawCalls=s.calls)}}}d&&i.render&&!h.current.originalRender&&(h.current.originalRender=i.render.bind(i),i.render=function(...e){var t,n;const r=i.info,s=(null===(t=null==r?void 0:r.render)||void 0===t?void 0:t.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,e);if(null==r?void 0:r.render){const e=r.render.calls||0;h.current.frameTriangles=(r.render.triangles||0)-s,h.current.frameDrawCalls=e-l}return a})};if(!d){const t=i.domElement;p=()=>{r=!1,n&&(n=null),e.stats.current.gpuAccurate=!1,e.stats.current.gpu=0},f=()=>{b()},t.addEventListener("webglcontextlost",p),t.addEventListener("webglcontextrestored",f)}b();const m=g.addAfterEffect(()=>{if(r&&n&&!d)try{const e=i.getContext(),t=null==e?void 0:e.getExtension("EXT_disjoint_timer_query_webgl2");t&&e.endQuery(t.TIME_ELAPSED_EXT)}catch(s){}if(!d&&i.info)if(t.aggressiveCount){const t=o.current;e.stats.current.triangles=t.triangles,e.stats.current.drawCalls=t.drawCalls,t.reset()}else{const t=u.current;e.stats.current.triangles=t.triangles,e.stats.current.drawCalls=t.drawCalls,t.reset()}}),v=setInterval(()=>{var s,l,o;if(a){if(!d){const t=i.getContext();if(!t||(null===(s=t.isContextLost)||void 0===s?void 0:s.call(t)))return e.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)?(e.stats.current.gpu=n.render.timestamp,e.stats.current.gpuAccurate=!0):e.stats.current.gpuAccurate=!1,t.trackCompute&&(null===(o=null==n?void 0:n.compute)||void 0===o?void 0:o.timestamp)&&(e.stats.current.compute=n.compute.timestamp),e.stats.current.triangles=h.current.frameTriangles,e.stats.current.drawCalls=h.current.frameDrawCalls}else{const t=i.getContext();if(!t)return;const s=t.getExtension("EXT_disjoint_timer_query_webgl2");if(s&&!r)try{t.getParameter(s.GPU_DISJOINT_EXT)||(n=t.createQuery(),n&&(t.beginQuery(s.TIME_ELAPSED_EXT,n),r=!0))}catch(u){e.stats.current.gpuAccurate=!1}if(n&&r)try{if(t.getQueryParameter(n,t.QUERY_RESULT_AVAILABLE)){const i=t.getQueryParameter(n,t.QUERY_RESULT)/1e6;e.stats.current.gpu=i,e.stats.current.gpuAccurate=!0,t.deleteQuery(n),n=null,r=!1}}catch(u){if(e.stats.current.gpuAccurate=!1,n){try{t.deleteQuery(n)}catch(c){}n=null,r=!1}}}}},16);return()=>{if(a=!1,clearInterval(v),m(),!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 e=i.getContext();null==e?void 0:e.deleteQuery(n)}catch(e){}}},[i,d,t.trackCompute,t.aggressiveCount]),p.useEffect(()=>{let i=!0;const n=t.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=e.stats.current;let u=!1;!0===t.smoothing?u=!0:!1===t.smoothing?u=!1:"object"==typeof t.smoothing&&(u=!1!==t.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}},[e,t.updateInterval,t.smoothing])}function h(e){var t;const i=p.useRef("Performance_"+Math.random().toString(36).substr(2,9));try{const n=u(e);if(!n)return void 0,void 0;f.useControls({[i.current]:n},{order:null!==(t=e.order)&&void 0!==t?t:-1},[])}catch(n){void 0}}function d(e,t){return i=this,n=arguments,s=function*(e,t,i={}){const{name:n="compute",autoReport:r=!0}=i,s=performance.now();try{const i=yield t(),l=performance.now()-s;return r&&(null==e?void 0:e.info)&&(e.info[n]||(e.info[n]={}),e.info[n].timestamp=l),{result:i,elapsed:l}}catch(l){const t=performance.now()-s;throw r&&(null==e?void 0:e.info)&&(e.info[n]||(e.info[n]={}),e.info[n].timestamp=t,e.info[n].error=!0),l}},new((r=void 0)||(r=Promise))((e,t)=>{function l(e){try{o(s.next(e))}catch(i){t(i)}}function a(e){try{o(s.throw(e))}catch(i){t(i)}}function o(t){var i;t.done?e(t.value):(i=t.value,i instanceof r?i:new r(e=>{e(i)})).then(l,a)}o((s=s.apply(i,n||[])).next())});var i,n,r,s}var p=require("react"),f=require("leva"),b=require("leva/plugin"),m=require("react/jsx-runtime"),g=require("@react-three/fiber");class v{constructor(e){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=e,this.buffer=new Float32Array(e)}push(e){if(this.filled){const e=this.buffer[this.pointer];this.sum-=e,e!==this.min&&e!==this.max||this.recalculateStats()}this.buffer[this.pointer]=e,this.sum+=e,this.min=Math.min(this.min,e),this.max=Math.max(this.max,e),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(e=>{this.min=Math.min(this.min,e),this.max=Math.max(this.max,e),this.sum+=e})}resize(e){if(e===this.size)return;const t=this.getData();this.size=e,this.buffer=new Float32Array(e),this.pointer=0,this.filled=!1,this.min=1/0,this.max=-1/0,this.sum=0;const i=Math.min(t.length,e),n=Math.max(0,t.length-i);for(let r=0;i>r;r++)this.push(t[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 e=new Float32Array(this.size);for(let t=0;this.size>t;t++)e[t]=this.buffer[(this.pointer+t)%this.size];return e}forEachValue(e){if(0!==this.count)if(this.filled)for(let t=0;this.size>t;t++)e(this.buffer[(this.pointer+t)%this.size],t);else for(let t=0;this.pointer>t;t++)e(this.buffer[t],t)}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 v(100),ms:new v(100),memory:new v(100),gpuPercent:new v(100),gpu:new v(100),cpu:new v(100),compute:new v(100),triangles:new v(100),drawCalls:new v(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(e){return this.listeners.add(e),e(this.data),()=>this.listeners.delete(e)}update(e){Object.assign(this.pendingUpdates,e),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(([e,t])=>{e in this.buffers&&"number"==typeof t&&this.buffers[e].push(t)}),this.listeners.forEach(e=>{try{e(this.data)}catch(t){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(e){Object.values(this.buffers).forEach(t=>t.resize(e))}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(e=>e.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}},y=e=>({fps:"FPS",ms:"MS",memory:"MEM",gpu:e.gpuPercentage?"GPU%":"GPU",cpu:"CPU",compute:"COMP",triangles:"TRI",drawCalls:"DRW",vsync:"VSYNC"}),x={fps(e){return e.toFixed(0)},ms(e){return e.toFixed(1)},memory(e){return e.toFixed(0)},gpu(e,t){return(null==t?void 0:t.gpuPercentage)?e.toFixed(0)+"%":e.toFixed(1)},cpu(e){return e.toFixed(1)},compute(e){return e.toFixed(1)},triangles(e){return 1e9>e?1e6>e?1e3>e?""+e:(e/1e3).toFixed(1)+"K":(e/1e6).toFixed(1)+"M":(e/1e9).toFixed(1)+"B"},drawCalls(e){return e.toFixed(0)},vsync(e){return e?e+"Hz":"Detecting..."}},C=(e,t,i,n=!1)=>{const r=n?(i-e)/(i-t):(e-t)/(i-t);return r>0?1>r?"#ffd93d":"#ff6b6b":"#51cf66"},j={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 O=null,M=!1;const S={fontFamily:"monospace",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"4px"},z={statsContainer(e,t){return{display:"grid",gridTemplateColumns:`repeat(${e}, 1fr)`,gap:"8px",padding:"8px",width:"100%",fontFamily:"monospace",fontSize:t+"px",boxSizing:"border-box",overflow:"hidden"}},statsCompactWrapper(e,t){return{display:"grid",gridTemplateColumns:`repeat(${e}, 1fr)`,gap:"8px",padding:"4px 8px",width:"100%",fontFamily:"monospace",fontSize:t+"px"}},graphGridContainer(e){return{display:"grid",gridTemplateColumns:`repeat(${e}, 1fr)`,gap:"8px",padding:"4px",width:"100%",boxSizing:"border-box",overflow:"hidden"}},statItem:Object.assign(Object.assign({display:"flex",flexDirection:"column",padding:"6px"},S),{minWidth:0}),statItemCompact:{display:"flex",alignItems:"center",gap:"2px",overflow:"hidden"},graphItemContainer:Object.assign(Object.assign({},S),{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%"}},k=b.createPlugin({component(){const e=b.useInputContext(),[t,i]=p.useState(w.get()),n=p.useRef(null),r=p.useRef(t),s=p.useRef(null),l=p.useRef(Date.now()),a=p.useMemo(()=>({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=p.useMemo(()=>e&&e.value?Object.assign(Object.assign({},a),"object"==typeof e.value&&"value"in e.value?e.value.value:e.value):a,[e,a]);return p.useEffect(()=>{let e=null;const t=()=>{e=w.subscribe(e=>{r.current=e,l.current=Date.now(),n.current||(n.current=setTimeout(()=>{i(r.current),n.current=null},16))})};t();const a=setInterval(()=>{Date.now()-l.current>1e3&&(e&&e(),t())},1e3);return()=>{clearInterval(a),e&&e(),n.current&&(clearTimeout(n.current),n.current=null),s.current&&(clearTimeout(s.current),s.current=null)}},[]),m.jsx(o,{stats:t,options:u})}});class W{constructor(e=!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=e}update(e){if(!this.enabled||!e||0>=e)return null;if(this.samples.push(e),this.samples.length>this.SAMPLE_SIZE&&this.samples.shift(),this.SAMPLE_SIZE>this.samples.length)return null;const t=this.samples.reduce((e,t)=>e+t)/this.samples.length,i=[30,60,72,75,90,120,144,165,240];for(const n of i)if(2>Math.abs(t-n))return n;return null}reset(){this.samples=[]}}class F{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 I{constructor(e=.1){Object.defineProperty(this,"alpha",{enumerable:!0,configurable:!0,writable:!0,value:e}),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(e){return this.initialized?(this.value=this.alpha*e+(1-this.alpha)*this.value,this.value):(this.value=e,this.initialized=!0,e)}reset(){this.initialized=!1,this.value=0}}class P{constructor(e=.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=e}filter(e){return Math.abs(e-this.lastValue)>this.threshold&&(this.lastValue=e),this.lastValue}reset(){this.lastValue=0}}class A{constructor(e){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==e?void 0:e.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==e?void 0:e.custom)&&Object.assign(this.alphas,e.custom)}smooth(e,t){if(!this.smoothers.has(e)){this.smoothers.set(e,new I(this.alphas[e]||.1));let t=.01;"memory"===e?t=.5:"triangles"!==e&&"drawCalls"!==e||(t=1),this.filters.set(e,new P(t))}const i=this.smoothers.get(e).update(t);return this.filters.get(e).filter(i)}reset(){this.smoothers.forEach(e=>e.reset()),this.filters.forEach(e=>e.reset())}}exports.stats=u,exports.statsPlugin=k,exports.trackComputeTime=d,exports.useComputeTracker=(e,t={})=>p.useCallback(i=>d(e,i,t),[e,t]),exports.useStatsPanel=(e={})=>{const t=p.useRef(null),i=p.useRef(null),n={stats:p.useRef({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:p.useRef({isWebGPU:!1,hasTimestampQuery:!1}),gpuTimingState:p.useRef({available:!1,ext:null,query:null,queryInProgress:!1,lastGPUTime:0}),vsyncDetector:p.useRef(null),createdQueries:p.useRef([])};return p.useEffect(()=>(t.current=Object.assign(Object.assign({},w.buffers),{destroy(){}}),()=>{var e;null===(e=t.current)||void 0===e?void 0:e.destroy(),t.current=null}),[e.graphHistory]),p.useEffect(()=>(i.current=w.registerInstance(),()=>{var e;null===(e=i.current)||void 0===e?void 0:e.call(i)}),[]),h(e),p.useEffect(()=>(w.getInstanceCount(),()=>{}),[]),c(n,{vsync:e.vsync,trackCompute:e.trackCompute,updateInterval:e.updateInterval,aggressiveCount:e.aggressiveCount,smoothing:e.smoothing}),p.useEffect(()=>()=>{w.reset()},[]),null};//# sourceMappingURL=index.js.map