typegpu
Version:
A thin layer between JS and WebGPU/WGSL that improves development experience and allows for faster iteration.
566 lines (565 loc) • 12.1 kB
JavaScript
import { $internal, $resolve } from "../shared/symbols.js";
import { numericLiteralToSnippet } from "../tgsl/generationHelpers.js";
import { bool, f16, f32, i32, u32 } from "./numeric.js";
import {} from "./snippet.js";
import { WORKAROUND_getSchema } from "./wgslTypes.js";
const XYZW = ['x', 'y', 'z', 'w'];
const RGBA = ['r', 'g', 'b', 'a'];
export class VecBase extends Array {
static {
// Defining 4-length swizzles
for (let e0 = 0; e0 < 4; e0++) {
for (let e1 = 0; e1 < 4; e1++) {
for (let e2 = 0; e2 < 4; e2++) {
for (let e3 = 0; e3 < 4; e3++) {
const xyzwProp = `${XYZW[e0]}${XYZW[e1]}${XYZW[e2]}${XYZW[e3]}`;
const rgbaProp = `${RGBA[e0]}${RGBA[e1]}${RGBA[e2]}${RGBA[e3]}`;
Object.defineProperty(VecBase.prototype, xyzwProp, {
get() {
return new this._Vec4(this[e0], this[e1], this[e2], this[e3]);
},
});
Object.defineProperty(VecBase.prototype, rgbaProp, {
get() {
return new this._Vec4(this[e0], this[e1], this[e2], this[e3]);
},
});
}
}
}
}
// Defining 3-length swizzles
for (let e0 = 0; e0 < 4; e0++) {
for (let e1 = 0; e1 < 4; e1++) {
for (let e2 = 0; e2 < 4; e2++) {
const xyzwProp = `${XYZW[e0]}${XYZW[e1]}${XYZW[e2]}`;
const rgbaProp = `${RGBA[e0]}${RGBA[e1]}${RGBA[e2]}`;
Object.defineProperty(VecBase.prototype, xyzwProp, {
get() {
return new this._Vec3(this[e0], this[e1], this[e2]);
},
});
Object.defineProperty(VecBase.prototype, rgbaProp, {
get() {
return new this._Vec3(this[e0], this[e1], this[e2]);
},
});
}
}
}
// Defining 2-length swizzles
for (let e0 = 0; e0 < 4; e0++) {
for (let e1 = 0; e1 < 4; e1++) {
const xyzwProp = `${XYZW[e0]}${XYZW[e1]}`;
const rgbaProp = `${RGBA[e0]}${RGBA[e1]}`;
Object.defineProperty(VecBase.prototype, xyzwProp, {
get() {
return new this._Vec2(this[e0], this[e1]);
},
});
Object.defineProperty(VecBase.prototype, rgbaProp, {
get() {
return new this._Vec2(this[e0], this[e1]);
},
});
}
}
}
castElement() {
return this[$internal].elementSchema;
}
[$resolve](ctx) {
// oxlint-disable-next-line typescript-eslint(no-explicit-any)
const vecSchema = WORKAROUND_getSchema(this);
if (this.every((e) => !e)) {
return ctx.gen.typeInstantiation(vecSchema, []);
}
if (this.every((e) => this[0] === e)) {
return ctx.gen.typeInstantiation(vecSchema, [numericLiteralToSnippet(this[0])]);
}
return ctx.gen.typeInstantiation(vecSchema, this.map((e) => numericLiteralToSnippet(e)));
}
toString() {
return `${this.kind}(${this.join(', ')})`;
}
}
class Vec2 extends VecBase {
e0;
e1;
constructor(x, y) {
super(2);
this.e0 = this.castElement()(x);
this.e1 = this.castElement()(y ?? x);
}
get 0() {
return this.e0;
}
get 1() {
return this.e1;
}
set 0(value) {
this.e0 = this.castElement()(value);
}
set 1(value) {
this.e1 = this.castElement()(value);
}
get x() {
return this[0];
}
get y() {
return this[1];
}
set x(value) {
this[0] = this.castElement()(value);
}
set y(value) {
this[1] = this.castElement()(value);
}
get r() {
return this[0];
}
get g() {
return this[1];
}
set r(value) {
this[0] = this.castElement()(value);
}
set g(value) {
this[1] = this.castElement()(value);
}
}
class Vec3 extends VecBase {
e0;
e1;
e2;
constructor(x, y, z) {
super(3);
this.e0 = this.castElement()(x);
this.e1 = this.castElement()(y ?? x);
this.e2 = this.castElement()(z ?? x);
}
get 0() {
return this.e0;
}
get 1() {
return this.e1;
}
get 2() {
return this.e2;
}
set 0(value) {
this.e0 = this.castElement()(value);
}
set 1(value) {
this.e1 = this.castElement()(value);
}
set 2(value) {
this.e2 = this.castElement()(value);
}
get x() {
return this[0];
}
get y() {
return this[1];
}
get z() {
return this[2];
}
set x(value) {
this[0] = this.castElement()(value);
}
set y(value) {
this[1] = this.castElement()(value);
}
set z(value) {
this[2] = this.castElement()(value);
}
get r() {
return this[0];
}
get g() {
return this[1];
}
get b() {
return this[2];
}
set r(value) {
this[0] = this.castElement()(value);
}
set g(value) {
this[1] = this.castElement()(value);
}
set b(value) {
this[2] = this.castElement()(value);
}
}
class Vec4 extends VecBase {
e0;
e1;
e2;
e3;
constructor(x, y, z, w) {
super(4);
this.e0 = this.castElement()(x);
this.e1 = this.castElement()(y ?? x);
this.e2 = this.castElement()(z ?? x);
this.e3 = this.castElement()(w ?? x);
}
get 0() {
return this.e0;
}
get 1() {
return this.e1;
}
get 2() {
return this.e2;
}
get 3() {
return this.e3;
}
set 0(value) {
this.e0 = this.castElement()(value);
}
set 1(value) {
this.e1 = this.castElement()(value);
}
set 2(value) {
this.e2 = this.castElement()(value);
}
set 3(value) {
this.e3 = this.castElement()(value);
}
get x() {
return this[0];
}
get y() {
return this[1];
}
get z() {
return this[2];
}
get w() {
return this[3];
}
set x(value) {
this[0] = value;
}
set y(value) {
this[1] = value;
}
set z(value) {
this[2] = value;
}
set w(value) {
this[3] = value;
}
get r() {
return this[0];
}
get g() {
return this[1];
}
get b() {
return this[2];
}
get a() {
return this[3];
}
set r(value) {
this[0] = value;
}
set g(value) {
this[1] = value;
}
set b(value) {
this[2] = value;
}
set a(value) {
this[3] = value;
}
}
export class Vec2fImpl extends Vec2 {
get [$internal]() {
return {
elementSchema: f32,
};
}
get kind() {
return 'vec2f';
}
get _Vec2() {
return Vec2fImpl;
}
get _Vec3() {
return Vec3fImpl;
}
get _Vec4() {
return Vec4fImpl;
}
}
export class Vec2hImpl extends Vec2 {
get [$internal]() {
return {
elementSchema: f16,
};
}
get kind() {
return 'vec2h';
}
get _Vec2() {
return Vec2hImpl;
}
get _Vec3() {
return Vec3hImpl;
}
get _Vec4() {
return Vec4hImpl;
}
}
export class Vec2iImpl extends Vec2 {
get [$internal]() {
return {
elementSchema: i32,
};
}
get kind() {
return 'vec2i';
}
get _Vec2() {
return Vec2iImpl;
}
get _Vec3() {
return Vec3iImpl;
}
get _Vec4() {
return Vec4iImpl;
}
}
export class Vec2uImpl extends Vec2 {
get [$internal]() {
return {
elementSchema: u32,
};
}
get kind() {
return 'vec2u';
}
get _Vec2() {
return Vec2uImpl;
}
get _Vec3() {
return Vec3uImpl;
}
get _Vec4() {
return Vec4uImpl;
}
}
export class Vec2bImpl extends Vec2 {
get [$internal]() {
return {
elementSchema: bool,
};
}
get kind() {
return 'vec2<bool>';
}
get _Vec2() {
return Vec2bImpl;
}
get _Vec3() {
return Vec3bImpl;
}
get _Vec4() {
return Vec4bImpl;
}
}
export class Vec3fImpl extends Vec3 {
get [$internal]() {
return {
elementSchema: f32,
};
}
get kind() {
return 'vec3f';
}
get _Vec2() {
return Vec2fImpl;
}
get _Vec3() {
return Vec3fImpl;
}
get _Vec4() {
return Vec4fImpl;
}
}
export class Vec3hImpl extends Vec3 {
get [$internal]() {
return {
elementSchema: f16,
};
}
get kind() {
return 'vec3h';
}
get _Vec2() {
return Vec2hImpl;
}
get _Vec3() {
return Vec3hImpl;
}
get _Vec4() {
return Vec4hImpl;
}
}
export class Vec3iImpl extends Vec3 {
get [$internal]() {
return {
elementSchema: i32,
};
}
get kind() {
return 'vec3i';
}
get _Vec2() {
return Vec2iImpl;
}
get _Vec3() {
return Vec3iImpl;
}
get _Vec4() {
return Vec4iImpl;
}
}
export class Vec3uImpl extends Vec3 {
get [$internal]() {
return {
elementSchema: u32,
};
}
get kind() {
return 'vec3u';
}
get _Vec2() {
return Vec2uImpl;
}
get _Vec3() {
return Vec3uImpl;
}
get _Vec4() {
return Vec4uImpl;
}
}
export class Vec3bImpl extends Vec3 {
get [$internal]() {
return {
elementSchema: bool,
};
}
get kind() {
return 'vec3<bool>';
}
get _Vec2() {
return Vec2bImpl;
}
get _Vec3() {
return Vec3bImpl;
}
get _Vec4() {
return Vec4bImpl;
}
}
export class Vec4fImpl extends Vec4 {
get [$internal]() {
return {
elementSchema: f32,
};
}
get kind() {
return 'vec4f';
}
get _Vec2() {
return Vec2fImpl;
}
get _Vec3() {
return Vec3fImpl;
}
get _Vec4() {
return Vec4fImpl;
}
}
export class Vec4hImpl extends Vec4 {
get [$internal]() {
return {
elementSchema: f16,
};
}
get kind() {
return 'vec4h';
}
get _Vec2() {
return Vec2hImpl;
}
get _Vec3() {
return Vec3hImpl;
}
get _Vec4() {
return Vec4hImpl;
}
}
export class Vec4iImpl extends Vec4 {
get [$internal]() {
return {
elementSchema: i32,
};
}
get kind() {
return 'vec4i';
}
get _Vec2() {
return Vec2iImpl;
}
get _Vec3() {
return Vec3iImpl;
}
get _Vec4() {
return Vec4iImpl;
}
}
export class Vec4uImpl extends Vec4 {
get [$internal]() {
return {
elementSchema: u32,
};
}
get kind() {
return 'vec4u';
}
get _Vec2() {
return Vec2uImpl;
}
get _Vec3() {
return Vec3uImpl;
}
get _Vec4() {
return Vec4uImpl;
}
}
export class Vec4bImpl extends Vec4 {
get [$internal]() {
return {
elementSchema: bool,
};
}
get kind() {
return 'vec4<bool>';
}
get _Vec2() {
return Vec2bImpl;
}
get _Vec3() {
return Vec3bImpl;
}
get _Vec4() {
return Vec4bImpl;
}
}