diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index b5df8e1a18..ec4476cbdc 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::{ }; use rustc_span::def_id::DefId; use rustc_span::Span; +use rustc_span::DUMMY_SP; use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind}; use rustc_target::abi::{ Abi, Align, FieldsShape, LayoutOf, Primitive, Scalar, Size, TagEncoding, VariantIdx, Variants, @@ -323,11 +324,15 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { fn trans_type_impl<'tcx>( cx: &CodegenCx<'tcx>, - span: Span, + mut span: Span, ty: TyAndLayout<'tcx>, is_immediate: bool, ) -> Word { if let TyKind::Adt(adt, substs) = *ty.ty.kind() { + if span == DUMMY_SP { + span = cx.tcx.def_span(adt.did); + } + let attrs = AggregatedSpirvAttributes::parse(cx, cx.tcx.get_attrs(adt.did)); if let Some(intrinsic_type_attr) = attrs.intrinsic_type.map(|attr| attr.value) { diff --git a/crates/rustc_codegen_spirv/src/builder/ext_inst.rs b/crates/rustc_codegen_spirv/src/builder/ext_inst.rs index 26611fd5e6..9ce66ab9a3 100644 --- a/crates/rustc_codegen_spirv/src/builder/ext_inst.rs +++ b/crates/rustc_codegen_spirv/src/builder/ext_inst.rs @@ -1,6 +1,5 @@ use super::Builder; use crate::builder_spirv::{SpirvValue, SpirvValueExt}; -use crate::codegen_cx::CodegenCx; use rspirv::spirv::{CLOp, GLOp, Word}; use rspirv::{dr::Operand, spirv::Capability}; @@ -40,14 +39,26 @@ impl ExtInst { } } - pub fn import_integer_functions_2_intel<'tcx>(&mut self, cx: &CodegenCx<'tcx>) { + pub fn require_integer_functions_2_intel<'a, 'tcx>( + &mut self, + bx: &Builder<'a, 'tcx>, + to_zombie: Word, + ) { if !self.integer_functions_2_intel { - assert!(!cx.target.is_kernel()); + assert!(!bx.target.is_kernel()); self.integer_functions_2_intel = true; - cx.emit_global() - .extension("SPV_INTEL_shader_integer_functions2"); - cx.emit_global() - .capability(Capability::IntegerFunctions2INTEL); + if !bx + .builder + .has_capability(Capability::IntegerFunctions2INTEL) + { + bx.zombie(to_zombie, "capability IntegerFunctions2INTEL is required"); + } + if !bx + .builder + .has_extension("SPV_INTEL_shader_integer_functions2") + { + bx.zombie(to_zombie, "extension IntegerFunctions2INTEL is required"); + } } } } diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index e7ea98b587..c793840f84 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -362,34 +362,36 @@ impl<'a, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'tcx> { if self.target.is_kernel() { self.cl_op(CLOp::clz, ret_ty, [args[0].immediate()]) } else { - self.ext_inst - .borrow_mut() - .import_integer_functions_2_intel(self); - self.emit() + let result = self + .emit() .u_count_leading_zeros_intel( args[0].immediate().ty, None, args[0].immediate().def(self), ) - .unwrap() - .with_type(args[0].immediate().ty) + .unwrap(); + self.ext_inst + .borrow_mut() + .require_integer_functions_2_intel(self, result); + result.with_type(args[0].immediate().ty) } } sym::cttz | sym::cttz_nonzero => { if self.target.is_kernel() { self.cl_op(CLOp::ctz, ret_ty, [args[0].immediate()]) } else { - self.ext_inst - .borrow_mut() - .import_integer_functions_2_intel(self); - self.emit() + let result = self + .emit() .u_count_trailing_zeros_intel( args[0].immediate().ty, None, args[0].immediate().def(self), ) - .unwrap() - .with_type(args[0].immediate().ty) + .unwrap(); + self.ext_inst + .borrow_mut() + .require_integer_functions_2_intel(self, result); + result.with_type(args[0].immediate().ty) } } diff --git a/crates/rustc_codegen_spirv/src/builder_spirv.rs b/crates/rustc_codegen_spirv/src/builder_spirv.rs index 618b79208f..5feac314ce 100644 --- a/crates/rustc_codegen_spirv/src/builder_spirv.rs +++ b/crates/rustc_codegen_spirv/src/builder_spirv.rs @@ -350,10 +350,6 @@ impl BuilderSpirv { // The linker will always be ran on this module builder.capability(Capability::Linkage); - builder.capability(Capability::Int8); - builder.capability(Capability::Int16); - builder.capability(Capability::Int64); - builder.capability(Capability::Float64); let addressing_model = if target.is_kernel() { builder.capability(Capability::Addresses); @@ -425,6 +421,18 @@ impl BuilderSpirv { }) } + pub fn has_extension(&self, extension: &str) -> bool { + self.builder + .borrow() + .module_ref() + .extensions + .iter() + .any(|inst| { + inst.class.opcode == Op::Extension + && inst.operands[0].unwrap_literal_string() == extension + }) + } + pub fn select_function_by_id(&self, id: Word) -> BuilderCursor { let mut builder = self.builder.borrow_mut(); for (index, func) in builder.module_ref().functions.iter().enumerate() { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index 944d8ce80d..263546b707 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -96,12 +96,22 @@ impl<'tcx> CodegenCx<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, codegen_unit: &'tcx CodegenUnit<'tcx>) -> Self { let sym = Symbols::get(); - let features = tcx + let mut feature_names = tcx .sess .target_features .iter() .filter(|s| *s != &sym.bindless) - .map(|s| s.as_str().parse()) + .map(|s| s.as_str()) + .collect::>(); + + // target_features is a HashSet, not a Vec, so we need to sort to have deterministic + // compilation - otherwise, the order of capabilities in binaries depends on the iteration + // order of the hashset. Sort by the string, since that's easy. + feature_names.sort(); + + let features = feature_names + .into_iter() + .map(|s| s.parse()) .collect::>() .unwrap_or_else(|error| { tcx.sess.err(&error); @@ -221,6 +231,7 @@ impl<'tcx> CodegenCx<'tcx> { || self.tcx.crate_name(LOCAL_CRATE) == self.sym.spirv_std || self.tcx.crate_name(LOCAL_CRATE) == self.sym.libm || self.tcx.crate_name(LOCAL_CRATE) == self.sym.num_traits + || self.tcx.crate_name(LOCAL_CRATE) == self.sym.glam } // FIXME(eddyb) should this just be looking at `kernel_mode`? diff --git a/crates/rustc_codegen_spirv/src/linker/capability_computation.rs b/crates/rustc_codegen_spirv/src/linker/capability_computation.rs deleted file mode 100644 index 4276ed3ba1..0000000000 --- a/crates/rustc_codegen_spirv/src/linker/capability_computation.rs +++ /dev/null @@ -1,105 +0,0 @@ -use rspirv::dr::{Instruction, Module}; -use rspirv::spirv::{Capability, Op}; -use rustc_data_structures::fx::FxHashSet; - -pub fn remove_extra_capabilities(module: &mut Module) { - let used_capabilities = used_capabilities(module); - let removable_capabilities: FxHashSet = [ - Capability::Int8, - Capability::Int16, - Capability::Int64, - Capability::Float16, - Capability::Float64, - Capability::IntegerFunctions2INTEL, - Capability::DemoteToHelperInvocationEXT, - Capability::DerivativeControl, - ] - .iter() - .copied() - .collect(); - let to_remove = removable_capabilities - .difference(&used_capabilities) - .copied() - .collect(); - remove_capabilities(module, &to_remove); -} - -fn used_capabilities(module: &Module) -> FxHashSet { - let mut set = FxHashSet::default(); - for inst in module.all_inst_iter() { - set.extend(inst.class.capabilities); - match inst.class.opcode { - Op::TypeInt => match inst.operands[0].unwrap_literal_int32() { - 8 => { - set.insert(Capability::Int8); - } - 16 => { - set.insert(Capability::Int16); - } - 64 => { - set.insert(Capability::Int64); - } - _ => {} - }, - Op::TypeFloat => match inst.operands[0].unwrap_literal_int32() { - 16 => { - set.insert(Capability::Float16); - } - 64 => { - set.insert(Capability::Float64); - } - _ => {} - }, - _ => {} - } - } - set -} - -fn remove_capabilities(module: &mut Module, set: &FxHashSet) { - module.capabilities.retain(|inst| { - inst.class.opcode != Op::Capability || !set.contains(&inst.operands[0].unwrap_capability()) - }); -} - -// rspirv pulls its spec information from the latest version. However, we might not be compiling for -// the latest version. -// For example, we might run into this situation: -// OpCapability VulkanMemoryModel in SPIR-V v1.5 requires no extensions -// OpCapability VulkanMemoryModel in SPIR-V <= v1.4 requires OpExtension SPV_KHR_vulkan_memory_model -// rspirv uses SPIR-V v1.5 (as of now), and so it states that VulkanMemoryModel needs no extensions -// We're compiling for, say, SPIR-V 1.3, and ask rspirv if VulkanMemoryModel requires an extension -// It says no. We strip it. Things explode. -// So, this function is to encode any special version-specific rules that aren't in rspirv. -fn additional_extensions(module: &Module, inst: &Instruction) -> &'static [&'static str] { - if inst.class.opcode == Op::Capability { - let version = module.header.as_ref().unwrap().version(); - match inst.operands[0].unwrap_capability() { - Capability::VulkanMemoryModel if version < (1, 5) => &["SPV_KHR_vulkan_memory_model"], - Capability::RuntimeDescriptorArray if version < (1, 5) => { - &["SPV_EXT_descriptor_indexing"] - } - _ => &[], - } - } else { - &[] - } -} - -pub fn remove_extra_extensions(module: &mut Module) { - let set: FxHashSet<&str> = module - .all_inst_iter() - .flat_map(|inst| { - let extensions = inst.class.extensions.iter().copied(); - let operand_extensions = inst.operands.iter().flat_map(|op| op.required_extensions()); - let additional_extensions = additional_extensions(module, inst).iter().copied(); - extensions - .chain(operand_extensions) - .chain(additional_extensions) - }) - .collect(); - - module.extensions.retain(|inst| { - inst.class.opcode != Op::Extension || set.contains(inst.operands[0].unwrap_literal_string()) - }) -} diff --git a/crates/rustc_codegen_spirv/src/linker/import_export_link.rs b/crates/rustc_codegen_spirv/src/linker/import_export_link.rs index 0c05093c1d..a6a4088377 100644 --- a/crates/rustc_codegen_spirv/src/linker/import_export_link.rs +++ b/crates/rustc_codegen_spirv/src/linker/import_export_link.rs @@ -56,7 +56,7 @@ fn find_import_export_pairs_and_killed_params( }; let import_type = *type_map.get(&import_id).expect("Unexpected op"); // Make sure the import/export pair has the same type. - check_tys_equal(sess, name, import_type, export_type)?; + check_tys_equal(sess, module, name, import_type, export_type)?; rewrite_rules.insert(import_id, export_id); if let Some(params) = fn_parameters.get(&import_id) { for ¶m in params { @@ -108,11 +108,56 @@ fn fn_parameters(module: &Module) -> FxHashMap> { .collect() } -fn check_tys_equal(sess: &Session, name: &str, import_type: Word, export_type: Word) -> Result<()> { +fn check_tys_equal( + sess: &Session, + module: &Module, + name: &str, + import_type: Word, + export_type: Word, +) -> Result<()> { if import_type == export_type { Ok(()) } else { - sess.err(&format!("Types mismatch for {:?}", name)); + // We have an error. It's okay to do something really slow now to report the error. + use std::fmt::Write; + let ty_defs = module + .types_global_values + .iter() + .filter_map(|inst| Some((inst.result_id?, inst))) + .collect(); + fn format_ty(ty_defs: &FxHashMap, ty: Word, buf: &mut String) { + match ty_defs.get(&ty) { + Some(def) => { + write!(buf, "({}", def.class.opname).unwrap(); + if let Some(result_type) = def.result_type { + write!(buf, " {}", result_type).unwrap(); + } + for op in &def.operands { + if let Some(id) = op.id_ref_any() { + write!(buf, " ").unwrap(); + format_ty(ty_defs, id, buf); + } + } + write!(buf, ")").unwrap(); + } + None => write!(buf, "{}", ty).unwrap(), + } + } + fn format_ty_(ty_defs: &FxHashMap, ty: Word) -> String { + let mut result = String::new(); + format_ty(ty_defs, ty, &mut result); + result + } + sess.struct_err(&format!("Types mismatch for {:?}", name)) + .note(&format!( + "import type: {}", + format_ty_(&ty_defs, import_type) + )) + .note(&format!( + "export type: {}", + format_ty_(&ty_defs, export_type) + )) + .emit(); Err(ErrorReported) } } diff --git a/crates/rustc_codegen_spirv/src/linker/mod.rs b/crates/rustc_codegen_spirv/src/linker/mod.rs index 386e75fa85..40c440e226 100644 --- a/crates/rustc_codegen_spirv/src/linker/mod.rs +++ b/crates/rustc_codegen_spirv/src/linker/mod.rs @@ -1,7 +1,6 @@ #[cfg(test)] mod test; -mod capability_computation; mod dce; mod duplicates; mod import_export_link; @@ -292,11 +291,6 @@ pub fn link(sess: &Session, mut inputs: Vec, opts: &Options) -> Result, + extensions: Vec, } impl SpirvBuilder { @@ -123,6 +126,8 @@ impl SpirvBuilder { target: target.into(), bindless: false, multimodule: false, + capabilities: Vec::new(), + extensions: Vec::new(), } } @@ -153,6 +158,20 @@ impl SpirvBuilder { self } + /// Adds a capability to the SPIR-V module. Checking if a capability is enabled in code can be + /// done via `#[cfg(target_feature = "TheCapability")]`. + pub fn capability(mut self, capability: Capability) -> Self { + self.capabilities.push(capability); + self + } + + /// Adds an extension to the SPIR-V module. Checking if an extension is enabled in code can be + /// done via `#[cfg(target_feature = "ext:the_extension")]`. + pub fn extension(mut self, extension: impl Into) -> Self { + self.extensions.push(extension.into()); + self + } + /// Builds the module. If `print_metadata` is true, you usually don't have to inspect the path /// in the result, as the environment variable for the path to the module will already be set. pub fn build(self) -> Result { @@ -234,8 +253,10 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result { let mut target_features = Vec::new(); if builder.bindless { - target_features.push("+bindless"); + target_features.push("+bindless".into()); } + target_features.extend(builder.capabilities.iter().map(|cap| format!("+{:?}", cap))); + target_features.extend(builder.extensions.iter().map(|ext| format!("+ext:{}", ext))); let feature_flag = if target_features.is_empty() { String::new() diff --git a/crates/spirv-std/shared/src/image_params.rs b/crates/spirv-std/shared/src/image_params.rs index a51bf4b5aa..e0c7f6583a 100644 --- a/crates/spirv-std/shared/src/image_params.rs +++ b/crates/spirv-std/shared/src/image_params.rs @@ -1,3 +1,7 @@ +// Hack: u8 requires the Int8 capability, so instead of compiling this to a u8, compile it to a +// u32. It's a little less efficient, but doesn't require the Int8 cap (and Arrayed values +// shouldn't be stored in memory anyway, so it's no less memory used) +#[repr(u32)] /// The access permissions for the image. #[derive(Copy, Clone, PartialEq, Eq)] pub enum AccessQualifier { @@ -10,6 +14,7 @@ pub enum AccessQualifier { } /// Whether the image uses arrayed content. +#[repr(u32)] #[derive(Copy, Clone, PartialEq, Eq)] pub enum Arrayed { /// The image uses not arrayed content. @@ -18,6 +23,7 @@ pub enum Arrayed { True = 1, } +#[cfg(any(not(target_arch = "spirv"), target_feature = "Int8"))] impl From for Arrayed { fn from(val: bool) -> Self { if val { @@ -29,6 +35,7 @@ impl From for Arrayed { } /// The dimension of the image. +#[repr(u32)] #[derive(Copy, Clone, PartialEq, Eq)] pub enum Dimensionality { /// 1D @@ -52,6 +59,7 @@ pub enum Dimensionality { /// type. /// /// [depth]: https://en.wikipedia.org/wiki/Depth_map +#[repr(u32)] #[derive(Copy, Clone, PartialEq, Eq)] pub enum ImageDepth { /// Indicates that the image does not contain depth information. @@ -63,6 +71,7 @@ pub enum ImageDepth { Unknown = 2, } +#[cfg(any(not(target_arch = "spirv"), target_feature = "Int8"))] impl From> for ImageDepth { fn from(val: Option) -> Self { match val { @@ -73,6 +82,7 @@ impl From> for ImageDepth { } } +#[cfg(any(not(target_arch = "spirv"), target_feature = "Int8"))] impl From for ImageDepth { fn from(val: bool) -> Self { match val { @@ -83,6 +93,7 @@ impl From for ImageDepth { } /// Whether the image uses arrayed content. +#[repr(u32)] #[derive(Copy, Clone, PartialEq, Eq)] pub enum Multisampled { /// The image contains single-sampled content. @@ -91,6 +102,7 @@ pub enum Multisampled { True = 1, } +#[cfg(any(not(target_arch = "spirv"), target_feature = "Int8"))] impl From for Multisampled { fn from(val: bool) -> Self { if val { @@ -102,6 +114,7 @@ impl From for Multisampled { } /// Whether or not the image will be accessed in combination with a sampler. +#[repr(u32)] #[derive(Copy, Clone, PartialEq, Eq)] pub enum Sampled { /// Indicates that it is not known ahead of time whether the image will use @@ -113,6 +126,7 @@ pub enum Sampled { No = 2, } +#[cfg(any(not(target_arch = "spirv"), target_feature = "Int8"))] impl From> for Sampled { fn from(val: Option) -> Self { match val { @@ -123,6 +137,7 @@ impl From> for Sampled { } } +#[cfg(any(not(target_arch = "spirv"), target_feature = "Int8"))] impl From for Sampled { fn from(val: bool) -> Self { match val { @@ -133,6 +148,7 @@ impl From for Sampled { } /// The underlying internal representation of the image. +#[repr(u32)] #[derive(PartialEq, Eq)] pub enum ImageFormat { /// Representation not known at compile time. diff --git a/examples/runners/wgpu/builder/src/main.rs b/examples/runners/wgpu/builder/src/main.rs index bb84c6f636..77211469e7 100644 --- a/examples/runners/wgpu/builder/src/main.rs +++ b/examples/runners/wgpu/builder/src/main.rs @@ -1,11 +1,19 @@ -use spirv_builder::SpirvBuilder; +use spirv_builder::{Capability, SpirvBuilder}; use std::env; use std::error::Error; use std::fs; use std::path::Path; -fn build_shader(path_to_create: &str, codegen_names: bool) -> Result<(), Box> { - let result = SpirvBuilder::new(path_to_create, "spirv-unknown-vulkan1.0").build()?; +fn build_shader( + path_to_create: &str, + codegen_names: bool, + caps: &[Capability], +) -> Result<(), Box> { + let mut builder = SpirvBuilder::new(path_to_create, "spirv-unknown-vulkan1.0"); + for &cap in caps { + builder = builder.capability(cap); + } + let result = builder.build()?; if codegen_names { let out_dir = env::var_os("OUT_DIR").unwrap(); let dest_path = Path::new(&out_dir).join("entry_points.rs"); @@ -15,9 +23,13 @@ fn build_shader(path_to_create: &str, codegen_names: bool) -> Result<(), Box Result<(), Box> { - build_shader("../../shaders/sky-shader", true)?; - build_shader("../../shaders/simplest-shader", false)?; - build_shader("../../shaders/compute-shader", false)?; - build_shader("../../shaders/mouse-shader", false)?; + build_shader("../../shaders/sky-shader", true, &[])?; + build_shader("../../shaders/simplest-shader", false, &[])?; + build_shader("../../shaders/compute-shader", false, &[])?; + build_shader( + "../../shaders/mouse-shader", + false, + &[Capability::Int8, Capability::Int16, Capability::Int64], + )?; Ok(()) } diff --git a/examples/runners/wgpu/src/lib.rs b/examples/runners/wgpu/src/lib.rs index 3faecc259d..72769e159f 100644 --- a/examples/runners/wgpu/src/lib.rs +++ b/examples/runners/wgpu/src/lib.rs @@ -59,7 +59,7 @@ pub enum RustGPUShader { fn shader_module(shader: RustGPUShader) -> wgpu::ShaderModuleDescriptor<'static> { #[cfg(not(any(target_os = "android", target_arch = "wasm32")))] { - use spirv_builder::SpirvBuilder; + use spirv_builder::{Capability, SpirvBuilder}; use std::borrow::Cow; use std::path::{Path, PathBuf}; // Hack: spirv_builder builds into a custom directory if running under cargo, to not @@ -70,11 +70,14 @@ fn shader_module(shader: RustGPUShader) -> wgpu::ShaderModuleDescriptor<'static> // under cargo by setting these environment variables. std::env::set_var("OUT_DIR", env!("OUT_DIR")); std::env::set_var("PROFILE", env!("PROFILE")); - let crate_name = match shader { - RustGPUShader::Simplest => "sky-shader", - RustGPUShader::Sky => "simplest-shader", - RustGPUShader::Compute => "compute-shader", - RustGPUShader::Mouse => "mouse-shader", + let (crate_name, capabilities): (_, &[Capability]) = match shader { + RustGPUShader::Simplest => ("sky-shader", &[]), + RustGPUShader::Sky => ("simplest-shader", &[]), + RustGPUShader::Compute => ("compute-shader", &[]), + RustGPUShader::Mouse => ( + "mouse-shader", + &[Capability::Int8, Capability::Int16, Capability::Int64], + ), }; let manifest_dir = env!("CARGO_MANIFEST_DIR"); let crate_path = [ @@ -87,10 +90,12 @@ fn shader_module(shader: RustGPUShader) -> wgpu::ShaderModuleDescriptor<'static> .iter() .copied() .collect::(); - let compile_result = SpirvBuilder::new(crate_path, "spirv-unknown-vulkan1.0") - .print_metadata(false) - .build() - .unwrap(); + let mut builder = + SpirvBuilder::new(crate_path, "spirv-unknown-vulkan1.0").print_metadata(false); + for &cap in capabilities { + builder = builder.capability(cap); + } + let compile_result = builder.build().unwrap(); let module_path = compile_result.module.unwrap_single(); let data = std::fs::read(module_path).unwrap(); let spirv = wgpu::util::make_spirv(&data); diff --git a/tests/src/main.rs b/tests/src/main.rs index dd0b0ef618..90d103b91b 100644 --- a/tests/src/main.rs +++ b/tests/src/main.rs @@ -299,6 +299,7 @@ fn rust_flags(codegen_backend_path: &Path) -> String { "-Cdebug-assertions=off", "-Cdebuginfo=2", "-Cembed-bitcode=no", + "-Ctarget-feature=+Int8,+Int16,+Int64,+Float64", ] .join(" ") } diff --git a/tests/ui/dis/asm_op_decorate.stderr b/tests/ui/dis/asm_op_decorate.stderr index 119398b2ee..11f4f039a0 100644 --- a/tests/ui/dis/asm_op_decorate.stderr +++ b/tests/ui/dis/asm_op_decorate.stderr @@ -1,3 +1,7 @@ +OpCapability Float64 +OpCapability Int16 +OpCapability Int64 +OpCapability Int8 OpCapability RuntimeDescriptorArray OpCapability Shader OpExtension "SPV_EXT_descriptor_indexing" diff --git a/tests/ui/dis/custom_entry_point.stderr b/tests/ui/dis/custom_entry_point.stderr index 240b113e8a..43683e3089 100644 --- a/tests/ui/dis/custom_entry_point.stderr +++ b/tests/ui/dis/custom_entry_point.stderr @@ -1,3 +1,7 @@ +OpCapability Float64 +OpCapability Int16 +OpCapability Int64 +OpCapability Int8 OpCapability Shader OpMemoryModel Logical Simple OpEntryPoint Fragment %1 "hello_world" diff --git a/tests/ui/image/issue_527.rs b/tests/ui/image/issue_527.rs index d9fffb26cb..7bcc7a30ae 100644 --- a/tests/ui/image/issue_527.rs +++ b/tests/ui/image/issue_527.rs @@ -1,5 +1,4 @@ // build-pass -// // compile-flags: -C target-feature=+StorageImageWriteWithoutFormat use glam::*;