Skip to content

Commit f5db64e

Browse files
authored
Reworked all callables to not use Function inheritance. (#300)
1 parent 68caf02 commit f5db64e

File tree

7 files changed

+231
-455
lines changed

7 files changed

+231
-455
lines changed

packages/typegpu/src/callable.ts

Lines changed: 0 additions & 34 deletions
This file was deleted.

packages/typegpu/src/data/matrix.ts

Lines changed: 70 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
Measurer,
77
type Parsed,
88
} from 'typed-binary';
9-
import { CallableImpl } from '../callable';
109
import { RecursiveDataTypeError } from '../errors';
1110
import { roundUp } from '../mathUtils';
1211
import type { TgpuData } from '../types';
@@ -17,48 +16,72 @@ import { vec2f, vec3f, vec4f, type vecBase } from './vector';
1716
// Implementation
1817
// --------------
1918

20-
interface MatSchemaOptions<T, TVec extends vecBase> {
19+
interface MatSchemaOptions<ValueType, ColumnType extends vecBase> {
2120
label: string;
22-
columnType: TgpuData<TVec>;
21+
columnType: TgpuData<ColumnType>;
2322
rows: number;
2423
columns: number;
25-
makeFromColumnVectors(...columns: TVec[]): T;
26-
makeFromElements(...elements: number[]): T;
24+
makeFromColumnVectors(...columns: ColumnType[]): ValueType;
25+
makeFromElements(...elements: number[]): ValueType;
2726
}
2827

29-
class MatSchemaImpl<T extends matBase<TColumn>, TColumn extends vecBase>
30-
extends CallableImpl<(number | TColumn)[], T>
31-
implements TgpuData<T>
32-
{
33-
public readonly __unwrapped!: T;
34-
35-
private readonly _columnType: TgpuData<TColumn>;
36-
private readonly _rows: number;
37-
private readonly _columns: number;
38-
private readonly _makeFromColumnVectors: (...columns: TColumn[]) => T;
39-
private readonly _makeFromElements: (...elements: number[]) => T;
40-
41-
public readonly byteAlignment: number;
42-
public readonly size: number;
43-
public readonly label: string;
44-
45-
constructor(options: MatSchemaOptions<T, TColumn>) {
46-
super();
47-
this._columnType = options.columnType;
48-
this._rows = options.rows;
49-
this._columns = options.columns;
50-
this.label = options.label;
51-
this._makeFromColumnVectors = options.makeFromColumnVectors;
52-
this._makeFromElements = options.makeFromElements;
53-
54-
this.byteAlignment = this._columnType.byteAlignment;
55-
this.size = roundUp(
56-
this._columnType.size * this._columns,
57-
this.byteAlignment,
58-
);
59-
}
28+
type MatSchema<
29+
ValueType extends matBase<ColumnType>,
30+
ColumnType extends vecBase,
31+
> = TgpuData<ValueType> & ((...args: (number | ColumnType)[]) => ValueType);
32+
33+
function createMatSchema<
34+
ValueType extends matBase<ColumnType>,
35+
ColumnType extends vecBase,
36+
>(
37+
options: MatSchemaOptions<ValueType, ColumnType>,
38+
): MatSchema<ValueType, ColumnType> {
39+
const MatSchema: TgpuData<ValueType> = {
40+
// Type-token, not available at runtime.
41+
__unwrapped: undefined as unknown as ValueType,
42+
43+
label: options.label,
44+
byteAlignment: options.columnType.byteAlignment,
45+
size: roundUp(
46+
options.columnType.size * options.columns,
47+
options.columnType.byteAlignment,
48+
),
49+
50+
resolveReferences() {
51+
throw new RecursiveDataTypeError();
52+
},
53+
54+
write(output: ISerialOutput, value: Parsed<ValueType>): void {
55+
for (const col of value.columns()) {
56+
options.columnType.write(output, col as Parsed<ColumnType>);
57+
}
58+
},
59+
60+
read(input: ISerialInput): Parsed<ValueType> {
61+
const columns = new Array(options.columns) as ColumnType[];
62+
63+
for (let c = 0; c < options.columns; ++c) {
64+
columns[c] = options.columnType.read(input) as ColumnType;
65+
}
66+
67+
return options.makeFromColumnVectors(...columns) as Parsed<ValueType>;
68+
},
6069

61-
_call(...args: (number | TColumn)[]): T {
70+
measure(_value: MaxValue, measurer: IMeasurer = new Measurer()): IMeasurer {
71+
alignIO(measurer, this.byteAlignment);
72+
return measurer.add(this.size);
73+
},
74+
75+
seekProperty() {
76+
throw new Error('Method not implemented.');
77+
},
78+
79+
resolve(): string {
80+
return options.label;
81+
},
82+
};
83+
84+
const construct = (...args: (number | ColumnType)[]): ValueType => {
6285
const elements: number[] = [];
6386

6487
for (const arg of args) {
@@ -70,45 +93,14 @@ class MatSchemaImpl<T extends matBase<TColumn>, TColumn extends vecBase>
7093
}
7194

7295
// Fill the rest with zeros
73-
for (let i = elements.length; i < this._columns * this._rows; ++i) {
96+
for (let i = elements.length; i < options.columns * options.rows; ++i) {
7497
elements.push(0);
7598
}
7699

77-
return this._makeFromElements(...elements);
78-
}
79-
80-
resolveReferences(): void {
81-
throw new RecursiveDataTypeError();
82-
}
83-
84-
write(output: ISerialOutput, value: Parsed<T>): void {
85-
for (const col of value.columns()) {
86-
this._columnType.write(output, col as Parsed<TColumn>);
87-
}
88-
}
89-
90-
read(input: ISerialInput): Parsed<T> {
91-
const columns = new Array(this._columns) as TColumn[];
100+
return options.makeFromElements(...elements);
101+
};
92102

93-
for (let c = 0; c < this._columns; ++c) {
94-
columns[c] = this._columnType.read(input) as TColumn;
95-
}
96-
97-
return this._makeFromColumnVectors(...columns) as Parsed<T>;
98-
}
99-
100-
measure(_value: MaxValue, measurer: IMeasurer = new Measurer()): IMeasurer {
101-
alignIO(measurer, this.byteAlignment);
102-
return measurer.add(this.size);
103-
}
104-
105-
seekProperty(): null {
106-
throw new Error('Method not implemented.');
107-
}
108-
109-
resolve(): string {
110-
return this.label;
111-
}
103+
return Object.assign(construct, MatSchema);
112104
}
113105

114106
interface matBase<TColumn> {
@@ -308,15 +300,15 @@ export type Mat2x2f = TgpuData<mat2x2f> &
308300
((...columns: vec2f[]) => mat2x2f) &
309301
(() => mat2x2f);
310302

311-
export const mat2x2f = new MatSchemaImpl({
303+
export const mat2x2f = createMatSchema({
312304
label: 'mat2x2f',
313305
columnType: vec2f,
314306
rows: 2,
315307
columns: 2,
316308
makeFromColumnVectors: (...columns: [vec2f, vec2f]) =>
317309
new mat2x2fImpl(...columns[0], ...columns[1]),
318310
makeFromElements: (...elements: number[]) => new mat2x2fImpl(...elements),
319-
}) as unknown as Mat2x2f;
311+
}) as Mat2x2f;
320312

321313
export interface mat3x3<TColumn> extends matBase<TColumn> {
322314
[0]: TColumn;
@@ -332,7 +324,7 @@ export type Mat3x3f = TgpuData<mat3x3f> &
332324
((...columns: vec3f[]) => mat3x3f) &
333325
(() => mat3x3f);
334326

335-
export const mat3x3f = new MatSchemaImpl({
327+
export const mat3x3f = createMatSchema({
336328
label: 'mat3x3f',
337329
columnType: vec3f,
338330
rows: 3,
@@ -341,7 +333,7 @@ export const mat3x3f = new MatSchemaImpl({
341333
return new mat3x3fImpl(...v0, ...v1, ...v2);
342334
},
343335
makeFromElements: (...elements: number[]) => new mat3x3fImpl(...elements),
344-
}) as unknown as Mat3x3f;
336+
}) as Mat3x3f;
345337

346338
export interface mat4x4<TColumn> extends matBase<TColumn> {
347339
[0]: TColumn;
@@ -358,7 +350,7 @@ export type Mat4x4f = TgpuData<mat4x4f> &
358350
((...columns: vec4f[]) => mat4x4f) &
359351
(() => mat4x4f);
360352

361-
export const mat4x4f = new MatSchemaImpl({
353+
export const mat4x4f = createMatSchema({
362354
label: 'mat4x4f',
363355
columnType: vec4f,
364356
rows: 4,
@@ -367,4 +359,4 @@ export const mat4x4f = new MatSchemaImpl({
367359
return new mat4x4fImpl(...v0, ...v1, ...v2, ...v3);
368360
},
369361
makeFromElements: (...elements: number[]) => new mat4x4fImpl(...elements),
370-
}) as unknown as Mat4x4f;
362+
}) as Mat4x4f;

0 commit comments

Comments
 (0)