Skip to content

Commit 595f101

Browse files
committed
Fix min device limits
1 parent 2afde78 commit 595f101

File tree

2 files changed

+41
-86
lines changed

2 files changed

+41
-86
lines changed

basic-3d-rendering/input-geometry/a-first-vertex-attribute.md

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -139,22 +139,6 @@ And we get nothing more than required, so that if we forget to update the initia
139139
140140
This initial check is done by specifying a non null `requiredLimits` pointer in the device descriptor. I suggest that we create a method `GetRequiredLimits(Adapter adapter)` dedicated to setting our app requirements:
141141
142-
````{tab} With webgpu.hpp
143-
```{lit} C++, Build device descriptor (append)
144-
// Before adapter.requestDevice(deviceDesc)
145-
RequiredLimits requiredLimits = GetRequiredLimits(adapter);
146-
deviceDesc.requiredLimits = &requiredLimits;
147-
```
148-
````
149-
150-
````{tab} Vanilla webgpu.h
151-
```{lit} C++, Build device descriptor (append, for tangle root "Vanilla")
152-
// Before requestDeviceSync(adapter, &deviceDesc)
153-
WGPURequiredLimits requiredLimits = GetRequiredLimits(adapter);
154-
deviceDesc.requiredLimits = &requiredLimits;
155-
```
156-
````
157-
158142
````{tab} With webgpu.hpp
159143
```{lit} C++, Private methods (append)
160144
// In Application class
@@ -171,9 +155,23 @@ private:
171155
```
172156
````
173157

174-
```{note}
175-
We do not really need the adapter to determine the required limits in our case, but I pass it as an argument because it **can become useful** in a scenario where a **different quality of device** is requested depending on the **adapter's capabilities**.
158+
We then call this method while building the **device descriptor**:
159+
160+
````{tab} With webgpu.hpp
161+
```{lit} C++, Build device descriptor (append)
162+
// Before adapter.requestDevice(deviceDesc)
163+
RequiredLimits requiredLimits = GetRequiredLimits(adapter);
164+
deviceDesc.requiredLimits = &requiredLimits;
176165
```
166+
````
167+
168+
````{tab} Vanilla webgpu.h
169+
```{lit} C++, Build device descriptor (append, for tangle root "Vanilla")
170+
// Before requestDeviceSync(adapter, &deviceDesc)
171+
WGPURequiredLimits requiredLimits = GetRequiredLimits(adapter);
172+
deviceDesc.requiredLimits = &requiredLimits;
173+
```
174+
````
177175
178176
The required limits follow the **same structure** than the supported limits, we can customize some of them for our vertex attribute:
179177
@@ -195,8 +193,8 @@ RequiredLimits Application::GetRequiredLimits(Adapter adapter) const {
195193
requiredLimits.limits.maxBufferSize = 6 * 2 * sizeof(float);
196194
// Maximum stride between 2 consecutive vertices in the vertex buffer
197195
requiredLimits.limits.maxVertexBufferArrayStride = 2 * sizeof(float);
198-
// This must be set even if we do not use storage buffers for now
199-
requiredLimits.limits.minStorageBufferOffsetAlignment = supportedLimits.limits.minStorageBufferOffsetAlignment;
196+
197+
{{Other device limits}}
200198
201199
return requiredLimits;
202200
}
@@ -232,6 +230,8 @@ WGPURequiredLimits Application::GetRequiredLimits(WGPUAdapter adapter) const {
232230
// Maximum stride between 2 consecutive vertices in the vertex buffer
233231
requiredLimits.limits.maxVertexBufferArrayStride = 2 * sizeof(float);
234232

233+
{{Other device limits}}
234+
235235
return requiredLimits;
236236
}
237237
```
@@ -269,14 +269,14 @@ limits.maxComputeWorkgroupsPerDimension = WGPU_LIMIT_U32_UNDEFINED;
269269
```
270270
````
271271
272-
```{important}
273-
Notice how I **initialized the required limits** object with `= Default` above. This is a syntactic helper provided by the `webgpu.hpp` wrapper for all structs to prevent us from manually setting default values. In this case it sets all limits to `WGPU_LIMIT_U32_UNDEFINED` or `WGPU_LIMIT_U64_UNDEFINED` to mean that there is no requirement.
274-
```
275-
276272
```{lit} C++, Application implementation (hidden, append, also for tangle root "Vanilla")
277273
{{GetRequiredLimits method}}
278274
```
279275
276+
```{important}
277+
Notice how I **initialized the required limits** object with `= Default` above. This is a syntactic helper provided by the `webgpu.hpp` wrapper for all structs to prevent us from manually setting default values. In this case it sets all limits to `WGPU_LIMIT_U32_UNDEFINED` or `WGPU_LIMIT_U64_UNDEFINED` to mean that there is no requirement.
278+
```
279+
280280
I now get these more secure supported limits:
281281
282282
```
@@ -286,6 +286,18 @@ device.maxVertexBuffers: 1
286286
287287
I recommend you have a look at all the fields of the `WGPULimits` structure in `webgpu.h` so that you know when to add something to the required limits.
288288
289+
````{note}
290+
There are two limits that may cause issue even if set to `WGPU_LIMIT_U32_UNDEFINED`, namely the one that set **minimums** rather than maximums. The default "undefined" value may not be supported by the adapter, so **in this case only** I suggest we forward values from the **supported limits**:
291+
292+
```{lit} C++, Other device limits (also for tangle root "Vanilla")
293+
// These two limits are different because they are "minimum" limits,
294+
// they are the only ones we are may forward from the adapter's supported
295+
// limits.
296+
requiredLimits.limits.minUniformBufferOffsetAlignment = supportedLimits.limits.minUniformBufferOffsetAlignment;
297+
requiredLimits.limits.minStorageBufferOffsetAlignment = supportedLimits.limits.minStorageBufferOffsetAlignment;
298+
```
299+
````
300+
289301
### Default capabilities
290302

291303
The official default capabilities can be found in [the specification](https://www.w3.org/TR/webgpu/#limit-default). This also mentions that:

basic-3d-rendering/input-geometry/multiple-attributes.md

Lines changed: 5 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -165,68 +165,11 @@ return vec4f(in.color, 1.0); // use the interpolated color coming from the verte
165165

166166
There is a **limit on the number of components** that can be forwarded from vertex to fragment shader. In our case, we ask for 3 (float) components:
167167

168-
```{lit} C++, List required limits (hidden, also for tangle root "Vanilla")
169-
// NB: In this auto-generated ("tangled") source code, updates to limits get
170-
// appended at the end of this block, so pay attention to the last line that
171-
// affects a given limit field.
172-
173-
// We use at most 1 vertex attribute for now
174-
requiredLimits.limits.maxVertexAttributes = 1;
175-
// We should also tell that we use 1 vertex buffers
176-
requiredLimits.limits.maxVertexBuffers = 1;
177-
// Maximum size of a buffer is 6 vertices of 2 float each
178-
requiredLimits.limits.maxBufferSize = 6 * 2 * sizeof(float);
179-
// Maximum stride between 2 consecutive vertices in the vertex buffer
180-
requiredLimits.limits.maxVertexBufferArrayStride = 2 * sizeof(float);
181-
// This must be set even if we do not use storage buffers for now
182-
requiredLimits.limits.minStorageBufferOffsetAlignment = supportedLimits.limits.minStorageBufferOffsetAlignment;
183-
```
184-
185-
```{lit} C++, List required limits (append, also for tangle root "Vanilla")
168+
```{lit} C++, Other device limits (append, also for tangle root "Vanilla")
186169
// There is a maximum of 3 float forwarded from vertex to fragment shader
187170
requiredLimits.limits.maxInterStageShaderComponents = 3;
188171
```
189172

190-
```{lit} C++, GetRequiredLimits method (hidden, replace)
191-
RequiredLimits Application::GetRequiredLimits(Adapter adapter) const {
192-
// Get adapter supported limits, in case we need them
193-
SupportedLimits supportedLimits;
194-
adapter.getLimits(&supportedLimits);
195-
196-
// Don't forget to = Default
197-
RequiredLimits requiredLimits = Default;
198-
199-
{{List required limits}}
200-
201-
return requiredLimits;
202-
}
203-
```
204-
205-
```{lit} C++, GetRequiredLimits method (hidden, replace, for tangle root "Vanilla")
206-
// If you do not use webgpu.hpp, I suggest you create a function to init the
207-
// WGPULimits structure:
208-
void setDefault(WGPULimits &limits) {
209-
limits.maxTextureDimension1D = WGPU_LIMIT_U32_UNDEFINED;
210-
limits.maxTextureDimension2D = WGPU_LIMIT_U32_UNDEFINED;
211-
limits.maxTextureDimension3D = WGPU_LIMIT_U32_UNDEFINED;
212-
{{Set everything to WGPU_LIMIT_U32_UNDEFINED or WGPU_LIMIT_U64_UNDEFINED to mean no limit}}
213-
}
214-
215-
WGPURequiredLimits Application::GetRequiredLimits(WGPUAdapter adapter) const {
216-
// Get adapter supported limits, in case we need them
217-
WGPUSupportedLimits supportedLimits;
218-
supportedLimits.nextInChain = nullptr;
219-
wgpuAdapterGetLimits(adapter, &supportedLimits);
220-
221-
WGPURequiredLimits requiredLimits{};
222-
setDefault(requiredLimits.limits);
223-
224-
{{List required limits}}
225-
226-
return requiredLimits;
227-
}
228-
```
229-
230173
Vertex Buffer Layout
231174
--------------------
232175

@@ -237,7 +180,7 @@ There are **different ways** of feeding multiple attributes to the vertex fetch
237180
````{admonition} Device limits
238181
Before anything, do not forget to **increase the vertex attribute limit** of your device:
239182
240-
```{lit} C++, List required limits (append, also for tangle root "Vanilla")
183+
```{lit} C++, Other device limits (append, also for tangle root "Vanilla")
241184
requiredLimits.limits.maxVertexAttributes = 2;
242185
// ^ This was 1
243186
```
@@ -337,7 +280,7 @@ vertexBufferLayout.stepMode = WGPUVertexStepMode_Vertex;
337280
````{admonition} Device limits
338281
We thus need to update the **buffer size and stride limits**:
339282
340-
```{lit} C++, List required limits (append, also for tangle root "Vanilla")
283+
```{lit} C++, Other device limits (append, also for tangle root "Vanilla")
341284
requiredLimits.limits.maxBufferSize = 6 * 5 * sizeof(float);
342285
requiredLimits.limits.maxVertexBufferArrayStride = 5 * sizeof(float);
343286
```
@@ -417,7 +360,7 @@ Another possible data layout is to have **two different buffers** for the two at
417360
````{admonition} Device limits
418361
Make sure to change the device limit to support this:
419362
420-
```{lit} C++, List required limits (append, also for tangle root "Vanilla")
363+
```{lit} C++, Other device limits (append, also for tangle root "Vanilla")
421364
requiredLimits.limits.maxVertexBuffers = 2;
422365
```
423366
````
@@ -454,7 +397,7 @@ assert(vertexCount == static_cast<uint32_t>(colorData.size() / 3));
454397
````{note}
455398
This time, the maximum buffer size/stride can be lower:
456399
457-
```{lit} C++, List required limits (append, also for tangle root "Vanilla")
400+
```{lit} C++, Other device limits (append, also for tangle root "Vanilla")
458401
requiredLimits.limits.maxBufferSize = 6 * 3 * sizeof(float);
459402
requiredLimits.limits.maxVertexBufferArrayStride = 3 * sizeof(float);
460403
```

0 commit comments

Comments
 (0)