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
|
||||
|
||||
[dependencies]
|
||||
ahash = "0.8"
|
||||
heck = "0.4"
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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" }
|
||||
|
@ -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`].
|
||||
///
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
|
@ -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 _;
|
||||
|
@ -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<FeaturesMember> {
|
||||
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<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)
|
||||
.into_iter()
|
||||
.map(|(ty, provided_by)| {
|
||||
|
@ -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};
|
||||
|
@ -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};
|
||||
|
@ -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<K, V> = indexmap::IndexMap<K, V, ahash::RandomState>;
|
||||
|
||||
pub fn autogen() {
|
||||
let registry = get_vk_registry("vk.xml");
|
||||
let vk_data = VkRegistryData::new(®istry);
|
||||
|
@ -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<PropertiesMember> {
|
||||
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<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)
|
||||
.into_iter()
|
||||
.map(|(ty, provided_by)| {
|
||||
|
@ -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<InstructionMember> {
|
||||
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
|
||||
|
@ -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<SpirvReqsMember> {
|
||||
let mut members: IndexMap<String, SpirvReqsMember> = IndexMap::new();
|
||||
let mut members: IndexMap<String, SpirvReqsMember> = IndexMap::default();
|
||||
|
||||
for ext_or_cap in capabilities {
|
||||
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},
|
||||
DeviceSize, OomError, RequirementNotMet, RequiresOneOf,
|
||||
};
|
||||
use ahash::HashMap;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
error::Error,
|
||||
fmt::{Display, Error as FmtError, Formatter},
|
||||
marker::PhantomData,
|
||||
|
@ -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},
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
@ -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},
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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},
|
||||
|
@ -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},
|
||||
|
@ -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<QueueFamilyProperties>,
|
||||
|
||||
// Data queried by the user at runtime, cached for faster lookups.
|
||||
external_buffer_properties: RwLock<HashMap<ExternalBufferInfo, ExternalBufferProperties>>,
|
||||
external_fence_properties: RwLock<HashMap<ExternalFenceInfo, ExternalFenceProperties>>,
|
||||
external_semaphore_properties:
|
||||
RwLock<HashMap<ExternalSemaphoreInfo, ExternalSemaphoreProperties>>,
|
||||
format_properties: RwLock<HashMap<Format, FormatProperties>>,
|
||||
image_format_properties: RwLock<HashMap<ImageFormatInfo, Option<ImageFormatProperties>>>,
|
||||
external_buffer_properties: OnceCache<ExternalBufferInfo, ExternalBufferProperties>,
|
||||
external_fence_properties: OnceCache<ExternalFenceInfo, ExternalFenceProperties>,
|
||||
external_semaphore_properties: OnceCache<ExternalSemaphoreInfo, ExternalSemaphoreProperties>,
|
||||
format_properties: OnceCache<Format, FormatProperties>,
|
||||
image_format_properties: OnceCache<ImageFormatInfo, Option<ImageFormatProperties>>,
|
||||
sparse_image_format_properties:
|
||||
RwLock<HashMap<SparseImageFormatInfo, Vec<SparseImageFormatProperties>>>,
|
||||
OnceCache<SparseImageFormatInfo, Vec<SparseImageFormatProperties>>,
|
||||
}
|
||||
|
||||
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<SparseImageFormatProperties> {
|
||||
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<W>,
|
||||
surface_info: SurfaceInfo,
|
||||
) -> Result<SurfaceCapabilities, VulkanError> {
|
||||
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<W>,
|
||||
surface_info: SurfaceInfo,
|
||||
) -> Result<Vec<(Format, ColorSpace)>, 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<W>,
|
||||
) -> Result<impl Iterator<Item = PresentMode>, 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<W>,
|
||||
) -> Result<bool, VulkanError> {
|
||||
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<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! {
|
||||
/// Type of a physical device.
|
||||
#[non_exhaustive]
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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<DynamicState, bool> = HashMap::default();
|
||||
let mut stages = HashMap::default();
|
||||
let mut stages_vk: SmallVec<[_; 5]> = SmallVec::new();
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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},
|
||||
|
@ -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<Item = &Capability> {
|
||||
|
@ -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,
|
||||
|
@ -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<W> {
|
||||
// This is stored here rather than on `PhysicalDevice` to ensure that it's freed when the
|
||||
// `Surface` is destroyed.
|
||||
pub(crate) surface_capabilities:
|
||||
RwLock<HashMap<(ash::vk::PhysicalDevice, SurfaceInfo), SurfaceCapabilities>>,
|
||||
OnceCache<(ash::vk::PhysicalDevice, SurfaceInfo), SurfaceCapabilities>,
|
||||
pub(crate) surface_formats:
|
||||
RwLock<HashMap<(ash::vk::PhysicalDevice, SurfaceInfo), Vec<(Format, ColorSpace)>>>,
|
||||
pub(crate) surface_present_modes: RwLock<HashMap<ash::vk::PhysicalDevice, Vec<PresentMode>>>,
|
||||
pub(crate) surface_support: RwLock<HashMap<(ash::vk::PhysicalDevice, u32), bool>>,
|
||||
OnceCache<(ash::vk::PhysicalDevice, SurfaceInfo), Vec<(Format, ColorSpace)>>,
|
||||
pub(crate) surface_present_modes: OnceCache<ash::vk::PhysicalDevice, Vec<PresentMode>>,
|
||||
pub(crate) surface_support: OnceCache<(ash::vk::PhysicalDevice, u32), bool>,
|
||||
}
|
||||
|
||||
impl<W> Surface<W> {
|
||||
@ -85,10 +84,10 @@ impl<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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<W> Surface<W> {
|
||||
#[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(),
|
||||
}))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user