Validate PTX build tests against SPIR-V sources

This commit is contained in:
Andrzej Janik 2020-07-12 14:58:54 +02:00
parent 279e6246ba
commit f2f3eeb303
14 changed files with 1138 additions and 12 deletions

7
.gitmodules vendored Normal file
View file

@ -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

View file

@ -3,6 +3,7 @@
members = [
"level_zero-sys",
"level_zero",
"spirv_tools-sys",
"notcuda",
"notcuda_inject",
"notcuda_redirect",

1
ext/spirv-headers Submodule

@ -0,0 +1 @@
Subproject commit 308bd07424350a6000f35a77b5f85cd4f3da319e

1
ext/spirv-tools Submodule

@ -0,0 +1 @@
Subproject commit e128ab0d624ce7beb08eb9656bb260c597a46d0a

View file

@ -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" }

View file

@ -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

View file

@ -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

View file

@ -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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<T: From<u8> + 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<dyn error::Error + 'a>> {
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::<u32>::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<Word, Word>) {
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<Word, Word>) {
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<Word, Word>) {
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<T, F: FnOnce(&T, &T, &mut HashMap<Word, Word>)>(
o1: &Option<T>,
o2: &Option<T>,
map: &mut HashMap<Word, Word>,
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<u32> = 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<u32> = 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
}

View file

@ -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<Vec<u32>, dr::Error> {
pub fn to_spirv_module(ast: ast::Module) -> Result<dr::Module, dr::Error> {
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<Vec<u32>, 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<Vec<u32>, dr::Error> {
let module = to_spirv_module(ast)?;
Ok(module.assemble())
}

View file

@ -0,0 +1,10 @@
[package]
name = "spirv_tools-sys"
version = "0.0.0"
authors = ["Andrzej Janik <vosen@vosen.pl>"]
edition = "2018"
[lib]
[build-dependencies]
cmake = "0.1"

1
spirv_tools-sys/README Normal file
View file

@ -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

24
spirv_tools-sys/build.rs Normal file
View file

@ -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(())
}

View file

@ -0,0 +1,3 @@
#[allow(warnings)]
mod spirv_tools;
pub use spirv_tools::*;

View file

@ -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::<spv_parsed_operand_t>(),
16usize,
concat!("Size of: ", stringify!(spv_parsed_operand_t))
);
assert_eq!(
::std::mem::align_of::<spv_parsed_operand_t>(),
4usize,
concat!("Alignment of ", stringify!(spv_parsed_operand_t))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_parsed_operand_t>())).offset as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(spv_parsed_operand_t),
"::",
stringify!(offset)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_parsed_operand_t>())).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::<spv_parsed_operand_t>())).type_ as *const _ as usize },
4usize,
concat!(
"Offset of field: ",
stringify!(spv_parsed_operand_t),
"::",
stringify!(type_)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<spv_parsed_operand_t>())).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::<spv_parsed_operand_t>())).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::<spv_parsed_instruction_t>(),
40usize,
concat!("Size of: ", stringify!(spv_parsed_instruction_t))
);
assert_eq!(
::std::mem::align_of::<spv_parsed_instruction_t>(),
8usize,
concat!("Alignment of ", stringify!(spv_parsed_instruction_t))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_parsed_instruction_t>())).words as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(spv_parsed_instruction_t),
"::",
stringify!(words)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<spv_parsed_instruction_t>())).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::<spv_parsed_instruction_t>())).opcode as *const _ as usize },
10usize,
concat!(
"Offset of field: ",
stringify!(spv_parsed_instruction_t),
"::",
stringify!(opcode)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<spv_parsed_instruction_t>())).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::<spv_parsed_instruction_t>())).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::<spv_parsed_instruction_t>())).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::<spv_parsed_instruction_t>())).operands as *const _ as usize
},
24usize,
concat!(
"Offset of field: ",
stringify!(spv_parsed_instruction_t),
"::",
stringify!(operands)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<spv_parsed_instruction_t>())).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::<spv_const_binary_t>(),
16usize,
concat!("Size of: ", stringify!(spv_const_binary_t))
);
assert_eq!(
::std::mem::align_of::<spv_const_binary_t>(),
8usize,
concat!("Alignment of ", stringify!(spv_const_binary_t))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_const_binary_t>())).code as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(spv_const_binary_t),
"::",
stringify!(code)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_const_binary_t>())).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::<spv_binary_t>(),
16usize,
concat!("Size of: ", stringify!(spv_binary_t))
);
assert_eq!(
::std::mem::align_of::<spv_binary_t>(),
8usize,
concat!("Alignment of ", stringify!(spv_binary_t))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_binary_t>())).code as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(spv_binary_t),
"::",
stringify!(code)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_binary_t>())).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::<spv_text_t>(),
16usize,
concat!("Size of: ", stringify!(spv_text_t))
);
assert_eq!(
::std::mem::align_of::<spv_text_t>(),
8usize,
concat!("Alignment of ", stringify!(spv_text_t))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_text_t>())).str_ as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(spv_text_t),
"::",
stringify!(str_)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_text_t>())).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::<spv_position_t>(),
24usize,
concat!("Size of: ", stringify!(spv_position_t))
);
assert_eq!(
::std::mem::align_of::<spv_position_t>(),
8usize,
concat!("Alignment of ", stringify!(spv_position_t))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_position_t>())).line as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(spv_position_t),
"::",
stringify!(line)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_position_t>())).column as *const _ as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(spv_position_t),
"::",
stringify!(column)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_position_t>())).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::<spv_diagnostic_t>(),
40usize,
concat!("Size of: ", stringify!(spv_diagnostic_t))
);
assert_eq!(
::std::mem::align_of::<spv_diagnostic_t>(),
8usize,
concat!("Alignment of ", stringify!(spv_diagnostic_t))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_diagnostic_t>())).position as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(spv_diagnostic_t),
"::",
stringify!(position)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_diagnostic_t>())).error as *const _ as usize },
24usize,
concat!(
"Offset of field: ",
stringify!(spv_diagnostic_t),
"::",
stringify!(error)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<spv_diagnostic_t>())).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;
}