Skip to content

Commit 43a4d53

Browse files
[naga wgsl-in wgsl-out] WGSL support for texture_external texture type (#7822)
* [naga wgsl-in wgsl-out] WGSL support for texture_external texture type Make wgsl-in correctly parse `texture_external` texture declarations, and allow such textures to be used in `textureDimensions()`, `textureSampleBaseClampToEdge()`, and `textureLoad()` function calls. In IR these are represented by the `ImageClass::External` image class, which is a 2D, non-multisampled, non-mipmapped, float-sampled image. Adds a new Capability `TEXTURE_EXTERNAL` and ensure validation rejects shaders containing external textures if this capability flag is not set. This capability is enabled for validation by wgpu devices which support the `TEXTURE_EXTERNAL` feature (currently only when using the noop backend), and by the Naga CLI when validating-only or when outputting WGSL. The WGSL backend can of course emit `ImageClass::External` images directly as `texture_external` textures. Other backends are, for now, unimplemented. Lastly, we add a snapshot test covering all the valid uses of a texture_external texture. These are: - As a global variable declaration - As an argument to the built-in functions `textureDimensions()`, `textureSampleBaseClampToEdge()`, and `textureLoad()` - As an argument to user-defined function declarations and calls. We keep these in their own test so that we can control which targets to run them against (currently WGSL and IR). When external textures are supported by all Naga backends we can, if so inclined, integrate these with existing texture tests. * fixup! [naga wgsl-in wgsl-out] WGSL support for texture_external texture type * fixup! [naga wgsl-in wgsl-out] WGSL support for texture_external texture type --------- Co-authored-by: Jim Blandy <[email protected]>
1 parent 4a00b62 commit 43a4d53

File tree

25 files changed

+774
-7
lines changed

25 files changed

+774
-7
lines changed

naga-cli/src/bin/naga.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,8 +538,8 @@ fn run() -> anyhow::Result<()> {
538538
use naga::valid::Capabilities as C;
539539
let missing = match Path::new(path).extension().and_then(|ex| ex.to_str()) {
540540
Some("wgsl") => C::CLIP_DISTANCE | C::CULL_DISTANCE,
541-
Some("metal") => C::CULL_DISTANCE,
542-
_ => C::empty(),
541+
Some("metal") => C::CULL_DISTANCE | C::TEXTURE_EXTERNAL,
542+
_ => C::TEXTURE_EXTERNAL,
543543
};
544544
caps & !missing
545545
});

naga/src/back/glsl/features.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,8 @@ impl<W> Writer<'_, W> {
421421
_ => {}
422422
},
423423
ImageClass::Sampled { multi: false, .. }
424-
| ImageClass::Depth { multi: false } => {}
424+
| ImageClass::Depth { multi: false }
425+
| ImageClass::External => {}
425426
}
426427
}
427428
_ => {}

naga/src/back/glsl/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,7 @@ impl<'a, W: Write> Writer<'a, W> {
11761176
Ic::Depth { multi: true } => ("sampler", float, "MS", ""),
11771177
Ic::Depth { multi: false } => ("sampler", float, "", "Shadow"),
11781178
Ic::Storage { format, .. } => ("image", format.into(), "", ""),
1179+
Ic::External => unimplemented!(),
11791180
};
11801181

11811182
let precision = if self.options.version.is_es() {
@@ -3302,6 +3303,7 @@ impl<'a, W: Write> Writer<'a, W> {
33023303
write!(self.out, "imageSize(")?;
33033304
self.write_expr(image, ctx)?;
33043305
}
3306+
ImageClass::External => unimplemented!(),
33053307
}
33063308
write!(self.out, ")")?;
33073309
if components != 1 || self.options.version.is_es() {
@@ -3317,6 +3319,7 @@ impl<'a, W: Write> Writer<'a, W> {
33173319
let fun_name = match class {
33183320
ImageClass::Sampled { .. } | ImageClass::Depth { .. } => "textureSize",
33193321
ImageClass::Storage { .. } => "imageSize",
3322+
ImageClass::External => unimplemented!(),
33203323
};
33213324
write!(self.out, "{fun_name}(")?;
33223325
self.write_expr(image, ctx)?;
@@ -3336,6 +3339,7 @@ impl<'a, W: Write> Writer<'a, W> {
33363339
"textureSamples"
33373340
}
33383341
ImageClass::Storage { .. } => "imageSamples",
3342+
ImageClass::External => unimplemented!(),
33393343
};
33403344
write!(self.out, "{fun_name}(")?;
33413345
self.write_expr(image, ctx)?;
@@ -4618,6 +4622,7 @@ impl<'a, W: Write> Writer<'a, W> {
46184622
"WGSL `textureLoad` from depth textures is not supported in GLSL".to_string(),
46194623
))
46204624
}
4625+
crate::ImageClass::External => unimplemented!(),
46214626
};
46224627

46234628
// openGL es doesn't have 1D images so we need workaround it

naga/src/back/hlsl/help.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ impl<W: Write> super::Writer<'_, W> {
195195
let storage_format_str = format.to_hlsl_str();
196196
write!(self.out, "<{storage_format_str}>")?
197197
}
198+
crate::ImageClass::External => unimplemented!(),
198199
}
199200
Ok(())
200201
}
@@ -290,6 +291,7 @@ impl<W: Write> super::Writer<'_, W> {
290291
crate::ImageClass::Depth { multi: false } => "Depth",
291292
crate::ImageClass::Sampled { multi: false, .. } => "",
292293
crate::ImageClass::Storage { .. } => "RW",
294+
crate::ImageClass::External => unimplemented!(),
293295
};
294296
let arrayed_str = if query.arrayed { "Array" } else { "" };
295297
let query_str = match query.query {
@@ -349,6 +351,7 @@ impl<W: Write> super::Writer<'_, W> {
349351
let extra_coords = match wiq.class {
350352
crate::ImageClass::Storage { .. } => 0,
351353
crate::ImageClass::Sampled { .. } | crate::ImageClass::Depth { .. } => 1,
354+
crate::ImageClass::External => unimplemented!(),
352355
};
353356

354357
// GetDimensions Overloaded Methods

naga/src/back/msl/writer.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ impl Display for TypeContext<'_> {
321321
};
322322
("texture", "", format.into(), access)
323323
}
324+
crate::ImageClass::External => unimplemented!(),
324325
};
325326
let base_name = scalar.to_msl_name();
326327
let array_str = if arrayed { "_array" } else { "" };
@@ -6637,6 +6638,7 @@ template <typename A>
66376638
"read-write textures".to_string(),
66386639
));
66396640
}
6641+
crate::ImageClass::External => unimplemented!(),
66406642
},
66416643
_ => {
66426644
return Err(Error::UnsupportedArrayOfType(base));

naga/src/back/spv/image.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ impl Load {
118118
crate::ImageClass::Depth { .. } | crate::ImageClass::Sampled { .. } => {
119119
spirv::Op::ImageFetch
120120
}
121+
crate::ImageClass::External => unimplemented!(),
121122
};
122123

123124
// `OpImageRead` and `OpImageFetch` instructions produce vec4<f32>

naga/src/back/spv/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ impl LocalImageType {
276276
flags: make_flags(false, ImageTypeFlags::empty()),
277277
image_format: format.into(),
278278
},
279+
crate::ImageClass::External => unimplemented!(),
279280
}
280281
}
281282
}

naga/src/back/spv/writer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,7 @@ impl Writer {
12461246
self.request_image_format_capabilities(format.into())?;
12471247
false
12481248
}
1249+
crate::ImageClass::External => unimplemented!(),
12491250
};
12501251

12511252
match dim {

naga/src/common/wgsl/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ where
250250
"texture_storage_{dim_str}{arrayed_str}<{format_str}{access_str}>"
251251
)?;
252252
}
253+
Ic::External => {
254+
write!(out, "texture_external")?;
255+
}
253256
}
254257
}
255258
TypeInner::Scalar(scalar) => {

naga/src/front/glsl/builtins.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,7 @@ impl Frontend {
21382138
ImageClass::Depth { .. } => (true, false),
21392139
ImageClass::Storage { .. } => (false, true),
21402140
ImageClass::Sampled { .. } => (false, false),
2141+
ImageClass::External => unreachable!(),
21412142
};
21422143

21432144
let coordinate = match (image_size, coord_size) {
@@ -2259,6 +2260,7 @@ pub fn sampled_to_depth(
22592260
kind: ErrorKind::SemanticError("Not a texture".into()),
22602261
meta,
22612262
}),
2263+
ImageClass::External => unreachable!(),
22622264
},
22632265
_ => errors.push(Error {
22642266
kind: ErrorKind::SemanticError("Not a texture".into()),

0 commit comments

Comments
 (0)