merge Texture and Image structs, add image aliasing
This commit is contained in:
parent
e76055860d
commit
0627556051
|
@ -1,13 +1,14 @@
|
||||||
use std::borrow::Cow;
|
use std::{borrow::Cow, collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
define_device_owned_handle,
|
define_device_owned_handle,
|
||||||
device::{DeviceOwned, QueueFlags},
|
device::{self, DeviceOwned, QueueFlags},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Device;
|
use super::Device;
|
||||||
use ash::{prelude::*, vk};
|
use ash::{prelude::*, vk};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use parking_lot::Mutex;
|
||||||
use vk_mem::Alloc;
|
use vk_mem::Alloc;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -83,11 +84,18 @@ impl Default for ImageDesc {
|
||||||
define_device_owned_handle! {
|
define_device_owned_handle! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub Image(vk::Image) {
|
pub Image(vk::Image) {
|
||||||
alloc: vk_mem::Allocation,
|
alloc: Option<vk_mem::Allocation>,
|
||||||
size: vk::Extent3D,
|
size: vk::Extent3D,
|
||||||
format: vk::Format,
|
format: vk::Format,
|
||||||
|
views: Mutex<HashMap<ImageViewDesc, vk::ImageView>>,
|
||||||
|
aliased: Option<Arc<Image>>,
|
||||||
} => |this| unsafe {
|
} => |this| unsafe {
|
||||||
this.inner.dev().alloc().destroy_image(this.handle(), &mut this.alloc);
|
for &view in this.views.lock().values() {
|
||||||
|
this.inner.dev().dev().destroy_image_view(view, None);
|
||||||
|
}
|
||||||
|
if this.aliased.is_none() {
|
||||||
|
this.inner.dev().alloc().destroy_image(this.handle(), this.alloc.as_mut().unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +148,16 @@ impl Image {
|
||||||
|
|
||||||
let (handle, alloc) = unsafe { device.alloc().create_image(info, alloc_info)? };
|
let (handle, alloc) = unsafe { device.alloc().create_image(info, alloc_info)? };
|
||||||
|
|
||||||
Self::construct(device, handle, name, alloc, extent, format)
|
Self::construct(
|
||||||
|
device,
|
||||||
|
handle,
|
||||||
|
name,
|
||||||
|
Some(alloc),
|
||||||
|
extent,
|
||||||
|
format,
|
||||||
|
Mutex::new(HashMap::new()),
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(&self) -> vk::Format {
|
pub fn format(&self) -> vk::Format {
|
||||||
|
@ -168,7 +185,110 @@ impl Image {
|
||||||
self.size.depth
|
self.size.depth
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view(&self, desc: ImageViewDesc) -> VkResult<ImageView> {
|
fn get_alloc(&self) -> Option<&vk_mem::Allocation> {
|
||||||
|
self.alloc
|
||||||
|
.as_ref()
|
||||||
|
.or(self.aliased.as_ref().and_then(|image| image.get_alloc()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn alias(self: Arc<Self>, desc: ImageDesc) -> VkResult<Image> {
|
||||||
|
let ImageDesc {
|
||||||
|
flags,
|
||||||
|
name,
|
||||||
|
format,
|
||||||
|
kind,
|
||||||
|
mip_levels,
|
||||||
|
array_layers,
|
||||||
|
samples,
|
||||||
|
extent,
|
||||||
|
tiling,
|
||||||
|
usage,
|
||||||
|
queue_families,
|
||||||
|
layout,
|
||||||
|
mem_usage,
|
||||||
|
alloc_flags,
|
||||||
|
} = desc;
|
||||||
|
|
||||||
|
let queue_families = self
|
||||||
|
.device()
|
||||||
|
.queue_families()
|
||||||
|
.family_indices(queue_families);
|
||||||
|
|
||||||
|
let sharing_mode = if queue_families.len() > 1 {
|
||||||
|
vk::SharingMode::CONCURRENT
|
||||||
|
} else {
|
||||||
|
vk::SharingMode::EXCLUSIVE
|
||||||
|
};
|
||||||
|
|
||||||
|
let info = &vk::ImageCreateInfo::default()
|
||||||
|
.flags(flags)
|
||||||
|
.image_type(kind)
|
||||||
|
.format(format)
|
||||||
|
.extent(extent)
|
||||||
|
.samples(samples)
|
||||||
|
.initial_layout(layout)
|
||||||
|
.tiling(tiling)
|
||||||
|
.usage(usage)
|
||||||
|
.sharing_mode(sharing_mode)
|
||||||
|
.queue_family_indices(&queue_families)
|
||||||
|
.array_layers(array_layers)
|
||||||
|
.mip_levels(mip_levels);
|
||||||
|
|
||||||
|
let alloc = self.get_alloc().unwrap();
|
||||||
|
|
||||||
|
let image = unsafe {
|
||||||
|
let image = self.device().dev().create_image(info, None)?;
|
||||||
|
|
||||||
|
let req = self.device().dev().get_image_memory_requirements(image);
|
||||||
|
if self.device().alloc().get_allocation_info(alloc).size < req.size {
|
||||||
|
return Err(vk::Result::ERROR_MEMORY_MAP_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.device().alloc().bind_image_memory(alloc, image)?;
|
||||||
|
image
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::construct(
|
||||||
|
self.device().clone(),
|
||||||
|
image,
|
||||||
|
name,
|
||||||
|
None,
|
||||||
|
extent,
|
||||||
|
format,
|
||||||
|
Mutex::new(HashMap::new()),
|
||||||
|
Some(self.aliased.clone().unwrap_or(self)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// technically, this ImageView belongs to the image and is managed by it.
|
||||||
|
pub fn get_view(&self, desc: ImageViewDesc) -> VkResult<vk::ImageView> {
|
||||||
|
use std::collections::hash_map::Entry::*;
|
||||||
|
match self.views.lock().entry(desc.hash_eq_copy()) {
|
||||||
|
Occupied(occupied) => Ok(*occupied.get()),
|
||||||
|
Vacant(vacant) => {
|
||||||
|
let view = unsafe {
|
||||||
|
let create_info = vk::ImageViewCreateInfo::default()
|
||||||
|
.flags(desc.flags)
|
||||||
|
.image(self.image())
|
||||||
|
.view_type(vk::ImageViewType::TYPE_2D)
|
||||||
|
.format(desc.format)
|
||||||
|
.components(desc.components)
|
||||||
|
.subresource_range(
|
||||||
|
vk::ImageSubresourceRange::default()
|
||||||
|
.aspect_mask(desc.aspect)
|
||||||
|
.base_mip_level(desc.mip_range.0)
|
||||||
|
.level_count(desc.mip_range.count())
|
||||||
|
.base_array_layer(desc.layer_range.0)
|
||||||
|
.layer_count(desc.layer_range.count()),
|
||||||
|
);
|
||||||
|
self.device().dev().create_image_view(&create_info, None)?
|
||||||
|
};
|
||||||
|
Ok(*vacant.insert(view))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_view(&self, desc: ImageViewDesc) -> VkResult<ImageView> {
|
||||||
let create_info = vk::ImageViewCreateInfo::default()
|
let create_info = vk::ImageViewCreateInfo::default()
|
||||||
.flags(desc.flags)
|
.flags(desc.flags)
|
||||||
.image(self.image())
|
.image(self.image())
|
||||||
|
@ -202,6 +322,32 @@ pub struct ImageViewDesc {
|
||||||
pub layer_range: MipRange,
|
pub layer_range: MipRange,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ImageViewDesc {
|
||||||
|
pub fn hash_eq_copy(&self) -> Self {
|
||||||
|
let &Self {
|
||||||
|
flags,
|
||||||
|
kind,
|
||||||
|
format,
|
||||||
|
components,
|
||||||
|
aspect,
|
||||||
|
mip_range,
|
||||||
|
layer_range,
|
||||||
|
..
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
flags,
|
||||||
|
name: None,
|
||||||
|
kind,
|
||||||
|
format,
|
||||||
|
components,
|
||||||
|
aspect,
|
||||||
|
mip_range,
|
||||||
|
layer_range,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct MipRange(u32, u32);
|
pub struct MipRange(u32, u32);
|
||||||
|
|
||||||
|
|
|
@ -47,51 +47,14 @@ mod util;
|
||||||
use device::{Device, DeviceOwned, DeviceQueueFamilies};
|
use device::{Device, DeviceOwned, DeviceQueueFamilies};
|
||||||
|
|
||||||
mod texture {
|
mod texture {
|
||||||
use std::{
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
collections::{hash_map::Entry, BTreeMap, HashMap},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use ash::prelude::VkResult;
|
use crate::{def_monotonic_id, images::Image, Device};
|
||||||
use parking_lot::Mutex;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
def_monotonic_id,
|
|
||||||
images::{Image, ImageView},
|
|
||||||
Device,
|
|
||||||
};
|
|
||||||
|
|
||||||
def_monotonic_id!(pub TextureId);
|
def_monotonic_id!(pub TextureId);
|
||||||
|
|
||||||
pub struct Texture {
|
|
||||||
id: TextureId,
|
|
||||||
image: Arc<Image>,
|
|
||||||
views: Mutex<HashMap<crate::images::ImageViewDesc, Arc<ImageView>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Texture {
|
|
||||||
pub fn id(&self) -> TextureId {
|
|
||||||
self.id
|
|
||||||
}
|
|
||||||
pub fn image(&self) -> Arc<Image> {
|
|
||||||
self.image.clone()
|
|
||||||
}
|
|
||||||
pub fn view(&self, desc: crate::images::ImageViewDesc) -> VkResult<Arc<ImageView>> {
|
|
||||||
let mut views = self.views.lock();
|
|
||||||
let view = match views.entry(desc) {
|
|
||||||
Entry::Occupied(entry) => entry.get().clone(),
|
|
||||||
Entry::Vacant(entry) => {
|
|
||||||
let view = Arc::new(self.image.view(entry.key().clone())?);
|
|
||||||
entry.insert(view).clone()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TextureManager {
|
pub struct TextureManager {
|
||||||
pub textures: BTreeMap<TextureId, Arc<Texture>>,
|
pub textures: BTreeMap<TextureId, Arc<Image>>,
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
dev: Device,
|
dev: Device,
|
||||||
}
|
}
|
||||||
|
@ -104,22 +67,20 @@ mod texture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn insert_image(&mut self, image: Arc<Image>) -> TextureId {
|
||||||
|
let id = TextureId::new();
|
||||||
|
self.textures.insert(id, image);
|
||||||
|
id
|
||||||
|
}
|
||||||
pub fn insert_image_with_id(&mut self, id: TextureId, image: Arc<Image>) {
|
pub fn insert_image_with_id(&mut self, id: TextureId, image: Arc<Image>) {
|
||||||
self.textures.insert(
|
self.textures.insert(id, image);
|
||||||
id,
|
|
||||||
Arc::new(Texture {
|
|
||||||
id,
|
|
||||||
image,
|
|
||||||
views: Mutex::new(HashMap::new()),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_texture(&mut self, id: TextureId) -> Option<Arc<Texture>> {
|
pub fn remove_texture(&mut self, id: TextureId) -> Option<Arc<Image>> {
|
||||||
self.textures.remove(&id)
|
self.textures.remove(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_texture(&self, id: TextureId) -> Option<Arc<Texture>> {
|
pub fn get_texture(&self, id: TextureId) -> Option<Arc<Image>> {
|
||||||
self.textures.get(&id).cloned()
|
self.textures.get(&id).cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue