Skip to content

Commit 2e4fd58

Browse files
committed
[core] Document validation::Interface and associated internals.
In `wgpu_core::validation`, add documentation for `Interface` and `EntryPoint`, and document some methods. In `wgpu_core::pipeline`, document `ShaderModule::finalize_entry_point_name` and expand on the documentation for the fields of `ProgrammableStageDescriptor`. In `wgpu_types::features`, fix a `cargo doc` warning.
1 parent faac3bb commit 2e4fd58

3 files changed

Lines changed: 154 additions & 13 deletions

File tree

wgpu-core/src/pipeline.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,25 @@ impl ShaderModule {
125125
})
126126
}
127127

128+
/// Select an entry point name, given an optional name and a shader stage.
129+
///
130+
/// This function takes care of turning the `Option<&str>`
131+
/// [`ProgrammableStageDescriptor::entry_point`][ep] into a specific name.
132+
///
133+
/// For non-passthrough shaders, if `entry_point` is `Some`, then return it
134+
/// as a `String`. Otherwise, return the name of the unique entry point in
135+
/// `self`'s module for `stage`; if there is not exactly one such entry
136+
/// point, return an error.
137+
///
138+
/// The non-passthrough case counts on `Interface::check_stage` to verify
139+
/// that an entry point with the given name actually exists.
140+
///
141+
/// For passthrough shaders, if `entry_point` is `Some`, verify that an
142+
/// entry point by that name exists (returning an error if not), and return
143+
/// it as a `String`. Otherwise, if `entry_point` is `None`, then check that
144+
/// this module has exactly one entry point, and return its name.
145+
///
146+
/// [ep]: crate::pipeline::ProgrammableStageDescriptor::entry_point
128147
pub(crate) fn finalize_entry_point_name(
129148
&self,
130149
stage: naga::ShaderStage,
@@ -223,25 +242,32 @@ impl WebGpuError for CreateShaderModuleError {
223242
pub struct ProgrammableStageDescriptor<'a, SM = ShaderModuleId> {
224243
/// The compiled shader module for this stage.
225244
pub module: SM,
226-
/// The name of the entry point in the compiled shader. The name is selected using the
227-
/// following logic:
245+
246+
/// The name of the entry point in `module` that this stage should use.
247+
///
248+
/// - If this is `Some(name)`, `module` must contain an entry point with the
249+
/// given name.
228250
///
229-
/// * If `Some(name)` is specified, there must be a function with this name in the shader.
230-
/// * If a single entry point associated with this stage must be in the shader, then proceed as
231-
/// if `Some(…)` was specified with that entry point's name.
251+
/// - If this is `None`, `module` must have only one entry point for this
252+
/// stage; we use that one.
232253
pub entry_point: Option<Cow<'a, str>>,
233-
/// Specifies the values of pipeline-overridable constants in the shader module.
254+
255+
/// Values for pipeline-overridable constants in `module` that this stage
256+
/// should use.
234257
///
235258
/// If an `@id` attribute was specified on the declaration,
236259
/// the key must be the pipeline constant ID as a decimal ASCII number; if not,
237260
/// the key must be the constant's identifier name.
238261
///
239262
/// The value may represent any of WGSL's concrete scalar types.
240263
pub constants: naga::back::PipelineConstants,
241-
/// Whether workgroup scoped memory will be initialized with zero values for this stage.
264+
265+
/// Whether variables in the workgroup address space will be initialized
266+
/// with zero values for this stage.
242267
///
243-
/// This is required by the WebGPU spec, but may have overhead which can be avoided
244-
/// for cross-platform applications
268+
/// The WebGPU spec requires variables in the workgroup address space to be
269+
/// zeroed. However, initialization does impose some overhead, and
270+
/// non-browser applications may not need it.
245271
pub zero_initialize_workgroup_memory: bool,
246272
}
247273

wgpu-core/src/validation.rs

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,16 +292,65 @@ struct EntryPointMeshInfo {
292292
primitive_topology: wgt::PrimitiveTopology,
293293
}
294294

295+
/// The [shader interface][si] of an entry point in a [`naga::Module`].
296+
///
297+
/// [si]: https://www.w3.org/TR/WGSL/#shader-interface
295298
#[derive(Debug, Default)]
296299
struct EntryPoint {
300+
/// The builtin and user-defined values passed to the entry point.
301+
///
302+
/// In WGSL, these can be either passed directly as arguments or
303+
/// gathered up in structs that are passed; here, they are all
304+
/// flattened out.
297305
inputs: Vec<Varying>,
306+
307+
/// The builtin and user-defined values returned by the entry point.
308+
///
309+
/// In WGSL, a function either returns a single varying directly,
310+
/// or returns a struct of varyings; here, they are all flattened
311+
/// out.
312+
///
313+
/// For mesh shaders, this also includes the vertex and primitive outputs.
298314
outputs: Vec<Varying>,
315+
316+
/// This entry point's [resource interface][ri].
317+
///
318+
/// This lists all the bound resources (that is, global variables with
319+
/// `@group` and `@binding` attributes) that this entry point statically
320+
/// uses.
321+
///
322+
/// Handles here refer to elements of [`Interface::resources`].
323+
///
324+
/// [ri]: https://www.w3.org/TR/WGSL/#resource-interface
299325
resources: Vec<naga::Handle<Resource>>,
326+
327+
/// Pairs of (texture, sampler) handles that this entry point uses
328+
/// together.
329+
///
330+
/// This is the same information that Naga provides in
331+
/// [`naga::valid::FunctionInfo::sampling_set`] (used for generating GLSL),
332+
/// but adjusted to use handles referring to [`Interface::resources`].
300333
sampling_pairs: FastHashSet<(naga::Handle<Resource>, naga::Handle<Resource>)>,
334+
335+
/// This entry point's workgroup size, if it is a [compute-like] shader
336+
/// (`compute`, `task`, or `mesh`).
337+
///
338+
/// For non-compute-like entry points, this is `[0, 0, 0]`.
339+
///
340+
/// [compute-like]: naga::ShaderStage::compute_like
301341
workgroup_size: [u32; 3],
342+
343+
/// Indicates that the entry point uses dual source blending.
302344
dual_source_blending: bool,
345+
346+
/// For task shaders and mesh shaders, the size of the task payload global
347+
/// they use to communicate.
303348
task_payload_size: Option<u32>,
349+
350+
/// Additional information for mesh shader entry points.
304351
mesh_info: Option<EntryPointMeshInfo>,
352+
353+
/// Size of the immediate data, and which slots this entry point uses.
305354
immediate_usage: naga::valid::ImmediateUsage,
306355
}
307356

@@ -317,10 +366,35 @@ impl hashbrown::Equivalent<EntryPointKey> for EntryPointKeyRef<'_> {
317366
}
318367
}
319368

369+
/// A summary of the [shader interfaces][si] of the entry points in a [`naga::Module`].
370+
///
371+
/// [si]: https://www.w3.org/TR/WGSL/#shader-interface
320372
#[derive(Debug)]
321373
pub struct Interface {
374+
/// A clone of the limits of the [`Device`] this module was created from.
375+
///
376+
/// [`Interface::check_stage`] consults this for workgroup size checks.
377+
///
378+
/// [`Device`]: crate::device::Device
322379
limits: wgt::Limits,
380+
381+
/// All the resources the module cites as global variables.
382+
///
383+
/// This lists all the module's bound resources: global variables with
384+
/// `@group` and `@binding` attributes.
385+
///
386+
/// Fields of [`EntryPoint`] like [`resources`] and [`sampling_pairs`] refer to
387+
/// elements in this arena by [`naga::Handle`].
388+
///
389+
/// [`resources`]: EntryPoint::resources
390+
/// [`sampling_pairs`]: EntryPoint::sampling_pairs
323391
resources: naga::Arena<Resource>,
392+
393+
/// The shader interface of each [`naga::EntryPoint`] in the module.
394+
///
395+
/// This table is keyed by (stage, name) pairs: [`naga::Module`]s are
396+
/// allowed to contain multiple entry points with the same name, as long as
397+
/// they are for different shader stages.
324398
entry_points: FastHashMap<EntryPointKey, EntryPoint>,
325399
}
326400

@@ -1115,6 +1189,19 @@ pub struct StageIo {
11151189
}
11161190

11171191
impl Interface {
1192+
/// Build some entry point's list of inputs or outputs.
1193+
///
1194+
/// Given `ty` and `binding` that describe an entry point's argument or
1195+
/// return value, figure out which builtins or locations are involved and
1196+
/// add them to `list`, which is either [`EntryPoint::inputs`] or
1197+
/// [`EntryPoint::outputs`].
1198+
///
1199+
/// - If `ty` is a struct type, visit its members to find
1200+
/// individual bindings, and add them to `list`.
1201+
///
1202+
/// - Otherwise, `binding` must be `Some(b)` where `b` describes a
1203+
/// binding's builtin or location, and `ty` gives its type. Add
1204+
/// this binding to `list`.
11181205
fn populate(
11191206
list: &mut Vec<Varying>,
11201207
binding: Option<&naga::Binding>,
@@ -1252,6 +1339,11 @@ impl Interface {
12521339
list.push(varying);
12531340
}
12541341

1342+
/// Construct an [`Interface`] value describing `module`.
1343+
///
1344+
/// The `info` argument must be the results from validating `module`, and
1345+
/// `limits` must be the limits for the device that we will use to create
1346+
/// this shader module.
12551347
pub fn new(module: &naga::Module, info: &naga::valid::ModuleInfo, limits: wgt::Limits) -> Self {
12561348
let mut resources = naga::Arena::new();
12571349
let mut resource_mapping = FastHashMap::default();
@@ -1404,6 +1496,11 @@ impl Interface {
14041496
.unwrap_or_default()
14051497
}
14061498

1499+
/// Select an entry point name, given an optional name and a shader stage.
1500+
///
1501+
/// See [`ShaderModule::finalize_entry_point_name`] for details.
1502+
///
1503+
/// [`ShaderModule::finalize_entry_point_name`]: crate::pipeline::ShaderModule::finalize_entry_point_name
14071504
pub fn finalize_entry_point_name(
14081505
&self,
14091506
stage: naga::ShaderStage,
@@ -1427,8 +1524,27 @@ impl Interface {
14271524
})
14281525
}
14291526

1430-
/// Among other things, this implements some validation logic defined by the WebGPU spec. at
1431-
/// <https://www.w3.org/TR/webgpu/#abstract-opdef-validating-inter-stage-interfaces>.
1527+
/// Analyze and validate an entry point for use as a given shader stage.
1528+
///
1529+
/// Validate the entry point named `entry_point_name` for use in
1530+
/// `shader_stage`:
1531+
///
1532+
/// - Apply the WebGPU specification's [validating inter-stage interfaces]
1533+
/// algorithm.
1534+
///
1535+
/// - Enforce workgroup size limits.
1536+
///
1537+
/// - Check bind group layouts, and fill in derived bind group layouts.
1538+
///
1539+
/// - Compute the minimum binding sizes, given the shader's resource
1540+
/// interface.
1541+
///
1542+
/// - Check the compatibility between textures and samplers.
1543+
///
1544+
/// Given `inputs`, describing this stage's inputs, return a [`StageIo`]
1545+
/// describing its outputs.
1546+
///
1547+
/// [validating inter-stage interfaces]: https://www.w3.org/TR/webgpu/#abstract-opdef-validating-inter-stage-interfaces
14321548
pub fn check_stage(
14331549
&self,
14341550
layouts: &mut BindingLayoutSource,

wgpu-types/src/features.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
//! The `wgpu` Rust API always uses the `Features` bit flag type to represent a
77
//! set of features. However, the WebGPU-defined JavaScript API uses
88
//! `kebab-case` feature name strings, so some utilities are provided for
9-
//! working with those names. See [`Features::as_str`] and [`<Features as
10-
//! FromStr>::from_str`].
9+
//! working with those names. See [`Features::as_str`] and [`Features::from_str`].
1110
//!
1211
//! The [`bitflags`] crate names flags by stringifying the
1312
//! `SCREAMING_SNAKE_CASE` identifier. These names are returned by

0 commit comments

Comments
 (0)