{"version":3,"file":"autoDetectRenderer.mjs","sources":["../../../src/rendering/renderers/autoDetectRenderer.ts"],"sourcesContent":["import { isWebGLSupported } from '../../utils/browser/isWebGLSupported';\nimport { isWebGPUSupported } from '../../utils/browser/isWebGPUSupported';\nimport { AbstractRenderer } from './shared/system/AbstractRenderer';\n\nimport type { WebGLOptions } from './gl/WebGLRenderer';\nimport type { WebGPUOptions } from './gpu/WebGPURenderer';\nimport type { Renderer, RendererOptions } from './types';\n\n/**\n * Options for {@link rendering.autoDetectRenderer}.\n * @memberof rendering\n */\nexport interface AutoDetectOptions extends RendererOptions\n{\n    /** The preferred renderer type. WebGPU is recommended as its generally faster than WebGL. */\n    preference?: 'webgl' | 'webgpu'// | 'canvas';\n    /** Optional WebGPUOptions to pass only to WebGPU renderer. */\n    webgpu?: Partial<WebGPUOptions>;\n    /** Optional WebGLOptions to pass only to the WebGL renderer */\n    webgl?: Partial<WebGLOptions>;\n}\n\nconst renderPriority = ['webgl', 'webgpu', 'canvas'];\n\n/**\n * Automatically determines the most appropriate renderer for the current environment.\n *\n * The function will prioritize the WebGL renderer as it is the most tested safe API to use.\n * In the near future as WebGPU becomes more stable and ubiquitous, it will be prioritized over WebGL.\n *\n * The selected renderer's code is then dynamically imported to optimize\n * performance and minimize the initial bundle size.\n *\n * To maximize the benefits of dynamic imports, it's recommended to use a modern bundler\n * that supports code splitting. This will place the renderer code in a separate chunk,\n * which is loaded only when needed.\n * @example\n *\n * // create a renderer\n * const renderer = await autoDetectRenderer({\n *   width: 800,\n *   height: 600,\n *   antialias: true,\n * });\n *\n * // custom for each renderer\n * const renderer = await autoDetectRenderer({\n *   width: 800,\n *   height: 600,\n *   webgpu:{\n *     antialias: true,\n *     backgroundColor: 'red'\n *   },\n *   webgl:{\n *     antialias: true,\n *     backgroundColor: 'green'\n *   }\n *  });\n * @param options - A partial configuration object based on the `AutoDetectOptions` type.\n * @returns A Promise that resolves to an instance of the selected renderer.\n * @memberof rendering\n */\nexport async function autoDetectRenderer(options: Partial<AutoDetectOptions>): Promise<Renderer>\n{\n    let preferredOrder: string[] = [];\n\n    if (options.preference)\n    {\n        preferredOrder.push(options.preference);\n\n        renderPriority.forEach((item) =>\n        {\n            if (item !== options.preference)\n            {\n                preferredOrder.push(item);\n            }\n        });\n    }\n    else\n    {\n        preferredOrder = renderPriority.slice();\n    }\n\n    let RendererClass: new () => Renderer;\n    let finalOptions: Partial<AutoDetectOptions> = {};\n\n    for (let i = 0; i < preferredOrder.length; i++)\n    {\n        const rendererType = preferredOrder[i];\n\n        if (rendererType === 'webgpu' && (await isWebGPUSupported()))\n        {\n            const { WebGPURenderer } = await import('./gpu/WebGPURenderer');\n\n            RendererClass = WebGPURenderer;\n\n            finalOptions = { ...options, ...options.webgpu };\n\n            break;\n        }\n        else if (\n            rendererType === 'webgl'\n            && isWebGLSupported(\n                options.failIfMajorPerformanceCaveat\n                    ?? AbstractRenderer.defaultOptions.failIfMajorPerformanceCaveat\n            )\n        )\n        {\n            const { WebGLRenderer } = await import('./gl/WebGLRenderer');\n\n            RendererClass = WebGLRenderer;\n\n            finalOptions = { ...options, ...options.webgl };\n\n            break;\n        }\n        else if (rendererType === 'canvas')\n        {\n            finalOptions = { ...options };\n\n            throw new Error('CanvasRenderer is not yet implemented');\n        }\n    }\n\n    delete finalOptions.webgpu;\n    delete finalOptions.webgl;\n\n    if (!RendererClass)\n    {\n        throw new Error('No available renderer for the current environment');\n    }\n\n    const renderer = new RendererClass();\n\n    await renderer.init(finalOptions);\n\n    return renderer;\n}\n"],"names":[],"mappings":";;;;;AAsBA,MAAM,cAAiB,GAAA,CAAC,OAAS,EAAA,QAAA,EAAU,QAAQ,CAAA,CAAA;AAwCnD,eAAsB,mBAAmB,OACzC,EAAA;AACI,EAAA,IAAI,iBAA2B,EAAC,CAAA;AAEhC,EAAA,IAAI,QAAQ,UACZ,EAAA;AACI,IAAe,cAAA,CAAA,IAAA,CAAK,QAAQ,UAAU,CAAA,CAAA;AAEtC,IAAe,cAAA,CAAA,OAAA,CAAQ,CAAC,IACxB,KAAA;AACI,MAAI,IAAA,IAAA,KAAS,QAAQ,UACrB,EAAA;AACI,QAAA,cAAA,CAAe,KAAK,IAAI,CAAA,CAAA;AAAA,OAC5B;AAAA,KACH,CAAA,CAAA;AAAA,GAGL,MAAA;AACI,IAAA,cAAA,GAAiB,eAAe,KAAM,EAAA,CAAA;AAAA,GAC1C;AAEA,EAAI,IAAA,aAAA,CAAA;AACJ,EAAA,IAAI,eAA2C,EAAC,CAAA;AAEhD,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,cAAA,CAAe,QAAQ,CAC3C,EAAA,EAAA;AACI,IAAM,MAAA,YAAA,GAAe,eAAe,CAAC,CAAA,CAAA;AAErC,IAAA,IAAI,YAAiB,KAAA,QAAA,IAAa,MAAM,iBAAA,EACxC,EAAA;AACI,MAAA,MAAM,EAAE,cAAA,EAAmB,GAAA,MAAM,OAAO,0BAAsB,CAAA,CAAA;AAE9D,MAAgB,aAAA,GAAA,cAAA,CAAA;AAEhB,MAAA,YAAA,GAAe,EAAE,GAAG,OAAS,EAAA,GAAG,QAAQ,MAAO,EAAA,CAAA;AAE/C,MAAA,MAAA;AAAA,KACJ,MAAA,IAEI,iBAAiB,OACd,IAAA,gBAAA;AAAA,MACC,OAAA,CAAQ,4BACD,IAAA,gBAAA,CAAiB,cAAe,CAAA,4BAAA;AAAA,KAG/C,EAAA;AACI,MAAA,MAAM,EAAE,aAAA,EAAkB,GAAA,MAAM,OAAO,wBAAoB,CAAA,CAAA;AAE3D,MAAgB,aAAA,GAAA,aAAA,CAAA;AAEhB,MAAA,YAAA,GAAe,EAAE,GAAG,OAAS,EAAA,GAAG,QAAQ,KAAM,EAAA,CAAA;AAE9C,MAAA,MAAA;AAAA,KACJ,MAAA,IACS,iBAAiB,QAC1B,EAAA;AACI,MAAe,YAAA,GAAA,EAAE,GAAG,OAAQ,EAAA,CAAA;AAE5B,MAAM,MAAA,IAAI,MAAM,uCAAuC,CAAA,CAAA;AAAA,KAC3D;AAAA,GACJ;AAEA,EAAA,OAAO,YAAa,CAAA,MAAA,CAAA;AACpB,EAAA,OAAO,YAAa,CAAA,KAAA,CAAA;AAEpB,EAAA,IAAI,CAAC,aACL,EAAA;AACI,IAAM,MAAA,IAAI,MAAM,mDAAmD,CAAA,CAAA;AAAA,GACvE;AAEA,EAAM,MAAA,QAAA,GAAW,IAAI,aAAc,EAAA,CAAA;AAEnC,EAAM,MAAA,QAAA,CAAS,KAAK,YAAY,CAAA,CAAA;AAEhC,EAAO,OAAA,QAAA,CAAA;AACX;;;;"}