mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-01-10 05:08:36 -05:00
[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 <jimb@red-bean.com>
This commit is contained in:
@@ -538,8 +538,8 @@ fn run() -> anyhow::Result<()> {
|
||||
use naga::valid::Capabilities as C;
|
||||
let missing = match Path::new(path).extension().and_then(|ex| ex.to_str()) {
|
||||
Some("wgsl") => C::CLIP_DISTANCE | C::CULL_DISTANCE,
|
||||
Some("metal") => C::CULL_DISTANCE,
|
||||
_ => C::empty(),
|
||||
Some("metal") => C::CULL_DISTANCE | C::TEXTURE_EXTERNAL,
|
||||
_ => C::TEXTURE_EXTERNAL,
|
||||
};
|
||||
caps & !missing
|
||||
});
|
||||
|
||||
@@ -421,7 +421,8 @@ impl<W> Writer<'_, W> {
|
||||
_ => {}
|
||||
},
|
||||
ImageClass::Sampled { multi: false, .. }
|
||||
| ImageClass::Depth { multi: false } => {}
|
||||
| ImageClass::Depth { multi: false }
|
||||
| ImageClass::External => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -1176,6 +1176,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
Ic::Depth { multi: true } => ("sampler", float, "MS", ""),
|
||||
Ic::Depth { multi: false } => ("sampler", float, "", "Shadow"),
|
||||
Ic::Storage { format, .. } => ("image", format.into(), "", ""),
|
||||
Ic::External => unimplemented!(),
|
||||
};
|
||||
|
||||
let precision = if self.options.version.is_es() {
|
||||
@@ -3302,6 +3303,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
write!(self.out, "imageSize(")?;
|
||||
self.write_expr(image, ctx)?;
|
||||
}
|
||||
ImageClass::External => unimplemented!(),
|
||||
}
|
||||
write!(self.out, ")")?;
|
||||
if components != 1 || self.options.version.is_es() {
|
||||
@@ -3317,6 +3319,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
let fun_name = match class {
|
||||
ImageClass::Sampled { .. } | ImageClass::Depth { .. } => "textureSize",
|
||||
ImageClass::Storage { .. } => "imageSize",
|
||||
ImageClass::External => unimplemented!(),
|
||||
};
|
||||
write!(self.out, "{fun_name}(")?;
|
||||
self.write_expr(image, ctx)?;
|
||||
@@ -3336,6 +3339,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
"textureSamples"
|
||||
}
|
||||
ImageClass::Storage { .. } => "imageSamples",
|
||||
ImageClass::External => unimplemented!(),
|
||||
};
|
||||
write!(self.out, "{fun_name}(")?;
|
||||
self.write_expr(image, ctx)?;
|
||||
@@ -4618,6 +4622,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
"WGSL `textureLoad` from depth textures is not supported in GLSL".to_string(),
|
||||
))
|
||||
}
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
};
|
||||
|
||||
// openGL es doesn't have 1D images so we need workaround it
|
||||
|
||||
@@ -195,6 +195,7 @@ impl<W: Write> super::Writer<'_, W> {
|
||||
let storage_format_str = format.to_hlsl_str();
|
||||
write!(self.out, "<{storage_format_str}>")?
|
||||
}
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -290,6 +291,7 @@ impl<W: Write> super::Writer<'_, W> {
|
||||
crate::ImageClass::Depth { multi: false } => "Depth",
|
||||
crate::ImageClass::Sampled { multi: false, .. } => "",
|
||||
crate::ImageClass::Storage { .. } => "RW",
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
};
|
||||
let arrayed_str = if query.arrayed { "Array" } else { "" };
|
||||
let query_str = match query.query {
|
||||
@@ -349,6 +351,7 @@ impl<W: Write> super::Writer<'_, W> {
|
||||
let extra_coords = match wiq.class {
|
||||
crate::ImageClass::Storage { .. } => 0,
|
||||
crate::ImageClass::Sampled { .. } | crate::ImageClass::Depth { .. } => 1,
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
};
|
||||
|
||||
// GetDimensions Overloaded Methods
|
||||
|
||||
@@ -321,6 +321,7 @@ impl Display for TypeContext<'_> {
|
||||
};
|
||||
("texture", "", format.into(), access)
|
||||
}
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
};
|
||||
let base_name = scalar.to_msl_name();
|
||||
let array_str = if arrayed { "_array" } else { "" };
|
||||
@@ -6637,6 +6638,7 @@ template <typename A>
|
||||
"read-write textures".to_string(),
|
||||
));
|
||||
}
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
},
|
||||
_ => {
|
||||
return Err(Error::UnsupportedArrayOfType(base));
|
||||
|
||||
@@ -118,6 +118,7 @@ impl Load {
|
||||
crate::ImageClass::Depth { .. } | crate::ImageClass::Sampled { .. } => {
|
||||
spirv::Op::ImageFetch
|
||||
}
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
};
|
||||
|
||||
// `OpImageRead` and `OpImageFetch` instructions produce vec4<f32>
|
||||
|
||||
@@ -276,6 +276,7 @@ impl LocalImageType {
|
||||
flags: make_flags(false, ImageTypeFlags::empty()),
|
||||
image_format: format.into(),
|
||||
},
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1246,6 +1246,7 @@ impl Writer {
|
||||
self.request_image_format_capabilities(format.into())?;
|
||||
false
|
||||
}
|
||||
crate::ImageClass::External => unimplemented!(),
|
||||
};
|
||||
|
||||
match dim {
|
||||
|
||||
@@ -250,6 +250,9 @@ where
|
||||
"texture_storage_{dim_str}{arrayed_str}<{format_str}{access_str}>"
|
||||
)?;
|
||||
}
|
||||
Ic::External => {
|
||||
write!(out, "texture_external")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeInner::Scalar(scalar) => {
|
||||
|
||||
@@ -2138,6 +2138,7 @@ impl Frontend {
|
||||
ImageClass::Depth { .. } => (true, false),
|
||||
ImageClass::Storage { .. } => (false, true),
|
||||
ImageClass::Sampled { .. } => (false, false),
|
||||
ImageClass::External => unreachable!(),
|
||||
};
|
||||
|
||||
let coordinate = match (image_size, coord_size) {
|
||||
@@ -2259,6 +2260,7 @@ pub fn sampled_to_depth(
|
||||
kind: ErrorKind::SemanticError("Not a texture".into()),
|
||||
meta,
|
||||
}),
|
||||
ImageClass::External => unreachable!(),
|
||||
},
|
||||
_ => errors.push(Error {
|
||||
kind: ErrorKind::SemanticError("Not a texture".into()),
|
||||
|
||||
@@ -3587,9 +3587,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
||||
self.expression_with_leaf_scalar(args.next()?, ir::Scalar::F32, ctx)?
|
||||
}
|
||||
|
||||
// Sampling `Storage` textures isn't allowed at all. Let the
|
||||
// validator report the error.
|
||||
ir::ImageClass::Storage { .. } => self.expression(args.next()?, ctx)?,
|
||||
// Sampling `External` textures with a specified level isn't
|
||||
// allowed, and sampling `Storage` textures isn't allowed at
|
||||
// all. Let the validator report the error.
|
||||
ir::ImageClass::Storage { .. } | ir::ImageClass::External => {
|
||||
self.expression(args.next()?, ctx)?
|
||||
}
|
||||
};
|
||||
level = ir::SampleLevel::Exact(exact);
|
||||
depth_ref = None;
|
||||
|
||||
@@ -676,6 +676,7 @@ impl Parser {
|
||||
| "texture_depth_cube"
|
||||
| "texture_depth_cube_array"
|
||||
| "texture_depth_multisampled_2d"
|
||||
| "texture_external"
|
||||
| "texture_storage_1d"
|
||||
| "texture_storage_1d_array"
|
||||
| "texture_storage_2d"
|
||||
@@ -1867,6 +1868,11 @@ impl Parser {
|
||||
arrayed: false,
|
||||
class: crate::ImageClass::Depth { multi: true },
|
||||
},
|
||||
"texture_external" => ast::Type::Image {
|
||||
dim: crate::ImageDimension::D2,
|
||||
arrayed: false,
|
||||
class: crate::ImageClass::External,
|
||||
},
|
||||
"texture_storage_1d" => {
|
||||
let (format, access) = lexer.next_format_generic()?;
|
||||
ast::Type::Image {
|
||||
|
||||
@@ -652,6 +652,8 @@ pub enum ImageClass {
|
||||
/// Multi-sampled depth image.
|
||||
multi: bool,
|
||||
},
|
||||
/// External texture.
|
||||
External,
|
||||
/// Storage image.
|
||||
Storage {
|
||||
format: StorageFormat,
|
||||
|
||||
@@ -383,6 +383,7 @@ impl super::ImageClass {
|
||||
match self {
|
||||
crate::ImageClass::Sampled { multi, .. } | crate::ImageClass::Depth { multi } => multi,
|
||||
crate::ImageClass::Storage { .. } => false,
|
||||
crate::ImageClass::External => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,6 +391,7 @@ impl super::ImageClass {
|
||||
match self {
|
||||
crate::ImageClass::Sampled { multi, .. } | crate::ImageClass::Depth { multi } => !multi,
|
||||
crate::ImageClass::Storage { .. } => false,
|
||||
crate::ImageClass::External => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -512,6 +512,10 @@ impl<'a> ResolveContext<'a> {
|
||||
scalar: format.into(),
|
||||
size: crate::VectorSize::Quad,
|
||||
},
|
||||
crate::ImageClass::External => Ti::Vector {
|
||||
scalar: crate::Scalar::F32,
|
||||
size: crate::VectorSize::Quad,
|
||||
},
|
||||
}),
|
||||
ref other => {
|
||||
log::error!("Image type {other:?}");
|
||||
|
||||
@@ -460,6 +460,7 @@ impl super::Validator {
|
||||
kind: crate::ScalarKind::Uint | crate::ScalarKind::Sint,
|
||||
multi: false,
|
||||
} if gather.is_some() => false,
|
||||
crate::ImageClass::External => false,
|
||||
crate::ImageClass::Depth { multi: false } => true,
|
||||
_ => return Err(ExpressionError::InvalidImageClass(class)),
|
||||
};
|
||||
@@ -551,7 +552,7 @@ impl super::Validator {
|
||||
crate::ImageClass::Sampled {
|
||||
kind: crate::ScalarKind::Float,
|
||||
multi: false
|
||||
}
|
||||
} | crate::ImageClass::External
|
||||
) {
|
||||
return Err(ExpressionError::InvalidSampleClampCoordinateToEdge(
|
||||
alloc::format!("image class `{class:?}`"),
|
||||
|
||||
@@ -168,6 +168,8 @@ bitflags::bitflags! {
|
||||
const RAY_HIT_VERTEX_POSITION = 1 << 25;
|
||||
/// Support for 16-bit floating-point types.
|
||||
const SHADER_FLOAT16 = 1 << 26;
|
||||
/// Support for [`ImageClass::External`]
|
||||
const TEXTURE_EXTERNAL = 1 << 27;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -732,6 +732,16 @@ impl super::Validator {
|
||||
if arrayed && matches!(dim, crate::ImageDimension::Cube) {
|
||||
self.require_type_capability(Capabilities::CUBE_ARRAY_TEXTURES)?;
|
||||
}
|
||||
if matches!(class, crate::ImageClass::External) {
|
||||
if dim != crate::ImageDimension::D2 || arrayed {
|
||||
return Err(TypeError::UnsupportedImageType {
|
||||
dim,
|
||||
arrayed,
|
||||
class,
|
||||
});
|
||||
}
|
||||
self.require_type_capability(Capabilities::TEXTURE_EXTERNAL)?;
|
||||
}
|
||||
TypeInfo::new(
|
||||
TypeFlags::ARGUMENT | TypeFlags::CREATION_RESOLVED,
|
||||
Alignment::ONE,
|
||||
|
||||
2
naga/tests/in/wgsl/texture-external.toml
Normal file
2
naga/tests/in/wgsl/texture-external.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
god_mode = true
|
||||
targets = "IR | WGSL"
|
||||
27
naga/tests/in/wgsl/texture-external.wgsl
Normal file
27
naga/tests/in/wgsl/texture-external.wgsl
Normal file
@@ -0,0 +1,27 @@
|
||||
@group(0) @binding(0)
|
||||
var tex: texture_external;
|
||||
@group(0) @binding(1)
|
||||
var samp: sampler;
|
||||
|
||||
fn test(t: texture_external) -> vec4<f32> {
|
||||
var a = textureSampleBaseClampToEdge(t, samp, vec2(0.0f));
|
||||
var b = textureLoad(t, vec2(0u));
|
||||
var c = textureDimensions(t);
|
||||
|
||||
return a + b + vec2f(c).xyxy;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fragment_main() -> @location(0) vec4<f32> {
|
||||
return test(tex);
|
||||
}
|
||||
|
||||
@vertex
|
||||
fn vertex_main() -> @builtin(position) vec4<f32> {
|
||||
return test(tex);
|
||||
}
|
||||
|
||||
@compute @workgroup_size(1)
|
||||
fn compute_main() {
|
||||
test(tex);
|
||||
}
|
||||
320
naga/tests/out/ir/wgsl-texture-external.compact.ron
Normal file
320
naga/tests/out/ir/wgsl-texture-external.compact.ron
Normal file
@@ -0,0 +1,320 @@
|
||||
(
|
||||
types: [
|
||||
(
|
||||
name: None,
|
||||
inner: Image(
|
||||
dim: D2,
|
||||
arrayed: false,
|
||||
class: External,
|
||||
),
|
||||
),
|
||||
(
|
||||
name: None,
|
||||
inner: Sampler(
|
||||
comparison: false,
|
||||
),
|
||||
),
|
||||
(
|
||||
name: None,
|
||||
inner: Vector(
|
||||
size: Quad,
|
||||
scalar: (
|
||||
kind: Float,
|
||||
width: 4,
|
||||
),
|
||||
),
|
||||
),
|
||||
(
|
||||
name: None,
|
||||
inner: Vector(
|
||||
size: Bi,
|
||||
scalar: (
|
||||
kind: Uint,
|
||||
width: 4,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
special_types: (
|
||||
ray_desc: None,
|
||||
ray_intersection: None,
|
||||
ray_vertex_return: None,
|
||||
predeclared_types: {},
|
||||
),
|
||||
constants: [],
|
||||
overrides: [],
|
||||
global_variables: [
|
||||
(
|
||||
name: Some("tex"),
|
||||
space: Handle,
|
||||
binding: Some((
|
||||
group: 0,
|
||||
binding: 0,
|
||||
)),
|
||||
ty: 0,
|
||||
init: None,
|
||||
),
|
||||
(
|
||||
name: Some("samp"),
|
||||
space: Handle,
|
||||
binding: Some((
|
||||
group: 0,
|
||||
binding: 1,
|
||||
)),
|
||||
ty: 1,
|
||||
init: None,
|
||||
),
|
||||
],
|
||||
global_expressions: [],
|
||||
functions: [
|
||||
(
|
||||
name: Some("test"),
|
||||
arguments: [
|
||||
(
|
||||
name: Some("t"),
|
||||
ty: 0,
|
||||
binding: None,
|
||||
),
|
||||
],
|
||||
result: Some((
|
||||
ty: 2,
|
||||
binding: None,
|
||||
)),
|
||||
local_variables: [
|
||||
(
|
||||
name: Some("a"),
|
||||
ty: 2,
|
||||
init: None,
|
||||
),
|
||||
(
|
||||
name: Some("b"),
|
||||
ty: 2,
|
||||
init: None,
|
||||
),
|
||||
(
|
||||
name: Some("c"),
|
||||
ty: 3,
|
||||
init: None,
|
||||
),
|
||||
],
|
||||
expressions: [
|
||||
FunctionArgument(0),
|
||||
GlobalVariable(1),
|
||||
Literal(F32(0.0)),
|
||||
Splat(
|
||||
size: Bi,
|
||||
value: 2,
|
||||
),
|
||||
ImageSample(
|
||||
image: 0,
|
||||
sampler: 1,
|
||||
gather: None,
|
||||
coordinate: 3,
|
||||
array_index: None,
|
||||
offset: None,
|
||||
level: Zero,
|
||||
depth_ref: None,
|
||||
clamp_to_edge: true,
|
||||
),
|
||||
LocalVariable(0),
|
||||
Literal(U32(0)),
|
||||
Splat(
|
||||
size: Bi,
|
||||
value: 6,
|
||||
),
|
||||
ImageLoad(
|
||||
image: 0,
|
||||
coordinate: 7,
|
||||
array_index: None,
|
||||
sample: None,
|
||||
level: None,
|
||||
),
|
||||
LocalVariable(1),
|
||||
ImageQuery(
|
||||
image: 0,
|
||||
query: Size(
|
||||
level: None,
|
||||
),
|
||||
),
|
||||
LocalVariable(2),
|
||||
Load(
|
||||
pointer: 5,
|
||||
),
|
||||
Load(
|
||||
pointer: 9,
|
||||
),
|
||||
Binary(
|
||||
op: Add,
|
||||
left: 12,
|
||||
right: 13,
|
||||
),
|
||||
Load(
|
||||
pointer: 11,
|
||||
),
|
||||
As(
|
||||
expr: 15,
|
||||
kind: Float,
|
||||
convert: Some(4),
|
||||
),
|
||||
Swizzle(
|
||||
size: Quad,
|
||||
vector: 16,
|
||||
pattern: (X, Y, X, Y),
|
||||
),
|
||||
Binary(
|
||||
op: Add,
|
||||
left: 14,
|
||||
right: 17,
|
||||
),
|
||||
],
|
||||
named_expressions: {
|
||||
0: "t",
|
||||
},
|
||||
body: [
|
||||
Emit((
|
||||
start: 3,
|
||||
end: 5,
|
||||
)),
|
||||
Store(
|
||||
pointer: 5,
|
||||
value: 4,
|
||||
),
|
||||
Emit((
|
||||
start: 7,
|
||||
end: 9,
|
||||
)),
|
||||
Store(
|
||||
pointer: 9,
|
||||
value: 8,
|
||||
),
|
||||
Emit((
|
||||
start: 10,
|
||||
end: 11,
|
||||
)),
|
||||
Store(
|
||||
pointer: 11,
|
||||
value: 10,
|
||||
),
|
||||
Emit((
|
||||
start: 12,
|
||||
end: 19,
|
||||
)),
|
||||
Return(
|
||||
value: Some(18),
|
||||
),
|
||||
],
|
||||
diagnostic_filter_leaf: None,
|
||||
),
|
||||
],
|
||||
entry_points: [
|
||||
(
|
||||
name: "fragment_main",
|
||||
stage: Fragment,
|
||||
early_depth_test: None,
|
||||
workgroup_size: (0, 0, 0),
|
||||
workgroup_size_overrides: None,
|
||||
function: (
|
||||
name: Some("fragment_main"),
|
||||
arguments: [],
|
||||
result: Some((
|
||||
ty: 2,
|
||||
binding: Some(Location(
|
||||
location: 0,
|
||||
interpolation: Some(Perspective),
|
||||
sampling: Some(Center),
|
||||
blend_src: None,
|
||||
)),
|
||||
)),
|
||||
local_variables: [],
|
||||
expressions: [
|
||||
GlobalVariable(0),
|
||||
CallResult(0),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Call(
|
||||
function: 0,
|
||||
arguments: [
|
||||
0,
|
||||
],
|
||||
result: Some(1),
|
||||
),
|
||||
Return(
|
||||
value: Some(1),
|
||||
),
|
||||
],
|
||||
diagnostic_filter_leaf: None,
|
||||
),
|
||||
),
|
||||
(
|
||||
name: "vertex_main",
|
||||
stage: Vertex,
|
||||
early_depth_test: None,
|
||||
workgroup_size: (0, 0, 0),
|
||||
workgroup_size_overrides: None,
|
||||
function: (
|
||||
name: Some("vertex_main"),
|
||||
arguments: [],
|
||||
result: Some((
|
||||
ty: 2,
|
||||
binding: Some(BuiltIn(Position(
|
||||
invariant: false,
|
||||
))),
|
||||
)),
|
||||
local_variables: [],
|
||||
expressions: [
|
||||
GlobalVariable(0),
|
||||
CallResult(0),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Call(
|
||||
function: 0,
|
||||
arguments: [
|
||||
0,
|
||||
],
|
||||
result: Some(1),
|
||||
),
|
||||
Return(
|
||||
value: Some(1),
|
||||
),
|
||||
],
|
||||
diagnostic_filter_leaf: None,
|
||||
),
|
||||
),
|
||||
(
|
||||
name: "compute_main",
|
||||
stage: Compute,
|
||||
early_depth_test: None,
|
||||
workgroup_size: (1, 1, 1),
|
||||
workgroup_size_overrides: None,
|
||||
function: (
|
||||
name: Some("compute_main"),
|
||||
arguments: [],
|
||||
result: None,
|
||||
local_variables: [],
|
||||
expressions: [
|
||||
GlobalVariable(0),
|
||||
CallResult(0),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Call(
|
||||
function: 0,
|
||||
arguments: [
|
||||
0,
|
||||
],
|
||||
result: Some(1),
|
||||
),
|
||||
Return(
|
||||
value: None,
|
||||
),
|
||||
],
|
||||
diagnostic_filter_leaf: None,
|
||||
),
|
||||
),
|
||||
],
|
||||
diagnostic_filters: [],
|
||||
diagnostic_filter_leaf: None,
|
||||
doc_comments: None,
|
||||
)
|
||||
320
naga/tests/out/ir/wgsl-texture-external.ron
Normal file
320
naga/tests/out/ir/wgsl-texture-external.ron
Normal file
@@ -0,0 +1,320 @@
|
||||
(
|
||||
types: [
|
||||
(
|
||||
name: None,
|
||||
inner: Image(
|
||||
dim: D2,
|
||||
arrayed: false,
|
||||
class: External,
|
||||
),
|
||||
),
|
||||
(
|
||||
name: None,
|
||||
inner: Sampler(
|
||||
comparison: false,
|
||||
),
|
||||
),
|
||||
(
|
||||
name: None,
|
||||
inner: Vector(
|
||||
size: Quad,
|
||||
scalar: (
|
||||
kind: Float,
|
||||
width: 4,
|
||||
),
|
||||
),
|
||||
),
|
||||
(
|
||||
name: None,
|
||||
inner: Vector(
|
||||
size: Bi,
|
||||
scalar: (
|
||||
kind: Uint,
|
||||
width: 4,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
special_types: (
|
||||
ray_desc: None,
|
||||
ray_intersection: None,
|
||||
ray_vertex_return: None,
|
||||
predeclared_types: {},
|
||||
),
|
||||
constants: [],
|
||||
overrides: [],
|
||||
global_variables: [
|
||||
(
|
||||
name: Some("tex"),
|
||||
space: Handle,
|
||||
binding: Some((
|
||||
group: 0,
|
||||
binding: 0,
|
||||
)),
|
||||
ty: 0,
|
||||
init: None,
|
||||
),
|
||||
(
|
||||
name: Some("samp"),
|
||||
space: Handle,
|
||||
binding: Some((
|
||||
group: 0,
|
||||
binding: 1,
|
||||
)),
|
||||
ty: 1,
|
||||
init: None,
|
||||
),
|
||||
],
|
||||
global_expressions: [],
|
||||
functions: [
|
||||
(
|
||||
name: Some("test"),
|
||||
arguments: [
|
||||
(
|
||||
name: Some("t"),
|
||||
ty: 0,
|
||||
binding: None,
|
||||
),
|
||||
],
|
||||
result: Some((
|
||||
ty: 2,
|
||||
binding: None,
|
||||
)),
|
||||
local_variables: [
|
||||
(
|
||||
name: Some("a"),
|
||||
ty: 2,
|
||||
init: None,
|
||||
),
|
||||
(
|
||||
name: Some("b"),
|
||||
ty: 2,
|
||||
init: None,
|
||||
),
|
||||
(
|
||||
name: Some("c"),
|
||||
ty: 3,
|
||||
init: None,
|
||||
),
|
||||
],
|
||||
expressions: [
|
||||
FunctionArgument(0),
|
||||
GlobalVariable(1),
|
||||
Literal(F32(0.0)),
|
||||
Splat(
|
||||
size: Bi,
|
||||
value: 2,
|
||||
),
|
||||
ImageSample(
|
||||
image: 0,
|
||||
sampler: 1,
|
||||
gather: None,
|
||||
coordinate: 3,
|
||||
array_index: None,
|
||||
offset: None,
|
||||
level: Zero,
|
||||
depth_ref: None,
|
||||
clamp_to_edge: true,
|
||||
),
|
||||
LocalVariable(0),
|
||||
Literal(U32(0)),
|
||||
Splat(
|
||||
size: Bi,
|
||||
value: 6,
|
||||
),
|
||||
ImageLoad(
|
||||
image: 0,
|
||||
coordinate: 7,
|
||||
array_index: None,
|
||||
sample: None,
|
||||
level: None,
|
||||
),
|
||||
LocalVariable(1),
|
||||
ImageQuery(
|
||||
image: 0,
|
||||
query: Size(
|
||||
level: None,
|
||||
),
|
||||
),
|
||||
LocalVariable(2),
|
||||
Load(
|
||||
pointer: 5,
|
||||
),
|
||||
Load(
|
||||
pointer: 9,
|
||||
),
|
||||
Binary(
|
||||
op: Add,
|
||||
left: 12,
|
||||
right: 13,
|
||||
),
|
||||
Load(
|
||||
pointer: 11,
|
||||
),
|
||||
As(
|
||||
expr: 15,
|
||||
kind: Float,
|
||||
convert: Some(4),
|
||||
),
|
||||
Swizzle(
|
||||
size: Quad,
|
||||
vector: 16,
|
||||
pattern: (X, Y, X, Y),
|
||||
),
|
||||
Binary(
|
||||
op: Add,
|
||||
left: 14,
|
||||
right: 17,
|
||||
),
|
||||
],
|
||||
named_expressions: {
|
||||
0: "t",
|
||||
},
|
||||
body: [
|
||||
Emit((
|
||||
start: 3,
|
||||
end: 5,
|
||||
)),
|
||||
Store(
|
||||
pointer: 5,
|
||||
value: 4,
|
||||
),
|
||||
Emit((
|
||||
start: 7,
|
||||
end: 9,
|
||||
)),
|
||||
Store(
|
||||
pointer: 9,
|
||||
value: 8,
|
||||
),
|
||||
Emit((
|
||||
start: 10,
|
||||
end: 11,
|
||||
)),
|
||||
Store(
|
||||
pointer: 11,
|
||||
value: 10,
|
||||
),
|
||||
Emit((
|
||||
start: 12,
|
||||
end: 19,
|
||||
)),
|
||||
Return(
|
||||
value: Some(18),
|
||||
),
|
||||
],
|
||||
diagnostic_filter_leaf: None,
|
||||
),
|
||||
],
|
||||
entry_points: [
|
||||
(
|
||||
name: "fragment_main",
|
||||
stage: Fragment,
|
||||
early_depth_test: None,
|
||||
workgroup_size: (0, 0, 0),
|
||||
workgroup_size_overrides: None,
|
||||
function: (
|
||||
name: Some("fragment_main"),
|
||||
arguments: [],
|
||||
result: Some((
|
||||
ty: 2,
|
||||
binding: Some(Location(
|
||||
location: 0,
|
||||
interpolation: Some(Perspective),
|
||||
sampling: Some(Center),
|
||||
blend_src: None,
|
||||
)),
|
||||
)),
|
||||
local_variables: [],
|
||||
expressions: [
|
||||
GlobalVariable(0),
|
||||
CallResult(0),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Call(
|
||||
function: 0,
|
||||
arguments: [
|
||||
0,
|
||||
],
|
||||
result: Some(1),
|
||||
),
|
||||
Return(
|
||||
value: Some(1),
|
||||
),
|
||||
],
|
||||
diagnostic_filter_leaf: None,
|
||||
),
|
||||
),
|
||||
(
|
||||
name: "vertex_main",
|
||||
stage: Vertex,
|
||||
early_depth_test: None,
|
||||
workgroup_size: (0, 0, 0),
|
||||
workgroup_size_overrides: None,
|
||||
function: (
|
||||
name: Some("vertex_main"),
|
||||
arguments: [],
|
||||
result: Some((
|
||||
ty: 2,
|
||||
binding: Some(BuiltIn(Position(
|
||||
invariant: false,
|
||||
))),
|
||||
)),
|
||||
local_variables: [],
|
||||
expressions: [
|
||||
GlobalVariable(0),
|
||||
CallResult(0),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Call(
|
||||
function: 0,
|
||||
arguments: [
|
||||
0,
|
||||
],
|
||||
result: Some(1),
|
||||
),
|
||||
Return(
|
||||
value: Some(1),
|
||||
),
|
||||
],
|
||||
diagnostic_filter_leaf: None,
|
||||
),
|
||||
),
|
||||
(
|
||||
name: "compute_main",
|
||||
stage: Compute,
|
||||
early_depth_test: None,
|
||||
workgroup_size: (1, 1, 1),
|
||||
workgroup_size_overrides: None,
|
||||
function: (
|
||||
name: Some("compute_main"),
|
||||
arguments: [],
|
||||
result: None,
|
||||
local_variables: [],
|
||||
expressions: [
|
||||
GlobalVariable(0),
|
||||
CallResult(0),
|
||||
],
|
||||
named_expressions: {},
|
||||
body: [
|
||||
Call(
|
||||
function: 0,
|
||||
arguments: [
|
||||
0,
|
||||
],
|
||||
result: Some(1),
|
||||
),
|
||||
Return(
|
||||
value: None,
|
||||
),
|
||||
],
|
||||
diagnostic_filter_leaf: None,
|
||||
),
|
||||
),
|
||||
],
|
||||
diagnostic_filters: [],
|
||||
diagnostic_filter_leaf: None,
|
||||
doc_comments: None,
|
||||
)
|
||||
39
naga/tests/out/wgsl/wgsl-texture-external.wgsl
Normal file
39
naga/tests/out/wgsl/wgsl-texture-external.wgsl
Normal file
@@ -0,0 +1,39 @@
|
||||
@group(0) @binding(0)
|
||||
var tex: texture_external;
|
||||
@group(0) @binding(1)
|
||||
var samp: sampler;
|
||||
|
||||
fn test(t: texture_external) -> vec4<f32> {
|
||||
var a: vec4<f32>;
|
||||
var b: vec4<f32>;
|
||||
var c: vec2<u32>;
|
||||
|
||||
let _e4 = textureSampleBaseClampToEdge(t, samp, vec2(0f));
|
||||
a = _e4;
|
||||
let _e8 = textureLoad(t, vec2(0u));
|
||||
b = _e8;
|
||||
let _e10 = textureDimensions(t);
|
||||
c = _e10;
|
||||
let _e12 = a;
|
||||
let _e13 = b;
|
||||
let _e15 = c;
|
||||
return ((_e12 + _e13) + vec2<f32>(_e15).xyxy);
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fragment_main() -> @location(0) vec4<f32> {
|
||||
let _e1 = test(tex);
|
||||
return _e1;
|
||||
}
|
||||
|
||||
@vertex
|
||||
fn vertex_main() -> @builtin(position) vec4<f32> {
|
||||
let _e1 = test(tex);
|
||||
return _e1;
|
||||
}
|
||||
|
||||
@compute @workgroup_size(1, 1, 1)
|
||||
fn compute_main() {
|
||||
let _e1 = test(tex);
|
||||
return;
|
||||
}
|
||||
@@ -494,6 +494,10 @@ pub fn create_validator(
|
||||
Caps::RAY_HIT_VERTEX_POSITION,
|
||||
features.intersects(wgt::Features::EXPERIMENTAL_RAY_HIT_VERTEX_RETURN),
|
||||
);
|
||||
caps.set(
|
||||
Caps::TEXTURE_EXTERNAL,
|
||||
features.intersects(wgt::Features::EXTERNAL_TEXTURE),
|
||||
);
|
||||
|
||||
naga::valid::Validator::new(flags, caps)
|
||||
}
|
||||
|
||||
@@ -46,6 +46,10 @@ impl From<&ResourceType> for BindingTypeName {
|
||||
fn from(ty: &ResourceType) -> BindingTypeName {
|
||||
match ty {
|
||||
ResourceType::Buffer { .. } => BindingTypeName::Buffer,
|
||||
ResourceType::Texture {
|
||||
class: naga::ImageClass::External,
|
||||
..
|
||||
} => BindingTypeName::ExternalTexture,
|
||||
ResourceType::Texture { .. } => BindingTypeName::Texture,
|
||||
ResourceType::Sampler { .. } => BindingTypeName::Sampler,
|
||||
ResourceType::AccelerationStructure { .. } => BindingTypeName::AccelerationStructure,
|
||||
@@ -594,6 +598,7 @@ impl Resource {
|
||||
access: naga_access,
|
||||
}
|
||||
}
|
||||
BindingType::ExternalTexture => naga::ImageClass::External,
|
||||
_ => {
|
||||
return Err(BindingError::WrongType {
|
||||
binding: (&entry.ty).into(),
|
||||
@@ -701,6 +706,7 @@ impl Resource {
|
||||
f
|
||||
},
|
||||
},
|
||||
naga::ImageClass::External => BindingType::ExternalTexture,
|
||||
}
|
||||
}
|
||||
ResourceType::AccelerationStructure { vertex_return } => {
|
||||
|
||||
Reference in New Issue
Block a user