diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9796b04 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,7 @@ +[submodule "ext/spirv-tools"] + path = ext/spirv-tools + url = https://github.com/KhronosGroup/SPIRV-Tools + branch = master +[submodule "ext/spirv-headers"] + path = ext/spirv-headers + url = https://github.com/KhronosGroup/SPIRV-Headers diff --git a/Cargo.toml b/Cargo.toml index 67ee0a0..eb94669 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "level_zero-sys", "level_zero", + "spirv_tools-sys", "notcuda", "notcuda_inject", "notcuda_redirect", diff --git a/ext/spirv-headers b/ext/spirv-headers new file mode 160000 index 0000000..308bd07 --- /dev/null +++ b/ext/spirv-headers @@ -0,0 +1 @@ +Subproject commit 308bd07424350a6000f35a77b5f85cd4f3da319e diff --git a/ext/spirv-tools b/ext/spirv-tools new file mode 160000 index 0000000..e128ab0 --- /dev/null +++ b/ext/spirv-tools @@ -0,0 +1 @@ +Subproject commit e128ab0d624ce7beb08eb9656bb260c597a46d0a diff --git a/ptx/Cargo.toml b/ptx/Cargo.toml index 7945929..d3c4b73 100644 --- a/ptx/Cargo.toml +++ b/ptx/Cargo.toml @@ -13,6 +13,7 @@ rspirv = "0.6" spirv_headers = "1.4" quick-error = "1.2" bit-vec = "0.6" +paste = "0.1" [build-dependencies.lalrpop] version = "0.18.1" @@ -21,3 +22,4 @@ features = ["lexer"] [dev-dependencies] level_zero-sys = { path = "../level_zero-sys" } level_zero = { path = "../level_zero" } +spirv_tools-sys = { path = "../spirv_tools-sys" } diff --git a/ptx/src/lib.rs b/ptx/src/lib.rs index 0b0fd71..5402326 100644 --- a/ptx/src/lib.rs +++ b/ptx/src/lib.rs @@ -1,3 +1,5 @@ +#[cfg_attr(macro_use, test)] +extern crate paste; #[macro_use] extern crate lalrpop_util; #[macro_use] @@ -11,6 +13,9 @@ extern crate level_zero_sys as l0; extern crate rspirv; extern crate spirv_headers as spirv; +#[cfg(test)] +extern crate spirv_tools_sys as spirv_tools; + lalrpop_mod!( #[allow(warnings)] ptx diff --git a/ptx/src/test/spirv_run/ld_st.spvtxt b/ptx/src/test/spirv_run/ld_st.spvtxt new file mode 100644 index 0000000..33bd251 --- /dev/null +++ b/ptx/src/test/spirv_run/ld_st.spvtxt @@ -0,0 +1,25 @@ +OpCapability GenericPointer +OpCapability Linkage +OpCapability Addresses +OpCapability Kernel +OpCapability Int64 +OpCapability Int8 +%1 = OpExtInstImport "OpenCL.std" +OpMemoryModel Physical64 OpenCL +OpEntryPoint Kernel %5 "ld_st" +%2 = OpTypeVoid +%3 = OpTypeInt 64 0 +%4 = OpTypeFunction %2 %3 %3 +%19 = OpTypePointer Generic %3 +%5 = OpFunction %2 None %4 +%6 = OpFunctionParameter %3 +%7 = OpFunctionParameter %3 +%18 = OpLabel +%13 = OpCopyObject %3 %6 +%14 = OpCopyObject %3 %7 +%15 = OpConvertUToPtr %19 %13 +%16 = OpLoad %3 %15 +%17 = OpConvertUToPtr %19 %14 +OpStore %17 %16 +OpReturn +OpFunctionEnd diff --git a/ptx/src/test/spirv_run/mod.rs b/ptx/src/test/spirv_run/mod.rs index bb27431..83d0510 100644 --- a/ptx/src/test/spirv_run/mod.rs +++ b/ptx/src/test/spirv_run/mod.rs @@ -1,21 +1,37 @@ use crate::ptx; use crate::translate; +use rspirv::dr::{Block, Function, Instruction, Loader, Operand}; +use spirv_headers::Word; +use spirv_tools_sys::{ + spv_binary, spv_endianness_t, spv_parsed_instruction_t, spv_result_t, spv_target_env, +}; use std::error; -use std::ffi::{CStr, CString}; +use std::ffi::{c_void, CStr, CString}; use std::fmt; use std::fmt::{Debug, Display, Formatter}; use std::mem; use std::slice; -use std::str; +use std::{collections::HashMap, ptr, str}; macro_rules! test_ptx { ($fn_name:ident, $input:expr, $output:expr) => { - #[test] - fn $fn_name() -> Result<(), Box> { - let ptx = include_str!(concat!(stringify!($fn_name), ".ptx")); - let input = $input; - let mut output = $output; - test_ptx_assert(stringify!($fn_name), ptx, &input, &mut output) + paste::item! { + #[test] + fn [<$fn_name _ptx>]() -> Result<(), Box> { + let ptx = include_str!(concat!(stringify!($fn_name), ".ptx")); + let input = $input; + let mut output = $output; + test_ptx_assert(stringify!($fn_name), ptx, &input, &mut output) + } + } + + paste::item! { + #[test] + fn [<$fn_name _spvtxt>]() -> Result<(), Box> { + let ptx_txt = include_str!(concat!(stringify!($fn_name), ".ptx")); + let spirv_txt = include_bytes!(concat!(stringify!($fn_name), ".spvtxt")); + test_spvtxt_assert(ptx_txt, spirv_txt) + } } }; } @@ -97,3 +113,141 @@ fn run_spirv + ze::SafeRepr + Copy + Debug>( queue.execute(cmd_list)?; Ok(result) } + +fn test_spvtxt_assert<'a>( + ptx_txt: &'a str, + spirv_txt: &'a [u8], +) -> Result<(), Box> { + let mut errors = Vec::new(); + let ast = ptx::ModuleParser::new().parse(&mut errors, ptx_txt)?; + assert!(errors.len() == 0); + let ptx_mod = translate::to_spirv_module(ast)?; + let spv_context = + unsafe { spirv_tools::spvContextCreate(spv_target_env::SPV_ENV_UNIVERSAL_1_3) }; + assert!(spv_context != ptr::null_mut()); + let mut spv_binary: spv_binary = ptr::null_mut(); + let result = unsafe { + spirv_tools::spvTextToBinary( + spv_context, + spirv_txt.as_ptr() as *const _, + spirv_txt.len(), + &mut spv_binary, + ptr::null_mut(), + ) + }; + assert!(result == spv_result_t::SPV_SUCCESS); + let mut parsed_spirv = Vec::::new(); + let result = unsafe { + spirv_tools::spvBinaryParse( + spv_context, + &mut parsed_spirv as *mut _ as *mut _, + (*spv_binary).code, + (*spv_binary).wordCount, + Some(parse_header_cb), + Some(parse_instruction_cb), + ptr::null_mut(), + ) + }; + let mut loader = Loader::new(); + rspirv::binary::parse_words(&parsed_spirv, &mut loader)?; + let spvtxt_mod = loader.module(); + assert_spirv_fn_equal(&ptx_mod.functions[0], &spvtxt_mod.functions[0]); + assert!(result == spv_result_t::SPV_SUCCESS); + Ok(()) +} + +fn assert_spirv_fn_equal(fn1: &Function, fn2: &Function) { + let mut map = HashMap::new(); + assert_option_equal(&fn1.def, &fn2.def, &mut map, assert_instr_equal); + assert_option_equal(&fn1.end, &fn2.end, &mut map, assert_instr_equal); + for (inst1, inst2) in fn1.parameters.iter().zip(fn2.parameters.iter()) { + assert_instr_equal(inst1, inst2, &mut map); + } + for (b1, b2) in fn1.blocks.iter().zip(fn2.blocks.iter()) { + assert_block_equal(b1, b2, &mut map); + } +} + +fn assert_block_equal(b1: &Block, b2: &Block, map: &mut HashMap) { + assert_option_equal(&b1.label, &b2.label, map, assert_instr_equal); + for (inst1, inst2) in b1.instructions.iter().zip(b2.instructions.iter()) { + assert_instr_equal(inst1, inst2, map); + } +} + +fn assert_instr_equal(instr1: &Instruction, instr2: &Instruction, map: &mut HashMap) { + assert_option_equal( + &instr1.result_type, + &instr2.result_type, + map, + assert_word_equal, + ); + assert_option_equal(&instr1.result_id, &instr2.result_id, map, assert_word_equal); + for (o1, o2) in instr1.operands.iter().zip(instr2.operands.iter()) { + match (o1, o2) { + (Operand::IdMemorySemantics(w1), Operand::IdMemorySemantics(w2)) => { + assert_word_equal(w1, w2, map) + } + (Operand::IdScope(w1), Operand::IdScope(w2)) => assert_word_equal(w1, w2, map), + (Operand::IdRef(w1), Operand::IdRef(w2)) => assert_word_equal(w1, w2, map), + (o1, o2) => assert_eq!(o1, o2), + } + } +} + +fn assert_word_equal(w1: &Word, w2: &Word, map: &mut HashMap) { + match map.entry(*w1) { + std::collections::hash_map::Entry::Occupied(entry) => { + assert_eq!(entry.get(), w2); + } + std::collections::hash_map::Entry::Vacant(entry) => { + entry.insert(*w2); + } + } +} + +fn assert_option_equal)>( + o1: &Option, + o2: &Option, + map: &mut HashMap, + f: F, +) { + match (o1, o2) { + (Some(t1), Some(t2)) => f(t1, t2, map), + (None, None) => (), + _ => panic!(), + } +} + +unsafe extern "C" fn parse_header_cb( + user_data: *mut c_void, + endian: spv_endianness_t, + magic: u32, + version: u32, + generator: u32, + id_bound: u32, + reserved: u32, +) -> spv_result_t { + if endian == spv_endianness_t::SPV_ENDIANNESS_BIG { + return spv_result_t::SPV_UNSUPPORTED; + } + let result_vec: &mut Vec = std::mem::transmute(user_data); + result_vec.push(magic); + result_vec.push(version); + result_vec.push(generator); + result_vec.push(id_bound); + result_vec.push(reserved); + spv_result_t::SPV_SUCCESS +} + +unsafe extern "C" fn parse_instruction_cb( + user_data: *mut c_void, + inst: *const spv_parsed_instruction_t, +) -> spv_result_t { + let inst = &*inst; + let result_vec: &mut Vec = std::mem::transmute(user_data); + for i in 0..inst.num_words { + result_vec.push(*(inst.words.add(i as usize))); + } + spv_result_t::SPV_SUCCESS +} diff --git a/ptx/src/translate.rs b/ptx/src/translate.rs index 4444ba7..1942586 100644 --- a/ptx/src/translate.rs +++ b/ptx/src/translate.rs @@ -5,7 +5,7 @@ use std::cell::RefCell; use std::collections::{BTreeMap, HashMap, HashSet}; use std::{borrow::Cow, fmt, mem}; -use rspirv::binary::{Assemble, Disassemble}; +use rspirv::binary::Assemble; #[derive(PartialEq, Eq, Hash, Clone, Copy)] enum SpirvType { @@ -73,7 +73,7 @@ impl TypeWordMap { } } -pub fn to_spirv(ast: ast::Module) -> Result, dr::Error> { +pub fn to_spirv_module(ast: ast::Module) -> Result { let mut builder = dr::Builder::new(); // https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_a_id_logicallayout_a_logical_layout_of_a_module builder.set_version(1, 0); @@ -85,8 +85,11 @@ pub fn to_spirv(ast: ast::Module) -> Result, dr::Error> { for f in ast.functions { emit_function(&mut builder, &mut map, f)?; } - let module = builder.module(); - println!("{}", module.disassemble()); + Ok(builder.module()) +} + +pub fn to_spirv(ast: ast::Module) -> Result, dr::Error> { + let module = to_spirv_module(ast)?; Ok(module.assemble()) } diff --git a/spirv_tools-sys/Cargo.toml b/spirv_tools-sys/Cargo.toml new file mode 100644 index 0000000..a5cadc1 --- /dev/null +++ b/spirv_tools-sys/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "spirv_tools-sys" +version = "0.0.0" +authors = ["Andrzej Janik "] +edition = "2018" + +[lib] + +[build-dependencies] +cmake = "0.1" \ No newline at end of file diff --git a/spirv_tools-sys/README b/spirv_tools-sys/README new file mode 100644 index 0000000..5865dc6 --- /dev/null +++ b/spirv_tools-sys/README @@ -0,0 +1 @@ +bindgen --whitelist-type="spv.*" --whitelist-function="spv.*" --size_t-is-usize --default-enum-style=rust ext/SPIRV-Tools/include/spirv-tools/libspirv.h -o lib.rs \ No newline at end of file diff --git a/spirv_tools-sys/build.rs b/spirv_tools-sys/build.rs new file mode 100644 index 0000000..8cdf695 --- /dev/null +++ b/spirv_tools-sys/build.rs @@ -0,0 +1,24 @@ +extern crate cmake; + +use cmake::Config; +use std::{env::VarError, path::PathBuf}; + +fn main() -> Result<(), VarError> { + let root_path = std::env::var("CARGO_MANIFEST_DIR")?; + let mut headers_path = PathBuf::new(); + headers_path.push(root_path); + headers_path.push("../ext/spirv-headers"); + let spirv_tools_dir = Config::new("../ext/spirv-tools") + .always_configure(false) + .define("SPIRV-Headers_SOURCE_DIR", headers_path) + .define("SPIRV_SKIP_EXECUTABLES", "ON") + .define("SPIRV_SKIP_TESTS", "ON") + .build(); + println!( + "cargo:rustc-link-search=native={}/bin", + spirv_tools_dir.display() + ); + // dynamic linking to avoid linking to C++ runtime + println!("cargo:rustc-link-lib=dylib=SPIRV-Tools-shared"); + Ok(()) +} diff --git a/spirv_tools-sys/src/lib.rs b/spirv_tools-sys/src/lib.rs new file mode 100644 index 0000000..c1a9dc2 --- /dev/null +++ b/spirv_tools-sys/src/lib.rs @@ -0,0 +1,3 @@ +#[allow(warnings)] +mod spirv_tools; +pub use spirv_tools::*; \ No newline at end of file diff --git a/spirv_tools-sys/src/spirv_tools.rs b/spirv_tools-sys/src/spirv_tools.rs new file mode 100644 index 0000000..44b86f4 --- /dev/null +++ b/spirv_tools-sys/src/spirv_tools.rs @@ -0,0 +1,889 @@ +/* automatically generated by rust-bindgen 0.54.1 */ + +pub type __uint16_t = ::std::os::raw::c_ushort; +pub type __uint32_t = ::std::os::raw::c_uint; +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_result_t { + SPV_SUCCESS = 0, + SPV_UNSUPPORTED = 1, + SPV_END_OF_STREAM = 2, + SPV_WARNING = 3, + SPV_FAILED_MATCH = 4, + SPV_REQUESTED_TERMINATION = 5, + SPV_ERROR_INTERNAL = -1, + SPV_ERROR_OUT_OF_MEMORY = -2, + SPV_ERROR_INVALID_POINTER = -3, + SPV_ERROR_INVALID_BINARY = -4, + SPV_ERROR_INVALID_TEXT = -5, + SPV_ERROR_INVALID_TABLE = -6, + SPV_ERROR_INVALID_VALUE = -7, + SPV_ERROR_INVALID_DIAGNOSTIC = -8, + SPV_ERROR_INVALID_LOOKUP = -9, + SPV_ERROR_INVALID_ID = -10, + SPV_ERROR_INVALID_CFG = -11, + SPV_ERROR_INVALID_LAYOUT = -12, + SPV_ERROR_INVALID_CAPABILITY = -13, + SPV_ERROR_INVALID_DATA = -14, + SPV_ERROR_MISSING_EXTENSION = -15, + SPV_ERROR_WRONG_VERSION = -16, + _spv_result_t = 2147483647, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_message_level_t { + SPV_MSG_FATAL = 0, + SPV_MSG_INTERNAL_ERROR = 1, + SPV_MSG_ERROR = 2, + SPV_MSG_WARNING = 3, + SPV_MSG_INFO = 4, + SPV_MSG_DEBUG = 5, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_endianness_t { + SPV_ENDIANNESS_LITTLE = 0, + SPV_ENDIANNESS_BIG = 1, + _spv_endianness_t = 2147483647, +} +impl spv_operand_type_t { + pub const SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE: spv_operand_type_t = + spv_operand_type_t::SPV_OPERAND_TYPE_OPTIONAL_ID; +} +impl spv_operand_type_t { + pub const SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE: spv_operand_type_t = + spv_operand_type_t::SPV_OPERAND_TYPE_VARIABLE_ID; +} +impl spv_operand_type_t { + pub const SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE: spv_operand_type_t = + spv_operand_type_t::SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER; +} +impl spv_operand_type_t { + pub const SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE: spv_operand_type_t = + spv_operand_type_t::SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_operand_type_t { + SPV_OPERAND_TYPE_NONE = 0, + SPV_OPERAND_TYPE_ID = 1, + SPV_OPERAND_TYPE_TYPE_ID = 2, + SPV_OPERAND_TYPE_RESULT_ID = 3, + SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID = 4, + SPV_OPERAND_TYPE_SCOPE_ID = 5, + SPV_OPERAND_TYPE_LITERAL_INTEGER = 6, + SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER = 7, + SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER = 8, + SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER = 9, + SPV_OPERAND_TYPE_LITERAL_STRING = 10, + SPV_OPERAND_TYPE_SOURCE_LANGUAGE = 11, + SPV_OPERAND_TYPE_EXECUTION_MODEL = 12, + SPV_OPERAND_TYPE_ADDRESSING_MODEL = 13, + SPV_OPERAND_TYPE_MEMORY_MODEL = 14, + SPV_OPERAND_TYPE_EXECUTION_MODE = 15, + SPV_OPERAND_TYPE_STORAGE_CLASS = 16, + SPV_OPERAND_TYPE_DIMENSIONALITY = 17, + SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE = 18, + SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE = 19, + SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT = 20, + SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER = 21, + SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE = 22, + SPV_OPERAND_TYPE_FP_ROUNDING_MODE = 23, + SPV_OPERAND_TYPE_LINKAGE_TYPE = 24, + SPV_OPERAND_TYPE_ACCESS_QUALIFIER = 25, + SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE = 26, + SPV_OPERAND_TYPE_DECORATION = 27, + SPV_OPERAND_TYPE_BUILT_IN = 28, + SPV_OPERAND_TYPE_GROUP_OPERATION = 29, + SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS = 30, + SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO = 31, + SPV_OPERAND_TYPE_CAPABILITY = 32, + SPV_OPERAND_TYPE_RAY_FLAGS = 33, + SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION = 34, + SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE = 35, + SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE = 36, + SPV_OPERAND_TYPE_IMAGE = 37, + SPV_OPERAND_TYPE_FP_FAST_MATH_MODE = 38, + SPV_OPERAND_TYPE_SELECTION_CONTROL = 39, + SPV_OPERAND_TYPE_LOOP_CONTROL = 40, + SPV_OPERAND_TYPE_FUNCTION_CONTROL = 41, + SPV_OPERAND_TYPE_MEMORY_ACCESS = 42, + SPV_OPERAND_TYPE_OPTIONAL_ID = 43, + SPV_OPERAND_TYPE_OPTIONAL_IMAGE = 44, + SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS = 45, + SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER = 46, + SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER = 47, + SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER = 48, + SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING = 49, + SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER = 50, + SPV_OPERAND_TYPE_OPTIONAL_CIV = 51, + SPV_OPERAND_TYPE_VARIABLE_ID = 52, + SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER = 53, + SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID = 54, + SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER = 55, + SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS = 56, + SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING = 57, + SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE = 58, + SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER = 59, + SPV_OPERAND_TYPE_DEBUG_OPERATION = 60, + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS = 61, + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING = 62, + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE = 63, + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER = 64, + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION = 65, + SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY = 66, + SPV_OPERAND_TYPE_NUM_OPERAND_TYPES = 67, + _spv_operand_type_t = 2147483647, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_ext_inst_type_t { + SPV_EXT_INST_TYPE_NONE = 0, + SPV_EXT_INST_TYPE_GLSL_STD_450 = 1, + SPV_EXT_INST_TYPE_OPENCL_STD = 2, + SPV_EXT_INST_TYPE_SPV_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER = 3, + SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX = 4, + SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER = 5, + SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT = 6, + SPV_EXT_INST_TYPE_DEBUGINFO = 7, + SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 = 8, + SPV_EXT_INST_TYPE_NONSEMANTIC_UNKNOWN = 9, + _spv_ext_inst_type_t = 2147483647, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_number_kind_t { + SPV_NUMBER_NONE = 0, + SPV_NUMBER_UNSIGNED_INT = 1, + SPV_NUMBER_SIGNED_INT = 2, + SPV_NUMBER_FLOATING = 3, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_text_to_binary_options_t { + SPV_TEXT_TO_BINARY_OPTION_NONE = 1, + SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS = 2, + _spv_text_to_binary_options_t = 2147483647, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_binary_to_text_options_t { + SPV_BINARY_TO_TEXT_OPTION_NONE = 1, + SPV_BINARY_TO_TEXT_OPTION_PRINT = 2, + SPV_BINARY_TO_TEXT_OPTION_COLOR = 4, + SPV_BINARY_TO_TEXT_OPTION_INDENT = 8, + SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET = 16, + SPV_BINARY_TO_TEXT_OPTION_NO_HEADER = 32, + SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES = 64, + _spv_binary_to_text_options_t = 2147483647, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_parsed_operand_t { + pub offset: u16, + pub num_words: u16, + pub type_: spv_operand_type_t, + pub number_kind: spv_number_kind_t, + pub number_bit_width: u32, +} +#[test] +fn bindgen_test_layout_spv_parsed_operand_t() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(spv_parsed_operand_t)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spv_parsed_operand_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).offset as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_operand_t), + "::", + stringify!(offset) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).num_words as *const _ as usize }, + 2usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_operand_t), + "::", + stringify!(num_words) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).type_ as *const _ as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_operand_t), + "::", + stringify!(type_) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).number_kind as *const _ as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_operand_t), + "::", + stringify!(number_kind) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).number_bit_width as *const _ as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_operand_t), + "::", + stringify!(number_bit_width) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_parsed_instruction_t { + pub words: *const u32, + pub num_words: u16, + pub opcode: u16, + pub ext_inst_type: spv_ext_inst_type_t, + pub type_id: u32, + pub result_id: u32, + pub operands: *const spv_parsed_operand_t, + pub num_operands: u16, +} +#[test] +fn bindgen_test_layout_spv_parsed_instruction_t() { + assert_eq!( + ::std::mem::size_of::(), + 40usize, + concat!("Size of: ", stringify!(spv_parsed_instruction_t)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spv_parsed_instruction_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).words as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_instruction_t), + "::", + stringify!(words) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).num_words as *const _ as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_instruction_t), + "::", + stringify!(num_words) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).opcode as *const _ as usize }, + 10usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_instruction_t), + "::", + stringify!(opcode) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).ext_inst_type as *const _ as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_instruction_t), + "::", + stringify!(ext_inst_type) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).type_id as *const _ as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_instruction_t), + "::", + stringify!(type_id) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).result_id as *const _ as usize + }, + 20usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_instruction_t), + "::", + stringify!(result_id) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).operands as *const _ as usize + }, + 24usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_instruction_t), + "::", + stringify!(operands) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::())).num_operands as *const _ as usize + }, + 32usize, + concat!( + "Offset of field: ", + stringify!(spv_parsed_instruction_t), + "::", + stringify!(num_operands) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_const_binary_t { + pub code: *const u32, + pub wordCount: usize, +} +#[test] +fn bindgen_test_layout_spv_const_binary_t() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(spv_const_binary_t)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spv_const_binary_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).code as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spv_const_binary_t), + "::", + stringify!(code) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).wordCount as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spv_const_binary_t), + "::", + stringify!(wordCount) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_binary_t { + pub code: *mut u32, + pub wordCount: usize, +} +#[test] +fn bindgen_test_layout_spv_binary_t() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(spv_binary_t)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spv_binary_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).code as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spv_binary_t), + "::", + stringify!(code) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).wordCount as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spv_binary_t), + "::", + stringify!(wordCount) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_text_t { + pub str_: *const ::std::os::raw::c_char, + pub length: usize, +} +#[test] +fn bindgen_test_layout_spv_text_t() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(spv_text_t)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spv_text_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).str_ as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spv_text_t), + "::", + stringify!(str_) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).length as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spv_text_t), + "::", + stringify!(length) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_position_t { + pub line: usize, + pub column: usize, + pub index: usize, +} +#[test] +fn bindgen_test_layout_spv_position_t() { + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(spv_position_t)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spv_position_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).line as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spv_position_t), + "::", + stringify!(line) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).column as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spv_position_t), + "::", + stringify!(column) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).index as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spv_position_t), + "::", + stringify!(index) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_diagnostic_t { + pub position: spv_position_t, + pub error: *mut ::std::os::raw::c_char, + pub isTextSource: bool, +} +#[test] +fn bindgen_test_layout_spv_diagnostic_t() { + assert_eq!( + ::std::mem::size_of::(), + 40usize, + concat!("Size of: ", stringify!(spv_diagnostic_t)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spv_diagnostic_t)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).position as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spv_diagnostic_t), + "::", + stringify!(position) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).error as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(spv_diagnostic_t), + "::", + stringify!(error) + ) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::())).isTextSource as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(spv_diagnostic_t), + "::", + stringify!(isTextSource) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_context_t { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_validator_options_t { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_optimizer_options_t { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_reducer_options_t { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spv_fuzzer_options_t { + _unused: [u8; 0], +} +pub type spv_const_binary = *mut spv_const_binary_t; +pub type spv_binary = *mut spv_binary_t; +pub type spv_text = *mut spv_text_t; +pub type spv_position = *mut spv_position_t; +pub type spv_diagnostic = *mut spv_diagnostic_t; +pub type spv_const_context = *const spv_context_t; +pub type spv_context = *mut spv_context_t; +pub type spv_validator_options = *mut spv_validator_options_t; +pub type spv_const_validator_options = *const spv_validator_options_t; +pub type spv_optimizer_options = *mut spv_optimizer_options_t; +pub type spv_const_optimizer_options = *const spv_optimizer_options_t; +pub type spv_reducer_options = *mut spv_reducer_options_t; +pub type spv_const_reducer_options = *const spv_reducer_options_t; +pub type spv_fuzzer_options = *mut spv_fuzzer_options_t; +pub type spv_const_fuzzer_options = *const spv_fuzzer_options_t; +extern "C" { + pub fn spvSoftwareVersionString() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvSoftwareVersionDetailsString() -> *const ::std::os::raw::c_char; +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_target_env { + SPV_ENV_UNIVERSAL_1_0 = 0, + SPV_ENV_VULKAN_1_0 = 1, + SPV_ENV_UNIVERSAL_1_1 = 2, + SPV_ENV_OPENCL_2_1 = 3, + SPV_ENV_OPENCL_2_2 = 4, + SPV_ENV_OPENGL_4_0 = 5, + SPV_ENV_OPENGL_4_1 = 6, + SPV_ENV_OPENGL_4_2 = 7, + SPV_ENV_OPENGL_4_3 = 8, + SPV_ENV_OPENGL_4_5 = 9, + SPV_ENV_UNIVERSAL_1_2 = 10, + SPV_ENV_OPENCL_1_2 = 11, + SPV_ENV_OPENCL_EMBEDDED_1_2 = 12, + SPV_ENV_OPENCL_2_0 = 13, + SPV_ENV_OPENCL_EMBEDDED_2_0 = 14, + SPV_ENV_OPENCL_EMBEDDED_2_1 = 15, + SPV_ENV_OPENCL_EMBEDDED_2_2 = 16, + SPV_ENV_UNIVERSAL_1_3 = 17, + SPV_ENV_VULKAN_1_1 = 18, + SPV_ENV_WEBGPU_0 = 19, + SPV_ENV_UNIVERSAL_1_4 = 20, + SPV_ENV_VULKAN_1_1_SPIRV_1_4 = 21, + SPV_ENV_UNIVERSAL_1_5 = 22, + SPV_ENV_VULKAN_1_2 = 23, +} +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum spv_validator_limit { + spv_validator_limit_max_struct_members = 0, + spv_validator_limit_max_struct_depth = 1, + spv_validator_limit_max_local_variables = 2, + spv_validator_limit_max_global_variables = 3, + spv_validator_limit_max_switch_branches = 4, + spv_validator_limit_max_function_args = 5, + spv_validator_limit_max_control_flow_nesting_depth = 6, + spv_validator_limit_max_access_chain_indexes = 7, + spv_validator_limit_max_id_bound = 8, +} +extern "C" { + pub fn spvTargetEnvDescription(env: spv_target_env) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvParseTargetEnv(s: *const ::std::os::raw::c_char, env: *mut spv_target_env) -> bool; +} +extern "C" { + pub fn spvParseVulkanEnv(vulkan_ver: u32, spirv_ver: u32, env: *mut spv_target_env) -> bool; +} +extern "C" { + pub fn spvContextCreate(env: spv_target_env) -> spv_context; +} +extern "C" { + pub fn spvContextDestroy(context: spv_context); +} +extern "C" { + pub fn spvValidatorOptionsCreate() -> spv_validator_options; +} +extern "C" { + pub fn spvValidatorOptionsDestroy(options: spv_validator_options); +} +extern "C" { + pub fn spvValidatorOptionsSetUniversalLimit( + options: spv_validator_options, + limit_type: spv_validator_limit, + limit: u32, + ); +} +extern "C" { + pub fn spvValidatorOptionsSetRelaxStoreStruct(options: spv_validator_options, val: bool); +} +extern "C" { + pub fn spvValidatorOptionsSetRelaxLogicalPointer(options: spv_validator_options, val: bool); +} +extern "C" { + pub fn spvValidatorOptionsSetBeforeHlslLegalization(options: spv_validator_options, val: bool); +} +extern "C" { + pub fn spvValidatorOptionsSetRelaxBlockLayout(options: spv_validator_options, val: bool); +} +extern "C" { + pub fn spvValidatorOptionsSetUniformBufferStandardLayout( + options: spv_validator_options, + val: bool, + ); +} +extern "C" { + pub fn spvValidatorOptionsSetScalarBlockLayout(options: spv_validator_options, val: bool); +} +extern "C" { + pub fn spvValidatorOptionsSetSkipBlockLayout(options: spv_validator_options, val: bool); +} +extern "C" { + pub fn spvOptimizerOptionsCreate() -> spv_optimizer_options; +} +extern "C" { + pub fn spvOptimizerOptionsDestroy(options: spv_optimizer_options); +} +extern "C" { + pub fn spvOptimizerOptionsSetRunValidator(options: spv_optimizer_options, val: bool); +} +extern "C" { + pub fn spvOptimizerOptionsSetValidatorOptions( + options: spv_optimizer_options, + val: spv_validator_options, + ); +} +extern "C" { + pub fn spvOptimizerOptionsSetMaxIdBound(options: spv_optimizer_options, val: u32); +} +extern "C" { + pub fn spvOptimizerOptionsSetPreserveBindings(options: spv_optimizer_options, val: bool); +} +extern "C" { + pub fn spvOptimizerOptionsSetPreserveSpecConstants(options: spv_optimizer_options, val: bool); +} +extern "C" { + pub fn spvReducerOptionsCreate() -> spv_reducer_options; +} +extern "C" { + pub fn spvReducerOptionsDestroy(options: spv_reducer_options); +} +extern "C" { + pub fn spvReducerOptionsSetStepLimit(options: spv_reducer_options, step_limit: u32); +} +extern "C" { + pub fn spvReducerOptionsSetFailOnValidationError( + options: spv_reducer_options, + fail_on_validation_error: bool, + ); +} +extern "C" { + pub fn spvFuzzerOptionsCreate() -> spv_fuzzer_options; +} +extern "C" { + pub fn spvFuzzerOptionsDestroy(options: spv_fuzzer_options); +} +extern "C" { + pub fn spvFuzzerOptionsEnableReplayValidation(options: spv_fuzzer_options); +} +extern "C" { + pub fn spvFuzzerOptionsSetRandomSeed(options: spv_fuzzer_options, seed: u32); +} +extern "C" { + pub fn spvFuzzerOptionsSetShrinkerStepLimit( + options: spv_fuzzer_options, + shrinker_step_limit: u32, + ); +} +extern "C" { + pub fn spvFuzzerOptionsEnableFuzzerPassValidation(options: spv_fuzzer_options); +} +extern "C" { + pub fn spvTextToBinary( + context: spv_const_context, + text: *const ::std::os::raw::c_char, + length: usize, + binary: *mut spv_binary, + diagnostic: *mut spv_diagnostic, + ) -> spv_result_t; +} +extern "C" { + pub fn spvTextToBinaryWithOptions( + context: spv_const_context, + text: *const ::std::os::raw::c_char, + length: usize, + options: u32, + binary: *mut spv_binary, + diagnostic: *mut spv_diagnostic, + ) -> spv_result_t; +} +extern "C" { + pub fn spvTextDestroy(text: spv_text); +} +extern "C" { + pub fn spvBinaryToText( + context: spv_const_context, + binary: *const u32, + word_count: usize, + options: u32, + text: *mut spv_text, + diagnostic: *mut spv_diagnostic, + ) -> spv_result_t; +} +extern "C" { + pub fn spvBinaryDestroy(binary: spv_binary); +} +extern "C" { + pub fn spvValidate( + context: spv_const_context, + binary: spv_const_binary, + diagnostic: *mut spv_diagnostic, + ) -> spv_result_t; +} +extern "C" { + pub fn spvValidateWithOptions( + context: spv_const_context, + options: spv_const_validator_options, + binary: spv_const_binary, + diagnostic: *mut spv_diagnostic, + ) -> spv_result_t; +} +extern "C" { + pub fn spvValidateBinary( + context: spv_const_context, + words: *const u32, + num_words: usize, + diagnostic: *mut spv_diagnostic, + ) -> spv_result_t; +} +extern "C" { + pub fn spvDiagnosticCreate( + position: spv_position, + message: *const ::std::os::raw::c_char, + ) -> spv_diagnostic; +} +extern "C" { + pub fn spvDiagnosticDestroy(diagnostic: spv_diagnostic); +} +extern "C" { + pub fn spvDiagnosticPrint(diagnostic: spv_diagnostic) -> spv_result_t; +} +extern "C" { + pub fn spvOpcodeString(opcode: u32) -> *const ::std::os::raw::c_char; +} +pub type spv_parsed_header_fn_t = ::std::option::Option< + unsafe extern "C" fn( + user_data: *mut ::std::os::raw::c_void, + endian: spv_endianness_t, + magic: u32, + version: u32, + generator: u32, + id_bound: u32, + reserved: u32, + ) -> spv_result_t, +>; +pub type spv_parsed_instruction_fn_t = ::std::option::Option< + unsafe extern "C" fn( + user_data: *mut ::std::os::raw::c_void, + parsed_instruction: *const spv_parsed_instruction_t, + ) -> spv_result_t, +>; +extern "C" { + pub fn spvBinaryParse( + context: spv_const_context, + user_data: *mut ::std::os::raw::c_void, + words: *const u32, + num_words: usize, + parse_header: spv_parsed_header_fn_t, + parse_instruction: spv_parsed_instruction_fn_t, + diagnostic: *mut spv_diagnostic, + ) -> spv_result_t; +}