Skip to content

Commit 702c4ef

Browse files
[wgsl] gate primitive_index built-in behind its extension & [glsl-out] require extensions for gl_PrimitiveID if needed (gfx-rs#8879)
1 parent 47ce3cb commit 702c4ef

25 files changed

Lines changed: 456 additions & 103 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ By @cwfitzgerald in [#8999](https://github.com/gfx-rs/wgpu/pull/8999).
6868
- `ir::Block::len`
6969
- Changed passthrough shaders to not require an entry point parameter, so that the same shader module may be used in multiple entry points. Also added support for metallib passthrough. By @inner-daemons in #8886.
7070
- Added support for `insert_debug_marker`, `push_debug_group` and `pop_debug_group` on WebGPU. By @evilpie in [#9017](https://github.com/gfx-rs/wgpu/pull/9017).
71+
- Added support for `enable primitive_index` and `@builtin(primitive_index)` with support on all platforms. By @inner-daemons in #8879.
7172

7273
#### naga
7374

naga/src/back/glsl/features.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ bitflags::bitflags! {
5757
const TEXTURE_ATOMICS = 1 << 25;
5858
/// Image atomics
5959
const SHADER_BARYCENTRICS = 1 << 26;
60+
/// Primitive index builtin
61+
const PRIMITIVE_INDEX = 1 << 27;
6062
}
6163
}
6264

@@ -298,6 +300,18 @@ impl FeaturesManager {
298300
)?;
299301
}
300302

303+
if self.0.contains(Features::PRIMITIVE_INDEX) {
304+
match options.version {
305+
Version::Embedded { version, .. } if version < 320 => {
306+
writeln!(out, "#extension GL_OES_geometry_shader : require")?;
307+
}
308+
Version::Desktop(version) if version < 150 => {
309+
writeln!(out, "#extension GL_ARB_geometry_shader4 : require")?;
310+
}
311+
_ => (),
312+
}
313+
}
314+
301315
Ok(())
302316
}
303317
}
@@ -616,6 +630,9 @@ impl<W> Writer<'_, W> {
616630
crate::BuiltIn::Barycentric { .. } => {
617631
self.features.request(Features::SHADER_BARYCENTRICS)
618632
}
633+
crate::BuiltIn::PrimitiveIndex => {
634+
self.features.request(Features::PRIMITIVE_INDEX)
635+
}
619636
_ => {}
620637
},
621638
Binding::Location {

naga/src/back/spv/writer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,6 +3083,7 @@ impl Writer {
30833083
Bi::PointCoord => BuiltIn::PointCoord,
30843084
Bi::FrontFacing => BuiltIn::FrontFacing,
30853085
Bi::PrimitiveIndex => {
3086+
// Geometry shader capability is required for primitive index
30863087
self.require_any(
30873088
"`primitive_index` built-in",
30883089
&[spirv::Capability::Geometry],

naga/src/back/wgsl/writer.rs

Lines changed: 73 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -278,96 +278,120 @@ impl<W: Write> Writer<W> {
278278
/// Helper method which writes all the `enable` declarations
279279
/// needed for a module.
280280
fn write_enable_declarations(&mut self, module: &Module) -> BackendResult {
281-
let mut needs_f16 = false;
282-
let mut needs_dual_source_blending = false;
283-
let mut needs_clip_distances = false;
284-
let mut needs_mesh_shaders = false;
285-
let mut needs_cooperative_matrix = false;
281+
#[derive(Default)]
282+
struct RequiredEnabled {
283+
f16: bool,
284+
dual_source_blending: bool,
285+
clip_distances: bool,
286+
mesh_shaders: bool,
287+
primitive_index: bool,
288+
cooperative_matrix: bool,
289+
}
290+
let mut needed = RequiredEnabled::default();
291+
292+
let check_binding = |binding: &crate::Binding, needed: &mut RequiredEnabled| match *binding
293+
{
294+
crate::Binding::Location {
295+
blend_src: Some(_), ..
296+
} => {
297+
needed.dual_source_blending = true;
298+
}
299+
crate::Binding::BuiltIn(crate::BuiltIn::ClipDistance) => {
300+
needed.clip_distances = true;
301+
}
302+
crate::Binding::BuiltIn(crate::BuiltIn::PrimitiveIndex) => {
303+
needed.primitive_index = true;
304+
}
305+
crate::Binding::Location {
306+
per_primitive: true,
307+
..
308+
} => {
309+
needed.mesh_shaders = true;
310+
}
311+
crate::Binding::BuiltIn(
312+
crate::BuiltIn::MeshTaskSize
313+
| crate::BuiltIn::CullPrimitive
314+
| crate::BuiltIn::PointIndex
315+
| crate::BuiltIn::LineIndices
316+
| crate::BuiltIn::TriangleIndices
317+
| crate::BuiltIn::VertexCount
318+
| crate::BuiltIn::Vertices
319+
| crate::BuiltIn::PrimitiveCount
320+
| crate::BuiltIn::Primitives,
321+
) => {
322+
needed.mesh_shaders = true;
323+
}
324+
_ => {}
325+
};
286326

287327
// Determine which `enable` declarations are needed
288328
for (_, ty) in module.types.iter() {
289329
match ty.inner {
290330
TypeInner::Scalar(scalar)
291331
| TypeInner::Vector { scalar, .. }
292332
| TypeInner::Matrix { scalar, .. } => {
293-
needs_f16 |= scalar == crate::Scalar::F16;
333+
needed.f16 |= scalar == crate::Scalar::F16;
294334
}
295335
TypeInner::Struct { ref members, .. } => {
296336
for binding in members.iter().filter_map(|m| m.binding.as_ref()) {
297-
match *binding {
298-
crate::Binding::Location {
299-
blend_src: Some(_), ..
300-
} => {
301-
needs_dual_source_blending = true;
302-
}
303-
crate::Binding::BuiltIn(crate::BuiltIn::ClipDistance) => {
304-
needs_clip_distances = true;
305-
}
306-
crate::Binding::Location {
307-
per_primitive: true,
308-
..
309-
} => {
310-
needs_mesh_shaders = true;
311-
}
312-
crate::Binding::BuiltIn(
313-
crate::BuiltIn::MeshTaskSize
314-
| crate::BuiltIn::CullPrimitive
315-
| crate::BuiltIn::PointIndex
316-
| crate::BuiltIn::LineIndices
317-
| crate::BuiltIn::TriangleIndices
318-
| crate::BuiltIn::VertexCount
319-
| crate::BuiltIn::Vertices
320-
| crate::BuiltIn::PrimitiveCount
321-
| crate::BuiltIn::Primitives,
322-
) => {
323-
needs_mesh_shaders = true;
324-
}
325-
_ => {}
326-
}
337+
check_binding(binding, &mut needed);
327338
}
328339
}
329340
TypeInner::CooperativeMatrix { .. } => {
330-
needs_cooperative_matrix = true;
341+
needed.cooperative_matrix = true;
331342
}
332343
_ => {}
333344
}
334345
}
335346

336-
if module
337-
.entry_points
338-
.iter()
339-
.any(|ep| matches!(ep.stage, ShaderStage::Mesh | ShaderStage::Task))
340-
{
341-
needs_mesh_shaders = true;
347+
for ep in &module.entry_points {
348+
if matches!(ep.stage, ShaderStage::Mesh | ShaderStage::Task) {
349+
needed.mesh_shaders = true;
350+
}
351+
if let Some(res) = ep.function.result.as_ref().and_then(|a| a.binding.as_ref()) {
352+
check_binding(res, &mut needed);
353+
}
354+
for arg in ep
355+
.function
356+
.arguments
357+
.iter()
358+
.filter_map(|a| a.binding.as_ref())
359+
{
360+
check_binding(arg, &mut needed);
361+
}
342362
}
343363

344364
if module
345365
.global_variables
346366
.iter()
347367
.any(|gv| gv.1.space == crate::AddressSpace::TaskPayload)
348368
{
349-
needs_mesh_shaders = true;
369+
needed.mesh_shaders = true;
350370
}
351371

352372
// Write required declarations
353373
let mut any_written = false;
354-
if needs_f16 {
374+
if needed.f16 {
355375
writeln!(self.out, "enable f16;")?;
356376
any_written = true;
357377
}
358-
if needs_dual_source_blending {
378+
if needed.dual_source_blending {
359379
writeln!(self.out, "enable dual_source_blending;")?;
360380
any_written = true;
361381
}
362-
if needs_clip_distances {
382+
if needed.clip_distances {
363383
writeln!(self.out, "enable clip_distances;")?;
364384
any_written = true;
365385
}
366-
if needs_mesh_shaders {
386+
if needed.mesh_shaders {
367387
writeln!(self.out, "enable wgpu_mesh_shader;")?;
368388
any_written = true;
369389
}
370-
if needs_cooperative_matrix {
390+
if needed.primitive_index {
391+
writeln!(self.out, "enable primitive_index;")?;
392+
any_written = true;
393+
}
394+
if needed.cooperative_matrix {
371395
writeln!(self.out, "enable wgpu_cooperative_matrix;")?;
372396
any_written = true;
373397
}

naga/src/front/wgsl/parse/conv.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,8 @@ pub fn map_address_space<'a>(
2121
"immediate" => Ok(crate::AddressSpace::Immediate),
2222
"function" => Ok(crate::AddressSpace::Function),
2323
"task_payload" => {
24-
if enable_extensions.contains(ImplementedEnableExtension::WgpuMeshShader) {
25-
Ok(crate::AddressSpace::TaskPayload)
26-
} else {
27-
Err(Box::new(Error::EnableExtensionNotEnabled {
28-
span,
29-
kind: ImplementedEnableExtension::WgpuMeshShader.into(),
30-
}))
31-
}
24+
enable_extensions.require(ImplementedEnableExtension::WgpuMeshShader, span)?;
25+
Ok(crate::AddressSpace::TaskPayload)
3226
}
3327
"ray_payload" => {
3428
if enable_extensions.contains(ImplementedEnableExtension::WgpuRayTracingPipeline) {
@@ -154,12 +148,11 @@ pub fn map_built_in(
154148
};
155149
match built_in {
156150
crate::BuiltIn::ClipDistance => {
157-
if !enable_extensions.contains(ImplementedEnableExtension::ClipDistances) {
158-
return Err(Box::new(Error::EnableExtensionNotEnabled {
159-
span,
160-
kind: ImplementedEnableExtension::ClipDistances.into(),
161-
}));
162-
}
151+
enable_extensions.require(ImplementedEnableExtension::ClipDistances, span)?
152+
}
153+
154+
crate::BuiltIn::PrimitiveIndex => {
155+
enable_extensions.require(ImplementedEnableExtension::PrimitiveIndex, span)?
163156
}
164157
crate::BuiltIn::CullPrimitive
165158
| crate::BuiltIn::PointIndex
@@ -169,12 +162,7 @@ pub fn map_built_in(
169162
| crate::BuiltIn::Vertices
170163
| crate::BuiltIn::PrimitiveCount
171164
| crate::BuiltIn::Primitives => {
172-
if !enable_extensions.contains(ImplementedEnableExtension::WgpuMeshShader) {
173-
return Err(Box::new(Error::EnableExtensionNotEnabled {
174-
span,
175-
kind: ImplementedEnableExtension::WgpuMeshShader.into(),
176-
}));
177-
}
165+
enable_extensions.require(ImplementedEnableExtension::WgpuMeshShader, span)?
178166
}
179167
_ => {}
180168
}

naga/src/front/wgsl/parse/directive/enable_extension.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub(crate) struct EnableExtensions {
1919
f16: bool,
2020
clip_distances: bool,
2121
wgpu_cooperative_matrix: bool,
22+
primitive_index: bool,
2223
}
2324

2425
impl EnableExtensions {
@@ -32,6 +33,7 @@ impl EnableExtensions {
3233
dual_source_blending: false,
3334
clip_distances: false,
3435
wgpu_cooperative_matrix: false,
36+
primitive_index: false,
3537
}
3638
}
3739

@@ -50,6 +52,7 @@ impl EnableExtensions {
5052
ImplementedEnableExtension::F16 => &mut self.f16,
5153
ImplementedEnableExtension::ClipDistances => &mut self.clip_distances,
5254
ImplementedEnableExtension::WgpuCooperativeMatrix => &mut self.wgpu_cooperative_matrix,
55+
ImplementedEnableExtension::PrimitiveIndex => &mut self.primitive_index,
5356
};
5457
*field = true;
5558
}
@@ -67,6 +70,22 @@ impl EnableExtensions {
6770
ImplementedEnableExtension::F16 => self.f16,
6871
ImplementedEnableExtension::ClipDistances => self.clip_distances,
6972
ImplementedEnableExtension::WgpuCooperativeMatrix => self.wgpu_cooperative_matrix,
73+
ImplementedEnableExtension::PrimitiveIndex => self.primitive_index,
74+
}
75+
}
76+
77+
pub(crate) fn require(
78+
&self,
79+
ext: ImplementedEnableExtension,
80+
span: Span,
81+
) -> Result<'static, ()> {
82+
if !self.contains(ext) {
83+
Err(Box::new(Error::EnableExtensionNotEnabled {
84+
span,
85+
kind: ext.into(),
86+
}))
87+
} else {
88+
Ok(())
7089
}
7190
}
7291
}
@@ -124,9 +143,7 @@ impl EnableExtension {
124143
Self::Implemented(ImplementedEnableExtension::WgpuCooperativeMatrix)
125144
}
126145
Self::SUBGROUPS => Self::Unimplemented(UnimplementedEnableExtension::Subgroups),
127-
Self::PRIMITIVE_INDEX => {
128-
Self::Unimplemented(UnimplementedEnableExtension::PrimitiveIndex)
129-
}
146+
Self::PRIMITIVE_INDEX => Self::Implemented(ImplementedEnableExtension::PrimitiveIndex),
130147
_ => return Err(Box::new(Error::UnknownEnableExtension(span, word))),
131148
})
132149
}
@@ -144,11 +161,11 @@ impl EnableExtension {
144161
ImplementedEnableExtension::DualSourceBlending => Self::DUAL_SOURCE_BLENDING,
145162
ImplementedEnableExtension::F16 => Self::F16,
146163
ImplementedEnableExtension::ClipDistances => Self::CLIP_DISTANCES,
164+
ImplementedEnableExtension::PrimitiveIndex => Self::PRIMITIVE_INDEX,
147165
ImplementedEnableExtension::WgpuRayTracingPipeline => Self::RAY_TRACING_PIPELINE,
148166
},
149167
Self::Unimplemented(kind) => match kind {
150168
UnimplementedEnableExtension::Subgroups => Self::SUBGROUPS,
151-
UnimplementedEnableExtension::PrimitiveIndex => Self::PRIMITIVE_INDEX,
152169
},
153170
}
154171
}
@@ -186,6 +203,12 @@ pub enum ImplementedEnableExtension {
186203
WgpuRayTracingPipeline,
187204
/// Enables the `wgpu_cooperative_matrix` extension, native only.
188205
WgpuCooperativeMatrix,
206+
/// Enables the `@builtin(primitive_index)` attribute in WGSL.
207+
///
208+
/// In the WGSL standard, this corresponds to [`enable primitive-index;`].
209+
///
210+
/// [`enable primitive-index;`]: https://www.w3.org/TR/WGSL/#extension-primitive_index
211+
PrimitiveIndex,
189212
}
190213

191214
impl ImplementedEnableExtension {
@@ -199,6 +222,7 @@ impl ImplementedEnableExtension {
199222
Self::WgpuRayQueryVertexReturn,
200223
Self::WgpuRayTracingPipeline,
201224
Self::WgpuCooperativeMatrix,
225+
Self::PrimitiveIndex,
202226
];
203227

204228
/// Returns slice of all variants of [`ImplementedEnableExtension`].
@@ -218,6 +242,7 @@ impl ImplementedEnableExtension {
218242
Self::WgpuRayQueryVertexReturn => C::RAY_HIT_VERTEX_POSITION,
219243
Self::WgpuCooperativeMatrix => C::COOPERATIVE_MATRIX,
220244
Self::WgpuRayTracingPipeline => C::RAY_TRACING_PIPELINE,
245+
Self::PrimitiveIndex => C::PRIMITIVE_INDEX,
221246
}
222247
}
223248
}
@@ -241,19 +266,12 @@ pub enum UnimplementedEnableExtension {
241266
///
242267
/// [`enable subgroups;`]: https://www.w3.org/TR/WGSL/#extension-subgroups
243268
Subgroups,
244-
/// Enables the `@builtin(primitive_index)` attribute in WGSL.
245-
///
246-
/// In the WGSL standard, this corresponds to [`enable primitive-index;`].
247-
///
248-
/// [`enable primitive-index;`]: https://www.w3.org/TR/WGSL/#extension-primitive_index
249-
PrimitiveIndex,
250269
}
251270

252271
impl UnimplementedEnableExtension {
253272
pub(crate) const fn tracking_issue_num(self) -> u16 {
254273
match self {
255274
Self::Subgroups => 5555,
256-
Self::PrimitiveIndex => 8236,
257275
}
258276
}
259277
}

naga/tests/in/wgsl/extra.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
enable primitive_index;
2+
13
struct ImmediateData {
24
index: u32,
35
double: vec2<f32>,

0 commit comments

Comments
 (0)