@dcl-regenesislabs/bevy-explorer-web 0.1.0-35857095341.commit-76a4f94 → 0.1.0-35987517326.commit-7fa64d1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/assets/{Showcase-CABgauPd.js → Showcase-BfxJWsCs.js} +1 -1
  2. package/assets/{design-BX8yaKxC.js → design-C0uJAczG.js} +1 -1
  3. package/assets/{index-Bthvqw3s.css → index-BqrUZqN4.css} +1 -1
  4. package/assets/{index-DgGH7dWN.js → index-DlppAQeK.js} +3 -3
  5. package/assets/{menus-DFHIIGSz.js → menus-MIy1chbp.js} +1 -1
  6. package/assets/{vendor-BJYt_uex.js → vendor-BCdBRHKw.js} +1 -1
  7. package/assets/{vendor-DWrzGrl8.css → vendor-zQph97Bl.css} +1 -1
  8. package/bridge-scene/static/BevyExplorerUI/about +1 -1
  9. package/bridge-scene/static/{bafkreics6nreaceg5dv3x3xjr4h3dr7y47z3epxatevje7zgspknwuw2lq → bafkreiae4chlakjjoty3cik5x2ffyvyfcixda4skjznqirqpacbhshjaki} +1 -1
  10. package/engine/boot.js +14 -5
  11. package/engine/engine.js +117 -48
  12. package/engine/gpu_cache.js +49 -28
  13. package/engine/pkg/manifest.json +1 -1
  14. package/engine/pkg/sandbox_worker.bundle.js +834 -289
  15. package/engine/pkg/snippets/bevy_internal-2d8ddab1173ada7c/src/web_worker.js +121 -0
  16. package/engine/pkg/snippets/comms-53217a45365bb5fa/livekit_web_bindings.js +47 -13
  17. package/engine/pkg/snippets/decentra-bevy-f9c23e535711925a/deploy/web/engine/gpu_cache.js +439 -0
  18. package/engine/pkg/webgpu_build.d.ts +97 -67
  19. package/engine/pkg/webgpu_build.js +413 -328
  20. package/engine/pkg/webgpu_build_bg.wasm +2 -2
  21. package/engine/pkg/webgpu_build_bg.wasm.d.ts +26 -25
  22. package/engine/sandbox_worker.js +3 -3
  23. package/index.html +17 -17
  24. package/package.json +3 -3
  25. package/engine/asset_loader.js +0 -30
  26. package/engine/asset_processor.js +0 -32
@@ -1,4 +1,4 @@
1
- import{t as e}from"./rolldown-runtime-D9-fqq9M.js";import{$ as t}from"./design-BX8yaKxC.js";var n=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0<n;){var r=n-1>>>1,a=e[r];if(0<i(a,t))e[r]=t,e[n]=a,n=r;else break a}}function n(e){return e.length===0?null:e[0]}function r(e){if(e.length===0)return null;var t=e[0],n=e.pop();if(n!==t){e[0]=n;a:for(var r=0,a=e.length,o=a>>>1;r<o;){var s=2*(r+1)-1,c=e[s],l=s+1,u=e[l];if(0>i(c,n))l<a&&0>i(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(l<a&&0>i(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,ee||(ee=!0,oe());else{var t=n(l);t!==null&&le(x,t.startTime-e)}}}var ee=!1,te=-1,ne=5,re=-1;function ie(){return g?!0:!(e.unstable_now()-re<ne)}function ae(){if(g=!1,ee){var t=e.unstable_now();re=t;var i=!0;try{a:{m=!1,h&&(h=!1,v(te),te=-1),p=!0;var a=f;try{b:{for(b(t),d=n(c);d!==null&&!(d.expirationTime>t&&ie());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&le(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?oe():ee=!1}}}var oe;if(typeof y==`function`)oe=function(){y(ae)};else if(typeof MessageChannel<`u`){var se=new MessageChannel,ce=se.port2;se.port1.onmessage=ae,oe=function(){ce.postMessage(null)}}else oe=function(){_(ae,0)};function le(t,n){te=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125<e?console.error(`forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported`):ne=0<e?Math.floor(1e3/e):5},e.unstable_getCurrentPriorityLevel=function(){return f},e.unstable_next=function(e){switch(f){case 1:case 2:case 3:var t=3;break;default:t=f}var n=f;f=t;try{return e()}finally{f=n}},e.unstable_requestPaint=function(){g=!0},e.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=f;f=e;try{return t()}finally{f=n}},e.unstable_scheduleCallback=function(r,i,a){var o=e.unstable_now();switch(typeof a==`object`&&a?(a=a.delay,a=typeof a==`number`&&0<a?o+a:o):a=o,r){case 1:var s=-1;break;case 2:s=250;break;case 5:s=1073741823;break;case 4:s=1e4;break;default:s=5e3}return s=a+s,r={id:u++,callback:i,priorityLevel:r,startTime:a,expirationTime:s,sortIndex:-1},a>o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(te),te=-1):h=!0,le(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,ee||(ee=!0,oe()))),r},e.unstable_shouldYield=ie,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),r=e(((e,t)=>{t.exports=n()})),i=e((e=>{var n=t();function r(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function i(){}var a={d:{f:i,r:function(){throw Error(r(522))},D:i,C:i,L:i,m:i,X:i,S:i,M:i},p:0,findDOMNode:null},o=Symbol.for(`react.portal`);function s(e,t,n){var r=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:o,key:r==null?null:``+r,children:e,containerInfo:t,implementation:n}}var c=n.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function l(e,t){if(e===`font`)return``;if(typeof t==`string`)return t===`use-credentials`?t:``}e.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a,e.createPortal=function(e,t){var n=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)throw Error(r(299));return s(e,t,null,n)},e.flushSync=function(e){var t=c.T,n=a.p;try{if(c.T=null,a.p=2,e)return e()}finally{c.T=t,a.p=n,a.d.f()}},e.preconnect=function(e,t){typeof e==`string`&&(t?(t=t.crossOrigin,t=typeof t==`string`?t===`use-credentials`?t:``:void 0):t=null,a.d.C(e,t))},e.prefetchDNS=function(e){typeof e==`string`&&a.d.D(e)},e.preinit=function(e,t){if(typeof e==`string`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin),i=typeof t.integrity==`string`?t.integrity:void 0,o=typeof t.fetchPriority==`string`?t.fetchPriority:void 0;n===`style`?a.d.S(e,typeof t.precedence==`string`?t.precedence:void 0,{crossOrigin:r,integrity:i,fetchPriority:o}):n===`script`&&a.d.X(e,{crossOrigin:r,integrity:i,fetchPriority:o,nonce:typeof t.nonce==`string`?t.nonce:void 0})}},e.preinitModule=function(e,t){if(typeof e==`string`){if(typeof t==`object`&&t){if(t.as==null||t.as===`script`){var n=l(t.as,t.crossOrigin);a.d.M(e,{crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0})}}else t??a.d.M(e)}},e.preload=function(e,t){if(typeof e==`string`&&typeof t==`object`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin);a.d.L(e,n,{crossOrigin:r,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0,type:typeof t.type==`string`?t.type:void 0,fetchPriority:typeof t.fetchPriority==`string`?t.fetchPriority:void 0,referrerPolicy:typeof t.referrerPolicy==`string`?t.referrerPolicy:void 0,imageSrcSet:typeof t.imageSrcSet==`string`?t.imageSrcSet:void 0,imageSizes:typeof t.imageSizes==`string`?t.imageSizes:void 0,media:typeof t.media==`string`?t.media:void 0})}},e.preloadModule=function(e,t){if(typeof e==`string`){if(t){var n=l(t.as,t.crossOrigin);a.d.m(e,{as:typeof t.as==`string`&&t.as!==`script`?t.as:void 0,crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0})}else a.d.m(e)}},e.requestFormReset=function(e){a.d.r(e)},e.unstable_batchedUpdates=function(e,t){return e(t)},e.useFormState=function(e,t,n){return c.H.useFormState(e,t,n)},e.useFormStatus=function(){return c.H.useHostTransitionStatus()},e.version=`19.2.8`})),a=e(((e,t)=>{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=i()})),o=e((e=>{var n=r(),i=t(),o=a();function s(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function c(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11)}function l(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do t=e,t.flags&4098&&(n=t.return),e=t.return;while(e)}return t.tag===3?n:null}function u(e){if(e.tag===13){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function d(e){if(e.tag===31){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function f(e){if(l(e)!==e)throw Error(s(188))}function p(e){var t=e.alternate;if(!t){if(t=l(e),t===null)throw Error(s(188));return t===e?e:null}for(var n=e,r=t;;){var i=n.return;if(i===null)break;var a=i.alternate;if(a===null){if(r=i.return,r!==null){n=r;continue}break}if(i.child===a.child){for(a=i.child;a;){if(a===n)return f(i),e;if(a===r)return f(i),t;a=a.sibling}throw Error(s(188))}if(n.return!==r.return)n=i,r=a;else{for(var o=!1,c=i.child;c;){if(c===n){o=!0,n=i,r=a;break}if(c===r){o=!0,r=i,n=a;break}c=c.sibling}if(!o){for(c=a.child;c;){if(c===n){o=!0,n=a,r=i;break}if(c===r){o=!0,r=a,n=i;break}c=c.sibling}if(!o)throw Error(s(189))}}if(n.alternate!==r)throw Error(s(190))}if(n.tag!==3)throw Error(s(188));return n.stateNode.current===n?e:t}function m(e){var t=e.tag;if(t===5||t===26||t===27||t===6)return e;for(e=e.child;e!==null;){if(t=m(e),t!==null)return t;e=e.sibling}return null}var h=Object.assign,g=Symbol.for(`react.element`),_=Symbol.for(`react.transitional.element`),v=Symbol.for(`react.portal`),y=Symbol.for(`react.fragment`),b=Symbol.for(`react.strict_mode`),x=Symbol.for(`react.profiler`),ee=Symbol.for(`react.consumer`),te=Symbol.for(`react.context`),ne=Symbol.for(`react.forward_ref`),re=Symbol.for(`react.suspense`),ie=Symbol.for(`react.suspense_list`),ae=Symbol.for(`react.memo`),oe=Symbol.for(`react.lazy`),se=Symbol.for(`react.activity`),ce=Symbol.for(`react.memo_cache_sentinel`),le=Symbol.iterator;function ue(e){return typeof e!=`object`||!e?null:(e=le&&e[le]||e[`@@iterator`],typeof e==`function`?e:null)}var de=Symbol.for(`react.client.reference`);function fe(e){if(e==null)return null;if(typeof e==`function`)return e.$$typeof===de?null:e.displayName||e.name||null;if(typeof e==`string`)return e;switch(e){case y:return`Fragment`;case x:return`Profiler`;case b:return`StrictMode`;case re:return`Suspense`;case ie:return`SuspenseList`;case se:return`Activity`}if(typeof e==`object`)switch(e.$$typeof){case v:return`Portal`;case te:return e.displayName||`Context`;case ee:return(e._context.displayName||`Context`)+`.Consumer`;case ne:var t=e.render;return e=e.displayName,e||=(e=t.displayName||t.name||``,e===``?`ForwardRef`:`ForwardRef(`+e+`)`),e;case ae:return t=e.displayName||null,t===null?fe(e.type)||`Memo`:t;case oe:t=e._payload,e=e._init;try{return fe(e(t))}catch{}}return null}var pe=Array.isArray,S=i.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,C=o.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,me={pending:!1,data:null,method:null,action:null},he=[],ge=-1;function _e(e){return{current:e}}function w(e){0>ge||(e.current=he[ge],he[ge]=null,ge--)}function T(e,t){ge++,he[ge]=e.current,e.current=t}var ve=_e(null),ye=_e(null),be=_e(null),xe=_e(null);function Se(e,t){switch(T(be,t),T(ye,e),T(ve,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}w(ve),T(ve,e)}function Ce(){w(ve),w(ye),w(be)}function we(e){e.memoizedState!==null&&T(xe,e);var t=ve.current,n=Hd(t,e.type);t!==n&&(T(ye,e),T(ve,n))}function Te(e){ye.current===e&&(w(ve),w(ye)),xe.current===e&&(w(xe),Qf._currentValue=me)}var Ee,De;function Oe(e){if(Ee===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Ee=t&&t[1]||``,De=-1<e.stack.indexOf(`
1
+ import{t as e}from"./rolldown-runtime-D9-fqq9M.js";import{$ as t}from"./design-C0uJAczG.js";var n=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0<n;){var r=n-1>>>1,a=e[r];if(0<i(a,t))e[r]=t,e[n]=a,n=r;else break a}}function n(e){return e.length===0?null:e[0]}function r(e){if(e.length===0)return null;var t=e[0],n=e.pop();if(n!==t){e[0]=n;a:for(var r=0,a=e.length,o=a>>>1;r<o;){var s=2*(r+1)-1,c=e[s],l=s+1,u=e[l];if(0>i(c,n))l<a&&0>i(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(l<a&&0>i(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,ee||(ee=!0,oe());else{var t=n(l);t!==null&&le(x,t.startTime-e)}}}var ee=!1,te=-1,ne=5,re=-1;function ie(){return g?!0:!(e.unstable_now()-re<ne)}function ae(){if(g=!1,ee){var t=e.unstable_now();re=t;var i=!0;try{a:{m=!1,h&&(h=!1,v(te),te=-1),p=!0;var a=f;try{b:{for(b(t),d=n(c);d!==null&&!(d.expirationTime>t&&ie());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&le(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?oe():ee=!1}}}var oe;if(typeof y==`function`)oe=function(){y(ae)};else if(typeof MessageChannel<`u`){var se=new MessageChannel,ce=se.port2;se.port1.onmessage=ae,oe=function(){ce.postMessage(null)}}else oe=function(){_(ae,0)};function le(t,n){te=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125<e?console.error(`forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported`):ne=0<e?Math.floor(1e3/e):5},e.unstable_getCurrentPriorityLevel=function(){return f},e.unstable_next=function(e){switch(f){case 1:case 2:case 3:var t=3;break;default:t=f}var n=f;f=t;try{return e()}finally{f=n}},e.unstable_requestPaint=function(){g=!0},e.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=f;f=e;try{return t()}finally{f=n}},e.unstable_scheduleCallback=function(r,i,a){var o=e.unstable_now();switch(typeof a==`object`&&a?(a=a.delay,a=typeof a==`number`&&0<a?o+a:o):a=o,r){case 1:var s=-1;break;case 2:s=250;break;case 5:s=1073741823;break;case 4:s=1e4;break;default:s=5e3}return s=a+s,r={id:u++,callback:i,priorityLevel:r,startTime:a,expirationTime:s,sortIndex:-1},a>o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(te),te=-1):h=!0,le(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,ee||(ee=!0,oe()))),r},e.unstable_shouldYield=ie,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),r=e(((e,t)=>{t.exports=n()})),i=e((e=>{var n=t();function r(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function i(){}var a={d:{f:i,r:function(){throw Error(r(522))},D:i,C:i,L:i,m:i,X:i,S:i,M:i},p:0,findDOMNode:null},o=Symbol.for(`react.portal`);function s(e,t,n){var r=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:o,key:r==null?null:``+r,children:e,containerInfo:t,implementation:n}}var c=n.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function l(e,t){if(e===`font`)return``;if(typeof t==`string`)return t===`use-credentials`?t:``}e.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=a,e.createPortal=function(e,t){var n=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)throw Error(r(299));return s(e,t,null,n)},e.flushSync=function(e){var t=c.T,n=a.p;try{if(c.T=null,a.p=2,e)return e()}finally{c.T=t,a.p=n,a.d.f()}},e.preconnect=function(e,t){typeof e==`string`&&(t?(t=t.crossOrigin,t=typeof t==`string`?t===`use-credentials`?t:``:void 0):t=null,a.d.C(e,t))},e.prefetchDNS=function(e){typeof e==`string`&&a.d.D(e)},e.preinit=function(e,t){if(typeof e==`string`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin),i=typeof t.integrity==`string`?t.integrity:void 0,o=typeof t.fetchPriority==`string`?t.fetchPriority:void 0;n===`style`?a.d.S(e,typeof t.precedence==`string`?t.precedence:void 0,{crossOrigin:r,integrity:i,fetchPriority:o}):n===`script`&&a.d.X(e,{crossOrigin:r,integrity:i,fetchPriority:o,nonce:typeof t.nonce==`string`?t.nonce:void 0})}},e.preinitModule=function(e,t){if(typeof e==`string`){if(typeof t==`object`&&t){if(t.as==null||t.as===`script`){var n=l(t.as,t.crossOrigin);a.d.M(e,{crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0})}}else t??a.d.M(e)}},e.preload=function(e,t){if(typeof e==`string`&&typeof t==`object`&&t&&typeof t.as==`string`){var n=t.as,r=l(n,t.crossOrigin);a.d.L(e,n,{crossOrigin:r,integrity:typeof t.integrity==`string`?t.integrity:void 0,nonce:typeof t.nonce==`string`?t.nonce:void 0,type:typeof t.type==`string`?t.type:void 0,fetchPriority:typeof t.fetchPriority==`string`?t.fetchPriority:void 0,referrerPolicy:typeof t.referrerPolicy==`string`?t.referrerPolicy:void 0,imageSrcSet:typeof t.imageSrcSet==`string`?t.imageSrcSet:void 0,imageSizes:typeof t.imageSizes==`string`?t.imageSizes:void 0,media:typeof t.media==`string`?t.media:void 0})}},e.preloadModule=function(e,t){if(typeof e==`string`){if(t){var n=l(t.as,t.crossOrigin);a.d.m(e,{as:typeof t.as==`string`&&t.as!==`script`?t.as:void 0,crossOrigin:n,integrity:typeof t.integrity==`string`?t.integrity:void 0})}else a.d.m(e)}},e.requestFormReset=function(e){a.d.r(e)},e.unstable_batchedUpdates=function(e,t){return e(t)},e.useFormState=function(e,t,n){return c.H.useFormState(e,t,n)},e.useFormStatus=function(){return c.H.useHostTransitionStatus()},e.version=`19.2.8`})),a=e(((e,t)=>{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=i()})),o=e((e=>{var n=r(),i=t(),o=a();function s(e){var t=`https://react.dev/errors/`+e;if(1<arguments.length){t+=`?args[]=`+encodeURIComponent(arguments[1]);for(var n=2;n<arguments.length;n++)t+=`&args[]=`+encodeURIComponent(arguments[n])}return`Minified React error #`+e+`; visit `+t+` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`}function c(e){return!(!e||e.nodeType!==1&&e.nodeType!==9&&e.nodeType!==11)}function l(e){var t=e,n=e;if(e.alternate)for(;t.return;)t=t.return;else{e=t;do t=e,t.flags&4098&&(n=t.return),e=t.return;while(e)}return t.tag===3?n:null}function u(e){if(e.tag===13){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function d(e){if(e.tag===31){var t=e.memoizedState;if(t===null&&(e=e.alternate,e!==null&&(t=e.memoizedState)),t!==null)return t.dehydrated}return null}function f(e){if(l(e)!==e)throw Error(s(188))}function p(e){var t=e.alternate;if(!t){if(t=l(e),t===null)throw Error(s(188));return t===e?e:null}for(var n=e,r=t;;){var i=n.return;if(i===null)break;var a=i.alternate;if(a===null){if(r=i.return,r!==null){n=r;continue}break}if(i.child===a.child){for(a=i.child;a;){if(a===n)return f(i),e;if(a===r)return f(i),t;a=a.sibling}throw Error(s(188))}if(n.return!==r.return)n=i,r=a;else{for(var o=!1,c=i.child;c;){if(c===n){o=!0,n=i,r=a;break}if(c===r){o=!0,r=i,n=a;break}c=c.sibling}if(!o){for(c=a.child;c;){if(c===n){o=!0,n=a,r=i;break}if(c===r){o=!0,r=a,n=i;break}c=c.sibling}if(!o)throw Error(s(189))}}if(n.alternate!==r)throw Error(s(190))}if(n.tag!==3)throw Error(s(188));return n.stateNode.current===n?e:t}function m(e){var t=e.tag;if(t===5||t===26||t===27||t===6)return e;for(e=e.child;e!==null;){if(t=m(e),t!==null)return t;e=e.sibling}return null}var h=Object.assign,g=Symbol.for(`react.element`),_=Symbol.for(`react.transitional.element`),v=Symbol.for(`react.portal`),y=Symbol.for(`react.fragment`),b=Symbol.for(`react.strict_mode`),x=Symbol.for(`react.profiler`),ee=Symbol.for(`react.consumer`),te=Symbol.for(`react.context`),ne=Symbol.for(`react.forward_ref`),re=Symbol.for(`react.suspense`),ie=Symbol.for(`react.suspense_list`),ae=Symbol.for(`react.memo`),oe=Symbol.for(`react.lazy`),se=Symbol.for(`react.activity`),ce=Symbol.for(`react.memo_cache_sentinel`),le=Symbol.iterator;function ue(e){return typeof e!=`object`||!e?null:(e=le&&e[le]||e[`@@iterator`],typeof e==`function`?e:null)}var de=Symbol.for(`react.client.reference`);function fe(e){if(e==null)return null;if(typeof e==`function`)return e.$$typeof===de?null:e.displayName||e.name||null;if(typeof e==`string`)return e;switch(e){case y:return`Fragment`;case x:return`Profiler`;case b:return`StrictMode`;case re:return`Suspense`;case ie:return`SuspenseList`;case se:return`Activity`}if(typeof e==`object`)switch(e.$$typeof){case v:return`Portal`;case te:return e.displayName||`Context`;case ee:return(e._context.displayName||`Context`)+`.Consumer`;case ne:var t=e.render;return e=e.displayName,e||=(e=t.displayName||t.name||``,e===``?`ForwardRef`:`ForwardRef(`+e+`)`),e;case ae:return t=e.displayName||null,t===null?fe(e.type)||`Memo`:t;case oe:t=e._payload,e=e._init;try{return fe(e(t))}catch{}}return null}var pe=Array.isArray,S=i.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,C=o.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,me={pending:!1,data:null,method:null,action:null},he=[],ge=-1;function _e(e){return{current:e}}function w(e){0>ge||(e.current=he[ge],he[ge]=null,ge--)}function T(e,t){ge++,he[ge]=e.current,e.current=t}var ve=_e(null),ye=_e(null),be=_e(null),xe=_e(null);function Se(e,t){switch(T(be,t),T(ye,e),T(ve,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}w(ve),T(ve,e)}function Ce(){w(ve),w(ye),w(be)}function we(e){e.memoizedState!==null&&T(xe,e);var t=ve.current,n=Hd(t,e.type);t!==n&&(T(ye,e),T(ve,n))}function Te(e){ye.current===e&&(w(ve),w(ye)),xe.current===e&&(w(xe),Qf._currentValue=me)}var Ee,De;function Oe(e){if(Ee===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Ee=t&&t[1]||``,De=-1<e.stack.indexOf(`
2
2
  at`)?` (<anonymous>)`:-1<e.stack.indexOf(`@`)?`@unknown:0:0`:``}return`
3
3
  `+Ee+e+De}var ke=!1;function Ae(e,t){if(!e||ke)return``;ke=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var r={DetermineComponentFrameRoot:function(){try{if(t){var n=function(){throw Error()};if(Object.defineProperty(n.prototype,"props",{set:function(){throw Error()}}),typeof Reflect==`object`&&Reflect.construct){try{Reflect.construct(n,[])}catch(e){var r=e}Reflect.construct(e,[],n)}else{try{n.call()}catch(e){r=e}e.call(n.prototype)}}else{try{throw Error()}catch(e){r=e}(n=e())&&typeof n.catch==`function`&&n.catch(function(){})}}catch(e){if(e&&r&&typeof e.stack==`string`)return[e.stack,r.stack]}return[null,null]}};r.DetermineComponentFrameRoot.displayName=`DetermineComponentFrameRoot`;var i=Object.getOwnPropertyDescriptor(r.DetermineComponentFrameRoot,`name`);i&&i.configurable&&Object.defineProperty(r.DetermineComponentFrameRoot,"name",{value:`DetermineComponentFrameRoot`});var a=r.DetermineComponentFrameRoot(),o=a[0],s=a[1];if(o&&s){var c=o.split(`
4
4
  `),l=s.split(`
@@ -1 +1 @@
1
- @font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35857095341.commit-76a4f94/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35857095341.commit-76a4f94/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35857095341.commit-76a4f94/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2)format("woff2-variations");unicode-range:U+1F??}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35857095341.commit-76a4f94/assets/inter-greek-wght-normal-CkhJZR-_.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35857095341.commit-76a4f94/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35857095341.commit-76a4f94/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35857095341.commit-76a4f94/assets/inter-latin-wght-normal-Dx4kXJAl.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
1
+ @font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35987517326.commit-7fa64d1/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35987517326.commit-7fa64d1/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35987517326.commit-7fa64d1/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2)format("woff2-variations");unicode-range:U+1F??}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35987517326.commit-7fa64d1/assets/inter-greek-wght-normal-CkhJZR-_.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35987517326.commit-7fa64d1/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35987517326.commit-7fa64d1/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35987517326.commit-7fa64d1/assets/inter-latin-wght-normal-Dx4kXJAl.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@@ -13,7 +13,7 @@
13
13
  "networkId": 0,
14
14
  "globalScenesUrn": [],
15
15
  "scenesUrn": [
16
- "urn:decentraland:entity:bafkreics6nreaceg5dv3x3xjr4h3dr7y47z3epxatevje7zgspknwuw2lq?=&baseUrl=https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35857095341.commit-76a4f94/bridge-scene/static/"
16
+ "urn:decentraland:entity:bafkreiae4chlakjjoty3cik5x2ffyvyfcixda4skjznqirqpacbhshjaki?=&baseUrl=https://cdn.decentraland.org/@dcl-regenesislabs/bevy-explorer-web/0.1.0-35987517326.commit-7fa64d1/bridge-scene/static/"
17
17
  ],
18
18
  "realmName": "BevyExplorerUI"
19
19
  },
@@ -1 +1 @@
1
- {"content":[{"file":"main.crdt","hash":"bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku"},{"file":"scene.json","hash":"bafkreidfb7vvixnyvoghjymlxn7dua6tl2rnscnhgj6yrk5cx3gr2dc3r4"},{"file":"images/icon-verified.png","hash":"bafkreiekho3ovv3r2wab75y2eanajcdcul3er4i73lk3gdl2ppher7nkxa"},{"file":"bin/index.js","hash":"bafybeibh4midj4cncxd4lngxyy4xx5zc4o2xhijh4uvn46kxv2bqh7wlie"}],"pointers":[],"timestamp":1790165617931,"type":"scene","metadata":{"ecs7":true,"runtimeVersion":"7","display":{"title":"UI Scene","description":"UI Scene shows a functional UI for Bevy Explorer","navmapThumbnail":"scene-thumbnail.png","favicon":"favicon_asset"},"owner":"","contact":{"name":"SDK","email":""},"main":"bin/index.js","tags":[],"scene":{"parcels":["0,0"],"base":"0,0"},"spawnPoints":[],"featureToggles":{"voiceChat":"enabled","portableExperiences":"enabled"}},"version":"v3"}
1
+ {"content":[{"file":"main.crdt","hash":"bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku"},{"file":"scene.json","hash":"bafkreidfb7vvixnyvoghjymlxn7dua6tl2rnscnhgj6yrk5cx3gr2dc3r4"},{"file":"images/icon-verified.png","hash":"bafkreiekho3ovv3r2wab75y2eanajcdcul3er4i73lk3gdl2ppher7nkxa"},{"file":"bin/index.js","hash":"bafybeibh4midj4cncxd4lngxyy4xx5zc4o2xhijh4uvn46kxv2bqh7wlie"}],"pointers":[],"timestamp":1790247291037,"type":"scene","metadata":{"ecs7":true,"runtimeVersion":"7","display":{"title":"UI Scene","description":"UI Scene shows a functional UI for Bevy Explorer","navmapThumbnail":"scene-thumbnail.png","favicon":"favicon_asset"},"owner":"","contact":{"name":"SDK","email":""},"main":"bin/index.js","tags":[],"scene":{"parcels":["0,0"],"base":"0,0"},"spawnPoints":[],"featureToggles":{"voiceChat":"enabled","portableExperiences":"enabled"}},"version":"v3"}
package/engine/boot.js CHANGED
@@ -25,7 +25,7 @@
25
25
  // here. The engine itself takes the domain and the overrides as engine_run options.
26
26
  // __bevyHomeScene() — the persisted home scene { realm, parcel: "x,y" } (realm null = none
27
27
  // pinned), for the host's "Skip to Home"; set alongside __bevyReadyToLaunch
28
- import { initEngine, start, applyOptionsToUrlParams, engine_home_scene, gpu_cache_hash, initGpuCache } from './engine.js'
28
+ import { initEngine, start, prepareRender, applyOptionsToUrlParams, engine_home_scene } from './engine.js'
29
29
 
30
30
  // ---- boot progress (replaces ui.js's DOM loading steps) -----------------------------------------
31
31
  // Weight of each step in the overall bar (sums to 100). Step ids are read by the React login bar
@@ -83,9 +83,10 @@ publish()
83
83
  // Only these engine messages can trip the flood. A healthy session floods the console with benign
84
84
  // ERROR lines at exactly this rate — a 404 asset retried per frame by bevy_asset, comms "channel
85
85
  // closed" during startup — so an allowlist, not a denylist, is what keeps the modal off a working
86
- // world. `captured wgpu error` is src/lib.rs's on_uncaptured_error handler: the device-level GPU
87
- // fault that blanks the screen while the render loop keeps beating.
88
- const FATAL_SIGNALS = ['captured wgpu error']
86
+ // world. `uncaptured wgpu error` is the render worker's on_uncaptured_error handler (bevy's
87
+ // web_worker module), mirrored to this console: the device-level GPU fault that blanks the screen
88
+ // while the render loop keeps beating.
89
+ const FATAL_SIGNALS = ['uncaptured wgpu error']
89
90
  // signature -> { count, since }. Per-signature counters (not a single last-seen key) so an identical
90
91
  // per-frame error still floods even when the loop interleaves it with a second error each frame.
91
92
  const floodCounts = new Map()
@@ -241,6 +242,13 @@ window.__setEngineTextFocus = (focused) => {
241
242
  window.__engineTextFocus = !!focused
242
243
  }
243
244
 
245
+ // gpu_cache.js (on the render worker) shows the page's #shader-compiling indicator while it
246
+ // compiles pipelines asynchronously; the HUD's renderBusy probe reads it.
247
+ window.__setShaderCompiling = (on) => {
248
+ const el = document.getElementById('shader-compiling')
249
+ if (el) el.style.display = on ? 'flex' : 'none'
250
+ }
251
+
244
252
  // ---- keyboard forwarding to the engine -----------------------------------------------------------
245
253
  // winit attaches its keyboard listeners to the CANVAS element, so the engine only hears keys while
246
254
  // the canvas holds DOM focus — click any HUD control and movement + every engine binding (which
@@ -333,7 +341,8 @@ window.addEventListener('keydown', (event) => {
333
341
  initEngine()
334
342
  .then(() => {
335
343
  window.setLoadingStepActive('gpu')
336
- return initGpuCache(gpu_cache_hash())
344
+ // spawns the render worker; gpu_cache.js warms its device there before the launch
345
+ return prepareRender()
337
346
  })
338
347
  .then(() => {
339
348
  window.setLoadingStepCompleted('gpu')
package/engine/engine.js CHANGED
@@ -1,11 +1,66 @@
1
1
  // Engine logic - ES module
2
2
  // Handles WASM/WebGPU initialization and game execution
3
3
 
4
- import init, { engine_init, engine_run, engine_console_command, engine_home_scene, gpu_cache_hash } from "./pkg/webgpu_build.js";
5
- import { initGpuCache } from "./gpu_cache.js";
4
+ import init, { engine_init, engine_start, engine_spawn_worker, engine_console_command, engine_home_scene, gpu_cache_hash, report_pointer_lock, media_host_main, audio_host_main, livekit_host_main, engine_prepare_render } from "./pkg/webgpu_build.js";
6
5
 
7
6
  // Re-export for main.js
8
- export { engine_home_scene, gpu_cache_hash, initGpuCache };
7
+ export { engine_home_scene, gpu_cache_hash };
8
+
9
+ // Spawns the render worker ahead of start(), so gpu_cache.js warms its device there (src/web.rs
10
+ // engine_render_setup) while the user is still on the login screen; resolves once it has.
11
+ // start() attaches the engine to that worker.
12
+ export function prepareRender() {
13
+ return new Promise((resolve, reject) => {
14
+ window.__gpuCacheReady = resolve;
15
+ try {
16
+ engine_prepare_render(document.getElementById("mygame-canvas"), glueUrl);
17
+ } catch (e) {
18
+ reject(e);
19
+ }
20
+ });
21
+ }
22
+
23
+ // The compiled engine module and its shared memory: every worker (asset loader/processor, scene
24
+ // sandboxes, and the engine + render workers started by start()) instantiates the same module on
25
+ // the same memory.
26
+ let compiledModule = null;
27
+ let sharedMemory = null;
28
+
29
+ /**
30
+ * Logs the app-level messages of a worker (bevy's own relay handles the workers' console
31
+ * mirroring and page calls).
32
+ * @param {string} name - worker name for logging
33
+ * @returns {(e: MessageEvent) => void}
34
+ */
35
+ function workerMessageHandler(name) {
36
+ return (e) => {
37
+ const data = e.data;
38
+ if (!data) return;
39
+ if (data.__bevy_ready !== undefined) console.log(`[Main JS] ${name} worker ready`);
40
+ else if (data.type) console.log(`[Main JS] ${name} worker: ${data.type}`);
41
+ };
42
+ }
43
+
44
+ /** The url of this module's wasm-bindgen glue, for bevy's workers to import. */
45
+ const glueUrl = new URL("./pkg/webgpu_build.js", import.meta.url).href;
46
+
47
+ /**
48
+ * Resolves once a worker bevy spawned has run its entry (it posts `__bevy_ready`), or rejects if
49
+ * it failed to (`__bevy_ready` with an `error`).
50
+ * @param {Worker} worker
51
+ * @returns {Promise<void>}
52
+ */
53
+ function workerReady(worker) {
54
+ return new Promise((resolve, reject) => {
55
+ const onReady = (e) => {
56
+ if (e.data?.__bevy_ready === undefined) return;
57
+ worker.removeEventListener("message", onReady);
58
+ if (e.data.error !== undefined) reject(new Error(e.data.error));
59
+ else resolve();
60
+ };
61
+ worker.addEventListener("message", onReady);
62
+ });
63
+ }
9
64
 
10
65
  /**
11
66
  * Records an uncaught worker error as context for the crash watchdog. A worker
@@ -159,7 +214,7 @@ export async function initEngine() {
159
214
  // so the 'compile' step only covers the tail left after the last byte arrives.
160
215
  setLoadingStepActive('download');
161
216
  console.time("compileTime")
162
- const compiledModule = await compileWasmWithProgress(
217
+ compiledModule = await compileWasmWithProgress(
163
218
  wasmUrl,
164
219
  expectedWasmSize,
165
220
  (percent) => setLoadingStepProgress('download', percent),
@@ -173,13 +228,22 @@ export async function initEngine() {
173
228
 
174
229
  const initialMemoryPages = 1280; // setting initial memory high causes malloc failures
175
230
  const maximumMemoryPages = 65536;
176
- const sharedMemory = new WebAssembly.Memory({
231
+ sharedMemory = new WebAssembly.Memory({
177
232
  initial: initialMemoryPages,
178
233
  maximum: maximumMemoryPages,
179
234
  shared: true,
180
235
  });
181
236
  window.wasm_memory = sharedMemory;
182
237
 
238
+ // Browser-only actions the engine relays here (copypwasmta via src/web.rs, crates/restricted_actions):
239
+ // the engine worker has no clipboard and no window.open. The click or key press that triggered
240
+ // them gives the page the transient activation they need.
241
+ window.__copyToClipboard = (text) => navigator.clipboard.writeText(text);
242
+ window.__readClipboard = () => navigator.clipboard.readText();
243
+ window.__openExternalUrl = (url) => {
244
+ if (!window.open(url, "_blank")) console.warn("[Main JS] window.open blocked:", url);
245
+ };
246
+
183
247
  // Setup HLS video source callback
184
248
  window.setVideoSource = (video, src) => {
185
249
  async function isHlsStream(url) {
@@ -442,49 +506,16 @@ export async function initEngine() {
442
506
  setLoadingStepActive('workers');
443
507
  setLoadingStepProgress('workers', 0);
444
508
 
445
- // start asset loader thread
446
- await new Promise((resolve, _reject) => {
447
- const assetLoaderPath = new URL("./asset_loader.js", import.meta.url);
448
-
449
- const assetLoader = new Worker(assetLoaderPath, { type: "module" });
450
- assetLoader.onerror = workerCrashHandler("asset loader");
451
- // Unprompted, as for the sandbox above.
452
- assetLoader.postMessage({
453
- type: "INIT_ASSET_LOADER",
454
- payload: {
455
- compiledModule,
456
- sharedMemory,
457
- },
458
- });
459
- assetLoader.onmessage = (workerEvent) => {
460
- if (workerEvent.data.type === "INITIALIZED") {
461
- assetLoader.onmessage = null;
462
- resolve();
463
- }
464
- };
465
- });
509
+ // The asset loader and processor threads: workers of ours, spawned on bevy's terms
510
+ // (src/web.rs init_asset_load_thread / image_processor_main).
511
+ const assetLoader = engine_spawn_worker(glueUrl, "init_asset_load_thread", "asset loader");
512
+ assetLoader.onerror = workerCrashHandler("asset loader");
513
+ await workerReady(assetLoader);
466
514
  setLoadingStepProgress('workers', 50);
467
515
 
468
- // start asset processor thread
469
- await new Promise((resolve, _reject) => {
470
- const assetProcessorPath = new URL("./asset_processor.js", import.meta.url);
471
-
472
- const assetProcessor = new Worker(assetProcessorPath, { type: "module" });
473
- assetProcessor.onerror = workerCrashHandler("asset processor");
474
- assetProcessor.postMessage({
475
- type: "INIT_ASSET_PROCESSOR",
476
- payload: {
477
- compiledModule,
478
- sharedMemory,
479
- },
480
- });
481
- assetProcessor.onmessage = (workerEvent) => {
482
- if (workerEvent.data.type === "INITIALIZED") {
483
- assetProcessor.onmessage = null;
484
- resolve();
485
- }
486
- };
487
- });
516
+ const assetProcessor = engine_spawn_worker(glueUrl, "image_processor_main", "asset processor");
517
+ assetProcessor.onerror = workerCrashHandler("asset processor");
518
+ await workerReady(assetProcessor);
488
519
  setLoadingStepCompleted('workers');
489
520
  }
490
521
 
@@ -569,9 +600,47 @@ export function start(options = {}) {
569
600
  delete window._buildEngineApi;
570
601
  };
571
602
 
603
+ // The engine runs off the page: winit's DOM side stays here on the canvas, the app world runs
604
+ // on an engine worker, the render world on a render worker that owns the canvas as an
605
+ // OffscreenCanvas, and the ComputeTaskPool's systems on compute workers (bevy::web_worker,
606
+ // src/web.rs engine_start), as many as the `computeThreads` launch option says, else sized
607
+ // from the core count there.
608
+ const canvas = document.getElementById("mygame-canvas");
572
609
  // Everything the host handed us goes through as-is (the engine rejects unknown keys).
573
- engine_run(options);
574
- window.engine_console_command = engine_console_command;
610
+ const { engine: engineWorker, render: renderWorker, compute: computeWorkers } = engine_start(
611
+ canvas,
612
+ options,
613
+ glueUrl
614
+ );
615
+ console.log(`[Main JS] compute workers: ${computeWorkers.length}`);
616
+ renderWorker.onerror = workerCrashHandler("render");
617
+ renderWorker.addEventListener("message", workerMessageHandler("render"));
618
+ computeWorkers.forEach((worker, i) => {
619
+ worker.onerror = workerCrashHandler(`compute ${i}`);
620
+ worker.addEventListener("message", workerMessageHandler(`compute ${i}`));
621
+ });
622
+ engineWorker.onerror = workerCrashHandler("engine");
623
+ engineWorker.addEventListener("message", workerMessageHandler("engine"));
624
+ // The console RPC is the host's "engine is up" signal (engineRpc.ts ready()); the engine
625
+ // worker is ready once engine_run has returned, having wired the command channel.
626
+ workerReady(engineWorker).then(() => {
627
+ window.engine_console_command = engine_console_command;
628
+ });
629
+
630
+ // The engine worker cannot see the document's pointer-lock state (Escape, a refused request):
631
+ // report it through the shared wasm memory (src/web.rs report_pointer_lock).
632
+ document.addEventListener("pointerlockchange", () => report_pointer_lock(document.pointerLockElement === canvas));
633
+ document.addEventListener("pointerlockerror", () => report_pointer_lock(false));
634
+
635
+ // Html media (scene video/audio) lives here on the page, the only thread with a DOM; the
636
+ // engine drives it over channels and the page transfers decoded frames to the render worker
637
+ // (crates/media/src/html).
638
+ media_host_main(renderWorker);
639
+ // Scene audio sources: the WebAudio graphs live here too (crates/av/src/audio_host_wasm.rs).
640
+ audio_host_main();
641
+ // Livekit rooms: the livekit-client objects (WebRTC) live here (crates/comms/src/livekit/web/host.rs).
642
+ livekit_host_main();
643
+
575
644
  window.loadSceneUtils = () => {
576
645
  return new Promise((resolve, reject) => {
577
646
  const s = document.createElement('script');
@@ -101,6 +101,26 @@ async function storeRequiredItems() {
101
101
  });
102
102
  }
103
103
 
104
+ // The small settings that lived in localStorage, which a worker has no access to.
105
+ async function getConfig(key) {
106
+ const db = await openDB();
107
+ return new Promise((resolve) => {
108
+ const request = db.transaction("deviceConfig", "readonly").objectStore("deviceConfig").get(key);
109
+ request.onsuccess = () => resolve(request.result);
110
+ request.onerror = () => resolve(undefined);
111
+ });
112
+ }
113
+
114
+ async function setConfig(key, value) {
115
+ const db = await openDB();
116
+ return new Promise((resolve, reject) => {
117
+ const tx = db.transaction("deviceConfig", "readwrite");
118
+ tx.oncomplete = () => resolve();
119
+ tx.onerror = () => reject(tx.error);
120
+ tx.objectStore("deviceConfig").put(value, key);
121
+ });
122
+ }
123
+
104
124
  async function fetchInstance(type, hash) {
105
125
  const db = await openDB();
106
126
  return new Promise((resolve, reject) => {
@@ -170,7 +190,7 @@ function patchWebgpuAdapter(fakeAsync) {
170
190
  device = await originalRequestDevice.apply(this, []);
171
191
  }
172
192
  gpuSessionState.device = device;
173
- localStorage.setItem("deviceDescriptor", jsonDescriptor);
193
+ await setConfig("deviceDescriptor", jsonDescriptor);
174
194
 
175
195
  function wrapDeviceFunction(itemType, originalFunction) {
176
196
  return (...args) => {
@@ -222,9 +242,9 @@ function patchWebgpuAdapter(fakeAsync) {
222
242
  } else {
223
243
  let inline_function = wrapDeviceFunction("pipeline", device.createRenderPipeline);
224
244
 
225
- window.pendingAsyncPipelineCount = 0;
226
- window.lastPipelineWasValidFlag = false;
227
- window.wgpuResolveIdle = [];
245
+ globalThis.pendingAsyncPipelineCount = 0;
246
+ globalThis.lastPipelineWasValidFlag = false;
247
+ globalThis.wgpuResolveIdle = [];
228
248
  const itemType = "pipeline";
229
249
  const placeholderPipeline = getPlaceholder(device);
230
250
 
@@ -233,26 +253,26 @@ function patchWebgpuAdapter(fakeAsync) {
233
253
  const hash = simpleHash(jsonArgs);
234
254
  const cachedItem = gpuSessionState[itemType].get(hash);
235
255
  if (cachedItem !== undefined) {
236
- window.nextPipelineCanFail = false;
237
- window.lastPipelineWasValidFlag = true;
256
+ globalThis.nextPipelineCanFail = false;
257
+ globalThis.lastPipelineWasValidFlag = true;
238
258
  return cachedItem;
239
259
  }
240
260
 
241
261
  console.log(`[GPU Cache] (async) no cached ${itemType} for ${hash}`);
242
262
 
243
- if (!window.nextPipelineCanFail) {
263
+ if (!globalThis.nextPipelineCanFail) {
244
264
  return inline_function.apply(device, args);
245
265
  }
246
- const sc = document.getElementById("shader-compiling"); if (sc) sc.style.display = "flex";
247
- window.nextPipelineCanFail = false;
248
- window.lastPipelineWasValidFlag = false;
249
- window.pendingAsyncPipelineCount++;
266
+ globalThis.__setShaderCompiling?.(true);
267
+ globalThis.nextPipelineCanFail = false;
268
+ globalThis.lastPipelineWasValidFlag = false;
269
+ globalThis.pendingAsyncPipelineCount++;
250
270
 
251
271
  const promise = device.createRenderPipelineAsync(args[0]).then(async (item) => {
252
272
  item.__gpu_item_type = itemType;
253
273
  item.__gpu_hash = hash;
254
274
  gpuSessionState[itemType].set(hash, item);
255
- window.pendingAsyncPipelineCount--;
275
+ globalThis.pendingAsyncPipelineCount--;
256
276
 
257
277
  if (!requiredItemTypes.has(itemType)) {
258
278
  requiredItemTypes.set(itemType, new Set());
@@ -264,11 +284,11 @@ function patchWebgpuAdapter(fakeAsync) {
264
284
  await storeInstance(itemType, hash, args);
265
285
  }
266
286
 
267
- if (window.pendingAsyncPipelineCount === 0) {
268
- while (window.wgpuResolveIdle.length > 0) {
269
- window.wgpuResolveIdle.pop()();
287
+ if (globalThis.pendingAsyncPipelineCount === 0) {
288
+ while (globalThis.wgpuResolveIdle.length > 0) {
289
+ globalThis.wgpuResolveIdle.pop()();
270
290
  }
271
- const sc2 = document.getElementById("shader-compiling"); if (sc2) sc2.style.display = "none";
291
+ globalThis.__setShaderCompiling?.(false);
272
292
  }
273
293
 
274
294
  return item;
@@ -283,19 +303,20 @@ function patchWebgpuAdapter(fakeAsync) {
283
303
  }
284
304
 
285
305
  async function createGpuCache(key) {
286
- const cachedKey = localStorage.getItem("gpuCacheKey");
306
+ const cachedKey = await getConfig("gpuCacheKey");
287
307
  if (cachedKey != key) {
288
308
  console.log("shaders updated, clearing db");
289
309
  await clearDatabase();
290
- localStorage.setItem("gpuCacheKey", key);
310
+ await setConfig("gpuCacheKey", key);
291
311
  return;
292
312
  }
293
313
 
294
- const cachedDeviceDescriptor = localStorage.getItem("deviceDescriptor");
295
- if (cachedDeviceDescriptor === null) {
314
+ const cachedDeviceDescriptor = await getConfig("deviceDescriptor");
315
+ if (cachedDeviceDescriptor === undefined) {
296
316
  return;
297
317
  }
298
318
  precaching = true;
319
+ const started = performance.now();
299
320
  const adapter = await navigator.gpu.requestAdapter();
300
321
  const device = await adapter.requestDevice(
301
322
  JSON.parse(cachedDeviceDescriptor)
@@ -322,7 +343,7 @@ async function createGpuCache(key) {
322
343
  const stats = Object.keys(gpuSessionState).map(
323
344
  (k) => `\n${k}: ${gpuSessionState[k].size ?? "ok"}`
324
345
  );
325
- console.log(`[GPU Cache]: preloaded ${stats}`);
346
+ console.log(`[GPU Cache]: preloaded in ${Math.round(performance.now() - started)} ms ${stats}`);
326
347
  }
327
348
 
328
349
  async function createItemType(itemType, asyncCreateFunction) {
@@ -400,19 +421,19 @@ function getPlaceholder(device) {
400
421
  });
401
422
  }
402
423
 
403
- window.allowADummyPipeline = function() {
404
- window.nextPipelineCanFail = true;
424
+ globalThis.allowADummyPipeline = function() {
425
+ globalThis.nextPipelineCanFail = true;
405
426
  }
406
427
 
407
- window.lastPipelineWasValid = function() {
408
- return window.lastPipelineWasValidFlag;
428
+ globalThis.lastPipelineWasValid = function() {
429
+ return globalThis.lastPipelineWasValidFlag;
409
430
  }
410
431
 
411
- window.waitForPipelines = function() {
412
- if (window.pendingAsyncPipelineCount === 0) {
432
+ globalThis.waitForPipelines = function() {
433
+ if (globalThis.pendingAsyncPipelineCount === 0) {
413
434
  return Promise.resolve();
414
435
  }
415
436
  return new Promise((resolve) => {
416
- window.wgpuResolveIdle.push(resolve);
437
+ globalThis.wgpuResolveIdle.push(resolve);
417
438
  });
418
439
  };
@@ -1 +1 @@
1
- {"wasmSize":111607801}
1
+ {"wasmSize":112317603}