mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 16:25:31 +00:00
add memoryMapPlaced and memoryMapRangePlaced features of VK_EXT_map_memory_placed extension (#2514)
* add partial support for VK_EXT_map_memory_placed extension implements the memoryMapPlaced and memoryMapRangePlaced features * fix clippy lint * add tests I don't love these tests, they probably fail silently in CI * fix conflicting requirement * update test * fmt * fix memory selection in test intersects does not do what I thought it does * remove incorrect assertion I don't think this is correct. The offset and size are both DeviceSize or u64. They are added together as positive numbers. * remove unused * put back non-range test * only run test on unix * wrap stuff to 100 cols this is actually really nice for reading * clippy * tweak impl * scope * remove unused * use NonNull * fmt * add flags field * update position * PLACED_EXT -> PLACED * removed unnecessary validation * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * remove more * typo * Update vulkano/src/memory/device_memory.rs Co-authored-by: Rua <ruawhitepaw@gmail.com> * add validate_device call * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * fix links * remove extra branch * use WHOLE_SIZE * use getter * fix boolean condition * Update vulkano/src/memory/device_memory.rs Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> * add specific changes marc asked for i've concluded that this choice is roughly semantically equivalent and this comes down to opinion. I can't be bothered to have an opinion here, imo this is a bikeshed. also it is temporary. until the docs are updated and the impls are updated. also i don't even really care about the ranged version of this feature, implemented it mostly for completeness than anything else * Incorporate latest spec updates --------- Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com> Co-authored-by: Rua <ruawhitepaw@gmail.com>
This commit is contained in:
parent
978c922e1b
commit
64f3b1e7bc
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -1069,9 +1069,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.152"
|
version = "0.2.153"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
@ -2347,6 +2347,7 @@ dependencies = [
|
|||||||
"half",
|
"half",
|
||||||
"heck",
|
"heck",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"libc",
|
||||||
"libloading 0.8.1",
|
"libloading 0.8.1",
|
||||||
"nom",
|
"nom",
|
||||||
"objc",
|
"objc",
|
||||||
|
@ -46,6 +46,9 @@ serde = { workspace = true, features = ["derive"] }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
vk-parse = { workspace = true }
|
vk-parse = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
libc = "0.2.153"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["macros"]
|
default = ["macros"]
|
||||||
macros = ["dep:vulkano-macros"]
|
macros = ["dep:vulkano-macros"]
|
||||||
|
@ -231,7 +231,8 @@ fn properties_members(types: &HashMap<&str, (&Type, Vec<&str>)>) -> Vec<Properti
|
|||||||
| "robustStorageBufferAccessSizeAlignment"
|
| "robustStorageBufferAccessSizeAlignment"
|
||||||
| "robustUniformBufferAccessSizeAlignment"
|
| "robustUniformBufferAccessSizeAlignment"
|
||||||
| "storageTexelBufferOffsetAlignmentBytes"
|
| "storageTexelBufferOffsetAlignmentBytes"
|
||||||
| "uniformTexelBufferOffsetAlignmentBytes" => {
|
| "uniformTexelBufferOffsetAlignmentBytes"
|
||||||
|
| "minPlacedMemoryMapAlignment" => {
|
||||||
quote! { DeviceAlignment }
|
quote! { DeviceAlignment }
|
||||||
}
|
}
|
||||||
_ => vulkano_type(ty, len),
|
_ => vulkano_type(ty, len),
|
||||||
|
@ -219,8 +219,8 @@ pub use self::{
|
|||||||
};
|
};
|
||||||
use super::{
|
use super::{
|
||||||
DedicatedAllocation, DeviceAlignment, DeviceMemory, ExternalMemoryHandleTypes,
|
DedicatedAllocation, DeviceAlignment, DeviceMemory, ExternalMemoryHandleTypes,
|
||||||
MemoryAllocateFlags, MemoryAllocateInfo, MemoryMapInfo, MemoryProperties, MemoryPropertyFlags,
|
MemoryAllocateFlags, MemoryAllocateInfo, MemoryMapFlags, MemoryMapInfo, MemoryProperties,
|
||||||
MemoryRequirements, MemoryType,
|
MemoryPropertyFlags, MemoryRequirements, MemoryType,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
device::{Device, DeviceOwned},
|
device::{Device, DeviceOwned},
|
||||||
@ -1094,6 +1094,7 @@ impl<S> GenericMemoryAllocator<S> {
|
|||||||
// - Mapping the whole range is always valid.
|
// - Mapping the whole range is always valid.
|
||||||
unsafe {
|
unsafe {
|
||||||
memory.map_unchecked(MemoryMapInfo {
|
memory.map_unchecked(MemoryMapInfo {
|
||||||
|
flags: MemoryMapFlags::empty(),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
size: memory.allocation_size(),
|
size: memory.allocation_size(),
|
||||||
_ne: crate::NonExhaustive(()),
|
_ne: crate::NonExhaustive(()),
|
||||||
|
@ -418,12 +418,61 @@ impl DeviceMemory {
|
|||||||
/// `self` must not be host-mapped already and must be allocated from host-visible memory.
|
/// `self` must not be host-mapped already and must be allocated from host-visible memory.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn map(&mut self, map_info: MemoryMapInfo) -> Result<(), Validated<VulkanError>> {
|
pub fn map(&mut self, map_info: MemoryMapInfo) -> Result<(), Validated<VulkanError>> {
|
||||||
self.validate_map(&map_info)?;
|
self.validate_map(&map_info, None)?;
|
||||||
|
|
||||||
unsafe { Ok(self.map_unchecked(map_info)?) }
|
unsafe { Ok(self.map_unchecked(map_info)?) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_map(&self, map_info: &MemoryMapInfo) -> Result<(), Box<ValidationError>> {
|
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn map_unchecked(&mut self, map_info: MemoryMapInfo) -> Result<(), VulkanError> {
|
||||||
|
unsafe { self.map_unchecked_inner(map_info, None) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Maps a range of memory to be accessed by the host at the specified `placed_address`.
|
||||||
|
///
|
||||||
|
/// Requires the [`memory_map_placed`] feature to be enabled on the device.
|
||||||
|
///
|
||||||
|
/// `placed_address` must be aligned to the [`min_placed_memory_map_alignment`] device
|
||||||
|
/// property.
|
||||||
|
///
|
||||||
|
/// `self` must not be host-mapped already and must be allocated from host-visible memory.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The memory mapping specified by `placed_address` and `map_info.size` will be replaced,
|
||||||
|
/// including mappings made by the Rust allocator, a library, or your application itself.
|
||||||
|
/// - The memory mapping specified by `placed_address` and `map_info.size` must not overlap any
|
||||||
|
/// existing Vulkan memory mapping.
|
||||||
|
///
|
||||||
|
/// [`memory_map_placed`]: crate::device::DeviceFeatures::memory_map_placed
|
||||||
|
/// [`min_placed_memory_map_alignment`]: crate::device::DeviceProperties::min_placed_memory_map_alignment
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn map_placed(
|
||||||
|
&mut self,
|
||||||
|
map_info: MemoryMapInfo,
|
||||||
|
placed_address: NonNull<c_void>,
|
||||||
|
) -> Result<(), Validated<VulkanError>> {
|
||||||
|
self.validate_map(&map_info, Some(placed_address))?;
|
||||||
|
|
||||||
|
unsafe { Ok(self.map_placed_unchecked(map_info, placed_address)?) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn map_placed_unchecked(
|
||||||
|
&mut self,
|
||||||
|
map_info: MemoryMapInfo,
|
||||||
|
placed_address: NonNull<c_void>,
|
||||||
|
) -> Result<(), VulkanError> {
|
||||||
|
unsafe { self.map_unchecked_inner(map_info, Some(placed_address)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_map(
|
||||||
|
&self,
|
||||||
|
map_info: &MemoryMapInfo,
|
||||||
|
placed_address: Option<NonNull<c_void>>,
|
||||||
|
) -> Result<(), Box<ValidationError>> {
|
||||||
if self.mapping_state.is_some() {
|
if self.mapping_state.is_some() {
|
||||||
return Err(Box::new(ValidationError {
|
return Err(Box::new(ValidationError {
|
||||||
problem: "this device memory is already host-mapped".into(),
|
problem: "this device memory is already host-mapped".into(),
|
||||||
@ -433,7 +482,7 @@ impl DeviceMemory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
map_info
|
map_info
|
||||||
.validate(self)
|
.validate(self, placed_address)
|
||||||
.map_err(|err| err.add_context("map_info"))?;
|
.map_err(|err| err.add_context("map_info"))?;
|
||||||
|
|
||||||
let memory_type = &self
|
let memory_type = &self
|
||||||
@ -458,9 +507,13 @@ impl DeviceMemory {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
unsafe fn map_unchecked_inner(
|
||||||
pub unsafe fn map_unchecked(&mut self, map_info: MemoryMapInfo) -> Result<(), VulkanError> {
|
&mut self,
|
||||||
|
map_info: MemoryMapInfo,
|
||||||
|
placed_address: Option<NonNull<c_void>>,
|
||||||
|
) -> Result<(), VulkanError> {
|
||||||
let MemoryMapInfo {
|
let MemoryMapInfo {
|
||||||
|
flags,
|
||||||
offset,
|
offset,
|
||||||
size,
|
size,
|
||||||
_ne: _,
|
_ne: _,
|
||||||
@ -477,13 +530,22 @@ impl DeviceMemory {
|
|||||||
|
|
||||||
if device.enabled_extensions().khr_map_memory2 {
|
if device.enabled_extensions().khr_map_memory2 {
|
||||||
let map_info_vk = ash::vk::MemoryMapInfoKHR {
|
let map_info_vk = ash::vk::MemoryMapInfoKHR {
|
||||||
flags: ash::vk::MemoryMapFlags::empty(),
|
flags: flags.into(),
|
||||||
memory: self.handle(),
|
memory: self.handle(),
|
||||||
offset,
|
offset,
|
||||||
size,
|
size,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut map_placed_info_vk = ash::vk::MemoryMapPlacedInfoEXT::default();
|
||||||
|
|
||||||
|
let map_info_vk = if let Some(it) = placed_address {
|
||||||
|
map_placed_info_vk.p_placed_address = it.as_ptr();
|
||||||
|
map_info_vk.push_next(&mut map_placed_info_vk)
|
||||||
|
} else {
|
||||||
|
map_info_vk
|
||||||
|
};
|
||||||
|
|
||||||
(fns.khr_map_memory2.map_memory2_khr)(
|
(fns.khr_map_memory2.map_memory2_khr)(
|
||||||
device.handle(),
|
device.handle(),
|
||||||
&map_info_vk,
|
&map_info_vk,
|
||||||
@ -1363,6 +1425,8 @@ vulkan_bitflags! {
|
|||||||
/// Parameters of a memory map operation.
|
/// Parameters of a memory map operation.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MemoryMapInfo {
|
pub struct MemoryMapInfo {
|
||||||
|
pub flags: MemoryMapFlags,
|
||||||
|
|
||||||
/// The offset (in bytes) from the beginning of the `DeviceMemory`, where the mapping starts.
|
/// The offset (in bytes) from the beginning of the `DeviceMemory`, where the mapping starts.
|
||||||
///
|
///
|
||||||
/// Must be less than the [`allocation_size`] of the device memory. If the the memory was not
|
/// Must be less than the [`allocation_size`] of the device memory. If the the memory was not
|
||||||
@ -1392,13 +1456,25 @@ pub struct MemoryMapInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryMapInfo {
|
impl MemoryMapInfo {
|
||||||
pub(crate) fn validate(&self, memory: &DeviceMemory) -> Result<(), Box<ValidationError>> {
|
pub(crate) fn validate(
|
||||||
|
&self,
|
||||||
|
memory: &DeviceMemory,
|
||||||
|
placed_address: Option<NonNull<c_void>>,
|
||||||
|
) -> Result<(), Box<ValidationError>> {
|
||||||
let &Self {
|
let &Self {
|
||||||
|
flags,
|
||||||
offset,
|
offset,
|
||||||
size,
|
size,
|
||||||
_ne: _,
|
_ne: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
|
let device = memory.device();
|
||||||
|
|
||||||
|
flags.validate_device(device).map_err(|err| {
|
||||||
|
err.add_context("flags")
|
||||||
|
.set_vuids(&["VUID-VkMemoryMapInfoKHR-flags-parameter"])
|
||||||
|
})?;
|
||||||
|
|
||||||
if !(offset < memory.allocation_size()) {
|
if !(offset < memory.allocation_size()) {
|
||||||
return Err(Box::new(ValidationError {
|
return Err(Box::new(ValidationError {
|
||||||
context: "offset".into(),
|
context: "offset".into(),
|
||||||
@ -1427,6 +1503,124 @@ impl MemoryMapInfo {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flags.contains(MemoryMapFlags::PLACED) {
|
||||||
|
if !device.enabled_features().memory_map_placed {
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "flags".into(),
|
||||||
|
problem: "contains `MemoryMapFlags::PLACED`".into(),
|
||||||
|
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
|
||||||
|
"memory_map_placed",
|
||||||
|
)])]),
|
||||||
|
vuids: &["VUID-VkMemoryMapInfoKHR-flags-09569"],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(placed_address) = placed_address else {
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "flags".into(),
|
||||||
|
problem:
|
||||||
|
"contains `MemoryMapFlags::PLACED`, but `DeviceMemory::map_placed` isn't \
|
||||||
|
used to specify the placed address"
|
||||||
|
.into(),
|
||||||
|
vuids: &["VUID-VkMemoryMapInfoKHR-flags-09570"],
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
// min_placed_memory_map_alignment is always provided when the device extension
|
||||||
|
// ext_map_memory_placed is available.
|
||||||
|
let min_placed_memory_map_alignment = device
|
||||||
|
.physical_device()
|
||||||
|
.properties()
|
||||||
|
.min_placed_memory_map_alignment
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if !is_aligned(
|
||||||
|
placed_address.as_ptr() as DeviceSize,
|
||||||
|
min_placed_memory_map_alignment,
|
||||||
|
) {
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "placed_address".into(),
|
||||||
|
problem: "is not aligned to an integer multiple of the \
|
||||||
|
`min_placed_memory_map_alignment` device property"
|
||||||
|
.into(),
|
||||||
|
vuids: &["VUID-VkMemoryMapPlacedInfoEXT-pPlacedAddress-09577"],
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if device.enabled_features().memory_map_range_placed {
|
||||||
|
if !is_aligned(offset, min_placed_memory_map_alignment) {
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "offset".into(),
|
||||||
|
problem: "is not aligned to an integer multiple of the \
|
||||||
|
`min_placed_memory_map_alignment` device property"
|
||||||
|
.into(),
|
||||||
|
vuids: &["VUID-VkMemoryMapInfoKHR-flags-09573"],
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !is_aligned(size, min_placed_memory_map_alignment) {
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "size".into(),
|
||||||
|
problem: "is not aligned to an integer multiple of the \
|
||||||
|
`min_placed_memory_map_alignment` device property"
|
||||||
|
.into(),
|
||||||
|
vuids: &["VUID-VkMemoryMapInfoKHR-flags-09574"],
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if offset != 0 {
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "offset".into(),
|
||||||
|
problem: "is not zero".into(),
|
||||||
|
vuids: &["VUID-VkMemoryMapInfoKHR-flags-09571"],
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if size != memory.allocation_size() {
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "size".into(),
|
||||||
|
problem: "is not `self.allocation_size()`".into(),
|
||||||
|
vuids: &["VUID-VkMemoryMapInfoKHR-flags-09572"],
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !is_aligned(memory.allocation_size(), min_placed_memory_map_alignment) {
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "flags".into(),
|
||||||
|
problem: "contains `MemoryMapFlags::PLACED`, but `self.allocation_size()` \
|
||||||
|
is not aligned to an integer multiple of the \
|
||||||
|
`min_placed_memory_map_alignment` device property"
|
||||||
|
.into(),
|
||||||
|
vuids: &["VUID-VkMemoryMapInfoKHR-flags-09651"],
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(handle_type) = memory.imported_handle_type() {
|
||||||
|
if handle_type == ExternalMemoryHandleType::HostAllocation
|
||||||
|
|| handle_type == ExternalMemoryHandleType::HostMappedForeignMemory
|
||||||
|
{
|
||||||
|
return Err(Box::new(ValidationError {
|
||||||
|
context: "flags".into(),
|
||||||
|
problem: "contains `MemoryMapFlags::PLACED`, but \
|
||||||
|
`self.imported_handle_type()` is \
|
||||||
|
`ExternalMemoryHandleType::HostAllocation` or \
|
||||||
|
`ExternalMemoryHandleType::HostMappedForeignMemory`"
|
||||||
|
.into(),
|
||||||
|
vuids: &["VUID-VkMemoryMapInfoKHR-flags-09575"],
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let atom_size = memory.atom_size();
|
let atom_size = memory.atom_size();
|
||||||
|
|
||||||
// Not required for merely mapping, but without this check the user can end up with
|
// Not required for merely mapping, but without this check the user can end up with
|
||||||
@ -1458,6 +1652,7 @@ impl Default for MemoryMapInfo {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
MemoryMapInfo {
|
MemoryMapInfo {
|
||||||
|
flags: MemoryMapFlags::empty(),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
size: 0,
|
size: 0,
|
||||||
_ne: crate::NonExhaustive(()),
|
_ne: crate::NonExhaustive(()),
|
||||||
@ -1465,6 +1660,13 @@ impl Default for MemoryMapInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vulkan_bitflags! {
|
||||||
|
#[non_exhaustive]
|
||||||
|
MemoryMapFlags = MemoryMapFlags(u32);
|
||||||
|
|
||||||
|
PLACED = PLACED_EXT,
|
||||||
|
}
|
||||||
|
|
||||||
/// Parameters of a memory unmap operation.
|
/// Parameters of a memory unmap operation.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MemoryUnmapInfo {
|
pub struct MemoryUnmapInfo {
|
||||||
@ -2142,7 +2344,8 @@ unsafe impl Sync for MappedDeviceMemory {}
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::MemoryAllocateInfo;
|
use super::MemoryAllocateInfo;
|
||||||
use crate::memory::{DeviceMemory, MemoryPropertyFlags};
|
use crate::memory::{DeviceMemory, MemoryMapFlags, MemoryMapInfo, MemoryPropertyFlags};
|
||||||
|
use std::{ptr, ptr::NonNull};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create() {
|
fn create() {
|
||||||
@ -2271,4 +2474,69 @@ mod tests {
|
|||||||
}
|
}
|
||||||
assert_eq!(device.allocation_count(), 1);
|
assert_eq!(device.allocation_count(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn map_placed() {
|
||||||
|
let (device, _) = gfx_dev_and_queue!(memory_map_placed; ext_map_memory_placed);
|
||||||
|
|
||||||
|
let memory_type_index = {
|
||||||
|
let physical_device = device.physical_device();
|
||||||
|
let memory_properties = physical_device.memory_properties();
|
||||||
|
let (idx, _) = memory_properties
|
||||||
|
.memory_types
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_idx, it)| {
|
||||||
|
it.property_flags.contains(
|
||||||
|
MemoryPropertyFlags::HOST_COHERENT
|
||||||
|
| MemoryPropertyFlags::HOST_VISIBLE
|
||||||
|
| MemoryPropertyFlags::DEVICE_LOCAL,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
idx as u32
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut memory = DeviceMemory::allocate(
|
||||||
|
device.clone(),
|
||||||
|
MemoryAllocateInfo {
|
||||||
|
allocation_size: 16 * 1024,
|
||||||
|
memory_type_index,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let address = unsafe {
|
||||||
|
let address = libc::mmap(
|
||||||
|
ptr::null_mut(),
|
||||||
|
16 * 1024,
|
||||||
|
libc::PROT_READ | libc::PROT_WRITE,
|
||||||
|
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
if address as i64 == -1 {
|
||||||
|
panic!("failed to map memory")
|
||||||
|
}
|
||||||
|
|
||||||
|
address
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
memory
|
||||||
|
.map_placed(
|
||||||
|
MemoryMapInfo {
|
||||||
|
flags: MemoryMapFlags::PLACED,
|
||||||
|
size: memory.allocation_size,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
NonNull::new(address).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,24 @@ macro_rules! instance {
|
|||||||
|
|
||||||
/// Creates a device and a queue for graphics operations.
|
/// Creates a device and a queue for graphics operations.
|
||||||
macro_rules! gfx_dev_and_queue {
|
macro_rules! gfx_dev_and_queue {
|
||||||
|
() => ({
|
||||||
|
gfx_dev_and_queue!(;)
|
||||||
|
});
|
||||||
($($feature:ident),*) => ({
|
($($feature:ident),*) => ({
|
||||||
|
gfx_dev_and_queue!($($feature),*;)
|
||||||
|
});
|
||||||
|
($($feature:ident),*; $($extension:ident),*) => ({
|
||||||
use crate::device::physical::PhysicalDeviceType;
|
use crate::device::physical::PhysicalDeviceType;
|
||||||
use crate::device::{Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo};
|
use crate::device::{Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo};
|
||||||
use crate::device::DeviceFeatures;
|
use crate::device::DeviceFeatures;
|
||||||
|
|
||||||
let instance = instance!();
|
let instance = instance!();
|
||||||
let enabled_extensions = DeviceExtensions::empty();
|
let enabled_extensions = DeviceExtensions {
|
||||||
|
$(
|
||||||
|
$extension: true,
|
||||||
|
)*
|
||||||
|
.. DeviceExtensions::empty()
|
||||||
|
};
|
||||||
let enabled_features = DeviceFeatures {
|
let enabled_features = DeviceFeatures {
|
||||||
$(
|
$(
|
||||||
$feature: true,
|
$feature: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user