Skip to content

Commit

Permalink
chore: various type fixes addressing deck.gl integration (#1685)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Nov 29, 2022
1 parent d4a9247 commit 7d9b397
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 63 deletions.
4 changes: 1 addition & 3 deletions modules/api/src/adapter/resources/texture.ts
@@ -1,6 +1,6 @@
// luma.gl, MIT license
import type Device from '../device';
import type {TypedArray} from '../../types';
import type {TypedArray, PartialBy} from '../../types';
import type {TextureFormat} from '../types/texture-formats';
import Resource, {ResourceProps, DEFAULT_RESOURCE_PROPS} from './resource';
import Sampler, {SamplerProps} from './sampler';
Expand Down Expand Up @@ -80,8 +80,6 @@ export type TextureViewProps = {
baseMipLevel?: number;
};

type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

const DEFAULT_TEXTURE_PROPS: PartialBy<Required<TextureProps>, 'width' | 'height' | 'type' | 'samples' | 'mipLevels' | 'textureUnit' | 'target' | 'dataFormat'> = {
...DEFAULT_RESOURCE_PROPS,
data: null,
Expand Down
15 changes: 11 additions & 4 deletions modules/api/src/index.ts
Expand Up @@ -10,7 +10,6 @@ export {default as Device} from './adapter/device';
export type {CanvasContextProps} from './adapter/canvas-context';
export {default as CanvasContext} from './adapter/canvas-context';


// GPU RESOURCES
export type {ResourceProps} from './adapter/resources/resource';
export {default as Resource} from './adapter/resources/resource';
Expand Down Expand Up @@ -64,7 +63,7 @@ export type {UniformFormat} from './adapter/types/uniform-formats';
export type {
TextureFormat,
ColorTextureFormat,
DepthStencilTextureFormat,
DepthStencilTextureFormat
} from './adapter/types/texture-formats';
export type {ColorAttachment, DepthStencilAttachment} from './adapter/types/types';

Expand All @@ -90,9 +89,17 @@ export {default as UniformBlock} from './lib/uniform-block';
export {decodeVertexFormat} from './adapter/utils/decode-vertex-format';
export {decodeTextureFormat} from './adapter/utils/decode-texture-format';


// GENERAL TYPES
export type {TypedArray, TypedArrayConstructor, NumberArray} from './types';
export type {
TypedArray,
TypedArrayConstructor,
NumberArray,
NumericArray,
BigIntOrNumberArray,
BigIntOrNumericArray,
ConstructorOf,
PartialBy
} from './types';

// GENERAL UTILS

Expand Down
20 changes: 18 additions & 2 deletions modules/api/src/types.ts
Expand Up @@ -10,7 +10,8 @@ export type TypedArray =
| Float32Array
| Float64Array;

export type TypedArrayConstructor =
/** TypeScript type covering constructors of any of the typed arrays */
export type TypedArrayConstructor =
| Int8ArrayConstructor
| Uint8ArrayConstructor
| Int16ArrayConstructor
Expand All @@ -21,9 +22,24 @@ export type TypedArray =
| Float32ArrayConstructor
| Float64ArrayConstructor;

export type BigIntTypedArray = BigInt64Array | BigUint64Array;
/** Keep big int arrays separate as they are still problematic, can't be indexed and don't work well on Safari */
export type BigIntTypedArray = BigInt64Array | BigUint64Array;

/** type covering all typed arrays and classic arrays consisting of numbers */
export type NumberArray = number[] | TypedArray;
export type NumericArray = number[] | TypedArray;

export type BigIntOrNumberArray = NumberArray | BigIntTypedArray;
export type BigIntOrNumericArray = NumberArray | BigIntTypedArray;

/** Get the constructor type of a type */
export interface ConstructorOf<T> {
new (...args: unknown[]): T;
}

/**
* Make specific fields in a type optional. Granular version of `Partial<T>`
* @example
* type PartialProps = PartialBy<Required<DeviceProps>, 'device' | 'canvas'>
*/
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
9 changes: 4 additions & 5 deletions modules/engine/src/lib/model.ts
@@ -1,6 +1,6 @@
// luma.gl, MIT license

import type {Device, Buffer, RenderPipelineProps, RenderPass, Binding} from '@luma.gl/api';
import type {Device, Buffer, RenderPipelineProps, RenderPass, Binding, PrimitiveTopology} from '@luma.gl/api';
import {RenderPipeline, Shader, cast} from '@luma.gl/api';
import type { ShaderModule } from '@luma.gl/shadertools';
import type Geometry from '../geometry/geometry';
Expand Down Expand Up @@ -35,7 +35,7 @@ export default class Model {
readonly id: string;
readonly vs: string;
readonly fs: string | undefined;
readonly topology: string;
readonly topology: PrimitiveTopology;
readonly vertexCount;
props: Required<ModelProps>;

Expand All @@ -61,14 +61,13 @@ export default class Model {
this.topology = this.props.geometry.topology;
}

const {pipeline, getUniforms} = PipelineFactory.getDefaultPipelineFactory(this.device).createRenderPipeline({
const pipelineFactory = PipelineFactory.getDefaultPipelineFactory(this.device);
const {pipeline, getUniforms} = pipelineFactory.createRenderPipeline({
...this.props,
vs: this.vs,
fs: this.fs,
topology: this.topology,
parameters: props.parameters,
// Geometry in the vertex shader!
// @ts-expect-error
layout: props.layout
});

Expand Down
28 changes: 15 additions & 13 deletions modules/engine/src/lib/pipeline-factory.ts
@@ -1,34 +1,35 @@
import type {RenderPipelineProps, RenderPipelineParameters} from '@luma.gl/api';
import type {RenderPipelineProps, RenderPipelineParameters, PrimitiveTopology, ShaderLayout} from '@luma.gl/api';
import {Device, RenderPipeline, ComputePipeline} from '@luma.gl/api/';
import type { ShaderModule } from '@luma.gl/shadertools';
import {assembleShaders} from '@luma.gl/shadertools';

export type GetRenderPipelineOptions = {
vs: string,
fs: string,
topology;
vs: string;
fs: string;
topology: PrimitiveTopology;
layout?: ShaderLayout;
parameters?: RenderPipelineParameters;

modules?: ShaderModule[];
defines?: Record<string, string | number | boolean>,
inject?: Record<string, string>,
defines?: Record<string, string | number | boolean>;
inject?: Record<string, string>;
transpileToGLSL100?: boolean;

varyings?: string[],
varyings?: string[];
bufferMode?: number,
};

export type GetComputePipelineOptions = {
cs: string,
parameters?: RenderPipelineParameters;
cs: string;
parameters?: RenderPipelineParameters;

modules?: ShaderModule[];
defines?: Record<string, string>,
inject?: Record<string, string>,
defines?: Record<string, string>;
inject?: Record<string, string>;
transpileToGLSL100?: boolean;

varyings?: string[],
bufferMode?: number,
varyings?: string[];
bufferMode?: number;
};

const DEFAULT_RENDER_PIPELINE_OPTIONS: Required<GetRenderPipelineOptions> = {
Expand All @@ -38,6 +39,7 @@ const DEFAULT_RENDER_PIPELINE_OPTIONS: Required<GetRenderPipelineOptions> = {
defines: {},
inject: {},
transpileToGLSL100: false,
layout: null,

varyings: [],
bufferMode: 0x8c8d, // // varyings/bufferMode for xform feedback, 0x8c8d: SEPARATE_ATTRIBS
Expand Down
56 changes: 28 additions & 28 deletions modules/engine/test/lib/pipeline-factory.spec.ts
Expand Up @@ -66,18 +66,18 @@ test('PipelineFactory#getDefaultPipelineFactory', (t) => {
test('PipelineFactory#basic', (t) => {
const pipelineFactory = new PipelineFactory(webgl1TestDevice);

const {pipeline: program1} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: program1} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});

t.ok(program1, 'Got a pipeline');

const {pipeline: pipeline2} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: pipeline2} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});

t.ok(program1 === pipeline2, 'Got cached pipeline');

const {pipeline: definePipeline1} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
defines: {
MY_DEFINE: true
}
Expand All @@ -88,7 +88,7 @@ test('PipelineFactory#basic', (t) => {
const {pipeline: definePipeline2} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
defines: {
MY_DEFINE: true
}
Expand All @@ -99,7 +99,7 @@ test('PipelineFactory#basic', (t) => {
const {pipeline: modulePipeline1} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
modules: [picking]
});

Expand All @@ -109,7 +109,7 @@ test('PipelineFactory#basic', (t) => {
const {pipeline: modulePipeline2} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
modules: [picking]
});

Expand All @@ -118,7 +118,7 @@ test('PipelineFactory#basic', (t) => {
const {pipeline: defineModulePipeline1} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
modules: [picking],
defines: {
MY_DEFINE: true
Expand All @@ -132,7 +132,7 @@ test('PipelineFactory#basic', (t) => {
const {pipeline: defineModulePipeline2} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
modules: [picking],
defines: {
MY_DEFINE: true
Expand All @@ -150,15 +150,15 @@ test('PipelineFactory#basic', (t) => {
test('PipelineFactory#hooks', (t) => {
const pipelineFactory = new PipelineFactory(webgl1TestDevice);

const {pipeline: preHookPipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: preHookPipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});

pipelineFactory.addShaderHook('vs:LUMAGL_pickColor(inout vec4 color)');
pipelineFactory.addShaderHook('fs:LUMAGL_fragmentColor(inout vec4 color)', {
header: 'if (color.a == 0.0) discard;\n',
footer: 'color.a *= 1.2;\n'
});

const {pipeline: postHookPipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: postHookPipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});

t.ok(preHookPipeline !== postHookPipeline, 'Adding hooks changes hash');

Expand All @@ -175,7 +175,7 @@ test('PipelineFactory#hooks', (t) => {
picking
);

const {pipeline: noModulePipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: noModulePipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});

t.ok(preHookPipeline !== noModulePipeline, 'Adding hooks changes hash');

Expand All @@ -200,7 +200,7 @@ test('PipelineFactory#hooks', (t) => {
const {pipeline: modulesPipeline} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
modules: [pickingInjection]
});
const modulesVs = modulesPipeline.vs.source;
Expand Down Expand Up @@ -232,7 +232,7 @@ test('PipelineFactory#hooks', (t) => {
const {pipeline: injectPipeline} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
inject: {
'vs:LUMAGL_pickColor': 'color *= 0.1;',
'fs:LUMAGL_fragmentColor': 'color += 0.1;'
Expand All @@ -247,7 +247,7 @@ test('PipelineFactory#hooks', (t) => {
const {pipeline: injectDefinePipeline1} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
inject: {
'vs:LUMAGL_pickColor': 'color *= 0.1;'
}
Expand All @@ -256,7 +256,7 @@ test('PipelineFactory#hooks', (t) => {
const {pipeline: injectDefinePipeline2} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
defines: {
'vs:LUMAGL_pickColor': 'color *= 0.1;'
}
Expand All @@ -270,24 +270,24 @@ test('PipelineFactory#hooks', (t) => {
test('PipelineFactory#defaultModules', (t) => {
const pipelineFactory = new PipelineFactory(webgl1TestDevice);

const {pipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});

const {pipeline: preDefaultModulePipeline} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
modules: [dirlight]
});

const preDefaultModuleSource = preDefaultModulePipeline.fs.source;

pipelineFactory.addDefaultModule(dirlight);

const {pipeline: defaultModulePipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: defaultModulePipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
const {pipeline: modulePipeline} = pipelineFactory.createRenderPipeline({
vs,
fs,
topology: 'triangles',
topology: 'triangle-list',
modules: [dirlight]
});

Expand All @@ -307,7 +307,7 @@ test('PipelineFactory#defaultModules', (t) => {

pipelineFactory.removeDefaultModule(dirlight);

const {pipeline: noDefaultModulePipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: noDefaultModulePipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});

t.ok(pipeline.fs.source === noDefaultModulePipeline.fs.source, 'Default module was removed');
t.ok(modulePipeline.fs.source !== noDefaultModulePipeline.fs.source, 'Default module was removed');
Expand All @@ -319,7 +319,7 @@ test('PipelineFactory#defaultModules', (t) => {
pipelineFactory.release(noDefaultModulePipeline);

pipelineFactory.addDefaultModule(dirlight);
const {pipeline: uncachedPipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: uncachedPipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
const defaultModuleSource = uncachedPipeline.fs.source;

t.ok(defaultModulePipeline !== uncachedPipeline, 'Pipeline is not cached');
Expand All @@ -331,8 +331,8 @@ test('PipelineFactory#defaultModules', (t) => {
test('PipelineFactory#release', (t) => {
const pipelineFactory = new PipelineFactory(webgl1TestDevice);

const {pipeline: pipeline1} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: pipeline2} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: pipeline1} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
const {pipeline: pipeline2} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});

pipelineFactory.release(pipeline1);
t.ok(!pipeline1.destroyed, 'Pipeline not deleted when still referenced.');
Expand All @@ -350,22 +350,22 @@ test('PipelineFactory#transpileToGLSL100', (t) => {
pipelineFactory.createRenderPipeline({
vs: VS_300,
fs: FS_300,
topology: 'triangles'
topology: 'triangle-list'
});
}, "Can't compile 300 shader with WebGL 1");

t.doesNotThrow(() => {
pipelineFactory.createRenderPipeline({
vs: VS_300,
fs: FS_300,
topology: 'triangles',
topology: 'triangle-list',
transpileToGLSL100: true
});
}, 'Can compile transpiled 300 shader with WebGL 1');

const {pipeline: programTranspiled} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles', transpileToGLSL100: true});
const {pipeline: programUntranspiled} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles'});
const {pipeline: programTranspiled2} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangles', transpileToGLSL100: true});
const {pipeline: programTranspiled} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list', transpileToGLSL100: true});
const {pipeline: programUntranspiled} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
const {pipeline: programTranspiled2} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list', transpileToGLSL100: true});

t.equals(programTranspiled, programTranspiled2, 'Transpiled programs match');
t.notEquals(
Expand Down

0 comments on commit 7d9b397

Please sign in to comment.