From 1c2d195dab63654c6b782709aa0c210d61e8dd83 Mon Sep 17 00:00:00 2001 From: marc0246 <40955683+marc0246@users.noreply.github.com> Date: Tue, 4 Oct 2022 10:04:52 +0200 Subject: [PATCH] Improvements to caches and switch to `ahash` (#2019) * Add `OnceCache` * Switch to `ahash` --- vulkano-shaders/Cargo.toml | 1 + vulkano-shaders/src/codegen.rs | 24 +- vulkano-shaders/src/entry_point.rs | 15 +- vulkano-shaders/src/lib.rs | 24 +- vulkano-shaders/src/structs.rs | 3 +- vulkano-util/Cargo.toml | 1 + vulkano-util/src/context.rs | 2 +- vulkano-util/src/renderer.rs | 24 +- vulkano-util/src/window.rs | 11 +- vulkano-win/src/raw_window_handle.rs | 7 +- vulkano/Cargo.toml | 2 + vulkano/autogen/extensions.rs | 3 +- vulkano/autogen/features.rs | 13 +- vulkano/autogen/fns.rs | 3 +- vulkano/autogen/formats.rs | 3 +- vulkano/autogen/mod.rs | 5 +- vulkano/autogen/properties.rs | 13 +- vulkano/autogen/spirv_parse.rs | 4 +- vulkano/autogen/spirv_reqs.rs | 6 +- vulkano/src/cache.rs | 78 ++++ vulkano/src/command_buffer/auto.rs | 2 +- vulkano/src/command_buffer/synced/builder.rs | 3 +- vulkano/src/command_buffer/synced/mod.rs | 2 +- vulkano/src/descriptor_set/layout.rs | 5 +- vulkano/src/descriptor_set/mod.rs | 2 +- vulkano/src/descriptor_set/pool/standard.rs | 3 +- vulkano/src/descriptor_set/pool/sys.rs | 2 +- vulkano/src/device/mod.rs | 3 +- vulkano/src/device/physical.rs | 359 ++++++++---------- vulkano/src/lib.rs | 1 + vulkano/src/pipeline/compute.rs | 2 +- vulkano/src/pipeline/graphics/builder.rs | 7 +- vulkano/src/pipeline/graphics/mod.rs | 2 +- .../src/pipeline/graphics/vertex_input/mod.rs | 2 +- vulkano/src/shader/mod.rs | 2 +- vulkano/src/shader/reflect.rs | 6 +- vulkano/src/shader/spirv.rs | 2 +- vulkano/src/swapchain/surface.rs | 139 ++++--- 38 files changed, 408 insertions(+), 378 deletions(-) create mode 100644 vulkano/src/cache.rs diff --git a/vulkano-shaders/Cargo.toml b/vulkano-shaders/Cargo.toml index 3c22db69..b142943b 100644 --- a/vulkano-shaders/Cargo.toml +++ b/vulkano-shaders/Cargo.toml @@ -15,6 +15,7 @@ categories = ["rendering::graphics-api"] proc-macro = true [dependencies] +ahash = "0.8" heck = "0.4" proc-macro2 = "1.0" quote = "1.0" diff --git a/vulkano-shaders/src/codegen.rs b/vulkano-shaders/src/codegen.rs index e448c65e..3d98723e 100644 --- a/vulkano-shaders/src/codegen.rs +++ b/vulkano-shaders/src/codegen.rs @@ -7,23 +7,21 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use crate::entry_point; -use crate::read_file_to_string; -use crate::structs; -use crate::RegisteredType; -use crate::TypesMeta; +use crate::{entry_point, read_file_to_string, structs, RegisteredType, TypesMeta}; +use ahash::HashMap; use proc_macro2::TokenStream; pub use shaderc::{CompilationArtifact, IncludeType, ResolvedInclude, ShaderKind}; use shaderc::{CompileOptions, Compiler, EnvVersion, SpirvVersion, TargetEnv}; -use std::collections::HashMap; -use std::iter::Iterator; -use std::path::Path; use std::{ cell::{RefCell, RefMut}, 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 { path.to_str().expect( @@ -378,7 +376,7 @@ mod tests { .unwrap(); let spirv = Spirv::new(comp.as_binary()).unwrap(); 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()); } @@ -407,7 +405,7 @@ mod tests { ) .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] fn test_wrap_alignment() { @@ -439,7 +437,7 @@ mod tests { ) .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] diff --git a/vulkano-shaders/src/entry_point.rs b/vulkano-shaders/src/entry_point.rs index 463786bb..2852dd70 100644 --- a/vulkano-shaders/src/entry_point.rs +++ b/vulkano-shaders/src/entry_point.rs @@ -7,15 +7,16 @@ // notice may not be copied, modified, or distributed except // according to those terms. +use ahash::HashMap; use proc_macro2::TokenStream; -use std::collections::HashMap; -use vulkano::pipeline::layout::PushConstantRange; -use vulkano::shader::spirv::ExecutionModel; -use vulkano::shader::{ - DescriptorIdentifier, DescriptorRequirements, ShaderExecution, ShaderInterfaceEntry, - ShaderInterfaceEntryType, SpecializationConstantRequirements, +use vulkano::{ + pipeline::layout::PushConstantRange, + shader::{ + spirv::ExecutionModel, DescriptorIdentifier, DescriptorRequirements, EntryPointInfo, + ShaderExecution, ShaderInterface, ShaderInterfaceEntry, ShaderInterfaceEntryType, + ShaderStages, SpecializationConstantRequirements, + }, }; -use vulkano::shader::{EntryPointInfo, ShaderInterface, ShaderStages}; pub(super) fn write_entry_point( name: &str, diff --git a/vulkano-shaders/src/lib.rs b/vulkano-shaders/src/lib.rs index fb4b28b8..55d03279 100644 --- a/vulkano-shaders/src/lib.rs +++ b/vulkano-shaders/src/lib.rs @@ -225,17 +225,19 @@ extern crate quote; extern crate syn; use crate::codegen::ShaderKind; +use ahash::HashMap; use shaderc::{EnvVersion, SpirvVersion}; -use std::borrow::Cow; -use std::collections::HashMap; -use std::fs; -use std::fs::File; -use std::io::{Read, Result as IoResult}; -use std::path::Path; -use std::slice::from_raw_parts; -use std::{env, iter::empty}; -use syn::parse::{Parse, ParseStream, Result}; +use std::{ + borrow::Cow, + env, fs, + fs::File, + io::{Read, Result as IoResult}, + iter::empty, + path::Path, + slice::from_raw_parts, +}; use syn::{ + parse::{Parse, ParseStream, Result}, 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 macro_defines = Vec::new(); let mut shared_constants = None; - let mut shaders = HashMap::new(); + let mut shaders = HashMap::default(); let mut spirv_version = None; let mut types_meta = 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 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 { let (code, types) = if let SourceKind::Bytes(path) = shader_source { diff --git a/vulkano-shaders/src/structs.rs b/vulkano-shaders/src/structs.rs index ac6e06d9..1d2613af 100644 --- a/vulkano-shaders/src/structs.rs +++ b/vulkano-shaders/src/structs.rs @@ -8,9 +8,10 @@ // according to those terms. use crate::{RegisteredType, TypesMeta}; +use ahash::HashMap; use heck::ToUpperCamelCase; use proc_macro2::{Span, TokenStream}; -use std::{borrow::Cow, collections::HashMap, mem}; +use std::{borrow::Cow, mem}; use syn::{Ident, LitStr}; use vulkano::shader::spirv::{Decoration, Id, Instruction, Spirv}; diff --git a/vulkano-util/Cargo.toml b/vulkano-util/Cargo.toml index a170f717..fd239dbb 100644 --- a/vulkano-util/Cargo.toml +++ b/vulkano-util/Cargo.toml @@ -12,6 +12,7 @@ keywords = ["vulkan", "bindings", "graphics", "gpu", "rendering"] categories = ["rendering::graphics-api"] [dependencies] +ahash = "0.8" vulkano = { version = "0.31.0", path = "../vulkano" } vulkano-win = { version = "0.31.0", path = "../vulkano-win" } winit = { version = "0.27" } diff --git a/vulkano-util/src/context.rs b/vulkano-util/src/context.rs index e25fd8a8..37eada12 100644 --- a/vulkano-util/src/context.rs +++ b/vulkano-util/src/context.rs @@ -17,8 +17,8 @@ use vulkano::{ debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo}, Instance, InstanceCreateInfo, InstanceExtensions, }, + Version, VulkanLibrary, }; -use vulkano::{Version, VulkanLibrary}; /// A configuration struct to pass various creation options to create [`VulkanoContext`]. /// diff --git a/vulkano-util/src/renderer.rs b/vulkano-util/src/renderer.rs index 950ac76f..f73a5dd7 100644 --- a/vulkano-util/src/renderer.rs +++ b/vulkano-util/src/renderer.rs @@ -7,22 +7,20 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::collections::HashMap; +use crate::{context::VulkanoContext, window::WindowDescriptor}; +use ahash::HashMap; 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::{ - device::Queue, + device::{Device, Queue}, format::Format, - image::{view::ImageView, ImageAccess, ImageViewAbstract}, - swapchain, - swapchain::{AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError}, - sync, - sync::{FlushError, GpuFuture}, + image::{ + view::ImageView, ImageAccess, ImageUsage, ImageViewAbstract, StorageImage, SwapchainImage, + }, + swapchain::{ + self, AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainCreationError, + SwapchainPresentInfo, + }, + sync::{self, FlushError, GpuFuture}, }; use vulkano_win::create_surface_from_winit; use winit::window::Window; diff --git a/vulkano-util/src/window.rs b/vulkano-util/src/window.rs index 78b57162..c30afe30 100644 --- a/vulkano-util/src/window.rs +++ b/vulkano-util/src/window.rs @@ -11,13 +11,14 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use crate::context::VulkanoContext; -use crate::renderer::VulkanoWindowRenderer; +use crate::{context::VulkanoContext, renderer::VulkanoWindowRenderer}; +use ahash::HashMap; use std::collections::hash_map::{Iter, IterMut}; -use std::collections::HashMap; use vulkano::swapchain::{PresentMode, SwapchainCreateInfo}; -use winit::dpi::LogicalSize; -use winit::window::{CursorGrabMode, WindowId}; +use winit::{ + dpi::LogicalSize, + window::{CursorGrabMode, WindowId}, +}; /// A struct organizing windows and their corresponding renderers. This makes it easy to handle multiple windows. /// diff --git a/vulkano-win/src/raw_window_handle.rs b/vulkano-win/src/raw_window_handle.rs index d575b309..a30086ba 100644 --- a/vulkano-win/src/raw_window_handle.rs +++ b/vulkano-win/src/raw_window_handle.rs @@ -6,9 +6,10 @@ use raw_window_handle::{ HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, }; use std::sync::Arc; -use vulkano::instance::Instance; -use vulkano::swapchain::Surface; -use vulkano::swapchain::SurfaceCreationError; +use vulkano::{ + instance::Instance, + swapchain::{Surface, SurfaceCreationError}, +}; /// Creates a vulkan surface from a generic window /// which implements HasRawWindowHandle and thus can reveal the os-dependent handle. diff --git a/vulkano/Cargo.toml b/vulkano/Cargo.toml index ba0b3faa..403b0ea1 100644 --- a/vulkano/Cargo.toml +++ b/vulkano/Cargo.toml @@ -14,6 +14,7 @@ readme = "../README.md" build = "build.rs" [dependencies] +ahash = "0.8" # 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. ash = "0.37" @@ -30,6 +31,7 @@ objc = "0.2.5" core-graphics-types = "0.1" [build-dependencies] +ahash = "0.8" heck = "0.4" indexmap = "1.8" lazy_static = "1.4" diff --git a/vulkano/autogen/extensions.rs b/vulkano/autogen/extensions.rs index 9d907666..66a781a0 100644 --- a/vulkano/autogen/extensions.rs +++ b/vulkano/autogen/extensions.rs @@ -7,9 +7,8 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use super::{write_file, VkRegistryData}; +use super::{write_file, IndexMap, VkRegistryData}; use heck::ToSnakeCase; -use indexmap::IndexMap; use proc_macro2::{Ident, Literal, TokenStream}; use quote::{format_ident, quote}; use std::fmt::Write as _; diff --git a/vulkano/autogen/features.rs b/vulkano/autogen/features.rs index 6d2114ab..5b214fdb 100644 --- a/vulkano/autogen/features.rs +++ b/vulkano/autogen/features.rs @@ -7,16 +7,13 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use super::{write_file, VkRegistryData}; +use super::{write_file, IndexMap, VkRegistryData}; +use ahash::HashMap; use heck::ToSnakeCase; -use indexmap::IndexMap; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use regex::Regex; -use std::{ - collections::{hash_map::Entry, HashMap}, - fmt::Write as _, -}; +use std::{collections::hash_map::Entry, fmt::Write as _}; use vk_parse::{Extension, Type, TypeMember, TypeMemberMarkup, TypeSpec}; // 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 { - let mut features = HashMap::new(); + let mut features = HashMap::default(); std::iter::once(&types["VkPhysicalDeviceFeatures"]) .chain(sorted_structs(types).into_iter()) .filter(|(ty, _)| { @@ -728,7 +725,7 @@ fn features_ffi_members<'a>( types: &'a HashMap<&str, (&Type, Vec<&str>)>, extensions: &IndexMap<&'a str, &Extension>, ) -> Vec { - 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) .into_iter() .map(|(ty, provided_by)| { diff --git a/vulkano/autogen/fns.rs b/vulkano/autogen/fns.rs index 753af494..0e53935e 100644 --- a/vulkano/autogen/fns.rs +++ b/vulkano/autogen/fns.rs @@ -7,9 +7,8 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use super::{write_file, VkRegistryData}; +use super::{write_file, IndexMap, VkRegistryData}; use heck::{ToSnakeCase, ToUpperCamelCase}; -use indexmap::IndexMap; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use vk_parse::{Extension, ExtensionChild, InterfaceItem}; diff --git a/vulkano/autogen/formats.rs b/vulkano/autogen/formats.rs index f253b1f3..5c37a367 100644 --- a/vulkano/autogen/formats.rs +++ b/vulkano/autogen/formats.rs @@ -7,9 +7,8 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use super::{extensions::RequiresOneOf, write_file, VkRegistryData}; +use super::{extensions::RequiresOneOf, write_file, IndexMap, VkRegistryData}; use heck::ToSnakeCase; -use indexmap::IndexMap; use lazy_static::lazy_static; use proc_macro2::{Ident, Literal, TokenStream}; use quote::{format_ident, quote}; diff --git a/vulkano/autogen/mod.rs b/vulkano/autogen/mod.rs index c6d63321..d6d55a66 100644 --- a/vulkano/autogen/mod.rs +++ b/vulkano/autogen/mod.rs @@ -8,11 +8,10 @@ // according to those terms. use self::spirv_grammar::SpirvGrammar; -use indexmap::IndexMap; +use ahash::HashMap; use lazy_static::lazy_static; use regex::Regex; use std::{ - collections::HashMap, env, fmt::Display, fs::File, @@ -36,6 +35,8 @@ mod spirv_parse; mod spirv_reqs; mod version; +pub type IndexMap = indexmap::IndexMap; + pub fn autogen() { let registry = get_vk_registry("vk.xml"); let vk_data = VkRegistryData::new(®istry); diff --git a/vulkano/autogen/properties.rs b/vulkano/autogen/properties.rs index fbfea7b8..cb85e19c 100644 --- a/vulkano/autogen/properties.rs +++ b/vulkano/autogen/properties.rs @@ -7,16 +7,13 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use super::{write_file, VkRegistryData}; +use super::{write_file, IndexMap, VkRegistryData}; +use ahash::HashMap; use heck::ToSnakeCase; -use indexmap::IndexMap; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use regex::Regex; -use std::{ - collections::{hash_map::Entry, HashMap}, - fmt::Write as _, -}; +use std::{collections::hash_map::Entry, fmt::Write as _}; use vk_parse::{Extension, Type, TypeMember, TypeMemberMarkup, TypeSpec}; 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 { - let mut properties = HashMap::new(); + let mut properties = HashMap::default(); [ &types["VkPhysicalDeviceProperties"], @@ -306,7 +303,7 @@ fn properties_ffi_members<'a>( types: &'a HashMap<&str, (&Type, Vec<&str>)>, extensions: &IndexMap<&'a str, &Extension>, ) -> Vec { - 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) .into_iter() .map(|(ty, provided_by)| { diff --git a/vulkano/autogen/spirv_parse.rs b/vulkano/autogen/spirv_parse.rs index 8f639f0b..474729da 100644 --- a/vulkano/autogen/spirv_parse.rs +++ b/vulkano/autogen/spirv_parse.rs @@ -8,11 +8,11 @@ // according to those terms. use super::{write_file, SpirvGrammar}; +use ahash::{HashMap, HashSet}; use heck::ToSnakeCase; use lazy_static::lazy_static; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; -use std::collections::{HashMap, HashSet}; lazy_static! { static ref SPEC_CONSTANT_OP: HashSet<&'static str> = { @@ -252,7 +252,7 @@ fn instruction_members(grammar: &SpirvGrammar) -> Vec { let name = format_ident!("{}", instruction.opname.strip_prefix("Op").unwrap()); let mut has_result_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 .operands diff --git a/vulkano/autogen/spirv_reqs.rs b/vulkano/autogen/spirv_reqs.rs index b1a0ecd3..ca6f96a8 100644 --- a/vulkano/autogen/spirv_reqs.rs +++ b/vulkano/autogen/spirv_reqs.rs @@ -9,10 +9,10 @@ use super::{ spirv_grammar::{SpirvGrammar, SpirvKindEnumerant}, - write_file, VkRegistryData, + write_file, IndexMap, VkRegistryData, }; use heck::ToSnakeCase; -use indexmap::{map::Entry, IndexMap}; +use indexmap::map::Entry; use lazy_static::lazy_static; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; @@ -148,7 +148,7 @@ fn spirv_capabilities_members( capabilities: &[&SpirvExtOrCap], grammar_enumerants: &[SpirvKindEnumerant], ) -> Vec { - let mut members: IndexMap = IndexMap::new(); + let mut members: IndexMap = IndexMap::default(); for ext_or_cap in capabilities { let mut enables: Vec<_> = ext_or_cap.enables.iter().filter_map(make_enable).collect(); diff --git a/vulkano/src/cache.rs b/vulkano/src/cache.rs new file mode 100644 index 00000000..34c0f37d --- /dev/null +++ b/vulkano/src/cache.rs @@ -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 { + inner: RwLock>, +} + +impl Default for OnceCache { + fn default() -> Self { + OnceCache { + inner: RwLock::new(HashMap::default()), + } + } +} + +impl OnceCache { + /// Creates a new `OnceCache`. + pub fn new() -> Self { + Self::default() + } +} + +impl OnceCache +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(&self, key: K, f: impl FnOnce(&K) -> Result) -> Result { + 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) + } + } + } +} diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index a8e0acfd..230999b2 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -29,8 +29,8 @@ use crate::{ sync::{AccessCheckError, AccessFlags, GpuFuture, PipelineMemoryAccess, PipelineStages}, DeviceSize, OomError, RequirementNotMet, RequiresOneOf, }; +use ahash::HashMap; use std::{ - collections::HashMap, error::Error, fmt::{Display, Error as FmtError, Formatter}, marker::PhantomData, diff --git a/vulkano/src/command_buffer/synced/builder.rs b/vulkano/src/command_buffer/synced/builder.rs index 2d3f5f24..11764094 100644 --- a/vulkano/src/command_buffer/synced/builder.rs +++ b/vulkano/src/command_buffer/synced/builder.rs @@ -43,10 +43,11 @@ use crate::{ }, DeviceSize, OomError, VulkanObject, }; +use ahash::HashMap; use smallvec::SmallVec; use std::{ borrow::Cow, - collections::{hash_map::Entry, HashMap}, + collections::hash_map::Entry, error::Error, fmt::{Debug, Display, Error as FmtError, Formatter}, ops::{Range, RangeInclusive}, diff --git a/vulkano/src/command_buffer/synced/mod.rs b/vulkano/src/command_buffer/synced/mod.rs index 51c1cc27..6cebcbfc 100644 --- a/vulkano/src/command_buffer/synced/mod.rs +++ b/vulkano/src/command_buffer/synced/mod.rs @@ -84,9 +84,9 @@ use crate::{ }, DeviceSize, }; +use ahash::HashMap; use std::{ borrow::Cow, - collections::HashMap, fmt::{Debug, Error as FmtError, Formatter}, ops::Range, sync::Arc, diff --git a/vulkano/src/descriptor_set/layout.rs b/vulkano/src/descriptor_set/layout.rs index 7bc302c3..9a3ab586 100644 --- a/vulkano/src/descriptor_set/layout.rs +++ b/vulkano/src/descriptor_set/layout.rs @@ -18,8 +18,9 @@ use crate::{ shader::{DescriptorRequirements, ShaderStages}, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; +use ahash::HashMap; use std::{ - collections::{BTreeMap, HashMap}, + collections::BTreeMap, error::Error, fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, @@ -900,7 +901,7 @@ mod tests { }, shader::ShaderStages, }; - use std::collections::HashMap; + use ahash::HashMap; #[test] fn empty() { diff --git a/vulkano/src/descriptor_set/mod.rs b/vulkano/src/descriptor_set/mod.rs index 813be192..0d3cf779 100644 --- a/vulkano/src/descriptor_set/mod.rs +++ b/vulkano/src/descriptor_set/mod.rs @@ -89,9 +89,9 @@ use crate::{ sampler::Sampler, OomError, VulkanObject, }; +use ahash::HashMap; use smallvec::{smallvec, SmallVec}; use std::{ - collections::HashMap, error::Error, fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, diff --git a/vulkano/src/descriptor_set/pool/standard.rs b/vulkano/src/descriptor_set/pool/standard.rs index 6c5524b3..22b92866 100644 --- a/vulkano/src/descriptor_set/pool/standard.rs +++ b/vulkano/src/descriptor_set/pool/standard.rs @@ -20,7 +20,8 @@ use crate::{ device::{Device, DeviceOwned}, OomError, }; -use std::{collections::HashMap, sync::Arc}; +use ahash::HashMap; +use std::sync::Arc; /// Standard implementation of a descriptor pool. /// diff --git a/vulkano/src/descriptor_set/pool/sys.rs b/vulkano/src/descriptor_set/pool/sys.rs index 23324005..fbe20a56 100644 --- a/vulkano/src/descriptor_set/pool/sys.rs +++ b/vulkano/src/descriptor_set/pool/sys.rs @@ -15,9 +15,9 @@ use crate::{ device::{Device, DeviceOwned}, OomError, Version, VulkanError, VulkanObject, }; +use ahash::HashMap; use smallvec::SmallVec; use std::{ - collections::HashMap, error::Error, fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, diff --git a/vulkano/src/device/mod.rs b/vulkano/src/device/mod.rs index 285e8dd1..d8d313eb 100644 --- a/vulkano/src/device/mod.rs +++ b/vulkano/src/device/mod.rs @@ -120,12 +120,13 @@ pub use crate::{ extensions::{ExtensionRestriction, ExtensionRestrictionError}, fns::DeviceFunctions, }; +use ahash::HashMap; use ash::vk::Handle; use parking_lot::Mutex; use smallvec::SmallVec; use std::{ cell::RefCell, - collections::{hash_map::Entry, HashMap}, + collections::hash_map::Entry, error::Error, ffi::CString, fmt::{Display, Error as FmtError, Formatter}, diff --git a/vulkano/src/device/physical.rs b/vulkano/src/device/physical.rs index 03184557..da0439db 100644 --- a/vulkano/src/device/physical.rs +++ b/vulkano/src/device/physical.rs @@ -10,6 +10,7 @@ use super::QueueFamilyProperties; use crate::{ buffer::{ExternalBufferInfo, ExternalBufferProperties}, + cache::OnceCache, device::{DeviceExtensions, Features, FeaturesFfi, Properties, PropertiesFfi}, format::{Format, FormatProperties}, image::{ @@ -30,10 +31,7 @@ use crate::{ ExtensionProperties, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use bytemuck::cast_slice; -use parking_lot::RwLock; use std::{ - collections::{hash_map::Entry, HashMap}, - convert::Infallible, error::Error, fmt::{Debug, Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, @@ -78,14 +76,13 @@ pub struct PhysicalDevice { queue_family_properties: Vec, // Data queried by the user at runtime, cached for faster lookups. - external_buffer_properties: RwLock>, - external_fence_properties: RwLock>, - external_semaphore_properties: - RwLock>, - format_properties: RwLock>, - image_format_properties: RwLock>>, + external_buffer_properties: OnceCache, + external_fence_properties: OnceCache, + external_semaphore_properties: OnceCache, + format_properties: OnceCache, + image_format_properties: OnceCache>, sparse_image_format_properties: - RwLock>>, + OnceCache>, } impl PhysicalDevice { @@ -143,12 +140,12 @@ impl PhysicalDevice { memory_properties, queue_family_properties, - external_buffer_properties: RwLock::new(HashMap::new()), - external_fence_properties: RwLock::new(HashMap::new()), - external_semaphore_properties: RwLock::new(HashMap::new()), - format_properties: RwLock::new(HashMap::new()), - image_format_properties: RwLock::new(HashMap::new()), - sparse_image_format_properties: RwLock::new(HashMap::new()), + external_buffer_properties: OnceCache::new(), + external_fence_properties: OnceCache::new(), + external_semaphore_properties: OnceCache::new(), + format_properties: OnceCache::new(), + image_format_properties: OnceCache::new(), + sparse_image_format_properties: OnceCache::new(), })) } @@ -544,7 +541,7 @@ impl PhysicalDevice { &self, info: ExternalBufferInfo, ) -> ExternalBufferProperties { - get_cached(&self.external_buffer_properties, info, |info| { + self.external_buffer_properties.get_or_insert(info, |info| { /* Input */ let &ExternalBufferInfo { @@ -584,13 +581,12 @@ impl PhysicalDevice { ); } - Ok::<_, Infallible>(ExternalBufferProperties { + ExternalBufferProperties { external_memory_properties: external_buffer_properties .external_memory_properties .into(), - }) + } }) - .unwrap() } /// Retrieves the external handle properties supported for fences with a given @@ -648,7 +644,7 @@ impl PhysicalDevice { &self, info: ExternalFenceInfo, ) -> ExternalFenceProperties { - get_cached(&self.external_fence_properties, info, |info| { + self.external_fence_properties.get_or_insert(info, |info| { /* Input */ let &ExternalFenceInfo { @@ -684,7 +680,7 @@ impl PhysicalDevice { ); } - Ok::<_, Infallible>(ExternalFenceProperties { + ExternalFenceProperties { exportable: external_fence_properties .external_fence_features .intersects(ash::vk::ExternalFenceFeatureFlags::EXPORTABLE), @@ -695,9 +691,8 @@ impl PhysicalDevice { .export_from_imported_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 @@ -755,58 +750,59 @@ impl PhysicalDevice { &self, info: ExternalSemaphoreInfo, ) -> ExternalSemaphoreProperties { - get_cached(&self.external_semaphore_properties, info, |info| { - /* Input */ + self.external_semaphore_properties + .get_or_insert(info, |info| { + /* Input */ - let &ExternalSemaphoreInfo { - handle_type, - _ne: _, - } = info; + let &ExternalSemaphoreInfo { + handle_type, + _ne: _, + } = info; - let external_semaphore_info = ash::vk::PhysicalDeviceExternalSemaphoreInfo { - handle_type: handle_type.into(), - ..Default::default() - }; + let external_semaphore_info = ash::vk::PhysicalDeviceExternalSemaphoreInfo { + handle_type: handle_type.into(), + ..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 { - (fns.v1_1.get_physical_device_external_semaphore_properties)( - self.handle, - &external_semaphore_info, - &mut external_semaphore_properties, - ) - } else { - (fns.khr_external_semaphore_capabilities - .get_physical_device_external_semaphore_properties_khr)( - self.handle, - &external_semaphore_info, - &mut external_semaphore_properties, - ); - } + if self.instance.api_version() >= Version::V1_1 { + (fns.v1_1.get_physical_device_external_semaphore_properties)( + self.handle, + &external_semaphore_info, + &mut external_semaphore_properties, + ) + } else { + (fns.khr_external_semaphore_capabilities + .get_physical_device_external_semaphore_properties_khr)( + self.handle, + &external_semaphore_info, + &mut external_semaphore_properties, + ); + } - Ok::<_, Infallible>(ExternalSemaphoreProperties { - exportable: external_semaphore_properties - .external_semaphore_features - .intersects(ash::vk::ExternalSemaphoreFeatureFlags::EXPORTABLE), - importable: external_semaphore_properties - .external_semaphore_features - .intersects(ash::vk::ExternalSemaphoreFeatureFlags::IMPORTABLE), - export_from_imported_handle_types: external_semaphore_properties - .export_from_imported_handle_types - .into(), - compatible_handle_types: external_semaphore_properties - .compatible_handle_types - .into(), + ExternalSemaphoreProperties { + exportable: external_semaphore_properties + .external_semaphore_features + .intersects(ash::vk::ExternalSemaphoreFeatureFlags::EXPORTABLE), + importable: external_semaphore_properties + .external_semaphore_features + .intersects(ash::vk::ExternalSemaphoreFeatureFlags::IMPORTABLE), + export_from_imported_handle_types: external_semaphore_properties + .export_from_imported_handle_types + .into(), + compatible_handle_types: external_semaphore_properties + .compatible_handle_types + .into(), + } }) - }) - .unwrap() } /// 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))] 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_properties3 = if self.api_version() >= Version::V1_3 || 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 { linear_tiling_features: format_properties3.linear_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(), _ne: crate::NonExhaustive(()), }, - }) + } }) - .unwrap() } /// Returns the properties supported for images with a given image configuration. @@ -1043,10 +1038,8 @@ impl PhysicalDevice { } } - get_cached( - &self.image_format_properties, - image_format_info, - |image_format_info| { + self.image_format_properties + .get_or_try_insert(image_format_info, |image_format_info| { /* Input */ let &ImageFormatInfo { format, @@ -1198,8 +1191,7 @@ impl PhysicalDevice { Err(VulkanError::FormatNotSupported) => None, Err(err) => return Err(err), }) - }, - ) + }) } /// Queries whether the physical device supports presenting to QNX Screen surfaces from queues @@ -1325,10 +1317,8 @@ impl PhysicalDevice { &self, format_info: SparseImageFormatInfo, ) -> Vec { - get_cached( - &self.sparse_image_format_properties, - format_info, - |format_info| { + self.sparse_image_format_properties + .get_or_insert(format_info, |format_info| { let &SparseImageFormatInfo { format, image_type, @@ -1396,34 +1386,32 @@ impl PhysicalDevice { sparse_image_format_properties2.set_len(count as usize); - Ok::<_, Infallible>( - sparse_image_format_properties2 - .into_iter() - .map( - |sparse_image_format_properties2| SparseImageFormatProperties { - aspects: sparse_image_format_properties2 + sparse_image_format_properties2 + .into_iter() + .map( + |sparse_image_format_properties2| SparseImageFormatProperties { + aspects: sparse_image_format_properties2 + .properties + .aspect_mask + .into(), + image_granularity: [ + sparse_image_format_properties2 .properties - .aspect_mask - .into(), - image_granularity: [ - sparse_image_format_properties2 - .properties - .image_granularity - .width, - sparse_image_format_properties2 - .properties - .image_granularity - .height, - sparse_image_format_properties2 - .properties - .image_granularity - .depth, - ], - flags: sparse_image_format_properties2.properties.flags.into(), - }, - ) - .collect(), - ) + .image_granularity + .width, + sparse_image_format_properties2 + .properties + .image_granularity + .height, + sparse_image_format_properties2 + .properties + .image_granularity + .depth, + ], + flags: sparse_image_format_properties2.properties.flags.into(), + }, + ) + .collect() } else { let mut count = 0; @@ -1454,26 +1442,22 @@ impl PhysicalDevice { sparse_image_format_properties.set_len(count as usize); - Ok::<_, Infallible>( - sparse_image_format_properties - .into_iter() - .map( - |sparse_image_format_properties| SparseImageFormatProperties { - aspects: sparse_image_format_properties.aspect_mask.into(), - image_granularity: [ - sparse_image_format_properties.image_granularity.width, - sparse_image_format_properties.image_granularity.height, - sparse_image_format_properties.image_granularity.depth, - ], - flags: sparse_image_format_properties.flags.into(), - }, - ) - .collect(), - ) + sparse_image_format_properties + .into_iter() + .map( + |sparse_image_format_properties| SparseImageFormatProperties { + aspects: sparse_image_format_properties.aspect_mask.into(), + image_granularity: [ + sparse_image_format_properties.image_granularity.width, + sparse_image_format_properties.image_granularity.height, + sparse_image_format_properties.image_granularity.depth, + ], + flags: sparse_image_format_properties.flags.into(), + }, + ) + .collect() } - }, - ) - .unwrap() + }) } /// Returns the capabilities that are supported by the physical device for the given surface. @@ -1555,8 +1539,7 @@ impl PhysicalDevice { surface: &Surface, surface_info: SurfaceInfo, ) -> Result { - get_cached( - &surface.surface_capabilities, + surface.surface_capabilities.get_or_try_insert( (self.handle, surface_info), |(_, surface_info)| { /* Input */ @@ -1805,8 +1788,7 @@ impl PhysicalDevice { surface: &Surface, surface_info: SurfaceInfo, ) -> Result, VulkanError> { - get_cached( - &surface.surface_formats, + surface.surface_formats.get_or_try_insert( (self.handle, surface_info), |(_, surface_info)| { let &SurfaceInfo { @@ -1992,47 +1974,49 @@ impl PhysicalDevice { &self, surface: &Surface, ) -> Result, VulkanError> { - get_cached(&surface.surface_present_modes, self.handle, |_| { - let fns = self.instance.fns(); + surface + .surface_present_modes + .get_or_try_insert(self.handle, |_| { + let fns = self.instance.fns(); - let modes = loop { - let mut count = 0; - (fns.khr_surface - .get_physical_device_surface_present_modes_khr)( - self.internal_object(), - surface.internal_object(), - &mut count, - ptr::null_mut(), - ) - .result() - .map_err(VulkanError::from)?; + let modes = loop { + let mut count = 0; + (fns.khr_surface + .get_physical_device_surface_present_modes_khr)( + self.internal_object(), + surface.internal_object(), + &mut count, + ptr::null_mut(), + ) + .result() + .map_err(VulkanError::from)?; - let mut modes = Vec::with_capacity(count as usize); - let result = (fns - .khr_surface - .get_physical_device_surface_present_modes_khr)( - self.internal_object(), - surface.internal_object(), - &mut count, - modes.as_mut_ptr(), - ); + let mut modes = Vec::with_capacity(count as usize); + let result = (fns + .khr_surface + .get_physical_device_surface_present_modes_khr)( + self.internal_object(), + surface.internal_object(), + &mut count, + modes.as_mut_ptr(), + ); - match result { - ash::vk::Result::SUCCESS => { - modes.set_len(count as usize); - break modes; + match result { + ash::vk::Result::SUCCESS => { + modes.set_len(count as usize); + break modes; + } + ash::vk::Result::INCOMPLETE => (), + err => return Err(VulkanError::from(err)), } - ash::vk::Result::INCOMPLETE => (), - err => return Err(VulkanError::from(err)), - } - }; + }; - Ok(modes - .into_iter() - .filter_map(|mode_vk| mode_vk.try_into().ok()) - .collect()) - }) - .map(IntoIterator::into_iter) + Ok(modes + .into_iter() + .filter_map(|mode_vk| mode_vk.try_into().ok()) + .collect()) + }) + .map(IntoIterator::into_iter) } /// Returns whether queues of the given queue family can draw on the given surface. @@ -2082,10 +2066,9 @@ impl PhysicalDevice { queue_family_index: u32, surface: &Surface, ) -> Result { - get_cached( - &surface.surface_support, - (self.handle, queue_family_index), - |_| { + surface + .surface_support + .get_or_try_insert((self.handle, queue_family_index), |_| { let fns = self.instance.fns(); let mut output = MaybeUninit::uninit(); @@ -2099,8 +2082,7 @@ impl PhysicalDevice { .map_err(VulkanError::from)?; Ok(output.assume_init() != 0) - }, - ) + }) } /// 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( - cache: &RwLock>, - key: K, - func: impl FnOnce(&K) -> Result, -) -> Result -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! { /// Type of a physical device. #[non_exhaustive] diff --git a/vulkano/src/lib.rs b/vulkano/src/lib.rs index 4ec7696b..5320bcbe 100644 --- a/vulkano/src/lib.rs +++ b/vulkano/src/lib.rs @@ -104,6 +104,7 @@ pub mod format; mod version; #[macro_use] pub mod render_pass; +mod cache; mod fns; pub mod image; pub mod instance; diff --git a/vulkano/src/pipeline/compute.rs b/vulkano/src/pipeline/compute.rs index 72ded833..1223963a 100644 --- a/vulkano/src/pipeline/compute.rs +++ b/vulkano/src/pipeline/compute.rs @@ -36,8 +36,8 @@ use crate::{ shader::{DescriptorRequirements, EntryPoint, SpecializationConstants}, DeviceSize, OomError, VulkanError, VulkanObject, }; +use ahash::HashMap; use std::{ - collections::HashMap, error::Error, fmt::{Debug, Display, Error as FmtError, Formatter}, mem, diff --git a/vulkano/src/pipeline/graphics/builder.rs b/vulkano/src/pipeline/graphics/builder.rs index bb939117..567d4ced 100644 --- a/vulkano/src/pipeline/graphics/builder.rs +++ b/vulkano/src/pipeline/graphics/builder.rs @@ -51,9 +51,10 @@ use crate::{ }, DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject, }; +use ahash::HashMap; use smallvec::SmallVec; use std::{ - collections::{hash_map::Entry, HashMap}, + collections::hash_map::Entry, mem::{size_of_val, MaybeUninit}, ptr, slice, 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. // 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) - let mut range_map = HashMap::new(); + let mut range_map = HashMap::default(); for stage in stages.iter() { if let Some(range) = stage.push_constant_requirements() { match range_map.entry((range.offset, range.size)) { @@ -2382,7 +2383,7 @@ where let render_pass = render_pass.as_ref().unwrap(); let mut descriptor_requirements: HashMap<(u32, u32), DescriptorRequirements> = - HashMap::new(); + HashMap::default(); let mut dynamic_state: HashMap = HashMap::default(); let mut stages = HashMap::default(); let mut stages_vk: SmallVec<[_; 5]> = SmallVec::new(); diff --git a/vulkano/src/pipeline/graphics/mod.rs b/vulkano/src/pipeline/graphics/mod.rs index 61af2d51..fc3e56e5 100644 --- a/vulkano/src/pipeline/graphics/mod.rs +++ b/vulkano/src/pipeline/graphics/mod.rs @@ -70,8 +70,8 @@ use crate::{ shader::{DescriptorRequirements, ShaderStage}, VulkanObject, }; +use ahash::HashMap; use std::{ - collections::HashMap, fmt::{Debug, Error as FmtError, Formatter}, hash::{Hash, Hasher}, ptr, diff --git a/vulkano/src/pipeline/graphics/vertex_input/mod.rs b/vulkano/src/pipeline/graphics/vertex_input/mod.rs index 1441545a..fa8b595a 100644 --- a/vulkano/src/pipeline/graphics/vertex_input/mod.rs +++ b/vulkano/src/pipeline/graphics/vertex_input/mod.rs @@ -106,7 +106,7 @@ pub use self::{ vertex::{Vertex, VertexMemberInfo, VertexMemberTy}, }; use crate::format::Format; -use std::collections::HashMap; +use ahash::HashMap; mod buffers; mod collection; diff --git a/vulkano/src/shader/mod.rs b/vulkano/src/shader/mod.rs index 4da6a68e..50fcbbec 100644 --- a/vulkano/src/shader/mod.rs +++ b/vulkano/src/shader/mod.rs @@ -28,9 +28,9 @@ use crate::{ sync::PipelineStages, DeviceSize, OomError, Version, VulkanError, VulkanObject, }; +use ahash::{HashMap, HashSet}; use std::{ borrow::Cow, - collections::{HashMap, HashSet}, error::Error, ffi::{CStr, CString}, fmt::{Display, Error as FmtError, Formatter}, diff --git a/vulkano/src/shader/reflect.rs b/vulkano/src/shader/reflect.rs index bd4543d8..258aad4f 100644 --- a/vulkano/src/shader/reflect.rs +++ b/vulkano/src/shader/reflect.rs @@ -25,10 +25,8 @@ use crate::{ }, DeviceSize, }; -use std::{ - borrow::Cow, - collections::{HashMap, HashSet}, -}; +use ahash::{HashMap, HashSet}; +use std::borrow::Cow; /// Returns an iterator of the capabilities used by `spirv`. pub fn spirv_capabilities(spirv: &Spirv) -> impl Iterator { diff --git a/vulkano/src/shader/spirv.rs b/vulkano/src/shader/spirv.rs index 2aef09d2..bc4bda60 100644 --- a/vulkano/src/shader/spirv.rs +++ b/vulkano/src/shader/spirv.rs @@ -16,8 +16,8 @@ //! [SPIR-V specification](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html). use crate::Version; +use ahash::{HashMap, HashMapExt}; use std::{ - collections::HashMap, error::Error, fmt::{Display, Error as FmtError, Formatter}, ops::Range, diff --git a/vulkano/src/swapchain/surface.rs b/vulkano/src/swapchain/surface.rs index 99f80b55..661392db 100644 --- a/vulkano/src/swapchain/surface.rs +++ b/vulkano/src/swapchain/surface.rs @@ -9,6 +9,7 @@ use super::{FullScreenExclusive, Win32Monitor}; use crate::{ + cache::OnceCache, format::Format, image::ImageUsage, instance::Instance, @@ -23,9 +24,7 @@ use crate::{ #[cfg(target_os = "ios")] use objc::{class, msg_send, runtime::Object, sel, sel_impl}; -use parking_lot::RwLock; use std::{ - collections::HashMap, error::Error, fmt::{Debug, Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, @@ -52,11 +51,11 @@ pub struct Surface { // This is stored here rather than on `PhysicalDevice` to ensure that it's freed when the // `Surface` is destroyed. pub(crate) surface_capabilities: - RwLock>, + OnceCache<(ash::vk::PhysicalDevice, SurfaceInfo), SurfaceCapabilities>, pub(crate) surface_formats: - RwLock>>, - pub(crate) surface_present_modes: RwLock>>, - pub(crate) surface_support: RwLock>, + OnceCache<(ash::vk::PhysicalDevice, SurfaceInfo), Vec<(Format, ColorSpace)>>, + pub(crate) surface_present_modes: OnceCache>, + pub(crate) surface_support: OnceCache<(ash::vk::PhysicalDevice, u32), bool>, } impl Surface { @@ -85,10 +84,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), } } @@ -151,10 +150,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -250,10 +249,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -331,10 +330,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -420,10 +419,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -506,10 +505,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -592,10 +591,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -679,10 +678,10 @@ impl Surface { has_swapchain: AtomicBool::new(false), metal_layer, - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -767,10 +766,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -845,10 +844,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -936,10 +935,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -1017,10 +1016,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -1110,10 +1109,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -1201,10 +1200,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -1292,10 +1291,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) } @@ -1383,10 +1382,10 @@ impl Surface { #[cfg(target_os = "ios")] metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), - surface_capabilities: RwLock::new(HashMap::new()), - surface_formats: RwLock::new(HashMap::new()), - surface_present_modes: RwLock::new(HashMap::new()), - surface_support: RwLock::new(HashMap::new()), + surface_capabilities: OnceCache::new(), + surface_formats: OnceCache::new(), + surface_present_modes: OnceCache::new(), + surface_support: OnceCache::new(), })) }