1use alloc::{
72 format,
73 string::{String, ToString},
74 vec::Vec,
75};
76use core::fmt::{Error as FmtError, Write};
77
78use crate::{arena::Handle, back::TaskDispatchLimits, ir, proc::index, valid::ModuleInfo};
79
80mod keywords;
81mod mesh_shader;
82mod ray;
83pub mod sampler;
84mod writer;
85
86pub use writer::Writer;
87
88pub type Slot = u8;
89pub type InlineSamplerIndex = u8;
90
91#[derive(Clone, Debug, PartialEq, Eq, Hash)]
92#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
93#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
94pub enum BindSamplerTarget {
95 Resource(Slot),
96 Inline(InlineSamplerIndex),
97}
98
99#[derive(Clone, Debug, PartialEq, Eq, Hash)]
105#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
106#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
107pub struct BindExternalTextureTarget {
108 pub planes: [Slot; 3],
109 pub params: Slot,
110}
111
112#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
113#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
114#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
115#[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(default))]
116pub struct BindTarget {
117 pub buffer: Option<Slot>,
118 pub texture: Option<Slot>,
119 pub sampler: Option<BindSamplerTarget>,
120 pub external_texture: Option<BindExternalTextureTarget>,
121 pub mutable: bool,
122}
123
124#[cfg(feature = "deserialize")]
125#[derive(serde::Deserialize)]
126struct BindingMapSerialization {
127 resource_binding: crate::ResourceBinding,
128 bind_target: BindTarget,
129}
130
131#[cfg(feature = "deserialize")]
132fn deserialize_binding_map<'de, D>(deserializer: D) -> Result<BindingMap, D::Error>
133where
134 D: serde::Deserializer<'de>,
135{
136 use serde::Deserialize;
137
138 let vec = Vec::<BindingMapSerialization>::deserialize(deserializer)?;
139 let mut map = BindingMap::default();
140 for item in vec {
141 map.insert(item.resource_binding, item.bind_target);
142 }
143 Ok(map)
144}
145
146pub type BindingMap = alloc::collections::BTreeMap<crate::ResourceBinding, BindTarget>;
148
149#[derive(Clone, Debug, Default, Hash, Eq, PartialEq)]
150#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
151#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
152#[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(default))]
153pub struct EntryPointResources {
154 #[cfg_attr(
155 feature = "deserialize",
156 serde(deserialize_with = "deserialize_binding_map")
157 )]
158 pub resources: BindingMap,
159
160 pub immediates_buffer: Option<Slot>,
161
162 pub sizes_buffer: Option<Slot>,
166}
167
168pub type EntryPointResourceMap = alloc::collections::BTreeMap<String, EntryPointResources>;
169
170enum ResolvedBinding {
171 BuiltIn(crate::BuiltIn),
172 Attribute(u32),
173 Color {
174 location: u32,
175 blend_src: Option<u32>,
176 },
177 User {
178 prefix: &'static str,
179 index: u32,
180 interpolation: Option<ResolvedInterpolation>,
181 },
182 Resource(BindTarget),
183 Payload,
184}
185
186#[derive(Copy, Clone)]
187enum ResolvedInterpolation {
188 CenterPerspective,
189 CenterNoPerspective,
190 CentroidPerspective,
191 CentroidNoPerspective,
192 SamplePerspective,
193 SampleNoPerspective,
194 Flat,
195 PerVertex,
196}
197
198#[derive(Debug, thiserror::Error)]
201pub enum Error {
202 #[error(transparent)]
203 Format(#[from] FmtError),
204 #[error("bind target {0:?} is empty")]
205 UnimplementedBindTarget(BindTarget),
206 #[error("composing of {0:?} is not implemented yet")]
207 UnsupportedCompose(Handle<crate::Type>),
208 #[error("operation {0:?} is not implemented yet")]
209 UnsupportedBinaryOp(crate::BinaryOperator),
210 #[error("standard function '{0}' is not implemented yet")]
211 UnsupportedCall(String),
212 #[error("feature '{0}' is not implemented yet")]
213 FeatureNotImplemented(String),
214 #[error("internal naga error: module should not have validated: {0}")]
215 GenericValidation(String),
216 #[error("BuiltIn {0:?} is not supported")]
217 UnsupportedBuiltIn(crate::BuiltIn),
218 #[error("capability {0:?} is not supported")]
219 CapabilityNotSupported(crate::valid::Capabilities),
220 #[error("attribute '{0}' is not supported for target MSL version")]
221 UnsupportedAttribute(String),
222 #[error("function '{0}' is not supported for target MSL version")]
223 UnsupportedFunction(String),
224 #[error("can not use writable storage buffers in fragment stage prior to MSL 1.2")]
225 UnsupportedWritableStorageBuffer,
226 #[error("can not use writable storage textures in {0:?} stage prior to MSL 1.2")]
227 UnsupportedWritableStorageTexture(ir::ShaderStage),
228 #[error("can not use read-write storage textures prior to MSL 1.2")]
229 UnsupportedRWStorageTexture,
230 #[error("array of '{0}' is not supported for target MSL version")]
231 UnsupportedArrayOf(String),
232 #[error("array of type '{0:?}' is not supported")]
233 UnsupportedArrayOfType(Handle<crate::Type>),
234 #[error("ray tracing is not supported prior to MSL 2.4")]
235 UnsupportedRayTracing,
236 #[error("cooperative matrix is not supported prior to MSL 2.3")]
237 UnsupportedCooperativeMatrix,
238 #[error("overrides should not be present at this stage")]
239 Override,
240 #[error("bitcasting to {0:?} is not supported")]
241 UnsupportedBitCast(crate::TypeInner),
242 #[error(transparent)]
243 ResolveArraySizeError(#[from] crate::proc::ResolveArraySizeError),
244 #[error("entry point with stage {0:?} and name '{1}' not found")]
245 EntryPointNotFound(ir::ShaderStage, String),
246 #[error("Cannot use mesh shader syntax prior to MSL 3.0")]
247 UnsupportedMeshShader,
248 #[error("Per vertex fragment inputs are not supported prior to MSL 4.0")]
249 PerVertexNotSupported,
250}
251
252#[derive(Clone, Debug, PartialEq, thiserror::Error)]
253#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
254#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
255pub enum EntryPointError {
256 #[error("global '{0}' doesn't have a binding")]
257 MissingBinding(String),
258 #[error("mapping of {0:?} is missing")]
259 MissingBindTarget(crate::ResourceBinding),
260 #[error("mapping for immediates is missing")]
261 MissingImmediateData,
262 #[error("mapping for sizes buffer is missing")]
263 MissingSizesBuffer,
264}
265
266#[derive(Clone, Copy, Debug)]
275enum LocationMode {
276 VertexInput,
278
279 VertexOutput,
281
282 FragmentInput,
284
285 FragmentOutput,
287
288 MeshOutput,
290
291 Uniform,
293}
294
295#[derive(Clone, Debug, Hash, PartialEq, Eq)]
296#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
297#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
298#[cfg_attr(feature = "deserialize", serde(default))]
299pub struct Options {
300 pub lang_version: (u8, u8),
302 pub per_entry_point_map: EntryPointResourceMap,
304 pub inline_samplers: Vec<sampler::InlineSampler>,
306 pub spirv_cross_compatibility: bool,
308 pub fake_missing_bindings: bool,
310 pub bounds_check_policies: index::BoundsCheckPolicies,
312 pub zero_initialize_workgroup_memory: bool,
314 pub force_loop_bounding: bool,
317 pub task_dispatch_limits: Option<TaskDispatchLimits>,
320 pub mesh_shader_primitive_indices_clamp: bool,
322 pub emit_int_div_checks: bool,
327}
328
329impl Default for Options {
330 fn default() -> Self {
331 Options {
332 lang_version: (1, 0),
333 per_entry_point_map: EntryPointResourceMap::default(),
334 inline_samplers: Vec::new(),
335 spirv_cross_compatibility: false,
336 fake_missing_bindings: true,
337 bounds_check_policies: index::BoundsCheckPolicies::default(),
338 zero_initialize_workgroup_memory: true,
339 force_loop_bounding: true,
340 task_dispatch_limits: None,
341 mesh_shader_primitive_indices_clamp: true,
342 emit_int_div_checks: true,
343 }
344 }
345}
346
347#[repr(u32)]
350#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
351#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
352#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
353pub enum VertexFormat {
354 Uint8 = 0,
356 Uint8x2 = 1,
358 Uint8x4 = 2,
360 Sint8 = 3,
362 Sint8x2 = 4,
364 Sint8x4 = 5,
366 Unorm8 = 6,
368 Unorm8x2 = 7,
370 Unorm8x4 = 8,
372 Snorm8 = 9,
374 Snorm8x2 = 10,
376 Snorm8x4 = 11,
378 Uint16 = 12,
380 Uint16x2 = 13,
382 Uint16x4 = 14,
384 Sint16 = 15,
386 Sint16x2 = 16,
388 Sint16x4 = 17,
390 Unorm16 = 18,
392 Unorm16x2 = 19,
394 Unorm16x4 = 20,
396 Snorm16 = 21,
398 Snorm16x2 = 22,
400 Snorm16x4 = 23,
402 Float16 = 24,
404 Float16x2 = 25,
406 Float16x4 = 26,
408 Float32 = 27,
410 Float32x2 = 28,
412 Float32x3 = 29,
414 Float32x4 = 30,
416 Uint32 = 31,
418 Uint32x2 = 32,
420 Uint32x3 = 33,
422 Uint32x4 = 34,
424 Sint32 = 35,
426 Sint32x2 = 36,
428 Sint32x3 = 37,
430 Sint32x4 = 38,
432 #[cfg_attr(
434 any(feature = "serialize", feature = "deserialize"),
435 serde(rename = "unorm10-10-10-2")
436 )]
437 Unorm10_10_10_2 = 43,
438 #[cfg_attr(
440 any(feature = "serialize", feature = "deserialize"),
441 serde(rename = "unorm8x4-bgra")
442 )]
443 Unorm8x4Bgra = 44,
444}
445
446#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
448#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
449#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
450pub enum VertexBufferStepMode {
451 Constant,
452 #[default]
453 ByVertex,
454 ByInstance,
455}
456
457#[derive(Debug, Clone, PartialEq, Eq, Hash)]
460#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
461#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
462pub struct AttributeMapping {
463 pub shader_location: u32,
465 pub offset: u32,
467 pub format: VertexFormat,
473}
474
475#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
478#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
479#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
480pub struct VertexBufferMapping {
481 pub id: u32,
483 pub stride: u32,
485 pub step_mode: VertexBufferStepMode,
487 pub attributes: Vec<AttributeMapping>,
489}
490
491#[derive(Debug, Default, Clone)]
493#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
494#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
495#[cfg_attr(feature = "deserialize", serde(default))]
496pub struct PipelineOptions {
497 pub entry_point: Option<(ir::ShaderStage, String)>,
505
506 pub allow_and_force_point_size: bool,
513
514 pub vertex_pulling_transform: bool,
522
523 pub vertex_buffer_mappings: Vec<VertexBufferMapping>,
526}
527
528impl Options {
529 fn resolve_local_binding(
530 &self,
531 binding: &crate::Binding,
532 mode: LocationMode,
533 ) -> Result<ResolvedBinding, Error> {
534 match *binding {
535 crate::Binding::BuiltIn(mut built_in) => {
536 match built_in {
537 crate::BuiltIn::Position { ref mut invariant } => {
538 if *invariant && self.lang_version < (2, 1) {
539 return Err(Error::UnsupportedAttribute("invariant".to_string()));
540 }
541
542 if !matches!(mode, LocationMode::VertexOutput) {
545 *invariant = false;
546 }
547 }
548 crate::BuiltIn::BaseInstance if self.lang_version < (1, 2) => {
549 return Err(Error::UnsupportedAttribute("base_instance".to_string()));
550 }
551 crate::BuiltIn::InstanceIndex if self.lang_version < (1, 2) => {
552 return Err(Error::UnsupportedAttribute("instance_id".to_string()));
553 }
554 crate::BuiltIn::PrimitiveIndex if self.lang_version < (2, 3) => {
557 return Err(Error::UnsupportedAttribute("primitive_id".to_string()));
558 }
559 crate::BuiltIn::ViewIndex if self.lang_version < (2, 2) => {
563 return Err(Error::UnsupportedAttribute("amplification_id".to_string()));
564 }
565 crate::BuiltIn::Barycentric { .. } if self.lang_version < (2, 3) => {
568 return Err(Error::UnsupportedAttribute("barycentric_coord".to_string()));
569 }
570 _ => {}
571 }
572
573 Ok(ResolvedBinding::BuiltIn(built_in))
574 }
575 crate::Binding::Location {
576 location,
577 interpolation,
578 sampling,
579 blend_src,
580 per_primitive,
581 } => match mode {
582 LocationMode::VertexInput => Ok(ResolvedBinding::Attribute(location)),
583 LocationMode::FragmentOutput => {
584 if blend_src.is_some() && self.lang_version < (1, 2) {
585 return Err(Error::UnsupportedAttribute("blend_src".to_string()));
586 }
587 Ok(ResolvedBinding::Color {
588 location,
589 blend_src,
590 })
591 }
592 LocationMode::VertexOutput
593 | LocationMode::FragmentInput
594 | LocationMode::MeshOutput => {
595 Ok(ResolvedBinding::User {
596 prefix: if self.spirv_cross_compatibility {
597 "locn"
598 } else {
599 "loc"
600 },
601 index: location,
602 interpolation: {
603 let interpolation = interpolation.unwrap();
607 let sampling = sampling.unwrap_or(crate::Sampling::Center);
608 Some(ResolvedInterpolation::from_binding(
609 interpolation,
610 sampling,
611 per_primitive,
612 ))
613 },
614 })
615 }
616 LocationMode::Uniform => Err(Error::GenericValidation(format!(
617 "Unexpected Binding::Location({location}) for the Uniform mode"
618 ))),
619 },
620 }
621 }
622
623 fn get_entry_point_resources(&self, ep: &crate::EntryPoint) -> Option<&EntryPointResources> {
624 self.per_entry_point_map.get(&ep.name)
625 }
626
627 fn get_resource_binding_target(
628 &self,
629 ep: &crate::EntryPoint,
630 res_binding: &crate::ResourceBinding,
631 ) -> Option<&BindTarget> {
632 self.get_entry_point_resources(ep)
633 .and_then(|res| res.resources.get(res_binding))
634 }
635
636 fn resolve_resource_binding(
637 &self,
638 ep: &crate::EntryPoint,
639 res_binding: &crate::ResourceBinding,
640 ) -> Result<ResolvedBinding, EntryPointError> {
641 let target = self.get_resource_binding_target(ep, res_binding);
642 match target {
643 Some(target) => Ok(ResolvedBinding::Resource(target.clone())),
644 None if self.fake_missing_bindings => Ok(ResolvedBinding::User {
645 prefix: "fake",
646 index: 0,
647 interpolation: None,
648 }),
649 None => Err(EntryPointError::MissingBindTarget(*res_binding)),
650 }
651 }
652
653 fn resolve_immediates(
654 &self,
655 ep: &crate::EntryPoint,
656 ) -> Result<ResolvedBinding, EntryPointError> {
657 let slot = self
658 .get_entry_point_resources(ep)
659 .and_then(|res| res.immediates_buffer);
660 match slot {
661 Some(slot) => Ok(ResolvedBinding::Resource(BindTarget {
662 buffer: Some(slot),
663 ..Default::default()
664 })),
665 None if self.fake_missing_bindings => Ok(ResolvedBinding::User {
666 prefix: "fake",
667 index: 0,
668 interpolation: None,
669 }),
670 None => Err(EntryPointError::MissingImmediateData),
671 }
672 }
673
674 fn resolve_sizes_buffer(
675 &self,
676 ep: &crate::EntryPoint,
677 ) -> Result<ResolvedBinding, EntryPointError> {
678 let slot = self
679 .get_entry_point_resources(ep)
680 .and_then(|res| res.sizes_buffer);
681 match slot {
682 Some(slot) => Ok(ResolvedBinding::Resource(BindTarget {
683 buffer: Some(slot),
684 ..Default::default()
685 })),
686 None if self.fake_missing_bindings => Ok(ResolvedBinding::User {
687 prefix: "fake",
688 index: 0,
689 interpolation: None,
690 }),
691 None => Err(EntryPointError::MissingSizesBuffer),
692 }
693 }
694}
695
696impl ResolvedBinding {
697 fn as_inline_sampler<'a>(&self, options: &'a Options) -> Option<&'a sampler::InlineSampler> {
698 match *self {
699 Self::Resource(BindTarget {
700 sampler: Some(BindSamplerTarget::Inline(index)),
701 ..
702 }) => Some(&options.inline_samplers[index as usize]),
703 _ => None,
704 }
705 }
706
707 fn try_fmt<W: Write>(&self, out: &mut W) -> Result<(), Error> {
708 write!(out, " [[")?;
709 match *self {
710 Self::BuiltIn(built_in) => {
711 use crate::BuiltIn as Bi;
712 let name = match built_in {
713 Bi::Position { invariant: false } => "position",
714 Bi::Position { invariant: true } => "position, invariant",
715 Bi::ViewIndex => "amplification_id",
716 Bi::BaseInstance => "base_instance",
718 Bi::BaseVertex => "base_vertex",
719 Bi::ClipDistances => "clip_distance",
720 Bi::InstanceIndex => "instance_id",
721 Bi::PointSize => "point_size",
722 Bi::VertexIndex => "vertex_id",
723 Bi::FragDepth => "depth(any)",
725 Bi::PointCoord => "point_coord",
726 Bi::FrontFacing => "front_facing",
727 Bi::PrimitiveIndex => "primitive_id",
728 Bi::Barycentric { perspective: true } => "barycentric_coord",
729 Bi::Barycentric { perspective: false } => {
730 "barycentric_coord, center_no_perspective"
731 }
732 Bi::SampleIndex => "sample_id",
733 Bi::SampleMask => "sample_mask",
734 Bi::GlobalInvocationId => "thread_position_in_grid",
736 Bi::LocalInvocationId => "thread_position_in_threadgroup",
737 Bi::LocalInvocationIndex => "thread_index_in_threadgroup",
738 Bi::WorkGroupId => "threadgroup_position_in_grid",
739 Bi::WorkGroupSize => "dispatch_threads_per_threadgroup",
740 Bi::NumWorkGroups => "threadgroups_per_grid",
741 Bi::NumSubgroups => "simdgroups_per_threadgroup",
743 Bi::SubgroupId => "simdgroup_index_in_threadgroup",
744 Bi::SubgroupSize => "threads_per_simdgroup",
745 Bi::SubgroupInvocationId => "thread_index_in_simdgroup",
746 Bi::CullDistance | Bi::DrawIndex => {
747 return Err(Error::UnsupportedBuiltIn(built_in))
748 }
749 Bi::CullPrimitive => "primitive_culled",
750 Bi::PointIndex | Bi::LineIndices | Bi::TriangleIndices => unimplemented!(),
752 Bi::MeshTaskSize
755 | Bi::VertexCount
756 | Bi::PrimitiveCount
757 | Bi::Vertices
758 | Bi::Primitives
759 | Bi::RayInvocationId
760 | Bi::NumRayInvocations
761 | Bi::InstanceCustomData
762 | Bi::GeometryIndex
763 | Bi::WorldRayOrigin
764 | Bi::WorldRayDirection
765 | Bi::ObjectRayOrigin
766 | Bi::ObjectRayDirection
767 | Bi::RayTmin
768 | Bi::RayTCurrentMax
769 | Bi::ObjectToWorld
770 | Bi::WorldToObject
771 | Bi::HitKind => unreachable!(),
772 };
773 write!(out, "{name}")?;
774 }
775 Self::Attribute(index) => write!(out, "attribute({index})")?,
776 Self::Color {
777 location,
778 blend_src,
779 } => {
780 if let Some(blend_src) = blend_src {
781 write!(out, "color({location}) index({blend_src})")?
782 } else {
783 write!(out, "color({location})")?
784 }
785 }
786 Self::User {
787 prefix,
788 index,
789 interpolation,
790 } => {
791 write!(out, "user({prefix}{index})")?;
792 if let Some(interpolation) = interpolation {
793 write!(out, ", ")?;
794 interpolation.try_fmt(out)?;
795 }
796 }
797 Self::Resource(ref target) => {
798 if let Some(id) = target.buffer {
799 write!(out, "buffer({id})")?;
800 } else if let Some(id) = target.texture {
801 write!(out, "texture({id})")?;
802 } else if let Some(BindSamplerTarget::Resource(id)) = target.sampler {
803 write!(out, "sampler({id})")?;
804 } else {
805 return Err(Error::UnimplementedBindTarget(target.clone()));
806 }
807 }
808 Self::Payload => write!(out, "payload")?,
809 }
810 write!(out, "]]")?;
811 Ok(())
812 }
813}
814
815impl ResolvedInterpolation {
816 const fn from_binding(
817 interpolation: crate::Interpolation,
818 sampling: crate::Sampling,
819 per_primitive: bool,
820 ) -> Self {
821 use crate::Interpolation as I;
822 use crate::Sampling as S;
823
824 if per_primitive {
825 return Self::Flat;
826 }
827
828 match (interpolation, sampling) {
829 (I::Perspective, S::Center) => Self::CenterPerspective,
830 (I::Perspective, S::Centroid) => Self::CentroidPerspective,
831 (I::Perspective, S::Sample) => Self::SamplePerspective,
832 (I::Linear, S::Center) => Self::CenterNoPerspective,
833 (I::Linear, S::Centroid) => Self::CentroidNoPerspective,
834 (I::Linear, S::Sample) => Self::SampleNoPerspective,
835 (I::Flat, _) => Self::Flat,
836 (I::PerVertex, S::Center) => Self::PerVertex,
837 _ => unreachable!(),
838 }
839 }
840
841 fn try_fmt<W: Write>(self, out: &mut W) -> Result<(), Error> {
842 let identifier = match self {
843 Self::CenterPerspective => "center_perspective",
844 Self::CenterNoPerspective => "center_no_perspective",
845 Self::CentroidPerspective => "centroid_perspective",
846 Self::CentroidNoPerspective => "centroid_no_perspective",
847 Self::SamplePerspective => "sample_perspective",
848 Self::SampleNoPerspective => "sample_no_perspective",
849 Self::Flat => "flat",
850 Self::PerVertex => unreachable!(),
851 };
852 out.write_str(identifier)?;
853 Ok(())
854 }
855}
856
857struct EntryPointArgument {
858 ty_name: String,
859 name: String,
860 binding: String,
861 init: Option<Handle<crate::Expression>>,
862}
863
864type BackendResult = Result<(), Error>;
866
867const NAMESPACE: &str = "metal";
868
869const WRAPPED_ARRAY_FIELD: &str = "inner";
873
874pub struct TranslationInfo {
877 pub entry_point_names: Vec<Result<String, EntryPointError>>,
882}
883
884pub fn write_string(
885 module: &crate::Module,
886 info: &ModuleInfo,
887 options: &Options,
888 pipeline_options: &PipelineOptions,
889) -> Result<(String, TranslationInfo), Error> {
890 let mut w = Writer::new(String::new());
891 let info = w.write(module, info, options, pipeline_options)?;
892 Ok((w.finish(), info))
893}
894
895pub fn supported_capabilities() -> crate::valid::Capabilities {
896 use crate::valid::Capabilities as Caps;
897 Caps::IMMEDIATES
898 | Caps::PRIMITIVE_INDEX
900 | Caps::TEXTURE_AND_SAMPLER_BINDING_ARRAY
901 | Caps::STORAGE_TEXTURE_BINDING_ARRAY
903 | Caps::STORAGE_BUFFER_BINDING_ARRAY
904 | Caps::CLIP_DISTANCES
905 | Caps::STORAGE_TEXTURE_16BIT_NORM_FORMATS
907 | Caps::MULTIVIEW
908 | Caps::MULTISAMPLED_SHADING
910 | Caps::RAY_QUERY
911 | Caps::DUAL_SOURCE_BLENDING
912 | Caps::CUBE_ARRAY_TEXTURES
913 | Caps::SHADER_INT64
914 | Caps::SUBGROUP
915 | Caps::SUBGROUP_BARRIER
916 | Caps::SHADER_INT64_ATOMIC_MIN_MAX
918 | Caps::SHADER_FLOAT32_ATOMIC
920 | Caps::TEXTURE_ATOMIC
921 | Caps::TEXTURE_INT64_ATOMIC
922 | Caps::SHADER_FLOAT16
924 | Caps::SHADER_INT16
925 | Caps::TEXTURE_EXTERNAL
926 | Caps::SHADER_FLOAT16_IN_FLOAT32
927 | Caps::SHADER_BARYCENTRICS
928 | Caps::MESH_SHADER
929 | Caps::MESH_SHADER_POINT_TOPOLOGY
930 | Caps::TEXTURE_AND_SAMPLER_BINDING_ARRAY_NON_UNIFORM_INDEXING
931 | Caps::STORAGE_TEXTURE_BINDING_ARRAY_NON_UNIFORM_INDEXING
933 | Caps::STORAGE_BUFFER_BINDING_ARRAY_NON_UNIFORM_INDEXING
934 | Caps::COOPERATIVE_MATRIX
935 | Caps::PER_VERTEX
936 | Caps::MEMORY_DECORATION_COHERENT
940}
941
942#[test]
943fn test_error_size() {
944 assert_eq!(size_of::<Error>(), 40);
945}