typegpu 0.12.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/std/operators.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { dualImpl } from "../core/function/dualImpl.js";
2
2
  import { stitch } from "../core/resolve/stitch.js";
3
3
  import { abstractFloat, f16, f32, u32 } from "../data/numeric.js";
4
- import { vec2i, vec2u, vec3i, vec3u, vec4i, vec4u, vecTypeToConstructor } from "../data/vector.js";
4
+ import { vec2i, vec2u, vec3i, vec3u, vec4i, vec4u } from "../data/vector.js";
5
5
  import { VectorOps } from "../data/vectorOps.js";
6
+ import { generalizeFn, upCast } from "../data/generalizeFn.js";
6
7
  import { isFloat32VecInstance, isInteger32VecInstance, isMat, isMatInstance, isUint32VecInstance, isVec, isVecInstance, } from "../data/wgslTypes.js";
7
8
  import { SignatureNotSupportedError } from "../errors.js";
8
9
  import { unify } from "../tgsl/conversion.js";
@@ -59,13 +60,13 @@ function cpuAdd(lhs, rhs) {
59
60
  return lhs + rhs; // default addition
60
61
  }
61
62
  if (typeof lhs === 'number' && isVecInstance(rhs)) {
62
- return VectorOps.addMixed[rhs.kind](rhs, lhs); // mixed addition
63
+ return generalizeFn((e) => lhs + e, [rhs]); // mixed addition
63
64
  }
64
65
  if (isVecInstance(lhs) && typeof rhs === 'number') {
65
- return VectorOps.addMixed[lhs.kind](lhs, rhs); // mixed addition
66
+ return generalizeFn((e) => e + rhs, [lhs]); // mixed addition
66
67
  }
67
68
  if ((isVecInstance(lhs) && isVecInstance(rhs)) || (isMatInstance(lhs) && isMatInstance(rhs))) {
68
- return VectorOps.add[lhs.kind](lhs, rhs); // component-wise addition
69
+ return generalizeFn((a, b) => a + b, [lhs, rhs]); // component-wise addition
69
70
  }
70
71
  throw new Error('Add/Sub called with invalid arguments.');
71
72
  }
@@ -92,13 +93,13 @@ function cpuMul(lhs, rhs) {
92
93
  return lhs * rhs; // default multiplication
93
94
  }
94
95
  if (typeof lhs === 'number' && (isVecInstance(rhs) || isMatInstance(rhs))) {
95
- return VectorOps.mulSxV[rhs.kind](lhs, rhs); // scale
96
+ return generalizeFn((e) => lhs * e, [rhs]); // scale
96
97
  }
97
98
  if ((isVecInstance(lhs) || isMatInstance(lhs)) && typeof rhs === 'number') {
98
- return VectorOps.mulSxV[lhs.kind](rhs, lhs); // scale
99
+ return generalizeFn((e) => e * rhs, [lhs]); // scale
99
100
  }
100
101
  if (isVecInstance(lhs) && isVecInstance(rhs)) {
101
- return VectorOps.mulVxV[lhs.kind](lhs, rhs); // component-wise
102
+ return generalizeFn((a, b) => a * b, [lhs, rhs]); // component-wise
102
103
  }
103
104
  if (isFloat32VecInstance(lhs) && isMatInstance(rhs)) {
104
105
  return VectorOps.mulVxM[rhs.kind](lhs, rhs); // row-vector-matrix
@@ -107,7 +108,7 @@ function cpuMul(lhs, rhs) {
107
108
  return VectorOps.mulMxV[lhs.kind](lhs, rhs); // matrix-column-vector
108
109
  }
109
110
  if (isMatInstance(lhs) && isMatInstance(rhs)) {
110
- return VectorOps.mulVxV[lhs.kind](lhs, rhs); // matrix multiplication
111
+ return VectorOps.mulMxM[lhs.kind](lhs, rhs); // matrix multiplication
111
112
  }
112
113
  throw new Error('Mul called with invalid arguments.');
113
114
  }
@@ -119,21 +120,7 @@ export const mul = dualImpl({
119
120
  sideEffects: false,
120
121
  });
121
122
  function cpuDiv(lhs, rhs) {
122
- if (typeof lhs === 'number' && typeof rhs === 'number') {
123
- return lhs / rhs;
124
- }
125
- if (typeof lhs === 'number' && isVecInstance(rhs)) {
126
- const schema = vecTypeToConstructor[rhs.kind];
127
- return VectorOps.div[rhs.kind](schema(lhs), rhs);
128
- }
129
- if (isVecInstance(lhs) && typeof rhs === 'number') {
130
- const schema = vecTypeToConstructor[lhs.kind];
131
- return VectorOps.div[lhs.kind](lhs, schema(rhs));
132
- }
133
- if (isVecInstance(lhs) && isVecInstance(rhs)) {
134
- return VectorOps.div[lhs.kind](lhs, rhs);
135
- }
136
- throw new Error('Div called with invalid arguments.');
123
+ return generalizeFn((a, b) => a / b, upCast([lhs, rhs]));
137
124
  }
138
125
  export const div = dualImpl({
139
126
  name: 'div',
@@ -151,33 +138,13 @@ export const mod = dualImpl({
151
138
  name: 'mod',
152
139
  signature: binaryDivSignature,
153
140
  normalImpl: ((a, b) => {
154
- if (typeof a === 'number' && typeof b === 'number') {
155
- return (a % b); // scalar % scalar
156
- }
157
- if (typeof a === 'number' && isVecInstance(b)) {
158
- // scalar % vector
159
- const schema = vecTypeToConstructor[b.kind];
160
- return VectorOps.mod[b.kind](schema(a), b);
161
- }
162
- if (isVecInstance(a) && typeof b === 'number') {
163
- const schema = vecTypeToConstructor[a.kind];
164
- // vector % scalar
165
- return VectorOps.mod[a.kind](a, schema(b));
166
- }
167
- if (isVecInstance(a) && isVecInstance(b)) {
168
- // vector % vector
169
- return VectorOps.mod[a.kind](a, b);
170
- }
171
- throw new Error('Mod called with invalid arguments, expected types: number or vector.');
141
+ return generalizeFn((a, b) => a % b, upCast([a, b]));
172
142
  }),
173
143
  codegenImpl: (ctx, [lhs, rhs]) => ctx.gen.emitBinaryOp(lhs, '%', rhs),
174
144
  sideEffects: false,
175
145
  });
176
146
  function cpuNeg(value) {
177
- if (typeof value === 'number') {
178
- return -value;
179
- }
180
- return VectorOps.neg[value.kind](value);
147
+ return generalizeFn((value) => -value, [value]);
181
148
  }
182
149
  export const neg = dualImpl({
183
150
  name: 'neg',
package/std/texture.js CHANGED
@@ -5,13 +5,16 @@ import { f32, i32, u32 } from "../data/numeric.js";
5
5
  import { vec2u, vec3u, vec4f, vec4i, vec4u } from "../data/vector.js";
6
6
  import { Void, } from "../data/wgslTypes.js";
7
7
  import { getTextureFormatInfo, } from "../core/texture/textureFormats.js";
8
+ function compactSnippetArgs(args) {
9
+ return args.filter((arg) => arg !== undefined);
10
+ }
8
11
  function sampleCpu(_texture, _sampler, _coords, _offsetOrArrayIndex, _maybeOffset) {
9
12
  throw new MissingCpuImplError('Texture sampling relies on GPU resources and cannot be executed outside of a draw call');
10
13
  }
11
14
  export const textureSample = dualImpl({
12
15
  name: 'textureSample',
13
16
  normalImpl: sampleCpu,
14
- codegenImpl: (_ctx, args) => stitch `textureSample(${args})`,
17
+ codegenImpl: (ctx, args) => ctx.gen.emitCall('textureSample', [], compactSnippetArgs(args)),
15
18
  signature: (...args) => {
16
19
  const isDepth = args[0].type.startsWith('texture_depth');
17
20
  return {
@@ -27,7 +30,7 @@ function sampleBiasCpu(_texture, _sampler, _coords, _biasOrArrayIndex, _biasOrOf
27
30
  export const textureSampleBias = dualImpl({
28
31
  name: 'textureSampleBias',
29
32
  normalImpl: sampleBiasCpu,
30
- codegenImpl: (_ctx, args) => stitch `textureSampleBias(${args})`,
33
+ codegenImpl: (ctx, args) => ctx.gen.emitCall('textureSampleBias', [], compactSnippetArgs(args)),
31
34
  signature: (...args) => ({
32
35
  argTypes: args,
33
36
  returnType: vec4f,
@@ -40,7 +43,7 @@ function sampleLevelCpu(_texture, _sampler, _coords, _level, _offsetOrArrayIndex
40
43
  export const textureSampleLevel = dualImpl({
41
44
  name: 'textureSampleLevel',
42
45
  normalImpl: sampleLevelCpu,
43
- codegenImpl: (_ctx, args) => stitch `textureSampleLevel(${args})`,
46
+ codegenImpl: (ctx, args) => ctx.gen.emitCall('textureSampleLevel', [], compactSnippetArgs(args)),
44
47
  signature: (...args) => {
45
48
  const isDepth = args[0].type.startsWith('texture_depth');
46
49
  return {
@@ -56,7 +59,7 @@ function textureLoadCpu(_texture, _coords, _levelOrArrayIndex) {
56
59
  export const textureLoad = dualImpl({
57
60
  name: 'textureLoad',
58
61
  normalImpl: textureLoadCpu,
59
- codegenImpl: (_ctx, args) => stitch `textureLoad(${args})`,
62
+ codegenImpl: (ctx, args) => ctx.gen.emitCall('textureLoad', [], compactSnippetArgs(args)),
60
63
  signature: (...args) => {
61
64
  const texture = args[0];
62
65
  if (isWgslTexture(texture)) {
@@ -104,7 +107,7 @@ function textureDimensionsCpu(_texture, _level) {
104
107
  export const textureDimensions = dualImpl({
105
108
  name: 'textureDimensions',
106
109
  normalImpl: textureDimensionsCpu,
107
- codegenImpl: (_ctx, args) => stitch `textureDimensions(${args})`,
110
+ codegenImpl: (ctx, args) => ctx.gen.emitCall('textureDimensions', [], compactSnippetArgs(args)),
108
111
  signature: (...args) => {
109
112
  const dim = args[0].dimension;
110
113
  if (dim === '1d') {
package/tgpuLogger.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- declare const warningTypes: readonly ["deprecated", "suspicious", "fallback", "precision-loss", "implicit-conversion", "webgpu-feature-missing", "webgpu-limits-exceeded", "locations-mismatched", "log-limit-exceeded", "external-omitted"];
1
+ declare const warningTypes: readonly ["deprecated", "suspicious", "fallback", "precision-loss", "implicit-conversion", "webgpu-feature-missing", "webgpu-limits-exceeded", "locations-mismatched", "log-limit-exceeded", "external-omitted", "uniform-schema-misaligned"];
2
2
  type WarningType = (typeof warningTypes)[number];
3
3
  interface Logger {
4
4
  warn(type: WarningType, ...args: unknown[]): void;
package/tgpuLogger.js CHANGED
@@ -10,6 +10,7 @@ const warningTypes = [
10
10
  'locations-mismatched',
11
11
  'log-limit-exceeded',
12
12
  'external-omitted',
13
+ 'uniform-schema-misaligned',
13
14
  ];
14
15
  export class TgpuLogger {
15
16
  #initialEnabledWarnings;
@@ -699,8 +699,9 @@ export class WgslGenerator {
699
699
  elemType = concretize(values[0]?.dataType);
700
700
  }
701
701
  const arrayType = arrayOf(elemType, values.length);
702
+ const allConstant = values.every((value) => value.origin === 'constant');
702
703
  return snip(new ArrayExpression(arrayType, values), arrayType,
703
- /* origin */ 'runtime', values.some((v) => v.possibleSideEffects));
704
+ /* origin */ allConstant ? 'constant' : 'runtime', values.some((v) => v.possibleSideEffects));
704
705
  }
705
706
  if (expression[0] === NODE.conditionalExpr) {
706
707
  // ternary operator
@@ -1,2 +0,0 @@
1
- import type { TgpuBindGroupLayout } from '../../tgpuBindGroupLayout.ts';
2
- export declare function warnIfOverflow(layouts: TgpuBindGroupLayout[], limits: GPUSupportedLimits): void;
@@ -1,16 +0,0 @@
1
- import { logger } from "../../tgpuLogger.js";
2
- export function warnIfOverflow(layouts, limits) {
3
- const entries = Object.values(layouts)
4
- .flatMap((layout) => Object.values(layout.entries))
5
- .filter((entry) => entry !== null);
6
- const uniform = entries.filter((entry) => 'uniform' in entry).length;
7
- const storage = entries.filter((entry) => 'storage' in entry).length;
8
- if (uniform > limits.maxUniformBuffersPerShaderStage) {
9
- logger.warn('webgpu-limits-exceeded', `Total number of uniform buffers (${uniform}) exceeds maxUniformBuffersPerShaderStage (${limits.maxUniformBuffersPerShaderStage}). Consider:
10
- 1. Grouping some of the uniforms into one using 'd.struct',
11
- 2. Increasing the limit when requesting a device or creating a root.`);
12
- }
13
- if (storage > limits.maxStorageBuffersPerShaderStage) {
14
- logger.warn('webgpu-limits-exceeded', `Total number of storage buffers (${storage}) exceeds maxStorageBuffersPerShaderStage (${limits.maxStorageBuffersPerShaderStage}).`);
15
- }
16
- }