diff --git a/docs/whats-new.md b/docs/whats-new.md index 6f95ba206c..491dbec697 100644 --- a/docs/whats-new.md +++ b/docs/whats-new.md @@ -9,7 +9,33 @@ Target Date: Q4, 2024 Production quality WebGPU backend **General** -- TypeScript v5.6, strictNullChecks enabled. +- TypeScript v5.6, all `"strict"` TypeScript options are now applied to all luma.gl modules. +- Website tooling upgrades +- All examples run on WebGPU +- Documentation improvements (TBD) +- Improved GitHub issue templates + +**@luma.gl/core** + +- Shader type APIs have been improved. +- `CommandEncoder`/`CommandBuffer` API improvements +- `Texture` class refactors complete. + +**@luma.gl/engine** + +- `AsyncTexture` now supports mipmap generation for WebGPU textures + +**@luma.gl/effects** + +- All postprocessing effects ported to WGSL (in progress) + +**@luma.gl/shadertools** + +- All shader modules ported to WGSL (in progress) + +**@luma.gl/gltf** + +- glTF and PRB now supported on WebGPU (in progress) ## Version 9.1 (In Beta) diff --git a/modules/core/tsconfig.json b/modules/core/tsconfig.json index eb0fd2ae45..c46add9685 100644 --- a/modules/core/tsconfig.json +++ b/modules/core/tsconfig.json @@ -3,7 +3,6 @@ "include": ["src/**/*"], "exclude": ["node_modules"], "compilerOptions": { - "noImplicitAny": true, "composite": true, "rootDir": "src", "outDir": "dist" diff --git a/modules/effects/tsconfig.json b/modules/effects/tsconfig.json index d4164f6786..f79744bbb1 100644 --- a/modules/effects/tsconfig.json +++ b/modules/effects/tsconfig.json @@ -3,7 +3,6 @@ "include": ["src/**/*"], "exclude": ["node_modules", "test"], "compilerOptions": { - "noImplicitAny": true, "composite": true, "rootDir": "src", "outDir": "dist" diff --git a/modules/gltf/src/gltf/create-gltf-model.ts b/modules/gltf/src/gltf/create-gltf-model.ts index 4231d3f6ce..4172a24f57 100644 --- a/modules/gltf/src/gltf/create-gltf-model.ts +++ b/modules/gltf/src/gltf/create-gltf-model.ts @@ -126,7 +126,7 @@ export function createGLTFModel(device: Device, options: CreateGLTFModelOptions) // Calculate managedResources // TODO: Implement resource management logic that will // not deallocate resources/textures/buffers that are shared - const managedResources = []; + const managedResources: any[] = []; // managedResources.push(...parsedMaterial.generatedTextures); // managedResources.push(...Object.values(attributes).map((attribute) => attribute.buffer)); diff --git a/modules/gltf/src/gltf/gltf-animator.ts b/modules/gltf/src/gltf/gltf-animator.ts index d9e26e7fa3..70e91c4273 100644 --- a/modules/gltf/src/gltf/gltf-animator.ts +++ b/modules/gltf/src/gltf/gltf-animator.ts @@ -2,6 +2,8 @@ // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors +// @ts-nocheck TODO + import {log, TypedArray} from '@luma.gl/core'; import {Matrix4, Quaternion} from '@math.gl/core'; diff --git a/modules/gltf/src/gltf/gltf-instantiator.ts b/modules/gltf/src/gltf/gltf-instantiator.ts index d92a950608..7afe055bb5 100644 --- a/modules/gltf/src/gltf/gltf-instantiator.ts +++ b/modules/gltf/src/gltf/gltf-instantiator.ts @@ -2,6 +2,8 @@ // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors +// @ts-nocheck TODO - fix types + import {Device, Buffer, PrimitiveTopology} from '@luma.gl/core'; import {Geometry, GeometryAttribute, GroupNode, ModelNode, ModelProps} from '@luma.gl/engine'; import {Matrix4} from '@math.gl/core'; diff --git a/modules/gltf/src/pbr/parse-pbr-material.ts b/modules/gltf/src/pbr/parse-pbr-material.ts index 6e4b336a91..1585ac46c6 100644 --- a/modules/gltf/src/pbr/parse-pbr-material.ts +++ b/modules/gltf/src/pbr/parse-pbr-material.ts @@ -1,3 +1,9 @@ +// luma.gl +// SPDX-License-Identifier: MIT +// Copyright (c) vis.gl contributors + +// @ts-nocheck TODO + import type {Device, Texture, Parameters} from '@luma.gl/core'; import {log} from '@luma.gl/core'; import {PBREnvironment} from './pbr-environment'; @@ -46,7 +52,7 @@ enum GLEnum { */ export function parsePBRMaterial( device: Device, - material, + material: any, attributes: Record, options: ParsePBRMaterialOptions ): ParsedPBRMaterial { diff --git a/modules/gltf/src/pbr/pbr-environment.ts b/modules/gltf/src/pbr/pbr-environment.ts index 4c6a82c485..07a115c93e 100644 --- a/modules/gltf/src/pbr/pbr-environment.ts +++ b/modules/gltf/src/pbr/pbr-environment.ts @@ -1,4 +1,6 @@ -// luma.gl, MIT license +// luma.gl +// SPDX-License-Identifier: MIT +// Copyright (c) vis.gl contributors import {Device, SamplerProps} from '@luma.gl/core'; import {AsyncTexture} from '@luma.gl/engine'; @@ -85,6 +87,7 @@ function makeCube( ): AsyncTexture { const data = {}; FACES.forEach(face => { + // @ts-ignore TODO data[String(face)] = getTextureForFace(face); }); return new AsyncTexture(device, { diff --git a/modules/gltf/test/gltf/gltf.spec.ts b/modules/gltf/test/gltf/gltf.spec.ts index b1ce8dc010..3b48024dd5 100644 --- a/modules/gltf/test/gltf/gltf.spec.ts +++ b/modules/gltf/test/gltf/gltf.spec.ts @@ -1,3 +1,7 @@ +// luma.gl +// SPDX-License-Identifier: MIT +// Copyright (c) vis.gl contributors + import test from 'tape-promise/tape'; import {getWebGLTestDevice} from '@luma.gl/test-utils'; diff --git a/modules/gltf/test/index.ts b/modules/gltf/test/index.ts index 7786b12f6c..0732eb8980 100644 --- a/modules/gltf/test/index.ts +++ b/modules/gltf/test/index.ts @@ -1,2 +1,5 @@ -// GLTF +// luma.gl +// SPDX-License-Identifier: MIT +// Copyright (c) vis.gl contributors + import './gltf/gltf.spec'; diff --git a/modules/gltf/tsconfig.json b/modules/gltf/tsconfig.json index 84b400e383..01c66bd9e2 100644 --- a/modules/gltf/tsconfig.json +++ b/modules/gltf/tsconfig.json @@ -3,7 +3,6 @@ "include": ["src/**/*"], "exclude": ["node_modules"], "compilerOptions": { - "noImplicitAny": false, "composite": true, "rootDir": "src", "outDir": "dist" diff --git a/modules/test-utils/src/create-test-device.ts b/modules/test-utils/src/create-test-device.ts index df246ae8ae..4756af48a9 100644 --- a/modules/test-utils/src/create-test-device.ts +++ b/modules/test-utils/src/create-test-device.ts @@ -26,6 +26,7 @@ const withResolvers = (): { resolve = _resolve; reject = _reject; }); + // @ts-ignore Assigned in callback. return {promise, resolve, reject}; }; diff --git a/modules/test-utils/src/snapshot-test-runner.ts b/modules/test-utils/src/snapshot-test-runner.ts index eb86d805a9..5d099536b9 100644 --- a/modules/test-utils/src/snapshot-test-runner.ts +++ b/modules/test-utils/src/snapshot-test-runner.ts @@ -56,6 +56,7 @@ export class SnapshotTestRunner extends TestRunner { }; // Take screenshot and compare + // @ts-ignore implicit any const result = await globalThis.browserTestDriver_captureAndDiffScreen(diffOptions); // invoke user callback diff --git a/modules/test-utils/src/utils/deep-copy.ts b/modules/test-utils/src/utils/deep-copy.ts index 8b32fa7024..fdcefd96a2 100644 --- a/modules/test-utils/src/utils/deep-copy.ts +++ b/modules/test-utils/src/utils/deep-copy.ts @@ -1,11 +1,11 @@ /** Recursively copies objects */ -export function deepCopy(object: Record) { +export function deepCopy(object: any): any { if (Array.isArray(object)) { return object.map(element => deepCopy(element)); } if (object !== null && typeof object === 'object') { - const newObject = {}; + const newObject: Record = {}; for (const key in object) { newObject[key] = deepCopy(object[key]); } diff --git a/modules/test-utils/tsconfig.json b/modules/test-utils/tsconfig.json index 9fd415ee12..7ff32a2f9b 100644 --- a/modules/test-utils/tsconfig.json +++ b/modules/test-utils/tsconfig.json @@ -3,7 +3,6 @@ "include": ["src/**/*"], "exclude": ["node_modules"], "compilerOptions": { - "noImplicitAny": false, "composite": true, "rootDir": "src", "outDir": "dist" diff --git a/modules/webgl/src/adapter/converters/webgl-shadertypes.ts b/modules/webgl/src/adapter/converters/webgl-shadertypes.ts index a1951cd154..1f8680ebc3 100644 --- a/modules/webgl/src/adapter/converters/webgl-shadertypes.ts +++ b/modules/webgl/src/adapter/converters/webgl-shadertypes.ts @@ -19,6 +19,7 @@ export function convertDataTypeToGLDataType(normalizedType: NormalizedDataType): export function convertShaderVariableTypeToGLDataType( normalizedType: VariableShaderType ): GLDataType { + // @ts-ignore TODO return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType]; } @@ -31,6 +32,7 @@ export function convertGLUniformTypeToShaderVariableType( /** Check if a WebGL "uniform:" is a texture binding */ export function isGLSamplerType(type: GLUniformType | GLSamplerType): type is GLSamplerType { + // @ts-ignore TODO return Boolean(WEBGL_SAMPLER_TO_TEXTURE_BINDINGS[type]); } diff --git a/modules/webgl/src/adapter/helpers/format-utils.ts b/modules/webgl/src/adapter/helpers/format-utils.ts index bf3fd94b64..4e5a3b889c 100644 --- a/modules/webgl/src/adapter/helpers/format-utils.ts +++ b/modules/webgl/src/adapter/helpers/format-utils.ts @@ -5,7 +5,7 @@ import {GL} from '@luma.gl/constants'; // Returns number of components in a specific readPixels WebGL format -export function glFormatToComponents(format) { +export function glFormatToComponents(format: GL): 0 | 1 | 2 | 3 | 4 { switch (format) { case GL.ALPHA: case GL.R32F: @@ -33,7 +33,7 @@ export function glFormatToComponents(format) { } // Return byte count for given readPixels WebGL type -export function glTypeToBytes(type) { +export function glTypeToBytes(type: GL): 0 | 1 | 2 | 4 { switch (type) { case GL.UNSIGNED_BYTE: return 1; diff --git a/modules/webgl/src/adapter/resources/webgl-command-buffer.ts b/modules/webgl/src/adapter/resources/webgl-command-buffer.ts index e48d8f4209..458bb65b69 100644 --- a/modules/webgl/src/adapter/resources/webgl-command-buffer.ts +++ b/modules/webgl/src/adapter/resources/webgl-command-buffer.ts @@ -413,7 +413,7 @@ function getFramebuffer(source: Texture | Framebuffer): { * Returns number of components in a specific readPixels WebGL format * @todo use shadertypes utils instead? */ -export function glFormatToComponents(format): 1 | 2 | 3 | 4 { +export function glFormatToComponents(format: GL): 1 | 2 | 3 | 4 { switch (format) { case GL.ALPHA: case GL.R32F: diff --git a/modules/webgl/src/adapter/resources/webgl-render-pass.ts b/modules/webgl/src/adapter/resources/webgl-render-pass.ts index 78ffa73b8e..f48d6ee3fd 100644 --- a/modules/webgl/src/adapter/resources/webgl-render-pass.ts +++ b/modules/webgl/src/adapter/resources/webgl-render-pass.ts @@ -24,7 +24,7 @@ export class WEBGLRenderPass extends RenderPass { this.device = device; // If no viewport is provided, apply reasonably defaults - let viewport; + let viewport: NumberArray4 | undefined; if (!props?.parameters?.viewport) { if (props?.framebuffer) { // Set the viewport to the size of the framebuffer @@ -114,7 +114,7 @@ export class WEBGLRenderPass extends RenderPass { console.warn('RenderPassParameters.stencilReference not yet implemented in WebGL'); // parameters.stencilFunc = [func, ref, mask]; // Does this work? - parameters[GL.STENCIL_REF] = parameters.stencilReference; + glParameters[GL.STENCIL_REF] = parameters.stencilReference; } if ('colorMask' in parameters) { diff --git a/modules/webgl/src/context/debug/spector-types.ts b/modules/webgl/src/context/debug/spector-types.ts index f97de571c7..6f9d527814 100644 --- a/modules/webgl/src/context/debug/spector-types.ts +++ b/modules/webgl/src/context/debug/spector-types.ts @@ -1,6 +1,8 @@ // Forked from https://github.com/BabylonJS/Spector.js/blob/master/dist/spector.d.ts /* eslint-disable camelcase, no-shadow */ +// @ts-nocheck + interface IEvent { add(callback: (element: T) => void, context?: any): number; remove(id: number): void; diff --git a/modules/webgl/src/context/debug/webgl-developer-tools.ts b/modules/webgl/src/context/debug/webgl-developer-tools.ts index 2603dceac7..d1d6d976eb 100644 --- a/modules/webgl/src/context/debug/webgl-developer-tools.ts +++ b/modules/webgl/src/context/debug/webgl-developer-tools.ts @@ -112,7 +112,7 @@ function getDebugContext( // DEBUG TRACING -function getFunctionString(functionName: string, functionArgs): string { +function getFunctionString(functionName: string, functionArgs: unknown[]): string { // Cover bug in webgl-debug-tools functionArgs = Array.from(functionArgs).map(arg => (arg === undefined ? 'undefined' : arg)); let args = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, functionArgs); @@ -120,7 +120,12 @@ function getFunctionString(functionName: string, functionArgs): string { return `gl.${functionName}(${args})`; } -function onGLError(props: DebugContextProps, err, functionName: string, args: any[]): void { +function onGLError( + props: DebugContextProps, + err: number, + functionName: string, + args: unknown[] +): void { // Cover bug in webgl-debug-tools args = Array.from(args).map(arg => (arg === undefined ? 'undefined' : arg)); const errorMessage = globalThis.WebGLDebugUtils.glEnumToString(err); @@ -135,7 +140,7 @@ function onGLError(props: DebugContextProps, err, functionName: string, args: an function onValidateGLFunc( props: DebugContextProps, functionName: string, - functionArgs: any[] + functionArgs: unknown[] ): void { let functionString: string = ''; if (log.level >= 1) { diff --git a/modules/webgl/src/context/helpers/webgl-extensions.ts b/modules/webgl/src/context/helpers/webgl-extensions.ts index cd289e6823..b3e37d2c24 100644 --- a/modules/webgl/src/context/helpers/webgl-extensions.ts +++ b/modules/webgl/src/context/helpers/webgl-extensions.ts @@ -10,8 +10,11 @@ export function getWebGLExtension( name: string, extensions: GLExtensions ): unknown { + // @ts-ignore TODO if (extensions[name] === undefined) { + // @ts-ignore TODO extensions[name] = gl.getExtension(name) || null; } + // @ts-ignore TODO return extensions[name]; } diff --git a/modules/webgl/src/context/parameters/unified-parameter-api.ts b/modules/webgl/src/context/parameters/unified-parameter-api.ts index 4ff51c64d6..59cc98554a 100644 --- a/modules/webgl/src/context/parameters/unified-parameter-api.ts +++ b/modules/webgl/src/context/parameters/unified-parameter-api.ts @@ -32,16 +32,19 @@ export function setGLParameters(gl: WebGL2RenderingContext, parameters: GLParame for (const key in parameters) { const glConstant = Number(key); + // @ts-ignore TODO const setter = GL_PARAMETER_SETTERS[key]; if (setter) { // Composite setters should only be called once, so save them if (typeof setter === 'string') { + // @ts-ignore TODO compositeSetters[setter] = true; } else { // if (gl[glConstant] !== undefined) { // TODO - added above check since this is being called on WebGL2 parameters in WebGL1... // TODO - deep equal on values? only call setter if value has changed? // NOTE - the setter will automatically update this.state + // @ts-ignore TODO setter(gl, parameters[key], glConstant); } } @@ -59,6 +62,7 @@ export function setGLParameters(gl: WebGL2RenderingContext, parameters: GLParame if (cache) { for (const key in compositeSetters) { // TODO - avoid calling composite setters if values have not changed. + // @ts-ignore TODO const compositeSetter = GL_COMPOSITE_PARAMETER_SETTERS[key]; // Note - if `trackContextState` has been called, // the setter will automatically update this.state.cache @@ -92,15 +96,18 @@ export function getGLParameters( if (typeof parameters === 'number') { // single GL enum const key = parameters; + // @ts-ignore TODO const getter = GL_PARAMETER_GETTERS[key]; return getter ? getter(gl, key) : gl.getParameter(key); } const parameterKeys = Array.isArray(parameters) ? parameters : Object.keys(parameters); - const state = {}; + const state: GLParameters = {}; for (const key of parameterKeys) { + // @ts-ignore TODO const getter = GL_PARAMETER_GETTERS[key]; + // @ts-ignore TODO state[key] = getter ? getter(gl, Number(key)) : gl.getParameter(Number(key)); } return state; @@ -119,7 +126,7 @@ export function resetGLParameters(gl: WebGL2RenderingContext): void { // Helpers // Returns true if given object is empty, false otherwise. -function isObjectEmpty(object) { +function isObjectEmpty(object: Record): boolean { // @ts-ignore dummy key variable for (const key in object) { return false; diff --git a/modules/webgl/src/context/parameters/webgl-parameter-tables.ts b/modules/webgl/src/context/parameters/webgl-parameter-tables.ts index 01a6a40917..90f91ea84c 100644 --- a/modules/webgl/src/context/parameters/webgl-parameter-tables.ts +++ b/modules/webgl/src/context/parameters/webgl-parameter-tables.ts @@ -2,6 +2,8 @@ // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors +// @ts-nocheck TODO fix + // Tables describing WebGL parameters import {GL, GLParameters} from '@luma.gl/constants'; diff --git a/modules/webgl/src/context/polyfills/polyfill-webgl1-extensions.ts b/modules/webgl/src/context/polyfills/polyfill-webgl1-extensions.ts index b9219ba902..aecc39a77d 100644 --- a/modules/webgl/src/context/polyfills/polyfill-webgl1-extensions.ts +++ b/modules/webgl/src/context/polyfills/polyfill-webgl1-extensions.ts @@ -132,6 +132,7 @@ export function polyfillWebGL1Extensions(gl: WebGL2RenderingContext): void { // Injected extensions if (extensionName in boundExtensions) { + // @ts-ignore TODO string index return boundExtensions[extensionName]; } diff --git a/modules/webgl/src/context/state-tracker/deep-array-equal.ts b/modules/webgl/src/context/state-tracker/deep-array-equal.ts index 740a887c50..7721bcdc1b 100644 --- a/modules/webgl/src/context/state-tracker/deep-array-equal.ts +++ b/modules/webgl/src/context/state-tracker/deep-array-equal.ts @@ -12,11 +12,7 @@ export function deepArrayEqual( if (x === y) { return true; } - const isArrayX = Array.isArray(x) || ArrayBuffer.isView(x); - const isArrayY = Array.isArray(y) || ArrayBuffer.isView(y); - // @ts-expect-error TODO fix - if (isArrayX && isArrayY && x.length === y.length) { - // @ts-expect-error TODO fix + if (isArray(x) && isArray(y) && x.length === y.length) { for (let i = 0; i < x.length; ++i) { if (x[i] !== y[i]) { return false; @@ -26,3 +22,7 @@ export function deepArrayEqual( } return false; } + +function isArray(x: unknown): x is unknown[] { + return Array.isArray(x) || ArrayBuffer.isView(x); +} diff --git a/modules/webgl/src/context/state-tracker/with-parameters.ts b/modules/webgl/src/context/state-tracker/with-parameters.ts index 7b178da23a..98d98e3805 100644 --- a/modules/webgl/src/context/state-tracker/with-parameters.ts +++ b/modules/webgl/src/context/state-tracker/with-parameters.ts @@ -51,7 +51,7 @@ export function withGLParameters( // Helpers // Returns true if given object is empty, false otherwise. -function isObjectEmpty(object) { +function isObjectEmpty(object: unknown): boolean { // @ts-ignore - dummy key variable for (const key in object) { return false; diff --git a/modules/webgl/tsconfig.json b/modules/webgl/tsconfig.json index 831bb07c00..f83b9b9d4d 100644 --- a/modules/webgl/tsconfig.json +++ b/modules/webgl/tsconfig.json @@ -3,7 +3,6 @@ "include": ["src/**/*"], "exclude": ["node_modules"], "compilerOptions": { - "noImplicitAny": false, "composite": true, "rootDir": "src", "outDir": "dist" diff --git a/modules/webgpu/tsconfig.json b/modules/webgpu/tsconfig.json index b787097330..016a4567cb 100644 --- a/modules/webgpu/tsconfig.json +++ b/modules/webgpu/tsconfig.json @@ -4,7 +4,6 @@ "exclude": ["node_modules"], "compilerOptions": { "typeRoots": ["../../node_modules/@webgpu/types"], - "noImplicitAny": true, "composite": true, "rootDir": "src", "outDir": "dist" diff --git a/tsconfig.json b/tsconfig.json index 6be97b70ea..9ff687f6bf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,6 @@ "skipLibCheck": true, "strict": true, - "noImplicitAny": true, // covered by strict "noImplicitThis": true, // covered by strict "strictBindCallApply": true, // covered by strict