mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 22:34:43 +00:00
* add `exact_entrypoint_interface` flag to vulkano-shaders Signed-off-by: Arc-blroth <45273859+Arc-blroth@users.noreply.github.com> * cargo fmt Signed-off-by: Arc-blroth <45273859+Arc-blroth@users.noreply.github.com> * oops Signed-off-by: Arc-blroth <45273859+Arc-blroth@users.noreply.github.com>
This commit is contained in:
parent
f1dad10cd4
commit
a83f0fe489
@ -37,6 +37,8 @@
|
||||
- Traits that no longer make sense in this context have been removed: `FormatDesc`, the `Possible*FormatDesc` traits, `StrongStorage`.
|
||||
- In types that had a type parameter for the format type, it has been removed.
|
||||
- `AcceptsPixels` has been converted to `Pixel`, which is implemented on the pixel type rather than on the format type.
|
||||
- **Breaking** `shader!` will generate descriptor information for all variables declared in the shader module, even if they are not used. *This reverts the default behavior from the last release.*
|
||||
- **Breaking** Added the `exact_entrypoint_interface` option to `shader!` to force vulkano to only generate descriptor information for variables that are used. (the default behavior from the last release)
|
||||
- Added two methods to `Format`: `planes` to query the number of planes in the format, and `aspects` to query what aspects an image of this type has.
|
||||
- The deprecated `cause` trait function on Vulkano error types is replaced with `source`.
|
||||
- Fixed bug in descriptor array layers check when the image is a cubemap.
|
||||
|
@ -204,6 +204,7 @@ pub(super) fn reflect<'a, I>(
|
||||
spirv: &[u32],
|
||||
types_meta: TypesMeta,
|
||||
input_paths: I,
|
||||
exact_entrypoint_interface: bool,
|
||||
dump: bool,
|
||||
) -> Result<TokenStream, Error>
|
||||
where
|
||||
@ -263,8 +264,12 @@ where
|
||||
let mut entry_points_outside_impl: Vec<TokenStream> = vec![];
|
||||
for instruction in doc.instructions.iter() {
|
||||
if let &Instruction::EntryPoint { .. } = instruction {
|
||||
let (outside, entry_point, descriptor_sets) =
|
||||
entry_point::write_entry_point(&doc, instruction, &types_meta);
|
||||
let (outside, entry_point, descriptor_sets) = entry_point::write_entry_point(
|
||||
&doc,
|
||||
instruction,
|
||||
&types_meta,
|
||||
exact_entrypoint_interface,
|
||||
);
|
||||
entry_points_inside_impl.push(entry_point);
|
||||
entry_points_outside_impl.push(outside);
|
||||
entry_points_outside_impl.push(descriptor_sets);
|
||||
|
@ -31,11 +31,12 @@ pub(super) fn write_descriptor_sets(
|
||||
entrypoint_id: u32,
|
||||
interface: &[u32],
|
||||
types_meta: &TypesMeta,
|
||||
exact_entrypoint_interface: bool,
|
||||
) -> TokenStream {
|
||||
// TODO: somewhat implemented correctly
|
||||
|
||||
// Finding all the descriptors.
|
||||
let descriptors = find_descriptors(doc, entrypoint_id, interface);
|
||||
let descriptors = find_descriptors(doc, entrypoint_id, interface, exact_entrypoint_interface);
|
||||
|
||||
// Looping to find all the push constant structs.
|
||||
let mut push_constants_size = 0;
|
||||
@ -138,14 +139,19 @@ pub(super) fn write_descriptor_sets(
|
||||
}
|
||||
}
|
||||
|
||||
fn find_descriptors(doc: &Spirv, entrypoint_id: u32, interface: &[u32]) -> Vec<Descriptor> {
|
||||
fn find_descriptors(
|
||||
doc: &Spirv,
|
||||
entrypoint_id: u32,
|
||||
interface: &[u32],
|
||||
exact: bool,
|
||||
) -> Vec<Descriptor> {
|
||||
let mut descriptors = Vec::new();
|
||||
|
||||
// For SPIR-V 1.4+, the entrypoint interface can specify variables of all storage classes,
|
||||
// and most tools will put all used variables in the entrypoint interface. However,
|
||||
// SPIR-V 1.0-1.3 do not specify variables other than Input/Output ones in the interface,
|
||||
// and instead the function itself must be inspected.
|
||||
let variables = {
|
||||
let variables = if exact {
|
||||
let mut found_variables: HashSet<u32> = interface.iter().cloned().collect();
|
||||
let mut inspected_functions: HashSet<u32> = HashSet::new();
|
||||
find_variables_in_function(
|
||||
@ -154,14 +160,16 @@ fn find_descriptors(doc: &Spirv, entrypoint_id: u32, interface: &[u32]) -> Vec<D
|
||||
&mut inspected_functions,
|
||||
&mut found_variables,
|
||||
);
|
||||
found_variables
|
||||
Some(found_variables)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Looping to find all the interface elements that have the `DescriptorSet` decoration.
|
||||
for set_decoration in doc.get_decorations(Decoration::DecorationDescriptorSet) {
|
||||
let variable_id = set_decoration.target_id;
|
||||
|
||||
if !variables.contains(&variable_id) {
|
||||
if exact && !variables.as_ref().unwrap().contains(&variable_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -650,7 +658,7 @@ mod tests {
|
||||
id, ref interface, ..
|
||||
} = instruction
|
||||
{
|
||||
descriptors.push(find_descriptors(&doc, id, interface));
|
||||
descriptors.push(find_descriptors(&doc, id, interface, true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -724,7 +732,7 @@ mod tests {
|
||||
id, ref interface, ..
|
||||
} = instruction
|
||||
{
|
||||
let descriptors = find_descriptors(&doc, id, interface);
|
||||
let descriptors = find_descriptors(&doc, id, interface, true);
|
||||
let mut bindings = Vec::new();
|
||||
for d in descriptors {
|
||||
bindings.push((d.set, d.binding));
|
||||
|
@ -19,6 +19,7 @@ pub(super) fn write_entry_point(
|
||||
doc: &Spirv,
|
||||
instruction: &Instruction,
|
||||
types_meta: &TypesMeta,
|
||||
exact_entrypoint_interface: bool,
|
||||
) -> (TokenStream, TokenStream, TokenStream) {
|
||||
let (execution, id, ep_name, interface) = match instruction {
|
||||
&Instruction::EntryPoint {
|
||||
@ -67,6 +68,7 @@ pub(super) fn write_entry_point(
|
||||
id,
|
||||
interface,
|
||||
&types_meta,
|
||||
exact_entrypoint_interface,
|
||||
);
|
||||
|
||||
let spec_consts_struct = if crate::spec_consts::has_specialization_constants(doc) {
|
||||
|
@ -134,6 +134,8 @@
|
||||
//! Provides the path to precompiled SPIR-V bytecode, relative to `Cargo.toml`.
|
||||
//! Cannot be used in conjunction with the `src` or `path` field.
|
||||
//! This allows using shaders compiled through a separate build system.
|
||||
//! **Note**: If your shader contains multiple entrypoints with different
|
||||
//! descriptor sets, you may also need to enable `exact_entrypoint_interface`.
|
||||
//!
|
||||
//! ## `include: ["...", "...", ..., "..."]`
|
||||
//!
|
||||
@ -172,6 +174,19 @@
|
||||
//! final output of generated code the user can also use `dump` macro
|
||||
//! option(see below).
|
||||
//!
|
||||
//! ## `exact_entrypoint_interface: true`
|
||||
//!
|
||||
//! By default, the macro assumes that all resources (Uniforms, Storage Buffers,
|
||||
//! Images, Samplers, etc) need to be bound into a descriptor set, even if they are
|
||||
//! not used in the shader code. However, shaders with multiple entrypoints may have
|
||||
//! conflicting descriptor sets for each entrypoint. Enabling this option will force
|
||||
//! the macro to only generate descriptor information for resources that are used
|
||||
//! in each entrypoint.
|
||||
//!
|
||||
//! The macro determines which resources are used by looking at each entrypoint's
|
||||
//! interface and bytecode. See [`src/descriptor_sets.rs`][descriptor_sets]
|
||||
//! for the exact logic.
|
||||
//!
|
||||
//! ## `dump: true`
|
||||
//!
|
||||
//! The crate fails to compile but prints the generated rust code to stdout.
|
||||
@ -186,6 +201,7 @@
|
||||
//! [PipelineLayoutDesc]: https://docs.rs/vulkano/*/vulkano/descriptor/pipeline_layout/trait.PipelineLayoutDesc.html
|
||||
//! [SpecializationConstants]: https://docs.rs/vulkano/*/vulkano/pipeline/shader/trait.SpecializationConstants.html
|
||||
//! [pipeline]: https://docs.rs/vulkano/*/vulkano/pipeline/index.html
|
||||
//! [descriptor_sets]: https://github.com/vulkano-rs/vulkano/blob/master/vulkano-shaders/src/descriptor_sets.rs#L142
|
||||
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/vulkano-rs/vulkano/master/logo.png")]
|
||||
#![recursion_limit = "1024"]
|
||||
@ -276,6 +292,7 @@ struct MacroInput {
|
||||
include_directories: Vec<String>,
|
||||
macro_defines: Vec<(String, String)>,
|
||||
types_meta: TypesMeta,
|
||||
exact_entrypoint_interface: bool,
|
||||
dump: bool,
|
||||
}
|
||||
|
||||
@ -287,6 +304,7 @@ impl Parse for MacroInput {
|
||||
let mut include_directories = Vec::new();
|
||||
let mut macro_defines = Vec::new();
|
||||
let mut types_meta = None;
|
||||
let mut exact_entrypoint_interface = None;
|
||||
|
||||
while !input.is_empty() {
|
||||
let name: Ident = input.parse()?;
|
||||
@ -504,6 +522,13 @@ impl Parse for MacroInput {
|
||||
|
||||
types_meta = Some(meta);
|
||||
}
|
||||
"exact_entrypoint_interface" => {
|
||||
if exact_entrypoint_interface.is_some() {
|
||||
panic!("Only one `dump` can be defined")
|
||||
}
|
||||
let lit: LitBool = input.parse()?;
|
||||
exact_entrypoint_interface = Some(lit.value);
|
||||
}
|
||||
"dump" => {
|
||||
if dump.is_some() {
|
||||
panic!("Only one `dump` can be defined")
|
||||
@ -538,6 +563,7 @@ impl Parse for MacroInput {
|
||||
dump,
|
||||
macro_defines,
|
||||
types_meta: types_meta.unwrap_or_else(|| TypesMeta::default()),
|
||||
exact_entrypoint_interface: exact_entrypoint_interface.unwrap_or(false),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -575,6 +601,7 @@ pub fn shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
unsafe { from_raw_parts(bytes.as_slice().as_ptr() as *const u32, bytes.len() / 4) },
|
||||
input.types_meta,
|
||||
empty(),
|
||||
input.exact_entrypoint_interface,
|
||||
input.dump,
|
||||
)
|
||||
.unwrap()
|
||||
@ -631,6 +658,7 @@ pub fn shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
content.as_binary(),
|
||||
input.types_meta,
|
||||
input_paths,
|
||||
input.exact_entrypoint_interface,
|
||||
input.dump,
|
||||
)
|
||||
.unwrap()
|
||||
|
Loading…
Reference in New Issue
Block a user