mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 00:04:15 +00:00
Improvements to caches and switch to ahash
(#2019)
* Add `OnceCache` * Switch to `ahash`
This commit is contained in:
parent
2277448a0e
commit
1c2d195dab
@ -15,6 +15,7 @@ categories = ["rendering::graphics-api"]
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ahash = "0.8"
|
||||||
heck = "0.4"
|
heck = "0.4"
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
|
@ -7,23 +7,21 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::entry_point;
|
use crate::{entry_point, read_file_to_string, structs, RegisteredType, TypesMeta};
|
||||||
use crate::read_file_to_string;
|
use ahash::HashMap;
|
||||||
use crate::structs;
|
|
||||||
use crate::RegisteredType;
|
|
||||||
use crate::TypesMeta;
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
pub use shaderc::{CompilationArtifact, IncludeType, ResolvedInclude, ShaderKind};
|
pub use shaderc::{CompilationArtifact, IncludeType, ResolvedInclude, ShaderKind};
|
||||||
use shaderc::{CompileOptions, Compiler, EnvVersion, SpirvVersion, TargetEnv};
|
use shaderc::{CompileOptions, Compiler, EnvVersion, SpirvVersion, TargetEnv};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::iter::Iterator;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::{
|
use std::{
|
||||||
cell::{RefCell, RefMut},
|
cell::{RefCell, RefMut},
|
||||||
io::Error as IoError,
|
io::Error as IoError,
|
||||||
|
iter::Iterator,
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
use vulkano::shader::{
|
||||||
|
reflect,
|
||||||
|
spirv::{Spirv, SpirvError},
|
||||||
};
|
};
|
||||||
use vulkano::shader::reflect;
|
|
||||||
use vulkano::shader::spirv::{Spirv, SpirvError};
|
|
||||||
|
|
||||||
pub(super) fn path_to_str(path: &Path) -> &str {
|
pub(super) fn path_to_str(path: &Path) -> &str {
|
||||||
path.to_str().expect(
|
path.to_str().expect(
|
||||||
@ -378,7 +376,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let spirv = Spirv::new(comp.as_binary()).unwrap();
|
let spirv = Spirv::new(comp.as_binary()).unwrap();
|
||||||
let res = std::panic::catch_unwind(|| {
|
let res = std::panic::catch_unwind(|| {
|
||||||
structs::write_structs("", &spirv, &TypesMeta::default(), &mut HashMap::new())
|
structs::write_structs("", &spirv, &TypesMeta::default(), &mut HashMap::default())
|
||||||
});
|
});
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
}
|
}
|
||||||
@ -407,7 +405,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let spirv = Spirv::new(comp.as_binary()).unwrap();
|
let spirv = Spirv::new(comp.as_binary()).unwrap();
|
||||||
structs::write_structs("", &spirv, &TypesMeta::default(), &mut HashMap::new());
|
structs::write_structs("", &spirv, &TypesMeta::default(), &mut HashMap::default());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrap_alignment() {
|
fn test_wrap_alignment() {
|
||||||
@ -439,7 +437,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let spirv = Spirv::new(comp.as_binary()).unwrap();
|
let spirv = Spirv::new(comp.as_binary()).unwrap();
|
||||||
structs::write_structs("", &spirv, &TypesMeta::default(), &mut HashMap::new());
|
structs::write_structs("", &spirv, &TypesMeta::default(), &mut HashMap::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -7,15 +7,16 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
|
use ahash::HashMap;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use std::collections::HashMap;
|
use vulkano::{
|
||||||
use vulkano::pipeline::layout::PushConstantRange;
|
pipeline::layout::PushConstantRange,
|
||||||
use vulkano::shader::spirv::ExecutionModel;
|
shader::{
|
||||||
use vulkano::shader::{
|
spirv::ExecutionModel, DescriptorIdentifier, DescriptorRequirements, EntryPointInfo,
|
||||||
DescriptorIdentifier, DescriptorRequirements, ShaderExecution, ShaderInterfaceEntry,
|
ShaderExecution, ShaderInterface, ShaderInterfaceEntry, ShaderInterfaceEntryType,
|
||||||
ShaderInterfaceEntryType, SpecializationConstantRequirements,
|
ShaderStages, SpecializationConstantRequirements,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use vulkano::shader::{EntryPointInfo, ShaderInterface, ShaderStages};
|
|
||||||
|
|
||||||
pub(super) fn write_entry_point(
|
pub(super) fn write_entry_point(
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -225,17 +225,19 @@ extern crate quote;
|
|||||||
extern crate syn;
|
extern crate syn;
|
||||||
|
|
||||||
use crate::codegen::ShaderKind;
|
use crate::codegen::ShaderKind;
|
||||||
|
use ahash::HashMap;
|
||||||
use shaderc::{EnvVersion, SpirvVersion};
|
use shaderc::{EnvVersion, SpirvVersion};
|
||||||
use std::borrow::Cow;
|
use std::{
|
||||||
use std::collections::HashMap;
|
borrow::Cow,
|
||||||
use std::fs;
|
env, fs,
|
||||||
use std::fs::File;
|
fs::File,
|
||||||
use std::io::{Read, Result as IoResult};
|
io::{Read, Result as IoResult},
|
||||||
use std::path::Path;
|
iter::empty,
|
||||||
use std::slice::from_raw_parts;
|
path::Path,
|
||||||
use std::{env, iter::empty};
|
slice::from_raw_parts,
|
||||||
use syn::parse::{Parse, ParseStream, Result};
|
};
|
||||||
use syn::{
|
use syn::{
|
||||||
|
parse::{Parse, ParseStream, Result},
|
||||||
Ident, ItemUse, LitBool, LitStr, Meta, MetaList, NestedMeta, Path as SynPath, TypeImplTrait,
|
Ident, ItemUse, LitBool, LitStr, Meta, MetaList, NestedMeta, Path as SynPath, TypeImplTrait,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -373,7 +375,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 shared_constants = None;
|
let mut shared_constants = None;
|
||||||
let mut shaders = HashMap::new();
|
let mut shaders = HashMap::default();
|
||||||
let mut spirv_version = None;
|
let mut spirv_version = None;
|
||||||
let mut types_meta = None;
|
let mut types_meta = None;
|
||||||
let mut vulkan_version = None;
|
let mut vulkan_version = None;
|
||||||
@ -802,7 +804,7 @@ pub fn shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
|
|
||||||
let mut shaders_code = Vec::with_capacity(input.shaders.len());
|
let mut shaders_code = Vec::with_capacity(input.shaders.len());
|
||||||
let mut types_code = Vec::with_capacity(input.shaders.len());
|
let mut types_code = Vec::with_capacity(input.shaders.len());
|
||||||
let mut types_registry = HashMap::new();
|
let mut types_registry = HashMap::default();
|
||||||
|
|
||||||
for (prefix, (shader_kind, shader_source)) in input.shaders {
|
for (prefix, (shader_kind, shader_source)) in input.shaders {
|
||||||
let (code, types) = if let SourceKind::Bytes(path) = shader_source {
|
let (code, types) = if let SourceKind::Bytes(path) = shader_source {
|
||||||
|
@ -8,9 +8,10 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::{RegisteredType, TypesMeta};
|
use crate::{RegisteredType, TypesMeta};
|
||||||
|
use ahash::HashMap;
|
||||||
use heck::ToUpperCamelCase;
|
use heck::ToUpperCamelCase;
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use std::{borrow::Cow, collections::HashMap, mem};
|
use std::{borrow::Cow, mem};
|
||||||
use syn::{Ident, LitStr};
|
use syn::{Ident, LitStr};
|
||||||
use vulkano::shader::spirv::{Decoration, Id, Instruction, Spirv};
|
use vulkano::shader::spirv::{Decoration, Id, Instruction, Spirv};
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ keywords = ["vulkan", "bindings", "graphics", "gpu", "rendering"]
|
|||||||
categories = ["rendering::graphics-api"]
|
categories = ["rendering::graphics-api"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ahash = "0.8"
|
||||||
vulkano = { version = "0.31.0", path = "../vulkano" }
|
vulkano = { version = "0.31.0", path = "../vulkano" }
|
||||||
vulkano-win = { version = "0.31.0", path = "../vulkano-win" }
|
vulkano-win = { version = "0.31.0", path = "../vulkano-win" }
|
||||||
winit = { version = "0.27" }
|
winit = { version = "0.27" }
|
||||||
|
@ -17,8 +17,8 @@ use vulkano::{
|
|||||||
debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo},
|
debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo},
|
||||||
Instance, InstanceCreateInfo, InstanceExtensions,
|
Instance, InstanceCreateInfo, InstanceExtensions,
|
||||||
},
|
},
|
||||||
|
Version, VulkanLibrary,
|
||||||
};
|
};
|
||||||
use vulkano::{Version, VulkanLibrary};
|
|
||||||
|
|
||||||
/// A configuration struct to pass various creation options to create [`VulkanoContext`].
|
/// A configuration struct to pass various creation options to create [`VulkanoContext`].
|
||||||
///
|
///
|
||||||
|
@ -7,22 +7,20 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use crate::{context::VulkanoContext, window::WindowDescriptor};
|
||||||
|
use ahash::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::context::VulkanoContext;
|
|
||||||
use crate::window::WindowDescriptor;
|
|
||||||
use vulkano::device::Device;
|
|
||||||
use vulkano::image::{ImageUsage, StorageImage, SwapchainImage};
|
|
||||||
use vulkano::swapchain::SwapchainPresentInfo;
|
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
device::Queue,
|
device::{Device, Queue},
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, ImageAccess, ImageViewAbstract},
|
image::{
|
||||||
swapchain,
|
view::ImageView, ImageAccess, ImageUsage, ImageViewAbstract, StorageImage, SwapchainImage,
|
||||||
swapchain::{AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError},
|
},
|
||||||
sync,
|
swapchain::{
|
||||||
sync::{FlushError, GpuFuture},
|
self, AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError,
|
||||||
|
SwapchainPresentInfo,
|
||||||
|
},
|
||||||
|
sync::{self, FlushError, GpuFuture},
|
||||||
};
|
};
|
||||||
use vulkano_win::create_surface_from_winit;
|
use vulkano_win::create_surface_from_winit;
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
|
@ -11,13 +11,14 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use crate::context::VulkanoContext;
|
use crate::{context::VulkanoContext, renderer::VulkanoWindowRenderer};
|
||||||
use crate::renderer::VulkanoWindowRenderer;
|
use ahash::HashMap;
|
||||||
use std::collections::hash_map::{Iter, IterMut};
|
use std::collections::hash_map::{Iter, IterMut};
|
||||||
use std::collections::HashMap;
|
|
||||||
use vulkano::swapchain::{PresentMode, SwapchainCreateInfo};
|
use vulkano::swapchain::{PresentMode, SwapchainCreateInfo};
|
||||||
use winit::dpi::LogicalSize;
|
use winit::{
|
||||||
use winit::window::{CursorGrabMode, WindowId};
|
dpi::LogicalSize,
|
||||||
|
window::{CursorGrabMode, WindowId},
|
||||||
|
};
|
||||||
|
|
||||||
/// A struct organizing windows and their corresponding renderers. This makes it easy to handle multiple windows.
|
/// A struct organizing windows and their corresponding renderers. This makes it easy to handle multiple windows.
|
||||||
///
|
///
|
||||||
|
@ -6,9 +6,10 @@ use raw_window_handle::{
|
|||||||
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
|
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vulkano::instance::Instance;
|
use vulkano::{
|
||||||
use vulkano::swapchain::Surface;
|
instance::Instance,
|
||||||
use vulkano::swapchain::SurfaceCreationError;
|
swapchain::{Surface, SurfaceCreationError},
|
||||||
|
};
|
||||||
|
|
||||||
/// Creates a vulkan surface from a generic window
|
/// Creates a vulkan surface from a generic window
|
||||||
/// which implements HasRawWindowHandle and thus can reveal the os-dependent handle.
|
/// which implements HasRawWindowHandle and thus can reveal the os-dependent handle.
|
||||||
|
@ -14,6 +14,7 @@ readme = "../README.md"
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ahash = "0.8"
|
||||||
# When updating Ash, also update vk.xml to the same Vulkan patch version that Ash uses.
|
# When updating Ash, also update vk.xml to the same Vulkan patch version that Ash uses.
|
||||||
# All versions of vk.xml can be found at https://github.com/KhronosGroup/Vulkan-Headers/commits/main/registry/vk.xml.
|
# All versions of vk.xml can be found at https://github.com/KhronosGroup/Vulkan-Headers/commits/main/registry/vk.xml.
|
||||||
ash = "0.37"
|
ash = "0.37"
|
||||||
@ -30,6 +31,7 @@ objc = "0.2.5"
|
|||||||
core-graphics-types = "0.1"
|
core-graphics-types = "0.1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
ahash = "0.8"
|
||||||
heck = "0.4"
|
heck = "0.4"
|
||||||
indexmap = "1.8"
|
indexmap = "1.8"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
@ -7,9 +7,8 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{write_file, VkRegistryData};
|
use super::{write_file, IndexMap, VkRegistryData};
|
||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
use indexmap::IndexMap;
|
|
||||||
use proc_macro2::{Ident, Literal, TokenStream};
|
use proc_macro2::{Ident, Literal, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
|
@ -7,16 +7,13 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{write_file, VkRegistryData};
|
use super::{write_file, IndexMap, VkRegistryData};
|
||||||
|
use ahash::HashMap;
|
||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
use indexmap::IndexMap;
|
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::{
|
use std::{collections::hash_map::Entry, fmt::Write as _};
|
||||||
collections::{hash_map::Entry, HashMap},
|
|
||||||
fmt::Write as _,
|
|
||||||
};
|
|
||||||
use vk_parse::{Extension, Type, TypeMember, TypeMemberMarkup, TypeSpec};
|
use vk_parse::{Extension, Type, TypeMember, TypeMemberMarkup, TypeSpec};
|
||||||
|
|
||||||
// This is not included in vk.xml, so it's added here manually
|
// This is not included in vk.xml, so it's added here manually
|
||||||
@ -515,7 +512,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn features_members(types: &HashMap<&str, (&Type, Vec<&str>)>) -> Vec<FeaturesMember> {
|
fn features_members(types: &HashMap<&str, (&Type, Vec<&str>)>) -> Vec<FeaturesMember> {
|
||||||
let mut features = HashMap::new();
|
let mut features = HashMap::default();
|
||||||
std::iter::once(&types["VkPhysicalDeviceFeatures"])
|
std::iter::once(&types["VkPhysicalDeviceFeatures"])
|
||||||
.chain(sorted_structs(types).into_iter())
|
.chain(sorted_structs(types).into_iter())
|
||||||
.filter(|(ty, _)| {
|
.filter(|(ty, _)| {
|
||||||
@ -728,7 +725,7 @@ fn features_ffi_members<'a>(
|
|||||||
types: &'a HashMap<&str, (&Type, Vec<&str>)>,
|
types: &'a HashMap<&str, (&Type, Vec<&str>)>,
|
||||||
extensions: &IndexMap<&'a str, &Extension>,
|
extensions: &IndexMap<&'a str, &Extension>,
|
||||||
) -> Vec<FeaturesFfiMember> {
|
) -> Vec<FeaturesFfiMember> {
|
||||||
let mut feature_included_in: HashMap<&str, Vec<&str>> = HashMap::new();
|
let mut feature_included_in: HashMap<&str, Vec<&str>> = HashMap::default();
|
||||||
sorted_structs(types)
|
sorted_structs(types)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(ty, provided_by)| {
|
.map(|(ty, provided_by)| {
|
||||||
|
@ -7,9 +7,8 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{write_file, VkRegistryData};
|
use super::{write_file, IndexMap, VkRegistryData};
|
||||||
use heck::{ToSnakeCase, ToUpperCamelCase};
|
use heck::{ToSnakeCase, ToUpperCamelCase};
|
||||||
use indexmap::IndexMap;
|
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use vk_parse::{Extension, ExtensionChild, InterfaceItem};
|
use vk_parse::{Extension, ExtensionChild, InterfaceItem};
|
||||||
|
@ -7,9 +7,8 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{extensions::RequiresOneOf, write_file, VkRegistryData};
|
use super::{extensions::RequiresOneOf, write_file, IndexMap, VkRegistryData};
|
||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
use indexmap::IndexMap;
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use proc_macro2::{Ident, Literal, TokenStream};
|
use proc_macro2::{Ident, Literal, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
@ -8,11 +8,10 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use self::spirv_grammar::SpirvGrammar;
|
use self::spirv_grammar::SpirvGrammar;
|
||||||
use indexmap::IndexMap;
|
use ahash::HashMap;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
env,
|
env,
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
fs::File,
|
fs::File,
|
||||||
@ -36,6 +35,8 @@ mod spirv_parse;
|
|||||||
mod spirv_reqs;
|
mod spirv_reqs;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
|
pub type IndexMap<K, V> = indexmap::IndexMap<K, V, ahash::RandomState>;
|
||||||
|
|
||||||
pub fn autogen() {
|
pub fn autogen() {
|
||||||
let registry = get_vk_registry("vk.xml");
|
let registry = get_vk_registry("vk.xml");
|
||||||
let vk_data = VkRegistryData::new(®istry);
|
let vk_data = VkRegistryData::new(®istry);
|
||||||
|
@ -7,16 +7,13 @@
|
|||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{write_file, VkRegistryData};
|
use super::{write_file, IndexMap, VkRegistryData};
|
||||||
|
use ahash::HashMap;
|
||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
use indexmap::IndexMap;
|
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::{
|
use std::{collections::hash_map::Entry, fmt::Write as _};
|
||||||
collections::{hash_map::Entry, HashMap},
|
|
||||||
fmt::Write as _,
|
|
||||||
};
|
|
||||||
use vk_parse::{Extension, Type, TypeMember, TypeMemberMarkup, TypeSpec};
|
use vk_parse::{Extension, Type, TypeMember, TypeMemberMarkup, TypeSpec};
|
||||||
|
|
||||||
pub fn write(vk_data: &VkRegistryData) {
|
pub fn write(vk_data: &VkRegistryData) {
|
||||||
@ -142,7 +139,7 @@ fn properties_output(members: &[PropertiesMember]) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn properties_members(types: &HashMap<&str, (&Type, Vec<&str>)>) -> Vec<PropertiesMember> {
|
fn properties_members(types: &HashMap<&str, (&Type, Vec<&str>)>) -> Vec<PropertiesMember> {
|
||||||
let mut properties = HashMap::new();
|
let mut properties = HashMap::default();
|
||||||
|
|
||||||
[
|
[
|
||||||
&types["VkPhysicalDeviceProperties"],
|
&types["VkPhysicalDeviceProperties"],
|
||||||
@ -306,7 +303,7 @@ fn properties_ffi_members<'a>(
|
|||||||
types: &'a HashMap<&str, (&Type, Vec<&str>)>,
|
types: &'a HashMap<&str, (&Type, Vec<&str>)>,
|
||||||
extensions: &IndexMap<&'a str, &Extension>,
|
extensions: &IndexMap<&'a str, &Extension>,
|
||||||
) -> Vec<PropertiesFfiMember> {
|
) -> Vec<PropertiesFfiMember> {
|
||||||
let mut property_included_in: HashMap<&str, Vec<&str>> = HashMap::new();
|
let mut property_included_in: HashMap<&str, Vec<&str>> = HashMap::default();
|
||||||
sorted_structs(types)
|
sorted_structs(types)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(ty, provided_by)| {
|
.map(|(ty, provided_by)| {
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
use super::{write_file, SpirvGrammar};
|
use super::{write_file, SpirvGrammar};
|
||||||
|
use ahash::{HashMap, HashSet};
|
||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref SPEC_CONSTANT_OP: HashSet<&'static str> = {
|
static ref SPEC_CONSTANT_OP: HashSet<&'static str> = {
|
||||||
@ -252,7 +252,7 @@ fn instruction_members(grammar: &SpirvGrammar) -> Vec<InstructionMember> {
|
|||||||
let name = format_ident!("{}", instruction.opname.strip_prefix("Op").unwrap());
|
let name = format_ident!("{}", instruction.opname.strip_prefix("Op").unwrap());
|
||||||
let mut has_result_id = false;
|
let mut has_result_id = false;
|
||||||
let mut has_result_type_id = false;
|
let mut has_result_type_id = false;
|
||||||
let mut operand_names = HashMap::new();
|
let mut operand_names = HashMap::default();
|
||||||
|
|
||||||
let mut operands = instruction
|
let mut operands = instruction
|
||||||
.operands
|
.operands
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
spirv_grammar::{SpirvGrammar, SpirvKindEnumerant},
|
spirv_grammar::{SpirvGrammar, SpirvKindEnumerant},
|
||||||
write_file, VkRegistryData,
|
write_file, IndexMap, VkRegistryData,
|
||||||
};
|
};
|
||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
use indexmap::{map::Entry, IndexMap};
|
use indexmap::map::Entry;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@ -148,7 +148,7 @@ fn spirv_capabilities_members(
|
|||||||
capabilities: &[&SpirvExtOrCap],
|
capabilities: &[&SpirvExtOrCap],
|
||||||
grammar_enumerants: &[SpirvKindEnumerant],
|
grammar_enumerants: &[SpirvKindEnumerant],
|
||||||
) -> Vec<SpirvReqsMember> {
|
) -> Vec<SpirvReqsMember> {
|
||||||
let mut members: IndexMap<String, SpirvReqsMember> = IndexMap::new();
|
let mut members: IndexMap<String, SpirvReqsMember> = IndexMap::default();
|
||||||
|
|
||||||
for ext_or_cap in capabilities {
|
for ext_or_cap in capabilities {
|
||||||
let mut enables: Vec<_> = ext_or_cap.enables.iter().filter_map(make_enable).collect();
|
let mut enables: Vec<_> = ext_or_cap.enables.iter().filter_map(make_enable).collect();
|
||||||
|
78
vulkano/src/cache.rs
Normal file
78
vulkano/src/cache.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use ahash::HashMap;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
use std::{collections::hash_map::Entry, hash::Hash};
|
||||||
|
|
||||||
|
/// A map specialized to caching properties that are specific to a Vulkan implementation.
|
||||||
|
///
|
||||||
|
/// Readers never block each other, except when an entry is vacant. In that case it gets written to
|
||||||
|
/// once and then never again, entries are immutable after insertion.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct OnceCache<K, V> {
|
||||||
|
inner: RwLock<HashMap<K, V>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> Default for OnceCache<K, V> {
|
||||||
|
fn default() -> Self {
|
||||||
|
OnceCache {
|
||||||
|
inner: RwLock::new(HashMap::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> OnceCache<K, V> {
|
||||||
|
/// Creates a new `OnceCache`.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> OnceCache<K, V>
|
||||||
|
where
|
||||||
|
K: Eq + Hash,
|
||||||
|
V: Clone,
|
||||||
|
{
|
||||||
|
/// Returns the value for the specified `key`. The entry gets written to with the value
|
||||||
|
/// returned by `f` if it doesn't exist.
|
||||||
|
pub fn get_or_insert(&self, key: K, f: impl FnOnce(&K) -> V) -> V {
|
||||||
|
if let Some(value) = self.inner.read().get(&key) {
|
||||||
|
return value.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.inner.write().entry(key) {
|
||||||
|
Entry::Occupied(entry) => {
|
||||||
|
// This can happen if someone else inserted an entry between when we released
|
||||||
|
// the read lock and acquired the write lock.
|
||||||
|
entry.get().clone()
|
||||||
|
}
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
let value = f(entry.key());
|
||||||
|
entry.insert(value.clone());
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the value for the specified `key`. The entry gets written to with the value
|
||||||
|
/// returned by `f` if it doesn't exist. If `f` returns [`Err`], the error is propagated and
|
||||||
|
/// the entry isn't written to.
|
||||||
|
pub fn get_or_try_insert<E>(&self, key: K, f: impl FnOnce(&K) -> Result<V, E>) -> Result<V, E> {
|
||||||
|
if let Some(value) = self.inner.read().get(&key) {
|
||||||
|
return Ok(value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.inner.write().entry(key) {
|
||||||
|
Entry::Occupied(entry) => {
|
||||||
|
// This can happen if someone else inserted an entry between when we released
|
||||||
|
// the read lock and acquired the write lock.
|
||||||
|
Ok(entry.get().clone())
|
||||||
|
}
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
let value = f(entry.key())?;
|
||||||
|
entry.insert(value.clone());
|
||||||
|
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -29,8 +29,8 @@ use crate::{
|
|||||||
sync::{AccessCheckError, AccessFlags, GpuFuture, PipelineMemoryAccess, PipelineStages},
|
sync::{AccessCheckError, AccessFlags, GpuFuture, PipelineMemoryAccess, PipelineStages},
|
||||||
DeviceSize, OomError, RequirementNotMet, RequiresOneOf,
|
DeviceSize, OomError, RequirementNotMet, RequiresOneOf,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Display, Error as FmtError, Formatter},
|
fmt::{Display, Error as FmtError, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
@ -43,10 +43,11 @@ use crate::{
|
|||||||
},
|
},
|
||||||
DeviceSize, OomError, VulkanObject,
|
DeviceSize, OomError, VulkanObject,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::{hash_map::Entry, HashMap},
|
collections::hash_map::Entry,
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Debug, Display, Error as FmtError, Formatter},
|
fmt::{Debug, Display, Error as FmtError, Formatter},
|
||||||
ops::{Range, RangeInclusive},
|
ops::{Range, RangeInclusive},
|
||||||
|
@ -84,9 +84,9 @@ use crate::{
|
|||||||
},
|
},
|
||||||
DeviceSize,
|
DeviceSize,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::HashMap,
|
|
||||||
fmt::{Debug, Error as FmtError, Formatter},
|
fmt::{Debug, Error as FmtError, Formatter},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
@ -18,8 +18,9 @@ use crate::{
|
|||||||
shader::{DescriptorRequirements, ShaderStages},
|
shader::{DescriptorRequirements, ShaderStages},
|
||||||
OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap},
|
collections::BTreeMap,
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Display, Error as FmtError, Formatter},
|
fmt::{Display, Error as FmtError, Formatter},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
@ -900,7 +901,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
shader::ShaderStages,
|
shader::ShaderStages,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use ahash::HashMap;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty() {
|
fn empty() {
|
||||||
|
@ -89,9 +89,9 @@ use crate::{
|
|||||||
sampler::Sampler,
|
sampler::Sampler,
|
||||||
OomError, VulkanObject,
|
OomError, VulkanObject,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Display, Error as FmtError, Formatter},
|
fmt::{Display, Error as FmtError, Formatter},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
|
@ -20,7 +20,8 @@ use crate::{
|
|||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
OomError,
|
OomError,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use ahash::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Standard implementation of a descriptor pool.
|
/// Standard implementation of a descriptor pool.
|
||||||
///
|
///
|
||||||
|
@ -15,9 +15,9 @@ use crate::{
|
|||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
OomError, Version, VulkanError, VulkanObject,
|
OomError, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Display, Error as FmtError, Formatter},
|
fmt::{Display, Error as FmtError, Formatter},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
|
@ -120,12 +120,13 @@ pub use crate::{
|
|||||||
extensions::{ExtensionRestriction, ExtensionRestrictionError},
|
extensions::{ExtensionRestriction, ExtensionRestrictionError},
|
||||||
fns::DeviceFunctions,
|
fns::DeviceFunctions,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use ash::vk::Handle;
|
use ash::vk::Handle;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{hash_map::Entry, HashMap},
|
collections::hash_map::Entry,
|
||||||
error::Error,
|
error::Error,
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
fmt::{Display, Error as FmtError, Formatter},
|
fmt::{Display, Error as FmtError, Formatter},
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
use super::QueueFamilyProperties;
|
use super::QueueFamilyProperties;
|
||||||
use crate::{
|
use crate::{
|
||||||
buffer::{ExternalBufferInfo, ExternalBufferProperties},
|
buffer::{ExternalBufferInfo, ExternalBufferProperties},
|
||||||
|
cache::OnceCache,
|
||||||
device::{DeviceExtensions, Features, FeaturesFfi, Properties, PropertiesFfi},
|
device::{DeviceExtensions, Features, FeaturesFfi, Properties, PropertiesFfi},
|
||||||
format::{Format, FormatProperties},
|
format::{Format, FormatProperties},
|
||||||
image::{
|
image::{
|
||||||
@ -30,10 +31,7 @@ use crate::{
|
|||||||
ExtensionProperties, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
ExtensionProperties, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
use bytemuck::cast_slice;
|
use bytemuck::cast_slice;
|
||||||
use parking_lot::RwLock;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, HashMap},
|
|
||||||
convert::Infallible,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Debug, Display, Error as FmtError, Formatter},
|
fmt::{Debug, Display, Error as FmtError, Formatter},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
@ -78,14 +76,13 @@ pub struct PhysicalDevice {
|
|||||||
queue_family_properties: Vec<QueueFamilyProperties>,
|
queue_family_properties: Vec<QueueFamilyProperties>,
|
||||||
|
|
||||||
// Data queried by the user at runtime, cached for faster lookups.
|
// Data queried by the user at runtime, cached for faster lookups.
|
||||||
external_buffer_properties: RwLock<HashMap<ExternalBufferInfo, ExternalBufferProperties>>,
|
external_buffer_properties: OnceCache<ExternalBufferInfo, ExternalBufferProperties>,
|
||||||
external_fence_properties: RwLock<HashMap<ExternalFenceInfo, ExternalFenceProperties>>,
|
external_fence_properties: OnceCache<ExternalFenceInfo, ExternalFenceProperties>,
|
||||||
external_semaphore_properties:
|
external_semaphore_properties: OnceCache<ExternalSemaphoreInfo, ExternalSemaphoreProperties>,
|
||||||
RwLock<HashMap<ExternalSemaphoreInfo, ExternalSemaphoreProperties>>,
|
format_properties: OnceCache<Format, FormatProperties>,
|
||||||
format_properties: RwLock<HashMap<Format, FormatProperties>>,
|
image_format_properties: OnceCache<ImageFormatInfo, Option<ImageFormatProperties>>,
|
||||||
image_format_properties: RwLock<HashMap<ImageFormatInfo, Option<ImageFormatProperties>>>,
|
|
||||||
sparse_image_format_properties:
|
sparse_image_format_properties:
|
||||||
RwLock<HashMap<SparseImageFormatInfo, Vec<SparseImageFormatProperties>>>,
|
OnceCache<SparseImageFormatInfo, Vec<SparseImageFormatProperties>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhysicalDevice {
|
impl PhysicalDevice {
|
||||||
@ -143,12 +140,12 @@ impl PhysicalDevice {
|
|||||||
memory_properties,
|
memory_properties,
|
||||||
queue_family_properties,
|
queue_family_properties,
|
||||||
|
|
||||||
external_buffer_properties: RwLock::new(HashMap::new()),
|
external_buffer_properties: OnceCache::new(),
|
||||||
external_fence_properties: RwLock::new(HashMap::new()),
|
external_fence_properties: OnceCache::new(),
|
||||||
external_semaphore_properties: RwLock::new(HashMap::new()),
|
external_semaphore_properties: OnceCache::new(),
|
||||||
format_properties: RwLock::new(HashMap::new()),
|
format_properties: OnceCache::new(),
|
||||||
image_format_properties: RwLock::new(HashMap::new()),
|
image_format_properties: OnceCache::new(),
|
||||||
sparse_image_format_properties: RwLock::new(HashMap::new()),
|
sparse_image_format_properties: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,7 +541,7 @@ impl PhysicalDevice {
|
|||||||
&self,
|
&self,
|
||||||
info: ExternalBufferInfo,
|
info: ExternalBufferInfo,
|
||||||
) -> ExternalBufferProperties {
|
) -> ExternalBufferProperties {
|
||||||
get_cached(&self.external_buffer_properties, info, |info| {
|
self.external_buffer_properties.get_or_insert(info, |info| {
|
||||||
/* Input */
|
/* Input */
|
||||||
|
|
||||||
let &ExternalBufferInfo {
|
let &ExternalBufferInfo {
|
||||||
@ -584,13 +581,12 @@ impl PhysicalDevice {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok::<_, Infallible>(ExternalBufferProperties {
|
ExternalBufferProperties {
|
||||||
external_memory_properties: external_buffer_properties
|
external_memory_properties: external_buffer_properties
|
||||||
.external_memory_properties
|
.external_memory_properties
|
||||||
.into(),
|
.into(),
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the external handle properties supported for fences with a given
|
/// Retrieves the external handle properties supported for fences with a given
|
||||||
@ -648,7 +644,7 @@ impl PhysicalDevice {
|
|||||||
&self,
|
&self,
|
||||||
info: ExternalFenceInfo,
|
info: ExternalFenceInfo,
|
||||||
) -> ExternalFenceProperties {
|
) -> ExternalFenceProperties {
|
||||||
get_cached(&self.external_fence_properties, info, |info| {
|
self.external_fence_properties.get_or_insert(info, |info| {
|
||||||
/* Input */
|
/* Input */
|
||||||
|
|
||||||
let &ExternalFenceInfo {
|
let &ExternalFenceInfo {
|
||||||
@ -684,7 +680,7 @@ impl PhysicalDevice {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok::<_, Infallible>(ExternalFenceProperties {
|
ExternalFenceProperties {
|
||||||
exportable: external_fence_properties
|
exportable: external_fence_properties
|
||||||
.external_fence_features
|
.external_fence_features
|
||||||
.intersects(ash::vk::ExternalFenceFeatureFlags::EXPORTABLE),
|
.intersects(ash::vk::ExternalFenceFeatureFlags::EXPORTABLE),
|
||||||
@ -695,9 +691,8 @@ impl PhysicalDevice {
|
|||||||
.export_from_imported_handle_types
|
.export_from_imported_handle_types
|
||||||
.into(),
|
.into(),
|
||||||
compatible_handle_types: external_fence_properties.compatible_handle_types.into(),
|
compatible_handle_types: external_fence_properties.compatible_handle_types.into(),
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the external handle properties supported for semaphores with a given
|
/// Retrieves the external handle properties supported for semaphores with a given
|
||||||
@ -755,58 +750,59 @@ impl PhysicalDevice {
|
|||||||
&self,
|
&self,
|
||||||
info: ExternalSemaphoreInfo,
|
info: ExternalSemaphoreInfo,
|
||||||
) -> ExternalSemaphoreProperties {
|
) -> ExternalSemaphoreProperties {
|
||||||
get_cached(&self.external_semaphore_properties, info, |info| {
|
self.external_semaphore_properties
|
||||||
/* Input */
|
.get_or_insert(info, |info| {
|
||||||
|
/* Input */
|
||||||
|
|
||||||
let &ExternalSemaphoreInfo {
|
let &ExternalSemaphoreInfo {
|
||||||
handle_type,
|
handle_type,
|
||||||
_ne: _,
|
_ne: _,
|
||||||
} = info;
|
} = info;
|
||||||
|
|
||||||
let external_semaphore_info = ash::vk::PhysicalDeviceExternalSemaphoreInfo {
|
let external_semaphore_info = ash::vk::PhysicalDeviceExternalSemaphoreInfo {
|
||||||
handle_type: handle_type.into(),
|
handle_type: handle_type.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
|
|
||||||
let mut external_semaphore_properties = ash::vk::ExternalSemaphoreProperties::default();
|
let mut external_semaphore_properties =
|
||||||
|
ash::vk::ExternalSemaphoreProperties::default();
|
||||||
|
|
||||||
/* Call */
|
/* Call */
|
||||||
|
|
||||||
let fns = self.instance.fns();
|
let fns = self.instance.fns();
|
||||||
|
|
||||||
if self.instance.api_version() >= Version::V1_1 {
|
if self.instance.api_version() >= Version::V1_1 {
|
||||||
(fns.v1_1.get_physical_device_external_semaphore_properties)(
|
(fns.v1_1.get_physical_device_external_semaphore_properties)(
|
||||||
self.handle,
|
self.handle,
|
||||||
&external_semaphore_info,
|
&external_semaphore_info,
|
||||||
&mut external_semaphore_properties,
|
&mut external_semaphore_properties,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(fns.khr_external_semaphore_capabilities
|
(fns.khr_external_semaphore_capabilities
|
||||||
.get_physical_device_external_semaphore_properties_khr)(
|
.get_physical_device_external_semaphore_properties_khr)(
|
||||||
self.handle,
|
self.handle,
|
||||||
&external_semaphore_info,
|
&external_semaphore_info,
|
||||||
&mut external_semaphore_properties,
|
&mut external_semaphore_properties,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok::<_, Infallible>(ExternalSemaphoreProperties {
|
ExternalSemaphoreProperties {
|
||||||
exportable: external_semaphore_properties
|
exportable: external_semaphore_properties
|
||||||
.external_semaphore_features
|
.external_semaphore_features
|
||||||
.intersects(ash::vk::ExternalSemaphoreFeatureFlags::EXPORTABLE),
|
.intersects(ash::vk::ExternalSemaphoreFeatureFlags::EXPORTABLE),
|
||||||
importable: external_semaphore_properties
|
importable: external_semaphore_properties
|
||||||
.external_semaphore_features
|
.external_semaphore_features
|
||||||
.intersects(ash::vk::ExternalSemaphoreFeatureFlags::IMPORTABLE),
|
.intersects(ash::vk::ExternalSemaphoreFeatureFlags::IMPORTABLE),
|
||||||
export_from_imported_handle_types: external_semaphore_properties
|
export_from_imported_handle_types: external_semaphore_properties
|
||||||
.export_from_imported_handle_types
|
.export_from_imported_handle_types
|
||||||
.into(),
|
.into(),
|
||||||
compatible_handle_types: external_semaphore_properties
|
compatible_handle_types: external_semaphore_properties
|
||||||
.compatible_handle_types
|
.compatible_handle_types
|
||||||
.into(),
|
.into(),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the properties of a format when used by this physical device.
|
/// Retrieves the properties of a format when used by this physical device.
|
||||||
@ -832,7 +828,7 @@ impl PhysicalDevice {
|
|||||||
|
|
||||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||||
pub unsafe fn format_properties_unchecked(&self, format: Format) -> FormatProperties {
|
pub unsafe fn format_properties_unchecked(&self, format: Format) -> FormatProperties {
|
||||||
get_cached(&self.format_properties, format, |&format| {
|
self.format_properties.get_or_insert(format, |&format| {
|
||||||
let mut format_properties2 = ash::vk::FormatProperties2::default();
|
let mut format_properties2 = ash::vk::FormatProperties2::default();
|
||||||
let mut format_properties3 = if self.api_version() >= Version::V1_3
|
let mut format_properties3 = if self.api_version() >= Version::V1_3
|
||||||
|| self.supported_extensions().khr_format_feature_flags2
|
|| self.supported_extensions().khr_format_feature_flags2
|
||||||
@ -874,7 +870,7 @@ impl PhysicalDevice {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok::<_, Infallible>(match format_properties3 {
|
match format_properties3 {
|
||||||
Some(format_properties3) => FormatProperties {
|
Some(format_properties3) => FormatProperties {
|
||||||
linear_tiling_features: format_properties3.linear_tiling_features.into(),
|
linear_tiling_features: format_properties3.linear_tiling_features.into(),
|
||||||
optimal_tiling_features: format_properties3.optimal_tiling_features.into(),
|
optimal_tiling_features: format_properties3.optimal_tiling_features.into(),
|
||||||
@ -893,9 +889,8 @@ impl PhysicalDevice {
|
|||||||
buffer_features: format_properties2.format_properties.buffer_features.into(),
|
buffer_features: format_properties2.format_properties.buffer_features.into(),
|
||||||
_ne: crate::NonExhaustive(()),
|
_ne: crate::NonExhaustive(()),
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the properties supported for images with a given image configuration.
|
/// Returns the properties supported for images with a given image configuration.
|
||||||
@ -1043,10 +1038,8 @@ impl PhysicalDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get_cached(
|
self.image_format_properties
|
||||||
&self.image_format_properties,
|
.get_or_try_insert(image_format_info, |image_format_info| {
|
||||||
image_format_info,
|
|
||||||
|image_format_info| {
|
|
||||||
/* Input */
|
/* Input */
|
||||||
let &ImageFormatInfo {
|
let &ImageFormatInfo {
|
||||||
format,
|
format,
|
||||||
@ -1198,8 +1191,7 @@ impl PhysicalDevice {
|
|||||||
Err(VulkanError::FormatNotSupported) => None,
|
Err(VulkanError::FormatNotSupported) => None,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
})
|
})
|
||||||
},
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Queries whether the physical device supports presenting to QNX Screen surfaces from queues
|
/// Queries whether the physical device supports presenting to QNX Screen surfaces from queues
|
||||||
@ -1325,10 +1317,8 @@ impl PhysicalDevice {
|
|||||||
&self,
|
&self,
|
||||||
format_info: SparseImageFormatInfo,
|
format_info: SparseImageFormatInfo,
|
||||||
) -> Vec<SparseImageFormatProperties> {
|
) -> Vec<SparseImageFormatProperties> {
|
||||||
get_cached(
|
self.sparse_image_format_properties
|
||||||
&self.sparse_image_format_properties,
|
.get_or_insert(format_info, |format_info| {
|
||||||
format_info,
|
|
||||||
|format_info| {
|
|
||||||
let &SparseImageFormatInfo {
|
let &SparseImageFormatInfo {
|
||||||
format,
|
format,
|
||||||
image_type,
|
image_type,
|
||||||
@ -1396,34 +1386,32 @@ impl PhysicalDevice {
|
|||||||
|
|
||||||
sparse_image_format_properties2.set_len(count as usize);
|
sparse_image_format_properties2.set_len(count as usize);
|
||||||
|
|
||||||
Ok::<_, Infallible>(
|
sparse_image_format_properties2
|
||||||
sparse_image_format_properties2
|
.into_iter()
|
||||||
.into_iter()
|
.map(
|
||||||
.map(
|
|sparse_image_format_properties2| SparseImageFormatProperties {
|
||||||
|sparse_image_format_properties2| SparseImageFormatProperties {
|
aspects: sparse_image_format_properties2
|
||||||
aspects: sparse_image_format_properties2
|
.properties
|
||||||
|
.aspect_mask
|
||||||
|
.into(),
|
||||||
|
image_granularity: [
|
||||||
|
sparse_image_format_properties2
|
||||||
.properties
|
.properties
|
||||||
.aspect_mask
|
.image_granularity
|
||||||
.into(),
|
.width,
|
||||||
image_granularity: [
|
sparse_image_format_properties2
|
||||||
sparse_image_format_properties2
|
.properties
|
||||||
.properties
|
.image_granularity
|
||||||
.image_granularity
|
.height,
|
||||||
.width,
|
sparse_image_format_properties2
|
||||||
sparse_image_format_properties2
|
.properties
|
||||||
.properties
|
.image_granularity
|
||||||
.image_granularity
|
.depth,
|
||||||
.height,
|
],
|
||||||
sparse_image_format_properties2
|
flags: sparse_image_format_properties2.properties.flags.into(),
|
||||||
.properties
|
},
|
||||||
.image_granularity
|
)
|
||||||
.depth,
|
.collect()
|
||||||
],
|
|
||||||
flags: sparse_image_format_properties2.properties.flags.into(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
@ -1454,26 +1442,22 @@ impl PhysicalDevice {
|
|||||||
|
|
||||||
sparse_image_format_properties.set_len(count as usize);
|
sparse_image_format_properties.set_len(count as usize);
|
||||||
|
|
||||||
Ok::<_, Infallible>(
|
sparse_image_format_properties
|
||||||
sparse_image_format_properties
|
.into_iter()
|
||||||
.into_iter()
|
.map(
|
||||||
.map(
|
|sparse_image_format_properties| SparseImageFormatProperties {
|
||||||
|sparse_image_format_properties| SparseImageFormatProperties {
|
aspects: sparse_image_format_properties.aspect_mask.into(),
|
||||||
aspects: sparse_image_format_properties.aspect_mask.into(),
|
image_granularity: [
|
||||||
image_granularity: [
|
sparse_image_format_properties.image_granularity.width,
|
||||||
sparse_image_format_properties.image_granularity.width,
|
sparse_image_format_properties.image_granularity.height,
|
||||||
sparse_image_format_properties.image_granularity.height,
|
sparse_image_format_properties.image_granularity.depth,
|
||||||
sparse_image_format_properties.image_granularity.depth,
|
],
|
||||||
],
|
flags: sparse_image_format_properties.flags.into(),
|
||||||
flags: sparse_image_format_properties.flags.into(),
|
},
|
||||||
},
|
)
|
||||||
)
|
.collect()
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the capabilities that are supported by the physical device for the given surface.
|
/// Returns the capabilities that are supported by the physical device for the given surface.
|
||||||
@ -1555,8 +1539,7 @@ impl PhysicalDevice {
|
|||||||
surface: &Surface<W>,
|
surface: &Surface<W>,
|
||||||
surface_info: SurfaceInfo,
|
surface_info: SurfaceInfo,
|
||||||
) -> Result<SurfaceCapabilities, VulkanError> {
|
) -> Result<SurfaceCapabilities, VulkanError> {
|
||||||
get_cached(
|
surface.surface_capabilities.get_or_try_insert(
|
||||||
&surface.surface_capabilities,
|
|
||||||
(self.handle, surface_info),
|
(self.handle, surface_info),
|
||||||
|(_, surface_info)| {
|
|(_, surface_info)| {
|
||||||
/* Input */
|
/* Input */
|
||||||
@ -1805,8 +1788,7 @@ impl PhysicalDevice {
|
|||||||
surface: &Surface<W>,
|
surface: &Surface<W>,
|
||||||
surface_info: SurfaceInfo,
|
surface_info: SurfaceInfo,
|
||||||
) -> Result<Vec<(Format, ColorSpace)>, VulkanError> {
|
) -> Result<Vec<(Format, ColorSpace)>, VulkanError> {
|
||||||
get_cached(
|
surface.surface_formats.get_or_try_insert(
|
||||||
&surface.surface_formats,
|
|
||||||
(self.handle, surface_info),
|
(self.handle, surface_info),
|
||||||
|(_, surface_info)| {
|
|(_, surface_info)| {
|
||||||
let &SurfaceInfo {
|
let &SurfaceInfo {
|
||||||
@ -1992,47 +1974,49 @@ impl PhysicalDevice {
|
|||||||
&self,
|
&self,
|
||||||
surface: &Surface<W>,
|
surface: &Surface<W>,
|
||||||
) -> Result<impl Iterator<Item = PresentMode>, VulkanError> {
|
) -> Result<impl Iterator<Item = PresentMode>, VulkanError> {
|
||||||
get_cached(&surface.surface_present_modes, self.handle, |_| {
|
surface
|
||||||
let fns = self.instance.fns();
|
.surface_present_modes
|
||||||
|
.get_or_try_insert(self.handle, |_| {
|
||||||
|
let fns = self.instance.fns();
|
||||||
|
|
||||||
let modes = loop {
|
let modes = loop {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
(fns.khr_surface
|
(fns.khr_surface
|
||||||
.get_physical_device_surface_present_modes_khr)(
|
.get_physical_device_surface_present_modes_khr)(
|
||||||
self.internal_object(),
|
self.internal_object(),
|
||||||
surface.internal_object(),
|
surface.internal_object(),
|
||||||
&mut count,
|
&mut count,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
)
|
)
|
||||||
.result()
|
.result()
|
||||||
.map_err(VulkanError::from)?;
|
.map_err(VulkanError::from)?;
|
||||||
|
|
||||||
let mut modes = Vec::with_capacity(count as usize);
|
let mut modes = Vec::with_capacity(count as usize);
|
||||||
let result = (fns
|
let result = (fns
|
||||||
.khr_surface
|
.khr_surface
|
||||||
.get_physical_device_surface_present_modes_khr)(
|
.get_physical_device_surface_present_modes_khr)(
|
||||||
self.internal_object(),
|
self.internal_object(),
|
||||||
surface.internal_object(),
|
surface.internal_object(),
|
||||||
&mut count,
|
&mut count,
|
||||||
modes.as_mut_ptr(),
|
modes.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
ash::vk::Result::SUCCESS => {
|
ash::vk::Result::SUCCESS => {
|
||||||
modes.set_len(count as usize);
|
modes.set_len(count as usize);
|
||||||
break modes;
|
break modes;
|
||||||
|
}
|
||||||
|
ash::vk::Result::INCOMPLETE => (),
|
||||||
|
err => return Err(VulkanError::from(err)),
|
||||||
}
|
}
|
||||||
ash::vk::Result::INCOMPLETE => (),
|
};
|
||||||
err => return Err(VulkanError::from(err)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(modes
|
Ok(modes
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|mode_vk| mode_vk.try_into().ok())
|
.filter_map(|mode_vk| mode_vk.try_into().ok())
|
||||||
.collect())
|
.collect())
|
||||||
})
|
})
|
||||||
.map(IntoIterator::into_iter)
|
.map(IntoIterator::into_iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether queues of the given queue family can draw on the given surface.
|
/// Returns whether queues of the given queue family can draw on the given surface.
|
||||||
@ -2082,10 +2066,9 @@ impl PhysicalDevice {
|
|||||||
queue_family_index: u32,
|
queue_family_index: u32,
|
||||||
surface: &Surface<W>,
|
surface: &Surface<W>,
|
||||||
) -> Result<bool, VulkanError> {
|
) -> Result<bool, VulkanError> {
|
||||||
get_cached(
|
surface
|
||||||
&surface.surface_support,
|
.surface_support
|
||||||
(self.handle, queue_family_index),
|
.get_or_try_insert((self.handle, queue_family_index), |_| {
|
||||||
|_| {
|
|
||||||
let fns = self.instance.fns();
|
let fns = self.instance.fns();
|
||||||
|
|
||||||
let mut output = MaybeUninit::uninit();
|
let mut output = MaybeUninit::uninit();
|
||||||
@ -2099,8 +2082,7 @@ impl PhysicalDevice {
|
|||||||
.map_err(VulkanError::from)?;
|
.map_err(VulkanError::from)?;
|
||||||
|
|
||||||
Ok(output.assume_init() != 0)
|
Ok(output.assume_init() != 0)
|
||||||
},
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the properties of tools that are currently active on the physical device.
|
/// Retrieves the properties of tools that are currently active on the physical device.
|
||||||
@ -2472,37 +2454,6 @@ impl Hash for PhysicalDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_cached<K, V, E>(
|
|
||||||
cache: &RwLock<HashMap<K, V>>,
|
|
||||||
key: K,
|
|
||||||
func: impl FnOnce(&K) -> Result<V, E>,
|
|
||||||
) -> Result<V, E>
|
|
||||||
where
|
|
||||||
K: Eq + Hash,
|
|
||||||
V: Clone,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
let read_lock = cache.read();
|
|
||||||
if let Some(result) = read_lock.get(&key) {
|
|
||||||
return Ok(result.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut write_lock = cache.write();
|
|
||||||
match write_lock.entry(key) {
|
|
||||||
Entry::Occupied(entry) => {
|
|
||||||
// This can happen if someone else inserted an entry between when we released
|
|
||||||
// the read lock and acquired the write lock.
|
|
||||||
Ok(entry.get().clone())
|
|
||||||
}
|
|
||||||
Entry::Vacant(entry) => {
|
|
||||||
let result = func(entry.key())?;
|
|
||||||
entry.insert(result.clone());
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vulkan_enum! {
|
vulkan_enum! {
|
||||||
/// Type of a physical device.
|
/// Type of a physical device.
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -104,6 +104,7 @@ pub mod format;
|
|||||||
mod version;
|
mod version;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod render_pass;
|
pub mod render_pass;
|
||||||
|
mod cache;
|
||||||
mod fns;
|
mod fns;
|
||||||
pub mod image;
|
pub mod image;
|
||||||
pub mod instance;
|
pub mod instance;
|
||||||
|
@ -36,8 +36,8 @@ use crate::{
|
|||||||
shader::{DescriptorRequirements, EntryPoint, SpecializationConstants},
|
shader::{DescriptorRequirements, EntryPoint, SpecializationConstants},
|
||||||
DeviceSize, OomError, VulkanError, VulkanObject,
|
DeviceSize, OomError, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Debug, Display, Error as FmtError, Formatter},
|
fmt::{Debug, Display, Error as FmtError, Formatter},
|
||||||
mem,
|
mem,
|
||||||
|
@ -51,9 +51,10 @@ use crate::{
|
|||||||
},
|
},
|
||||||
DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject,
|
DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, HashMap},
|
collections::hash_map::Entry,
|
||||||
mem::{size_of_val, MaybeUninit},
|
mem::{size_of_val, MaybeUninit},
|
||||||
ptr, slice,
|
ptr, slice,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
@ -217,7 +218,7 @@ where
|
|||||||
// We want to union each push constant range into a set of ranges that do not have intersecting stage flags.
|
// We want to union each push constant range into a set of ranges that do not have intersecting stage flags.
|
||||||
// e.g. The range [0, 16) is either made available to Vertex | Fragment or we only make [0, 16) available to
|
// e.g. The range [0, 16) is either made available to Vertex | Fragment or we only make [0, 16) available to
|
||||||
// Vertex and a subrange available to Fragment, like [0, 8)
|
// Vertex and a subrange available to Fragment, like [0, 8)
|
||||||
let mut range_map = HashMap::new();
|
let mut range_map = HashMap::default();
|
||||||
for stage in stages.iter() {
|
for stage in stages.iter() {
|
||||||
if let Some(range) = stage.push_constant_requirements() {
|
if let Some(range) = stage.push_constant_requirements() {
|
||||||
match range_map.entry((range.offset, range.size)) {
|
match range_map.entry((range.offset, range.size)) {
|
||||||
@ -2382,7 +2383,7 @@ where
|
|||||||
let render_pass = render_pass.as_ref().unwrap();
|
let render_pass = render_pass.as_ref().unwrap();
|
||||||
|
|
||||||
let mut descriptor_requirements: HashMap<(u32, u32), DescriptorRequirements> =
|
let mut descriptor_requirements: HashMap<(u32, u32), DescriptorRequirements> =
|
||||||
HashMap::new();
|
HashMap::default();
|
||||||
let mut dynamic_state: HashMap<DynamicState, bool> = HashMap::default();
|
let mut dynamic_state: HashMap<DynamicState, bool> = HashMap::default();
|
||||||
let mut stages = HashMap::default();
|
let mut stages = HashMap::default();
|
||||||
let mut stages_vk: SmallVec<[_; 5]> = SmallVec::new();
|
let mut stages_vk: SmallVec<[_; 5]> = SmallVec::new();
|
||||||
|
@ -70,8 +70,8 @@ use crate::{
|
|||||||
shader::{DescriptorRequirements, ShaderStage},
|
shader::{DescriptorRequirements, ShaderStage},
|
||||||
VulkanObject,
|
VulkanObject,
|
||||||
};
|
};
|
||||||
|
use ahash::HashMap;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
fmt::{Debug, Error as FmtError, Formatter},
|
fmt::{Debug, Error as FmtError, Formatter},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
ptr,
|
ptr,
|
||||||
|
@ -106,7 +106,7 @@ pub use self::{
|
|||||||
vertex::{Vertex, VertexMemberInfo, VertexMemberTy},
|
vertex::{Vertex, VertexMemberInfo, VertexMemberTy},
|
||||||
};
|
};
|
||||||
use crate::format::Format;
|
use crate::format::Format;
|
||||||
use std::collections::HashMap;
|
use ahash::HashMap;
|
||||||
|
|
||||||
mod buffers;
|
mod buffers;
|
||||||
mod collection;
|
mod collection;
|
||||||
|
@ -28,9 +28,9 @@ use crate::{
|
|||||||
sync::PipelineStages,
|
sync::PipelineStages,
|
||||||
DeviceSize, OomError, Version, VulkanError, VulkanObject,
|
DeviceSize, OomError, Version, VulkanError, VulkanObject,
|
||||||
};
|
};
|
||||||
|
use ahash::{HashMap, HashSet};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
error::Error,
|
error::Error,
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
fmt::{Display, Error as FmtError, Formatter},
|
fmt::{Display, Error as FmtError, Formatter},
|
||||||
|
@ -25,10 +25,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
DeviceSize,
|
DeviceSize,
|
||||||
};
|
};
|
||||||
use std::{
|
use ahash::{HashMap, HashSet};
|
||||||
borrow::Cow,
|
use std::borrow::Cow;
|
||||||
collections::{HashMap, HashSet},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Returns an iterator of the capabilities used by `spirv`.
|
/// Returns an iterator of the capabilities used by `spirv`.
|
||||||
pub fn spirv_capabilities(spirv: &Spirv) -> impl Iterator<Item = &Capability> {
|
pub fn spirv_capabilities(spirv: &Spirv) -> impl Iterator<Item = &Capability> {
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
//! [SPIR-V specification](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html).
|
//! [SPIR-V specification](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html).
|
||||||
|
|
||||||
use crate::Version;
|
use crate::Version;
|
||||||
|
use ahash::{HashMap, HashMapExt};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Display, Error as FmtError, Formatter},
|
fmt::{Display, Error as FmtError, Formatter},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
use super::{FullScreenExclusive, Win32Monitor};
|
use super::{FullScreenExclusive, Win32Monitor};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
cache::OnceCache,
|
||||||
format::Format,
|
format::Format,
|
||||||
image::ImageUsage,
|
image::ImageUsage,
|
||||||
instance::Instance,
|
instance::Instance,
|
||||||
@ -23,9 +24,7 @@ use crate::{
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
use objc::{class, msg_send, runtime::Object, sel, sel_impl};
|
use objc::{class, msg_send, runtime::Object, sel, sel_impl};
|
||||||
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
fmt::{Debug, Display, Error as FmtError, Formatter},
|
fmt::{Debug, Display, Error as FmtError, Formatter},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
@ -52,11 +51,11 @@ pub struct Surface<W> {
|
|||||||
// This is stored here rather than on `PhysicalDevice` to ensure that it's freed when the
|
// This is stored here rather than on `PhysicalDevice` to ensure that it's freed when the
|
||||||
// `Surface` is destroyed.
|
// `Surface` is destroyed.
|
||||||
pub(crate) surface_capabilities:
|
pub(crate) surface_capabilities:
|
||||||
RwLock<HashMap<(ash::vk::PhysicalDevice, SurfaceInfo), SurfaceCapabilities>>,
|
OnceCache<(ash::vk::PhysicalDevice, SurfaceInfo), SurfaceCapabilities>,
|
||||||
pub(crate) surface_formats:
|
pub(crate) surface_formats:
|
||||||
RwLock<HashMap<(ash::vk::PhysicalDevice, SurfaceInfo), Vec<(Format, ColorSpace)>>>,
|
OnceCache<(ash::vk::PhysicalDevice, SurfaceInfo), Vec<(Format, ColorSpace)>>,
|
||||||
pub(crate) surface_present_modes: RwLock<HashMap<ash::vk::PhysicalDevice, Vec<PresentMode>>>,
|
pub(crate) surface_present_modes: OnceCache<ash::vk::PhysicalDevice, Vec<PresentMode>>,
|
||||||
pub(crate) surface_support: RwLock<HashMap<(ash::vk::PhysicalDevice, u32), bool>>,
|
pub(crate) surface_support: OnceCache<(ash::vk::PhysicalDevice, u32), bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W> Surface<W> {
|
impl<W> Surface<W> {
|
||||||
@ -85,10 +84,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,10 +150,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,10 +249,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,10 +330,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,10 +419,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,10 +505,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,10 +591,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,10 +678,10 @@ impl<W> Surface<W> {
|
|||||||
has_swapchain: AtomicBool::new(false),
|
has_swapchain: AtomicBool::new(false),
|
||||||
metal_layer,
|
metal_layer,
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,10 +766,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,10 +844,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -936,10 +935,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1017,10 +1016,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,10 +1109,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1201,10 +1200,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1292,10 +1291,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1383,10 +1382,10 @@ impl<W> Surface<W> {
|
|||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()),
|
||||||
|
|
||||||
surface_capabilities: RwLock::new(HashMap::new()),
|
surface_capabilities: OnceCache::new(),
|
||||||
surface_formats: RwLock::new(HashMap::new()),
|
surface_formats: OnceCache::new(),
|
||||||
surface_present_modes: RwLock::new(HashMap::new()),
|
surface_present_modes: OnceCache::new(),
|
||||||
surface_support: RwLock::new(HashMap::new()),
|
surface_support: OnceCache::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user