Skip to content

wgpu-core implementation for external textures #7823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/standalone/custom_backend/src/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ impl DeviceInterface for CustomDevice {
unimplemented!()
}

fn create_external_texture(
&self,
_desc: &wgpu::ExternalTextureDescriptor<'_>,
_planes: &[&wgpu::TextureView],
) -> wgpu::custom::DispatchExternalTexture {
unimplemented!()
}

fn create_blas(
&self,
_desc: &wgpu::CreateBlasDescriptor<'_>,
Expand Down
4 changes: 2 additions & 2 deletions naga-cli/src/bin/naga.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,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
});
Expand Down
3 changes: 2 additions & 1 deletion naga/src/back/glsl/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,8 @@ impl<W> Writer<'_, W> {
_ => {}
},
ImageClass::Sampled { multi: false, .. }
| ImageClass::Depth { multi: false } => {}
| ImageClass::Depth { multi: false }
| ImageClass::External => {}
}
}
_ => {}
Expand Down
5 changes: 5 additions & 0 deletions naga/src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand All @@ -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)?;
Expand All @@ -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)?;
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions naga/src/back/hlsl/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions naga/src/back/msl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 { "" };
Expand Down Expand Up @@ -6637,6 +6638,7 @@ template <typename A>
"read-write textures".to_string(),
));
}
crate::ImageClass::External => unimplemented!(),
},
_ => {
return Err(Error::UnsupportedArrayOfType(base));
Expand Down
1 change: 1 addition & 0 deletions naga/src/back/spv/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions naga/src/back/spv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ impl LocalImageType {
flags: make_flags(false, ImageTypeFlags::empty()),
image_format: format.into(),
},
crate::ImageClass::External => unimplemented!(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions naga/src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,7 @@ impl Writer {
self.request_image_format_capabilities(format.into())?;
false
}
crate::ImageClass::External => unimplemented!(),
};

match dim {
Expand Down
3 changes: 3 additions & 0 deletions naga/src/common/wgsl/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ where
"texture_storage_{dim_str}{arrayed_str}<{format_str}{access_str}>"
)?;
}
Ic::External => {
write!(out, "texture_external")?;
}
}
}
TypeInner::Scalar(scalar) => {
Expand Down
2 changes: 2 additions & 0 deletions naga/src/front/glsl/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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()),
Expand Down
9 changes: 6 additions & 3 deletions naga/src/front/wgsl/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions naga/src/front/wgsl/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions naga/src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,8 @@ pub enum ImageClass {
/// Multi-sampled depth image.
multi: bool,
},
/// External texture.
External,
/// Storage image.
Storage {
format: StorageFormat,
Expand Down
2 changes: 2 additions & 0 deletions naga/src/proc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,13 +383,15 @@ impl super::ImageClass {
match self {
crate::ImageClass::Sampled { multi, .. } | crate::ImageClass::Depth { multi } => multi,
crate::ImageClass::Storage { .. } => false,
crate::ImageClass::External => false,
}
}

pub const fn is_mipmapped(self) -> bool {
match self {
crate::ImageClass::Sampled { multi, .. } | crate::ImageClass::Depth { multi } => !multi,
crate::ImageClass::Storage { .. } => false,
crate::ImageClass::External => false,
}
}

Expand Down
4 changes: 4 additions & 0 deletions naga/src/proc/typifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion naga/src/valid/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
};
Expand Down Expand Up @@ -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:?}`"),
Expand Down
2 changes: 2 additions & 0 deletions naga/src/valid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,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;
}
}

Expand Down
3 changes: 3 additions & 0 deletions naga/src/valid/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,9 @@ impl super::Validator {
if arrayed && matches!(dim, crate::ImageDimension::Cube) {
self.require_type_capability(Capabilities::CUBE_ARRAY_TEXTURES)?;
}
if matches!(class, crate::ImageClass::External) {
self.require_type_capability(Capabilities::TEXTURE_EXTERNAL)?;
}
TypeInfo::new(
TypeFlags::ARGUMENT | TypeFlags::CREATION_RESOLVED,
Alignment::ONE,
Expand Down
2 changes: 2 additions & 0 deletions naga/tests/in/wgsl/texture-external.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
god_mode = true
targets = "IR | WGSL"
17 changes: 17 additions & 0 deletions naga/tests/in/wgsl/texture-external.wgsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@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 main() -> @location(0) vec4<f32> {
return test(tex);
}
Loading