summaryrefslogtreecommitdiffstats
path: root/third_party/rust/spirv-cross-internal/src/msl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/spirv-cross-internal/src/msl.rs')
-rw-r--r--third_party/rust/spirv-cross-internal/src/msl.rs545
1 files changed, 545 insertions, 0 deletions
diff --git a/third_party/rust/spirv-cross-internal/src/msl.rs b/third_party/rust/spirv-cross-internal/src/msl.rs
new file mode 100644
index 0000000000..18f45a2ebf
--- /dev/null
+++ b/third_party/rust/spirv-cross-internal/src/msl.rs
@@ -0,0 +1,545 @@
+use crate::bindings as br;
+use crate::{compiler, spirv, ErrorCode};
+
+use std::collections::BTreeMap;
+use std::ffi::{CStr, CString};
+use std::marker::PhantomData;
+use std::ptr;
+use std::u8;
+
+/// A MSL target.
+#[derive(Debug, Clone)]
+pub enum Target {}
+
+pub struct TargetData {
+ vertex_attribute_overrides: Vec<br::spirv_cross::MSLShaderInput>,
+ resource_binding_overrides: Vec<br::spirv_cross::MSLResourceBinding>,
+ const_samplers: Vec<br::ScMslConstSamplerMapping>,
+}
+
+impl spirv::Target for Target {
+ type Data = TargetData;
+}
+
+/// Location of a vertex attribute to override
+#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
+pub struct VertexAttributeLocation(pub u32);
+
+/// Format of the vertex attribute
+#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
+pub enum Format {
+ Other,
+ Uint8,
+ Uint16,
+}
+
+impl Format {
+ fn as_raw(&self) -> br::spirv_cross::MSLShaderInputFormat {
+ use self::Format::*;
+ match self {
+ Other => br::spirv_cross::MSLShaderInputFormat_MSL_SHADER_INPUT_FORMAT_OTHER,
+ Uint8 => br::spirv_cross::MSLShaderInputFormat_MSL_SHADER_INPUT_FORMAT_UINT8,
+ Uint16 => br::spirv_cross::MSLShaderInputFormat_MSL_SHADER_INPUT_FORMAT_UINT16,
+ }
+ }
+}
+
+/// Vertex attribute description for overriding
+#[derive(Debug, Clone, Hash, Eq, PartialEq)]
+pub struct VertexAttribute {
+ pub buffer_id: u32,
+ pub format: Format,
+ pub built_in: Option<spirv::BuiltIn>,
+ pub vecsize: u32,
+}
+
+/// Location of a resource binding to override
+#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
+pub struct ResourceBindingLocation {
+ pub stage: spirv::ExecutionModel,
+ pub desc_set: u32,
+ pub binding: u32,
+}
+
+/// Resource binding description for overriding
+#[derive(Debug, Clone, Hash, Eq, PartialEq)]
+pub struct ResourceBinding {
+ pub buffer_id: u32,
+ pub texture_id: u32,
+ pub sampler_id: u32,
+}
+
+/// Location of a sampler binding to override
+#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
+pub struct SamplerLocation {
+ pub desc_set: u32,
+ pub binding: u32,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub enum SamplerCoord {
+ Normalized = 0,
+ Pixel = 1,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub enum SamplerFilter {
+ Nearest = 0,
+ Linear = 1,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub enum SamplerMipFilter {
+ None = 0,
+ Nearest = 1,
+ Linear = 2,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub enum SamplerAddress {
+ ClampToZero = 0,
+ ClampToEdge = 1,
+ ClampToBorder = 2,
+ Repeat = 3,
+ MirroredRepeat = 4,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub enum SamplerCompareFunc {
+ Never = 0,
+ Less = 1,
+ LessEqual = 2,
+ Greater = 3,
+ GreaterEqual = 4,
+ Equal = 5,
+ NotEqual = 6,
+ Always = 7,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub enum SamplerBorderColor {
+ TransparentBlack = 0,
+ OpaqueBlack = 1,
+ OpaqueWhite = 2,
+}
+
+#[repr(transparent)]
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub struct LodBase16(u8);
+
+impl LodBase16 {
+ pub const ZERO: Self = LodBase16(0);
+ pub const MAX: Self = LodBase16(!0);
+}
+
+impl From<f32> for LodBase16 {
+ fn from(v: f32) -> Self {
+ LodBase16((v * 16.0).max(0.0).min(u8::MAX as f32) as u8)
+ }
+}
+
+impl Into<f32> for LodBase16 {
+ fn into(self) -> f32 {
+ self.0 as f32 / 16.0
+ }
+}
+
+/// MSL format resolution.
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum FormatResolution {
+ _444 = 0,
+ _422 = 1,
+ _420 = 2,
+}
+
+/// MSL chroma location.
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum ChromaLocation {
+ CositedEven = 0,
+ LocationMidpoint = 1,
+}
+
+/// MSL component swizzle.
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum ComponentSwizzle {
+ Identity = 0,
+ Zero = 1,
+ One = 2,
+ R = 3,
+ G = 4,
+ B = 5,
+ A = 6,
+}
+
+/// Data fully defining a constant sampler.
+#[derive(Debug, Clone, Hash, Eq, PartialEq)]
+pub struct SamplerData {
+ pub coord: SamplerCoord,
+ pub min_filter: SamplerFilter,
+ pub mag_filter: SamplerFilter,
+ pub mip_filter: SamplerMipFilter,
+ pub s_address: SamplerAddress,
+ pub t_address: SamplerAddress,
+ pub r_address: SamplerAddress,
+ pub compare_func: SamplerCompareFunc,
+ pub border_color: SamplerBorderColor,
+ pub lod_clamp_min: LodBase16,
+ pub lod_clamp_max: LodBase16,
+ pub max_anisotropy: i32,
+ // Sampler YCbCr conversion parameters
+ pub planes: u32,
+ pub resolution: FormatResolution,
+ pub chroma_filter: SamplerFilter,
+ pub x_chroma_offset: ChromaLocation,
+ pub y_chroma_offset: ChromaLocation,
+ pub swizzle: [ComponentSwizzle; 4],
+ pub ycbcr_conversion_enable: bool,
+ pub ycbcr_model: SamplerYCbCrModelConversion,
+ pub ycbcr_range: SamplerYCbCrRange,
+ pub bpc: u32,
+}
+
+/// A MSL sampler YCbCr model conversion.
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum SamplerYCbCrModelConversion {
+ RgbIdentity = 0,
+ YCbCrIdentity = 1,
+ YCbCrBt709 = 2,
+ YCbCrBt601 = 3,
+ YCbCrBt2020 = 4,
+}
+
+/// A MSL sampler YCbCr range.
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum SamplerYCbCrRange {
+ ItuFull = 0,
+ ItuNarrow = 1,
+}
+
+/// A MSL shader platform.
+#[repr(u8)]
+#[allow(non_snake_case, non_camel_case_types)]
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+pub enum Platform {
+ iOS = 0,
+ macOS = 1,
+}
+
+/// A MSL shader model version.
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+pub enum Version {
+ V1_0,
+ V1_1,
+ V1_2,
+ V2_0,
+ V2_1,
+ V2_2,
+}
+
+impl Version {
+ fn as_raw(self) -> u32 {
+ use self::Version::*;
+ match self {
+ V1_0 => 10000,
+ V1_1 => 10100,
+ V1_2 => 10200,
+ V2_0 => 20000,
+ V2_1 => 20100,
+ V2_2 => 20200,
+ }
+ }
+}
+
+#[derive(Debug, Clone, Hash, Eq, PartialEq)]
+pub struct CompilerVertexOptions {
+ pub invert_y: bool,
+ pub transform_clip_space: bool,
+}
+
+impl Default for CompilerVertexOptions {
+ fn default() -> Self {
+ CompilerVertexOptions {
+ invert_y: false,
+ transform_clip_space: false,
+ }
+ }
+}
+
+/// MSL compiler options.
+#[non_exhaustive]
+#[derive(Debug, Clone, Hash, Eq, PartialEq)]
+pub struct CompilerOptions {
+ /// The target platform.
+ pub platform: Platform,
+ /// The target MSL version.
+ pub version: Version,
+ /// Vertex compiler options.
+ pub vertex: CompilerVertexOptions,
+ /// The buffer index to use for swizzle.
+ pub swizzle_buffer_index: u32,
+ // The buffer index to use for indirect params.
+ pub indirect_params_buffer_index: u32,
+ /// The buffer index to use for output.
+ pub output_buffer_index: u32,
+ /// The buffer index to use for patch output.
+ pub patch_output_buffer_index: u32,
+ /// The buffer index to use for tessellation factor.
+ pub tessellation_factor_buffer_index: u32,
+ /// The buffer index to use for buffer size.
+ pub buffer_size_buffer_index: u32,
+ /// Whether the built-in point size should be enabled.
+ pub enable_point_size_builtin: bool,
+ /// Whether rasterization should be enabled.
+ pub enable_rasterization: bool,
+ /// Whether to capture output to buffer.
+ pub capture_output_to_buffer: bool,
+ /// Whether to swizzle texture samples.
+ pub swizzle_texture_samples: bool,
+ /// Whether to place the origin of tessellation domain shaders in the lower left.
+ pub tessellation_domain_origin_lower_left: bool,
+ /// Whether to enable use of argument buffers (only compatible with MSL 2.0).
+ pub enable_argument_buffers: bool,
+ /// Whether to pad fragment output to have at least the number of components as the render pass.
+ pub pad_fragment_output_components: bool,
+ /// MSL resource bindings overrides.
+ pub resource_binding_overrides: BTreeMap<ResourceBindingLocation, ResourceBinding>,
+ /// MSL vertex attribute overrides.
+ pub vertex_attribute_overrides: BTreeMap<VertexAttributeLocation, VertexAttribute>,
+ /// MSL const sampler mappings.
+ pub const_samplers: BTreeMap<SamplerLocation, SamplerData>,
+ /// Whether to force native arrays (useful to workaround issues on some hardware).
+ pub force_native_arrays: bool,
+ /// Whether to force all uninitialized variables to be initialized to zero.
+ pub force_zero_initialized_variables: bool,
+ /// The name and execution model of the entry point to use. If no entry
+ /// point is specified, then the first entry point found will be used.
+ pub entry_point: Option<(String, spirv::ExecutionModel)>,
+}
+
+impl Default for CompilerOptions {
+ fn default() -> Self {
+ CompilerOptions {
+ platform: Platform::macOS,
+ version: Version::V1_2,
+ vertex: CompilerVertexOptions::default(),
+ swizzle_buffer_index: 30,
+ indirect_params_buffer_index: 29,
+ output_buffer_index: 28,
+ patch_output_buffer_index: 27,
+ tessellation_factor_buffer_index: 26,
+ buffer_size_buffer_index: 25,
+ enable_point_size_builtin: true,
+ enable_rasterization: true,
+ capture_output_to_buffer: false,
+ swizzle_texture_samples: false,
+ tessellation_domain_origin_lower_left: false,
+ enable_argument_buffers: false,
+ pad_fragment_output_components: false,
+ resource_binding_overrides: Default::default(),
+ vertex_attribute_overrides: Default::default(),
+ const_samplers: Default::default(),
+ force_native_arrays: false,
+ force_zero_initialized_variables: false,
+ entry_point: None,
+ }
+ }
+}
+
+impl<'a> spirv::Parse<Target> for spirv::Ast<Target> {
+ fn parse(module: &spirv::Module) -> Result<Self, ErrorCode> {
+ let mut sc_compiler = ptr::null_mut();
+ unsafe {
+ check!(br::sc_internal_compiler_msl_new(
+ &mut sc_compiler,
+ module.words.as_ptr(),
+ module.words.len(),
+ ));
+ }
+
+ Ok(spirv::Ast {
+ compiler: compiler::Compiler {
+ sc_compiler,
+ target_data: TargetData {
+ resource_binding_overrides: Vec::new(),
+ vertex_attribute_overrides: Vec::new(),
+ const_samplers: Vec::new(),
+ },
+ has_been_compiled: false,
+ },
+ target_type: PhantomData,
+ })
+ }
+}
+
+impl spirv::Compile<Target> for spirv::Ast<Target> {
+ type CompilerOptions = CompilerOptions;
+
+ /// Set MSL compiler specific compilation settings.
+ fn set_compiler_options(&mut self, options: &CompilerOptions) -> Result<(), ErrorCode> {
+ if let Some((name, model)) = &options.entry_point {
+ let name_raw = CString::new(name.as_str()).map_err(|_| ErrorCode::Unhandled)?;
+ let model = model.as_raw();
+ unsafe {
+ check!(br::sc_internal_compiler_set_entry_point(
+ self.compiler.sc_compiler,
+ name_raw.as_ptr(),
+ model,
+ ));
+ }
+ };
+ let raw_options = br::ScMslCompilerOptions {
+ vertex_invert_y: options.vertex.invert_y,
+ vertex_transform_clip_space: options.vertex.transform_clip_space,
+ platform: options.platform as _,
+ version: options.version.as_raw(),
+ enable_point_size_builtin: options.enable_point_size_builtin,
+ disable_rasterization: !options.enable_rasterization,
+ swizzle_buffer_index: options.swizzle_buffer_index,
+ indirect_params_buffer_index: options.indirect_params_buffer_index,
+ shader_output_buffer_index: options.output_buffer_index,
+ shader_patch_output_buffer_index: options.patch_output_buffer_index,
+ shader_tess_factor_buffer_index: options.tessellation_factor_buffer_index,
+ buffer_size_buffer_index: options.buffer_size_buffer_index,
+ capture_output_to_buffer: options.capture_output_to_buffer,
+ swizzle_texture_samples: options.swizzle_texture_samples,
+ tess_domain_origin_lower_left: options.tessellation_domain_origin_lower_left,
+ argument_buffers: options.enable_argument_buffers,
+ pad_fragment_output_components: options.pad_fragment_output_components,
+ force_native_arrays: options.force_native_arrays,
+ force_zero_initialized_variables: options.force_zero_initialized_variables,
+ };
+ unsafe {
+ check!(br::sc_internal_compiler_msl_set_options(
+ self.compiler.sc_compiler,
+ &raw_options,
+ ));
+ }
+
+ self.compiler.target_data.resource_binding_overrides.clear();
+ self.compiler.target_data.resource_binding_overrides.extend(
+ options.resource_binding_overrides.iter().map(|(loc, res)| {
+ br::spirv_cross::MSLResourceBinding {
+ stage: loc.stage.as_raw(),
+ desc_set: loc.desc_set,
+ binding: loc.binding,
+ msl_buffer: res.buffer_id,
+ msl_texture: res.texture_id,
+ msl_sampler: res.sampler_id,
+ }
+ }),
+ );
+
+ self.compiler.target_data.vertex_attribute_overrides.clear();
+ self.compiler.target_data.vertex_attribute_overrides.extend(
+ options.vertex_attribute_overrides.iter().map(|(loc, vat)| {
+ br::spirv_cross::MSLShaderInput {
+ location: loc.0,
+ format: vat.format.as_raw(),
+ builtin: spirv::built_in_as_raw(vat.built_in),
+ vecsize: vat.vecsize,
+ }
+ }),
+ );
+
+ self.compiler.target_data.const_samplers.clear();
+ self.compiler
+ .target_data
+ .const_samplers
+ .extend(options.const_samplers.iter().map(|(loc, data)| unsafe {
+ use std::mem::transmute;
+ br::ScMslConstSamplerMapping {
+ desc_set: loc.desc_set,
+ binding: loc.binding,
+ sampler: br::spirv_cross::MSLConstexprSampler {
+ coord: transmute(data.coord),
+ min_filter: transmute(data.min_filter),
+ mag_filter: transmute(data.mag_filter),
+ mip_filter: transmute(data.mip_filter),
+ s_address: transmute(data.s_address),
+ t_address: transmute(data.t_address),
+ r_address: transmute(data.r_address),
+ compare_func: transmute(data.compare_func),
+ border_color: transmute(data.border_color),
+ lod_clamp_min: data.lod_clamp_min.into(),
+ lod_clamp_max: data.lod_clamp_max.into(),
+ max_anisotropy: data.max_anisotropy,
+ compare_enable: data.compare_func != SamplerCompareFunc::Always,
+ lod_clamp_enable: data.lod_clamp_min != LodBase16::ZERO
+ || data.lod_clamp_max != LodBase16::MAX,
+ anisotropy_enable: data.max_anisotropy != 0,
+ bpc: data.bpc,
+ chroma_filter: transmute(data.chroma_filter),
+ planes: data.planes,
+ resolution: transmute(data.resolution),
+ swizzle: transmute(data.swizzle),
+ x_chroma_offset: transmute(data.x_chroma_offset),
+ y_chroma_offset: transmute(data.y_chroma_offset),
+ ycbcr_conversion_enable: data.ycbcr_conversion_enable,
+ ycbcr_model: transmute(data.ycbcr_model),
+ ycbcr_range: transmute(data.ycbcr_range),
+ },
+ }
+ }));
+
+ Ok(())
+ }
+
+ /// Generate MSL shader from the AST.
+ fn compile(&mut self) -> Result<String, ErrorCode> {
+ self.compile_internal()
+ }
+}
+
+impl spirv::Ast<Target> {
+ fn compile_internal(&self) -> Result<String, ErrorCode> {
+ let vat_overrides = &self.compiler.target_data.vertex_attribute_overrides;
+ let res_overrides = &self.compiler.target_data.resource_binding_overrides;
+ let const_samplers = &self.compiler.target_data.const_samplers;
+ unsafe {
+ let mut shader_ptr = ptr::null();
+ check!(br::sc_internal_compiler_msl_compile(
+ self.compiler.sc_compiler,
+ &mut shader_ptr,
+ vat_overrides.as_ptr(),
+ vat_overrides.len(),
+ res_overrides.as_ptr(),
+ res_overrides.len(),
+ const_samplers.as_ptr(),
+ const_samplers.len(),
+ ));
+ let shader = match CStr::from_ptr(shader_ptr).to_str() {
+ Ok(v) => v.to_owned(),
+ Err(_) => return Err(ErrorCode::Unhandled),
+ };
+ check!(br::sc_internal_free_pointer(
+ shader_ptr as *mut std::os::raw::c_void
+ ));
+ Ok(shader)
+ }
+ }
+
+ pub fn is_rasterization_enabled(&self) -> Result<bool, ErrorCode> {
+ unsafe {
+ let mut is_disabled = false;
+ check!(br::sc_internal_compiler_msl_get_is_rasterization_disabled(
+ self.compiler.sc_compiler,
+ &mut is_disabled
+ ));
+ Ok(!is_disabled)
+ }
+ }
+}
+
+// TODO: Generate with bindgen
+pub const ARGUMENT_BUFFER_BINDING: u32 = !3;