mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-26 00:34:19 +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`.
|
- 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.
|
- 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.
|
- `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.
|
- 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`.
|
- 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.
|
- 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],
|
spirv: &[u32],
|
||||||
types_meta: TypesMeta,
|
types_meta: TypesMeta,
|
||||||
input_paths: I,
|
input_paths: I,
|
||||||
|
exact_entrypoint_interface: bool,
|
||||||
dump: bool,
|
dump: bool,
|
||||||
) -> Result<TokenStream, Error>
|
) -> Result<TokenStream, Error>
|
||||||
where
|
where
|
||||||
@ -263,8 +264,12 @@ where
|
|||||||
let mut entry_points_outside_impl: Vec<TokenStream> = vec![];
|
let mut entry_points_outside_impl: Vec<TokenStream> = vec![];
|
||||||
for instruction in doc.instructions.iter() {
|
for instruction in doc.instructions.iter() {
|
||||||
if let &Instruction::EntryPoint { .. } = instruction {
|
if let &Instruction::EntryPoint { .. } = instruction {
|
||||||
let (outside, entry_point, descriptor_sets) =
|
let (outside, entry_point, descriptor_sets) = entry_point::write_entry_point(
|
||||||
entry_point::write_entry_point(&doc, instruction, &types_meta);
|
&doc,
|
||||||
|
instruction,
|
||||||
|
&types_meta,
|
||||||
|
exact_entrypoint_interface,
|
||||||
|
);
|
||||||
entry_points_inside_impl.push(entry_point);
|
entry_points_inside_impl.push(entry_point);
|
||||||
entry_points_outside_impl.push(outside);
|
entry_points_outside_impl.push(outside);
|
||||||
entry_points_outside_impl.push(descriptor_sets);
|
entry_points_outside_impl.push(descriptor_sets);
|
||||||
|
@ -31,11 +31,12 @@ pub(super) fn write_descriptor_sets(
|
|||||||
entrypoint_id: u32,
|
entrypoint_id: u32,
|
||||||
interface: &[u32],
|
interface: &[u32],
|
||||||
types_meta: &TypesMeta,
|
types_meta: &TypesMeta,
|
||||||
|
exact_entrypoint_interface: bool,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
// TODO: somewhat implemented correctly
|
// TODO: somewhat implemented correctly
|
||||||
|
|
||||||
// Finding all the descriptors.
|
// 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.
|
// Looping to find all the push constant structs.
|
||||||
let mut push_constants_size = 0;
|
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();
|
let mut descriptors = Vec::new();
|
||||||
|
|
||||||
// For SPIR-V 1.4+, the entrypoint interface can specify variables of all storage classes,
|
// 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,
|
// 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,
|
// 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.
|
// 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 found_variables: HashSet<u32> = interface.iter().cloned().collect();
|
||||||
let mut inspected_functions: HashSet<u32> = HashSet::new();
|
let mut inspected_functions: HashSet<u32> = HashSet::new();
|
||||||
find_variables_in_function(
|
find_variables_in_function(
|
||||||
@ -154,14 +160,16 @@ fn find_descriptors(doc: &Spirv, entrypoint_id: u32, interface: &[u32]) -> Vec<D
|
|||||||
&mut inspected_functions,
|
&mut inspected_functions,
|
||||||
&mut found_variables,
|
&mut found_variables,
|
||||||
);
|
);
|
||||||
found_variables
|
Some(found_variables)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Looping to find all the interface elements that have the `DescriptorSet` decoration.
|
// Looping to find all the interface elements that have the `DescriptorSet` decoration.
|
||||||
for set_decoration in doc.get_decorations(Decoration::DecorationDescriptorSet) {
|
for set_decoration in doc.get_decorations(Decoration::DecorationDescriptorSet) {
|
||||||
let variable_id = set_decoration.target_id;
|
let variable_id = set_decoration.target_id;
|
||||||
|
|
||||||
if !variables.contains(&variable_id) {
|
if exact && !variables.as_ref().unwrap().contains(&variable_id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,7 +658,7 @@ mod tests {
|
|||||||
id, ref interface, ..
|
id, ref interface, ..
|
||||||
} = instruction
|
} = 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, ..
|
id, ref interface, ..
|
||||||
} = instruction
|
} = instruction
|
||||||
{
|
{
|
||||||
let descriptors = find_descriptors(&doc, id, interface);
|
let descriptors = find_descriptors(&doc, id, interface, true);
|
||||||
let mut bindings = Vec::new();
|
let mut bindings = Vec::new();
|
||||||
for d in descriptors {
|
for d in descriptors {
|
||||||
bindings.push((d.set, d.binding));
|
bindings.push((d.set, d.binding));
|
||||||
|
@ -19,6 +19,7 @@ pub(super) fn write_entry_point(
|
|||||||
doc: &Spirv,
|
doc: &Spirv,
|
||||||
instruction: &Instruction,
|
instruction: &Instruction,
|
||||||
types_meta: &TypesMeta,
|
types_meta: &TypesMeta,
|
||||||
|
exact_entrypoint_interface: bool,
|
||||||
) -> (TokenStream, TokenStream, TokenStream) {
|
) -> (TokenStream, TokenStream, TokenStream) {
|
||||||
let (execution, id, ep_name, interface) = match instruction {
|
let (execution, id, ep_name, interface) = match instruction {
|
||||||
&Instruction::EntryPoint {
|
&Instruction::EntryPoint {
|
||||||
@ -67,6 +68,7 @@ pub(super) fn write_entry_point(
|
|||||||
id,
|
id,
|
||||||
interface,
|
interface,
|
||||||
&types_meta,
|
&types_meta,
|
||||||
|
exact_entrypoint_interface,
|
||||||
);
|
);
|
||||||
|
|
||||||
let spec_consts_struct = if crate::spec_consts::has_specialization_constants(doc) {
|
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`.
|
//! Provides the path to precompiled SPIR-V bytecode, relative to `Cargo.toml`.
|
||||||
//! Cannot be used in conjunction with the `src` or `path` field.
|
//! Cannot be used in conjunction with the `src` or `path` field.
|
||||||
//! This allows using shaders compiled through a separate build system.
|
//! 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: ["...", "...", ..., "..."]`
|
//! ## `include: ["...", "...", ..., "..."]`
|
||||||
//!
|
//!
|
||||||
@ -172,6 +174,19 @@
|
|||||||
//! final output of generated code the user can also use `dump` macro
|
//! final output of generated code the user can also use `dump` macro
|
||||||
//! option(see below).
|
//! 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`
|
//! ## `dump: true`
|
||||||
//!
|
//!
|
||||||
//! The crate fails to compile but prints the generated rust code to stdout.
|
//! 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
|
//! [PipelineLayoutDesc]: https://docs.rs/vulkano/*/vulkano/descriptor/pipeline_layout/trait.PipelineLayoutDesc.html
|
||||||
//! [SpecializationConstants]: https://docs.rs/vulkano/*/vulkano/pipeline/shader/trait.SpecializationConstants.html
|
//! [SpecializationConstants]: https://docs.rs/vulkano/*/vulkano/pipeline/shader/trait.SpecializationConstants.html
|
||||||
//! [pipeline]: https://docs.rs/vulkano/*/vulkano/pipeline/index.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")]
|
#![doc(html_logo_url = "https://raw.githubusercontent.com/vulkano-rs/vulkano/master/logo.png")]
|
||||||
#![recursion_limit = "1024"]
|
#![recursion_limit = "1024"]
|
||||||
@ -276,6 +292,7 @@ struct MacroInput {
|
|||||||
include_directories: Vec<String>,
|
include_directories: Vec<String>,
|
||||||
macro_defines: Vec<(String, String)>,
|
macro_defines: Vec<(String, String)>,
|
||||||
types_meta: TypesMeta,
|
types_meta: TypesMeta,
|
||||||
|
exact_entrypoint_interface: bool,
|
||||||
dump: bool,
|
dump: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,6 +304,7 @@ impl Parse for MacroInput {
|
|||||||
let mut include_directories = Vec::new();
|
let mut include_directories = Vec::new();
|
||||||
let mut macro_defines = Vec::new();
|
let mut macro_defines = Vec::new();
|
||||||
let mut types_meta = None;
|
let mut types_meta = None;
|
||||||
|
let mut exact_entrypoint_interface = None;
|
||||||
|
|
||||||
while !input.is_empty() {
|
while !input.is_empty() {
|
||||||
let name: Ident = input.parse()?;
|
let name: Ident = input.parse()?;
|
||||||
@ -504,6 +522,13 @@ impl Parse for MacroInput {
|
|||||||
|
|
||||||
types_meta = Some(meta);
|
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" => {
|
"dump" => {
|
||||||
if dump.is_some() {
|
if dump.is_some() {
|
||||||
panic!("Only one `dump` can be defined")
|
panic!("Only one `dump` can be defined")
|
||||||
@ -538,6 +563,7 @@ impl Parse for MacroInput {
|
|||||||
dump,
|
dump,
|
||||||
macro_defines,
|
macro_defines,
|
||||||
types_meta: types_meta.unwrap_or_else(|| TypesMeta::default()),
|
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) },
|
unsafe { from_raw_parts(bytes.as_slice().as_ptr() as *const u32, bytes.len() / 4) },
|
||||||
input.types_meta,
|
input.types_meta,
|
||||||
empty(),
|
empty(),
|
||||||
|
input.exact_entrypoint_interface,
|
||||||
input.dump,
|
input.dump,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@ -631,6 +658,7 @@ pub fn shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
content.as_binary(),
|
content.as_binary(),
|
||||||
input.types_meta,
|
input.types_meta,
|
||||||
input_paths,
|
input_paths,
|
||||||
|
input.exact_entrypoint_interface,
|
||||||
input.dump,
|
input.dump,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
Loading…
Reference in New Issue
Block a user