mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 22:34:43 +00:00
Some shader fixes and improvements (#2280)
This commit is contained in:
parent
b00e6627b4
commit
cf8e8c3732
@ -440,17 +440,7 @@ fn read_spirv_words_from_file(path: impl AsRef<Path>) -> Vec<u32> {
|
||||
});
|
||||
file.read_to_end(&mut bytes).unwrap();
|
||||
|
||||
// Convert the bytes to words.
|
||||
// SPIR-V is defined to be always little-endian, so this may need an endianness conversion.
|
||||
assert!(
|
||||
bytes.len() % 4 == 0,
|
||||
"file `{}` does not contain a whole number of SPIR-V words",
|
||||
path.display(),
|
||||
);
|
||||
|
||||
// TODO: Use `slice::array_chunks` once it's stable.
|
||||
bytes
|
||||
.chunks_exact(4)
|
||||
.map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap()))
|
||||
.collect()
|
||||
vulkano::shader::spirv::bytes_to_words(&bytes)
|
||||
.unwrap_or_else(|err| panic!("file `{}`: {}", path.display(), err))
|
||||
.into_owned()
|
||||
}
|
||||
|
@ -230,7 +230,6 @@ use shaderc::{EnvVersion, SpirvVersion};
|
||||
use std::{
|
||||
env, fs, mem,
|
||||
path::{Path, PathBuf},
|
||||
slice,
|
||||
};
|
||||
use structs::TypeRegistry;
|
||||
use syn::{
|
||||
@ -336,20 +335,10 @@ fn shader_inner(mut input: MacroInput) -> Result<TokenStream> {
|
||||
let bytes = fs::read(&full_path)
|
||||
.or_else(|err| bail!(path, "failed to read source `{full_path:?}`: {err}"))?;
|
||||
|
||||
if bytes.len() % 4 != 0 {
|
||||
bail!(path, "SPIR-V bytes must be an integer multiple of 4");
|
||||
}
|
||||
let words = vulkano::shader::spirv::bytes_to_words(&bytes)
|
||||
.or_else(|err| bail!(path, "failed to read source `{full_path:?}`: {err}"))?;
|
||||
|
||||
// Here, we are praying that the system allocator of the user aligns allocations to
|
||||
// at least 4, which *should* be the case on all targets.
|
||||
assert_eq!(bytes.as_ptr() as usize % 4, 0);
|
||||
|
||||
// SAFETY: We checked that the bytes are aligned correctly for `u32`, and that
|
||||
// there is an integer number of `u32`s contained.
|
||||
let words =
|
||||
unsafe { slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len() / 4) };
|
||||
|
||||
codegen::reflect(&input, path, name, words, Vec::new(), &mut type_registry)?
|
||||
codegen::reflect(&input, path, name, &words, Vec::new(), &mut type_registry)?
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -667,12 +667,7 @@ impl TypeStruct {
|
||||
Instruction::Name { name, .. } => Some(Ident::new(name, Span::call_site())),
|
||||
_ => None,
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
Error::new_spanned(
|
||||
&shader.source,
|
||||
"expected struct in shader interface to have an associated `Name` instruction",
|
||||
)
|
||||
})?;
|
||||
.unwrap_or_else(|| format_ident!("Unnamed{}", struct_id.as_raw()));
|
||||
|
||||
let mut members = Vec::<Member>::with_capacity(member_type_ids.len());
|
||||
|
||||
@ -822,7 +817,10 @@ impl TypeStruct {
|
||||
members.push(Member { ident, ty, offset });
|
||||
}
|
||||
|
||||
Ok(TypeStruct { ident, members })
|
||||
Ok(TypeStruct {
|
||||
ident,
|
||||
members,
|
||||
})
|
||||
}
|
||||
|
||||
fn size(&self) -> Option<usize> {
|
||||
|
@ -151,7 +151,7 @@ use spirv::ExecutionModel;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::hash_map::Entry,
|
||||
mem::{align_of, discriminant, size_of, size_of_val, MaybeUninit},
|
||||
mem::{discriminant, size_of_val, MaybeUninit},
|
||||
num::NonZeroU64,
|
||||
ptr,
|
||||
sync::Arc,
|
||||
@ -357,23 +357,15 @@ impl ShaderModule {
|
||||
/// - Panics if the length of `bytes` is not a multiple of 4.
|
||||
#[deprecated(
|
||||
since = "0.34.0",
|
||||
note = "read little-endian words yourself, and then use `new` instead"
|
||||
note = "use `shader::spirv::bytes_to_words`, and then use `new` instead"
|
||||
)]
|
||||
#[inline]
|
||||
pub unsafe fn from_bytes(
|
||||
device: Arc<Device>,
|
||||
bytes: &[u8],
|
||||
) -> Result<Arc<ShaderModule>, Validated<VulkanError>> {
|
||||
assert!(bytes.as_ptr() as usize % align_of::<u32>() == 0);
|
||||
assert!(bytes.len() % size_of::<u32>() == 0);
|
||||
|
||||
Self::new(
|
||||
device,
|
||||
ShaderModuleCreateInfo::new(std::slice::from_raw_parts(
|
||||
bytes.as_ptr() as *const _,
|
||||
bytes.len() / size_of::<u32>(),
|
||||
)),
|
||||
)
|
||||
let words = spirv::bytes_to_words(bytes).unwrap();
|
||||
Self::new(device, ShaderModuleCreateInfo::new(&words))
|
||||
}
|
||||
|
||||
/// Returns information about the entry point with the provided name. Returns `None` if no entry
|
||||
|
@ -18,6 +18,7 @@
|
||||
use crate::Version;
|
||||
use ahash::{HashMap, HashMapExt};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
error::Error,
|
||||
fmt::{Display, Error as FmtError, Formatter},
|
||||
ops::Range,
|
||||
@ -563,10 +564,18 @@ impl<'a> StructMemberInfo<'a> {
|
||||
#[repr(transparent)]
|
||||
pub struct Id(u32);
|
||||
|
||||
impl Id {
|
||||
// Returns the raw numeric value of this Id.
|
||||
#[inline]
|
||||
pub const fn as_raw(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Id> for u32 {
|
||||
#[inline]
|
||||
fn from(id: Id) -> u32 {
|
||||
id.0
|
||||
id.as_raw()
|
||||
}
|
||||
}
|
||||
|
||||
@ -792,3 +801,37 @@ impl Display for ParseErrors {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts SPIR-V bytes to words. If necessary, the byte order is swapped from little-endian
|
||||
/// to native-endian.
|
||||
pub fn bytes_to_words(bytes: &[u8]) -> Result<Cow<'_, [u32]>, SpirvBytesNotMultipleOf4> {
|
||||
// If the current target is little endian, and the slice already has the right size and
|
||||
// alignment, then we can just transmute the slice with bytemuck.
|
||||
#[cfg(target_endian = "little")]
|
||||
if let Ok(words) = bytemuck::try_cast_slice(bytes) {
|
||||
return Ok(Cow::Borrowed(words));
|
||||
}
|
||||
|
||||
if bytes.len() % 4 != 0 {
|
||||
return Err(SpirvBytesNotMultipleOf4);
|
||||
}
|
||||
|
||||
// TODO: Use `slice::array_chunks` once it's stable.
|
||||
let words: Vec<u32> = bytes
|
||||
.chunks_exact(4)
|
||||
.map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap()))
|
||||
.collect();
|
||||
|
||||
Ok(Cow::Owned(words))
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct SpirvBytesNotMultipleOf4;
|
||||
|
||||
impl Error for SpirvBytesNotMultipleOf4 {}
|
||||
|
||||
impl Display for SpirvBytesNotMultipleOf4 {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "the length of the provided slice is not a multiple of 4")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user