Skip to content

Commit 60a42a0

Browse files
committed
Implement better limit checking.
Implement a "quitIfLimitNotMet()" helper that tests for the existence of a limit in adapter.limits, checks that it meets a certain value, and errors if not. If successful, it will add the limit to a GPURequiredLimits object.
1 parent 02db960 commit 60a42a0

File tree

10 files changed

+55
-44
lines changed

10 files changed

+55
-44
lines changed

sample/a-buffer/main.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { mat4, vec3 } from 'wgpu-matrix';
22
import { GUI } from 'dat.gui';
33

4-
import { quitIfWebGPUNotAvailable } from '../util';
4+
import { quitIfWebGPUNotAvailable, quitIfLimitLessThan } from '../util';
55
import { mesh } from '../../meshes/teapot';
66

77
import opaqueWGSL from './opaque.wgsl';
@@ -16,10 +16,8 @@ const canvas = document.querySelector('canvas') as HTMLCanvasElement;
1616
const adapter = await navigator.gpu?.requestAdapter({
1717
featureLevel: 'compatibility',
1818
});
19-
let limits: Record<string, GPUSize32>;
20-
if ('maxStorageBuffersInFragmentStage' in adapter.limits) {
21-
limits = { maxStorageBuffersInFragmentStage: 2 };
22-
}
19+
const limits: Record<string, GPUSize32> = {};
20+
quitIfLimitLessThan(adapter, 'maxStorageBuffersInFragmentStage', 2, limits);
2321
const device = await adapter?.requestDevice({
2422
requiredLimits: limits,
2523
});

sample/bitonicSort/utils.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import type { GUI } from 'dat.gui';
22
import fullscreenTexturedQuad from '../../shaders/fullscreenTexturedQuad.wgsl';
3-
import { quitIfAdapterNotAvailable, quitIfWebGPUNotAvailable } from '../util';
3+
import {
4+
quitIfAdapterNotAvailable,
5+
quitIfWebGPUNotAvailable,
6+
quitIfLimitLessThan,
7+
} from '../util';
48

59
type BindGroupBindingLayout =
610
| GPUBufferBindingLayout
@@ -119,13 +123,11 @@ export const SampleInitFactoryWebGPU = async (
119123

120124
const timestampQueryAvailable = adapter.features.has('timestamp-query');
121125
let features = [];
122-
let limits: Record<string, GPUSize32>;
126+
const limits: Record<string, GPUSize32> = {};
123127
if (timestampQueryAvailable) {
124128
features = ['timestamp-query'];
125129
}
126-
if ('maxStorageBuffersInFragmentStage' in adapter.limits) {
127-
limits = { maxStorageBuffersInFragmentStage: 1 };
128-
}
130+
quitIfLimitLessThan(adapter, 'maxStorageBuffersInFragmentStage', 1, limits);
129131
const device = await adapter.requestDevice({
130132
requiredFeatures: features,
131133
requiredLimits: limits,

sample/cornell/main.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ const canvas = document.querySelector('canvas') as HTMLCanvasElement;
1212
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
1313
const requiredFeatures: GPUFeatureName[] =
1414
presentationFormat === 'bgra8unorm' ? ['bgra8unorm-storage'] : [];
15-
const adapter = await navigator.gpu?.requestAdapter();
15+
const adapter = await navigator.gpu?.requestAdapter({
16+
featureLevel: 'compatibility',
17+
});
1618
quitIfAdapterNotAvailable(adapter);
1719

1820
for (const feature of requiredFeatures) {
@@ -22,7 +24,13 @@ for (const feature of requiredFeatures) {
2224
);
2325
}
2426
}
25-
const device = await adapter?.requestDevice({ requiredFeatures });
27+
const requiredLimits: Record<string, GPUSize32> = {};
28+
requiredLimits['maxComputeWorkgroupSizeX'] = 256;
29+
requiredLimits['maxComputeInvocationsPerWorkgroup'] = 256;
30+
const device = await adapter?.requestDevice({
31+
requiredFeatures,
32+
requiredLimits
33+
});
2634
quitIfWebGPUNotAvailable(adapter, device);
2735

2836
const params: {

sample/cornell/rasterizer.wgsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct VertexOut {
1616
@builtin(position) position : vec4f,
1717
@location(0) uv : vec2f,
1818
@location(1) emissive : vec3f,
19-
@interpolate(flat)
19+
@interpolate(flat, either)
2020
@location(2) quad : u32,
2121
}
2222

sample/deferredRendering/main.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import fragmentWriteGBuffers from './fragmentWriteGBuffers.wgsl';
88
import vertexTextureQuad from './vertexTextureQuad.wgsl';
99
import fragmentGBuffersDebugView from './fragmentGBuffersDebugView.wgsl';
1010
import fragmentDeferredRendering from './fragmentDeferredRendering.wgsl';
11-
import { quitIfWebGPUNotAvailable } from '../util';
11+
import { quitIfWebGPUNotAvailable, quitIfLimitLessThan } from '../util';
1212

1313
const kMaxNumLights = 1024;
1414
const lightExtentMin = vec3.fromValues(-50, -30, -50);
@@ -18,10 +18,8 @@ const canvas = document.querySelector('canvas') as HTMLCanvasElement;
1818
const adapter = await navigator.gpu?.requestAdapter({
1919
featureLevel: 'compatibility',
2020
});
21-
let limits: Record<string, GPUSize32>;
22-
if ('maxStorageBuffersInFragmentStage' in adapter.limits) {
23-
limits = { maxStorageBuffersInFragmentStage: 1 };
24-
}
21+
const limits: Record<string, GPUSize32> = {};
22+
quitIfLimitLessThan(adapter, 'maxStorageBuffersInFragmentStage', 1, limits);
2523
const device = await adapter?.requestDevice({
2624
requiredLimits: limits,
2725
});

sample/samplerParameters/main.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { GUI } from 'dat.gui';
33

44
import texturedSquareWGSL from './texturedSquare.wgsl';
55
import showTextureWGSL from './showTexture.wgsl';
6-
import { quitIfWebGPUNotAvailable } from '../util';
6+
import { quitIfWebGPUNotAvailable, quitIfLimitLessThan } from '../util';
77

88
const kMatrices: Readonly<Float32Array> = new Float32Array([
99
// Row 1: Scale by 2
@@ -31,10 +31,8 @@ const canvas = document.querySelector('canvas') as HTMLCanvasElement;
3131
const adapter = await navigator.gpu?.requestAdapter({
3232
featureLevel: 'compatibility',
3333
});
34-
let limits: Record<string, GPUSize32>;
35-
if ('maxStorageBuffersInVertexStage' in adapter.limits) {
36-
limits = { maxStorageBuffersInVertexStage: 1 };
37-
}
34+
const limits: Record<string, GPUSize32> = {};
35+
quitIfLimitLessThan(adapter, 'maxStorageBuffersInVertexStage', 1, limits);
3836
const device = await adapter?.requestDevice({
3937
requiredLimits: limits,
4038
});

sample/skinnedMesh/main.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
createSkinnedGridRenderPipeline,
1010
} from './gridUtils';
1111
import { gridIndices } from './gridData';
12-
import { quitIfWebGPUNotAvailable } from '../util';
12+
import { quitIfWebGPUNotAvailable, quitIfLimitLessThan } from '../util';
1313

1414
const MAT4X4_BYTES = 64;
1515

@@ -98,10 +98,8 @@ const canvas = document.querySelector('canvas') as HTMLCanvasElement;
9898
const adapter = await navigator.gpu?.requestAdapter({
9999
featureLevel: 'compatibility',
100100
});
101-
let limits: Record<string, GPUSize32>;
102-
if ('maxStorageBuffersInVertexStage' in adapter.limits) {
103-
limits = { maxStorageBuffersInVertexStage: 2 };
104-
}
101+
const limits: Record<string, GPUSize32> = {};
102+
quitIfLimitLessThan(adapter, 'maxStorageBuffersInVertexStage', 2, limits);
105103
const device = await adapter?.requestDevice({
106104
requiredLimits: limits,
107105
});

sample/textRenderingMsdf/main.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,15 @@ import { MsdfTextRenderer } from './msdfText';
1111

1212
import basicVertWGSL from '../../shaders/basic.vert.wgsl';
1313
import vertexPositionColorWGSL from '../../shaders/vertexPositionColor.frag.wgsl';
14-
import { quitIfWebGPUNotAvailable } from '../util';
14+
import { quitIfWebGPUNotAvailable, quitIfLimitLessThan } from '../util';
1515

1616
const canvas = document.querySelector('canvas') as HTMLCanvasElement;
1717
const adapter = await navigator.gpu?.requestAdapter({
1818
featureLevel: 'compatibility',
1919
});
20-
let limits: Record<string, GPUSize32>;
21-
if (
22-
'maxStorageBuffersInFragmentStage' in adapter.limits &&
23-
'maxStorageBuffersInVertexStage' in adapter.limits
24-
) {
25-
limits = {
26-
maxStorageBuffersInFragmentStage: 1,
27-
maxStorageBuffersInVertexStage: 2,
28-
};
29-
}
20+
const limits: Record<string, GPUSize32> = {};
21+
quitIfLimitLessThan(adapter, 'maxStorageBuffersInFragmentStage', 1, limits);
22+
quitIfLimitLessThan(adapter, 'maxStorageBuffersInVertexStage', 2, limits);
3023
const device = await adapter?.requestDevice({
3124
requiredLimits: limits,
3225
});

sample/util.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@ export function quitIfAdapterNotAvailable(
1111
}
1212
}
1313

14+
export function quitIfLimitLessThan(
15+
adapter: GPUAdapter,
16+
limit: string,
17+
requiredValue: number,
18+
limits: Record<string, GPUSize32>
19+
) {
20+
if (limit in adapter.limits) {
21+
const limitKey = limit as keyof GPUSupportedLimits;
22+
const limitValue = adapter.limits[limitKey] as number;
23+
if (limitValue < requiredValue) {
24+
fail(
25+
`This sample can't run on this system. ${limit} is ${limitValue}, and this sample requires at least ${requiredValue}.`
26+
);
27+
}
28+
limits[limit] = requiredValue;
29+
}
30+
}
31+
1432
/**
1533
* Shows an error dialog if getting a adapter or device wasn't successful,
1634
* or if/when the device is lost or has an uncaptured error.

sample/wireframe/main.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { modelData } from './models';
44
import { randElement, randColor } from './utils';
55
import solidColorLitWGSL from './solidColorLit.wgsl';
66
import wireframeWGSL from './wireframe.wgsl';
7-
import { quitIfWebGPUNotAvailable } from '../util';
7+
import { quitIfWebGPUNotAvailable, quitIfLimitLessThan } from '../util';
88

99
const settings = {
1010
barycentricCoordinatesBased: false,
@@ -64,10 +64,8 @@ function createVertexAndIndexBuffer(
6464
const adapter = await navigator.gpu?.requestAdapter({
6565
featureLevel: 'compatibility',
6666
});
67-
let limits: Record<string, GPUSize32>;
68-
if ('maxStorageBuffersInVertexStage' in adapter.limits) {
69-
limits = { maxStorageBuffersInVertexStage: 2 };
70-
}
67+
const limits: Record<string, GPUSize32> = {};
68+
quitIfLimitLessThan(adapter, 'maxStorageBuffersInVertexStage', 2, limits);
7169
const device = await adapter?.requestDevice({
7270
requiredLimits: limits,
7371
});

0 commit comments

Comments
 (0)