rusticl: use blob for all serialization

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30351>
This commit is contained in:
Karol Herbst
2024-07-24 15:40:36 +02:00
committed by Marge Bot
parent dc896c31f9
commit b58390bca2
3 changed files with 159 additions and 163 deletions

View File

@@ -41,6 +41,7 @@ pub enum KernelArgValue {
Sampler(Arc<Sampler>),
}
#[repr(u8)]
#[derive(Hash, PartialEq, Eq, Clone, Copy)]
pub enum KernelArgType {
Constant = 0, // for anything passed by value
@@ -161,103 +162,123 @@ impl KernelArg {
}
}
fn serialize(&self) -> Vec<u8> {
let mut bin = Vec::new();
fn serialize(args: &[Self], blob: &mut blob) {
unsafe {
blob_write_uint16(blob, args.len() as u16);
bin.append(&mut self.spirv.serialize());
bin.extend_from_slice(&self.size.to_ne_bytes());
bin.extend_from_slice(&self.offset.to_ne_bytes());
bin.extend_from_slice(&self.binding.to_ne_bytes());
bin.extend_from_slice(&(self.dead as u8).to_ne_bytes());
bin.extend_from_slice(&(self.kind as u8).to_ne_bytes());
bin
for arg in args {
arg.spirv.serialize(blob);
blob_write_uint16(blob, arg.size as u16);
blob_write_uint16(blob, arg.offset as u16);
blob_write_uint16(blob, arg.binding as u16);
blob_write_uint8(blob, arg.dead.into());
blob_write_uint8(blob, arg.kind as u8);
}
}
}
fn deserialize(bin: &mut &[u8]) -> Option<Self> {
let spirv = spirv::SPIRVKernelArg::deserialize(bin)?;
let size = read_ne_usize(bin);
let offset = read_ne_usize(bin);
let binding = read_ne_u32(bin);
let dead = read_ne_u8(bin) == 1;
fn deserialize(blob: &mut blob_reader) -> Option<Vec<Self>> {
unsafe {
let len = blob_read_uint16(blob) as usize;
let mut res = Vec::with_capacity(len);
let kind = match read_ne_u8(bin) {
0 => KernelArgType::Constant,
1 => KernelArgType::Image,
2 => KernelArgType::RWImage,
3 => KernelArgType::Sampler,
4 => KernelArgType::Texture,
5 => KernelArgType::MemGlobal,
6 => KernelArgType::MemConstant,
7 => KernelArgType::MemLocal,
_ => return None,
};
for _ in 0..len {
let spirv = spirv::SPIRVKernelArg::deserialize(blob)?;
let size = blob_read_uint16(blob) as usize;
let offset = blob_read_uint16(blob) as usize;
let binding = blob_read_uint16(blob) as u32;
let dead = blob_read_uint8(blob) != 0;
Some(Self {
spirv: spirv,
kind: kind,
size: size,
offset: offset,
binding: binding,
dead: dead,
})
let kind = match blob_read_uint8(blob) {
0 => KernelArgType::Constant,
1 => KernelArgType::Image,
2 => KernelArgType::RWImage,
3 => KernelArgType::Sampler,
4 => KernelArgType::Texture,
5 => KernelArgType::MemGlobal,
6 => KernelArgType::MemConstant,
7 => KernelArgType::MemLocal,
_ => return None,
};
res.push(Self {
spirv: spirv,
kind: kind,
size: size,
offset: offset,
binding: binding,
dead: dead,
});
}
Some(res)
}
}
}
impl InternalKernelArg {
fn serialize(&self) -> Vec<u8> {
let mut bin = Vec::new();
bin.extend_from_slice(&self.size.to_ne_bytes());
bin.extend_from_slice(&self.offset.to_ne_bytes());
match self.kind {
InternalKernelArgType::ConstantBuffer => bin.push(0),
InternalKernelArgType::GlobalWorkOffsets => bin.push(1),
InternalKernelArgType::PrintfBuffer => bin.push(2),
InternalKernelArgType::InlineSampler((addr_mode, filter_mode, norm)) => {
bin.push(3);
bin.extend_from_slice(&addr_mode.to_ne_bytes());
bin.extend_from_slice(&filter_mode.to_ne_bytes());
bin.push(norm as u8);
fn serialize(args: &[Self], blob: &mut blob) {
unsafe {
blob_write_uint16(blob, args.len() as u16);
for arg in args {
blob_write_uint16(blob, arg.size as u16);
blob_write_uint16(blob, arg.offset as u16);
match arg.kind {
InternalKernelArgType::ConstantBuffer => blob_write_uint8(blob, 0),
InternalKernelArgType::GlobalWorkOffsets => blob_write_uint8(blob, 1),
InternalKernelArgType::PrintfBuffer => blob_write_uint8(blob, 2),
InternalKernelArgType::InlineSampler((addr_mode, filter_mode, norm)) => {
blob_write_uint8(blob, 3);
blob_write_uint8(blob, norm.into());
blob_write_uint32(blob, addr_mode);
blob_write_uint32(blob, filter_mode)
}
InternalKernelArgType::FormatArray => blob_write_uint8(blob, 4),
InternalKernelArgType::OrderArray => blob_write_uint8(blob, 5),
InternalKernelArgType::WorkDim => blob_write_uint8(blob, 6),
InternalKernelArgType::WorkGroupOffsets => blob_write_uint8(blob, 7),
InternalKernelArgType::NumWorkgroups => blob_write_uint8(blob, 8),
};
}
InternalKernelArgType::FormatArray => bin.push(4),
InternalKernelArgType::OrderArray => bin.push(5),
InternalKernelArgType::WorkDim => bin.push(6),
InternalKernelArgType::WorkGroupOffsets => bin.push(7),
InternalKernelArgType::NumWorkgroups => bin.push(8),
}
bin
}
fn deserialize(bin: &mut &[u8]) -> Option<Self> {
let size = read_ne_usize(bin);
let offset = read_ne_usize(bin);
fn deserialize(blob: &mut blob_reader) -> Option<Vec<Self>> {
unsafe {
let len = blob_read_uint16(blob) as usize;
let mut res = Vec::with_capacity(len);
let kind = match read_ne_u8(bin) {
0 => InternalKernelArgType::ConstantBuffer,
1 => InternalKernelArgType::GlobalWorkOffsets,
2 => InternalKernelArgType::PrintfBuffer,
3 => {
let addr_mode = read_ne_u32(bin);
let filter_mode = read_ne_u32(bin);
let norm = read_ne_u8(bin) == 1;
InternalKernelArgType::InlineSampler((addr_mode, filter_mode, norm))
for _ in 0..len {
let size = blob_read_uint16(blob) as usize;
let offset = blob_read_uint16(blob) as usize;
let kind = match blob_read_uint8(blob) {
0 => InternalKernelArgType::ConstantBuffer,
1 => InternalKernelArgType::GlobalWorkOffsets,
2 => InternalKernelArgType::PrintfBuffer,
3 => {
let norm = blob_read_uint8(blob) != 0;
let addr_mode = blob_read_uint32(blob);
let filter_mode = blob_read_uint32(blob);
InternalKernelArgType::InlineSampler((addr_mode, filter_mode, norm))
}
4 => InternalKernelArgType::FormatArray,
5 => InternalKernelArgType::OrderArray,
6 => InternalKernelArgType::WorkDim,
7 => InternalKernelArgType::WorkGroupOffsets,
8 => InternalKernelArgType::NumWorkgroups,
_ => return None,
};
res.push(Self {
kind: kind,
size: size,
offset: offset,
});
}
4 => InternalKernelArgType::FormatArray,
5 => InternalKernelArgType::OrderArray,
6 => InternalKernelArgType::WorkDim,
7 => InternalKernelArgType::WorkGroupOffsets,
8 => InternalKernelArgType::NumWorkgroups,
_ => return None,
};
Some(Self {
kind: kind,
size: size,
offset: offset,
})
Some(res)
}
}
}
@@ -813,28 +834,19 @@ fn deserialize_nir(
bin: &mut &[u8],
d: &Device,
) -> Option<(NirShader, Vec<KernelArg>, Vec<InternalKernelArg>)> {
let nir_len = read_ne_usize(bin);
let mut reader = blob_reader::default();
unsafe {
blob_reader_init(&mut reader, bin.as_ptr().cast(), bin.len());
}
let nir = NirShader::deserialize(
bin,
nir_len,
&mut reader,
d.screen()
.nir_shader_compiler_options(pipe_shader_type::PIPE_SHADER_COMPUTE),
)?;
let arg_len = read_ne_usize(bin);
let mut args = Vec::with_capacity(arg_len);
for _ in 0..arg_len {
args.push(KernelArg::deserialize(bin)?);
}
let arg_len = read_ne_usize(bin);
let mut internal_args = Vec::with_capacity(arg_len);
for _ in 0..arg_len {
internal_args.push(InternalKernelArg::deserialize(bin)?);
}
assert!(bin.is_empty());
let args = KernelArg::deserialize(&mut reader)?;
let internal_args = InternalKernelArg::deserialize(&mut reader)?;
Some((nir, args, internal_args))
}
@@ -865,23 +877,16 @@ pub(super) fn convert_spirv_to_nir(
let (args, internal_args) = lower_and_optimize_nir(dev, &mut nir, args, &dev.lib_clc);
if let Some(cache) = cache {
let mut bin = Vec::new();
let mut nir = nir.serialize();
bin.extend_from_slice(&nir.len().to_ne_bytes());
bin.append(&mut nir);
bin.extend_from_slice(&args.len().to_ne_bytes());
for arg in &args {
bin.append(&mut arg.serialize());
let mut blob = blob::default();
unsafe {
blob_init(&mut blob);
nir.serialize(&mut blob);
KernelArg::serialize(&args, &mut blob);
InternalKernelArg::serialize(&internal_args, &mut blob);
let bin = slice::from_raw_parts(blob.data, blob.size);
cache.put(bin, &mut key.unwrap());
blob_finish(&mut blob);
}
bin.extend_from_slice(&internal_args.len().to_ne_bytes());
for arg in &internal_args {
bin.append(&mut arg.serialize());
}
cache.put(&bin, &mut key.unwrap());
}
(nir, args, internal_args)

View File

@@ -441,46 +441,51 @@ impl Drop for SPIRVBin {
}
impl SPIRVKernelArg {
pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::new();
pub fn serialize(&self, blob: &mut blob) {
let name_arr = self.name.as_bytes();
let type_name_arr = self.type_name.as_bytes();
res.extend_from_slice(&name_arr.len().to_ne_bytes());
res.extend_from_slice(name_arr);
res.extend_from_slice(&type_name_arr.len().to_ne_bytes());
res.extend_from_slice(type_name_arr);
res.extend_from_slice(&u32::to_ne_bytes(self.access_qualifier.0));
res.extend_from_slice(&u32::to_ne_bytes(self.type_qualifier.0));
res.push(self.address_qualifier as u8);
unsafe {
blob_write_uint32(blob, self.access_qualifier.0);
blob_write_uint32(blob, self.type_qualifier.0);
res
blob_write_uint16(blob, name_arr.len() as u16);
blob_write_uint16(blob, type_name_arr.len() as u16);
blob_write_bytes(blob, name_arr.as_ptr().cast(), name_arr.len());
blob_write_bytes(blob, type_name_arr.as_ptr().cast(), type_name_arr.len());
blob_write_uint8(blob, self.address_qualifier as u8);
}
}
pub fn deserialize(bin: &mut &[u8]) -> Option<Self> {
let name_len = read_ne_usize(bin);
let name = read_string(bin, name_len)?;
let type_len = read_ne_usize(bin);
let type_name = read_string(bin, type_len)?;
let access_qualifier = read_ne_u32(bin);
let type_qualifier = read_ne_u32(bin);
pub fn deserialize(blob: &mut blob_reader) -> Option<Self> {
unsafe {
let access_qualifier = blob_read_uint32(blob);
let type_qualifier = blob_read_uint32(blob);
let address_qualifier = match read_ne_u8(bin) {
0 => clc_kernel_arg_address_qualifier::CLC_KERNEL_ARG_ADDRESS_PRIVATE,
1 => clc_kernel_arg_address_qualifier::CLC_KERNEL_ARG_ADDRESS_CONSTANT,
2 => clc_kernel_arg_address_qualifier::CLC_KERNEL_ARG_ADDRESS_LOCAL,
3 => clc_kernel_arg_address_qualifier::CLC_KERNEL_ARG_ADDRESS_GLOBAL,
_ => return None,
};
let name_len = blob_read_uint16(blob) as usize;
let type_len = blob_read_uint16(blob) as usize;
Some(Self {
name: name,
type_name: type_name,
access_qualifier: clc_kernel_arg_access_qualifier(access_qualifier),
address_qualifier: address_qualifier,
type_qualifier: clc_kernel_arg_type_qualifier(type_qualifier),
})
let name = slice::from_raw_parts(blob_read_bytes(blob, name_len).cast(), name_len);
let type_name = slice::from_raw_parts(blob_read_bytes(blob, type_len).cast(), type_len);
let address_qualifier = match blob_read_uint8(blob) {
0 => clc_kernel_arg_address_qualifier::CLC_KERNEL_ARG_ADDRESS_PRIVATE,
1 => clc_kernel_arg_address_qualifier::CLC_KERNEL_ARG_ADDRESS_CONSTANT,
2 => clc_kernel_arg_address_qualifier::CLC_KERNEL_ARG_ADDRESS_LOCAL,
3 => clc_kernel_arg_address_qualifier::CLC_KERNEL_ARG_ADDRESS_GLOBAL,
_ => return None,
};
Some(Self {
name: String::from_utf8_unchecked(name.to_owned()),
type_name: String::from_utf8_unchecked(type_name.to_owned()),
access_qualifier: clc_kernel_arg_access_qualifier(access_qualifier),
address_qualifier: address_qualifier,
type_qualifier: clc_kernel_arg_type_qualifier(type_qualifier),
})
}
}
}

View File

@@ -156,29 +156,15 @@ impl NirShader {
}
pub fn deserialize(
input: &mut &[u8],
len: usize,
blob: &mut blob_reader,
options: *const nir_shader_compiler_options,
) -> Option<Self> {
let mut reader = blob_reader::default();
let (bin, rest) = input.split_at(len);
*input = rest;
unsafe {
blob_reader_init(&mut reader, bin.as_ptr().cast(), len);
Self::new(nir_deserialize(ptr::null_mut(), options, &mut reader))
}
unsafe { Self::new(nir_deserialize(ptr::null_mut(), options, blob)) }
}
pub fn serialize(&self) -> Vec<u8> {
let mut blob = blob::default();
pub fn serialize(&self, blob: &mut blob) {
unsafe {
blob_init(&mut blob);
nir_serialize(&mut blob, self.nir.as_ptr(), false);
let res = slice::from_raw_parts(blob.data, blob.size).to_vec();
blob_finish(&mut blob);
res
nir_serialize(blob, self.nir.as_ptr(), false);
}
}